diff --git a/.dockerignore b/.dockerignore index 9f14b98059..7998ff877f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -75,6 +75,9 @@ target/ # pyenv .python-version +# asdf +.tool-versions + # celery beat schedule file celerybeat-schedule diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 3bf9c4e1f6..5703d39be1 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -7,11 +7,16 @@ - [ ] Bugfix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] Code quality improvements to existing code or addition of tests - [ ] Other -**Related issue or feature (if applicable):** fixes +**Related issue or feature (if applicable):** -**Pull request in [esphome-docs](https://github.com/esphome/esphome-docs) with documentation (if applicable):** esphome/esphome-docs# +- fixes + +**Pull request in [esphome-docs](https://github.com/esphome/esphome-docs) with documentation (if applicable):** + +- esphome/esphome-docs# ## Test Environment @@ -23,12 +28,6 @@ - [ ] RTL87xx ## Example entry for `config.yaml`: - ```yaml # Example config.yaml diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 56be20bd87..5c686605c3 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -46,7 +46,10 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@v6.7.0 + uses: docker/build-push-action@v6.9.0 + env: + DOCKER_BUILD_SUMMARY: false + DOCKER_BUILD_RECORD_UPLOAD: false with: context: . file: ./docker/Dockerfile @@ -69,7 +72,10 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@v6.7.0 + uses: docker/build-push-action@v6.9.0 + env: + DOCKER_BUILD_SUMMARY: false + DOCKER_BUILD_RECORD_UPLOAD: false with: context: . file: ./docker/Dockerfile diff --git a/.github/actions/restore-python/action.yml b/.github/actions/restore-python/action.yml index c618a5ca97..06c54578f5 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@v5.2.0 + uses: actions/setup-python@v5.3.0 with: python-version: ${{ inputs.python-version }} - name: Restore Python virtual environment id: cache-venv - uses: actions/cache/restore@v4.0.2 + uses: actions/cache/restore@v4.1.2 with: path: venv # yamllint disable-line rule:line-length diff --git a/.github/workflows/ci-api-proto.yml b/.github/workflows/ci-api-proto.yml index 8112c4e0ff..a6b2e2b2b3 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.2.0 + uses: actions/setup-python@v5.3.0 with: python-version: "3.11" diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 891367d16a..435a58498e 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -42,11 +42,11 @@ jobs: steps: - uses: actions/checkout@v4.1.7 - name: Set up Python - uses: actions/setup-python@v5.2.0 + uses: actions/setup-python@v5.3.0 with: python-version: "3.9" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.6.1 + uses: docker/setup-buildx-action@v3.7.1 - name: Set up QEMU uses: docker/setup-qemu-action@v3.2.0 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c4fa65695..82a55d0e2a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,12 +41,12 @@ 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.2.0 + uses: actions/setup-python@v5.3.0 with: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore Python virtual environment id: cache-venv - uses: actions/cache@v4.0.2 + uses: actions/cache@v4.1.2 with: path: venv # yamllint disable-line rule:line-length @@ -302,20 +302,22 @@ jobs: - name: Cache platformio if: github.ref == 'refs/heads/dev' - uses: actions/cache@v4.0.2 + uses: actions/cache@v4.1.2 with: path: ~/.platformio key: platformio-${{ matrix.pio_cache_key }} - name: Cache platformio if: github.ref != 'refs/heads/dev' - uses: actions/cache/restore@v4.0.2 + uses: actions/cache/restore@v4.1.2 with: path: ~/.platformio key: platformio-${{ matrix.pio_cache_key }} - name: Install clang-tidy - run: sudo apt-get install clang-tidy-14 + run: | + sudo apt-get update + sudo apt-get install clang-tidy-14 - name: Register problem matchers run: | @@ -397,7 +399,9 @@ jobs: file: ${{ fromJson(needs.list-components.outputs.components) }} steps: - name: Install dependencies - run: sudo apt-get install libsdl2-dev + run: | + sudo apt-get update + sudo apt-get install libsdl2-dev - name: Check out code from GitHub uses: actions/checkout@v4.1.7 @@ -451,7 +455,9 @@ jobs: run: echo ${{ matrix.components }} - name: Install dependencies - run: sudo apt-get install libsdl2-dev + run: | + sudo apt-get update + sudo apt-get install libsdl2-dev - name: Check out code from GitHub uses: actions/checkout@v4.1.7 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000..ddeb0a99d2 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,91 @@ +# 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: + workflow_dispatch: + 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}}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 522de63360..5072bec222 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.2.0 + uses: actions/setup-python@v5.3.0 with: python-version: "3.x" - name: Set up python environment @@ -65,7 +65,7 @@ jobs: pip3 install build python3 -m build - name: Publish - uses: pypa/gh-action-pypi-publish@v1.10.1 + uses: pypa/gh-action-pypi-publish@v1.10.3 deploy-docker: name: Build ESPHome ${{ matrix.platform }} @@ -85,12 +85,12 @@ jobs: steps: - uses: actions/checkout@v4.1.7 - name: Set up Python - uses: actions/setup-python@v5.2.0 + uses: actions/setup-python@v5.3.0 with: python-version: "3.9" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.6.1 + uses: docker/setup-buildx-action@v3.7.1 - name: Set up QEMU if: matrix.platform != 'linux/amd64' uses: docker/setup-qemu-action@v3.2.0 @@ -141,7 +141,7 @@ jobs: echo name=$(cat /tmp/platform) >> $GITHUB_OUTPUT - name: Upload digests - uses: actions/upload-artifact@v4.4.0 + uses: actions/upload-artifact@v4.4.3 with: name: digests-${{ steps.sanitize.outputs.name }} path: /tmp/digests @@ -184,7 +184,7 @@ jobs: merge-multiple: true - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.6.1 + uses: docker/setup-buildx-action@v3.7.1 - name: Log in to docker hub if: matrix.registry == 'dockerhub' diff --git a/.github/workflows/sync-device-classes.yml b/.github/workflows/sync-device-classes.yml index e834ff3793..7a46d596a1 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.2.0 + uses: actions/setup-python@v5.3.0 with: python-version: 3.12 @@ -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.5 with: commit-message: "Synchronise Device Classes from Home Assistant" committer: esphomebot diff --git a/.gitignore b/.gitignore index 79820249ac..ad38e26fdd 100644 --- a/.gitignore +++ b/.gitignore @@ -75,6 +75,9 @@ cov.xml # pyenv .python-version +# asdf +.tool-versions + # Environments .env .venv diff --git a/CODEOWNERS b/CODEOWNERS index 1d4df3ccb8..5eb1f863f2 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -24,6 +24,7 @@ esphome/components/ade7953_i2c/* @angelnu esphome/components/ade7953_spi/* @angelnu esphome/components/ads1118/* @solomondg1 esphome/components/ags10/* @mak-42 +esphome/components/aic3204/* @kbx81 esphome/components/airthings_ble/* @jeromelaban esphome/components/airthings_wave_base/* @jeromelaban @kpfleming @ncareau esphome/components/airthings_wave_mini/* @ncareau @@ -47,6 +48,9 @@ esphome/components/at581x/* @X-Ryl669 esphome/components/atc_mithermometer/* @ahpohl esphome/components/atm90e26/* @danieltwagner esphome/components/atm90e32/* @circuitsetup @descipher +esphome/components/audio/* @kahrendt +esphome/components/audio_dac/* @kbx81 +esphome/components/axs15231/* @clydebarrow esphome/components/b_parasite/* @rbaron esphome/components/ballu/* @bazuchan esphome/components/bang_bang/* @OttoWinter @@ -81,12 +85,13 @@ esphome/components/bmp581/* @kahrendt esphome/components/bp1658cj/* @Cossid esphome/components/bp5758d/* @Cossid esphome/components/button/* @esphome/core +esphome/components/bytebuffer/* @clydebarrow esphome/components/canbus/* @danielschramm @mvturnho esphome/components/cap1188/* @mreditor97 esphome/components/captive_portal/* @OttoWinter esphome/components/ccs811/* @habbie esphome/components/cd74hc4067/* @asoehlke -esphome/components/ch422g/* @jesterret +esphome/components/ch422g/* @clydebarrow @jesterret esphome/components/climate/* @esphome/core esphome/components/climate_ir/* @glmnet esphome/components/color_temperature/* @jesserockz @@ -152,6 +157,7 @@ esphome/components/ft63x6/* @gpambrozio esphome/components/gcja5/* @gcormier esphome/components/gdk101/* @Szewcson esphome/components/globals/* @esphome/core +esphome/components/gp2y1010au0f/* @zry98 esphome/components/gp8403/* @jesserockz esphome/components/gpio/* @esphome/core esphome/components/gpio/one_wire/* @ssieb @@ -159,6 +165,7 @@ esphome/components/gps/* @coogle esphome/components/graph/* @synco esphome/components/graphical_display_menu/* @MrMDavidson esphome/components/gree/* @orestismers +esphome/components/grove_gas_mc_v2/* @YorkshireIoT esphome/components/grove_tb6612fng/* @max246 esphome/components/growatt_solar/* @leeuwte esphome/components/gt911/* @clydebarrow @jesserockz @@ -166,6 +173,7 @@ esphome/components/haier/* @paveldn esphome/components/haier/binary_sensor/* @paveldn esphome/components/haier/button/* @paveldn esphome/components/haier/sensor/* @paveldn +esphome/components/haier/switch/* @paveldn esphome/components/haier/text_sensor/* @paveldn esphome/components/havells_solar/* @sourabhjaiswal esphome/components/hbridge/fan/* @WeekendWarrior @@ -191,10 +199,11 @@ esphome/components/htu31d/* @betterengineering esphome/components/hydreon_rgxx/* @functionpointer esphome/components/hyt271/* @Philippe12 esphome/components/i2c/* @esphome/core +esphome/components/i2c_device/* @gabest11 esphome/components/i2s_audio/* @jesserockz esphome/components/i2s_audio/media_player/* @jesserockz esphome/components/i2s_audio/microphone/* @jesserockz -esphome/components/i2s_audio/speaker/* @jesserockz +esphome/components/i2s_audio/speaker/* @jesserockz @kahrendt esphome/components/iaqcore/* @yozik04 esphome/components/ili9xxx/* @clydebarrow @nielsnl68 esphome/components/improv_base/* @esphome/core @@ -227,10 +236,12 @@ 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 esphome/components/matrix_keypad/* @ssieb +esphome/components/max17043/* @blacknell esphome/components/max31865/* @DAVe3283 esphome/components/max44009/* @berfenger esphome/components/max6956/* @looping40 @@ -277,6 +288,7 @@ esphome/components/mopeka_std_check/* @Fabian-Schmidt esphome/components/mpl3115a2/* @kbickar esphome/components/mpu6886/* @fabaff esphome/components/ms8607/* @e28eta +esphome/components/nau7802/* @cujomalainey esphome/components/network/* @esphome/core esphome/components/nextion/* @edwardtfn @senexcrenshaw esphome/components/nextion/binary_sensor/* @senexcrenshaw @@ -285,9 +297,11 @@ esphome/components/nextion/switch/* @senexcrenshaw esphome/components/nextion/text_sensor/* @senexcrenshaw esphome/components/nfc/* @jesserockz @kbx81 esphome/components/noblex/* @AGalfra +esphome/components/npi19/* @bakerkj 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 @@ -315,7 +329,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/qspi_dbi/* @clydebarrow esphome/components/qwiic_pir/* @kahrendt esphome/components/radon_eye_ble/* @jeffeb3 esphome/components/radon_eye_rd200/* @jeffeb3 @@ -364,7 +378,7 @@ esphome/components/smt100/* @piechade esphome/components/sn74hc165/* @jesserockz esphome/components/socket/* @esphome/core esphome/components/sonoff_d1/* @anatoly-savchenkov -esphome/components/speaker/* @jesserockz +esphome/components/speaker/* @jesserockz @kahrendt esphome/components/spi/* @clydebarrow @esphome/core esphome/components/spi_device/* @clydebarrow esphome/components/spi_led_strip/* @clydebarrow @@ -394,10 +408,13 @@ esphome/components/sun/* @OttoWinter esphome/components/sun_gtil2/* @Mat931 esphome/components/switch/* @esphome/core esphome/components/t6615/* @tylermenezes +esphome/components/tc74/* @sethgirvan esphome/components/tca9548a/* @andreashergert1984 +esphome/components/tca9555/* @mobrembski esphome/components/tcl112/* @glmnet esphome/components/tee501/* @Stock-M esphome/components/teleinfo/* @0hax +esphome/components/tem3200/* @bakerkj esphome/components/template/alarm_control_panel/* @grahambrown11 @hwstar esphome/components/template/datetime/* @rfdarter esphome/components/template/event/* @nohat diff --git a/README.md b/README.md index bb6fb37d3a..da1b2b3650 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,5 @@ For issues, please go to [the issue tracker](https://github.com/esphome/issues/issues). For feature requests, please see [feature requests](https://github.com/esphome/feature-requests/issues). + +[![ESPHome - A project from the Open Home Foundation](https://www.openhomefoundation.org/badges/esphome.png)](https://www.openhomefoundation.org/) diff --git a/docker/Dockerfile b/docker/Dockerfile index 4393d5a447..52a4794f24 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 \ @@ -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 \ @@ -86,7 +86,7 @@ RUN \ pip3 install \ --break-system-packages --no-cache-dir \ # Keep platformio version in sync with requirements.txt - platformio==6.1.15 \ + platformio==6.1.16 \ # Change some platformio settings && platformio settings set enable_telemetry No \ && platformio settings set check_platformio_interval 1000000 \ @@ -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 '*' diff --git a/esphome/automation.py b/esphome/automation.py index 0bd6cf0af0..34159561c2 100644 --- a/esphome/automation.py +++ b/esphome/automation.py @@ -1,6 +1,8 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import ( + CONF_ALL, + CONF_ANY, CONF_AUTOMATION_ID, CONF_CONDITION, CONF_COUNT, @@ -73,6 +75,13 @@ def validate_potentially_and_condition(value): return validate_condition(value) +def validate_potentially_or_condition(value): + if isinstance(value, list): + with cv.remove_prepend_path(["or"]): + return validate_condition({"or": value}) + return validate_condition(value) + + DelayAction = cg.esphome_ns.class_("DelayAction", Action, cg.Component) LambdaAction = cg.esphome_ns.class_("LambdaAction", Action) IfAction = cg.esphome_ns.class_("IfAction", Action) @@ -166,6 +175,18 @@ async def or_condition_to_code(config, condition_id, template_arg, args): return cg.new_Pvariable(condition_id, template_arg, conditions) +@register_condition("all", AndCondition, validate_condition_list) +async def all_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("any", OrCondition, validate_condition_list) +async def any_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("not", NotCondition, validate_potentially_and_condition) async def not_condition_to_code(config, condition_id, template_arg, args): condition = await build_condition(config, template_arg, args) @@ -223,15 +244,21 @@ async def delay_action_to_code(config, action_id, template_arg, args): IfAction, cv.All( { - cv.Required(CONF_CONDITION): validate_potentially_and_condition, + cv.Exclusive( + CONF_CONDITION, CONF_CONDITION + ): validate_potentially_and_condition, + cv.Exclusive(CONF_ANY, CONF_CONDITION): validate_potentially_or_condition, + cv.Exclusive(CONF_ALL, CONF_CONDITION): validate_potentially_and_condition, cv.Optional(CONF_THEN): validate_action_list, cv.Optional(CONF_ELSE): validate_action_list, }, cv.has_at_least_one_key(CONF_THEN, CONF_ELSE), + cv.has_at_least_one_key(CONF_CONDITION, CONF_ANY, CONF_ALL), ), ) async def if_action_to_code(config, action_id, template_arg, args): - conditions = await build_condition(config[CONF_CONDITION], template_arg, args) + cond_conf = next(el for el in config if el in (CONF_ANY, CONF_ALL, CONF_CONDITION)) + conditions = await build_condition(config[cond_conf], template_arg, args) var = cg.new_Pvariable(action_id, template_arg, conditions) if CONF_THEN in config: actions = await build_action_list(config[CONF_THEN], template_arg, args) diff --git a/esphome/components/aic3204/__init__.py b/esphome/components/aic3204/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/aic3204/aic3204.cpp b/esphome/components/aic3204/aic3204.cpp new file mode 100644 index 0000000000..0560f2366b --- /dev/null +++ b/esphome/components/aic3204/aic3204.cpp @@ -0,0 +1,173 @@ +#include "aic3204.h" + +#include "esphome/core/defines.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace aic3204 { + +static const char *const TAG = "aic3204"; + +#define ERROR_CHECK(err, msg) \ + if (!(err)) { \ + ESP_LOGE(TAG, msg); \ + this->mark_failed(); \ + return; \ + } + +void AIC3204::setup() { + ESP_LOGCONFIG(TAG, "Setting up AIC3204..."); + + // Set register page to 0 + ERROR_CHECK(this->write_byte(AIC3204_PAGE_CTRL, 0x00), "Set page 0 failed"); + // Initiate SW reset (PLL is powered off as part of reset) + ERROR_CHECK(this->write_byte(AIC3204_SW_RST, 0x01), "Software reset failed"); + // *** Program clock settings *** + // Default is CODEC_CLKIN is from MCLK pin. Don't need to change this. + // MDAC*NDAC*FOSR*48Khz = mClk (24.576 MHz when the XMOS is expecting 48kHz audio) + // (See page 51 of https://www.ti.com/lit/ml/slaa557/slaa557.pdf) + // We do need MDAC*DOSR/32 >= the resource compute level for the processing block + // So here 2*128/32 = 8, which is equal to processing block 1 's resource compute + // See page 5 of https://www.ti.com/lit/an/slaa404c/slaa404c.pdf for the workflow + // for determining these settings. + + // Power up NDAC and set to 2 + ERROR_CHECK(this->write_byte(AIC3204_NDAC, 0x82), "Set NDAC failed"); + // Power up MDAC and set to 2 + ERROR_CHECK(this->write_byte(AIC3204_MDAC, 0x82), "Set MDAC failed"); + // Program DOSR = 128 + ERROR_CHECK(this->write_byte(AIC3204_DOSR, 0x80), "Set DOSR failed"); + // Set Audio Interface Config: I2S, 32 bits, DOUT always driving + ERROR_CHECK(this->write_byte(AIC3204_CODEC_IF, 0x30), "Set CODEC_IF failed"); + // For I2S Firmware only, set SCLK/MFP3 pin as Audio Data In + ERROR_CHECK(this->write_byte(AIC3204_SCLK_MFP3, 0x02), "Set SCLK/MFP3 failed"); + ERROR_CHECK(this->write_byte(AIC3204_AUDIO_IF_4, 0x01), "Set AUDIO_IF_4 failed"); + ERROR_CHECK(this->write_byte(AIC3204_AUDIO_IF_5, 0x01), "Set AUDIO_IF_5 failed"); + // Program the DAC processing block to be used - PRB_P1 + ERROR_CHECK(this->write_byte(AIC3204_DAC_SIG_PROC, 0x01), "Set DAC_SIG_PROC failed"); + + // *** Select Page 1 *** + ERROR_CHECK(this->write_byte(AIC3204_PAGE_CTRL, 0x01), "Set page 1 failed"); + // Enable the internal AVDD_LDO: + ERROR_CHECK(this->write_byte(AIC3204_LDO_CTRL, 0x09), "Set LDO_CTRL failed"); + // *** Program Analog Blocks *** + // Disable Internal Crude AVdd in presence of external AVdd supply or before powering up internal AVdd LDO + ERROR_CHECK(this->write_byte(AIC3204_PWR_CFG, 0x08), "Set PWR_CFG failed"); + // Enable Master Analog Power Control + ERROR_CHECK(this->write_byte(AIC3204_LDO_CTRL, 0x01), "Set LDO_CTRL failed"); + // Page 125: Common mode control register, set d6 to 1 to make the full chip common mode = 0.75 v + // We are using the internal AVdd regulator with a nominal output of 1.72 V (see LDO_CTRL_REGISTER on page 123) + // Page 86 says to only set the common mode voltage to 0.9 v if AVdd >= 1.8... but it isn't on our hardware + // We also adjust the HPL and HPR gains to -2dB gian later in this config flow compensate (see page 47) + // (All pages refer to the TLV320AIC3204 Application Reference Guide) + ERROR_CHECK(this->write_byte(AIC3204_CM_CTRL, 0x40), "Set CM_CTRL failed"); + // *** Set PowerTune Modes *** + // Set the Left & Right DAC PowerTune mode to PTM_P3/4. Use Class-AB driver. + ERROR_CHECK(this->write_byte(AIC3204_PLAY_CFG1, 0x00), "Set PLAY_CFG1 failed"); + ERROR_CHECK(this->write_byte(AIC3204_PLAY_CFG2, 0x00), "Set PLAY_CFG2 failed"); + // Set the REF charging time to 40ms + ERROR_CHECK(this->write_byte(AIC3204_REF_STARTUP, 0x01), "Set REF_STARTUP failed"); + // HP soft stepping settings for optimal pop performance at power up + // Rpop used is 6k with N = 6 and soft step = 20usec. This should work with 47uF coupling + // capacitor. Can try N=5,6 or 7 time constants as well. Trade-off delay vs “pop” sound. + ERROR_CHECK(this->write_byte(AIC3204_HP_START, 0x25), "Set HP_START failed"); + // Route Left DAC to HPL + ERROR_CHECK(this->write_byte(AIC3204_HPL_ROUTE, 0x08), "Set HPL_ROUTE failed"); + // Route Right DAC to HPR + ERROR_CHECK(this->write_byte(AIC3204_HPR_ROUTE, 0x08), "Set HPR_ROUTE failed"); + // Route Left DAC to LOL + ERROR_CHECK(this->write_byte(AIC3204_LOL_ROUTE, 0x08), "Set LOL_ROUTE failed"); + // Route Right DAC to LOR + ERROR_CHECK(this->write_byte(AIC3204_LOR_ROUTE, 0x08), "Set LOR_ROUTE failed"); + + // Unmute HPL and set gain to -2dB (see comment before configuring the AIC3204_CM_CTRL register) + ERROR_CHECK(this->write_byte(AIC3204_HPL_GAIN, 0x3e), "Set HPL_GAIN failed"); + // Unmute HPR and set gain to -2dB (see comment before configuring the AIC3204_CM_CTRL register) + ERROR_CHECK(this->write_byte(AIC3204_HPR_GAIN, 0x3e), "Set HPR_GAIN failed"); + // Unmute LOL and set gain to 0dB + ERROR_CHECK(this->write_byte(AIC3204_LOL_DRV_GAIN, 0x00), "Set LOL_DRV_GAIN failed"); + // Unmute LOR and set gain to 0dB + ERROR_CHECK(this->write_byte(AIC3204_LOR_DRV_GAIN, 0x00), "Set LOR_DRV_GAIN failed"); + + // Power up HPL and HPR, LOL and LOR drivers + ERROR_CHECK(this->write_byte(AIC3204_OP_PWR_CTRL, 0x3C), "Set OP_PWR_CTRL failed"); + + // Wait for 2.5 sec for soft stepping to take effect before attempting power-up + this->set_timeout(2500, [this]() { + // *** Power Up DAC *** + // Select Page 0 + ERROR_CHECK(this->write_byte(AIC3204_PAGE_CTRL, 0x00), "Set PAGE_CTRL failed"); + // Power up the Left and Right DAC Channels. Route Left data to Left DAC and Right data to Right DAC. + // DAC Vol control soft step 1 step per DAC word clock. + ERROR_CHECK(this->write_byte(AIC3204_DAC_CH_SET1, 0xd4), "Set DAC_CH_SET1 failed"); + // Set left and right DAC digital volume control + ERROR_CHECK(this->write_volume_(), "Set volume failed"); + // Unmute left and right channels + ERROR_CHECK(this->write_mute_(), "Set mute failed"); + }); +} + +void AIC3204::dump_config() { + ESP_LOGCONFIG(TAG, "AIC3204:"); + LOG_I2C_DEVICE(this); + + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with AIC3204 failed"); + } +} + +bool AIC3204::set_mute_off() { + this->is_muted_ = false; + return this->write_mute_(); +} + +bool AIC3204::set_mute_on() { + this->is_muted_ = true; + return this->write_mute_(); +} + +bool AIC3204::set_auto_mute_mode(uint8_t auto_mute_mode) { + this->auto_mute_mode_ = auto_mute_mode & 0x07; + ESP_LOGVV(TAG, "Setting auto_mute_mode to 0x%.2x", this->auto_mute_mode_); + return this->write_mute_(); +} + +bool AIC3204::set_volume(float volume) { + this->volume_ = clamp(volume, 0.0, 1.0); + return this->write_volume_(); +} + +bool AIC3204::is_muted() { return this->is_muted_; } + +float AIC3204::volume() { return this->volume_; } + +bool AIC3204::write_mute_() { + uint8_t mute_mode_byte = this->auto_mute_mode_ << 4; // auto-mute control is bits 4-6 + mute_mode_byte |= this->is_muted_ ? 0x0c : 0x00; // mute bits are 2-3 + if (!this->write_byte(AIC3204_PAGE_CTRL, 0x00) || !this->write_byte(AIC3204_DAC_CH_SET2, mute_mode_byte)) { + ESP_LOGE(TAG, "Writing mute modes failed"); + return false; + } + return true; +} + +bool AIC3204::write_volume_() { + const int8_t dvc_min_byte = -127; + const int8_t dvc_max_byte = 48; + + int8_t volume_byte = dvc_min_byte + (this->volume_ * (dvc_max_byte - dvc_min_byte)); + volume_byte = clamp(volume_byte, dvc_min_byte, dvc_max_byte); + + ESP_LOGVV(TAG, "Setting volume to 0x%.2x", volume_byte & 0xFF); + + if ((!this->write_byte(AIC3204_PAGE_CTRL, 0x00)) || (!this->write_byte(AIC3204_DACL_VOL_D, volume_byte)) || + (!this->write_byte(AIC3204_DACR_VOL_D, volume_byte))) { + ESP_LOGE(TAG, "Writing volume failed"); + return false; + } + return true; +} + +} // namespace aic3204 +} // namespace esphome diff --git a/esphome/components/aic3204/aic3204.h b/esphome/components/aic3204/aic3204.h new file mode 100644 index 0000000000..783a58a2b9 --- /dev/null +++ b/esphome/components/aic3204/aic3204.h @@ -0,0 +1,88 @@ +#pragma once + +#include "esphome/components/audio_dac/audio_dac.h" +#include "esphome/components/i2c/i2c.h" +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/core/hal.h" + +namespace esphome { +namespace aic3204 { + +// TLV320AIC3204 Register Addresses +// Page 0 +static const uint8_t AIC3204_PAGE_CTRL = 0x00; // Register 0 - Page Control +static const uint8_t AIC3204_SW_RST = 0x01; // Register 1 - Software Reset +static const uint8_t AIC3204_CLK_PLL1 = 0x04; // Register 4 - Clock Setting Register 1, Multiplexers +static const uint8_t AIC3204_CLK_PLL2 = 0x05; // Register 5 - Clock Setting Register 2, P and R values +static const uint8_t AIC3204_CLK_PLL3 = 0x06; // Register 6 - Clock Setting Register 3, J values +static const uint8_t AIC3204_NDAC = 0x0B; // Register 11 - NDAC Divider Value +static const uint8_t AIC3204_MDAC = 0x0C; // Register 12 - MDAC Divider Value +static const uint8_t AIC3204_DOSR = 0x0E; // Register 14 - DOSR Divider Value (LS Byte) +static const uint8_t AIC3204_NADC = 0x12; // Register 18 - NADC Divider Value +static const uint8_t AIC3204_MADC = 0x13; // Register 19 - MADC Divider Value +static const uint8_t AIC3204_AOSR = 0x14; // Register 20 - AOSR Divider Value +static const uint8_t AIC3204_CODEC_IF = 0x1B; // Register 27 - CODEC Interface Control +static const uint8_t AIC3204_AUDIO_IF_4 = 0x1F; // Register 31 - Audio Interface Setting Register 4 +static const uint8_t AIC3204_AUDIO_IF_5 = 0x20; // Register 32 - Audio Interface Setting Register 5 +static const uint8_t AIC3204_SCLK_MFP3 = 0x38; // Register 56 - SCLK/MFP3 Function Control +static const uint8_t AIC3204_DAC_SIG_PROC = 0x3C; // Register 60 - DAC Sig Processing Block Control +static const uint8_t AIC3204_ADC_SIG_PROC = 0x3D; // Register 61 - ADC Sig Processing Block Control +static const uint8_t AIC3204_DAC_CH_SET1 = 0x3F; // Register 63 - DAC Channel Setup 1 +static const uint8_t AIC3204_DAC_CH_SET2 = 0x40; // Register 64 - DAC Channel Setup 2 +static const uint8_t AIC3204_DACL_VOL_D = 0x41; // Register 65 - DAC Left Digital Vol Control +static const uint8_t AIC3204_DACR_VOL_D = 0x42; // Register 66 - DAC Right Digital Vol Control +static const uint8_t AIC3204_DRC_ENABLE = 0x44; +static const uint8_t AIC3204_ADC_CH_SET = 0x51; // Register 81 - ADC Channel Setup +static const uint8_t AIC3204_ADC_FGA_MUTE = 0x52; // Register 82 - ADC Fine Gain Adjust/Mute + +// Page 1 +static const uint8_t AIC3204_PWR_CFG = 0x01; // Register 1 - Power Config +static const uint8_t AIC3204_LDO_CTRL = 0x02; // Register 2 - LDO Control +static const uint8_t AIC3204_PLAY_CFG1 = 0x03; // Register 3 - Playback Config 1 +static const uint8_t AIC3204_PLAY_CFG2 = 0x04; // Register 4 - Playback Config 2 +static const uint8_t AIC3204_OP_PWR_CTRL = 0x09; // Register 9 - Output Driver Power Control +static const uint8_t AIC3204_CM_CTRL = 0x0A; // Register 10 - Common Mode Control +static const uint8_t AIC3204_HPL_ROUTE = 0x0C; // Register 12 - HPL Routing Select +static const uint8_t AIC3204_HPR_ROUTE = 0x0D; // Register 13 - HPR Routing Select +static const uint8_t AIC3204_LOL_ROUTE = 0x0E; // Register 14 - LOL Routing Selection +static const uint8_t AIC3204_LOR_ROUTE = 0x0F; // Register 15 - LOR Routing Selection +static const uint8_t AIC3204_HPL_GAIN = 0x10; // Register 16 - HPL Driver Gain +static const uint8_t AIC3204_HPR_GAIN = 0x11; // Register 17 - HPR Driver Gain +static const uint8_t AIC3204_LOL_DRV_GAIN = 0x12; // Register 18 - LOL Driver Gain Setting +static const uint8_t AIC3204_LOR_DRV_GAIN = 0x13; // Register 19 - LOR Driver Gain Setting +static const uint8_t AIC3204_HP_START = 0x14; // Register 20 - Headphone Driver Startup +static const uint8_t AIC3204_LPGA_P_ROUTE = 0x34; // Register 52 - Left PGA Positive Input Route +static const uint8_t AIC3204_LPGA_N_ROUTE = 0x36; // Register 54 - Left PGA Negative Input Route +static const uint8_t AIC3204_RPGA_P_ROUTE = 0x37; // Register 55 - Right PGA Positive Input Route +static const uint8_t AIC3204_RPGA_N_ROUTE = 0x39; // Register 57 - Right PGA Negative Input Route +static const uint8_t AIC3204_LPGA_VOL = 0x3B; // Register 59 - Left PGA Volume +static const uint8_t AIC3204_RPGA_VOL = 0x3C; // Register 60 - Right PGA Volume +static const uint8_t AIC3204_ADC_PTM = 0x3D; // Register 61 - ADC Power Tune Config +static const uint8_t AIC3204_AN_IN_CHRG = 0x47; // Register 71 - Analog Input Quick Charging Config +static const uint8_t AIC3204_REF_STARTUP = 0x7B; // Register 123 - Reference Power Up Config + +class AIC3204 : public audio_dac::AudioDac, public Component, public i2c::I2CDevice { + public: + void setup() override; + void dump_config() override; + float get_setup_priority() const override { return setup_priority::DATA; } + + bool set_mute_off() override; + bool set_mute_on() override; + bool set_auto_mute_mode(uint8_t auto_mute_mode); + bool set_volume(float volume) override; + + bool is_muted() override; + float volume() override; + + protected: + bool write_mute_(); + bool write_volume_(); + + uint8_t auto_mute_mode_{0}; + float volume_{0}; +}; + +} // namespace aic3204 +} // namespace esphome diff --git a/esphome/components/aic3204/audio_dac.py b/esphome/components/aic3204/audio_dac.py new file mode 100644 index 0000000000..da7a54df54 --- /dev/null +++ b/esphome/components/aic3204/audio_dac.py @@ -0,0 +1,52 @@ +from esphome import automation +import esphome.codegen as cg +from esphome.components import i2c +from esphome.components.audio_dac import AudioDac +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_MODE + +CODEOWNERS = ["@kbx81"] +DEPENDENCIES = ["i2c"] + +aic3204_ns = cg.esphome_ns.namespace("aic3204") +AIC3204 = aic3204_ns.class_("AIC3204", AudioDac, cg.Component, i2c.I2CDevice) + +SetAutoMuteAction = aic3204_ns.class_("SetAutoMuteAction", automation.Action) + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(AIC3204), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x18)) +) + + +SET_AUTO_MUTE_ACTION_SCHEMA = cv.maybe_simple_value( + { + cv.GenerateID(): cv.use_id(AIC3204), + cv.Required(CONF_MODE): cv.templatable(cv.int_range(max=7, min=0)), + }, + key=CONF_MODE, +) + + +@automation.register_action( + "aic3204.set_auto_mute_mode", SetAutoMuteAction, SET_AUTO_MUTE_ACTION_SCHEMA +) +async def aic3204_set_volume_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.get(CONF_MODE), args, int) + cg.add(var.set_auto_mute_mode(template_)) + + return var + + +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/aic3204/automation.h b/esphome/components/aic3204/automation.h new file mode 100644 index 0000000000..416a88fa12 --- /dev/null +++ b/esphome/components/aic3204/automation.h @@ -0,0 +1,23 @@ +#pragma once + +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "aic3204.h" + +namespace esphome { +namespace aic3204 { + +template class SetAutoMuteAction : public Action { + public: + explicit SetAutoMuteAction(AIC3204 *aic3204) : aic3204_(aic3204) {} + + TEMPLATABLE_VALUE(uint8_t, auto_mute_mode) + + void play(Ts... x) override { this->aic3204_->set_auto_mute_mode(this->auto_mute_mode_.value(x...)); } + + protected: + AIC3204 *aic3204_; +}; + +} // namespace aic3204 +} // namespace esphome diff --git a/esphome/components/alarm_control_panel/__init__.py b/esphome/components/alarm_control_panel/__init__.py index 8987d708fd..379fbf32f9 100644 --- a/esphome/components/alarm_control_panel/__init__.py +++ b/esphome/components/alarm_control_panel/__init__.py @@ -9,7 +9,7 @@ from esphome.const import ( CONF_MQTT_ID, CONF_ON_STATE, CONF_TRIGGER_ID, - CONF_WEB_SERVER_ID, + CONF_WEB_SERVER, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_helpers import setup_entity @@ -195,9 +195,8 @@ 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) + if web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(var, web_server_config) if mqtt_id := config.get(CONF_MQTT_ID): mqtt_ = cg.new_Pvariable(mqtt_id, var) await mqtt.register_mqtt_component(mqtt_, config) diff --git a/esphome/components/animation/__init__.py b/esphome/components/animation/__init__.py index dbfc82c891..5a308855de 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] @@ -269,7 +271,8 @@ async def to_code(config): pos += 1 elif config[CONF_TYPE] in ["RGB565", "TRANSPARENT_IMAGE"]: - data = [0 for _ in range(height * width * 2 * frames)] + bytes_per_pixel = 3 if transparent else 2 + data = [0 for _ in range(height * width * bytes_per_pixel * frames)] pos = 0 for frameIndex in range(frames): image.seek(frameIndex) @@ -286,17 +289,13 @@ async def to_code(config): G = g >> 2 B = b >> 3 rgb = (R << 11) | (G << 5) | B - - if transparent: - if rgb == 0x0020: - rgb = 0 - if a < 0x80: - rgb = 0x0020 - data[pos] = rgb >> 8 pos += 1 data[pos] = rgb & 0xFF pos += 1 + if transparent: + data[pos] = a + pos += 1 elif config[CONF_TYPE] in ["BINARY", "TRANSPARENT_BINARY"]: width8 = ((width + 7) // 8) * 8 @@ -306,6 +305,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]) diff --git a/esphome/components/animation/animation.cpp b/esphome/components/animation/animation.cpp index 7e0efa97e0..1375dfe07e 100644 --- a/esphome/components/animation/animation.cpp +++ b/esphome/components/animation/animation.cpp @@ -62,7 +62,7 @@ void Animation::set_frame(int frame) { } void Animation::update_data_start_() { - const uint32_t image_size = image_type_to_width_stride(this->width_, this->type_) * this->height_; + const uint32_t image_size = this->get_width_stride() * this->height_; this->data_start_ = this->animation_data_start_ + image_size * this->current_frame_; } diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index ad6fc79cf3..684540ffa6 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -62,6 +62,8 @@ service APIConnection { rpc unsubscribe_bluetooth_le_advertisements(UnsubscribeBluetoothLEAdvertisementsRequest) returns (void) {} rpc subscribe_voice_assistant(SubscribeVoiceAssistantRequest) returns (void) {} + rpc voice_assistant_get_configuration(VoiceAssistantConfigurationRequest) returns (VoiceAssistantConfigurationResponse) {} + rpc voice_assistant_set_configuration(VoiceAssistantSetConfiguration) returns (void) {} rpc alarm_control_panel_command (AlarmControlPanelCommandRequest) returns (void) {} } @@ -1118,6 +1120,7 @@ message MediaPlayerSupportedFormat { uint32 sample_rate = 2; uint32 num_channels = 3; MediaPlayerFormatPurpose purpose = 4; + uint32 sample_bytes = 5; } message ListEntitiesMediaPlayerResponse { option (id) = 63; @@ -1553,6 +1556,53 @@ 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; +} + +message VoiceAssistantWakeWord { + string 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 string 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 string active_wake_words = 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..bb55a2ccf6 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1,4 +1,5 @@ #include "api_connection.h" +#ifdef USE_API #include #include #include @@ -1032,6 +1033,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); } @@ -1213,6 +1215,52 @@ 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); + } +} + +VoiceAssistantConfigurationResponse APIConnection::voice_assistant_get_configuration( + const VoiceAssistantConfigurationRequest &msg) { + VoiceAssistantConfigurationResponse resp; + if (voice_assistant::global_voice_assistant != nullptr) { + if (voice_assistant::global_voice_assistant->get_api_connection() != this) { + return resp; + } + + auto &config = voice_assistant::global_voice_assistant->get_configuration(); + for (auto &wake_word : config.available_wake_words) { + VoiceAssistantWakeWord resp_wake_word; + resp_wake_word.id = wake_word.id; + resp_wake_word.wake_word = wake_word.wake_word; + for (const auto &lang : wake_word.trained_languages) { + resp_wake_word.trained_languages.push_back(lang); + } + resp.available_wake_words.push_back(std::move(resp_wake_word)); + } + for (auto &wake_word_id : config.active_wake_words) { + resp.active_wake_words.push_back(wake_word_id); + } + resp.max_active_wake_words = config.max_active_wake_words; + } + return resp; +} + +void APIConnection::voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &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_set_configuration(msg.active_wake_words); + } +} + #endif #ifdef USE_ALARM_CONTROL_PANEL @@ -1521,3 +1569,4 @@ void APIConnection::on_fatal_error() { } // namespace api } // namespace esphome +#endif diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 714e806470..043aaee421 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -1,12 +1,13 @@ #pragma once +#include "esphome/core/defines.h" +#ifdef USE_API #include "api_frame_helper.h" #include "api_pb2.h" #include "api_pb2_service.h" #include "api_server.h" #include "esphome/core/application.h" #include "esphome/core/component.h" -#include "esphome/core/defines.h" #include @@ -151,6 +152,10 @@ 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; + VoiceAssistantConfigurationResponse voice_assistant_get_configuration( + const VoiceAssistantConfigurationRequest &msg) override; + void voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) override; #endif #ifdef USE_ALARM_CONTROL_PANEL @@ -264,3 +269,4 @@ class APIConnection : public APIServerConnection { } // namespace api } // namespace esphome +#endif diff --git a/esphome/components/api/api_frame_helper.cpp b/esphome/components/api/api_frame_helper.cpp index f4b18a1fd6..62f375508c 100644 --- a/esphome/components/api/api_frame_helper.cpp +++ b/esphome/components/api/api_frame_helper.cpp @@ -1,5 +1,5 @@ #include "api_frame_helper.h" - +#ifdef USE_API #include "esphome/core/log.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" @@ -1028,3 +1028,4 @@ APIError APIPlaintextFrameHelper::shutdown(int how) { } // namespace api } // namespace esphome +#endif diff --git a/esphome/components/api/api_frame_helper.h b/esphome/components/api/api_frame_helper.h index bf4872d2d6..56d8bf1973 100644 --- a/esphome/components/api/api_frame_helper.h +++ b/esphome/components/api/api_frame_helper.h @@ -5,7 +5,7 @@ #include #include "esphome/core/defines.h" - +#ifdef USE_API #ifdef USE_API_NOISE #include "noise/protocol.h" #endif @@ -190,3 +190,4 @@ class APIPlaintextFrameHelper : public APIFrameHelper { } // namespace api } // namespace esphome +#endif diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index c944d0dae8..8df152881c 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 @@ -7061,6 +7071,193 @@ 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 VoiceAssistantWakeWord::decode_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 1: { + this->id = value.as_string(); + return true; + } + 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_string(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: "); + out.append("'").append(this->id).append("'"); + 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 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; + } + case 2: { + this->active_wake_words.push_back(value.as_string()); + 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_string(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: "); + out.append("'").append(it).append("'"); + 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_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 1: { + this->active_wake_words.push_back(value.as_string()); + return true; + } + default: + return false; + } +} +void VoiceAssistantSetConfiguration::encode(ProtoWriteBuffer buffer) const { + for (auto &it : this->active_wake_words) { + buffer.encode_string(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: "); + out.append("'").append(it).append("'"); + 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..063c217bf7 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; @@ -1825,6 +1826,76 @@ 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 VoiceAssistantWakeWord : public ProtoMessage { + public: + std::string id{}; + 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; +}; +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_length(uint32_t field_id, ProtoLengthDelimited 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..6e11d7169d 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -486,6 +486,29 @@ 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_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) { @@ -1135,6 +1158,39 @@ 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; + } + 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; } @@ -1625,6 +1681,35 @@ void APIServerConnection::on_subscribe_voice_assistant_request(const SubscribeVo this->subscribe_voice_assistant(msg); } #endif +#ifdef USE_VOICE_ASSISTANT +void APIServerConnection::on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &msg) { + if (!this->is_connection_setup()) { + this->on_no_setup_connection(); + return; + } + if (!this->is_authenticated()) { + this->on_unauthenticated_access(); + return; + } + VoiceAssistantConfigurationResponse ret = this->voice_assistant_get_configuration(msg); + if (!this->send_voice_assistant_configuration_response(ret)) { + this->on_fatal_error(); + } +} +#endif +#ifdef USE_VOICE_ASSISTANT +void APIServerConnection::on_voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) { + if (!this->is_connection_setup()) { + this->on_no_setup_connection(); + return; + } + if (!this->is_authenticated()) { + this->on_unauthenticated_access(); + return; + } + this->voice_assistant_set_configuration(msg); +} +#endif #ifdef USE_ALARM_CONTROL_PANEL void APIServerConnection::on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &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 83bfc2ed98..51b94bf530 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -247,6 +247,21 @@ 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_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 @@ -419,6 +434,13 @@ class APIServerConnection : public APIServerConnectionBase { #ifdef USE_VOICE_ASSISTANT virtual void subscribe_voice_assistant(const SubscribeVoiceAssistantRequest &msg) = 0; #endif +#ifdef USE_VOICE_ASSISTANT + virtual VoiceAssistantConfigurationResponse voice_assistant_get_configuration( + const VoiceAssistantConfigurationRequest &msg) = 0; +#endif +#ifdef USE_VOICE_ASSISTANT + virtual void voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) = 0; +#endif #ifdef USE_ALARM_CONTROL_PANEL virtual void alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) = 0; #endif @@ -520,6 +542,12 @@ class APIServerConnection : public APIServerConnectionBase { #ifdef USE_VOICE_ASSISTANT void on_subscribe_voice_assistant_request(const SubscribeVoiceAssistantRequest &msg) override; #endif +#ifdef USE_VOICE_ASSISTANT + void on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &msg) override; +#endif +#ifdef USE_VOICE_ASSISTANT + void on_voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) override; +#endif #ifdef USE_ALARM_CONTROL_PANEL void on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &msg) override; #endif diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 0fde3e47af..f16b5a13cf 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -1,4 +1,5 @@ #include "api_server.h" +#ifdef USE_API #include #include "api_connection.h" #include "esphome/components/network/util.h" @@ -403,3 +404,4 @@ void APIServer::on_alarm_control_panel_update(alarm_control_panel::AlarmControlP } // namespace api } // namespace esphome +#endif diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index 899eaede49..42e0b1048a 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -1,5 +1,7 @@ #pragma once +#include "esphome/core/defines.h" +#ifdef USE_API #include "api_noise_context.h" #include "api_pb2.h" #include "api_pb2_service.h" @@ -7,7 +9,6 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/controller.h" -#include "esphome/core/defines.h" #include "esphome/core/log.h" #include "list_entities.h" #include "subscribe_state.h" @@ -153,3 +154,4 @@ template class APIConnectedCondition : public Condition { } // namespace api } // namespace esphome +#endif diff --git a/esphome/components/api/custom_api_device.h b/esphome/components/api/custom_api_device.h index 845a35fc54..1a8e189f41 100644 --- a/esphome/components/api/custom_api_device.h +++ b/esphome/components/api/custom_api_device.h @@ -1,9 +1,9 @@ #pragma once #include -#include "user_services.h" #include "api_server.h" - +#ifdef USE_API +#include "user_services.h" namespace esphome { namespace api { @@ -216,3 +216,4 @@ class CustomAPIDevice { } // namespace api } // namespace esphome +#endif diff --git a/esphome/components/api/homeassistant_service.h b/esphome/components/api/homeassistant_service.h index f04181e5b2..e91756c3c9 100644 --- a/esphome/components/api/homeassistant_service.h +++ b/esphome/components/api/homeassistant_service.h @@ -1,10 +1,10 @@ #pragma once +#include "api_server.h" +#ifdef USE_API +#include "api_pb2.h" #include "esphome/core/helpers.h" #include "esphome/core/automation.h" -#include "api_pb2.h" -#include "api_server.h" - #include namespace esphome { @@ -81,3 +81,4 @@ template class HomeAssistantServiceCallAction : public Action +#include + +namespace esphome { +namespace audio { + +struct AudioStreamInfo { + bool operator==(const AudioStreamInfo &rhs) const { + return (channels == rhs.channels) && (bits_per_sample == rhs.bits_per_sample) && (sample_rate == rhs.sample_rate); + } + bool operator!=(const AudioStreamInfo &rhs) const { return !operator==(rhs); } + size_t get_bytes_per_sample() const { return bits_per_sample / 8; } + uint8_t channels = 1; + uint8_t bits_per_sample = 16; + uint32_t sample_rate = 16000; +}; + +} // namespace audio +} // namespace esphome diff --git a/esphome/components/audio_dac/__init__.py b/esphome/components/audio_dac/__init__.py new file mode 100644 index 0000000000..978ed195bd --- /dev/null +++ b/esphome/components/audio_dac/__init__.py @@ -0,0 +1,57 @@ +from esphome import automation +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_VOLUME +from esphome.core import coroutine_with_priority + +CODEOWNERS = ["@kbx81"] +IS_PLATFORM_COMPONENT = True + +audio_dac_ns = cg.esphome_ns.namespace("audio_dac") +AudioDac = audio_dac_ns.class_("AudioDac") + +MuteOffAction = audio_dac_ns.class_("MuteOffAction", automation.Action) +MuteOnAction = audio_dac_ns.class_("MuteOnAction", automation.Action) +SetVolumeAction = audio_dac_ns.class_("SetVolumeAction", automation.Action) + + +MUTE_ACTION_SCHEMA = maybe_simple_id( + { + cv.GenerateID(): cv.use_id(AudioDac), + } +) + +SET_VOLUME_ACTION_SCHEMA = cv.maybe_simple_value( + { + cv.GenerateID(): cv.use_id(AudioDac), + cv.Required(CONF_VOLUME): cv.templatable(cv.percentage), + }, + key=CONF_VOLUME, +) + + +@automation.register_action("audio_dac.mute_off", MuteOffAction, MUTE_ACTION_SCHEMA) +@automation.register_action("audio_dac.mute_on", MuteOnAction, MUTE_ACTION_SCHEMA) +async def audio_dac_mute_action_to_code(config, action_id, template_arg, args): + paren = await cg.get_variable(config[CONF_ID]) + return cg.new_Pvariable(action_id, template_arg, paren) + + +@automation.register_action( + "audio_dac.set_volume", SetVolumeAction, SET_VOLUME_ACTION_SCHEMA +) +async def audio_dac_set_volume_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.get(CONF_VOLUME), args, float) + cg.add(var.set_volume(template_)) + + return var + + +@coroutine_with_priority(100.0) +async def to_code(config): + cg.add_define("USE_AUDIO_DAC") + cg.add_global(audio_dac_ns.using) diff --git a/esphome/components/audio_dac/audio_dac.h b/esphome/components/audio_dac/audio_dac.h new file mode 100644 index 0000000000..a62d17b849 --- /dev/null +++ b/esphome/components/audio_dac/audio_dac.h @@ -0,0 +1,23 @@ +#pragma once + +#include "esphome/core/defines.h" +#include "esphome/core/hal.h" + +namespace esphome { +namespace audio_dac { + +class AudioDac { + public: + virtual bool set_mute_off() = 0; + virtual bool set_mute_on() = 0; + virtual bool set_volume(float volume) = 0; + + virtual bool is_muted() = 0; + virtual float volume() = 0; + + protected: + bool is_muted_{false}; +}; + +} // namespace audio_dac +} // namespace esphome diff --git a/esphome/components/audio_dac/automation.h b/esphome/components/audio_dac/automation.h new file mode 100644 index 0000000000..b6cf2acaf4 --- /dev/null +++ b/esphome/components/audio_dac/automation.h @@ -0,0 +1,43 @@ +#pragma once + +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "audio_dac.h" + +namespace esphome { +namespace audio_dac { + +template class MuteOffAction : public Action { + public: + explicit MuteOffAction(AudioDac *audio_dac) : audio_dac_(audio_dac) {} + + void play(Ts... x) override { this->audio_dac_->set_mute_off(); } + + protected: + AudioDac *audio_dac_; +}; + +template class MuteOnAction : public Action { + public: + explicit MuteOnAction(AudioDac *audio_dac) : audio_dac_(audio_dac) {} + + void play(Ts... x) override { this->audio_dac_->set_mute_on(); } + + protected: + AudioDac *audio_dac_; +}; + +template class SetVolumeAction : public Action { + public: + explicit SetVolumeAction(AudioDac *audio_dac) : audio_dac_(audio_dac) {} + + TEMPLATABLE_VALUE(float, volume) + + void play(Ts... x) override { this->audio_dac_->set_volume(this->volume_.value(x...)); } + + protected: + AudioDac *audio_dac_; +}; + +} // namespace audio_dac +} // namespace esphome diff --git a/esphome/components/axs15231/__init__.py b/esphome/components/axs15231/__init__.py new file mode 100644 index 0000000000..3246dbed24 --- /dev/null +++ b/esphome/components/axs15231/__init__.py @@ -0,0 +1,6 @@ +import esphome.codegen as cg + +CODEOWNERS = ["@clydebarrow"] +DEPENDENCIES = ["i2c"] + +axs15231_ns = cg.esphome_ns.namespace("axs15231") diff --git a/esphome/components/axs15231/touchscreen/__init__.py b/esphome/components/axs15231/touchscreen/__init__.py new file mode 100644 index 0000000000..8c18d8ca75 --- /dev/null +++ b/esphome/components/axs15231/touchscreen/__init__.py @@ -0,0 +1,36 @@ +from esphome import pins +import esphome.codegen as cg +from esphome.components import i2c, touchscreen +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_INTERRUPT_PIN, CONF_RESET_PIN + +from .. import axs15231_ns + +AXS15231Touchscreen = axs15231_ns.class_( + "AXS15231Touchscreen", + touchscreen.Touchscreen, + i2c.I2CDevice, +) + +CONFIG_SCHEMA = ( + touchscreen.touchscreen_schema("50ms") + .extend( + { + cv.GenerateID(): cv.declare_id(AXS15231Touchscreen), + 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(0x3B)) +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await touchscreen.register_touchscreen(var, config) + await i2c.register_i2c_device(var, config) + + if interrupt_pin := config.get(CONF_INTERRUPT_PIN): + cg.add(var.set_interrupt_pin(await cg.gpio_pin_expression(interrupt_pin))) + 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/axs15231/touchscreen/axs15231_touchscreen.cpp b/esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp new file mode 100644 index 0000000000..54b39a6bb9 --- /dev/null +++ b/esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp @@ -0,0 +1,64 @@ +#include "axs15231_touchscreen.h" + +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace axs15231 { + +static const char *const TAG = "ax15231.touchscreen"; + +constexpr static const uint8_t AXS_READ_TOUCHPAD[11] = {0xb5, 0xab, 0xa5, 0x5a, 0x0, 0x0, 0x0, 0x8}; + +#define ERROR_CHECK(err) \ + if ((err) != i2c::ERROR_OK) { \ + this->status_set_warning("Failed to communicate"); \ + return; \ + } + +void AXS15231Touchscreen::setup() { + ESP_LOGCONFIG(TAG, "Setting up AXS15231 Touchscreen..."); + if (this->reset_pin_ != nullptr) { + this->reset_pin_->setup(); + this->reset_pin_->digital_write(false); + delay(5); + this->reset_pin_->digital_write(true); + delay(10); + } + if (this->interrupt_pin_ != nullptr) { + this->interrupt_pin_->pin_mode(gpio::FLAG_INPUT); + this->interrupt_pin_->setup(); + this->attach_interrupt_(this->interrupt_pin_, gpio::INTERRUPT_FALLING_EDGE); + } + this->x_raw_max_ = this->display_->get_native_width(); + this->y_raw_max_ = this->display_->get_native_height(); + ESP_LOGCONFIG(TAG, "AXS15231 Touchscreen setup complete"); +} + +void AXS15231Touchscreen::update_touches() { + i2c::ErrorCode err; + uint8_t data[8]{}; + + err = this->write(AXS_READ_TOUCHPAD, sizeof(AXS_READ_TOUCHPAD), false); + ERROR_CHECK(err); + err = this->read(data, sizeof(data)); + ERROR_CHECK(err); + this->status_clear_warning(); + if (data[0] != 0) // no touches + return; + uint16_t x = encode_uint16(data[2] & 0xF, data[3]); + uint16_t y = encode_uint16(data[4] & 0xF, data[5]); + this->add_raw_touch_position_(0, x, y); +} + +void AXS15231Touchscreen::dump_config() { + ESP_LOGCONFIG(TAG, "AXS15231 Touchscreen:"); + LOG_I2C_DEVICE(this); + LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_); + LOG_PIN(" Reset Pin: ", this->reset_pin_); + ESP_LOGCONFIG(TAG, " Width: %d", this->x_raw_max_); + ESP_LOGCONFIG(TAG, " Height: %d", this->y_raw_max_); +} + +} // namespace axs15231 +} // namespace esphome diff --git a/esphome/components/axs15231/touchscreen/axs15231_touchscreen.h b/esphome/components/axs15231/touchscreen/axs15231_touchscreen.h new file mode 100644 index 0000000000..a55c5c0d32 --- /dev/null +++ b/esphome/components/axs15231/touchscreen/axs15231_touchscreen.h @@ -0,0 +1,27 @@ +#pragma once + +#include "esphome/components/i2c/i2c.h" +#include "esphome/components/touchscreen/touchscreen.h" +#include "esphome/core/component.h" +#include "esphome/core/hal.h" + +namespace esphome { +namespace axs15231 { + +class AXS15231Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice { + public: + void setup() override; + void dump_config() override; + + void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; } + void set_reset_pin(GPIOPin *pin) { this->reset_pin_ = pin; } + + protected: + void update_touches() override; + + InternalGPIOPin *interrupt_pin_{}; + GPIOPin *reset_pin_{}; +}; + +} // namespace axs15231 +} // namespace esphome diff --git a/esphome/components/bang_bang/bang_bang_climate.cpp b/esphome/components/bang_bang/bang_bang_climate.cpp index b34764907f..aed97b2890 100644 --- a/esphome/components/bang_bang/bang_bang_climate.cpp +++ b/esphome/components/bang_bang/bang_bang_climate.cpp @@ -157,8 +157,11 @@ void BangBangClimate::switch_to_action_(climate::ClimateAction action) { default: trig = nullptr; } - assert(trig != nullptr); - trig->trigger(); + if (trig != nullptr) { + trig->trigger(); + } else { + ESP_LOGW(TAG, "trig not set - unsupported action"); + } this->action = action; this->prev_trigger_ = trig; this->publish_state(); diff --git a/esphome/components/bedjet/bedjet_codec.cpp b/esphome/components/bedjet/bedjet_codec.cpp index 7e90621235..9a312e226c 100644 --- a/esphome/components/bedjet/bedjet_codec.cpp +++ b/esphome/components/bedjet/bedjet_codec.cpp @@ -13,8 +13,10 @@ float bedjet_temp_to_f(const uint8_t temp) { /** Cleans up the packet before sending. */ BedjetPacket *BedjetCodec::clean_packet_() { - // So far no commands require more than 2 bytes of data. - assert(this->packet_.data_length <= 2); + // So far no commands require more than 2 bytes of data + if (this->packet_.data_length > 2) { + ESP_LOGW(TAG, "Packet may be malformed"); + } for (int i = this->packet_.data_length; i < 2; i++) { this->packet_.data[i] = '\0'; } diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index 95fd17bcc0..d947c2aba6 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -25,7 +25,7 @@ from esphome.const import ( CONF_STATE, CONF_TIMING, CONF_TRIGGER_ID, - CONF_WEB_SERVER_ID, + CONF_WEB_SERVER, DEVICE_CLASS_BATTERY, DEVICE_CLASS_BATTERY_CHARGING, DEVICE_CLASS_CARBON_MONOXIDE, @@ -543,9 +543,8 @@ 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) + if web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(var, web_server_config) async def register_binary_sensor(var, config): diff --git a/esphome/components/bl0906/sensor.py b/esphome/components/bl0906/sensor.py index bc370c9252..42c6f06092 100644 --- a/esphome/components/bl0906/sensor.py +++ b/esphome/components/bl0906/sensor.py @@ -145,8 +145,9 @@ FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( ), ) 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) + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + return var async def to_code(config): 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/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/ble_rssi/sensor.py b/esphome/components/ble_rssi/sensor.py index e3ba1abfd7..c4e767aa21 100644 --- a/esphome/components/ble_rssi/sensor.py +++ b/esphome/components/ble_rssi/sensor.py @@ -45,7 +45,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, } ) .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) @@ -79,7 +79,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/bme68x_bsec2/__init__.py b/esphome/components/bme68x_bsec2/__init__.py index 1930c7c9e3..d6dbb52f18 100644 --- a/esphome/components/bme68x_bsec2/__init__.py +++ b/esphome/components/bme68x_bsec2/__init__.py @@ -16,7 +16,7 @@ CODEOWNERS = ["@neffs", "@kbx81"] DOMAIN = "bme68x_bsec2" -BSEC2_LIBRARY_VERSION = "v1.7.2502" +BSEC2_LIBRARY_VERSION = "v1.8.2610" CONF_ALGORITHM_OUTPUT = "algorithm_output" CONF_BME68X_BSEC2_ID = "bme68x_bsec2_id" diff --git a/esphome/components/button/__init__.py b/esphome/components/button/__init__.py index 3010d3006a..366d0edf7d 100644 --- a/esphome/components/button/__init__.py +++ b/esphome/components/button/__init__.py @@ -11,7 +11,7 @@ from esphome.const import ( CONF_MQTT_ID, CONF_ON_PRESS, CONF_TRIGGER_ID, - CONF_WEB_SERVER_ID, + CONF_WEB_SERVER, DEVICE_CLASS_EMPTY, DEVICE_CLASS_IDENTIFY, DEVICE_CLASS_RESTART, @@ -97,9 +97,8 @@ 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) + if web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(var, web_server_config) async def register_button(var, config): diff --git a/esphome/components/bytebuffer/__init__.py b/esphome/components/bytebuffer/__init__.py new file mode 100644 index 0000000000..3c7c695118 --- /dev/null +++ b/esphome/components/bytebuffer/__init__.py @@ -0,0 +1,5 @@ +CODEOWNERS = ["@clydebarrow"] + +# Allows bytebuffer to be configured in yaml, to allow use of the C++ api. + +CONFIG_SCHEMA = {} diff --git a/esphome/components/bytebuffer/bytebuffer.h b/esphome/components/bytebuffer/bytebuffer.h new file mode 100644 index 0000000000..030484ce32 --- /dev/null +++ b/esphome/components/bytebuffer/bytebuffer.h @@ -0,0 +1,421 @@ +#pragma once + +#include +#include +#include +#include +#include "esphome/core/helpers.h" + +namespace esphome { +namespace bytebuffer { + +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: + * + * 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. + * + * The code is defined here in the header file rather than in a .cpp file, so that it does not get compiled if not used. + * The templated functions ensure that only those typed functions actually used are compiled. The functions + * are implicitly inline-able which will aid performance. + */ +class ByteBuffer { + public: + // Default constructor (compatibility with TEMPLATABLE_VALUE) + // Creates a zero-length ByteBuffer which is little use to anybody. + ByteBuffer() : ByteBuffer(std::vector()) {} + + /** + * Create a new Bytebuffer with the given capacity + */ + ByteBuffer(size_t capacity, Endian endianness = LITTLE) + : data_(std::vector(capacity)), endianness_(endianness), limit_(capacity){}; + + // templated functions to implement putting and getting data of various types. There are two flavours of all + // functions - one that uses the position as the offset, and updates the position accordingly, and one that + // takes an explicit offset and does not update the position. + // Separate temnplates are provided for types that fit into 32 bits and those that are bigger. These delegate + // the actual put/get to common code based around those sizes. + // This reduces the code size and execution time for smaller types. A similar structure for e.g. 16 bits is unlikely + // to provide any further benefit given that all target platforms are native 32 bit. + + template + T get(typename std::enable_if::value, T>::type * = 0, + typename std::enable_if<(sizeof(T) <= sizeof(uint32_t)), T>::type * = 0) { + // integral types that fit into 32 bit + return static_cast(this->get_uint32_(sizeof(T))); + } + + template + T get(size_t offset, typename std::enable_if::value, T>::type * = 0, + typename std::enable_if<(sizeof(T) <= sizeof(uint32_t)), T>::type * = 0) { + return static_cast(this->get_uint32_(offset, sizeof(T))); + } + + template + void put(const T &value, typename std::enable_if::value, T>::type * = 0, + typename std::enable_if<(sizeof(T) <= sizeof(uint32_t)), T>::type * = 0) { + this->put_uint32_(static_cast(value), sizeof(T)); + } + + template + void put(const T &value, size_t offset, typename std::enable_if::value, T>::type * = 0, + typename std::enable_if<(sizeof(T) <= sizeof(uint32_t)), T>::type * = 0) { + this->put_uint32_(static_cast(value), offset, sizeof(T)); + } + + // integral types that do not fit into 32 bit (basically only 64 bit types) + template + T get(typename std::enable_if::value, T>::type * = 0, + typename std::enable_if<(sizeof(T) == sizeof(uint64_t)), T>::type * = 0) { + return static_cast(this->get_uint64_(sizeof(T))); + } + + template + T get(size_t offset, typename std::enable_if::value, T>::type * = 0, + typename std::enable_if<(sizeof(T) == sizeof(uint64_t)), T>::type * = 0) { + return static_cast(this->get_uint64_(offset, sizeof(T))); + } + + template + void put(const T &value, typename std::enable_if::value, T>::type * = 0, + typename std::enable_if<(sizeof(T) == sizeof(uint64_t)), T>::type * = 0) { + this->put_uint64_(value, sizeof(T)); + } + + template + void put(const T &value, size_t offset, typename std::enable_if::value, T>::type * = 0, + typename std::enable_if<(sizeof(T) == sizeof(uint64_t)), T>::type * = 0) { + this->put_uint64_(static_cast(value), offset, sizeof(T)); + } + + // floating point types. Caters for 32 and 64 bit floating point. + template + T get(typename std::enable_if::value, T>::type * = 0, + typename std::enable_if<(sizeof(T) == sizeof(uint32_t)), T>::type * = 0) { + return bit_cast(this->get_uint32_(sizeof(T))); + } + + template + T get(typename std::enable_if::value, T>::type * = 0, + typename std::enable_if<(sizeof(T) == sizeof(uint64_t)), T>::type * = 0) { + return bit_cast(this->get_uint64_(sizeof(T))); + } + + template + T get(size_t offset, typename std::enable_if::value, T>::type * = 0, + typename std::enable_if<(sizeof(T) == sizeof(uint32_t)), T>::type * = 0) { + return bit_cast(this->get_uint32_(offset, sizeof(T))); + } + + template + T get(size_t offset, typename std::enable_if::value, T>::type * = 0, + typename std::enable_if<(sizeof(T) == sizeof(uint64_t)), T>::type * = 0) { + return bit_cast(this->get_uint64_(offset, sizeof(T))); + } + template + void put(const T &value, typename std::enable_if::value, T>::type * = 0, + typename std::enable_if<(sizeof(T) <= sizeof(uint32_t)), T>::type * = 0) { + this->put_uint32_(bit_cast(value), sizeof(T)); + } + + template + void put(const T &value, typename std::enable_if::value, T>::type * = 0, + typename std::enable_if<(sizeof(T) == sizeof(uint64_t)), T>::type * = 0) { + this->put_uint64_(bit_cast(value), sizeof(T)); + } + + template + void put(const T &value, size_t offset, typename std::enable_if::value, T>::type * = 0, + typename std::enable_if<(sizeof(T) <= sizeof(uint32_t)), T>::type * = 0) { + this->put_uint32_(bit_cast(value), offset, sizeof(T)); + } + + template + void put(const T &value, size_t offset, typename std::enable_if::value, T>::type * = 0, + typename std::enable_if<(sizeof(T) == sizeof(uint64_t)), T>::type * = 0) { + this->put_uint64_(bit_cast(value), offset, sizeof(T)); + } + + template static ByteBuffer wrap(T value, Endian endianness = LITTLE) { + ByteBuffer buffer = ByteBuffer(sizeof(T), endianness); + buffer.put(value); + buffer.flip(); + return buffer; + } + + static ByteBuffer wrap(std::vector const &data, Endian endianness = LITTLE) { + ByteBuffer buffer = {data}; + buffer.endianness_ = endianness; + return buffer; + } + + static ByteBuffer wrap(const uint8_t *ptr, size_t len, Endian endianness = LITTLE) { + return wrap(std::vector(ptr, ptr + len), endianness); + } + + // convenience functions with explicit types named.. + void put_float(float value) { this->put(value); } + void put_double(double value) { this->put(value); } + + uint8_t get_uint8() { return this->data_[this->position_++]; } + // Get a 16 bit unsigned value, increment by 2 + uint16_t get_uint16() { return this->get(); } + // Get a 24 bit unsigned value, increment by 3 + uint32_t get_uint24() { return this->get_uint32_(3); }; + // Get a 32 bit unsigned value, increment by 4 + uint32_t get_uint32() { return this->get(); }; + // Get a 64 bit unsigned value, increment by 8 + uint64_t get_uint64() { return this->get(); }; + // Signed versions of the get functions + uint8_t get_int8() { return static_cast(this->get_uint8()); }; + int16_t get_int16() { return this->get(); } + int32_t get_int32() { return this->get(); } + int64_t get_int64() { return this->get(); } + // Get a float value, increment by 4 + float get_float() { return this->get(); } + // Get a double value, increment by 8 + double get_double() { return this->get(); } + + // Get a bool value, increment by 1 + bool get_bool() { return static_cast(this->get_uint8()); } + + uint32_t get_int24(size_t offset) { + auto value = this->get_uint24(offset); + uint32_t mask = (~static_cast(0)) << 23; + if ((value & mask) != 0) + value |= mask; + return value; + } + + uint32_t get_int24() { + auto value = this->get_uint24(); + uint32_t mask = (~static_cast(0)) << 23; + if ((value & mask) != 0) + value |= mask; + return value; + } + std::vector get_vector(size_t length, size_t offset) { + auto start = this->data_.begin() + offset; + return {start, start + length}; + } + + std::vector get_vector(size_t length) { + auto result = this->get_vector(length, this->position_); + this->position_ += length; + return result; + } + + // Convenience named functions + void put_uint8(uint8_t value) { this->data_[this->position_++] = value; } + void put_uint16(uint16_t value) { this->put(value); } + void put_uint24(uint32_t value) { this->put_uint32_(value, 3); } + void put_uint32(uint32_t value) { this->put(value); } + void put_uint64(uint64_t value) { this->put(value); } + // Signed versions of the put functions + void put_int8(int8_t value) { this->put_uint8(static_cast(value)); } + void put_int16(int16_t value) { this->put(value); } + void put_int24(int32_t value) { this->put_uint32_(value, 3); } + void put_int32(int32_t value) { this->put(value); } + void put_int64(int64_t value) { this->put(value); } + // Extra put functions + void put_bool(bool value) { this->put_uint8(value); } + + // versions of the above with an offset, these do not update the position + + uint64_t get_uint64(size_t offset) { return this->get(offset); } + uint32_t get_uint24(size_t offset) { return this->get_uint32_(offset, 3); }; + double get_double(size_t offset) { return get(offset); } + + // Get one byte from the buffer, increment position by 1 + uint8_t get_uint8(size_t offset) { return this->data_[offset]; } + // Get a 16 bit unsigned value, increment by 2 + uint16_t get_uint16(size_t offset) { return get(offset); } + // Get a 24 bit unsigned value, increment by 3 + uint32_t get_uint32(size_t offset) { return this->get(offset); }; + // Get a 64 bit unsigned value, increment by 8 + uint8_t get_int8(size_t offset) { return get(offset); } + int16_t get_int16(size_t offset) { return get(offset); } + int32_t get_int32(size_t offset) { return get(offset); } + int64_t get_int64(size_t offset) { return get(offset); } + // Get a float value, increment by 4 + float get_float(size_t offset) { return get(offset); } + // Get a double value, increment by 8 + + // Get a bool value, increment by 1 + bool get_bool(size_t offset) { return this->get_uint8(offset); } + + void put_uint8(uint8_t value, size_t offset) { this->data_[offset] = value; } + void put_uint16(uint16_t value, size_t offset) { this->put(value, offset); } + void put_uint24(uint32_t value, size_t offset) { this->put(value, offset); } + void put_uint32(uint32_t value, size_t offset) { this->put(value, offset); } + void put_uint64(uint64_t value, size_t offset) { this->put(value, offset); } + // Signed versions of the put functions + void put_int8(int8_t value, size_t offset) { this->put_uint8(static_cast(value), offset); } + void put_int16(int16_t value, size_t offset) { this->put(value, offset); } + void put_int24(int32_t value, size_t offset) { this->put_uint32_(value, offset, 3); } + void put_int32(int32_t value, size_t offset) { this->put(value, offset); } + void put_int64(int64_t value, size_t offset) { this->put(value, offset); } + // Extra put functions + void put_float(float value, size_t offset) { this->put(value, offset); } + void put_double(double value, size_t offset) { this->put(value, offset); } + void put_bool(bool value, size_t offset) { this->put_uint8(value, offset); } + void put(const std::vector &value, size_t offset) { + std::copy(value.begin(), value.end(), this->data_.begin() + offset); + } + void put_vector(const std::vector &value, size_t offset) { this->put(value, offset); } + void put(const std::vector &value) { + this->put_vector(value, this->position_); + this->position_ += value.size(); + } + void put_vector(const std::vector &value) { this->put(value); } + + // Getters + + 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; } + // retrieve a pointer to the underlying data. + std::vector get_data() { return this->data_; }; + + void get_bytes(void *dest, size_t length) { + std::copy(this->data_.begin() + this->position_, this->data_.begin() + this->position_ + length, (uint8_t *) dest); + this->position_ += length; + } + + void get_bytes(void *dest, size_t length, size_t offset) { + std::copy(this->data_.begin() + offset, this->data_.begin() + offset + length, (uint8_t *) dest); + } + + void rewind() { this->position_ = 0; } + void reset() { this->position_ = this->mark_; } + + void set_limit(size_t limit) { this->limit_ = limit; } + void set_position(size_t position) { this->position_ = position; } + void clear() { + this->limit_ = this->get_capacity(); + this->position_ = 0; + } + void flip() { + this->limit_ = this->position_; + this->position_ = 0; + } + + protected: + uint64_t get_uint64_(size_t offset, size_t length) const { + uint64_t value = 0; + if (this->endianness_ == LITTLE) { + offset += length; + while (length-- != 0) { + value <<= 8; + value |= this->data_[--offset]; + } + } else { + while (length-- != 0) { + value <<= 8; + value |= this->data_[offset++]; + } + } + return value; + } + + uint64_t get_uint64_(size_t length) { + auto result = this->get_uint64_(this->position_, length); + this->position_ += length; + return result; + } + uint32_t get_uint32_(size_t offset, size_t length) const { + uint32_t value = 0; + if (this->endianness_ == LITTLE) { + offset += length; + while (length-- != 0) { + value <<= 8; + value |= this->data_[--offset]; + } + } else { + while (length-- != 0) { + value <<= 8; + value |= this->data_[offset++]; + } + } + return value; + } + + uint32_t get_uint32_(size_t length) { + auto result = this->get_uint32_(this->position_, length); + this->position_ += length; + return result; + } + + /// Putters + + void put_uint64_(uint64_t value, size_t length) { + this->put_uint64_(value, this->position_, length); + this->position_ += length; + } + void put_uint32_(uint32_t value, size_t length) { + this->put_uint32_(value, this->position_, length); + this->position_ += length; + } + + void put_uint64_(uint64_t value, size_t offset, size_t length) { + if (this->endianness_ == LITTLE) { + while (length-- != 0) { + this->data_[offset++] = static_cast(value); + value >>= 8; + } + } else { + offset += length; + while (length-- != 0) { + this->data_[--offset] = static_cast(value); + value >>= 8; + } + } + } + + void put_uint32_(uint32_t value, size_t offset, size_t length) { + if (this->endianness_ == LITTLE) { + while (length-- != 0) { + this->data_[offset++] = static_cast(value); + value >>= 8; + } + } else { + offset += length; + while (length-- != 0) { + this->data_[--offset] = static_cast(value); + value >>= 8; + } + } + } + ByteBuffer(std::vector const &data) : data_(data), limit_(data.size()) {} + + std::vector data_; + Endian endianness_{LITTLE}; + size_t position_{0}; + size_t mark_{0}; + size_t limit_{0}; +}; + +} // namespace bytebuffer +} // namespace esphome diff --git a/esphome/components/ch422g/__init__.py b/esphome/components/ch422g/__init__.py index cf8b5f65d3..6a7bace0a2 100644 --- a/esphome/components/ch422g/__init__.py +++ b/esphome/components/ch422g/__init__.py @@ -1,18 +1,20 @@ from esphome import pins import esphome.codegen as cg from esphome.components import i2c +from esphome.components.i2c import I2CBus import esphome.config_validation as cv from esphome.const import ( + CONF_I2C_ID, CONF_ID, CONF_INPUT, CONF_INVERTED, CONF_MODE, CONF_NUMBER, + CONF_OPEN_DRAIN, CONF_OUTPUT, - CONF_RESTORE_VALUE, ) -CODEOWNERS = ["@jesterret"] +CODEOWNERS = ["@jesterret", "@clydebarrow"] DEPENDENCIES = ["i2c"] MULTI_CONF = True ch422g_ns = cg.esphome_ns.namespace("ch422g") @@ -23,29 +25,36 @@ CH422GGPIOPin = ch422g_ns.class_( ) 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)) -) + +# Note that no address is configurable - each register in the CH422G has a dedicated i2c address +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_ID): cv.declare_id(CH422GComponent), + cv.GenerateID(CONF_I2C_ID): cv.use_id(I2CBus), + } +).extend(cv.COMPONENT_SCHEMA) async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) - cg.add(var.set_restore_value(config[CONF_RESTORE_VALUE])) await cg.register_component(var, config) - await i2c.register_i2c_device(var, config) + # Can't use register_i2c_device because there is no CONF_ADDRESS + parent = await cg.get_variable(config[CONF_I2C_ID]) + cg.add(var.set_i2c_bus(parent)) + + +# This is used as a final validation step so that modes have been fully transformed. +def pin_mode_check(pin_config, _): + if pin_config[CONF_MODE][CONF_INPUT] and pin_config[CONF_NUMBER] >= 8: + raise cv.Invalid("CH422G only supports input on pins 0-7") + if pin_config[CONF_MODE][CONF_OPEN_DRAIN] and pin_config[CONF_NUMBER] < 8: + raise cv.Invalid("CH422G only supports open drain output on pins 8-11") CH422G_PIN_SCHEMA = pins.gpio_base_schema( CH422GGPIOPin, - cv.int_range(min=0, max=7), - modes=[CONF_INPUT, CONF_OUTPUT], + cv.int_range(min=0, max=11), + modes=[CONF_INPUT, CONF_OUTPUT, CONF_OPEN_DRAIN], ).extend( { cv.Required(CONF_CH422G): cv.use_id(CH422GComponent), @@ -53,7 +62,7 @@ CH422G_PIN_SCHEMA = pins.gpio_base_schema( ) -@pins.PIN_SCHEMA_REGISTRY.register(CONF_CH422G, CH422G_PIN_SCHEMA) +@pins.PIN_SCHEMA_REGISTRY.register(CONF_CH422G, CH422G_PIN_SCHEMA, pin_mode_check) async def ch422g_pin_to_code(config): var = cg.new_Pvariable(config[CONF_ID]) parent = await cg.get_variable(config[CONF_CH422G]) diff --git a/esphome/components/ch422g/ch422g.cpp b/esphome/components/ch422g/ch422g.cpp index 25038991ed..0db179d99e 100644 --- a/esphome/components/ch422g/ch422g.cpp +++ b/esphome/components/ch422g/ch422g.cpp @@ -4,33 +4,33 @@ 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 uint8_t CH422G_REG_MODE = 0x24; +static const uint8_t CH422G_MODE_OUTPUT = 0x01; // enables output mode on 0-7 +static const uint8_t CH422G_MODE_OPEN_DRAIN = 0x04; // enables open drain mode on 8-11 +static const uint8_t CH422G_REG_IN = 0x26; // read reg for input bits +static const uint8_t CH422G_REG_OUT = 0x38; // write reg for output bits 0-7 +static const uint8_t CH422G_REG_OUT_UPPER = 0x23; // write reg for output bits 8-11 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_()) { + // set outputs before mode + this->write_outputs_(); + // Set mode and check for errors + if (!this->set_mode_(this->mode_value_) || !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()); + ESP_LOGCONFIG(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; + this->pin_read_flags_ = 0x00; } void CH422GComponent::dump_config() { @@ -41,82 +41,99 @@ void CH422GComponent::dump_config() { } } -// ch422g doesn't have any flag support (needs docs?) -void CH422GComponent::pin_mode(uint8_t pin, gpio::Flags flags) {} +void CH422GComponent::pin_mode(uint8_t pin, gpio::Flags flags) { + if (pin < 8) { + if (flags & gpio::FLAG_OUTPUT) { + this->mode_value_ |= CH422G_MODE_OUTPUT; + } + } else { + if (flags & gpio::FLAG_OPEN_DRAIN) { + this->mode_value_ |= CH422G_MODE_OPEN_DRAIN; + } + } +} bool CH422GComponent::digital_read(uint8_t pin) { - if (this->pin_read_cache_ == 0 || this->pin_read_cache_ & (1 << pin)) { + if (this->pin_read_flags_ == 0 || this->pin_read_flags_ & (1 << pin)) { // Read values on first access or in case it's being read again in the same loop this->read_inputs_(); } - this->pin_read_cache_ |= (1 << pin); - return this->state_mask_ & (1 << pin); + this->pin_read_flags_ |= (1 << pin); + return (this->input_bits_ & (1 << pin)) != 0; } void CH422GComponent::digital_write(uint8_t pin, bool value) { if (value) { - this->write_output_(this->state_mask_ | (1 << pin)); + this->output_bits_ |= (1 << pin); } else { - this->write_output_(this->state_mask_ & ~(1 << pin)); + this->output_bits_ &= ~(1 << pin); } + this->write_outputs_(); } 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 result; + // reading inputs requires the chip to be in input mode, possibly temporarily. + if (this->mode_value_ & CH422G_MODE_OUTPUT) { + this->set_mode_(this->mode_value_ & ~CH422G_MODE_OUTPUT); + result = this->read_reg_(CH422G_REG_IN); + this->set_mode_(this->mode_value_); + } else { + result = this->read_reg_(CH422G_REG_IN); } - - 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->input_bits_ = result; 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()); +// Write a register. Can't use the standard write_byte() method because there is no single pre-configured i2c address. +bool CH422GComponent::write_reg_(uint8_t reg, uint8_t value) { + auto err = this->bus_->write(reg, &value, 1); + if (err != i2c::ERROR_OK) { + this->status_set_warning(str_sprintf("write failed for register 0x%X, error %d", reg, err).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; } +uint8_t CH422GComponent::read_reg_(uint8_t reg) { + uint8_t value; + auto err = this->bus_->read(reg, &value, 1); + if (err != i2c::ERROR_OK) { + this->status_set_warning(str_sprintf("read failed for register 0x%X, error %d", reg, err).c_str()); + return 0; + } + this->status_clear_warning(); + return value; +} + +bool CH422GComponent::set_mode_(uint8_t mode) { return this->write_reg_(CH422G_REG_MODE, mode); } + +bool CH422GComponent::write_outputs_() { + return this->write_reg_(CH422G_REG_OUT, static_cast(this->output_bits_)) && + this->write_reg_(CH422G_REG_OUT_UPPER, static_cast(this->output_bits_ >> 8)); +} + 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_; } +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_); } +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_); } +void CH422GGPIOPin::set_flags(gpio::Flags flags) { + flags_ = flags; + this->parent_->pin_mode(this->pin_, flags); +} } // namespace ch422g } // namespace esphome diff --git a/esphome/components/ch422g/ch422g.h b/esphome/components/ch422g/ch422g.h index 781df65437..30780e09ad 100644 --- a/esphome/components/ch422g/ch422g.h +++ b/esphome/components/ch422g/ch422g.h @@ -23,32 +23,30 @@ class CH422GComponent : public Component, public i2c::I2CDevice { 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 write_reg_(uint8_t reg, uint8_t value); + uint8_t read_reg_(uint8_t reg); + bool set_mode_(uint8_t mode); bool read_inputs_(); - - bool write_output_(uint8_t value); + bool write_outputs_(); /// The mask to write as output state - 1 means HIGH, 0 means LOW - uint8_t state_mask_{0x00}; + uint16_t output_bits_{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}; + uint8_t pin_read_flags_ = {0x00}; + /// Copy of last read values + uint8_t input_bits_ = {0x00}; + /// Copy of the mode value + uint8_t mode_value_{}; }; -/// Helper class to expose a CH422G pin as an internal input GPIO pin. +/// Helper class to expose a CH422G pin as a GPIO pin. class CH422GGPIOPin : public GPIOPin { public: - void setup() override; + void setup() override{}; void pin_mode(gpio::Flags flags) override; bool digital_read() override; void digital_write(bool value) override; @@ -57,13 +55,13 @@ class CH422GGPIOPin : public GPIOPin { 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; } + void set_flags(gpio::Flags flags); protected: - CH422GComponent *parent_; - uint8_t pin_; - bool inverted_; - gpio::Flags flags_; + CH422GComponent *parent_{}; + uint8_t pin_{}; + bool inverted_{}; + gpio::Flags flags_{}; }; } // namespace ch422g diff --git a/esphome/components/climate/__init__.py b/esphome/components/climate/__init__.py index c7e4ce7745..b302e2ab4e 100644 --- a/esphome/components/climate/__init__.py +++ b/esphome/components/climate/__init__.py @@ -43,7 +43,7 @@ from esphome.const import ( CONF_TEMPERATURE_STEP, CONF_TRIGGER_ID, CONF_VISUAL, - CONF_WEB_SERVER_ID, + CONF_WEB_SERVER, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_helpers import setup_entity @@ -408,9 +408,8 @@ 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) + if web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(var, web_server_config) async def register_climate(var, config): diff --git a/esphome/components/cover/__init__.py b/esphome/components/cover/__init__.py index d25dd91148..e7e3ac3bb0 100644 --- a/esphome/components/cover/__init__.py +++ b/esphome/components/cover/__init__.py @@ -17,7 +17,7 @@ from esphome.const import ( CONF_TILT_COMMAND_TOPIC, CONF_TILT_STATE_TOPIC, CONF_TRIGGER_ID, - CONF_WEB_SERVER_ID, + CONF_WEB_SERVER, DEVICE_CLASS_AWNING, DEVICE_CLASS_BLIND, DEVICE_CLASS_CURTAIN, @@ -137,10 +137,6 @@ 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) @@ -156,6 +152,9 @@ async def setup_cover_core_(var, config): if (tilt_command_topic := config.get(CONF_TILT_COMMAND_TOPIC)) is not None: cg.add(mqtt_.set_custom_tilt_command_topic(tilt_command_topic)) + if web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(var, web_server_config) + async def register_cover(var, config): if not CORE.has_id(config[CONF_ID]): diff --git a/esphome/components/cse7766/cse7766.cpp b/esphome/components/cse7766/cse7766.cpp index f1420aa127..48240464b3 100644 --- a/esphome/components/cse7766/cse7766.cpp +++ b/esphome/components/cse7766/cse7766.cpp @@ -147,6 +147,7 @@ void CSE7766Component::parse_data_() { float power = 0.0f; if (power_cycle_exceeds_range) { // Datasheet: power cycle exceeding range means active power is 0 + have_power = true; if (this->power_sensor_ != nullptr) { this->power_sensor_->publish_state(0.0f); } @@ -178,6 +179,15 @@ void CSE7766Component::parse_data_() { if (this->apparent_power_sensor_ != nullptr) { this->apparent_power_sensor_->publish_state(apparent_power); } + if (have_power && this->reactive_power_sensor_ != nullptr) { + const float reactive_power = apparent_power - power; + if (reactive_power < 0.0f) { + ESP_LOGD(TAG, "Impossible reactive power: %.4f is negative", reactive_power); + this->reactive_power_sensor_->publish_state(0.0f); + } else { + this->reactive_power_sensor_->publish_state(reactive_power); + } + } if (this->power_factor_sensor_ != nullptr && (have_power || power_cycle_exceeds_range)) { float pf = NAN; if (apparent_power > 0) { @@ -232,8 +242,9 @@ void CSE7766Component::dump_config() { LOG_SENSOR(" ", "Power", this->power_sensor_); LOG_SENSOR(" ", "Energy", this->energy_sensor_); LOG_SENSOR(" ", "Apparent Power", this->apparent_power_sensor_); + LOG_SENSOR(" ", "Reactive Power", this->reactive_power_sensor_); LOG_SENSOR(" ", "Power Factor", this->power_factor_sensor_); - this->check_uart_settings(4800); + this->check_uart_settings(4800, 1, uart::UART_CONFIG_PARITY_EVEN); } } // namespace cse7766 diff --git a/esphome/components/cse7766/cse7766.h b/esphome/components/cse7766/cse7766.h index 0b724d6bbb..5d89b3b75b 100644 --- a/esphome/components/cse7766/cse7766.h +++ b/esphome/components/cse7766/cse7766.h @@ -16,6 +16,9 @@ class CSE7766Component : public Component, public uart::UARTDevice { void set_apparent_power_sensor(sensor::Sensor *apparent_power_sensor) { apparent_power_sensor_ = apparent_power_sensor; } + void set_reactive_power_sensor(sensor::Sensor *reactive_power_sensor) { + reactive_power_sensor_ = reactive_power_sensor; + } void set_power_factor_sensor(sensor::Sensor *power_factor_sensor) { power_factor_sensor_ = power_factor_sensor; } void loop() override; @@ -35,6 +38,7 @@ class CSE7766Component : public Component, public uart::UARTDevice { sensor::Sensor *power_sensor_{nullptr}; sensor::Sensor *energy_sensor_{nullptr}; sensor::Sensor *apparent_power_sensor_{nullptr}; + sensor::Sensor *reactive_power_sensor_{nullptr}; sensor::Sensor *power_factor_sensor_{nullptr}; uint32_t cf_pulses_total_{0}; uint16_t cf_pulses_last_{0}; diff --git a/esphome/components/cse7766/sensor.py b/esphome/components/cse7766/sensor.py index b64dcf7de3..b5b11a661e 100644 --- a/esphome/components/cse7766/sensor.py +++ b/esphome/components/cse7766/sensor.py @@ -8,18 +8,21 @@ from esphome.const import ( CONF_ID, CONF_POWER, CONF_POWER_FACTOR, + CONF_REACTIVE_POWER, CONF_VOLTAGE, DEVICE_CLASS_APPARENT_POWER, DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, DEVICE_CLASS_POWER, DEVICE_CLASS_POWER_FACTOR, + DEVICE_CLASS_REACTIVE_POWER, DEVICE_CLASS_VOLTAGE, STATE_CLASS_MEASUREMENT, STATE_CLASS_TOTAL_INCREASING, UNIT_AMPERE, UNIT_VOLT, UNIT_VOLT_AMPS, + UNIT_VOLT_AMPS_REACTIVE, UNIT_WATT, UNIT_WATT_HOURS, ) @@ -62,6 +65,12 @@ CONFIG_SCHEMA = cv.Schema( device_class=DEVICE_CLASS_APPARENT_POWER, state_class=STATE_CLASS_MEASUREMENT, ), + cv.Optional(CONF_REACTIVE_POWER): sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT_AMPS_REACTIVE, + accuracy_decimals=1, + device_class=DEVICE_CLASS_REACTIVE_POWER, + state_class=STATE_CLASS_MEASUREMENT, + ), cv.Optional(CONF_POWER_FACTOR): sensor.sensor_schema( accuracy_decimals=2, device_class=DEVICE_CLASS_POWER_FACTOR, @@ -70,7 +79,7 @@ CONFIG_SCHEMA = cv.Schema( } ).extend(uart.UART_DEVICE_SCHEMA) FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( - "cse7766", baud_rate=4800, require_rx=True + "cse7766", baud_rate=4800, parity="EVEN", require_rx=True ) @@ -94,6 +103,9 @@ async def to_code(config): if apparent_power_config := config.get(CONF_APPARENT_POWER): sens = await sensor.new_sensor(apparent_power_config) cg.add(var.set_apparent_power_sensor(sens)) + if reactive_power_config := config.get(CONF_REACTIVE_POWER): + sens = await sensor.new_sensor(reactive_power_config) + cg.add(var.set_reactive_power_sensor(sens)) if power_factor_config := config.get(CONF_POWER_FACTOR): sens = await sensor.new_sensor(power_factor_config) cg.add(var.set_power_factor_sensor(sens)) diff --git a/esphome/components/cst816/touchscreen/__init__.py b/esphome/components/cst816/touchscreen/__init__.py index a3603ef575..288ca17593 100644 --- a/esphome/components/cst816/touchscreen/__init__.py +++ b/esphome/components/cst816/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, CONF_RESET_PIN -from .. import cst816_ns +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_INTERRUPT_PIN, CONF_RESET_PIN +from .. import cst816_ns CST816Touchscreen = cst816_ns.class_( "CST816Touchscreen", @@ -14,11 +13,14 @@ CST816Touchscreen = cst816_ns.class_( ) CST816ButtonListener = cst816_ns.class_("CST816ButtonListener") + +CONF_SKIP_PROBE = "skip_probe" CONFIG_SCHEMA = touchscreen.TOUCHSCREEN_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(CST816Touchscreen), cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema, cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_SKIP_PROBE, default=False): cv.boolean, } ).extend(i2c.i2c_device_schema(0x15)) @@ -28,6 +30,7 @@ async def to_code(config): await touchscreen.register_touchscreen(var, config) await i2c.register_i2c_device(var, config) + cg.add(var.set_skip_probe(config[CONF_SKIP_PROBE])) 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): diff --git a/esphome/components/cst816/touchscreen/cst816_touchscreen.cpp b/esphome/components/cst816/touchscreen/cst816_touchscreen.cpp index 9e59810c7e..7dcb130e20 100644 --- a/esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +++ b/esphome/components/cst816/touchscreen/cst816_touchscreen.cpp @@ -8,32 +8,33 @@ void CST816Touchscreen::continue_setup_() { this->interrupt_pin_->setup(); this->attach_interrupt_(this->interrupt_pin_, gpio::INTERRUPT_FALLING_EDGE); } - if (!this->read_byte(REG_CHIP_ID, &this->chip_id_)) { + if (this->read_byte(REG_CHIP_ID, &this->chip_id_)) { + switch (this->chip_id_) { + case CST820_CHIP_ID: + case CST826_CHIP_ID: + case CST716_CHIP_ID: + case CST816S_CHIP_ID: + case CST816D_CHIP_ID: + case CST816T_CHIP_ID: + break; + default: + this->mark_failed(); + this->status_set_error(str_sprintf("Unknown chip ID 0x%02X", this->chip_id_).c_str()); + return; + } + this->write_byte(REG_IRQ_CTL, IRQ_EN_MOTION); + } else if (!this->skip_probe_) { + this->status_set_error("Failed to read chip id"); this->mark_failed(); - esph_log_e(TAG, "Failed to read chip id"); return; } - switch (this->chip_id_) { - case CST820_CHIP_ID: - case CST826_CHIP_ID: - case CST716_CHIP_ID: - case CST816S_CHIP_ID: - case CST816D_CHIP_ID: - case CST816T_CHIP_ID: - break; - default: - this->mark_failed(); - esph_log_e(TAG, "Unknown chip ID 0x%02X", this->chip_id_); - return; - } - this->write_byte(REG_IRQ_CTL, IRQ_EN_MOTION); 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, "CST816 Touchscreen setup complete"); + ESP_LOGCONFIG(TAG, "CST816 Touchscreen setup complete"); } void CST816Touchscreen::update_button_state_(bool state) { @@ -45,7 +46,7 @@ void CST816Touchscreen::update_button_state_(bool state) { } void CST816Touchscreen::setup() { - esph_log_config(TAG, "Setting up CST816 Touchscreen..."); + ESP_LOGCONFIG(TAG, "Setting up CST816 Touchscreen..."); if (this->reset_pin_ != nullptr) { this->reset_pin_->setup(); this->reset_pin_->digital_write(true); @@ -73,7 +74,7 @@ void CST816Touchscreen::update_touches() { uint16_t x = encode_uint16(data[REG_XPOS_HIGH] & 0xF, data[REG_XPOS_LOW]); uint16_t y = encode_uint16(data[REG_YPOS_HIGH] & 0xF, data[REG_YPOS_LOW]); - esph_log_v(TAG, "Read touch %d/%d", x, y); + ESP_LOGV(TAG, "Read touch %d/%d", x, y); if (x >= this->x_raw_max_) { this->update_button_state_(true); } else { diff --git a/esphome/components/cst816/touchscreen/cst816_touchscreen.h b/esphome/components/cst816/touchscreen/cst816_touchscreen.h index 24e664e7ee..dc00e675ba 100644 --- a/esphome/components/cst816/touchscreen/cst816_touchscreen.h +++ b/esphome/components/cst816/touchscreen/cst816_touchscreen.h @@ -45,6 +45,7 @@ class CST816Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; } void set_reset_pin(GPIOPin *pin) { this->reset_pin_ = pin; } + void set_skip_probe(bool skip_probe) { this->skip_probe_ = skip_probe; } protected: void continue_setup_(); @@ -53,6 +54,7 @@ class CST816Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice InternalGPIOPin *interrupt_pin_{}; GPIOPin *reset_pin_{}; uint8_t chip_id_{}; + bool skip_probe_{}; // if set, do not expect to be able to probe the controller on the i2c bus. std::vector button_listeners_; bool button_touched_{}; }; diff --git a/esphome/components/datetime/__init__.py b/esphome/components/datetime/__init__.py index 5429121d56..7edf527e01 100644 --- a/esphome/components/datetime/__init__.py +++ b/esphome/components/datetime/__init__.py @@ -18,7 +18,7 @@ from esphome.const import ( CONF_TIME_ID, CONF_TRIGGER_ID, CONF_TYPE, - CONF_WEB_SERVER_ID, + CONF_WEB_SERVER, CONF_YEAR, ) from esphome.core import CORE, coroutine_with_priority @@ -26,7 +26,6 @@ from esphome.cpp_generator import MockObjClass from esphome.cpp_helpers import setup_entity CODEOWNERS = ["@rfdarter", "@jesserockz"] -DEPENDENCIES = ["time"] IS_PLATFORM_COMPONENT = True @@ -62,20 +61,28 @@ DATETIME_MODES = [ ] -_DATETIME_SCHEMA = ( - cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) - .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) - .extend( +def _validate_time_present(config): + config = config.copy() + if CONF_ON_TIME in config and CONF_TIME_ID not in config: + time_id = cv.use_id(time.RealTimeClock)(None) + config[CONF_TIME_ID] = time_id + return config + + +_DATETIME_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend( + web_server.WEBSERVER_SORTING_SCHEMA, + cv.MQTT_COMMAND_COMPONENT_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), + cv.Optional(CONF_TIME_ID): cv.use_id(time.RealTimeClock), } - ) -) + ), +).add_extra(_validate_time_present) def date_schema(class_: MockObjClass) -> cv.Schema: @@ -131,15 +138,15 @@ 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) + if web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(var, web_server_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) - rtc = await cg.get_variable(config[CONF_TIME_ID]) - cg.add(var.set_rtc(rtc)) + if CONF_TIME_ID in config: + rtc = await cg.get_variable(config[CONF_TIME_ID]) + cg.add(var.set_rtc(rtc)) for conf in config.get(CONF_ON_TIME, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID]) diff --git a/esphome/components/datetime/datetime_base.h b/esphome/components/datetime/datetime_base.h index c8240390e3..dea34e6110 100644 --- a/esphome/components/datetime/datetime_base.h +++ b/esphome/components/datetime/datetime_base.h @@ -4,8 +4,9 @@ #include "esphome/core/component.h" #include "esphome/core/entity_base.h" #include "esphome/core/time.h" - +#ifdef USE_TIME #include "esphome/components/time/real_time_clock.h" +#endif namespace esphome { namespace datetime { @@ -19,23 +20,29 @@ class DateTimeBase : public EntityBase { void add_on_state_callback(std::function &&callback) { this->state_callback_.add(std::move(callback)); } +#ifdef USE_TIME void set_rtc(time::RealTimeClock *rtc) { this->rtc_ = rtc; } time::RealTimeClock *get_rtc() const { return this->rtc_; } +#endif protected: CallbackManager state_callback_; +#ifdef USE_TIME time::RealTimeClock *rtc_; +#endif bool has_state_{false}; }; +#ifdef USE_TIME class DateTimeStateTrigger : public Trigger { public: explicit DateTimeStateTrigger(DateTimeBase *parent) { parent->add_on_state_callback([this, parent]() { this->trigger(parent->state_as_esptime()); }); } }; +#endif } // namespace datetime } // namespace esphome diff --git a/esphome/components/datetime/datetime_entity.cpp b/esphome/components/datetime/datetime_entity.cpp index 9a61d341e4..f215b7acb5 100644 --- a/esphome/components/datetime/datetime_entity.cpp +++ b/esphome/components/datetime/datetime_entity.cpp @@ -192,6 +192,7 @@ void DateTimeEntityRestoreState::apply(DateTimeEntity *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 @@ -245,6 +246,7 @@ bool OnDateTimeTrigger::matches_(const ESPTime &time) const { time.day_of_month == this->parent_->day && time.hour == this->parent_->hour && time.minute == this->parent_->minute && time.second == this->parent_->second; } +#endif } // namespace datetime } // namespace esphome diff --git a/esphome/components/datetime/datetime_entity.h b/esphome/components/datetime/datetime_entity.h index d541fa96b1..27db84cf7e 100644 --- a/esphome/components/datetime/datetime_entity.h +++ b/esphome/components/datetime/datetime_entity.h @@ -134,6 +134,7 @@ template class DateTimeSetAction : public Action, public } }; +#ifdef USE_TIME class OnDateTimeTrigger : public Trigger<>, public Component, public Parented { public: void loop() override; @@ -143,6 +144,7 @@ class OnDateTimeTrigger : public Trigger<>, public Component, public Parented last_check_; }; +#endif } // namespace datetime } // namespace esphome diff --git a/esphome/components/datetime/time_entity.cpp b/esphome/components/datetime/time_entity.cpp index ea5e6684d0..db0094ae01 100644 --- a/esphome/components/datetime/time_entity.cpp +++ b/esphome/components/datetime/time_entity.cpp @@ -94,6 +94,7 @@ 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 @@ -145,6 +146,7 @@ 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 diff --git a/esphome/components/datetime/time_entity.h b/esphome/components/datetime/time_entity.h index 62e593d28a..f7e0a7ddd9 100644 --- a/esphome/components/datetime/time_entity.h +++ b/esphome/components/datetime/time_entity.h @@ -113,6 +113,7 @@ template class TimeSetAction : public Action, public Pare } }; +#ifdef USE_TIME class OnTimeTrigger : public Trigger<>, public Component, public Parented { public: void loop() override; @@ -122,6 +123,7 @@ class OnTimeTrigger : public Trigger<>, public Component, public Parented last_check_; }; +#endif } // namespace datetime } // namespace esphome diff --git a/esphome/components/debug/debug_esp32.cpp b/esphome/components/debug/debug_esp32.cpp index 34aea9e26b..cb4330f422 100644 --- a/esphome/components/debug/debug_esp32.cpp +++ b/esphome/components/debug/debug_esp32.cpp @@ -36,7 +36,8 @@ std::string DebugComponent::get_reset_reason_() { 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) +#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || \ + defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C6) case RTC_SW_SYS_RESET: #endif reset_reason = "Software Reset Digital Core"; @@ -72,14 +73,16 @@ std::string DebugComponent::get_reset_reason_() { 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) +#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || \ + defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C6) 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) +#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || \ + defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C6) case RTC_SW_CPU_RESET: #endif reset_reason = "Software Reset CPU"; @@ -98,27 +101,32 @@ std::string DebugComponent::get_reset_reason_() { 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) +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || \ + defined(USE_ESP32_VARIANT_ESP32C6) 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) +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) + case GLITCH_RTC_RESET: + reset_reason = "Glitch Reset Digital Core And RTC Module"; + break; +#endif +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C6) 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; +#endif +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3) case POWER_GLITCH_RESET: reset_reason = "Power Glitch Reset Digital Core And RTC Module"; break; diff --git a/esphome/components/display/display.cpp b/esphome/components/display/display.cpp index 63c74e09ca..145a4f5278 100644 --- a/esphome/components/display/display.cpp +++ b/esphome/components/display/display.cpp @@ -156,6 +156,148 @@ void Display::filled_circle(int center_x, int center_y, int radius, Color color) } } while (dx <= 0); } +void Display::filled_ring(int center_x, int center_y, int radius1, int radius2, Color color) { + int rmax = radius1 > radius2 ? radius1 : radius2; + int rmin = radius1 < radius2 ? radius1 : radius2; + int dxmax = -int32_t(rmax), dxmin = -int32_t(rmin); + int dymax = 0, dymin = 0; + int errmax = 2 - 2 * rmax, errmin = 2 - 2 * rmin; + int e2max, e2min; + do { + // 8 dots for borders + this->draw_pixel_at(center_x - dxmax, center_y + dymax, color); + this->draw_pixel_at(center_x + dxmax, center_y + dymax, color); + this->draw_pixel_at(center_x - dxmin, center_y + dymin, color); + this->draw_pixel_at(center_x + dxmin, center_y + dymin, color); + this->draw_pixel_at(center_x + dxmax, center_y - dymax, color); + this->draw_pixel_at(center_x - dxmax, center_y - dymax, color); + this->draw_pixel_at(center_x + dxmin, center_y - dymin, color); + this->draw_pixel_at(center_x - dxmin, center_y - dymin, color); + if (dymin < rmin) { + // two parts - four lines + int hline_width = -(dxmax - dxmin) + 1; + this->horizontal_line(center_x + dxmax, center_y + dymax, hline_width, color); + this->horizontal_line(center_x - dxmin, center_y + dymax, hline_width, color); + this->horizontal_line(center_x + dxmax, center_y - dymax, hline_width, color); + this->horizontal_line(center_x - dxmin, center_y - dymax, hline_width, color); + } else { + // one part - top and bottom + int hline_width = 2 * (-dxmax) + 1; + this->horizontal_line(center_x + dxmax, center_y + dymax, hline_width, color); + this->horizontal_line(center_x + dxmax, center_y - dymax, hline_width, color); + } + e2max = errmax; + // tune external + if (e2max < dymax) { + errmax += ++dymax * 2 + 1; + if (-dxmax == dymax && e2max <= dxmax) { + e2max = 0; + } + } + if (e2max > dxmax) { + errmax += ++dxmax * 2 + 1; + } + // tune internal + while (dymin < dymax && dymin < rmin) { + e2min = errmin; + if (e2min < dymin) { + errmin += ++dymin * 2 + 1; + if (-dxmin == dymin && e2min <= dxmin) { + e2min = 0; + } + } + if (e2min > dxmin) { + errmin += ++dxmin * 2 + 1; + } + } + } while (dxmax <= 0); +} +void Display::filled_gauge(int center_x, int center_y, int radius1, int radius2, int progress, Color color) { + int rmax = radius1 > radius2 ? radius1 : radius2; + int rmin = radius1 < radius2 ? radius1 : radius2; + int dxmax = -int32_t(rmax), dxmin = -int32_t(rmin), upd_dxmax, upd_dxmin; + int dymax = 0, dymin = 0; + int errmax = 2 - 2 * rmax, errmin = 2 - 2 * rmin; + int e2max, e2min; + progress = std::max(0, std::min(progress, 100)); // 0..100 + int draw_progress = progress > 50 ? (100 - progress) : progress; + float tan_a = (progress == 50) ? 65535 : tan(float(draw_progress) * M_PI / 100); // slope + + do { + // outer dots + this->draw_pixel_at(center_x + dxmax, center_y - dymax, color); + this->draw_pixel_at(center_x - dxmax, center_y - dymax, color); + if (dymin < rmin) { // side parts + int lhline_width = -(dxmax - dxmin) + 1; + if (progress >= 50) { + if (float(dymax) < float(-dxmax) * tan_a) { + upd_dxmax = ceil(float(dymax) / tan_a); + } else { + upd_dxmax = -dxmax; + } + this->horizontal_line(center_x + dxmax, center_y - dymax, lhline_width, color); // left + if (!dymax) + this->horizontal_line(center_x - dxmin, center_y, lhline_width, color); // right horizontal border + if (upd_dxmax > -dxmin) { // right + int rhline_width = (upd_dxmax + dxmin) + 1; + this->horizontal_line(center_x - dxmin, center_y - dymax, + rhline_width > lhline_width ? lhline_width : rhline_width, color); + } + } else { + if (float(dymin) > float(-dxmin) * tan_a) { + upd_dxmin = ceil(float(dymin) / tan_a); + } else { + upd_dxmin = -dxmin; + } + lhline_width = -(dxmax + upd_dxmin) + 1; + if (!dymax) + this->horizontal_line(center_x - dxmin, center_y, lhline_width, color); // right horizontal border + if (lhline_width > 0) + this->horizontal_line(center_x + dxmax, center_y - dymax, lhline_width, color); + } + } else { // top part + int hline_width = 2 * (-dxmax) + 1; + if (progress >= 50) { + if (dymax < float(-dxmax) * tan_a) { + upd_dxmax = ceil(float(dymax) / tan_a); + hline_width = -dxmax + upd_dxmax + 1; + } + } else { + if (dymax < float(-dxmax) * tan_a) { + upd_dxmax = ceil(float(dymax) / tan_a); + hline_width = -dxmax - upd_dxmax + 1; + } else + hline_width = 0; + } + if (hline_width > 0) + this->horizontal_line(center_x + dxmax, center_y - dymax, hline_width, color); + } + e2max = errmax; + if (e2max < dymax) { + errmax += ++dymax * 2 + 1; + if (-dxmax == dymax && e2max <= dxmax) { + e2max = 0; + } + } + if (e2max > dxmax) { + errmax += ++dxmax * 2 + 1; + } + while (dymin <= dymax && dymin <= rmin && dxmin <= 0) { + this->draw_pixel_at(center_x + dxmin, center_y - dymin, color); + this->draw_pixel_at(center_x - dxmin, center_y - dymin, color); + e2min = errmin; + if (e2min < dymin) { + errmin += ++dymin * 2 + 1; + if (-dxmin == dymin && e2min <= dxmin) { + e2min = 0; + } + } + if (e2min > dxmin) { + errmin += ++dxmin * 2 + 1; + } + } + } while (dxmax <= 0); +} void HOT Display::triangle(int x1, int y1, int x2, int y2, int x3, int y3, Color color) { this->line(x1, y1, x2, y2, color); this->line(x1, y1, x3, y3, color); diff --git a/esphome/components/display/display.h b/esphome/components/display/display.h index 34feafea6e..54e897cdec 100644 --- a/esphome/components/display/display.h +++ b/esphome/components/display/display.h @@ -285,6 +285,13 @@ class Display : public PollingComponent { /// Fill a circle centered around [center_x,center_y] with the radius radius with the given color. void filled_circle(int center_x, int center_y, int radius, Color color = COLOR_ON); + /// Fill a ring centered around [center_x,center_y] between two circles with the radius1 and radius2 with the given + /// color. + void filled_ring(int center_x, int center_y, int radius1, int radius2, Color color = COLOR_ON); + /// Fill a half-ring "gauge" centered around [center_x,center_y] between two circles with the radius1 and radius2 + /// with he given color and filled up to 'progress' percent + void filled_gauge(int center_x, int center_y, int radius1, int radius2, int progress, Color color = COLOR_ON); + /// Draw the outline of a triangle contained between the points [x1,y1], [x2,y2] and [x3,y3] with the given color. void triangle(int x1, int y1, int x2, int y2, int x3, int y3, Color color = COLOR_ON); 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( diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index b630c7638e..61fbb53e3a 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -13,6 +13,7 @@ from esphome.const import ( CONF_COMPONENTS, CONF_ESPHOME, CONF_FRAMEWORK, + CONF_IGNORE_EFUSE_CUSTOM_MAC, CONF_IGNORE_EFUSE_MAC_CRC, CONF_NAME, CONF_PATH, @@ -52,6 +53,7 @@ from .const import ( # noqa KEY_SDKCONFIG_OPTIONS, KEY_SUBMODULES, KEY_VARIANT, + VARIANT_ESP32, VARIANT_FRIENDLY, VARIANTS, ) @@ -239,7 +241,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 @@ -375,6 +377,15 @@ def final_validate(config): f"Please specify {CONF_FLASH_SIZE} within esp32 configuration only" ) + if ( + config[CONF_VARIANT] != VARIANT_ESP32 + and CONF_ADVANCED in (conf_fw := config[CONF_FRAMEWORK]) + and CONF_IGNORE_EFUSE_MAC_CRC in conf_fw[CONF_ADVANCED] + ): + raise cv.Invalid( + f"{CONF_IGNORE_EFUSE_MAC_CRC} is not supported on {config[CONF_VARIANT]}" + ) + return config @@ -384,6 +395,13 @@ ARDUINO_FRAMEWORK_SCHEMA = cv.All( cv.Optional(CONF_VERSION, default="recommended"): cv.string_strict, cv.Optional(CONF_SOURCE): cv.string_strict, cv.Optional(CONF_PLATFORM_VERSION): _parse_platform_version, + cv.Optional(CONF_ADVANCED, default={}): cv.Schema( + { + cv.Optional( + CONF_IGNORE_EFUSE_CUSTOM_MAC, default=False + ): cv.boolean, + } + ), } ), _arduino_check_versions, @@ -401,7 +419,10 @@ ESP_IDF_FRAMEWORK_SCHEMA = cv.All( }, cv.Optional(CONF_ADVANCED, default={}): cv.Schema( { - cv.Optional(CONF_IGNORE_EFUSE_MAC_CRC, default=False): cv.boolean, + cv.Optional( + CONF_IGNORE_EFUSE_CUSTOM_MAC, default=False + ): cv.boolean, + cv.Optional(CONF_IGNORE_EFUSE_MAC_CRC): cv.boolean, } ), cv.Optional(CONF_COMPONENTS, default=[]): cv.ensure_list( @@ -480,6 +501,9 @@ async def to_code(config): conf = config[CONF_FRAMEWORK] cg.add_platformio_option("platform", conf[CONF_PLATFORM_VERSION]) + if CONF_ADVANCED in conf and conf[CONF_ADVANCED][CONF_IGNORE_EFUSE_CUSTOM_MAC]: + cg.add_define("USE_ESP32_IGNORE_EFUSE_CUSTOM_MAC") + add_extra_script( "post", "post_build.py", @@ -526,8 +550,8 @@ async def to_code(config): for name, value in conf[CONF_SDKCONFIG_OPTIONS].items(): add_idf_sdkconfig_option(name, RawSdkconfigValue(value)) - if conf[CONF_ADVANCED][CONF_IGNORE_EFUSE_MAC_CRC]: - cg.add_define("USE_ESP32_IGNORE_EFUSE_MAC_CRC") + if conf[CONF_ADVANCED].get(CONF_IGNORE_EFUSE_MAC_CRC): + add_idf_sdkconfig_option("CONFIG_ESP_MAC_IGNORE_MAC_CRC_ERROR", True) if (framework_ver.major, framework_ver.minor) >= (4, 4): add_idf_sdkconfig_option( "CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE", False diff --git a/esphome/components/esp32/boards.py b/esphome/components/esp32/boards.py index 60abcd447c..02744ecb6f 100644 --- a/esphome/components/esp32/boards.py +++ b/esphome/components/esp32/boards.py @@ -103,6 +103,173 @@ ESP32_BOARD_PINS = { "LED": 13, "LED_BUILTIN": 13, }, + "adafruit_feather_esp32s3": { + "BUTTON": 0, + "A0": 18, + "A1": 17, + "A2": 16, + "A3": 15, + "A4": 14, + "A5": 8, + "SCK": 36, + "MOSI": 35, + "MISO": 37, + "RX": 38, + "TX": 39, + "SCL": 4, + "SDA": 3, + "NEOPIXEL": 33, + "PIN_NEOPIXEL": 33, + "NEOPIXEL_POWER": 21, + "I2C_POWER": 7, + "LED": 13, + "LED_BUILTIN": 13, + }, + "adafruit_feather_esp32s3_nopsram": { + "BUTTON": 0, + "A0": 18, + "A1": 17, + "A2": 16, + "A3": 15, + "A4": 14, + "A5": 8, + "SCK": 36, + "MOSI": 35, + "MISO": 37, + "RX": 38, + "TX": 39, + "SCL": 4, + "SDA": 3, + "NEOPIXEL": 33, + "PIN_NEOPIXEL": 33, + "NEOPIXEL_POWER": 21, + "I2C_POWER": 7, + "LED": 13, + "LED_BUILTIN": 13, + }, + "adafruit_feather_esp32s3_tft": { + "BUTTON": 0, + "A0": 18, + "A1": 17, + "A2": 16, + "A3": 15, + "A4": 14, + "A5": 8, + "SCK": 36, + "MOSI": 35, + "MISO": 37, + "RX": 2, + "TX": 1, + "SCL": 41, + "SDA": 42, + "NEOPIXEL": 33, + "PIN_NEOPIXEL": 33, + "NEOPIXEL_POWER": 34, + "TFT_I2C_POWER": 21, + "TFT_CS": 7, + "TFT_DC": 39, + "TFT_RESET": 40, + "TFT_BACKLIGHT": 45, + "LED": 13, + "LED_BUILTIN": 13, + }, + "adafruit_funhouse_esp32s2": { + "BUTTON_UP": 5, + "BUTTON_DOWN": 3, + "BUTTON_SELECT": 4, + "DOTSTAR_DATA": 14, + "DOTSTAR_CLOCK": 15, + "PIR_SENSE": 16, + "A0": 17, + "A1": 2, + "A2": 1, + "CAP6": 6, + "CAP7": 7, + "CAP8": 8, + "CAP9": 9, + "CAP10": 10, + "CAP11": 11, + "CAP12": 12, + "CAP13": 13, + "SPEAKER": 42, + "LED": 37, + "LIGHT": 18, + "TFT_MOSI": 35, + "TFT_SCK": 36, + "TFT_CS": 40, + "TFT_DC": 39, + "TFT_RESET": 41, + "TFT_BACKLIGHT": 21, + "RED_LED": 31, + "BUTTON": 0, + }, + "adafruit_itsybitsy_esp32": { + "A0": 25, + "A1": 26, + "A2": 4, + "A3": 38, + "A4": 37, + "A5": 36, + "SCK": 19, + "MOSI": 21, + "MISO": 22, + "SCL": 27, + "SDA": 15, + "TX": 20, + "RX": 8, + "NEOPIXEL": 0, + "PIN_NEOPIXEL": 0, + "NEOPIXEL_POWER": 2, + "BUTTON": 35, + }, + "adafruit_magtag29_esp32s2": { + "A1": 18, + "BUTTON_A": 15, + "BUTTON_B": 14, + "BUTTON_C": 12, + "BUTTON_D": 11, + "SDA": 33, + "SCL": 34, + "SPEAKER": 17, + "SPEAKER_ENABLE": 16, + "VOLTAGE_MONITOR": 4, + "ACCELEROMETER_INT": 9, + "ACCELEROMETER_INTERRUPT": 9, + "LIGHT": 3, + "NEOPIXEL": 1, + "PIN_NEOPIXEL": 1, + "NEOPIXEL_POWER": 21, + "EPD_BUSY": 5, + "EPD_RESET": 6, + "EPD_DC": 7, + "EPD_CS": 8, + "EPD_MOSI": 35, + "EPD_SCK": 36, + "EPD_MISO": 37, + "BUTTON": 0, + "LED": 13, + "LED_BUILTIN": 13, + }, + "adafruit_metro_esp32s2": { + "A0": 17, + "A1": 18, + "A2": 1, + "A3": 2, + "A4": 3, + "A5": 4, + "RX": 38, + "TX": 37, + "SCL": 34, + "SDA": 33, + "MISO": 37, + "SCK": 36, + "MOSI": 35, + "NEOPIXEL": 45, + "PIN_NEOPIXEL": 45, + "LED": 42, + "LED_BUILTIN": 42, + "BUTTON": 0, + }, "adafruit_qtpy_esp32c3": { "A0": 4, "A1": 3, @@ -141,6 +308,26 @@ ESP32_BOARD_PINS = { "BUTTON": 0, "SWITCH": 0, }, + "adafruit_qtpy_esp32s3_nopsram": { + "A0": 18, + "A1": 17, + "A2": 9, + "A3": 8, + "SDA": 7, + "SCL": 6, + "MOSI": 35, + "MISO": 37, + "SCK": 36, + "RX": 16, + "TX": 5, + "SDA1": 41, + "SCL1": 40, + "NEOPIXEL": 39, + "PIN_NEOPIXEL": 39, + "NEOPIXEL_POWER": 38, + "BUTTON": 0, + "SWITCH": 0, + }, "adafruit_qtpy_esp32": { "A0": 26, "A1": 25, @@ -1068,7 +1255,18 @@ ESP32_BOARD_PINS = { "_VBAT": 35, }, "wemosbat": {"LED": 16}, - "wesp32": {"MISO": 32, "SCL": 4, "SDA": 15}, + "wesp32": { + "MISO": 32, + "MOSI": 23, + "SCK": 18, + "SCL": 4, + "SDA": 15, + "MISO1": 12, + "MOSI1": 13, + "SCK1": 14, + "SCL1": 5, + "SDA1": 33, + }, "widora-air": { "A1": 39, "A2": 35, 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/const_esp32c6.h b/esphome/components/esp32_ble/const_esp32c6.h index 69f9adcf6b..89179d8dd9 100644 --- a/esphome/components/esp32_ble/const_esp32c6.h +++ b/esphome/components/esp32_ble/const_esp32c6.h @@ -40,6 +40,9 @@ static const esp_bt_controller_config_t BT_CONTROLLER_CONFIG = { .controller_run_cpu = 0, .enable_qa_test = RUN_QA_TEST, .enable_bqb_test = RUN_BQB_TEST, +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 3, 1) + // The following fields have been removed since ESP IDF version 5.3.1, see commit: + // https://github.com/espressif/esp-idf/commit/e761c1de8f9c0777829d597b4d5a33bb070a30a8 .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, @@ -47,6 +50,7 @@ static const esp_bt_controller_config_t BT_CONTROLLER_CONFIG = { .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, +#endif .enable_tx_cca = DEFAULT_BT_LE_TX_CCA_ENABLED, .cca_rssi_thresh = 256 - DEFAULT_BT_LE_CCA_RSSI_THRESH, .sleep_en = NIMBLE_SLEEP_ENABLE, @@ -58,6 +62,9 @@ static const esp_bt_controller_config_t BT_CONTROLLER_CONFIG = { .cpu_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, .ignore_wl_for_direct_adv = 0, .enable_pcl = DEFAULT_BT_LE_POWER_CONTROL_ENABLED, +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 3) + .csa2_select = DEFAULT_BT_LE_50_FEATURE_SUPPORT, +#endif .config_magic = CONFIG_MAGIC, }; 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 { 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; diff --git a/esphome/components/esp32_improv/__init__.py b/esphome/components/esp32_improv/__init__.py index 705dff0f1b..ecc07d4c91 100644 --- a/esphome/components/esp32_improv/__init__.py +++ b/esphome/components/esp32_improv/__init__.py @@ -1,7 +1,8 @@ +from esphome import automation import esphome.codegen as cg from esphome.components import binary_sensor, esp32_ble_server, output import esphome.config_validation as cv -from esphome.const import CONF_ID +from esphome.const import CONF_ID, CONF_ON_STATE, CONF_TRIGGER_ID AUTO_LOAD = ["esp32_ble_server"] CODEOWNERS = ["@jesserockz"] @@ -11,13 +12,36 @@ CONF_AUTHORIZED_DURATION = "authorized_duration" CONF_AUTHORIZER = "authorizer" CONF_BLE_SERVER_ID = "ble_server_id" CONF_IDENTIFY_DURATION = "identify_duration" +CONF_ON_PROVISIONED = "on_provisioned" +CONF_ON_PROVISIONING = "on_provisioning" +CONF_ON_START = "on_start" +CONF_ON_STOP = "on_stop" CONF_STATUS_INDICATOR = "status_indicator" CONF_WIFI_TIMEOUT = "wifi_timeout" +improv_ns = cg.esphome_ns.namespace("improv") +Error = improv_ns.enum("Error") +State = improv_ns.enum("State") + esp32_improv_ns = cg.esphome_ns.namespace("esp32_improv") ESP32ImprovComponent = esp32_improv_ns.class_( "ESP32ImprovComponent", cg.Component, esp32_ble_server.BLEServiceComponent ) +ESP32ImprovProvisionedTrigger = esp32_improv_ns.class_( + "ESP32ImprovProvisionedTrigger", automation.Trigger.template() +) +ESP32ImprovProvisioningTrigger = esp32_improv_ns.class_( + "ESP32ImprovProvisioningTrigger", automation.Trigger.template() +) +ESP32ImprovStartTrigger = esp32_improv_ns.class_( + "ESP32ImprovStartTrigger", automation.Trigger.template() +) +ESP32ImprovStateTrigger = esp32_improv_ns.class_( + "ESP32ImprovStateTrigger", automation.Trigger.template() +) +ESP32ImprovStoppedTrigger = esp32_improv_ns.class_( + "ESP32ImprovStoppedTrigger", automation.Trigger.template() +) CONFIG_SCHEMA = cv.Schema( @@ -37,6 +61,37 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional( CONF_WIFI_TIMEOUT, default="1min" ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_ON_PROVISIONED): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + ESP32ImprovProvisionedTrigger + ), + } + ), + cv.Optional(CONF_ON_PROVISIONING): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + ESP32ImprovProvisioningTrigger + ), + } + ), + cv.Optional(CONF_ON_START): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESP32ImprovStartTrigger), + } + ), + cv.Optional(CONF_ON_STATE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESP32ImprovStateTrigger), + } + ), + cv.Optional(CONF_ON_STOP): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + ESP32ImprovStoppedTrigger + ), + } + ), } ).extend(cv.COMPONENT_SCHEMA) @@ -63,3 +118,29 @@ async def to_code(config): if CONF_STATUS_INDICATOR in config: status_indicator = await cg.get_variable(config[CONF_STATUS_INDICATOR]) cg.add(var.set_status_indicator(status_indicator)) + + use_state_callback = False + for conf in config.get(CONF_ON_PROVISIONED, []): + 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_PROVISIONING, []): + 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_START, []): + 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_STATE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation( + trigger, [(State, "state"), (Error, "error")], conf + ) + use_state_callback = True + for conf in config.get(CONF_ON_STOP, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [], conf) + use_state_callback = True + if use_state_callback: + cg.add_define("USE_ESP32_IMPROV_STATE_CALLBACK") diff --git a/esphome/components/esp32_improv/automation.h b/esphome/components/esp32_improv/automation.h new file mode 100644 index 0000000000..52c5da125b --- /dev/null +++ b/esphome/components/esp32_improv/automation.h @@ -0,0 +1,72 @@ +#pragma once +#ifdef USE_ESP32 +#ifdef USE_ESP32_IMPROV_STATE_CALLBACK +#include "esp32_improv_component.h" + +#include "esphome/core/automation.h" + +#include + +namespace esphome { +namespace esp32_improv { + +class ESP32ImprovProvisionedTrigger : public Trigger<> { + public: + explicit ESP32ImprovProvisionedTrigger(ESP32ImprovComponent *parent) { + parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) { + if (state == improv::STATE_PROVISIONED && !parent->is_failed()) { + trigger(); + } + }); + } +}; + +class ESP32ImprovProvisioningTrigger : public Trigger<> { + public: + explicit ESP32ImprovProvisioningTrigger(ESP32ImprovComponent *parent) { + parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) { + if (state == improv::STATE_PROVISIONING && !parent->is_failed()) { + trigger(); + } + }); + } +}; + +class ESP32ImprovStartTrigger : public Trigger<> { + public: + explicit ESP32ImprovStartTrigger(ESP32ImprovComponent *parent) { + parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) { + if ((state == improv::STATE_AUTHORIZED || state == improv::STATE_AWAITING_AUTHORIZATION) && + !parent->is_failed()) { + trigger(); + } + }); + } +}; + +class ESP32ImprovStateTrigger : public Trigger { + public: + explicit ESP32ImprovStateTrigger(ESP32ImprovComponent *parent) { + parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) { + if (!parent->is_failed()) { + trigger(state, error); + } + }); + } +}; + +class ESP32ImprovStoppedTrigger : public Trigger<> { + public: + explicit ESP32ImprovStoppedTrigger(ESP32ImprovComponent *parent) { + parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) { + if (state == improv::STATE_STOPPED && !parent->is_failed()) { + trigger(); + } + }); + } +}; + +} // namespace esp32_improv +} // namespace esphome +#endif +#endif diff --git a/esphome/components/esp32_improv/esp32_improv_component.cpp b/esphome/components/esp32_improv/esp32_improv_component.cpp index d90eaac3b6..d36b50feb0 100644 --- a/esphome/components/esp32_improv/esp32_improv_component.cpp +++ b/esphome/components/esp32_improv/esp32_improv_component.cpp @@ -68,7 +68,12 @@ void ESP32ImprovComponent::setup_characteristics() { void ESP32ImprovComponent::loop() { if (!global_ble_server->is_running()) { - this->state_ = improv::STATE_STOPPED; + if (this->state_ != improv::STATE_STOPPED) { + this->state_ = improv::STATE_STOPPED; +#ifdef USE_ESP32_IMPROV_STATE_CALLBACK + this->state_callback_.call(this->state_, this->error_state_); +#endif + } this->incoming_data_.clear(); return; } @@ -217,6 +222,9 @@ void ESP32ImprovComponent::set_state_(improv::State state) { service_data[7] = 0x00; // Reserved esp32_ble::global_ble->advertising_set_service_data(service_data); +#ifdef USE_ESP32_IMPROV_STATE_CALLBACK + this->state_callback_.call(this->state_, this->error_state_); +#endif } void ESP32ImprovComponent::set_error_(improv::Error error) { @@ -270,7 +278,7 @@ void ESP32ImprovComponent::dump_config() { void ESP32ImprovComponent::process_incoming_data_() { uint8_t length = this->incoming_data_[1]; - ESP_LOGD(TAG, "Processing bytes - %s", format_hex_pretty(this->incoming_data_).c_str()); + ESP_LOGV(TAG, "Processing bytes - %s", format_hex_pretty(this->incoming_data_).c_str()); if (this->incoming_data_.size() - 3 == length) { this->set_error_(improv::ERROR_NONE); improv::ImprovCommand command = improv::parse_improv_data(this->incoming_data_); @@ -295,7 +303,7 @@ void ESP32ImprovComponent::process_incoming_data_() { wifi::global_wifi_component->set_sta(sta); wifi::global_wifi_component->start_connecting(sta, false); this->set_state_(improv::STATE_PROVISIONING); - ESP_LOGD(TAG, "Received Improv wifi settings ssid=%s, password=" LOG_SECRET("%s"), command.ssid.c_str(), + ESP_LOGD(TAG, "Received Improv Wi-Fi settings ssid=%s, password=" LOG_SECRET("%s"), command.ssid.c_str(), command.password.c_str()); auto f = std::bind(&ESP32ImprovComponent::on_wifi_connect_timeout_, this); @@ -313,7 +321,7 @@ void ESP32ImprovComponent::process_incoming_data_() { this->incoming_data_.clear(); } } else if (this->incoming_data_.size() - 2 > length) { - ESP_LOGV(TAG, "Too much data came in, or malformed resetting buffer..."); + ESP_LOGV(TAG, "Too much data received or data malformed; resetting buffer..."); this->incoming_data_.clear(); } else { ESP_LOGV(TAG, "Waiting for split data packets..."); @@ -327,7 +335,7 @@ void ESP32ImprovComponent::on_wifi_connect_timeout_() { if (this->authorizer_ != nullptr) this->authorized_start_ = millis(); #endif - ESP_LOGW(TAG, "Timed out trying to connect to given WiFi network"); + ESP_LOGW(TAG, "Timed out while connecting to Wi-Fi network"); wifi::global_wifi_component->clear_sta(); } diff --git a/esphome/components/esp32_improv/esp32_improv_component.h b/esphome/components/esp32_improv/esp32_improv_component.h index 3ed377a6ad..062b3f585b 100644 --- a/esphome/components/esp32_improv/esp32_improv_component.h +++ b/esphome/components/esp32_improv/esp32_improv_component.h @@ -9,6 +9,10 @@ #include "esphome/components/esp32_ble_server/ble_server.h" #include "esphome/components/wifi/wifi_component.h" +#ifdef USE_ESP32_IMPROV_STATE_CALLBACK +#include "esphome/core/automation.h" +#endif + #ifdef USE_BINARY_SENSOR #include "esphome/components/binary_sensor/binary_sensor.h" #endif @@ -42,6 +46,11 @@ class ESP32ImprovComponent : public Component, public BLEServiceComponent { void stop() override; bool is_active() const { return this->state_ != improv::STATE_STOPPED; } +#ifdef USE_ESP32_IMPROV_STATE_CALLBACK + void add_on_state_callback(std::function &&callback) { + this->state_callback_.add(std::move(callback)); + } +#endif #ifdef USE_BINARY_SENSOR void set_authorizer(binary_sensor::BinarySensor *authorizer) { this->authorizer_ = authorizer; } #endif @@ -54,6 +63,9 @@ class ESP32ImprovComponent : public Component, public BLEServiceComponent { void set_wifi_timeout(uint32_t wifi_timeout) { this->wifi_timeout_ = wifi_timeout; } uint32_t get_wifi_timeout() const { return this->wifi_timeout_; } + improv::State get_improv_state() const { return this->state_; } + improv::Error get_improv_error_state() const { return this->error_state_; } + protected: bool should_start_{false}; bool setup_complete_{false}; @@ -84,6 +96,9 @@ class ESP32ImprovComponent : public Component, public BLEServiceComponent { improv::State state_{improv::STATE_STOPPED}; improv::Error error_state_{improv::ERROR_NONE}; +#ifdef USE_ESP32_IMPROV_STATE_CALLBACK + CallbackManager state_callback_{}; +#endif bool status_indicator_state_{false}; void set_status_indicator_state_(bool state); diff --git a/esphome/components/esp32_rmt_led_strip/led_strip.cpp b/esphome/components/esp32_rmt_led_strip/led_strip.cpp index 71ab099de5..c2209f7a6c 100644 --- a/esphome/components/esp32_rmt_led_strip/led_strip.cpp +++ b/esphome/components/esp32_rmt_led_strip/led_strip.cpp @@ -22,7 +22,7 @@ void ESP32RMTLEDStripLightOutput::setup() { size_t buffer_size = this->get_buffer_size_(); - ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); + RAMAllocator allocator(this->use_psram_ ? 0 : RAMAllocator::ALLOC_INTERNAL); this->buf_ = allocator.allocate(buffer_size); if (this->buf_ == nullptr) { ESP_LOGE(TAG, "Cannot allocate LED buffer!"); @@ -37,7 +37,7 @@ void ESP32RMTLEDStripLightOutput::setup() { return; } - ExternalRAMAllocator rmt_allocator(ExternalRAMAllocator::ALLOW_FAILURE); + RAMAllocator rmt_allocator(this->use_psram_ ? 0 : RAMAllocator::ALLOC_INTERNAL); 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 diff --git a/esphome/components/esp32_rmt_led_strip/led_strip.h b/esphome/components/esp32_rmt_led_strip/led_strip.h index 43215cf12b..d21bd86e75 100644 --- a/esphome/components/esp32_rmt_led_strip/led_strip.h +++ b/esphome/components/esp32_rmt_led_strip/led_strip.h @@ -45,6 +45,7 @@ class ESP32RMTLEDStripLightOutput : public light::AddressableLight { 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; } + void set_use_psram(bool use_psram) { this->use_psram_ = use_psram; } /// 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; } @@ -75,6 +76,7 @@ class ESP32RMTLEDStripLightOutput : public light::AddressableLight { uint16_t num_leds_; bool is_rgbw_; bool is_wrgb_; + bool use_psram_; rmt_item32_t bit0_, bit1_, reset_; RGBOrder rgb_order_; diff --git a/esphome/components/esp32_rmt_led_strip/light.py b/esphome/components/esp32_rmt_led_strip/light.py index 1e3c2d4f72..79f339e248 100644 --- a/esphome/components/esp32_rmt_led_strip/light.py +++ b/esphome/components/esp32_rmt_led_strip/light.py @@ -55,7 +55,7 @@ CHIPSETS = { "SM16703": LEDStripTimings(300, 900, 900, 300, 0, 0), } - +CONF_USE_PSRAM = "use_psram" CONF_IS_WRGB = "is_wrgb" CONF_BIT0_HIGH = "bit0_high" CONF_BIT0_LOW = "bit0_low" @@ -77,6 +77,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(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, + cv.Optional(CONF_USE_PSRAM, default=True): cv.boolean, cv.Inclusive( CONF_BIT0_HIGH, "custom", @@ -145,6 +146,7 @@ async def to_code(config): 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])) + cg.add(var.set_use_psram(config[CONF_USE_PSRAM])) cg.add( var.set_rmt_channel( diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index 1c6acda724..dca37b8dc2 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -1,3 +1,4 @@ +import logging from esphome import pins import esphome.codegen as cg from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant @@ -23,6 +24,7 @@ from esphome.const import ( CONF_MISO_PIN, CONF_MOSI_PIN, CONF_PAGE_ID, + CONF_POLLING_INTERVAL, CONF_RESET_PIN, CONF_SPI, CONF_STATIC_IP, @@ -30,13 +32,16 @@ from esphome.const import ( CONF_TYPE, CONF_USE_ADDRESS, CONF_VALUE, + KEY_CORE, + KEY_FRAMEWORK_VERSION, ) -from esphome.core import CORE, coroutine_with_priority +from esphome.core import CORE, TimePeriodMilliseconds, coroutine_with_priority import esphome.final_validate as fv CONFLICTS_WITH = ["wifi"] DEPENDENCIES = ["esp32"] AUTO_LOAD = ["network"] +LOGGER = logging.getLogger(__name__) ethernet_ns = cg.esphome_ns.namespace("ethernet") PHYRegister = ethernet_ns.struct("PHYRegister") @@ -59,9 +64,11 @@ ETHERNET_TYPES = { "KSZ8081": EthernetType.ETHERNET_TYPE_KSZ8081, "KSZ8081RNA": EthernetType.ETHERNET_TYPE_KSZ8081RNA, "W5500": EthernetType.ETHERNET_TYPE_W5500, + "OPENETH": EthernetType.ETHERNET_TYPE_OPENETH, } SPI_ETHERNET_TYPES = ["W5500"] +SPI_ETHERNET_DEFAULT_POLLING_INTERVAL = TimePeriodMilliseconds(milliseconds=10) emac_rmii_clock_mode_t = cg.global_ns.enum("emac_rmii_clock_mode_t") emac_rmii_clock_gpio_t = cg.global_ns.enum("emac_rmii_clock_gpio_t") @@ -99,6 +106,24 @@ EthernetComponent = ethernet_ns.class_("EthernetComponent", cg.Component) ManualIP = ethernet_ns.struct("ManualIP") +def _is_framework_spi_polling_mode_supported(): + # SPI Ethernet without IRQ feature is added in + # esp-idf >= (5.3+ ,5.2.1+, 5.1.4) and arduino-esp32 >= 3.0.0 + framework_version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] + if CORE.using_esp_idf: + if framework_version >= cv.Version(5, 3, 0): + return True + if cv.Version(5, 3, 0) > framework_version >= cv.Version(5, 2, 1): + return True + if cv.Version(5, 2, 0) > framework_version >= cv.Version(5, 1, 4): + return True + return False + if CORE.using_arduino: + return framework_version >= cv.Version(3, 0, 0) + # fail safe: Unknown framework + return False + + def _validate(config): if CONF_USE_ADDRESS not in config: if CONF_MANUAL_IP in config: @@ -106,6 +131,27 @@ def _validate(config): else: use_address = CORE.name + config[CONF_DOMAIN] config[CONF_USE_ADDRESS] = use_address + if config[CONF_TYPE] in SPI_ETHERNET_TYPES: + if _is_framework_spi_polling_mode_supported(): + if CONF_POLLING_INTERVAL in config and CONF_INTERRUPT_PIN in config: + raise cv.Invalid( + f"Cannot specify more than one of {CONF_INTERRUPT_PIN}, {CONF_POLLING_INTERVAL}" + ) + if CONF_POLLING_INTERVAL not in config and CONF_INTERRUPT_PIN not in config: + config[CONF_POLLING_INTERVAL] = SPI_ETHERNET_DEFAULT_POLLING_INTERVAL + else: + if CONF_POLLING_INTERVAL in config: + raise cv.Invalid( + "In this version of the framework " + f"({CORE.target_framework} {CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]}), " + f"'{CONF_POLLING_INTERVAL}' is not supported." + ) + if CONF_INTERRUPT_PIN not in config: + raise cv.Invalid( + "In this version of the framework " + f"({CORE.target_framework} {CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]}), " + f"'{CONF_INTERRUPT_PIN}' is a required option for [ethernet]." + ) return config @@ -156,6 +202,11 @@ SPI_SCHEMA = BASE_SCHEMA.extend( cv.Optional(CONF_CLOCK_SPEED, default="26.67MHz"): cv.All( cv.frequency, cv.int_range(int(8e6), int(80e6)) ), + # Set default value (SPI_ETHERNET_DEFAULT_POLLING_INTERVAL) at _validate() + cv.Optional(CONF_POLLING_INTERVAL): cv.All( + cv.positive_time_period_milliseconds, + cv.Range(min=TimePeriodMilliseconds(milliseconds=1)), + ), } ), ) @@ -171,6 +222,7 @@ CONFIG_SCHEMA = cv.All( "KSZ8081": RMII_SCHEMA, "KSZ8081RNA": RMII_SCHEMA, "W5500": SPI_SCHEMA, + "OPENETH": BASE_SCHEMA, }, upper=True, ), @@ -232,6 +284,10 @@ async def to_code(config): cg.add(var.set_cs_pin(config[CONF_CS_PIN])) if CONF_INTERRUPT_PIN in config: cg.add(var.set_interrupt_pin(config[CONF_INTERRUPT_PIN])) + else: + cg.add(var.set_polling_interval(config[CONF_POLLING_INTERVAL])) + if _is_framework_spi_polling_mode_supported(): + cg.add_define("USE_ETHERNET_SPI_POLLING_SUPPORT") if CONF_RESET_PIN in config: cg.add(var.set_reset_pin(config[CONF_RESET_PIN])) cg.add(var.set_clock_speed(config[CONF_CLOCK_SPEED])) @@ -240,6 +296,9 @@ async def to_code(config): if CORE.using_esp_idf: add_idf_sdkconfig_option("CONFIG_ETH_USE_SPI_ETHERNET", True) add_idf_sdkconfig_option("CONFIG_ETH_SPI_ETHERNET_W5500", True) + elif config[CONF_TYPE] == "OPENETH": + cg.add_define("USE_ETHERNET_OPENETH") + add_idf_sdkconfig_option("CONFIG_ETH_USE_OPENETH", True) else: cg.add(var.set_phy_addr(config[CONF_PHY_ADDR])) cg.add(var.set_mdc_pin(config[CONF_MDC_PIN])) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index fdb6eb2da0..08f5fa6642 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -116,10 +116,15 @@ void EthernetComponent::setup() { eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle); #endif w5500_config.int_gpio_num = this->interrupt_pin_; +#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT + w5500_config.poll_period_ms = this->polling_interval_; +#endif phy_config.phy_addr = this->phy_addr_spi_; phy_config.reset_gpio_num = this->reset_pin_; esp_eth_mac_t *mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config); +#elif defined(USE_ETHERNET_OPENETH) + esp_eth_mac_t *mac = esp_eth_mac_new_openeth(&mac_config); #else phy_config.phy_addr = this->phy_addr_; phy_config.reset_gpio_num = this->power_pin_; @@ -143,6 +148,13 @@ void EthernetComponent::setup() { #endif switch (this->type_) { +#ifdef USE_ETHERNET_OPENETH + case ETHERNET_TYPE_OPENETH: { + phy_config.autonego_timeout_ms = 1000; + this->phy_ = esp_eth_phy_new_dp83848(&phy_config); + break; + } +#endif #if CONFIG_ETH_USE_ESP32_EMAC case ETHERNET_TYPE_LAN8720: { this->phy_ = esp_eth_phy_new_lan87xx(&phy_config); @@ -302,6 +314,10 @@ void EthernetComponent::dump_config() { eth_type = "W5500"; break; + case ETHERNET_TYPE_OPENETH: + eth_type = "OPENETH"; + break; + default: eth_type = "Unknown"; break; @@ -314,7 +330,14 @@ void EthernetComponent::dump_config() { ESP_LOGCONFIG(TAG, " MISO Pin: %u", this->miso_pin_); ESP_LOGCONFIG(TAG, " MOSI Pin: %u", this->mosi_pin_); ESP_LOGCONFIG(TAG, " CS Pin: %u", this->cs_pin_); - ESP_LOGCONFIG(TAG, " IRQ Pin: %u", this->interrupt_pin_); +#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT + if (this->polling_interval_ != 0) { + ESP_LOGCONFIG(TAG, " Polling Interval: %lu ms", this->polling_interval_); + } else +#endif + { + ESP_LOGCONFIG(TAG, " IRQ Pin: %d", this->interrupt_pin_); + } ESP_LOGCONFIG(TAG, " Reset Pin: %d", this->reset_pin_); ESP_LOGCONFIG(TAG, " Clock Speed: %d MHz", this->clock_speed_ / 1000000); #else @@ -523,6 +546,9 @@ void EthernetComponent::set_cs_pin(uint8_t cs_pin) { this->cs_pin_ = cs_pin; } void EthernetComponent::set_interrupt_pin(uint8_t interrupt_pin) { this->interrupt_pin_ = interrupt_pin; } void EthernetComponent::set_reset_pin(uint8_t reset_pin) { this->reset_pin_ = reset_pin; } void EthernetComponent::set_clock_speed(int clock_speed) { this->clock_speed_ = clock_speed; } +#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT +void EthernetComponent::set_polling_interval(uint32_t polling_interval) { this->polling_interval_ = polling_interval; } +#endif #else void EthernetComponent::set_phy_addr(uint8_t phy_addr) { this->phy_addr_ = phy_addr; } void EthernetComponent::set_power_pin(int power_pin) { this->power_pin_ = power_pin; } diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index f0fe6cab87..fb178431d5 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -25,6 +25,7 @@ enum EthernetType { ETHERNET_TYPE_KSZ8081, ETHERNET_TYPE_KSZ8081RNA, ETHERNET_TYPE_W5500, + ETHERNET_TYPE_OPENETH, }; struct ManualIP { @@ -66,6 +67,9 @@ class EthernetComponent : public Component { void set_interrupt_pin(uint8_t interrupt_pin); void set_reset_pin(uint8_t reset_pin); void set_clock_speed(int clock_speed); +#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT + void set_polling_interval(uint32_t polling_interval); +#endif #else void set_phy_addr(uint8_t phy_addr); void set_power_pin(int power_pin); @@ -107,10 +111,13 @@ class EthernetComponent : public Component { uint8_t miso_pin_; uint8_t mosi_pin_; uint8_t cs_pin_; - uint8_t interrupt_pin_; + int interrupt_pin_{-1}; int reset_pin_{-1}; int phy_addr_spi_{-1}; int clock_speed_; +#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT + uint32_t polling_interval_{0}; +#endif #else uint8_t phy_addr_{0}; int power_pin_{-1}; diff --git a/esphome/components/event/__init__.py b/esphome/components/event/__init__.py index 031a4c0de8..a7732dfcaf 100644 --- a/esphome/components/event/__init__.py +++ b/esphome/components/event/__init__.py @@ -1,6 +1,6 @@ from esphome import automation import esphome.codegen as cg -from esphome.components import mqtt +from esphome.components import mqtt, web_server import esphome.config_validation as cv from esphome.const import ( CONF_DEVICE_CLASS, @@ -11,6 +11,7 @@ from esphome.const import ( CONF_MQTT_ID, CONF_ON_EVENT, CONF_TRIGGER_ID, + CONF_WEB_SERVER, DEVICE_CLASS_BUTTON, DEVICE_CLASS_DOORBELL, DEVICE_CLASS_EMPTY, @@ -40,17 +41,21 @@ 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), - } - ), - } +EVENT_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.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() @@ -97,6 +102,9 @@ async def setup_event_core_(var, config, *, event_types: list[str]): mqtt_ = cg.new_Pvariable(mqtt_id, var) await mqtt.register_mqtt_component(mqtt_, config) + if web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(var, web_server_config) + async def register_event(var, config, *, event_types: list[str]): if not CORE.has_id(config[CONF_ID]): diff --git a/esphome/components/fan/__init__.py b/esphome/components/fan/__init__.py index 62624ec6e3..4e0e52cd65 100644 --- a/esphome/components/fan/__init__.py +++ b/esphome/components/fan/__init__.py @@ -25,7 +25,7 @@ from esphome.const import ( CONF_SPEED_LEVEL_STATE_TOPIC, CONF_SPEED_STATE_TOPIC, CONF_TRIGGER_ID, - CONF_WEB_SERVER_ID, + CONF_WEB_SERVER, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_helpers import setup_entity @@ -218,9 +218,8 @@ 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) + if web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(var, web_server_config) for conf in config.get(CONF_ON_STATE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) diff --git a/esphome/components/font/__init__.py b/esphome/components/font/__init__.py index b5ed02e89a..a3f11df50e 100644 --- a/esphome/components/font/__init__.py +++ b/esphome/components/font/__init__.py @@ -98,13 +98,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==10.2.0")' + '(pip install "pillow==10.4.0")' ) from err - if version.parse(PIL.__version__) != version.parse("10.2.0"): + if version.parse(PIL.__version__) != version.parse("10.4.0"): raise cv.Invalid( - "Please update your pillow installation to 10.2.0. " - '(pip install "pillow==10.2.0")' + "Please update your pillow installation to 10.4.0. " + '(pip install "pillow==10.4.0")' ) return value @@ -344,7 +344,7 @@ class TrueTypeFontWrapper: return offset_x, offset_y def getmask(self, glyph, **kwargs): - return self.font.getmask(glyph, **kwargs) + return self.font.getmask(str(glyph), **kwargs) def getmetrics(self, glyphs): return self.font.getmetrics() @@ -359,7 +359,7 @@ class BitmapFontWrapper: return 0, 0 def getmask(self, glyph, **kwargs): - return self.font.getmask(glyph, **kwargs) + return self.font.getmask(str(glyph), **kwargs) def getmetrics(self, glyphs): max_height = 0 diff --git a/esphome/components/gp2y1010au0f/__init__.py b/esphome/components/gp2y1010au0f/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/gp2y1010au0f/gp2y1010au0f.cpp b/esphome/components/gp2y1010au0f/gp2y1010au0f.cpp new file mode 100644 index 0000000000..95b7653e51 --- /dev/null +++ b/esphome/components/gp2y1010au0f/gp2y1010au0f.cpp @@ -0,0 +1,67 @@ +#include "gp2y1010au0f.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" + +#include + +namespace esphome { +namespace gp2y1010au0f { + +static const char *const TAG = "gp2y1010au0f"; +static const float MIN_VOLTAGE = 0.0f; +static const float MAX_VOLTAGE = 4.0f; + +void GP2Y1010AU0FSensor::dump_config() { + LOG_SENSOR("", "Sharp GP2Y1010AU0F PM2.5 Sensor", this); + ESP_LOGCONFIG(TAG, " Sampling duration: %" PRId32 " ms", this->sample_duration_); + ESP_LOGCONFIG(TAG, " ADC voltage multiplier: %.3f", this->voltage_multiplier_); + LOG_UPDATE_INTERVAL(this); +} + +void GP2Y1010AU0FSensor::update() { + is_sampling_ = true; + + this->set_timeout("read", this->sample_duration_, [this]() { + this->is_sampling_ = false; + if (this->num_samples_ == 0) + return; + + float mean = this->sample_sum_ / float(this->num_samples_); + ESP_LOGD(TAG, "ADC read voltage: %.3f V (mean from %" PRId32 " samples)", mean, this->num_samples_); + + // PM2.5 calculation + // ref: https://www.howmuchsnow.com/arduino/airquality/ + int16_t pm_2_5_value = 170 * mean; + this->publish_state(pm_2_5_value); + }); + + // reset readings + this->num_samples_ = 0; + this->sample_sum_ = 0.0f; +} + +void GP2Y1010AU0FSensor::loop() { + if (!this->is_sampling_) + return; + + // enable the internal IR LED + this->led_output_->turn_on(); + // wait for the sensor to stabilize + delayMicroseconds(this->sample_wait_before_); + // perform a single sample + float read_voltage = this->source_->sample(); + // disable the internal IR LED + this->led_output_->turn_off(); + + if (std::isnan(read_voltage)) + return; + read_voltage = read_voltage * this->voltage_multiplier_ - this->voltage_offset_; + if (read_voltage < MIN_VOLTAGE || read_voltage > MAX_VOLTAGE) + return; + + this->num_samples_++; + this->sample_sum_ += read_voltage; +} + +} // namespace gp2y1010au0f +} // namespace esphome diff --git a/esphome/components/gp2y1010au0f/gp2y1010au0f.h b/esphome/components/gp2y1010au0f/gp2y1010au0f.h new file mode 100644 index 0000000000..5ee58e68d2 --- /dev/null +++ b/esphome/components/gp2y1010au0f/gp2y1010au0f.h @@ -0,0 +1,52 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/voltage_sampler/voltage_sampler.h" +#include "esphome/components/output/binary_output.h" + +namespace esphome { +namespace gp2y1010au0f { + +class GP2Y1010AU0FSensor : public sensor::Sensor, public PollingComponent { + public: + void update() override; + void loop() override; + void dump_config() override; + float get_setup_priority() const override { + // after the base sensor has been initialized + return setup_priority::DATA - 1.0f; + } + + void set_adc_source(voltage_sampler::VoltageSampler *source) { source_ = source; } + void set_voltage_refs(float offset, float multiplier) { + this->voltage_offset_ = offset; + this->voltage_multiplier_ = multiplier; + } + void set_led_output(output::BinaryOutput *output) { led_output_ = output; } + + protected: + // duration in ms of the sampling phase + uint32_t sample_duration_ = 100; + // duration in us of the wait before sampling + // ref: https://global.sharp/products/device/lineup/data/pdf/datasheet/gp2y1010au_appl_e.pdf + uint32_t sample_wait_before_ = 280; + // duration in us of the wait after sampling + // it seems no need to delay on purpose since one ADC sampling takes longer than that (300-400 us on ESP8266) + // uint32_t sample_wait_after_ = 40; + // the sampling source to read voltage from + voltage_sampler::VoltageSampler *source_; + // ADC voltage reading offset + float voltage_offset_ = 0.0f; + // ADC voltage reading multiplier + float voltage_multiplier_ = 1.0f; + // the binary output to control the sampling LED + output::BinaryOutput *led_output_; + + float sample_sum_ = 0.0f; + uint32_t num_samples_ = 0; + bool is_sampling_ = false; +}; + +} // namespace gp2y1010au0f +} // namespace esphome diff --git a/esphome/components/gp2y1010au0f/sensor.py b/esphome/components/gp2y1010au0f/sensor.py new file mode 100644 index 0000000000..7e1bd277a6 --- /dev/null +++ b/esphome/components/gp2y1010au0f/sensor.py @@ -0,0 +1,61 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor, voltage_sampler, output +from esphome.const import ( + CONF_SENSOR, + CONF_OUTPUT, + DEVICE_CLASS_PM25, + STATE_CLASS_MEASUREMENT, + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, +) + +DEPENDENCIES = ["output"] +AUTO_LOAD = ["voltage_sampler"] +CODEOWNERS = ["@zry98"] + +CONF_ADC_VOLTAGE_OFFSET = "adc_voltage_offset" +CONF_ADC_VOLTAGE_MULTIPLIER = "adc_voltage_multiplier" + +gp2y1010au0f_ns = cg.esphome_ns.namespace("gp2y1010au0f") +GP2Y1010AU0FSensor = gp2y1010au0f_ns.class_( + "GP2Y1010AU0FSensor", sensor.Sensor, cg.PollingComponent +) + +CONFIG_SCHEMA = ( + sensor.sensor_schema( + GP2Y1010AU0FSensor, + unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, + accuracy_decimals=0, + device_class=DEVICE_CLASS_PM25, + state_class=STATE_CLASS_MEASUREMENT, + icon=ICON_CHEMICAL_WEAPON, + ) + .extend( + { + cv.Required(CONF_SENSOR): cv.use_id(voltage_sampler.VoltageSampler), + cv.Optional(CONF_ADC_VOLTAGE_OFFSET, default=0.0): cv.float_, + cv.Optional(CONF_ADC_VOLTAGE_MULTIPLIER, default=1.0): cv.float_, + cv.Required(CONF_OUTPUT): cv.use_id(output.BinaryOutput), + } + ) + .extend(cv.polling_component_schema("60s")) +) + + +async def to_code(config): + var = await sensor.new_sensor(config) + await cg.register_component(var, config) + + # the ADC sensor to read voltage from + adc_sensor = await cg.get_variable(config[CONF_SENSOR]) + cg.add(var.set_adc_source(adc_sensor)) + cg.add( + var.set_voltage_refs( + config[CONF_ADC_VOLTAGE_OFFSET], config[CONF_ADC_VOLTAGE_MULTIPLIER] + ) + ) + + # the binary output to control the module's internal IR LED + led_output = await cg.get_variable(config[CONF_OUTPUT]) + cg.add(var.set_led_output(led_output)) diff --git a/esphome/components/gp8403/output/__init__.py b/esphome/components/gp8403/output/__init__.py index 1cf95ac6e5..7f17faa1b1 100644 --- a/esphome/components/gp8403/output/__init__.py +++ b/esphome/components/gp8403/output/__init__.py @@ -16,7 +16,7 @@ CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(GP8403Output), cv.GenerateID(CONF_GP8403_ID): cv.use_id(GP8403), - cv.Required(CONF_CHANNEL): cv.one_of(0, 1), + cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=1), } ).extend(cv.COMPONENT_SCHEMA) diff --git a/esphome/components/gpio_expander/__init__.py b/esphome/components/gpio_expander/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/gpio_expander/cached_gpio.h b/esphome/components/gpio_expander/cached_gpio.h new file mode 100644 index 0000000000..784c5f0f4a --- /dev/null +++ b/esphome/components/gpio_expander/cached_gpio.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include "esphome/core/hal.h" + +namespace esphome { +namespace gpio_expander { + +/// @brief A class to cache the read state of a GPIO expander. +template class CachedGpioExpander { + public: + bool digital_read(T pin) { + if (!this->read_cache_invalidated_[pin]) { + this->read_cache_invalidated_[pin] = true; + return this->digital_read_cache(pin); + } + return this->digital_read_hw(pin); + } + + void digital_write(T pin, bool value) { this->digital_write_hw(pin, value); } + + protected: + virtual bool digital_read_hw(T pin) = 0; + virtual bool digital_read_cache(T pin) = 0; + virtual void digital_write_hw(T pin, bool value) = 0; + + void reset_pin_cache_() { + for (T i = 0; i < N; i++) { + this->read_cache_invalidated_[i] = false; + } + } + + std::array read_cache_invalidated_{}; +}; + +} // namespace gpio_expander +} // namespace esphome diff --git a/esphome/components/grove_gas_mc_v2/__init__.py b/esphome/components/grove_gas_mc_v2/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp b/esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp new file mode 100644 index 0000000000..ed40ba42a5 --- /dev/null +++ b/esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp @@ -0,0 +1,88 @@ +#include "grove_gas_mc_v2.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace grove_gas_mc_v2 { + +static const char *const TAG = "grove_gas_mc_v2"; + +// I2C Commands for Grove Gas Multichannel V2 Sensor +// Taken from: +// https://github.com/Seeed-Studio/Seeed_Arduino_MultiGas/blob/master/src/Multichannel_Gas_GroveGasMultichannelV2.h +static const uint8_t GROVE_GAS_MC_V2_HEAT_ON = 0xFE; +static const uint8_t GROVE_GAS_MC_V2_HEAT_OFF = 0xFF; +static const uint8_t GROVE_GAS_MC_V2_READ_GM102B = 0x01; +static const uint8_t GROVE_GAS_MC_V2_READ_GM302B = 0x03; +static const uint8_t GROVE_GAS_MC_V2_READ_GM502B = 0x05; +static const uint8_t GROVE_GAS_MC_V2_READ_GM702B = 0x07; + +bool GroveGasMultichannelV2Component::read_sensor_(uint8_t address, sensor::Sensor *sensor) { + if (sensor == nullptr) { + return true; + } + uint32_t value = 0; + if (!this->read_bytes(address, (uint8_t *) &value, 4)) { + ESP_LOGW(TAG, "Reading Grove Gas Sensor data failed!"); + this->error_code_ = COMMUNICATION_FAILED; + this->status_set_warning(); + return false; + } + sensor->publish_state(value); + return true; +} + +void GroveGasMultichannelV2Component::setup() { + ESP_LOGCONFIG(TAG, "Setting up Grove Multichannel Gas Sensor V2..."); + + // Before reading sensor values, must preheat sensor + if (!(this->write_bytes(GROVE_GAS_MC_V2_HEAT_ON, {}))) { + this->mark_failed(); + this->error_code_ = APP_START_FAILED; + } +} + +void GroveGasMultichannelV2Component::update() { + // Read from each of the gas sensors + if (!this->read_sensor_(GROVE_GAS_MC_V2_READ_GM102B, this->nitrogen_dioxide_sensor_)) + return; + if (!this->read_sensor_(GROVE_GAS_MC_V2_READ_GM302B, this->ethanol_sensor_)) + return; + if (!this->read_sensor_(GROVE_GAS_MC_V2_READ_GM502B, this->tvoc_sensor_)) + return; + if (!this->read_sensor_(GROVE_GAS_MC_V2_READ_GM702B, this->carbon_monoxide_sensor_)) + return; + + this->status_clear_warning(); +} + +void GroveGasMultichannelV2Component::dump_config() { + ESP_LOGCONFIG(TAG, "Grove Multichannel Gas Sensor V2"); + LOG_I2C_DEVICE(this) + LOG_UPDATE_INTERVAL(this) + LOG_SENSOR(" ", "Nitrogen Dioxide", this->nitrogen_dioxide_sensor_) + LOG_SENSOR(" ", "Ethanol", this->ethanol_sensor_) + LOG_SENSOR(" ", "Carbon Monoxide", this->carbon_monoxide_sensor_) + LOG_SENSOR(" ", "TVOC", this->tvoc_sensor_) + + if (this->is_failed()) { + switch (this->error_code_) { + case COMMUNICATION_FAILED: + ESP_LOGW(TAG, "Communication failed! Is the sensor connected?"); + break; + case APP_INVALID: + ESP_LOGW(TAG, "Sensor reported invalid APP installed."); + break; + case APP_START_FAILED: + ESP_LOGW(TAG, "Sensor reported APP start failed."); + break; + case UNKNOWN: + default: + ESP_LOGW(TAG, "Unknown setup error!"); + break; + } + } +} + +} // namespace grove_gas_mc_v2 +} // namespace esphome diff --git a/esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.h b/esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.h new file mode 100644 index 0000000000..1987d33f37 --- /dev/null +++ b/esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.h @@ -0,0 +1,39 @@ +#pragma once + +#include "esphome/components/i2c/i2c.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/core/component.h" +#include "esphome/core/preferences.h" + +namespace esphome { +namespace grove_gas_mc_v2 { + +class GroveGasMultichannelV2Component : public PollingComponent, public i2c::I2CDevice { + SUB_SENSOR(tvoc) + SUB_SENSOR(carbon_monoxide) + SUB_SENSOR(nitrogen_dioxide) + SUB_SENSOR(ethanol) + + public: + /// Setup the sensor and test for a connection. + void setup() override; + /// Schedule temperature+pressure readings. + void update() override; + + void dump_config() override; + + float get_setup_priority() const override { return setup_priority::DATA; } + + protected: + enum ErrorCode { + UNKNOWN, + COMMUNICATION_FAILED, + APP_INVALID, + APP_START_FAILED, + } error_code_{UNKNOWN}; + + bool read_sensor_(uint8_t address, sensor::Sensor *sensor); +}; + +} // namespace grove_gas_mc_v2 +} // namespace esphome diff --git a/esphome/components/grove_gas_mc_v2/sensor.py b/esphome/components/grove_gas_mc_v2/sensor.py new file mode 100644 index 0000000000..0c35047850 --- /dev/null +++ b/esphome/components/grove_gas_mc_v2/sensor.py @@ -0,0 +1,77 @@ +import esphome.codegen as cg +from esphome.components import i2c, sensor +import esphome.config_validation as cv +from esphome.const import ( + CONF_CARBON_MONOXIDE, + CONF_ETHANOL, + CONF_ID, + CONF_NITROGEN_DIOXIDE, + CONF_TVOC, + DEVICE_CLASS_CARBON_MONOXIDE, + DEVICE_CLASS_NITROGEN_DIOXIDE, + DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS, + ICON_AIR_FILTER, + ICON_FLASK_ROUND_BOTTOM, + ICON_GAS_CYLINDER, + ICON_MOLECULE_CO, + STATE_CLASS_MEASUREMENT, + UNIT_MICROGRAMS_PER_CUBIC_METER, + UNIT_PARTS_PER_MILLION, +) + +CODEOWNERS = ["@YorkshireIoT"] +DEPENDENCIES = ["i2c"] + +grove_gas_mc_v2_ns = cg.esphome_ns.namespace("grove_gas_mc_v2") + +GroveGasMultichannelV2Component = grove_gas_mc_v2_ns.class_( + "GroveGasMultichannelV2Component", cg.PollingComponent, i2c.I2CDevice +) + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(GroveGasMultichannelV2Component), + cv.Optional(CONF_TVOC): sensor.sensor_schema( + unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, + icon=ICON_AIR_FILTER, + accuracy_decimals=0, + device_class=DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_CARBON_MONOXIDE): sensor.sensor_schema( + unit_of_measurement=UNIT_PARTS_PER_MILLION, + icon=ICON_MOLECULE_CO, + accuracy_decimals=0, + device_class=DEVICE_CLASS_CARBON_MONOXIDE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_NITROGEN_DIOXIDE): sensor.sensor_schema( + unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, + icon=ICON_GAS_CYLINDER, + accuracy_decimals=0, + device_class=DEVICE_CLASS_NITROGEN_DIOXIDE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_ETHANOL): sensor.sensor_schema( + unit_of_measurement=UNIT_PARTS_PER_MILLION, + icon=ICON_FLASK_ROUND_BOTTOM, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x08)) +) + + +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 in [CONF_TVOC, CONF_CARBON_MONOXIDE, CONF_NITROGEN_DIOXIDE, CONF_ETHANOL]: + if sensor_config := config.get(key): + sensor_ = await sensor.new_sensor(sensor_config) + cg.add(getattr(var, f"set_{key}_sensor")(sensor_)) diff --git a/esphome/components/haier/climate.py b/esphome/components/haier/climate.py index f7423a1356..f2dc7174cb 100644 --- a/esphome/components/haier/climate.py +++ b/esphome/components/haier/climate.py @@ -114,7 +114,6 @@ SUPPORTED_CLIMATE_PRESETS_SMARTAIR2_OPTIONS = { SUPPORTED_CLIMATE_PRESETS_HON_OPTIONS = { "AWAY": ClimatePreset.CLIMATE_PRESET_AWAY, "BOOST": ClimatePreset.CLIMATE_PRESET_BOOST, - "ECO": ClimatePreset.CLIMATE_PRESET_ECO, "SLEEP": ClimatePreset.CLIMATE_PRESET_SLEEP, } @@ -240,7 +239,9 @@ CONFIG_SCHEMA = cv.All( ): cv.ensure_list( cv.enum(SUPPORTED_HON_CONTROL_METHODS, upper=True) ), - cv.Optional(CONF_BEEPER, default=True): cv.boolean, + cv.Optional(CONF_BEEPER): cv.invalid( + f"The {CONF_BEEPER} option is deprecated, use beeper_on/beeper_off actions or beeper switch for a haier platform instead" + ), cv.Optional( CONF_CONTROL_PACKET_SIZE, default=PROTOCOL_CONTROL_PACKET_SIZE ): cv.int_range(min=PROTOCOL_CONTROL_PACKET_SIZE, max=50), @@ -254,7 +255,7 @@ CONFIG_SCHEMA = cv.All( ): cv.int_range(min=PROTOCOL_STATUS_MESSAGE_HEADER_SIZE), cv.Optional( CONF_SUPPORTED_PRESETS, - default=["BOOST", "ECO", "SLEEP"], # No AWAY by default + default=["BOOST", "SLEEP"], # No AWAY by default ): cv.ensure_list( cv.enum(SUPPORTED_CLIMATE_PRESETS_HON_OPTIONS, upper=True) ), diff --git a/esphome/components/haier/haier_base.cpp b/esphome/components/haier/haier_base.cpp index 0bd3863160..ba80c1ca1b 100644 --- a/esphome/components/haier/haier_base.cpp +++ b/esphome/components/haier/haier_base.cpp @@ -52,8 +52,6 @@ bool check_timeout(std::chrono::steady_clock::time_point now, std::chrono::stead HaierClimateBase::HaierClimateBase() : haier_protocol_(*this), protocol_phase_(ProtocolPhases::SENDING_INIT_1), - display_status_(true), - health_mode_(false), force_send_control_(false), forced_request_status_(false), reset_protocol_request_(false), @@ -127,21 +125,34 @@ haier_protocol::HaierMessage HaierClimateBase::get_wifi_signal_message_() { } #endif -bool HaierClimateBase::get_display_state() const { return this->display_status_; } - -void HaierClimateBase::set_display_state(bool state) { - if (this->display_status_ != state) { - this->display_status_ = state; - this->force_send_control_ = true; +void HaierClimateBase::save_settings() { + HaierBaseSettings settings{this->get_health_mode(), this->get_display_state()}; + if (!this->base_rtc_.save(&settings)) { + ESP_LOGW(TAG, "Failed to save settings"); } } -bool HaierClimateBase::get_health_mode() const { return this->health_mode_; } +bool HaierClimateBase::get_display_state() const { + return (this->display_status_ == SwitchState::ON) || (this->display_status_ == SwitchState::PENDING_ON); +} + +void HaierClimateBase::set_display_state(bool state) { + if (state != this->get_display_state()) { + this->display_status_ = state ? SwitchState::PENDING_ON : SwitchState::PENDING_OFF; + this->force_send_control_ = true; + this->save_settings(); + } +} + +bool HaierClimateBase::get_health_mode() const { + return (this->health_mode_ == SwitchState::ON) || (this->health_mode_ == SwitchState::PENDING_ON); +} void HaierClimateBase::set_health_mode(bool state) { - if (this->health_mode_ != state) { - this->health_mode_ = state; + if (state != this->get_health_mode()) { + this->health_mode_ = state ? SwitchState::PENDING_ON : SwitchState::PENDING_OFF; this->force_send_control_ = true; + this->save_settings(); } } @@ -287,6 +298,14 @@ void HaierClimateBase::loop() { } this->process_phase(now); this->haier_protocol_.loop(); +#ifdef USE_SWITCH + if ((this->display_switch_ != nullptr) && (this->display_switch_->state != this->get_display_state())) { + this->display_switch_->publish_state(this->get_display_state()); + } + if ((this->health_mode_switch_ != nullptr) && (this->health_mode_switch_->state != this->get_health_mode())) { + this->health_mode_switch_->publish_state(this->get_health_mode()); + } +#endif // USE_SWITCH } void HaierClimateBase::process_protocol_reset() { @@ -329,6 +348,26 @@ bool HaierClimateBase::prepare_pending_action() { ClimateTraits HaierClimateBase::traits() { return traits_; } +void HaierClimateBase::initialization() { + constexpr uint32_t restore_settings_version = 0xA77D21EF; + this->base_rtc_ = + global_preferences->make_preference(this->get_object_id_hash() ^ restore_settings_version); + HaierBaseSettings recovered; + if (!this->base_rtc_.load(&recovered)) { + recovered = {false, true}; + } + this->display_status_ = recovered.display_state ? SwitchState::PENDING_ON : SwitchState::PENDING_OFF; + this->health_mode_ = recovered.health_mode ? SwitchState::PENDING_ON : SwitchState::PENDING_OFF; +#ifdef USE_SWITCH + if (this->display_switch_ != nullptr) { + this->display_switch_->publish_state(this->get_display_state()); + } + if (this->health_mode_switch_ != nullptr) { + this->health_mode_switch_->publish_state(this->get_health_mode()); + } +#endif +} + void HaierClimateBase::control(const ClimateCall &call) { ESP_LOGD("Control", "Control call"); if (!this->valid_connection()) { @@ -353,6 +392,22 @@ void HaierClimateBase::control(const ClimateCall &call) { } } +#ifdef USE_SWITCH +void HaierClimateBase::set_display_switch(switch_::Switch *sw) { + this->display_switch_ = sw; + if ((this->display_switch_ != nullptr) && (this->valid_connection())) { + this->display_switch_->publish_state(this->get_display_state()); + } +} + +void HaierClimateBase::set_health_mode_switch(switch_::Switch *sw) { + this->health_mode_switch_ = sw; + if ((this->health_mode_switch_ != nullptr) && (this->valid_connection())) { + this->health_mode_switch_->publish_state(this->get_health_mode()); + } +} +#endif + void HaierClimateBase::HvacSettings::reset() { this->valid = false; this->mode.reset(); diff --git a/esphome/components/haier/haier_base.h b/esphome/components/haier/haier_base.h index 7d92a6611c..f0597c49ff 100644 --- a/esphome/components/haier/haier_base.h +++ b/esphome/components/haier/haier_base.h @@ -8,6 +8,10 @@ // HaierProtocol #include +#ifdef USE_SWITCH +#include "esphome/components/switch/switch.h" +#endif + namespace esphome { namespace haier { @@ -20,10 +24,24 @@ enum class ActionRequest : uint8_t { START_STERI_CLEAN = 5, // only hOn }; +struct HaierBaseSettings { + bool health_mode; + bool display_state; +}; + class HaierClimateBase : public esphome::Component, public esphome::climate::Climate, public esphome::uart::UARTDevice, public haier_protocol::ProtocolStream { +#ifdef USE_SWITCH + public: + void set_display_switch(switch_::Switch *sw); + void set_health_mode_switch(switch_::Switch *sw); + + protected: + switch_::Switch *display_switch_{nullptr}; + switch_::Switch *health_mode_switch_{nullptr}; +#endif public: HaierClimateBase(); HaierClimateBase(const HaierClimateBase &) = delete; @@ -82,7 +100,8 @@ 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; // NOLINT(readability-identifier-naming) virtual haier_protocol::HaierMessage get_power_message(bool state) = 0; // NOLINT(readability-identifier-naming) - virtual void initialization(){}; + virtual void save_settings(); + virtual void initialization(); virtual bool prepare_pending_action(); virtual void process_protocol_reset(); esphome::climate::ClimateTraits traits() override; @@ -127,13 +146,19 @@ class HaierClimateBase : public esphome::Component, ActionRequest action; esphome::optional message; }; + enum class SwitchState { + OFF = 0b00, + ON = 0b01, + PENDING_OFF = 0b10, + PENDING_ON = 0b11, + }; haier_protocol::ProtocolHandler haier_protocol_; ProtocolPhases protocol_phase_; esphome::optional action_request_; uint8_t fan_mode_speed_; uint8_t other_modes_fan_speed_; - bool display_status_; - bool health_mode_; + SwitchState display_status_{SwitchState::ON}; + SwitchState health_mode_{SwitchState::OFF}; bool force_send_control_; bool forced_request_status_; bool reset_protocol_request_; @@ -148,6 +173,7 @@ class HaierClimateBase : public esphome::Component, 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_{}; + ESPPreferenceObject base_rtc_; }; class StatusMessageTrigger : public Trigger { diff --git a/esphome/components/haier/hon_climate.cpp b/esphome/components/haier/hon_climate.cpp index a1c5098cec..e7be1fa418 100644 --- a/esphome/components/haier/hon_climate.cpp +++ b/esphome/components/haier/hon_climate.cpp @@ -31,9 +31,32 @@ HonClimate::HonClimate() HonClimate::~HonClimate() {} -void HonClimate::set_beeper_state(bool state) { this->beeper_status_ = state; } +void HonClimate::set_beeper_state(bool state) { + if (state != this->settings_.beeper_state) { + this->settings_.beeper_state = state; +#ifdef USE_SWITCH + this->beeper_switch_->publish_state(state); +#endif + this->hon_rtc_.save(&this->settings_); + } +} -bool HonClimate::get_beeper_state() const { return this->beeper_status_; } +bool HonClimate::get_beeper_state() const { return this->settings_.beeper_state; } + +void HonClimate::set_quiet_mode_state(bool state) { + if (state != this->get_quiet_mode_state()) { + this->quiet_mode_state_ = state ? SwitchState::PENDING_ON : SwitchState::PENDING_OFF; + this->settings_.quiet_mode_state = state; +#ifdef USE_SWITCH + this->quiet_mode_switch_->publish_state(state); +#endif + this->hon_rtc_.save(&this->settings_); + } +} + +bool HonClimate::get_quiet_mode_state() const { + return (this->quiet_mode_state_ == SwitchState::ON) || (this->quiet_mode_state_ == SwitchState::PENDING_ON); +} esphome::optional HonClimate::get_vertical_airflow() const { return this->current_vertical_swing_; @@ -474,16 +497,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); + HaierClimateBase::initialization(); + constexpr uint32_t restore_settings_version = 0x57EB59DDUL; + this->hon_rtc_ = + global_preferences->make_preference(this->get_object_id_hash() ^ restore_settings_version); HonSettings recovered; - if (this->rtc_.load(&recovered)) { + if (this->hon_rtc_.load(&recovered)) { this->settings_ = recovered; } else { - this->settings_ = {hon_protocol::VerticalSwingMode::CENTER, hon_protocol::HorizontalSwingMode::CENTER}; + this->settings_ = {hon_protocol::VerticalSwingMode::CENTER, hon_protocol::HorizontalSwingMode::CENTER, true, false}; } this->current_vertical_swing_ = this->settings_.last_vertiacal_swing; this->current_horizontal_swing_ = this->settings_.last_horizontal_swing; + this->quiet_mode_state_ = this->settings_.quiet_mode_state ? SwitchState::PENDING_ON : SwitchState::PENDING_OFF; } haier_protocol::HaierMessage HonClimate::get_control_message() { @@ -519,8 +545,7 @@ haier_protocol::HaierMessage HonClimate::get_control_message() { out_data->ac_power = 1; out_data->ac_mode = (uint8_t) hon_protocol::ConditioningMode::FAN; out_data->fan_mode = this->fan_mode_speed_; // Auto doesn't work in fan only mode - // Disabling boost and eco mode for Fan only - out_data->quiet_mode = 0; + // Disabling boost for Fan only out_data->fast_mode = 0; break; case CLIMATE_MODE_COOL: @@ -582,47 +607,34 @@ haier_protocol::HaierMessage HonClimate::get_control_message() { } if (out_data->ac_power == 0) { // If AC is off - no presets allowed - out_data->quiet_mode = 0; out_data->fast_mode = 0; out_data->sleep_mode = 0; } else if (climate_control.preset.has_value()) { switch (climate_control.preset.value()) { case CLIMATE_PRESET_NONE: - out_data->quiet_mode = 0; - out_data->fast_mode = 0; - out_data->sleep_mode = 0; - out_data->ten_degree = 0; - break; - case CLIMATE_PRESET_ECO: - // Eco is not supported in Fan only mode - out_data->quiet_mode = (this->mode != CLIMATE_MODE_FAN_ONLY) ? 1 : 0; out_data->fast_mode = 0; out_data->sleep_mode = 0; out_data->ten_degree = 0; break; case CLIMATE_PRESET_BOOST: - out_data->quiet_mode = 0; // Boost is not supported in Fan only mode out_data->fast_mode = (this->mode != CLIMATE_MODE_FAN_ONLY) ? 1 : 0; out_data->sleep_mode = 0; out_data->ten_degree = 0; break; case CLIMATE_PRESET_AWAY: - out_data->quiet_mode = 0; out_data->fast_mode = 0; out_data->sleep_mode = 0; // 10 degrees allowed only in heat mode out_data->ten_degree = (this->mode == CLIMATE_MODE_HEAT) ? 1 : 0; break; case CLIMATE_PRESET_SLEEP: - out_data->quiet_mode = 0; out_data->fast_mode = 0; out_data->sleep_mode = 1; out_data->ten_degree = 0; break; default: ESP_LOGE("Control", "Unsupported preset"); - out_data->quiet_mode = 0; out_data->fast_mode = 0; out_data->sleep_mode = 0; out_data->ten_degree = 0; @@ -638,10 +650,23 @@ haier_protocol::HaierMessage HonClimate::get_control_message() { 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; + { + // Quiet mode + if ((out_data->ac_power == 0) || (out_data->ac_mode == (uint8_t) hon_protocol::ConditioningMode::FAN)) { + // If AC is off or in fan only mode - no quiet mode allowed + out_data->quiet_mode = 0; + } else { + out_data->quiet_mode = this->get_quiet_mode_state() ? 1 : 0; + } + // Clean quiet mode state pending flag + this->quiet_mode_state_ = (SwitchState) ((uint8_t) this->quiet_mode_state_ & 0b01); + } + out_data->beeper_status = ((!this->get_beeper_state()) || (!has_hvac_settings)) ? 1 : 0; control_out_buffer[4] = 0; // This byte should be cleared before setting values - out_data->display_status = this->display_status_ ? 1 : 0; - out_data->health_mode = this->health_mode_ ? 1 : 0; + out_data->display_status = this->get_display_state() ? 1 : 0; + this->display_status_ = (SwitchState) ((uint8_t) this->display_status_ & 0b01); + out_data->health_mode = this->get_health_mode() ? 1 : 0; + this->health_mode_ = (SwitchState) ((uint8_t) this->health_mode_ & 0b01); return haier_protocol::HaierMessage(haier_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcommandsControl::SET_GROUP_PARAMETERS, control_out_buffer, this->real_control_packet_size_); @@ -765,6 +790,22 @@ void HonClimate::update_sub_text_sensor_(SubTextSensorType type, const std::stri } #endif // USE_TEXT_SENSOR +#ifdef USE_SWITCH +void HonClimate::set_beeper_switch(switch_::Switch *sw) { + this->beeper_switch_ = sw; + if (this->beeper_switch_ != nullptr) { + this->beeper_switch_->publish_state(this->get_beeper_state()); + } +} + +void HonClimate::set_quiet_mode_switch(switch_::Switch *sw) { + this->quiet_mode_switch_ = sw; + if (this->quiet_mode_switch_ != nullptr) { + this->quiet_mode_switch_->publish_state(this->settings_.quiet_mode_state); + } +} +#endif // USE_SWITCH + haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t *packet_buffer, uint8_t size) { size_t expected_size = 2 + this->status_message_header_size_ + this->real_control_packet_size_ + this->real_sensors_packet_size_; @@ -827,9 +868,7 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t * { // Extra modes/presets optional old_preset = this->preset; - if (packet.control.quiet_mode != 0) { - this->preset = CLIMATE_PRESET_ECO; - } else if (packet.control.fast_mode != 0) { + if (packet.control.fast_mode != 0) { this->preset = CLIMATE_PRESET_BOOST; } else if (packet.control.sleep_mode != 0) { this->preset = CLIMATE_PRESET_SLEEP; @@ -883,28 +922,26 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t * } should_publish = should_publish || (!old_fan_mode.has_value()) || (old_fan_mode.value() != fan_mode.value()); } - { - // Display status - // should be before "Climate mode" because it is changing this->mode - if (packet.control.ac_power != 0) { - // if AC is off display status always ON so process it only when AC is on - bool disp_status = packet.control.display_status != 0; - if (disp_status != this->display_status_) { - // Do something only if display status changed - if (this->mode == CLIMATE_MODE_OFF) { - // AC just turned on from remote need to turn off display - this->force_send_control_ = true; - } else { - this->display_status_ = disp_status; - } + // Display status + // should be before "Climate mode" because it is changing this->mode + if (packet.control.ac_power != 0) { + // if AC is off display status always ON so process it only when AC is on + bool disp_status = packet.control.display_status != 0; + if (disp_status != this->get_display_state()) { + // Do something only if display status changed + if (this->mode == CLIMATE_MODE_OFF) { + // AC just turned on from remote need to turn off display + this->force_send_control_ = true; + } else if ((((uint8_t) this->health_mode_) & 0b10) == 0) { + this->display_status_ = disp_status ? SwitchState::ON : SwitchState::OFF; } } } - { - // Health mode - bool old_health_mode = this->health_mode_; - this->health_mode_ = packet.control.health_mode == 1; - should_publish = should_publish || (old_health_mode != this->health_mode_); + // Health mode + if ((((uint8_t) this->health_mode_) & 0b10) == 0) { + bool old_health_mode = this->get_health_mode(); + this->health_mode_ = packet.control.health_mode == 1 ? SwitchState::ON : SwitchState::OFF; + should_publish = should_publish || (old_health_mode != this->get_health_mode()); } { CleaningState new_cleaning; @@ -958,17 +995,36 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t * } should_publish = should_publish || (old_mode != this->mode); } + { + // Quiet mode, should be after climate mode + if ((this->mode != CLIMATE_MODE_FAN_ONLY) && (this->mode != CLIMATE_MODE_OFF) && + ((((uint8_t) this->quiet_mode_state_) & 0b10) == 0)) { + // In proper mode and not in pending state + bool new_quiet_mode = packet.control.quiet_mode != 0; + if (new_quiet_mode != this->get_quiet_mode_state()) { + this->quiet_mode_state_ = new_quiet_mode ? SwitchState::ON : SwitchState::OFF; + this->settings_.quiet_mode_state = new_quiet_mode; + this->hon_rtc_.save(&this->settings_); + } + } + } { // Swing mode ClimateSwingMode old_swing_mode = this->swing_mode; - if (packet.control.horizontal_swing_mode == (uint8_t) hon_protocol::HorizontalSwingMode::AUTO) { - if (packet.control.vertical_swing_mode == (uint8_t) hon_protocol::VerticalSwingMode::AUTO) { + const std::set &swing_modes = traits_.get_supported_swing_modes(); + bool vertical_swing_supported = swing_modes.find(CLIMATE_SWING_VERTICAL) != swing_modes.end(); + bool horizontal_swing_supported = swing_modes.find(CLIMATE_SWING_HORIZONTAL) != swing_modes.end(); + if (horizontal_swing_supported && + (packet.control.horizontal_swing_mode == (uint8_t) hon_protocol::HorizontalSwingMode::AUTO)) { + if (vertical_swing_supported && + (packet.control.vertical_swing_mode == (uint8_t) hon_protocol::VerticalSwingMode::AUTO)) { this->swing_mode = CLIMATE_SWING_BOTH; } else { this->swing_mode = CLIMATE_SWING_HORIZONTAL; } } else { - if (packet.control.vertical_swing_mode == (uint8_t) hon_protocol::VerticalSwingMode::AUTO) { + if (vertical_swing_supported && + (packet.control.vertical_swing_mode == (uint8_t) hon_protocol::VerticalSwingMode::AUTO)) { this->swing_mode = CLIMATE_SWING_VERTICAL; } else { this->swing_mode = CLIMATE_SWING_OFF; @@ -985,7 +1041,7 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t * 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_); + this->hon_rtc_.save(&this->settings_); } should_publish = should_publish || (old_swing_mode != this->swing_mode); } @@ -1017,7 +1073,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->get_beeper_state() ? ZERO_BUF : ONE_BUF, 2)); } // Health mode { @@ -1025,13 +1081,16 @@ 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->get_health_mode() ? ONE_BUF : ZERO_BUF, 2)); + this->health_mode_ = (SwitchState) ((uint8_t) this->health_mode_ & 0b01); } // Climate mode + ClimateMode climate_mode = this->mode; bool new_power = this->mode != CLIMATE_MODE_OFF; uint8_t fan_mode_buf[] = {0x00, 0xFF}; uint8_t quiet_mode_buf[] = {0x00, 0xFF}; if (climate_control.mode.has_value()) { + climate_mode = climate_control.mode.value(); uint8_t buffer[2] = {0x00, 0x00}; switch (climate_control.mode.value()) { case CLIMATE_MODE_OFF: @@ -1076,8 +1135,6 @@ void HonClimate::fill_control_messages_queue_() { (uint8_t) hon_protocol::DataParameters::AC_MODE, buffer, 2)); fan_mode_buf[1] = this->other_modes_fan_speed_; // Auto doesn't work in fan only mode - // Disabling eco mode for Fan only - quiet_mode_buf[1] = 0; break; case CLIMATE_MODE_COOL: new_power = true; @@ -1108,30 +1165,20 @@ void HonClimate::fill_control_messages_queue_() { uint8_t away_mode_buf[] = {0x00, 0xFF}; if (!new_power) { // If AC is off - no presets allowed - quiet_mode_buf[1] = 0x00; fast_mode_buf[1] = 0x00; away_mode_buf[1] = 0x00; } else if (climate_control.preset.has_value()) { switch (climate_control.preset.value()) { case CLIMATE_PRESET_NONE: - quiet_mode_buf[1] = 0x00; - fast_mode_buf[1] = 0x00; - away_mode_buf[1] = 0x00; - break; - case CLIMATE_PRESET_ECO: - // Eco is not supported in Fan only mode - quiet_mode_buf[1] = (this->mode != CLIMATE_MODE_FAN_ONLY) ? 0x01 : 0x00; fast_mode_buf[1] = 0x00; away_mode_buf[1] = 0x00; break; case CLIMATE_PRESET_BOOST: - quiet_mode_buf[1] = 0x00; // Boost is not supported in Fan only mode fast_mode_buf[1] = (this->mode != CLIMATE_MODE_FAN_ONLY) ? 0x01 : 0x00; away_mode_buf[1] = 0x00; break; case CLIMATE_PRESET_AWAY: - quiet_mode_buf[1] = 0x00; fast_mode_buf[1] = 0x00; away_mode_buf[1] = (this->mode == CLIMATE_MODE_HEAT) ? 0x01 : 0x00; break; @@ -1140,8 +1187,18 @@ void HonClimate::fill_control_messages_queue_() { break; } } + { + // Quiet mode + if (new_power && (climate_mode != CLIMATE_MODE_FAN_ONLY) && this->get_quiet_mode_state()) { + quiet_mode_buf[1] = 0x01; + } else { + quiet_mode_buf[1] = 0x00; + } + // Clean quiet mode state pending flag + this->quiet_mode_state_ = (SwitchState) ((uint8_t) this->quiet_mode_state_ & 0b01); + } auto presets = this->traits_.get_supported_presets(); - if ((quiet_mode_buf[1] != 0xFF) && ((presets.find(climate::ClimatePreset::CLIMATE_PRESET_ECO) != presets.end()))) { + if (quiet_mode_buf[1] != 0xFF) { this->control_messages_queue_.push( haier_protocol::HaierMessage(haier_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcommandsControl::SET_SINGLE_PARAMETER + diff --git a/esphome/components/haier/hon_climate.h b/esphome/components/haier/hon_climate.h index 64c54186ed..58173f8154 100644 --- a/esphome/components/haier/hon_climate.h +++ b/esphome/components/haier/hon_climate.h @@ -10,6 +10,9 @@ #ifdef USE_TEXT_SENSOR #include "esphome/components/text_sensor/text_sensor.h" #endif +#ifdef USE_SWITCH +#include "esphome/components/switch/switch.h" +#endif #include "esphome/core/automation.h" #include "haier_base.h" #include "hon_packet.h" @@ -28,6 +31,8 @@ enum class HonControlMethod { MONITOR_ONLY = 0, SET_GROUP_PARAMETERS, SET_SINGLE struct HonSettings { hon_protocol::VerticalSwingMode last_vertiacal_swing; hon_protocol::HorizontalSwingMode last_horizontal_swing; + bool beeper_state; + bool quiet_mode_state; }; class HonClimate : public HaierClimateBase { @@ -86,6 +91,15 @@ class HonClimate : public HaierClimateBase { 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 +#ifdef USE_SWITCH + public: + void set_beeper_switch(switch_::Switch *sw); + void set_quiet_mode_switch(switch_::Switch *sw); + + protected: + switch_::Switch *beeper_switch_{nullptr}; + switch_::Switch *quiet_mode_switch_{nullptr}; #endif public: HonClimate(); @@ -95,6 +109,8 @@ class HonClimate : public HaierClimateBase { void dump_config() override; void set_beeper_state(bool state); bool get_beeper_state() const; + void set_quiet_mode_state(bool state); + bool get_quiet_mode_state() const; esphome::optional get_vertical_airflow() const; void set_vertical_airflow(hon_protocol::VerticalSwingMode direction); esphome::optional get_horizontal_airflow() const; @@ -153,7 +169,6 @@ class HonClimate : public HaierClimateBase { bool functions_[5]; }; - bool beeper_status_; CleaningState cleaning_status_; bool got_valid_outdoor_temp_; esphome::optional pending_vertical_direction_{}; @@ -175,7 +190,8 @@ class HonClimate : public HaierClimateBase { esphome::optional current_vertical_swing_{}; esphome::optional current_horizontal_swing_{}; HonSettings settings_; - ESPPreferenceObject rtc_; + ESPPreferenceObject hon_rtc_; + SwitchState quiet_mode_state_{SwitchState::OFF}; }; class HaierAlarmStartTrigger : public Trigger { diff --git a/esphome/components/haier/smartair2_climate.cpp b/esphome/components/haier/smartair2_climate.cpp index 028e8a4087..63c22821b3 100644 --- a/esphome/components/haier/smartair2_climate.cpp +++ b/esphome/components/haier/smartair2_climate.cpp @@ -376,8 +376,10 @@ haier_protocol::HaierMessage Smartair2Climate::get_control_message() { } } } - out_data->display_status = this->display_status_ ? 0 : 1; - out_data->health_mode = this->health_mode_ ? 1 : 0; + out_data->display_status = this->get_display_state() ? 0 : 1; + this->display_status_ = (SwitchState) ((uint8_t) this->display_status_ & 0b01); + out_data->health_mode = this->get_health_mode() ? 1 : 0; + this->health_mode_ = (SwitchState) ((uint8_t) this->health_mode_ & 0b01); return haier_protocol::HaierMessage(haier_protocol::FrameType::CONTROL, 0x4D5F, control_out_buffer, sizeof(smartair2_protocol::HaierPacketControl)); } @@ -446,28 +448,26 @@ haier_protocol::HandlerError Smartair2Climate::process_status_message_(const uin } should_publish = should_publish || (!old_fan_mode.has_value()) || (old_fan_mode.value() != fan_mode.value()); } - { - // Display status - // should be before "Climate mode" because it is changing this->mode - if (packet.control.ac_power != 0) { - // if AC is off display status always ON so process it only when AC is on - bool disp_status = packet.control.display_status == 0; - if (disp_status != this->display_status_) { - // Do something only if display status changed - if (this->mode == CLIMATE_MODE_OFF) { - // AC just turned on from remote need to turn off display - this->force_send_control_ = true; - } else { - this->display_status_ = disp_status; - } + // Display status + // should be before "Climate mode" because it is changing this->mode + if (packet.control.ac_power != 0) { + // if AC is off display status always ON so process it only when AC is on + bool disp_status = packet.control.display_status == 0; + if (disp_status != this->get_display_state()) { + // Do something only if display status changed + if (this->mode == CLIMATE_MODE_OFF) { + // AC just turned on from remote need to turn off display + this->force_send_control_ = true; + } else if ((((uint8_t) this->health_mode_) & 0b10) == 0) { + this->display_status_ = disp_status ? SwitchState::ON : SwitchState::OFF; } } } - { - // Health mode - bool old_health_mode = this->health_mode_; - this->health_mode_ = packet.control.health_mode == 1; - should_publish = should_publish || (old_health_mode != this->health_mode_); + // Health mode + if ((((uint8_t) this->health_mode_) & 0b10) == 0) { + bool old_health_mode = this->get_health_mode(); + this->health_mode_ = packet.control.health_mode == 1 ? SwitchState::ON : SwitchState::OFF; + should_publish = should_publish || (old_health_mode != this->get_health_mode()); } { // Climate mode diff --git a/esphome/components/haier/switch/__init__.py b/esphome/components/haier/switch/__init__.py new file mode 100644 index 0000000000..6076cb0bd5 --- /dev/null +++ b/esphome/components/haier/switch/__init__.py @@ -0,0 +1,91 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +import esphome.final_validate as fv +from esphome.components import switch +from esphome.const import ( + CONF_BEEPER, + CONF_DISPLAY, + ENTITY_CATEGORY_CONFIG, +) +from ..climate import ( + CONF_HAIER_ID, + CONF_PROTOCOL, + HaierClimateBase, + haier_ns, + PROTOCOL_HON, +) + +CODEOWNERS = ["@paveldn"] +BeeperSwitch = haier_ns.class_("BeeperSwitch", switch.Switch) +HealthModeSwitch = haier_ns.class_("HealthModeSwitch", switch.Switch) +DisplaySwitch = haier_ns.class_("DisplaySwitch", switch.Switch) +QuietModeSwitch = haier_ns.class_("QuietModeSwitch", switch.Switch) + +# Haier switches +CONF_HEALTH_MODE = "health_mode" +CONF_QUIET_MODE = "quiet_mode" + +# Additional icons +ICON_LEAF = "mdi:leaf" +ICON_LED_ON = "mdi:led-on" +ICON_VOLUME_HIGH = "mdi:volume-high" +ICON_VOLUME_OFF = "mdi:volume-off" + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_HAIER_ID): cv.use_id(HaierClimateBase), + cv.Optional(CONF_DISPLAY): switch.switch_schema( + DisplaySwitch, + icon=ICON_LED_ON, + entity_category=ENTITY_CATEGORY_CONFIG, + default_restore_mode="DISABLED", + ), + cv.Optional(CONF_HEALTH_MODE): switch.switch_schema( + HealthModeSwitch, + icon=ICON_LEAF, + default_restore_mode="DISABLED", + ), + # Beeper switch is only supported for HonClimate + cv.Optional(CONF_BEEPER): switch.switch_schema( + BeeperSwitch, + icon=ICON_VOLUME_HIGH, + entity_category=ENTITY_CATEGORY_CONFIG, + default_restore_mode="DISABLED", + ), + # Quiet mode is only supported for HonClimate + cv.Optional(CONF_QUIET_MODE): switch.switch_schema( + QuietModeSwitch, + icon=ICON_VOLUME_OFF, + entity_category=ENTITY_CATEGORY_CONFIG, + default_restore_mode="DISABLED", + ), + } +) + + +def _final_validate(config): + full_config = fv.full_config.get() + for switch_type in [CONF_BEEPER, CONF_QUIET_MODE]: + # Check switches that are only supported for HonClimate + if config.get(switch_type): + climate_path = full_config.get_path_for_id(config[CONF_HAIER_ID])[:-1] + climate_conf = full_config.get_config_for_path(climate_path) + protocol_type = climate_conf.get(CONF_PROTOCOL) + if protocol_type.casefold() != PROTOCOL_HON.casefold(): + raise cv.Invalid( + f"{switch_type} switch is only supported for hon climate" + ) + return config + + +FINAL_VALIDATE_SCHEMA = _final_validate + + +async def to_code(config): + parent = await cg.get_variable(config[CONF_HAIER_ID]) + + for switch_type in [CONF_DISPLAY, CONF_HEALTH_MODE, CONF_BEEPER, CONF_QUIET_MODE]: + if conf := config.get(switch_type): + sw_var = await switch.new_switch(conf) + await cg.register_parented(sw_var, parent) + cg.add(getattr(parent, f"set_{switch_type}_switch")(sw_var)) diff --git a/esphome/components/haier/switch/beeper.cpp b/esphome/components/haier/switch/beeper.cpp new file mode 100644 index 0000000000..1ce64d0848 --- /dev/null +++ b/esphome/components/haier/switch/beeper.cpp @@ -0,0 +1,14 @@ +#include "beeper.h" + +namespace esphome { +namespace haier { + +void BeeperSwitch::write_state(bool state) { + if (this->parent_->get_beeper_state() != state) { + this->parent_->set_beeper_state(state); + } + this->publish_state(state); +} + +} // namespace haier +} // namespace esphome diff --git a/esphome/components/haier/switch/beeper.h b/esphome/components/haier/switch/beeper.h new file mode 100644 index 0000000000..7396a7a0dd --- /dev/null +++ b/esphome/components/haier/switch/beeper.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/switch/switch.h" +#include "../hon_climate.h" + +namespace esphome { +namespace haier { + +class BeeperSwitch : public switch_::Switch, public Parented { + public: + BeeperSwitch() = default; + + protected: + void write_state(bool state) override; +}; + +} // namespace haier +} // namespace esphome diff --git a/esphome/components/haier/switch/display.cpp b/esphome/components/haier/switch/display.cpp new file mode 100644 index 0000000000..5e24843dcf --- /dev/null +++ b/esphome/components/haier/switch/display.cpp @@ -0,0 +1,14 @@ +#include "display.h" + +namespace esphome { +namespace haier { + +void DisplaySwitch::write_state(bool state) { + if (this->parent_->get_display_state() != state) { + this->parent_->set_display_state(state); + } + this->publish_state(state); +} + +} // namespace haier +} // namespace esphome diff --git a/esphome/components/haier/switch/display.h b/esphome/components/haier/switch/display.h new file mode 100644 index 0000000000..f93ccfcdb7 --- /dev/null +++ b/esphome/components/haier/switch/display.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/switch/switch.h" +#include "../haier_base.h" + +namespace esphome { +namespace haier { + +class DisplaySwitch : public switch_::Switch, public Parented { + public: + DisplaySwitch() = default; + + protected: + void write_state(bool state) override; +}; + +} // namespace haier +} // namespace esphome diff --git a/esphome/components/haier/switch/health_mode.cpp b/esphome/components/haier/switch/health_mode.cpp new file mode 100644 index 0000000000..3715759bdd --- /dev/null +++ b/esphome/components/haier/switch/health_mode.cpp @@ -0,0 +1,14 @@ +#include "health_mode.h" + +namespace esphome { +namespace haier { + +void HealthModeSwitch::write_state(bool state) { + if (this->parent_->get_health_mode() != state) { + this->parent_->set_health_mode(state); + } + this->publish_state(state); +} + +} // namespace haier +} // namespace esphome diff --git a/esphome/components/haier/switch/health_mode.h b/esphome/components/haier/switch/health_mode.h new file mode 100644 index 0000000000..cfd2aa2f22 --- /dev/null +++ b/esphome/components/haier/switch/health_mode.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/switch/switch.h" +#include "../haier_base.h" + +namespace esphome { +namespace haier { + +class HealthModeSwitch : public switch_::Switch, public Parented { + public: + HealthModeSwitch() = default; + + protected: + void write_state(bool state) override; +}; + +} // namespace haier +} // namespace esphome diff --git a/esphome/components/haier/switch/quiet_mode.cpp b/esphome/components/haier/switch/quiet_mode.cpp new file mode 100644 index 0000000000..056312b5f0 --- /dev/null +++ b/esphome/components/haier/switch/quiet_mode.cpp @@ -0,0 +1,14 @@ +#include "quiet_mode.h" + +namespace esphome { +namespace haier { + +void QuietModeSwitch::write_state(bool state) { + if (this->parent_->get_quiet_mode_state() != state) { + this->parent_->set_quiet_mode_state(state); + } + this->publish_state(state); +} + +} // namespace haier +} // namespace esphome diff --git a/esphome/components/haier/switch/quiet_mode.h b/esphome/components/haier/switch/quiet_mode.h new file mode 100644 index 0000000000..bad5289500 --- /dev/null +++ b/esphome/components/haier/switch/quiet_mode.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/components/switch/switch.h" +#include "../hon_climate.h" + +namespace esphome { +namespace haier { + +class QuietModeSwitch : public switch_::Switch, public Parented { + public: + QuietModeSwitch() = default; + + protected: + void write_state(bool state) override; +}; + +} // namespace haier +} // namespace esphome diff --git a/esphome/components/hmac_md5/hmac_md5.cpp b/esphome/components/hmac_md5/hmac_md5.cpp index 90bf91882f..d766a55fab 100644 --- a/esphome/components/hmac_md5/hmac_md5.cpp +++ b/esphome/components/hmac_md5/hmac_md5.cpp @@ -1,6 +1,7 @@ #include #include #include "hmac_md5.h" +#ifdef USE_MD5 #include "esphome/core/helpers.h" namespace esphome { @@ -54,3 +55,4 @@ bool HmacMD5::equals_hex(const char *expected) { return this->ohash_.equals_hex( } // namespace hmac_md5 } // namespace esphome +#endif diff --git a/esphome/components/hmac_md5/hmac_md5.h b/esphome/components/hmac_md5/hmac_md5.h index e6a97ad2e3..b83b9d5421 100644 --- a/esphome/components/hmac_md5/hmac_md5.h +++ b/esphome/components/hmac_md5/hmac_md5.h @@ -1,8 +1,8 @@ #pragma once #include "esphome/core/defines.h" +#ifdef USE_MD5 #include "esphome/components/md5/md5.h" - #include namespace esphome { @@ -46,3 +46,4 @@ class HmacMD5 { } // namespace hmac_md5 } // namespace esphome +#endif diff --git a/esphome/components/host/__init__.py b/esphome/components/host/__init__.py index e83bf2dba8..eb8cfbd984 100644 --- a/esphome/components/host/__init__.py +++ b/esphome/components/host/__init__.py @@ -16,7 +16,7 @@ from .const import KEY_HOST from .gpio import host_pin_to_code # noqa CODEOWNERS = ["@esphome/core", "@clydebarrow"] -AUTO_LOAD = ["network"] +AUTO_LOAD = ["network", "preferences"] def set_core_data(config): diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index c01baf8644..d87d9b8a45 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -22,6 +22,63 @@ struct Header { const char *value; }; +// Some common HTTP status codes +enum HttpStatus { + HTTP_STATUS_OK = 200, + HTTP_STATUS_NO_CONTENT = 204, + HTTP_STATUS_PARTIAL_CONTENT = 206, + + /* 3xx - Redirection */ + HTTP_STATUS_MULTIPLE_CHOICES = 300, + HTTP_STATUS_MOVED_PERMANENTLY = 301, + HTTP_STATUS_FOUND = 302, + HTTP_STATUS_SEE_OTHER = 303, + HTTP_STATUS_NOT_MODIFIED = 304, + HTTP_STATUS_TEMPORARY_REDIRECT = 307, + HTTP_STATUS_PERMANENT_REDIRECT = 308, + + /* 4XX - CLIENT ERROR */ + HTTP_STATUS_BAD_REQUEST = 400, + HTTP_STATUS_UNAUTHORIZED = 401, + HTTP_STATUS_FORBIDDEN = 403, + HTTP_STATUS_NOT_FOUND = 404, + HTTP_STATUS_METHOD_NOT_ALLOWED = 405, + HTTP_STATUS_NOT_ACCEPTABLE = 406, + HTTP_STATUS_LENGTH_REQUIRED = 411, + + /* 5xx - Server Error */ + HTTP_STATUS_INTERNAL_ERROR = 500 +}; + +/** + * @brief Returns true if the HTTP status code is a redirect. + * + * @param status the HTTP status code to check + * @return true if the status code is a redirect, false otherwise + */ +inline bool is_redirect(int const status) { + switch (status) { + case HTTP_STATUS_MOVED_PERMANENTLY: + case HTTP_STATUS_FOUND: + case HTTP_STATUS_SEE_OTHER: + case HTTP_STATUS_TEMPORARY_REDIRECT: + case HTTP_STATUS_PERMANENT_REDIRECT: + return true; + default: + return false; + } +} + +/** + * @brief Checks if the given HTTP status code indicates a successful request. + * + * A successful request is one where the status code is in the range 200-299 + * + * @param status the HTTP status code to check + * @return true if the status code indicates a successful request, false otherwise + */ +inline bool is_success(int const status) { return status >= HTTP_STATUS_OK && status < HTTP_STATUS_MULTIPLE_CHOICES; } + class HttpRequestComponent; class HttpContainer : public Parented { diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp index 2148d92ad2..af1eb6f459 100644 --- a/esphome/components/http_request/http_request_arduino.cpp +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -113,11 +113,10 @@ std::shared_ptr HttpRequestArduino::start(std::string url, std::s return nullptr; } - if (container->status_code < 200 || container->status_code >= 300) { + if (!is_success(container->status_code)) { ESP_LOGE(TAG, "HTTP Request failed; URL: %s; Code: %d", url.c_str(), container->status_code); this->status_momentary_error("failed", 1000); - container->end(); - return nullptr; + // Still return the container, so it can be used to get the status code and error message } int content_length = container->client_.getSize(); diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index 3819f5544e..c6c567b620 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -6,7 +6,6 @@ #include "esphome/components/watchdog/watchdog.h" #include "esphome/core/application.h" -#include "esphome/core/defines.h" #include "esphome/core/log.h" #if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE @@ -118,20 +117,14 @@ std::shared_ptr HttpRequestIDF::start(std::string url, std::strin return nullptr; } - auto is_ok = [](int code) { return code >= HttpStatus_Ok && code < HttpStatus_MultipleChoices; }; - 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)) { + if (is_success(container->status_code)) { 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); @@ -142,9 +135,9 @@ std::shared_ptr HttpRequestIDF::start(std::string url, std::strin 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); + char redirect_url[256]{}; + if (esp_http_client_get_url(client, redirect_url, sizeof(redirect_url) - 1) == ESP_OK) { + ESP_LOGV(TAG, "redirecting to url: %s", redirect_url); } #endif err = esp_http_client_open(client, 0); @@ -157,7 +150,7 @@ std::shared_ptr HttpRequestIDF::start(std::string url, std::strin 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)) { + if (is_success(container->status_code)) { container->duration_ms = millis() - start; return container; } @@ -172,8 +165,7 @@ std::shared_ptr HttpRequestIDF::start(std::string url, std::strin 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; + return container; } int HttpContainerIDF::read(uint8_t *buf, size_t max_len) { diff --git a/esphome/components/http_request/ota/ota_http_request.cpp b/esphome/components/http_request/ota/ota_http_request.cpp index 1553de0bc1..cec30d72ec 100644 --- a/esphome/components/http_request/ota/ota_http_request.cpp +++ b/esphome/components/http_request/ota/ota_http_request.cpp @@ -106,7 +106,7 @@ uint8_t OtaHttpRequestComponent::do_ota_() { auto container = this->parent_->get(url_with_auth); - if (container == nullptr) { + if (container == nullptr || container->status_code != HTTP_STATUS_OK) { return OTA_CONNECTION_ERROR; } diff --git a/esphome/components/http_request/update/http_request_update.cpp b/esphome/components/http_request/update/http_request_update.cpp index 059148e7e5..0e0966c22b 100644 --- a/esphome/components/http_request/update/http_request_update.cpp +++ b/esphome/components/http_request/update/http_request_update.cpp @@ -31,7 +31,7 @@ void HttpRequestUpdate::setup() { void HttpRequestUpdate::update() { auto container = this->request_parent_->get(this->source_url_); - if (container == nullptr) { + if (container == nullptr || container->status_code != HTTP_STATUS_OK) { std::string msg = str_sprintf("Failed to fetch manifest from %s", this->source_url_.c_str()); this->status_set_error(msg.c_str()); return; diff --git a/esphome/components/i2c_device/__init__.py b/esphome/components/i2c_device/__init__.py new file mode 100644 index 0000000000..e145ba56f8 --- /dev/null +++ b/esphome/components/i2c_device/__init__.py @@ -0,0 +1,26 @@ +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 = ["@gabest11"] +MULTI_CONF = True + +i2c_device_ns = cg.esphome_ns.namespace("i2c_device") + +I2CDeviceComponent = i2c_device_ns.class_( + "I2CDeviceComponent", cg.Component, i2c.I2CDevice +) + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_ID): cv.declare_id(I2CDeviceComponent), + } +).extend(i2c.i2c_device_schema(None)) + + +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/i2c_device/i2c_device.cpp b/esphome/components/i2c_device/i2c_device.cpp new file mode 100644 index 0000000000..455c68fbed --- /dev/null +++ b/esphome/components/i2c_device/i2c_device.cpp @@ -0,0 +1,17 @@ +#include "i2c_device.h" +#include "esphome/core/log.h" +#include "esphome/core/hal.h" +#include + +namespace esphome { +namespace i2c_device { + +static const char *const TAG = "i2c_device"; + +void I2CDeviceComponent::dump_config() { + ESP_LOGCONFIG(TAG, "I2CDevice"); + LOG_I2C_DEVICE(this); +} + +} // namespace i2c_device +} // namespace esphome diff --git a/esphome/components/i2c_device/i2c_device.h b/esphome/components/i2c_device/i2c_device.h new file mode 100644 index 0000000000..ab118e3e89 --- /dev/null +++ b/esphome/components/i2c_device/i2c_device.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/i2c/i2c.h" + +namespace esphome { +namespace i2c_device { + +class I2CDeviceComponent : public Component, public i2c::I2CDevice { + public: + void dump_config() override; + float get_setup_priority() const override { return setup_priority::DATA; } + + protected: +}; + +} // namespace i2c_device +} // namespace esphome diff --git a/esphome/components/i2s_audio/__init__.py b/esphome/components/i2s_audio/__init__.py index 05e44696d8..d376907925 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,26 @@ 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_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" + 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 +60,75 @@ I2S_PORTS = { VARIANT_ESP32C3: 1, } +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, +} + +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, +} + +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, +): + 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 + ), + 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), + ), + } + ) + + +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])) + 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( { 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..7e2798c33d 100644 --- a/esphome/components/i2s_audio/i2s_audio.h +++ b/esphome/components/i2s_audio/i2s_audio.h @@ -11,9 +11,27 @@ 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; } + 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; } -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_; + i2s_bits_per_chan_t bits_per_channel_; + bool use_apll_; +}; + +class I2SAudioIn : public I2SAudioBase {}; + +class I2SAudioOut : public I2SAudioBase {}; class I2SAudioComponent : public Component { public: 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 844f176bea..161046e962 100644 --- a/esphome/components/i2s_audio/microphone/__init__.py +++ b/esphome/components/i2s_audio/microphone/__init__.py @@ -1,20 +1,17 @@ -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, + I2SAudioIn, + i2s_audio_component_schema, + i2s_audio_ns, + register_i2s_audio_component, ) CODEOWNERS = ["@jesserockz"] @@ -23,29 +20,14 @@ 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,21 +44,15 @@ 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, + default_sample_rate=16000, + default_channel=CONF_RIGHT, + default_bits_per_sample="32bit", + ) ).extend(cv.COMPONENT_SCHEMA) + CONFIG_SCHEMA = cv.All( cv.typed_schema( { @@ -88,7 +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_PDM, default=False): cv.boolean, } ), }, @@ -101,8 +77,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 +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_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) 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 07ca0528aa..ea3f357624 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h @@ -30,13 +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: void start_(); void stop_(); @@ -48,11 +41,6 @@ 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..dd43d6cb39 100644 --- a/esphome/components/i2s_audio/speaker/__init__.py +++ b/esphome/components/i2s_audio/speaker/__init__.py @@ -1,36 +1,53 @@ -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, CONF_MODE, CONF_TIMEOUT from .. import ( - CONF_I2S_AUDIO_ID, CONF_I2S_DOUT_PIN, - I2SAudioComponent, + CONF_LEFT, + CONF_MONO, + CONF_RIGHT, + CONF_STEREO, I2SAudioOut, + i2s_audio_component_schema, i2s_audio_ns, + register_i2s_audio_component, ) -CODEOWNERS = ["@jesserockz"] +AUTO_LOAD = ["audio"] +CODEOWNERS = ["@jesserockz", "@kahrendt"] DEPENDENCIES = ["i2s_audio"] 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" +CONF_I2S_COMM_FMT = "i2s_comm_fmt" +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"] +i2s_comm_format_t = cg.global_ns.enum("i2s_comm_format_t") +I2C_COMM_FMT_OPTIONS = { + "stand_i2s": i2s_comm_format_t.I2S_COMM_FORMAT_STAND_I2S, + "stand_msb": i2s_comm_format_t.I2S_COMM_FORMAT_STAND_MSB, + "stand_pcm_short": i2s_comm_format_t.I2S_COMM_FORMAT_STAND_PCM_SHORT, + "stand_pcm_long": i2s_comm_format_t.I2S_COMM_FORMAT_STAND_PCM_LONG, + "stand_max": i2s_comm_format_t.I2S_COMM_FORMAT_STAND_MAX, + "i2s_msb": i2s_comm_format_t.I2S_COMM_FORMAT_I2S_MSB, + "i2s_lsb": i2s_comm_format_t.I2S_COMM_FORMAT_I2S_LSB, + "pcm": i2s_comm_format_t.I2S_COMM_FORMAT_PCM, + "pcm_short": i2s_comm_format_t.I2S_COMM_FORMAT_PCM_SHORT, + "pcm_long": i2s_comm_format_t.I2S_COMM_FORMAT_PCM_LONG, +} NO_INTERNAL_DAC_VARIANTS = [esp32.const.VARIANT_ESP32S2] @@ -44,28 +61,43 @@ def validate_esp32_variant(config): return config +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="500ms" + ): cv.positive_time_period_milliseconds, + } + ) + .extend(cv.COMPONENT_SCHEMA) +) + CONFIG_SCHEMA = cv.All( cv.typed_schema( { - "internal": speaker.SPEAKER_SCHEMA.extend( + "internal": 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( + ), + "external": BASE_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 + cv.Optional(CONF_I2S_COMM_FMT, default="stand_i2s"): cv.enum( + I2C_COMM_FMT_OPTIONS, lower=True ), } - ).extend(cv.COMPONENT_SCHEMA), + ), }, key=CONF_DAC_TYPE, ), @@ -76,12 +108,12 @@ 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)) + cg.add(var.set_i2s_comm_fmt(config[CONF_I2S_COMM_FMT])) + 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 cf5a2c2766..cf6c3bbbba 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -4,6 +4,8 @@ #include +#include "esphome/components/audio/audio.h" + #include "esphome/core/application.h" #include "esphome/core/hal.h" #include "esphome/core/log.h" @@ -11,172 +13,342 @@ namespace esphome { namespace i2s_audio { -static const size_t BUFFER_COUNT = 20; +static const size_t DMA_BUFFER_SIZE = 512; +static const size_t DMA_BUFFERS_COUNT = 4; +static const size_t FRAMES_IN_ALL_DMA_BUFFERS = DMA_BUFFER_SIZE * DMA_BUFFERS_COUNT; +static const size_t RING_BUFFER_SAMPLES = 8192; +static const size_t TASK_DELAY_MS = 10; +static const size_t TASK_STACK_SIZE = 4096; +static const ssize_t TASK_PRIORITY = 23; static const char *const TAG = "i2s_audio.speaker"; +enum SpeakerEventGroupBits : uint32_t { + COMMAND_START = (1 << 0), // Starts the main task purpose + COMMAND_STOP = (1 << 1), // stops the main task + COMMAND_STOP_GRACEFULLY = (1 << 2), // Stops the task once all data has been written + MESSAGE_RING_BUFFER_AVAILABLE_TO_WRITE = (1 << 5), // Locks the ring buffer when not set + STATE_STARTING = (1 << 10), + STATE_RUNNING = (1 << 11), + STATE_STOPPING = (1 << 12), + STATE_STOPPED = (1 << 13), + ERR_INVALID_FORMAT = (1 << 14), + ERR_TASK_FAILED_TO_START = (1 << 15), + ERR_ESP_INVALID_STATE = (1 << 16), + ERR_ESP_INVALID_ARG = (1 << 17), + ERR_ESP_INVALID_SIZE = (1 << 18), + ERR_ESP_NO_MEM = (1 << 19), + ERR_ESP_FAIL = (1 << 20), + ALL_ERR_ESP_BITS = ERR_ESP_INVALID_STATE | ERR_ESP_INVALID_ARG | ERR_ESP_INVALID_SIZE | ERR_ESP_NO_MEM | ERR_ESP_FAIL, + ALL_BITS = 0x00FFFFFF, // All valid FreeRTOS event group bits +}; + +// Translates a SpeakerEventGroupBits ERR_ESP bit to the coressponding esp_err_t +static esp_err_t err_bit_to_esp_err(uint32_t bit) { + switch (bit) { + case SpeakerEventGroupBits::ERR_ESP_INVALID_STATE: + return ESP_ERR_INVALID_STATE; + case SpeakerEventGroupBits::ERR_ESP_INVALID_ARG: + return ESP_ERR_INVALID_ARG; + case SpeakerEventGroupBits::ERR_ESP_INVALID_SIZE: + return ESP_ERR_INVALID_SIZE; + case SpeakerEventGroupBits::ERR_ESP_NO_MEM: + return ESP_ERR_NO_MEM; + default: + return ESP_FAIL; + } +} + +/// @brief Multiplies the input array of Q15 numbers by a Q15 constant factor +/// +/// Based on `dsps_mulc_s16_ansi` from the esp-dsp library: +/// https://github.com/espressif/esp-dsp/blob/master/modules/math/mulc/fixed/dsps_mulc_s16_ansi.c +/// (accessed on 2024-09-30). +/// @param input Array of Q15 numbers +/// @param output Array of Q15 numbers +/// @param len Length of array +/// @param c Q15 constant factor +static void q15_multiplication(const int16_t *input, int16_t *output, size_t len, int16_t c) { + for (int i = 0; i < len; i++) { + int32_t acc = (int32_t) input[i] * (int32_t) c; + output[i] = (int16_t) (acc >> 15); + } +} + +// Lists the Q15 fixed point scaling factor for volume reduction. +// Has 100 values representing silence and a reduction [49, 48.5, ... 0.5, 0] dB. +// dB to PCM scaling factor formula: floating_point_scale_factor = 2^(-db/6.014) +// float to Q15 fixed point formula: q15_scale_factor = floating_point_scale_factor * 2^(15) +static const std::vector Q15_VOLUME_SCALING_FACTORS = { + 0, 116, 122, 130, 137, 146, 154, 163, 173, 183, 194, 206, 218, 231, 244, + 259, 274, 291, 308, 326, 345, 366, 388, 411, 435, 461, 488, 517, 548, 580, + 615, 651, 690, 731, 774, 820, 868, 920, 974, 1032, 1094, 1158, 1227, 1300, 1377, + 1459, 1545, 1637, 1734, 1837, 1946, 2061, 2184, 2313, 2450, 2596, 2750, 2913, 3085, 3269, + 3462, 3668, 3885, 4116, 4360, 4619, 4893, 5183, 5490, 5816, 6161, 6527, 6914, 7324, 7758, + 8218, 8706, 9222, 9770, 10349, 10963, 11613, 12302, 13032, 13805, 14624, 15491, 16410, 17384, 18415, + 19508, 20665, 21891, 23189, 24565, 26022, 27566, 29201, 30933, 32767}; + 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; + if (this->event_group_ == nullptr) { + this->event_group_ = xEventGroupCreate(); } - this->event_queue_ = xQueueCreate(BUFFER_COUNT, sizeof(TaskEvent)); - if (this->event_queue_ == nullptr) { - ESP_LOGE(TAG, "Failed to create event queue"); + if (this->event_group_ == nullptr) { + ESP_LOGE(TAG, "Failed to create event group"); this->mark_failed(); return; } } +void I2SAudioSpeaker::loop() { + uint32_t event_group_bits = xEventGroupGetBits(this->event_group_); + + if (event_group_bits & SpeakerEventGroupBits::STATE_STARTING) { + ESP_LOGD(TAG, "Starting Speaker"); + this->state_ = speaker::STATE_STARTING; + xEventGroupClearBits(this->event_group_, SpeakerEventGroupBits::STATE_STARTING); + } + if (event_group_bits & SpeakerEventGroupBits::STATE_RUNNING) { + ESP_LOGD(TAG, "Started Speaker"); + this->state_ = speaker::STATE_RUNNING; + xEventGroupClearBits(this->event_group_, SpeakerEventGroupBits::STATE_RUNNING); + this->status_clear_warning(); + this->status_clear_error(); + } + if (event_group_bits & SpeakerEventGroupBits::STATE_STOPPING) { + ESP_LOGD(TAG, "Stopping Speaker"); + this->state_ = speaker::STATE_STOPPING; + xEventGroupClearBits(this->event_group_, SpeakerEventGroupBits::STATE_STOPPING); + } + if (event_group_bits & SpeakerEventGroupBits::STATE_STOPPED) { + if (!this->task_created_) { + ESP_LOGD(TAG, "Stopped Speaker"); + this->state_ = speaker::STATE_STOPPED; + xEventGroupClearBits(this->event_group_, SpeakerEventGroupBits::ALL_BITS); + this->speaker_task_handle_ = nullptr; + } + } + + if (event_group_bits & SpeakerEventGroupBits::ERR_TASK_FAILED_TO_START) { + this->status_set_error("Failed to start speaker task"); + xEventGroupClearBits(this->event_group_, SpeakerEventGroupBits::ERR_TASK_FAILED_TO_START); + } + + if (event_group_bits & SpeakerEventGroupBits::ERR_INVALID_FORMAT) { + this->status_set_error("Failed to adjust I2S bus to match the incoming audio"); + ESP_LOGE(TAG, + "Incompatible audio format: sample rate = %" PRIu32 ", channels = %" PRIu8 ", bits per sample = %" PRIu8, + this->audio_stream_info_.sample_rate, this->audio_stream_info_.channels, + this->audio_stream_info_.bits_per_sample); + } + + if (event_group_bits & SpeakerEventGroupBits::ALL_ERR_ESP_BITS) { + uint32_t error_bits = event_group_bits & SpeakerEventGroupBits::ALL_ERR_ESP_BITS; + ESP_LOGW(TAG, "Error writing to I2S: %s", esp_err_to_name(err_bit_to_esp_err(error_bits))); + this->status_set_warning(); + } +} + +void I2SAudioSpeaker::set_volume(float volume) { + this->volume_ = volume; +#ifdef USE_AUDIO_DAC + if (this->audio_dac_ != nullptr) { + if (volume > 0.0) { + this->audio_dac_->set_mute_off(); + } + this->audio_dac_->set_volume(volume); + } else +#endif + { + // Fallback to software volume control by using a Q15 fixed point scaling factor + ssize_t decibel_index = remap(volume, 0.0f, 1.0f, 0, Q15_VOLUME_SCALING_FACTORS.size() - 1); + this->q15_volume_factor_ = Q15_VOLUME_SCALING_FACTORS[decibel_index]; + } +} + +void I2SAudioSpeaker::set_mute_state(bool mute_state) { + this->mute_state_ = mute_state; +#ifdef USE_AUDIO_DAC + if (this->audio_dac_) { + if (mute_state) { + this->audio_dac_->set_mute_on(); + } else { + this->audio_dac_->set_mute_off(); + } + } else +#endif + { + if (mute_state) { + // Fallback to software volume control and scale by 0 + this->q15_volume_factor_ = 0; + } else { + // Revert to previous volume when unmuting + this->set_volume(this->volume_); + } + } +} + +size_t I2SAudioSpeaker::play(const uint8_t *data, size_t length, TickType_t ticks_to_wait) { + 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(); + } + + // Wait for the ring buffer to be available + uint32_t event_bits = + xEventGroupWaitBits(this->event_group_, SpeakerEventGroupBits::MESSAGE_RING_BUFFER_AVAILABLE_TO_WRITE, pdFALSE, + pdFALSE, pdMS_TO_TICKS(TASK_DELAY_MS)); + + if (event_bits & SpeakerEventGroupBits::MESSAGE_RING_BUFFER_AVAILABLE_TO_WRITE) { + // Ring buffer is available to write + + // Lock the ring buffer, write to it, then unlock it + xEventGroupClearBits(this->event_group_, SpeakerEventGroupBits::MESSAGE_RING_BUFFER_AVAILABLE_TO_WRITE); + size_t bytes_written = this->audio_ring_buffer_->write_without_replacement((void *) data, length, ticks_to_wait); + xEventGroupSetBits(this->event_group_, SpeakerEventGroupBits::MESSAGE_RING_BUFFER_AVAILABLE_TO_WRITE); + + return bytes_written; + } + + return 0; +} + +bool I2SAudioSpeaker::has_buffered_data() const { + if (this->audio_ring_buffer_ != nullptr) { + return this->audio_ring_buffer_->available() > 0; + } + return false; +} + +void I2SAudioSpeaker::speaker_task(void *params) { + I2SAudioSpeaker *this_speaker = (I2SAudioSpeaker *) params; + uint32_t event_group_bits = + xEventGroupWaitBits(this_speaker->event_group_, + SpeakerEventGroupBits::COMMAND_START | SpeakerEventGroupBits::COMMAND_STOP | + SpeakerEventGroupBits::COMMAND_STOP_GRACEFULLY, // Bit message to read + pdTRUE, // Clear the bits on exit + pdFALSE, // Don't wait for all the bits, + portMAX_DELAY); // Block indefinitely until a bit is set + + if (event_group_bits & (SpeakerEventGroupBits::COMMAND_STOP | SpeakerEventGroupBits::COMMAND_STOP_GRACEFULLY)) { + // Received a stop signal before the task was requested to start + this_speaker->delete_task_(0); + } + + xEventGroupSetBits(this_speaker->event_group_, SpeakerEventGroupBits::STATE_STARTING); + + audio::AudioStreamInfo audio_stream_info = this_speaker->audio_stream_info_; + const ssize_t bytes_per_sample = audio_stream_info.get_bytes_per_sample(); + const uint8_t number_of_channels = audio_stream_info.channels; + + const size_t dma_buffers_size = FRAMES_IN_ALL_DMA_BUFFERS * bytes_per_sample * number_of_channels; + + if (this_speaker->send_esp_err_to_event_group_( + this_speaker->allocate_buffers_(dma_buffers_size, RING_BUFFER_SAMPLES * bytes_per_sample))) { + // Failed to allocate buffers + xEventGroupSetBits(this_speaker->event_group_, SpeakerEventGroupBits::ERR_ESP_NO_MEM); + this_speaker->delete_task_(dma_buffers_size); + } + + if (this_speaker->send_esp_err_to_event_group_(this_speaker->start_i2s_driver_())) { + // Failed to start I2S driver + this_speaker->delete_task_(dma_buffers_size); + } else { + // Ring buffer is allocated, so indicate its can be written to + xEventGroupSetBits(this_speaker->event_group_, SpeakerEventGroupBits::MESSAGE_RING_BUFFER_AVAILABLE_TO_WRITE); + } + + if (!this_speaker->send_esp_err_to_event_group_(this_speaker->reconfigure_i2s_stream_info_(audio_stream_info))) { + // Successfully set the I2S stream info, ready to write audio data to the I2S port + + xEventGroupSetBits(this_speaker->event_group_, SpeakerEventGroupBits::STATE_RUNNING); + + bool stop_gracefully = false; + uint32_t last_data_received_time = millis(); + + while ((millis() - last_data_received_time) <= this_speaker->timeout_) { + event_group_bits = xEventGroupGetBits(this_speaker->event_group_); + + if (event_group_bits & SpeakerEventGroupBits::COMMAND_STOP) { + break; + } + if (event_group_bits & SpeakerEventGroupBits::COMMAND_STOP_GRACEFULLY) { + stop_gracefully = true; + } + + size_t bytes_to_read = dma_buffers_size; + size_t bytes_read = this_speaker->audio_ring_buffer_->read((void *) this_speaker->data_buffer_, bytes_to_read, + pdMS_TO_TICKS(TASK_DELAY_MS)); + + if (bytes_read > 0) { + last_data_received_time = millis(); + size_t bytes_written = 0; + + if ((audio_stream_info.bits_per_sample == 16) && (this_speaker->q15_volume_factor_ < INT16_MAX)) { + // Scale samples by the volume factor in place + q15_multiplication((int16_t *) this_speaker->data_buffer_, (int16_t *) this_speaker->data_buffer_, + bytes_read / sizeof(int16_t), this_speaker->q15_volume_factor_); + } + + if (audio_stream_info.bits_per_sample == (uint8_t) this_speaker->bits_per_sample_) { + i2s_write(this_speaker->parent_->get_port(), this_speaker->data_buffer_, bytes_read, &bytes_written, + portMAX_DELAY); + } else if (audio_stream_info.bits_per_sample < (uint8_t) this_speaker->bits_per_sample_) { + i2s_write_expand(this_speaker->parent_->get_port(), this_speaker->data_buffer_, bytes_read, + audio_stream_info.bits_per_sample, this_speaker->bits_per_sample_, &bytes_written, + portMAX_DELAY); + } + + if (bytes_written != bytes_read) { + xEventGroupSetBits(this_speaker->event_group_, SpeakerEventGroupBits::ERR_ESP_INVALID_SIZE); + } + + } else { + // No data received + + if (stop_gracefully) { + break; + } + + i2s_zero_dma_buffer(this_speaker->parent_->get_port()); + } + } + } else { + // Couldn't configure the I2S port to be compatible with the incoming audio + xEventGroupSetBits(this_speaker->event_group_, SpeakerEventGroupBits::ERR_INVALID_FORMAT); + } + i2s_zero_dma_buffer(this_speaker->parent_->get_port()); + + xEventGroupSetBits(this_speaker->event_group_, SpeakerEventGroupBits::STATE_STOPPING); + + i2s_stop(this_speaker->parent_->get_port()); + i2s_driver_uninstall(this_speaker->parent_->get_port()); + + this_speaker->parent_->unlock(); + this_speaker->delete_task_(dma_buffers_size); +} + void I2SAudioSpeaker::start() { - if (this->is_failed()) { - ESP_LOGE(TAG, "Cannot start audio, speaker failed to setup"); + if (this->is_failed() || this->status_has_error()) return; - } - if (this->task_created_) { - ESP_LOGW(TAG, "Called start while task has been already created."); + if ((this->state_ == speaker::STATE_STARTING) || (this->state_ == speaker::STATE_RUNNING)) 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 + + if (this->speaker_task_handle_ == nullptr) { + xTaskCreate(I2SAudioSpeaker::speaker_task, "speaker_task", TASK_STACK_SIZE, (void *) this, TASK_PRIORITY, + &this->speaker_task_handle_); } - xTaskCreate(I2SAudioSpeaker::player_task, "speaker_task", 8192, (void *) this, 1, &this->player_task_handle_); - this->task_created_ = true; -} - -void I2SAudioSpeaker::player_task(void *params) { - I2SAudioSpeaker *this_speaker = (I2SAudioSpeaker *) params; - - TaskEvent event; - event.type = TaskEventType::STARTING; - 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, - .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, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - .bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT, - }; -#if SOC_I2S_SUPPORTS_DAC - if (this_speaker->internal_dac_mode_ != I2S_DAC_CHANNEL_DISABLE) { - config.mode = (i2s_mode_t) (config.mode | I2S_MODE_DAC_BUILT_IN); - } -#endif - - esp_err_t err = i2s_driver_install(this_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) { -#endif - i2s_pin_config_t pin_config = this_speaker->parent_->get_pin_config(); - pin_config.data_out_num = this_speaker->dout_pin_; - - i2s_set_pin(this_speaker->parent_->get_port(), &pin_config); -#if SOC_I2S_SUPPORTS_DAC + if (this->speaker_task_handle_ != nullptr) { + xEventGroupSetBits(this->event_group_, SpeakerEventGroupBits::COMMAND_START); + this->task_created_ = true; } else { - i2s_set_dac_mode(this_speaker->internal_dac_mode_); - } -#endif - - DataEvent data_event; - - event.type = TaskEventType::STARTED; - xQueueSend(this_speaker->event_queue_, &event, portMAX_DELAY); - - int16_t buffer[BUFFER_SIZE / 2]; - - while (true) { - if (xQueueReceive(this_speaker->buffer_queue_, &data_event, 100 / portTICK_PERIOD_MS) != pdTRUE) { - break; // End of audio from main thread - } - if (data_event.stop) { - // Stop signal from main thread - 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; - - 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)); - if (err != ESP_OK) { - event = {.type = TaskEventType::WARNING, .err = err}; - 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--; - 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"); - } - } - - 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()); - - i2s_driver_uninstall(this_speaker->parent_->get_port()); - - event.type = TaskEventType::STOPPED; - if (xQueueSend(this_speaker->event_queue_, &event, 10 / portTICK_PERIOD_MS) != pdTRUE) { - ESP_LOGW(TAG, "Failed to send STOPPED event"); - } - - while (true) { - delay(10); + xEventGroupSetBits(this->event_group_, SpeakerEventGroupBits::ERR_TASK_FAILED_TO_START); } } @@ -189,94 +361,169 @@ void I2SAudioSpeaker::stop_(bool wait_on_empty) { return; if (this->state_ == speaker::STATE_STOPPED) return; - if (this->state_ == speaker::STATE_STARTING) { - this->state_ = speaker::STATE_STOPPED; - return; - } - this->state_ = speaker::STATE_STOPPING; - DataEvent data; - data.stop = true; + if (wait_on_empty) { - xQueueSend(this->buffer_queue_, &data, portMAX_DELAY); + xEventGroupSetBits(this->event_group_, SpeakerEventGroupBits::COMMAND_STOP_GRACEFULLY); } else { - xQueueSendToFront(this->buffer_queue_, &data, portMAX_DELAY); + xEventGroupSetBits(this->event_group_, SpeakerEventGroupBits::COMMAND_STOP); } } -void I2SAudioSpeaker::watch_() { - TaskEvent event; - 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"); - this->state_ = speaker::STATE_RUNNING; - 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_); - this->task_created_ = false; - 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)); - this->status_set_warning(); - break; - } +bool I2SAudioSpeaker::send_esp_err_to_event_group_(esp_err_t err) { + switch (err) { + case ESP_OK: + return false; + case ESP_ERR_INVALID_STATE: + xEventGroupSetBits(this->event_group_, SpeakerEventGroupBits::ERR_ESP_INVALID_STATE); + return true; + case ESP_ERR_INVALID_ARG: + xEventGroupSetBits(this->event_group_, SpeakerEventGroupBits::ERR_ESP_INVALID_ARG); + return true; + case ESP_ERR_INVALID_SIZE: + xEventGroupSetBits(this->event_group_, SpeakerEventGroupBits::ERR_ESP_INVALID_SIZE); + return true; + case ESP_ERR_NO_MEM: + xEventGroupSetBits(this->event_group_, SpeakerEventGroupBits::ERR_ESP_NO_MEM); + return true; + default: + xEventGroupSetBits(this->event_group_, SpeakerEventGroupBits::ERR_ESP_FAIL); + return true; } } -void I2SAudioSpeaker::loop() { - switch (this->state_) { - case speaker::STATE_STARTING: - this->start_(); - [[fallthrough]]; - case speaker::STATE_RUNNING: - case speaker::STATE_STOPPING: - this->watch_(); - break; - case speaker::STATE_STOPPED: - break; +esp_err_t I2SAudioSpeaker::allocate_buffers_(size_t data_buffer_size, size_t ring_buffer_size) { + if (this->data_buffer_ == nullptr) { + // Allocate data buffer for temporarily storing audio from the ring buffer before writing to the I2S bus + ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); + this->data_buffer_ = allocator.allocate(data_buffer_size); } + + if (this->data_buffer_ == nullptr) { + return ESP_ERR_NO_MEM; + } + + if (this->audio_ring_buffer_ == nullptr) { + // Allocate ring buffer + this->audio_ring_buffer_ = RingBuffer::create(ring_buffer_size); + } + + if (this->audio_ring_buffer_ == nullptr) { + return ESP_ERR_NO_MEM; + } + + return ESP_OK; } -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; +esp_err_t I2SAudioSpeaker::start_i2s_driver_() { + if (!this->parent_->try_lock()) { + return ESP_ERR_INVALID_STATE; } - if (this->state_ != speaker::STATE_RUNNING && this->state_ != speaker::STATE_STARTING) { - this->start(); + + i2s_driver_config_t config = { + .mode = (i2s_mode_t) (this->i2s_mode_ | I2S_MODE_TX), + .sample_rate = this->sample_rate_, + .bits_per_sample = this->bits_per_sample_, + .channel_format = this->channel_, + .communication_format = this->i2s_comm_fmt_, + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, + .dma_buf_count = DMA_BUFFERS_COUNT, + .dma_buf_len = DMA_BUFFER_SIZE, + .use_apll = this->use_apll_, + .tx_desc_auto_clear = true, + .fixed_mclk = I2S_PIN_NO_CHANGE, + .mclk_multiple = I2S_MCLK_MULTIPLE_256, + .bits_per_chan = this->bits_per_channel_, +#if SOC_I2S_SUPPORTS_TDM + .chan_mask = (i2s_channel_t) (I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1), + .total_chan = 2, + .left_align = false, + .big_edin = false, + .bit_order_msb = false, + .skip_msk = false, +#endif + }; +#if SOC_I2S_SUPPORTS_DAC + if (this->internal_dac_mode_ != I2S_DAC_CHANNEL_DISABLE) { + config.mode = (i2s_mode_t) (config.mode | I2S_MODE_DAC_BUILT_IN); } - size_t remaining = length; - size_t index = 0; - while (remaining > 0) { - DataEvent event; - event.stop = false; - size_t to_send_length = std::min(remaining, BUFFER_SIZE); - event.len = to_send_length; - memcpy(event.data, data + index, to_send_length); - if (xQueueSend(this->buffer_queue_, &event, 0) != pdTRUE) { - return index; - } - remaining -= to_send_length; - index += to_send_length; +#endif + + esp_err_t err = i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr); + if (err != ESP_OK) { + // Failed to install the driver, so unlock the I2S port + this->parent_->unlock(); + return err; } - return index; + +#if SOC_I2S_SUPPORTS_DAC + if (this->internal_dac_mode_ == I2S_DAC_CHANNEL_DISABLE) { +#endif + i2s_pin_config_t pin_config = this->parent_->get_pin_config(); + pin_config.data_out_num = this->dout_pin_; + + err = i2s_set_pin(this->parent_->get_port(), &pin_config); +#if SOC_I2S_SUPPORTS_DAC + } else { + i2s_set_dac_mode(this->internal_dac_mode_); + } +#endif + + if (err != ESP_OK) { + // Failed to set the data out pin, so uninstall the driver and unlock the I2S port + i2s_driver_uninstall(this->parent_->get_port()); + this->parent_->unlock(); + } + + return err; } -bool I2SAudioSpeaker::has_buffered_data() const { return uxQueueMessagesWaiting(this->buffer_queue_) > 0; } +esp_err_t I2SAudioSpeaker::reconfigure_i2s_stream_info_(audio::AudioStreamInfo &audio_stream_info) { + if (this->i2s_mode_ & I2S_MODE_MASTER) { + // ESP controls for the the I2S bus, so adjust the sample rate and bits per sample to match the incoming audio + this->sample_rate_ = audio_stream_info.sample_rate; + this->bits_per_sample_ = (i2s_bits_per_sample_t) audio_stream_info.bits_per_sample; + } else if (this->sample_rate_ != audio_stream_info.sample_rate) { + // Can't reconfigure I2S bus, so the sample rate must match the configured value + return ESP_ERR_INVALID_ARG; + } + + if ((i2s_bits_per_sample_t) audio_stream_info.bits_per_sample > this->bits_per_sample_) { + // Currently can't handle the case when the incoming audio has more bits per sample than the configured value + return ESP_ERR_INVALID_ARG; + } + + if (audio_stream_info.channels == 1) { + return i2s_set_clk(this->parent_->get_port(), this->sample_rate_, this->bits_per_sample_, I2S_CHANNEL_MONO); + } else if (audio_stream_info.channels == 2) { + return i2s_set_clk(this->parent_->get_port(), this->sample_rate_, this->bits_per_sample_, I2S_CHANNEL_STEREO); + } + + return ESP_ERR_INVALID_ARG; +} + +void I2SAudioSpeaker::delete_task_(size_t buffer_size) { + if (this->audio_ring_buffer_ != nullptr) { + xEventGroupWaitBits(this->event_group_, + MESSAGE_RING_BUFFER_AVAILABLE_TO_WRITE, // Bit message to read + pdFALSE, // Don't clear the bits on exit + pdTRUE, // Don't wait for all the bits, + portMAX_DELAY); // Block indefinitely until a command bit is set + + this->audio_ring_buffer_.reset(); // Deallocates the ring buffer stored in the unique_ptr + this->audio_ring_buffer_ = nullptr; + } + + if (this->data_buffer_ != nullptr) { + ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); + allocator.deallocate(this->data_buffer_, buffer_size); + this->data_buffer_ = nullptr; + } + + xEventGroupSetBits(this->event_group_, SpeakerEventGroupBits::STATE_STOPPED); + + this->task_created_ = false; + vTaskDelete(nullptr); +} } // namespace i2s_audio } // namespace esphome diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h index 0bdb67ceba..3c512d4d4d 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h @@ -5,78 +5,132 @@ #include "../i2s_audio.h" #include -#include -#include +#include +#include + +#include "esphome/components/audio/audio.h" #include "esphome/components/speaker/speaker.h" + #include "esphome/core/component.h" #include "esphome/core/gpio.h" #include "esphome/core/helpers.h" +#include "esphome/core/ring_buffer.h" namespace esphome { namespace i2s_audio { -static const size_t BUFFER_SIZE = 1024; - -enum class TaskEventType : uint8_t { - STARTING = 0, - STARTED, - PLAYING, - STOPPING, - STOPPED, - WARNING = 255, -}; - -struct TaskEvent { - TaskEventType type; - esp_err_t err; -}; - -struct DataEvent { - bool stop; - size_t len; - 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; } 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; } #endif - void set_external_dac_channels(uint8_t channels) { this->external_dac_channels_ = channels; } + void set_i2s_comm_fmt(i2s_comm_format_t mode) { this->i2s_comm_fmt_ = mode; } void start() override; void stop() override; void finish() override; - size_t play(const uint8_t *data, size_t length) override; + /// @brief Plays the provided audio data. + /// Starts the speaker task, if necessary. Writes the audio data to the ring buffer. + /// @param data Audio data in the format set by the parent speaker classes ``set_audio_stream_info`` method. + /// @param length The length of the audio data in bytes. + /// @param ticks_to_wait The FreeRTOS ticks to wait before writing as much data as possible to the ring buffer. + /// @return The number of bytes that were actually written to the ring buffer. + size_t play(const uint8_t *data, size_t length, TickType_t ticks_to_wait) override; + size_t play(const uint8_t *data, size_t length) override { return play(data, length, 0); } bool has_buffered_data() const override; + /// @brief Sets the volume of the speaker. Uses the speaker's configured audio dac component. If unavailble, it is + /// implemented as a software volume control. Overrides the default setter to convert the floating point volume to a + /// Q15 fixed-point factor. + /// @param volume between 0.0 and 1.0 + void set_volume(float volume) override; + + /// @brief Mutes or unmute the speaker. Uses the speaker's configured audio dac component. If unavailble, it is + /// implemented as a software volume control. Overrides the default setter to convert the floating point volume to a + /// Q15 fixed-point factor. + /// @param mute_state true for muting, false for unmuting + void set_mute_state(bool mute_state) override; + protected: - void start_(); + /// @brief Function for the FreeRTOS task handling audio output. + /// After receiving the COMMAND_START signal, allocates space for the buffers, starts the I2S driver, and reads + /// audio from the ring buffer and writes audio to the I2S port. Stops immmiately after receiving the COMMAND_STOP + /// signal and stops only after the ring buffer is empty after receiving the COMMAND_STOP_GRACEFULLY signal. Stops if + /// the ring buffer hasn't read data for more than timeout_ milliseconds. When stopping, it deallocates the buffers, + /// stops the I2S driver, unlocks the I2S port, and deletes the task. It communicates the state and any errors via + /// event_group_. + /// @param params I2SAudioSpeaker component + static void speaker_task(void *params); + + /// @brief Sends a stop command to the speaker task via event_group_. + /// @param wait_on_empty If false, sends the COMMAND_STOP signal. If true, sends the COMMAND_STOP_GRACEFULLY signal. void stop_(bool wait_on_empty); - void watch_(); - static void player_task(void *params); + /// @brief Sets the corresponding ERR_ESP event group bits. + /// @param err esp_err_t error code. + /// @return True if an ERR_ESP bit is set and false if err == ESP_OK + bool send_esp_err_to_event_group_(esp_err_t err); - TaskHandle_t player_task_handle_{nullptr}; - QueueHandle_t buffer_queue_; - QueueHandle_t event_queue_; + /// @brief Allocates the data buffer and ring buffer + /// @param data_buffer_size Number of bytes to allocate for the data buffer. + /// @param ring_buffer_size Number of bytes to allocate for the ring buffer. + /// @return ESP_ERR_NO_MEM if either buffer fails to allocate + /// ESP_OK if successful + esp_err_t allocate_buffers_(size_t data_buffer_size, size_t ring_buffer_size); + + /// @brief Starts the ESP32 I2S driver. + /// Attempts to lock the I2S port, starts the I2S driver, and sets the data out pin. If it fails, it will unlock + /// the I2S port and uninstall the driver, if necessary. + /// @return ESP_ERR_INVALID_STATE if the I2S port is already locked. + /// ESP_ERR_INVALID_ARG if installing the driver or setting the data out pin fails due to a parameter error. + /// ESP_ERR_NO_MEM if the driver fails to install due to a memory allocation error. + /// ESP_FAIL if setting the data out pin fails due to an IO error + /// ESP_OK if successful + esp_err_t start_i2s_driver_(); + + /// @brief Adjusts the I2S driver configuration to match the incoming audio stream. + /// Modifies I2S driver's sample rate, bits per sample, and number of channel settings. If the I2S is in secondary + /// mode, it only modifies the number of channels. + /// @param audio_stream_info Describes the incoming audio stream + /// @return ESP_ERR_INVALID_ARG if there is a parameter error, if there is more than 2 channels in the stream, or if + /// the audio settings are incompatible with the configuration. + /// ESP_ERR_NO_MEM if the driver fails to reconfigure due to a memory allocation error. + /// ESP_OK if successful. + esp_err_t reconfigure_i2s_stream_info_(audio::AudioStreamInfo &audio_stream_info); + + /// @brief Deletes the speaker's task. + /// Deallocates the data_buffer_ and audio_ring_buffer_, if necessary, and deletes the task. Should only be called by + /// the speaker_task itself. + /// @param buffer_size The allocated size of the data_buffer_. + void delete_task_(size_t buffer_size); + + TaskHandle_t speaker_task_handle_{nullptr}; + EventGroupHandle_t event_group_{nullptr}; + + uint8_t *data_buffer_; + std::unique_ptr audio_ring_buffer_; + + uint32_t timeout_; + uint8_t dout_pin_; - uint8_t dout_pin_{0}; bool task_created_{false}; + int16_t q15_volume_factor_{INT16_MAX}; + #if SOC_I2S_SUPPORTS_DAC i2s_dac_mode_t internal_dac_mode_{I2S_DAC_CHANNEL_DISABLE}; #endif - uint8_t external_dac_channels_; + i2s_comm_format_t i2s_comm_fmt_; }; } // namespace i2s_audio diff --git a/esphome/components/ili9xxx/display.py b/esphome/components/ili9xxx/display.py index 2182ca9a6d..68e3aa953d 100644 --- a/esphome/components/ili9xxx/display.py +++ b/esphome/components/ili9xxx/display.py @@ -10,6 +10,7 @@ from esphome.const import ( CONF_DIMENSIONS, CONF_HEIGHT, CONF_ID, + CONF_INIT_SEQUENCE, CONF_INVERT_COLORS, CONF_LAMBDA, CONF_MIRROR_X, @@ -89,7 +90,6 @@ 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): diff --git a/esphome/components/ili9xxx/ili9xxx_display.h b/esphome/components/ili9xxx/ili9xxx_display.h index 5033f702de..c141739d2a 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.h +++ b/esphome/components/ili9xxx/ili9xxx_display.h @@ -89,6 +89,7 @@ class ILI9XXXDisplay : public display::DisplayBuffer, void dump_config() override; void setup() override; + void on_shutdown() override { this->command(ILI9XXX_SLPIN); } display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_COLOR; } void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorOrder order, diff --git a/esphome/components/image/__init__.py b/esphome/components/image/__init__.py index e5a205f1e0..8742540067 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 +import puremagic + +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, @@ -238,13 +237,12 @@ 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 + # Local imports only to allow "validate_pillow_installed" to run *before* importing it + # cairosvg 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,14 +272,16 @@ 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() except Exception as e: raise core.EsphomeError(f"Could not load image file {path}: {e}") - mime = Magic(mime=True) - file_type = mime.from_buffer(file_contents) + file_type = puremagic.from_string(file_contents, mime=True) resize = config.get(CONF_RESIZE) if "svg" in file_type: @@ -361,24 +361,21 @@ async def to_code(config): elif config[CONF_TYPE] in ["RGB565"]: image = image.convert("RGBA") pixels = list(image.getdata()) - data = [0 for _ in range(height * width * 2)] + bytes_per_pixel = 3 if transparent else 2 + data = [0 for _ in range(height * width * bytes_per_pixel)] pos = 0 for r, g, b, a in pixels: R = r >> 3 G = g >> 2 B = b >> 3 rgb = (R << 11) | (G << 5) | B - - if transparent: - if rgb == 0x0020: - rgb = 0 - if a < 0x80: - rgb = 0x0020 - data[pos] = rgb >> 8 pos += 1 data[pos] = rgb & 0xFF pos += 1 + if transparent: + data[pos] = a + pos += 1 elif config[CONF_TYPE] in ["BINARY", "TRANSPARENT_BINARY"]: if transparent: diff --git a/esphome/components/image/image.cpp b/esphome/components/image/image.cpp index 0ddb8110cb..ca2f659fb0 100644 --- a/esphome/components/image/image.cpp +++ b/esphome/components/image/image.cpp @@ -79,6 +79,50 @@ Color Image::get_pixel(int x, int y, Color color_on, Color color_off) const { return color_off; } } +#ifdef USE_LVGL +lv_img_dsc_t *Image::get_lv_img_dsc() { + // lazily construct lvgl image_dsc. + if (this->dsc_.data != this->data_start_) { + this->dsc_.data = this->data_start_; + this->dsc_.header.always_zero = 0; + this->dsc_.header.reserved = 0; + this->dsc_.header.w = this->width_; + this->dsc_.header.h = this->height_; + this->dsc_.data_size = this->get_width_stride() * this->get_height(); + switch (this->get_type()) { + case IMAGE_TYPE_BINARY: + this->dsc_.header.cf = LV_IMG_CF_ALPHA_1BIT; + break; + + case IMAGE_TYPE_GRAYSCALE: + this->dsc_.header.cf = LV_IMG_CF_ALPHA_8BIT; + break; + + case IMAGE_TYPE_RGB24: + this->dsc_.header.cf = LV_IMG_CF_RGB888; + break; + + case IMAGE_TYPE_RGB565: +#if LV_COLOR_DEPTH == 16 + this->dsc_.header.cf = this->has_transparency() ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR; +#else + this->dsc_.header.cf = LV_IMG_CF_RGB565; +#endif + break; + + case IMAGE_TYPE_RGBA: +#if LV_COLOR_DEPTH == 32 + this->dsc_.header.cf = LV_IMG_CF_TRUE_COLOR; +#else + this->dsc_.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA; +#endif + break; + } + } + return &this->dsc_; +} +#endif // USE_LVGL + bool Image::get_binary_pixel_(int x, int y) const { const uint32_t width_8 = ((this->width_ + 7u) / 8u) * 8u; const uint32_t pos = x + y * width_8; @@ -103,21 +147,21 @@ Color Image::get_rgb24_pixel_(int x, int y) const { return color; } Color Image::get_rgb565_pixel_(int x, int y) const { - const uint32_t pos = (x + y * this->width_) * 2; - uint16_t rgb565 = - progmem_read_byte(this->data_start_ + pos + 0) << 8 | progmem_read_byte(this->data_start_ + pos + 1); + const uint8_t *pos = this->data_start_; + if (this->transparent_) { + pos += (x + y * this->width_) * 3; + } else { + pos += (x + y * this->width_) * 2; + } + uint16_t rgb565 = encode_uint16(progmem_read_byte(pos), progmem_read_byte(pos + 1)); auto r = (rgb565 & 0xF800) >> 11; auto g = (rgb565 & 0x07E0) >> 5; auto b = rgb565 & 0x001F; - Color color = Color((r << 3) | (r >> 2), (g << 2) | (g >> 4), (b << 3) | (b >> 2)); - if (rgb565 == 0x0020 && transparent_) { - // darkest green has been defined as transparent color for transparent RGB565 images. - color.w = 0; - } else { - color.w = 0xFF; - } + auto a = this->transparent_ ? progmem_read_byte(pos + 2) : 0xFF; + Color color = Color((r << 3) | (r >> 2), (g << 2) | (g >> 4), (b << 3) | (b >> 2), a); return color; } + Color Image::get_grayscale_pixel_(int x, int y) const { const uint32_t pos = (x + y * this->width_); const uint8_t gray = progmem_read_byte(this->data_start_ + pos); diff --git a/esphome/components/image/image.h b/esphome/components/image/image.h index 5f1f50a134..40370d18da 100644 --- a/esphome/components/image/image.h +++ b/esphome/components/image/image.h @@ -1,6 +1,10 @@ #pragma once #include "esphome/core/color.h" -#include "esphome/components/display/display_buffer.h" +#include "esphome/components/display/display.h" + +#ifdef USE_LVGL +#include "esphome/components/lvgl/lvgl_proxy.h" +#endif // USE_LVGL namespace esphome { namespace image { @@ -13,38 +17,42 @@ enum ImageType { IMAGE_TYPE_RGBA = 4, }; -inline int image_type_to_bpp(ImageType type) { - switch (type) { - case IMAGE_TYPE_BINARY: - return 1; - case IMAGE_TYPE_GRAYSCALE: - return 8; - case IMAGE_TYPE_RGB565: - return 16; - case IMAGE_TYPE_RGB24: - return 24; - case IMAGE_TYPE_RGBA: - return 32; - } - return 0; -} - -inline int image_type_to_width_stride(int width, ImageType type) { return (width * image_type_to_bpp(type) + 7u) / 8u; } - class Image : public display::BaseImage { public: Image(const uint8_t *data_start, int width, int height, ImageType type); Color get_pixel(int x, int y, Color color_on = display::COLOR_ON, Color color_off = display::COLOR_OFF) const; int get_width() const override; int get_height() const override; - const uint8_t *get_data_start() { return this->data_start_; } + const uint8_t *get_data_start() const { return this->data_start_; } ImageType get_type() const; + int get_bpp() const { + switch (this->type_) { + case IMAGE_TYPE_BINARY: + return 1; + case IMAGE_TYPE_GRAYSCALE: + return 8; + case IMAGE_TYPE_RGB565: + return this->transparent_ ? 24 : 16; + case IMAGE_TYPE_RGB24: + return 24; + case IMAGE_TYPE_RGBA: + return 32; + } + return 0; + } + + /// Return the stride of the image in bytes, that is, the distance in bytes + /// between two consecutive rows of pixels. + uint32_t get_width_stride() const { return (this->width_ * this->get_bpp() + 7u) / 8u; } void draw(int x, int y, display::Display *display, Color color_on, Color color_off) override; void set_transparency(bool transparent) { transparent_ = transparent; } bool has_transparency() const { return transparent_; } +#ifdef USE_LVGL + lv_img_dsc_t *get_lv_img_dsc(); +#endif protected: bool get_binary_pixel_(int x, int y) const; Color get_rgb24_pixel_(int x, int y) const; @@ -57,6 +65,9 @@ class Image : public display::BaseImage { ImageType type_; const uint8_t *data_start_; bool transparent_; +#ifdef USE_LVGL + lv_img_dsc_t dsc_{}; +#endif }; } // namespace image diff --git a/esphome/components/inkplate6/display.py b/esphome/components/inkplate6/display.py index 58a146d2fd..8fe7f7d41d 100644 --- a/esphome/components/inkplate6/display.py +++ b/esphome/components/inkplate6/display.py @@ -53,6 +53,8 @@ MODELS = { "inkplate_10": InkplateModel.INKPLATE_10, "inkplate_6_plus": InkplateModel.INKPLATE_6_PLUS, "inkplate_6_v2": InkplateModel.INKPLATE_6_V2, + "inkplate_5": InkplateModel.INKPLATE_5, + "inkplate_5_v2": InkplateModel.INKPLATE_5_V2, } CONFIG_SCHEMA = cv.All( diff --git a/esphome/components/inkplate6/inkplate.h b/esphome/components/inkplate6/inkplate.h index 2946c89e1c..ca2ad46f1e 100644 --- a/esphome/components/inkplate6/inkplate.h +++ b/esphome/components/inkplate6/inkplate.h @@ -15,6 +15,8 @@ enum InkplateModel : uint8_t { INKPLATE_10 = 1, INKPLATE_6_PLUS = 2, INKPLATE_6_V2 = 3, + INKPLATE_5 = 4, + INKPLATE_5_V2 = 5, }; class Inkplate6 : public display::DisplayBuffer, public i2c::I2CDevice { @@ -29,7 +31,7 @@ class Inkplate6 : public display::DisplayBuffer, public i2c::I2CDevice { const uint8_t pixelMaskLUT[8] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80}; const uint8_t pixelMaskGLUT[2] = {0x0F, 0xF0}; - const uint8_t waveform3BitAll[4][8][9] = {// INKPLATE_6 + const uint8_t waveform3BitAll[6][8][9] = {// INKPLATE_6 {{0, 1, 1, 0, 0, 1, 1, 0, 0}, {0, 1, 2, 1, 1, 2, 1, 0, 0}, {1, 1, 1, 2, 2, 1, 0, 0, 0}, @@ -64,7 +66,25 @@ class Inkplate6 : public display::DisplayBuffer, public i2c::I2CDevice { {1, 1, 1, 1, 2, 2, 1, 0, 0}, {0, 1, 1, 1, 2, 2, 1, 0, 0}, {0, 0, 0, 0, 1, 1, 2, 0, 0}, - {0, 0, 0, 0, 0, 1, 2, 0, 0}}}; + {0, 0, 0, 0, 0, 1, 2, 0, 0}}, + // INKPLATE_5 + {{0, 0, 1, 1, 0, 1, 1, 1, 0}, + {0, 1, 1, 1, 1, 2, 0, 1, 0}, + {1, 2, 2, 0, 2, 1, 1, 1, 0}, + {1, 1, 1, 2, 0, 1, 1, 2, 0}, + {0, 1, 1, 1, 2, 0, 1, 2, 0}, + {0, 0, 0, 1, 1, 2, 1, 2, 0}, + {1, 1, 1, 2, 0, 2, 1, 2, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}}, + // INKPLATE_5_V2 + {{0, 0, 1, 1, 2, 1, 1, 1, 0}, + {1, 1, 2, 2, 1, 2, 1, 1, 0}, + {0, 1, 2, 2, 1, 1, 2, 1, 0}, + {0, 0, 1, 1, 1, 1, 1, 2, 0}, + {1, 2, 1, 2, 1, 1, 1, 2, 0}, + {0, 1, 1, 1, 2, 0, 1, 2, 0}, + {1, 1, 1, 2, 2, 2, 1, 2, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}}}; void set_greyscale(bool greyscale) { this->greyscale_ = greyscale; @@ -146,6 +166,10 @@ class Inkplate6 : public display::DisplayBuffer, public i2c::I2CDevice { return 800; } else if (this->model_ == INKPLATE_10) { return 1200; + } else if (this->model_ == INKPLATE_5) { + return 960; + } else if (this->model_ == INKPLATE_5_V2) { + return 1280; } else if (this->model_ == INKPLATE_6_PLUS) { return 1024; } @@ -155,6 +179,10 @@ class Inkplate6 : public display::DisplayBuffer, public i2c::I2CDevice { int get_height_internal() override { if (this->model_ == INKPLATE_6 || this->model_ == INKPLATE_6_V2) { return 600; + } else if (this->model_ == INKPLATE_5) { + return 540; + } else if (this->model_ == INKPLATE_5_V2) { + return 720; } else if (this->model_ == INKPLATE_10) { return 825; } else if (this->model_ == INKPLATE_6_PLUS) { diff --git a/esphome/components/internal_temperature/internal_temperature.cpp b/esphome/components/internal_temperature/internal_temperature.cpp index 47f516f568..9ef5cbecd5 100644 --- a/esphome/components/internal_temperature/internal_temperature.cpp +++ b/esphome/components/internal_temperature/internal_temperature.cpp @@ -7,7 +7,8 @@ extern "C" { uint8_t temprature_sens_read(); } -#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) +#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || \ + defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) #include "driver/temp_sensor.h" #endif // USE_ESP32_VARIANT #endif // USE_ESP32 @@ -34,7 +35,8 @@ void InternalTemperatureSensor::update() { ESP_LOGV(TAG, "Raw temperature value: %d", raw); temperature = (raw - 32) / 1.8f; success = (raw != 128); -#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) +#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || \ + defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) temp_sensor_config_t tsens = TSENS_CONFIG_DEFAULT(); temp_sensor_set_config(tsens); temp_sensor_start(); diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index a8034f8fab..b29d2e309c 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 @@ -50,7 +46,7 @@ from .const import ( _LOGGER = logging.getLogger(__name__) CODEOWNERS = ["@kuba2k2"] -AUTO_LOAD = [] +AUTO_LOAD = ["preferences"] def _detect_variant(value): @@ -174,12 +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(0, 0, 0), "https://github.com/libretiny-eu/libretiny.git"), - "latest": (cv.Version(0, 0, 0), None), - "recommended": (cv.Version(1, 5, 1), 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, 7, 0), None), } @@ -282,10 +277,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") diff --git a/esphome/components/light/__init__.py b/esphome/components/light/__init__.py index d9f139d2f4..feac385b66 100644 --- a/esphome/components/light/__init__.py +++ b/esphome/components/light/__init__.py @@ -3,27 +3,39 @@ 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_BLUE, + CONF_BRIGHTNESS, + CONF_COLD_WHITE, CONF_COLD_WHITE_COLOR_TEMPERATURE, + CONF_COLOR_BRIGHTNESS, CONF_COLOR_CORRECT, + CONF_COLOR_MODE, + CONF_COLOR_TEMPERATURE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_EFFECTS, CONF_FLASH_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, + CONF_GREEN, CONF_ID, + CONF_INITIAL_STATE, CONF_MQTT_ID, CONF_ON_STATE, CONF_ON_TURN_OFF, CONF_ON_TURN_ON, CONF_POWER_SUPPLY, + CONF_RED, CONF_RESTORE_MODE, + CONF_STATE, CONF_TRIGGER_ID, + CONF_WARM_WHITE, CONF_WARM_WHITE_COLOR_TEMPERATURE, - CONF_WEB_SERVER_ID, + CONF_WEB_SERVER, + CONF_WHITE, ) from esphome.core import coroutine_with_priority from esphome.cpp_helpers import setup_entity -from .automation import light_control_to_code # noqa +from .automation import LIGHT_STATE_SCHEMA from .effects import ( ADDRESSABLE_EFFECTS, BINARY_EFFECTS, @@ -35,8 +47,10 @@ from .effects import ( from .types import ( # noqa AddressableLight, AddressableLightState, + ColorMode, LightOutput, LightState, + LightStateRTCState, LightStateTrigger, LightTurnOffTrigger, LightTurnOnTrigger, @@ -85,6 +99,7 @@ LIGHT_SCHEMA = ( cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LightStateTrigger), } ), + cv.Optional(CONF_INITIAL_STATE): LIGHT_STATE_SCHEMA, } ) ) @@ -145,6 +160,22 @@ async def setup_light_core_(light_var, output_var, config): cg.add(light_var.set_restore_mode(config[CONF_RESTORE_MODE])) + if (initial_state_config := config.get(CONF_INITIAL_STATE)) is not None: + initial_state = LightStateRTCState( + initial_state_config.get(CONF_COLOR_MODE, ColorMode.UNKNOWN), + initial_state_config.get(CONF_STATE, False), + initial_state_config.get(CONF_BRIGHTNESS, 1.0), + initial_state_config.get(CONF_COLOR_BRIGHTNESS, 1.0), + initial_state_config.get(CONF_RED, 1.0), + initial_state_config.get(CONF_GREEN, 1.0), + initial_state_config.get(CONF_BLUE, 1.0), + initial_state_config.get(CONF_WHITE, 1.0), + initial_state_config.get(CONF_COLOR_TEMPERATURE, 1.0), + initial_state_config.get(CONF_COLD_WHITE, 1.0), + initial_state_config.get(CONF_WARM_WHITE, 1.0), + ) + cg.add(light_var.set_initial_state(initial_state)) + if ( default_transition_length := config.get(CONF_DEFAULT_TRANSITION_LENGTH) ) is not None: @@ -181,9 +212,8 @@ 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) + if web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(light_var, web_server_config) async def register_light(output_var, config): diff --git a/esphome/components/light/automation.py b/esphome/components/light/automation.py index ec0375f54a..e5aa8fa0e9 100644 --- a/esphome/components/light/automation.py +++ b/esphome/components/light/automation.py @@ -1,41 +1,42 @@ +from esphome import automation import esphome.codegen as cg import esphome.config_validation as cv -from esphome import automation from esphome.const import ( - CONF_ID, - CONF_COLOR_MODE, - CONF_TRANSITION_LENGTH, - CONF_STATE, - CONF_FLASH_LENGTH, - CONF_EFFECT, - CONF_BRIGHTNESS, - CONF_COLOR_BRIGHTNESS, - CONF_RED, - CONF_GREEN, CONF_BLUE, - CONF_WHITE, - CONF_COLOR_TEMPERATURE, + CONF_BRIGHTNESS, + CONF_BRIGHTNESS_LIMITS, CONF_COLD_WHITE, - CONF_WARM_WHITE, + CONF_COLOR_BRIGHTNESS, + CONF_COLOR_MODE, + CONF_COLOR_TEMPERATURE, + CONF_EFFECT, + CONF_FLASH_LENGTH, + CONF_GREEN, + CONF_ID, + CONF_LIMIT_MODE, + CONF_MAX_BRIGHTNESS, + CONF_MIN_BRIGHTNESS, CONF_RANGE_FROM, CONF_RANGE_TO, - CONF_BRIGHTNESS_LIMITS, - CONF_LIMIT_MODE, - CONF_MIN_BRIGHTNESS, - CONF_MAX_BRIGHTNESS, + CONF_RED, + CONF_STATE, + CONF_TRANSITION_LENGTH, + CONF_WARM_WHITE, + CONF_WHITE, ) + from .types import ( - ColorMode, COLOR_MODES, LIMIT_MODES, - DimRelativeAction, - ToggleAction, - LightState, - LightControlAction, AddressableLightState, AddressableSet, - LightIsOnCondition, + ColorMode, + DimRelativeAction, + LightControlAction, LightIsOffCondition, + LightIsOnCondition, + LightState, + ToggleAction, ) @@ -62,18 +63,10 @@ async def light_toggle_to_code(config, action_id, template_arg, args): return var -LIGHT_CONTROL_ACTION_SCHEMA = cv.Schema( +LIGHT_STATE_SCHEMA = cv.Schema( { - cv.Required(CONF_ID): cv.use_id(LightState), cv.Optional(CONF_COLOR_MODE): cv.enum(COLOR_MODES, upper=True, space="_"), cv.Optional(CONF_STATE): cv.templatable(cv.boolean), - cv.Exclusive(CONF_TRANSITION_LENGTH, "transformer"): cv.templatable( - cv.positive_time_period_milliseconds - ), - cv.Exclusive(CONF_FLASH_LENGTH, "transformer"): cv.templatable( - cv.positive_time_period_milliseconds - ), - cv.Exclusive(CONF_EFFECT, "transformer"): cv.templatable(cv.string), cv.Optional(CONF_BRIGHTNESS): cv.templatable(cv.percentage), cv.Optional(CONF_COLOR_BRIGHTNESS): cv.templatable(cv.percentage), cv.Optional(CONF_RED): cv.templatable(cv.percentage), @@ -85,6 +78,20 @@ LIGHT_CONTROL_ACTION_SCHEMA = cv.Schema( cv.Optional(CONF_WARM_WHITE): cv.templatable(cv.percentage), } ) + +LIGHT_CONTROL_ACTION_SCHEMA = LIGHT_STATE_SCHEMA.extend( + { + cv.Required(CONF_ID): cv.use_id(LightState), + cv.Exclusive(CONF_TRANSITION_LENGTH, "transformer"): cv.templatable( + cv.positive_time_period_milliseconds + ), + cv.Exclusive(CONF_FLASH_LENGTH, "transformer"): cv.templatable( + cv.positive_time_period_milliseconds + ), + cv.Exclusive(CONF_EFFECT, "transformer"): cv.templatable(cv.string), + } +) + LIGHT_TURN_OFF_ACTION_SCHEMA = automation.maybe_simple_id( { cv.Required(CONF_ID): cv.use_id(LightState), diff --git a/esphome/components/light/effects.py b/esphome/components/light/effects.py index be50f63321..67c318eb8e 100644 --- a/esphome/components/light/effects.py +++ b/esphome/components/light/effects.py @@ -1,59 +1,59 @@ -from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor +from esphome import automation import esphome.codegen as cg import esphome.config_validation as cv -from esphome import automation - from esphome.const import ( - CONF_NAME, - CONF_LAMBDA, - CONF_UPDATE_INTERVAL, - CONF_TRANSITION_LENGTH, - CONF_COLORS, - CONF_STATE, - CONF_DURATION, - CONF_BRIGHTNESS, - CONF_COLOR_MODE, - CONF_COLOR_BRIGHTNESS, - CONF_RED, - CONF_GREEN, - CONF_BLUE, - CONF_WHITE, - CONF_COLOR_TEMPERATURE, - CONF_COLD_WHITE, - CONF_WARM_WHITE, CONF_ALPHA, + CONF_BLUE, + CONF_BRIGHTNESS, + CONF_COLD_WHITE, + CONF_COLOR_BRIGHTNESS, + CONF_COLOR_MODE, + CONF_COLOR_TEMPERATURE, + CONF_COLORS, + CONF_DURATION, + CONF_GREEN, CONF_INTENSITY, - CONF_SPEED, - CONF_WIDTH, - CONF_NUM_LEDS, - CONF_RANDOM, - CONF_SEQUENCE, + CONF_LAMBDA, CONF_MAX_BRIGHTNESS, CONF_MIN_BRIGHTNESS, + CONF_NAME, + CONF_NUM_LEDS, + CONF_RANDOM, + CONF_RED, + CONF_SEQUENCE, + CONF_SPEED, + CONF_STATE, + CONF_TRANSITION_LENGTH, + CONF_UPDATE_INTERVAL, + CONF_WARM_WHITE, + CONF_WHITE, + CONF_WIDTH, ) +from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor from esphome.util import Registry + from .types import ( - ColorMode, COLOR_MODES, + AddressableColorWipeEffect, + AddressableColorWipeEffectColor, + AddressableFireworksEffect, + AddressableFlickerEffect, + AddressableLambdaLightEffect, + AddressableLightRef, + AddressableRainbowLightEffect, + AddressableRandomTwinkleEffect, + AddressableScanEffect, + AddressableTwinkleEffect, + AutomationLightEffect, + Color, + ColorMode, + FlickerLightEffect, LambdaLightEffect, + LightColorValues, PulseLightEffect, RandomLightEffect, StrobeLightEffect, StrobeLightEffectColor, - LightColorValues, - AddressableLightRef, - AddressableLambdaLightEffect, - FlickerLightEffect, - AddressableRainbowLightEffect, - AddressableColorWipeEffect, - AddressableColorWipeEffectColor, - AddressableScanEffect, - AddressableTwinkleEffect, - AddressableRandomTwinkleEffect, - AddressableFireworksEffect, - AddressableFlickerEffect, - AutomationLightEffect, - Color, ) CONF_ADD_LED_INTERVAL = "add_led_interval" diff --git a/esphome/components/light/light_state.cpp b/esphome/components/light/light_state.cpp index fe6538e65e..16b78a17bd 100644 --- a/esphome/components/light/light_state.cpp +++ b/esphome/components/light/light_state.cpp @@ -1,6 +1,7 @@ #include "esphome/core/log.h" -#include "light_state.h" + #include "light_output.h" +#include "light_state.h" #include "transformers.h" namespace esphome { @@ -16,21 +17,6 @@ LightCall LightState::turn_off() { return this->make_call().set_state(false); } LightCall LightState::toggle() { return this->make_call().set_state(!this->remote_values.is_on()); } LightCall LightState::make_call() { return LightCall(this); } -struct LightStateRTCState { - ColorMode color_mode{ColorMode::UNKNOWN}; - bool state{false}; - float brightness{1.0f}; - float color_brightness{1.0f}; - float red{1.0f}; - float green{1.0f}; - float blue{1.0f}; - float white{1.0f}; - float color_temp{1.0f}; - float cold_white{1.0f}; - float warm_white{1.0f}; - uint32_t effect{0}; -}; - void LightState::setup() { ESP_LOGCONFIG(TAG, "Setting up light '%s'...", this->get_name().c_str()); @@ -48,6 +34,9 @@ void LightState::setup() { auto call = this->make_call(); LightStateRTCState recovered{}; + if (this->initial_state_.has_value()) { + recovered = *this->initial_state_; + } switch (this->restore_mode_) { case LIGHT_RESTORE_DEFAULT_OFF: case LIGHT_RESTORE_DEFAULT_ON: @@ -175,6 +164,7 @@ void LightState::set_flash_transition_length(uint32_t flash_transition_length) { uint32_t LightState::get_flash_transition_length() const { return this->flash_transition_length_; } void LightState::set_gamma_correct(float gamma_correct) { this->gamma_correct_ = gamma_correct; } void LightState::set_restore_mode(LightRestoreMode restore_mode) { this->restore_mode_ = restore_mode; } +void LightState::set_initial_state(const LightStateRTCState &initial_state) { this->initial_state_ = initial_state; } bool LightState::supports_effects() { return !this->effects_.empty(); } const std::vector &LightState::get_effects() const { return this->effects_; } void LightState::add_effects(const std::vector &effects) { diff --git a/esphome/components/light/light_state.h b/esphome/components/light/light_state.h index b0aaa453b5..acba986f24 100644 --- a/esphome/components/light/light_state.h +++ b/esphome/components/light/light_state.h @@ -28,6 +28,35 @@ enum LightRestoreMode { LIGHT_RESTORE_AND_ON, }; +struct LightStateRTCState { + LightStateRTCState(ColorMode color_mode, bool state, float brightness, float color_brightness, float red, float green, + float blue, float white, float color_temp, float cold_white, float warm_white) + : color_mode(color_mode), + state(state), + brightness(brightness), + color_brightness(color_brightness), + red(red), + green(green), + blue(blue), + white(white), + color_temp(color_temp), + cold_white(cold_white), + warm_white(warm_white) {} + LightStateRTCState() = default; + ColorMode color_mode{ColorMode::UNKNOWN}; + bool state{false}; + float brightness{1.0f}; + float color_brightness{1.0f}; + float red{1.0f}; + float green{1.0f}; + float blue{1.0f}; + float white{1.0f}; + float color_temp{1.0f}; + float cold_white{1.0f}; + float warm_white{1.0f}; + uint32_t effect{0}; +}; + /** This class represents the communication layer between the front-end MQTT layer and the * hardware output layer. */ @@ -116,6 +145,9 @@ class LightState : public EntityBase, public Component { /// Set the restore mode of this light void set_restore_mode(LightRestoreMode restore_mode); + /// Set the initial state of this light + void set_initial_state(const LightStateRTCState &initial_state); + /// Return whether the light has any effects that meet the trait requirements. bool supports_effects(); @@ -212,6 +244,8 @@ class LightState : public EntityBase, public Component { float gamma_correct_{}; /// Restore mode of the light. LightRestoreMode restore_mode_; + /// Initial state of the light. + optional initial_state_{}; /// List of effects for this light. std::vector effects_; diff --git a/esphome/components/light/types.py b/esphome/components/light/types.py index 64483bcc9c..a586bcbd13 100644 --- a/esphome/components/light/types.py +++ b/esphome/components/light/types.py @@ -1,5 +1,5 @@ -import esphome.codegen as cg from esphome import automation +import esphome.codegen as cg # Base light_ns = cg.esphome_ns.namespace("light") @@ -12,6 +12,8 @@ AddressableLightRef = AddressableLight.operator("ref") Color = cg.esphome_ns.class_("Color") LightColorValues = light_ns.class_("LightColorValues") +LightStateRTCState = light_ns.struct("LightStateRTCState") + # Color modes ColorMode = light_ns.enum("ColorMode", is_class=True) COLOR_MODES = { diff --git a/esphome/components/lock/__init__.py b/esphome/components/lock/__init__.py index 6b92bc264b..6925861b52 100644 --- a/esphome/components/lock/__init__.py +++ b/esphome/components/lock/__init__.py @@ -9,7 +9,7 @@ from esphome.const import ( CONF_ON_LOCK, CONF_ON_UNLOCK, CONF_TRIGGER_ID, - CONF_WEB_SERVER_ID, + CONF_WEB_SERVER, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_helpers import setup_entity @@ -66,9 +66,8 @@ 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) + if web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(var, web_server_config) async def register_lock(var, config): diff --git a/esphome/components/logger/logger_esp32.cpp b/esphome/components/logger/logger_esp32.cpp index b0f1051d34..c9de3d815a 100644 --- a/esphome/components/logger/logger_esp32.cpp +++ b/esphome/components/logger/logger_esp32.cpp @@ -10,8 +10,12 @@ #ifdef USE_LOGGER_USB_SERIAL_JTAG #include +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 3, 0) #include #include +#else +#include +#endif #endif #include "freertos/FreeRTOS.h" @@ -36,10 +40,17 @@ static const char *const TAG = "logger"; static void init_usb_serial_jtag_() { setvbuf(stdin, NULL, _IONBF, 0); // Disable buffering on stdin +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 3, 0) // 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); +#else + // Minicom, screen, idf_monitor send CR when ENTER key is pressed + usb_serial_jtag_vfs_set_rx_line_endings(ESP_LINE_ENDINGS_CR); + // Move the caret to the beginning of the next line on '\n' + usb_serial_jtag_vfs_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); +#endif // Enable non-blocking mode on stdin and stdout fcntl(fileno(stdout), F_SETFL, 0); @@ -57,7 +68,11 @@ static void init_usb_serial_jtag_() { } // Tell vfs to use usb-serial-jtag driver +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 3, 0) esp_vfs_usb_serial_jtag_use_driver(); +#else + usb_serial_jtag_vfs_use_driver(); +#endif } #endif 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/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index a4ca9d56f3..4a1a26cc0b 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -22,8 +22,10 @@ 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 .hello_world import get_hello_world from .lv_validation import lv_bool, lv_images_used from .lvcode import LvContext, LvglComponent from .schemas import ( @@ -46,12 +48,13 @@ from .types import ( FontEngine, IdleTrigger, ObjUpdateAction, + PauseTrigger, lv_font_t, lv_group_t, lv_style_t, lvgl_ns, ) -from .widgets import Widget, add_widgets, lv_scr_act, set_obj_properties +from .widgets import Widget, add_widgets, get_scr_act, set_obj_properties, styles_used from .widgets.animimg import animimg_spec from .widgets.arc import arc_spec from .widgets.button import button_spec @@ -68,6 +71,7 @@ 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, generate_page_triggers, page_spec +from .widgets.qrcode import qr_code_spec from .widgets.roller import roller_spec from .widgets.slider import slider_spec from .widgets.spinbox import spinbox_spec @@ -106,6 +110,7 @@ for w_type in ( spinbox_spec, keyboard_spec, tileview_spec, + qr_code_spec, ): WIDGET_TYPES[w_type.name] = w_type @@ -128,17 +133,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 +147,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 +179,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, @@ -194,7 +188,7 @@ def final_validation(config): async def to_code(config): cg.add_library("lvgl/lvgl", "8.4.0") - CORE.add_define("USE_LVGL") + cg.add_define("USE_LVGL") # suppress default enabling of extra widgets add_define("_LV_KCONFIG_PRESENT") # Always enable - lots of things use it. @@ -208,7 +202,13 @@ async def to_code(config): 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_LOG_LEVEL", f"LV_LOG_LEVEL_{df.LV_LOG_LEVELS[config[df.CONF_LOG_LEVEL]]}" + ) + cg.add_define( + "LVGL_LOG_LEVEL", + cg.RawExpression(f"ESPHOME_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()}") @@ -222,15 +222,9 @@ async def to_code(config): "LV_COLOR_CHROMA_KEY", await lvalid.lv_color.process(config[df.CONF_TRANSPARENCY_KEY]), ) - CORE.add_build_flag("-Isrc") + cg.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, obj_spec, 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 @@ -240,8 +234,17 @@ async def to_code(config): 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])) + displays = [await cg.get_variable(display) for display in config[df.CONF_DISPLAYS]] + lv_component = cg.new_Pvariable( + config[CONF_ID], + displays, + frac, + config[df.CONF_FULL_REFRESH], + config[df.CONF_DRAW_ROUNDING], + config[df.CONF_RESUME_ON_INPUT], + ) + await cg.register_component(lv_component, config) + Widget.create(config[CONF_ID], lv_component, obj_spec, config) for font in helpers.esphome_fonts_used: await cg.get_variable(font) @@ -263,37 +266,48 @@ async def to_code(config): else: add_define("LV_FONT_DEFAULT", await lvalid.lv_font.process(default_font)) + lv_scr_act = get_scr_act(lv_component) async with LvContext(lv_component): await touchscreens_to_code(lv_component, 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) - await add_top_layer(config) - await msgboxes_to_code(config) - await disp_update(f"{lv_component}->get_disp()", config) - # At this point only the setup code should be generated - assert LvContext.added_lambda_count == 1 - Widget.set_completed() + await add_top_layer(lv_component, config) + await msgboxes_to_code(lv_component, config) + await disp_update(lv_component.get_disp(), config) + # Set this directly since we are limited in how many methods can be added to the Widget class. + Widget.widgets_completed = True async with LvContext(lv_component): await generate_triggers(lv_component) await generate_page_triggers(lv_component, config) + await initial_focus_to_code(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) await build_automation(idle_trigger, [], conf) - await initial_focus_to_code(config) + for conf in config.get(df.CONF_ON_PAUSE, ()): + pause_trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], lv_component, True) + await build_automation(pause_trigger, [], conf) + for conf in config.get(df.CONF_ON_RESUME, ()): + resume_trigger = cg.new_Pvariable( + conf[CONF_TRIGGER_ID], lv_component, False + ) + await build_automation(resume_trigger, [], conf) for comp in helpers.lvgl_components_required: - CORE.add_define(f"USE_LVGL_{comp.upper()}") + cg.add_define(f"USE_LVGL_{comp.upper()}") + if "transform_angle" in styles_used: + add_define("LV_COLOR_SCREEN_TRANSP", "1") 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}"') + cg.add_build_flag("-DLV_CONF_H=1") + cg.add_build_flag(f'-DLV_CONF_PATH="{LV_CONF_FILENAME}"') def display_schema(config): @@ -301,6 +315,13 @@ def display_schema(config): return value or [cv.use_id(Display)(config)] +def add_hello_world(config): + if df.CONF_WIDGETS not in config and CONF_PAGES not in config: + LOGGER.info("No pages or widgets configured, creating default hello_world page") + config[df.CONF_WIDGETS] = cv.ensure_list(WIDGET_SCHEMA)(get_hello_world()) + return config + + FINAL_VALIDATE_SCHEMA = final_validation CONFIG_SCHEMA = ( @@ -313,9 +334,10 @@ CONFIG_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(df.CONF_DRAW_ROUNDING, default=2): cv.positive_int, 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 + *df.LV_LOG_LEVELS, upper=True ), cv.Optional(df.CONF_BYTE_ORDER, default="big_endian"): cv.one_of( "big_endian", "little_endian" @@ -340,6 +362,16 @@ CONFIG_SCHEMA = ( ), } ), + cv.Optional(df.CONF_ON_PAUSE): validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PauseTrigger), + } + ), + cv.Optional(df.CONF_ON_RESUME): validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PauseTrigger), + } + ), 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) @@ -351,10 +383,13 @@ 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), + cv.Optional(df.CONF_RESUME_ON_INPUT, default=True): cv.boolean, } ) .extend(DISP_BG_SCHEMA) -).add_extra(cv.has_at_least_one_key(CONF_PAGES, df.CONF_WIDGETS)) + .add_extra(add_hello_world) +) diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py index 8138551c30..48472354f8 100644 --- a/esphome/components/lvgl/automation.py +++ b/esphome/components/lvgl/automation.py @@ -5,7 +5,7 @@ from esphome import automation import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_ACTION, CONF_GROUP, CONF_ID, CONF_TIMEOUT -from esphome.cpp_generator import RawExpression, get_variable +from esphome.cpp_generator import get_variable from esphome.cpp_types import nullptr from .defines import ( @@ -23,7 +23,6 @@ from .lvcode import ( UPDATE_EVENT, LambdaContext, LocalVariable, - LvConditional, LvglComponent, ReturnStatement, add_line_marks, @@ -47,8 +46,8 @@ from .types import ( ) from .widgets import ( Widget, + get_scr_act, get_widgets, - lv_scr_act, set_obj_properties, wait_for_widgets, ) @@ -66,8 +65,6 @@ async def action_to_code( ): 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: await action(widget) var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) @@ -126,7 +123,7 @@ async def lvgl_is_idle(config, condition_id, template_arg, args): 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: + with LocalVariable("lv_disp_tmp", lv_disp_t, disp) as disp_temp: if (bg_color := config.get(CONF_DISP_BG_COLOR)) is not None: lv.disp_set_bg_color(disp_temp, await lv_color.process(bg_color)) if bg_image := config.get(CONF_DISP_BG_IMAGE): @@ -136,15 +133,24 @@ async def disp_update(disp, config: dict): @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), - } + cv.Any( + cv.maybe_simple_value( + { + cv.Required(CONF_ID): cv.use_id(lv_obj_t), + cv.GenerateID(CONF_LVGL_ID): cv.use_id(LvglComponent), + }, + key=CONF_ID, + ), + cv.Schema( + { + cv.GenerateID(CONF_LVGL_ID): cv.use_id(LvglComponent), + } + ), ), ) async def obj_invalidate_to_code(config, action_id, template_arg, args): - widgets = await get_widgets(config) or [lv_scr_act] + lv_comp = await cg.get_variable(config[CONF_LVGL_ID]) + widgets = await get_widgets(config) or [get_scr_act(lv_comp)] async def do_invalidate(widget: Widget): lv_obj.invalidate(widget.obj) @@ -164,7 +170,7 @@ async def obj_invalidate_to_code(config, action_id, template_arg, args): 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()" + disp = literal(f"{w.obj}->get_disp()") 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()) @@ -229,19 +235,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..4d48028611 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,14 +186,17 @@ LV_ANIM = LvConstant( "OUT_BOTTOM", ) -LOG_LEVELS = ( - "TRACE", - "INFO", - "WARN", - "ERROR", - "USER", - "NONE", -) +LV_GRAD_DIR = LvConstant("LV_GRAD_DIR_", "NONE", "HOR", "VER") +LV_DITHER = LvConstant("LV_DITHER_", "NONE", "ORDERED", "ERR_DIFF") + +LV_LOG_LEVELS = { + "VERBOSE": "TRACE", + "DEBUG": "TRACE", + "INFO": "INFO", + "WARN": "WARN", + "ERROR": "ERROR", + "NONE": "NONE", +} LV_LONG_MODES = LvConstant( "LV_LABEL_LONG_", @@ -374,6 +390,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" @@ -391,6 +408,7 @@ CONF_DEFAULT_FONT = "default_font" CONF_DEFAULT_GROUP = "default_group" CONF_DIR = "dir" CONF_DISPLAYS = "displays" +CONF_DRAW_ROUNDING = "draw_rounding" CONF_EDITING = "editing" CONF_ENCODERS = "encoders" CONF_END_ANGLE = "end_angle" @@ -405,6 +423,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" @@ -433,7 +452,10 @@ CONF_OFFSET_X = "offset_x" CONF_OFFSET_Y = "offset_y" CONF_ONE_CHECKED = "one_checked" CONF_ONE_LINE = "one_line" +CONF_ON_PAUSE = "on_pause" +CONF_ON_RESUME = "on_resume" CONF_ON_SELECT = "on_select" +CONF_OPA = "opa" CONF_NEXT = "next" CONF_PAD_ROW = "pad_row" CONF_PAD_COLUMN = "pad_column" @@ -447,6 +469,7 @@ CONF_POINTS = "points" CONF_PREVIOUS = "previous" CONF_REPEAT_COUNT = "repeat_count" CONF_RECOLOR = "recolor" +CONF_RESUME_ON_INPUT = "resume_on_input" CONF_RIGHT_BUTTON = "right_button" CONF_ROLLOVER = "rollover" CONF_ROOT_BACK_BTN = "root_back_btn" @@ -454,6 +477,7 @@ CONF_ROWS = "rows" CONF_SCALE_LINES = "scale_lines" CONF_SCROLLBAR_MODE = "scrollbar_mode" CONF_SELECTED_INDEX = "selected_index" +CONF_SELECTED_TEXT = "selected_text" CONF_SHOW_SNOW = "show_snow" CONF_SPIN_TIME = "spin_time" CONF_SRC = "src" 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/hello_world.py b/esphome/components/lvgl/hello_world.py new file mode 100644 index 0000000000..2c2ec6732c --- /dev/null +++ b/esphome/components/lvgl/hello_world.py @@ -0,0 +1,64 @@ +from io import StringIO + +from esphome.yaml_util import parse_yaml + +CONFIG = """ +- obj: + radius: 0 + pad_all: 12 + bg_color: 0xFFFFFF + height: 100% + width: 100% + widgets: + - spinner: + id: hello_world_spinner_ + align: center + indicator: + arc_color: tomato + height: 100 + width: 100 + spin_time: 2s + arc_length: 60deg + - label: + id: hello_world_label_ + text: "Hello World!" + align: center + on_click: + lvgl.spinner.update: + id: hello_world_spinner_ + arc_color: springgreen + - checkbox: + pad_all: 8 + text: Checkbox + align: top_right + on_click: + lvgl.label.update: + id: hello_world_label_ + text: "Checked!" + - button: + pad_all: 8 + checkable: true + align: top_left + text_font: montserrat_20 + on_click: + lvgl.label.update: + id: hello_world_label_ + text: "Clicked!" + widgets: + - label: + text: "Button" + - slider: + width: 80% + align: bottom_mid + on_value: + lvgl.label.update: + id: hello_world_label_ + text: + format: "%.0f%%" + args: [x] +""" + + +def get_hello_world(): + with StringIO(CONFIG) as fp: + return parse_yaml("hello_world", fp) diff --git a/esphome/components/lvgl/light/__init__.py b/esphome/components/lvgl/light/__init__.py index a0eeded349..8031ae8221 100644 --- a/esphome/components/lvgl/light/__init__.py +++ b/esphome/components/lvgl/light/__init__.py @@ -2,9 +2,9 @@ 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 esphome.const import CONF_GAMMA_CORRECT, CONF_OUTPUT_ID -from ..defines import CONF_LVGL_ID +from ..defines import CONF_LVGL_ID, CONF_WIDGET from ..lvcode import LvContext from ..schemas import LVGL_SCHEMA from ..types import LvType, lvgl_ns @@ -15,7 +15,7 @@ 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.Required(CONF_WIDGET): cv.use_id(lv_led_t), cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(LVLight), } ).extend(LVGL_SCHEMA) @@ -26,7 +26,7 @@ async def to_code(config): await light.register_light(var, config) paren = await cg.get_variable(config[CONF_LVGL_ID]) - widget = await get_widgets(config, CONF_LED) + widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] await wait_for_widgets() async with LvContext(paren) as ctx: diff --git a/esphome/components/lvgl/lv_validation.py b/esphome/components/lvgl/lv_validation.py index d8af9f7aa9..b91b0905df 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,8 @@ from .defines import ( call_lambda, literal, ) -from .helpers import ( - esphome_fonts_used, - lv_fonts_used, - lvgl_components_required, - requires_component, -) -from .lvcode import lv_expr -from .types import lv_font_t, lv_img_t +from .helpers import esphome_fonts_used, lv_fonts_used, requires_component +from .types import lv_font_t, lv_gradient_t, lv_img_t opacity_consts = LvConstant("LV_OPA_", "TRANSP", "COVER") @@ -47,23 +48,184 @@ def opacity_validator(value): opacity = LValidator(opacity_validator, uint32, retmapper=literal) +COLOR_NAMES = { + "aliceblue": 0xF0F8FF, + "antiquewhite": 0xFAEBD7, + "aqua": 0x00FFFF, + "aquamarine": 0x7FFFD4, + "azure": 0xF0FFFF, + "beige": 0xF5F5DC, + "bisque": 0xFFE4C4, + "black": 0x000000, + "blanchedalmond": 0xFFEBCD, + "blue": 0x0000FF, + "blueviolet": 0x8A2BE2, + "brown": 0xA52A2A, + "burlywood": 0xDEB887, + "cadetblue": 0x5F9EA0, + "chartreuse": 0x7FFF00, + "chocolate": 0xD2691E, + "coral": 0xFF7F50, + "cornflowerblue": 0x6495ED, + "cornsilk": 0xFFF8DC, + "crimson": 0xDC143C, + "cyan": 0x00FFFF, + "darkblue": 0x00008B, + "darkcyan": 0x008B8B, + "darkgoldenrod": 0xB8860B, + "darkgray": 0xA9A9A9, + "darkgreen": 0x006400, + "darkgrey": 0xA9A9A9, + "darkkhaki": 0xBDB76B, + "darkmagenta": 0x8B008B, + "darkolivegreen": 0x556B2F, + "darkorange": 0xFF8C00, + "darkorchid": 0x9932CC, + "darkred": 0x8B0000, + "darksalmon": 0xE9967A, + "darkseagreen": 0x8FBC8F, + "darkslateblue": 0x483D8B, + "darkslategray": 0x2F4F4F, + "darkslategrey": 0x2F4F4F, + "darkturquoise": 0x00CED1, + "darkviolet": 0x9400D3, + "deeppink": 0xFF1493, + "deepskyblue": 0x00BFFF, + "dimgray": 0x696969, + "dimgrey": 0x696969, + "dodgerblue": 0x1E90FF, + "firebrick": 0xB22222, + "floralwhite": 0xFFFAF0, + "forestgreen": 0x228B22, + "fuchsia": 0xFF00FF, + "gainsboro": 0xDCDCDC, + "ghostwhite": 0xF8F8FF, + "goldenrod": 0xDAA520, + "gold": 0xFFD700, + "gray": 0x808080, + "green": 0x008000, + "greenyellow": 0xADFF2F, + "grey": 0x808080, + "honeydew": 0xF0FFF0, + "hotpink": 0xFF69B4, + "indianred": 0xCD5C5C, + "indigo": 0x4B0082, + "ivory": 0xFFFFF0, + "khaki": 0xF0E68C, + "lavenderblush": 0xFFF0F5, + "lavender": 0xE6E6FA, + "lawngreen": 0x7CFC00, + "lemonchiffon": 0xFFFACD, + "lightblue": 0xADD8E6, + "lightcoral": 0xF08080, + "lightcyan": 0xE0FFFF, + "lightgoldenrodyellow": 0xFAFAD2, + "lightgray": 0xD3D3D3, + "lightgreen": 0x90EE90, + "lightgrey": 0xD3D3D3, + "lightpink": 0xFFB6C1, + "lightsalmon": 0xFFA07A, + "lightseagreen": 0x20B2AA, + "lightskyblue": 0x87CEFA, + "lightslategray": 0x778899, + "lightslategrey": 0x778899, + "lightsteelblue": 0xB0C4DE, + "lightyellow": 0xFFFFE0, + "lime": 0x00FF00, + "limegreen": 0x32CD32, + "linen": 0xFAF0E6, + "magenta": 0xFF00FF, + "maroon": 0x800000, + "mediumaquamarine": 0x66CDAA, + "mediumblue": 0x0000CD, + "mediumorchid": 0xBA55D3, + "mediumpurple": 0x9370DB, + "mediumseagreen": 0x3CB371, + "mediumslateblue": 0x7B68EE, + "mediumspringgreen": 0x00FA9A, + "mediumturquoise": 0x48D1CC, + "mediumvioletred": 0xC71585, + "midnightblue": 0x191970, + "mintcream": 0xF5FFFA, + "mistyrose": 0xFFE4E1, + "moccasin": 0xFFE4B5, + "navajowhite": 0xFFDEAD, + "navy": 0x000080, + "oldlace": 0xFDF5E6, + "olive": 0x808000, + "olivedrab": 0x6B8E23, + "orange": 0xFFA500, + "orangered": 0xFF4500, + "orchid": 0xDA70D6, + "palegoldenrod": 0xEEE8AA, + "palegreen": 0x98FB98, + "paleturquoise": 0xAFEEEE, + "palevioletred": 0xDB7093, + "papayawhip": 0xFFEFD5, + "peachpuff": 0xFFDAB9, + "peru": 0xCD853F, + "pink": 0xFFC0CB, + "plum": 0xDDA0DD, + "powderblue": 0xB0E0E6, + "purple": 0x800080, + "rebeccapurple": 0x663399, + "red": 0xFF0000, + "rosybrown": 0xBC8F8F, + "royalblue": 0x4169E1, + "saddlebrown": 0x8B4513, + "salmon": 0xFA8072, + "sandybrown": 0xF4A460, + "seagreen": 0x2E8B57, + "seashell": 0xFFF5EE, + "sienna": 0xA0522D, + "silver": 0xC0C0C0, + "skyblue": 0x87CEEB, + "slateblue": 0x6A5ACD, + "slategray": 0x708090, + "slategrey": 0x708090, + "snow": 0xFFFAFA, + "springgreen": 0x00FF7F, + "steelblue": 0x4682B4, + "tan": 0xD2B48C, + "teal": 0x008080, + "thistle": 0xD8BFD8, + "tomato": 0xFF6347, + "turquoise": 0x40E0D0, + "violet": 0xEE82EE, + "wheat": 0xF5DEB3, + "white": 0xFFFFFF, + "whitesmoke": 0xF5F5F5, + "yellow": 0xFFFF00, + "yellowgreen": 0x9ACD32, +} + @schema_extractor("one_of") def color(value): if value == SCHEMA_EXTRACT: return ["hex color value", "color ID"] - return cv.Any(cv.int_, cv.use_id(ColorStruct))(value) + return cv.Any(cv.int_, cv.one_of(*COLOR_NAMES, lower=True), cv.use_id(ColorStruct))( + value + ) def color_retmapper(value): if isinstance(value, cv.Lambda): return cv.returning_lambda(value) + if isinstance(value, str) and value in COLOR_NAMES: + value = COLOR_NAMES[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): @@ -80,6 +242,8 @@ 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, str) and value.lower().endswith("px"): + value = cv.int_(value[:-2]) value = cv.Any(cv.int_, cv.percentage)(value) if isinstance(value, int): return value @@ -103,6 +267,9 @@ def angle(value): return int(cv.float_range(0.0, 360.0)(cv.angle(value)) * 10) +lv_angle = LValidator(angle, uint32) + + @schema_extractor("one_of") def size_validator(value): """A size in one axis - one of "size_content", a number (pixels) or a percentage""" @@ -110,10 +277,8 @@ def size_validator(value): 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 percentage or an integer (pixels)") + if isinstance(value, str) and value.upper() == "SIZE_CONTENT": + return "LV_SIZE_CONTENT" return pixels_or_percent_validator(value) @@ -132,7 +297,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 +306,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): @@ -167,7 +332,7 @@ def image_validator(value): lv_image = LValidator( image_validator, lv_img_t, - retmapper=lambda x: lv_expr.img_from(MockObj(x)), + retmapper=lambda x: MockObj(x, "->").get_lv_img_dsc(), requires="image", ) lv_bool = LValidator(cv.boolean, cg.bool_, retmapper=literal) @@ -239,9 +404,25 @@ class TextValidator(LValidator): lv_text = TextValidator() lv_float = LValidator(cv.float_, cg.float_) lv_int = LValidator(cv.int_, cg.int_) +lv_positive_int = LValidator(cv.positive_int, cg.int_) lv_brightness = LValidator(cv.percentage, cg.float_, retmapper=lambda x: int(x * 255)) +def gradient_mapper(value): + return MockObj(value) + + +def 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..37d6670b84 100644 --- a/esphome/components/lvgl/lvcode.py +++ b/esphome/components/lvgl/lvcode.py @@ -183,16 +183,11 @@ class LvContext(LambdaContext): 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())) - LvContext.added_lambda_count += 1 - 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)) + cg.add(expression) return expression def __call__(self, *args): diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index 89c9828740..70cfb859de 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -5,16 +5,12 @@ #include "lvgl_hal.h" #include "lvgl_esphome.h" +#include + 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 const char *const EVENT_NAMES[] = { "NONE", "PRESSED", @@ -69,30 +65,39 @@ std::string lv_event_code_name_for(uint8_t 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) - area->x1--; - if (!(area->x2 & 1)) - area->x2++; - if (area->y1 & 1) - area->y1--; - if (!(area->y2 & 1)) - area->y2++; + // cater for display driver chips with special requirements for bounds of partial + // draw areas. Extend the draw area to satisfy: + // * Coordinates must be a multiple of draw_rounding + auto *comp = static_cast(disp_drv->user_data); + auto draw_rounding = comp->draw_rounding; + // round down the start coordinates + area->x1 = area->x1 / draw_rounding * draw_rounding; + area->y1 = area->y1 / draw_rounding * draw_rounding; + // round up the end coordinates + area->x2 = (area->x2 + draw_rounding) / draw_rounding * draw_rounding - 1; + area->y2 = (area->y2 + draw_rounding) / draw_rounding * draw_rounding - 1; } 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::dump_config() { + ESP_LOGCONFIG(TAG, "LVGL:"); + ESP_LOGCONFIG(TAG, " Display width/height: %d x %d", this->disp_drv_.hor_res, this->disp_drv_.ver_res); + ESP_LOGCONFIG(TAG, " Rotation: %d", this->rotation); + ESP_LOGCONFIG(TAG, " Draw rounding: %d", (int) this->draw_rounding); +} 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()); } + this->pause_callbacks_.call(paused); } + 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); } @@ -133,19 +138,64 @@ void LvglComponent::show_prev_page(lv_scr_load_anim_t anim, uint32_t time) { } 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) { +void LvglComponent::draw_buffer_(const lv_area_t *area, lv_color_t *ptr) { + auto width = lv_area_get_width(area); + auto height = lv_area_get_height(area); + auto x1 = area->x1; + auto y1 = area->y1; + lv_color_t *dst = this->rotate_buf_; + switch (this->rotation) { + case display::DISPLAY_ROTATION_90_DEGREES: + for (lv_coord_t x = height; x-- != 0;) { + for (lv_coord_t y = 0; y != width; y++) { + dst[y * height + x] = *ptr++; + } + } + y1 = x1; + x1 = this->disp_drv_.ver_res - area->y1 - height; + width = height; + height = lv_area_get_width(area); + break; + + case display::DISPLAY_ROTATION_180_DEGREES: + for (lv_coord_t y = height; y-- != 0;) { + for (lv_coord_t x = width; x-- != 0;) { + dst[y * width + x] = *ptr++; + } + } + x1 = this->disp_drv_.hor_res - x1 - width; + y1 = this->disp_drv_.ver_res - y1 - height; + break; + + case display::DISPLAY_ROTATION_270_DEGREES: + for (lv_coord_t x = 0; x != height; x++) { + for (lv_coord_t y = width; y-- != 0;) { + dst[y * height + x] = *ptr++; + } + } + x1 = y1; + y1 = this->disp_drv_.hor_res - area->x1 - width; + width = height; + height = lv_area_get_width(area); + break; + + default: + dst = ptr; + break; + } 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); + ESP_LOGV(TAG, "draw buffer x1=%d, y1=%d, width=%d, height=%d", x1, y1, width, height); + display->draw_pixels_at(x1, y1, width, height, (const uint8_t *) dst, display::COLOR_ORDER_RGB, LV_BITNESS, + LV_COLOR_16_SWAP); } } void LvglComponent::flush_cb_(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { 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)); + this->draw_buffer_(area, color_p); + ESP_LOGVV(TAG, "flush_cb, area=%d/%d, %d/%d took %dms", area->x1, area->y1, lv_area_get_width(area), + lv_area_get_height(area), (int) (millis() - now)); } lv_disp_flush_ready(disp_drv); } @@ -160,6 +210,13 @@ IdleTrigger::IdleTrigger(LvglComponent *parent, TemplatableValue timeo }); } +PauseTrigger::PauseTrigger(LvglComponent *parent, TemplatableValue paused) : paused_(std::move(paused)) { + parent->add_on_pause_callback([this](bool pausing) { + if (this->paused_.value() == pausing) + this->trigger(); + }); +} + #ifdef USE_LVGL_TOUCHSCREEN LVTouchListener::LVTouchListener(uint16_t long_press_time, uint16_t long_press_repeat_time) { lv_indev_drv_init(&this->drv_); @@ -203,6 +260,39 @@ LVEncoderListener::LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_ } #endif // USE_LVGL_KEY_LISTENER +#if defined(USE_LVGL_DROPDOWN) || defined(LV_USE_ROLLER) +std::string LvSelectable::get_selected_text() { + auto selected = this->get_selected_index(); + if (selected >= this->options_.size()) + return ""; + return this->options_[selected]; +} + +static std::string join_string(std::vector options) { + return std::accumulate( + options.begin(), options.end(), std::string(), + [](const std::string &a, const std::string &b) -> std::string { return a + (a.length() > 0 ? "\n" : "") + b; }); +} + +void LvSelectable::set_selected_text(const std::string &text, lv_anim_enable_t anim) { + auto index = std::find(this->options_.begin(), this->options_.end(), text); + if (index != this->options_.end()) { + this->set_selected_index(index - this->options_.begin(), anim); + lv_event_send(this->obj, lv_api_event, nullptr); + } +} + +void LvSelectable::set_options(std::vector options) { + auto index = this->get_selected_index(); + if (index >= options.size()) + index = options.size() - 1; + this->options_ = std::move(options); + this->set_option_string(join_string(this->options_).c_str()); + lv_event_send(this->obj, LV_EVENT_REFRESH, nullptr); + this->set_selected_index(index, LV_ANIM_OFF); +} +#endif // USE_LVGL_DROPDOWN || LV_USE_ROLLER + #ifdef USE_LVGL_BUTTONMATRIX void LvButtonMatrixType::set_obj(lv_obj_t *lv_obj) { LvCompound::set_obj(lv_obj); @@ -261,45 +351,75 @@ void LvKeyboardType::set_obj(lv_obj_t *lv_obj) { #endif // USE_LVGL_KEYBOARD 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(); + int iterations = 6 - lv_disp_get_inactive_time(this->disp_) / 60000; + if (iterations <= 0) + iterations = 1; + while (iterations-- != 0) { + auto col = random_uint32() % this->disp_drv_.hor_res; + col = col / this->draw_rounding * this->draw_rounding; + auto row = random_uint32() % this->disp_drv_.ver_res; + row = row / this->draw_rounding * this->draw_rounding; + auto size = (random_uint32() % 32) / this->draw_rounding * this->draw_rounding - 1; + lv_area_t area; + area.x1 = col; + area.y1 = row; + area.x2 = col + size; + area.y2 = row + size; + if (area.x2 >= this->disp_drv_.hor_res) + area.x2 = this->disp_drv_.hor_res - 1; + if (area.y2 >= this->disp_drv_.ver_res) + area.y2 = this->disp_drv_.ver_res - 1; + + size_t line_len = lv_area_get_width(&area) * lv_area_get_height(&area) / 2; + for (size_t i = 0; i != line_len; i++) { + ((uint32_t *) (this->draw_buf_.buf1))[i] = random_uint32(); + } + this->draw_buffer_(&area, (lv_color_t *) this->draw_buf_.buf1); } - 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 - lv_log_register_print_cb(log_cb); -#endif +/** + * @class LvglComponent + * @brief Component for rendering LVGL. + * + * This component renders LVGL widgets on a display. Some initialisation must be done in the constructor + * since LVGL needs to be initialised before any widgets can be created. + * + * @param displays a list of displays to render onto. All displays must have the same + * resolution. + * @param buffer_frac the fraction of the display resolution to use for the LVGL + * draw buffer. A higher value will make animations smoother but + * also increase memory usage. + * @param full_refresh if true, the display will be fully refreshed on every frame. + * If false, only changed areas will be updated. + * @param draw_rounding the rounding to use when drawing. A value of 1 will draw + * without any rounding, a value of 2 will round to the nearest + * multiple of 2, and so on. + * @param resume_on_input if true, this component will resume rendering when the user + * presses a key or clicks on the screen. + */ +LvglComponent::LvglComponent(std::vector displays, float buffer_frac, bool full_refresh, + int draw_rounding, bool resume_on_input) + : draw_rounding(draw_rounding), + displays_(std::move(displays)), + buffer_frac_(buffer_frac), + full_refresh_(full_refresh), + resume_on_input_(resume_on_input) { lv_init(); 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; - 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; + this->rotation = display->get_rotation(); + if (this->rotation != display::DISPLAY_ROTATION_0_DEGREES) { + this->rotate_buf_ = static_cast(lv_custom_mem_alloc(buf_bytes)); // NOLINT + if (this->rotate_buf_ == nullptr) + return; } + auto *buf = lv_custom_mem_alloc(buf_bytes); // NOLINT + if (buf == nullptr) + 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_; @@ -307,33 +427,36 @@ void LvglComponent::setup() { 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); +} + +void LvglComponent::setup() { + if (this->draw_buf_.buf1 == nullptr) { + this->mark_failed(); + this->status_set_error("Memory allocation failure"); + return; + } + ESP_LOGCONFIG(TAG, "LVGL Setup starts"); +#if LV_USE_LOG + lv_log_register_print_cb([](const char *buf) { + auto next = strchr(buf, ')'); + if (next != nullptr) + buf = next + 1; + while (isspace(*buf)) + buf++; + esp_log_printf_(LVGL_LOG_LEVEL, TAG, 0, "%.*s", (int) strlen(buf) - 1, buf); + }); +#endif + // Rotation will be handled by our drawing function, so reset the display rotation. + for (auto *display : this->displays_) + display->set_rotation(display::DISPLAY_ROTATION_0_DEGREES); 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_) { @@ -348,56 +471,6 @@ 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) { - 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 // USE_LVGL_IMAGE #ifdef USE_LVGL_ANIMIMG void lv_animimg_stop(lv_obj_t *obj) { diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index e248530971..f357c4950c 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -4,6 +4,9 @@ #ifdef USE_BINARY_SENSOR #include "esphome/components/binary_sensor/binary_sensor.h" #endif // USE_BINARY_SENSOR +#ifdef USE_LVGL_IMAGE +#include "esphome/components/image/image.h" +#endif // USE_LVGL_IMAGE #ifdef USE_LVGL_ROTARY_ENCODER #include "esphome/components/rotary_encoder/rotary_encoder.h" #endif // USE_LVGL_ROTARY_ENCODER @@ -18,11 +21,9 @@ #include "esphome/core/component.h" #include "esphome/core/log.h" #include -#include #include -#ifdef USE_LVGL_IMAGE -#include "esphome/components/image/image.h" -#endif // USE_LVGL_IMAGE +#include +#include #ifdef USE_LVGL_FONT #include "esphome/components/font/font.h" @@ -41,10 +42,6 @@ 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); } -#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 @@ -53,6 +50,14 @@ static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BIT static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_332; #endif // LV_COLOR_DEPTH +#ifdef USE_LVGL_IMAGE +// Shortcut / overload, so that the source of an image can easily be updated +// from within a lambda. +inline void lv_img_set_src(lv_obj_t *obj, esphome::image::Image *image) { + lv_img_set_src(obj, image->get_lv_img_dsc()); +} +#endif // USE_LVGL_IMAGE + // Parent class for things that wrap an LVGL object class LvCompound { public: @@ -105,10 +110,6 @@ 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 - #ifdef USE_LVGL_ANIMIMG void lv_animimg_stop(lv_obj_t *obj); #endif // USE_LVGL_ANIMIMG @@ -117,6 +118,8 @@ class LvglComponent : public PollingComponent { constexpr static const char *const TAG = "lvgl"; public: + LvglComponent(std::vector displays, float buffer_frac, bool full_refresh, int draw_rounding, + bool resume_on_input); 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; } @@ -126,19 +129,27 @@ class LvglComponent : public PollingComponent { 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_on_pause_callback(std::function &&callback) { this->pause_callbacks_.add(std::move(callback)); } 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_; } + lv_obj_t *get_scr_act() { return lv_disp_get_scr_act(this->disp_); } + // Pause or resume the display. + // @param paused If true, pause the display. If false, resume the display. + // @param show_snow If true, show the snow effect when paused. void set_paused(bool paused, bool show_snow); + bool is_paused() const { return this->paused_; } + // If the display is paused and we have resume_on_input_ set to true, resume the display. + void maybe_wakeup() { + if (this->paused_ && this->resume_on_input_) { + this->set_paused(false, false); + } + } + 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); void show_next_page(lv_scr_load_anim_t anim, uint32_t time); @@ -151,12 +162,21 @@ class LvglComponent : public PollingComponent { lv_group_focus_obj(mark); } } + // rounding factor to align bounds of update area when drawing + size_t draw_rounding{2}; + + display::DisplayRotation rotation{display::DISPLAY_ROTATION_0_DEGREES}; protected: void write_random_(); - void draw_buffer_(const lv_area_t *area, const uint8_t *ptr); + void draw_buffer_(const lv_area_t *area, lv_color_t *ptr); void flush_cb_(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p); + std::vector displays_{}; + size_t buffer_frac_{1}; + bool full_refresh_{}; + bool resume_on_input_{}; + lv_disp_draw_buf_t draw_buf_{}; lv_disp_drv_t disp_drv_{}; lv_disp_t *disp_{}; @@ -164,14 +184,12 @@ class LvglComponent : public PollingComponent { std::vector pages_{}; size_t current_page_{0}; bool show_snow_{}; - lv_coord_t snow_line_{}; bool page_wrap_{true}; std::map focus_marks_{}; - std::vector> init_lambdas_; CallbackManager idle_callbacks_{}; - size_t buffer_frac_{1}; - bool full_refresh_{}; + CallbackManager pause_callbacks_{}; + lv_color_t *rotate_buf_{}; }; class IdleTrigger : public Trigger<> { @@ -183,6 +201,14 @@ class IdleTrigger : public Trigger<> { bool is_idle_{}; }; +class PauseTrigger : public Trigger<> { + public: + explicit PauseTrigger(LvglComponent *parent, TemplatableValue paused); + + protected: + TemplatableValue paused_; +}; + template class LvglAction : public Action, public Parented { public: explicit LvglAction(std::function &&lamb) : action_(std::move(lamb)) {} @@ -207,7 +233,10 @@ class LVTouchListener : public touchscreen::TouchListener, public Parentedparent_->maybe_wakeup(); + } lv_indev_drv_t *get_drv() { return &this->drv_; } protected: @@ -222,6 +251,7 @@ class LVEncoderListener : public Parented { public: LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_t lprt); +#ifdef USE_BINARY_SENSOR void set_left_button(binary_sensor::BinarySensor *left_button) { left_button->add_on_state_callback([this](bool state) { this->event(LV_KEY_LEFT, state); }); } @@ -232,6 +262,7 @@ class LVEncoderListener : public Parented { void set_enter_button(binary_sensor::BinarySensor *enter_button) { enter_button->add_on_state_callback([this](bool state) { this->event(LV_KEY_ENTER, state); }); } +#endif #ifdef USE_LVGL_ROTARY_ENCODER void set_sensor(rotary_encoder::RotaryEncoderSensor *sensor) { @@ -243,12 +274,18 @@ class LVEncoderListener : public Parented { if (!this->parent_->is_paused()) { this->pressed_ = pressed; this->key_ = key; + } else if (!pressed) { + // maybe wakeup on release if paused + this->parent_->maybe_wakeup(); } } void set_count(int32_t count) { - if (!this->parent_->is_paused()) + if (!this->parent_->is_paused()) { this->count_ = count; + } else { + this->parent_->maybe_wakeup(); + } } lv_indev_drv_t *get_drv() { return &this->drv_; } @@ -262,6 +299,48 @@ class LVEncoderListener : public Parented { }; #endif // USE_LVGL_KEY_LISTENER +#if defined(USE_LVGL_DROPDOWN) || defined(LV_USE_ROLLER) +class LvSelectable : public LvCompound { + public: + virtual size_t get_selected_index() = 0; + virtual void set_selected_index(size_t index, lv_anim_enable_t anim) = 0; + void set_selected_text(const std::string &text, lv_anim_enable_t anim); + std::string get_selected_text(); + std::vector get_options() { return this->options_; } + void set_options(std::vector options); + + protected: + virtual void set_option_string(const char *options) = 0; + std::vector options_{}; +}; + +#ifdef USE_LVGL_DROPDOWN +class LvDropdownType : public LvSelectable { + public: + size_t get_selected_index() override { return lv_dropdown_get_selected(this->obj); } + void set_selected_index(size_t index, lv_anim_enable_t anim) override { lv_dropdown_set_selected(this->obj, index); } + + protected: + void set_option_string(const char *options) override { lv_dropdown_set_options(this->obj, options); } +}; +#endif // USE_LVGL_DROPDOWN + +#ifdef USE_LVGL_ROLLER +class LvRollerType : public LvSelectable { + public: + size_t get_selected_index() override { return lv_roller_get_selected(this->obj); } + void set_selected_index(size_t index, lv_anim_enable_t anim) override { + lv_roller_set_selected(this->obj, index, anim); + } + void set_mode(lv_roller_mode_t mode) { this->mode_ = mode; } + + protected: + void set_option_string(const char *options) override { lv_roller_set_options(this->obj, options, this->mode_); } + lv_roller_mode_t mode_{LV_ROLLER_MODE_NORMAL}; +}; +#endif +#endif // defined(USE_LVGL_DROPDOWN) || defined(LV_USE_ROLLER) + #ifdef USE_LVGL_BUTTONMATRIX class LvButtonMatrixType : public key_provider::KeyProvider, public LvCompound { public: diff --git a/esphome/components/lvgl/lvgl_proxy.h b/esphome/components/lvgl/lvgl_proxy.h new file mode 100644 index 0000000000..0ccd80e541 --- /dev/null +++ b/esphome/components/lvgl/lvgl_proxy.h @@ -0,0 +1,17 @@ +#pragma once +/** +* This header is for use in components that might or might not use LVGL. There is a platformio bug where +the mere mention of a header file, even if ifdefed, causes the build to fail. This is a workaround, since if this +file is included in the build, LVGL is always included. +*/ +#ifdef USE_LVGL +// required for clang-tidy +#ifndef LV_CONF_H +#define LV_CONF_SKIP 1 // NOLINT +#endif // LV_CONF_H + +#include +namespace esphome { +namespace lvgl {} // namespace lvgl +} // namespace esphome +#endif // USE_LVGL diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index 9ff0fec5bc..bb14c11ddd 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, @@ -91,12 +91,13 @@ STYLE_PROPS = { "arc_opa": lvalid.opacity, "arc_color": lvalid.lv_color, "arc_rounded": lvalid.lv_bool, - "arc_width": cv.positive_int, + "arc_width": lvalid.lv_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, @@ -110,7 +111,7 @@ STYLE_PROPS = { "border_side": df.LvConstant( "LV_BORDER_SIDE_", "NONE", "TOP", "BOTTOM", "LEFT", "RIGHT", "INTERNAL" ).several_of, - "border_width": cv.positive_int, + "border_width": lvalid.lv_positive_int, "clip_corner": lvalid.lv_bool, "color_filter_opa": lvalid.opacity, "height": lvalid.size, @@ -133,11 +134,11 @@ STYLE_PROPS = { "pad_right": lvalid.pixels, "pad_top": lvalid.pixels, "shadow_color": lvalid.lv_color, - "shadow_ofs_x": cv.int_, - "shadow_ofs_y": cv.int_, + "shadow_ofs_x": lvalid.lv_int, + "shadow_ofs_y": lvalid.lv_int, "shadow_opa": lvalid.opacity, - "shadow_spread": cv.int_, - "shadow_width": cv.positive_int, + "shadow_spread": lvalid.lv_int, + "shadow_width": lvalid.lv_positive_int, "text_align": df.LvConstant( "LV_TEXT_ALIGN_", "LEFT", "CENTER", "RIGHT", "AUTO" ).one_of, @@ -149,7 +150,7 @@ STYLE_PROPS = { "text_letter_space": cv.positive_int, "text_line_space": cv.positive_int, "text_opa": lvalid.opacity, - "transform_angle": lvalid.angle, + "transform_angle": lvalid.lv_angle, "transform_height": lvalid.pixels_or_percent, "transform_pivot_x": lvalid.pixels_or_percent, "transform_pivot_y": lvalid.pixels_or_percent, @@ -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, @@ -215,7 +216,7 @@ def automation_schema(typ: LvType): events = df.LV_EVENT_TRIGGERS + (CONF_ON_VALUE,) else: events = df.LV_EVENT_TRIGGERS - args = [typ.get_arg_type()] if isinstance(typ, LvType) else [] + args = typ.get_arg_type() if isinstance(typ, LvType) else [] args.append(lv_event_t_ptr) return { cv.Optional(event): validate_automation( diff --git a/esphome/components/lvgl/select/__init__.py b/esphome/components/lvgl/select/__init__.py index 73ac50aa55..5e50b6b385 100644 --- a/esphome/components/lvgl/select/__init__.py +++ b/esphome/components/lvgl/select/__init__.py @@ -3,18 +3,10 @@ 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 ( - API_EVENT, - EVENT_ARG, - UPDATE_EVENT, - LambdaContext, - LvContext, - lv, - lv_add, -) +from ..defines import CONF_ANIMATED, CONF_LVGL_ID, CONF_WIDGET, literal +from ..lvcode import LvContext from ..schemas import LVGL_SCHEMA -from ..types import LV_EVENT, LvSelect, lvgl_ns +from ..types import LvSelect, lvgl_ns from ..widgets import get_widgets, wait_for_widgets LVGLSelect = lvgl_ns.class_("LVGLSelect", select.Select) @@ -38,20 +30,10 @@ async def to_code(config): 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: - 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( - paren.add_event_cb( - widget.obj, - await pub_ctx.get_lambda(), - LV_EVENT.VALUE_CHANGED, - UPDATE_EVENT, + selector.set_widget( + widget.var, + literal("LV_ANIM_ON" if config[CONF_ANIMATED] else "LV_ANIM_OFF"), ) ) - 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 index 97cc8697eb..4538e339c3 100644 --- a/esphome/components/lvgl/select/lvgl_select.h +++ b/esphome/components/lvgl/select/lvgl_select.h @@ -6,58 +6,52 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/preferences.h" +#include "../lvgl.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_ = std::move(lambda); + void set_widget(LvSelectable *widget, lv_anim_enable_t anim = LV_ANIM_OFF) { + this->widget_ = widget; + this->anim_ = anim; + this->set_options_(); + lv_obj_add_event_cb( + this->widget_->obj, + [](lv_event_t *e) { + auto *it = static_cast(e->user_data); + it->set_options_(); + }, + LV_EVENT_REFRESH, this); if (this->initial_state_.has_value()) { this->control(this->initial_state_.value()); this->initial_state_.reset(); } + this->publish(); + auto lamb = [](lv_event_t *e) { + auto *self = static_cast(e->user_data); + self->publish(); + }; + lv_obj_add_event_cb(this->widget_->obj, lamb, LV_EVENT_VALUE_CHANGED, this); + lv_obj_add_event_cb(this->widget_->obj, lamb, lv_update_event, this); } - 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)); } + void publish() { this->publish_state(this->widget_->get_selected_text()); } 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()); + if (this->widget_ != nullptr) { + this->widget_->set_selected_text(value, this->anim_); } else { - this->initial_state_ = value.c_str(); + this->initial_state_ = value; } } + void set_options_() { this->traits.set_options(this->widget_->get_options()); } - std::function control_lambda_{}; - optional initial_state_{}; + LvSelectable *widget_{}; + optional initial_state_{}; + lv_anim_enable_t anim_{LV_ANIM_OFF}; }; } // namespace lvgl diff --git a/esphome/components/lvgl/styles.py b/esphome/components/lvgl/styles.py index 26c2694a52..6332e0976f 100644 --- a/esphome/components/lvgl/styles.py +++ b/esphome/components/lvgl/styles.py @@ -12,13 +12,11 @@ from .defines import ( ) from .helpers import add_lv_use from .lvcode import LambdaContext, LocalVariable, lv, lv_assign, lv_variable -from .schemas import ALL_STYLES +from .schemas import ALL_STYLES, STYLE_REMAP from .types import lv_lambda_t, lv_obj_t, lv_obj_t_ptr 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())") - async def styles_to_code(config): """Convert styles to C__ code.""" @@ -31,7 +29,8 @@ async def styles_to_code(config): value = await validator.process(value) if isinstance(value, list): value = "|".join(value) - lv.call(f"style_set_{prop}", svar, literal(value)) + remapped_prop = STYLE_REMAP.get(prop, prop) + lv.call(f"style_set_{remapped_prop}", svar, literal(value)) async def theme_to_code(config): @@ -50,9 +49,10 @@ async def theme_to_code(config): lv_assign(apply, await context.get_lambda()) -async def add_top_layer(config): +async def add_top_layer(lv_component, config): + top_layer = lv.disp_get_layer_top(lv_component.get_disp()) if top_conf := config.get(CONF_TOP_LAYER): - with LocalVariable("top_layer", lv_obj_t, TOP_LAYER) as top_layer_obj: + 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/text/__init__.py b/esphome/components/lvgl/text/__init__.py index 540591d24b..a59e703591 100644 --- a/esphome/components/lvgl/text/__init__.py +++ b/esphome/components/lvgl/text/__init__.py @@ -34,13 +34,13 @@ async def to_code(config): 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) + await widget.set_property("text", "text_value.c_str()") + lv.event_send(widget.obj, API_EVENT, cg.nullptr) control.add(textvar.publish_state(widget.get_value())) async with LambdaContext(EVENT_ARG) as lamb: lv_add(textvar.publish_state(widget.get_value())) async with LvContext(paren): - widget.var.set_control_lambda(await control.get_lambda()) + lv_add(textvar.set_control_lambda(await control.get_lambda())) lv_add( paren.add_event_cb( widget.obj, diff --git a/esphome/components/lvgl/trigger.py b/esphome/components/lvgl/trigger.py index 5288745fab..eb6e483203 100644 --- a/esphome/components/lvgl/trigger.py +++ b/esphome/components/lvgl/trigger.py @@ -67,9 +67,9 @@ async def add_trigger(conf, lv_component, w, *events): tid = conf[CONF_TRIGGER_ID] trigger = cg.new_Pvariable(tid) args = w.get_args() + [(lv_event_t_ptr, "event")] - value = w.get_value() + value = w.get_values() 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, literal("event"))) + 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 e4735ea58d..b504f24674 100644 --- a/esphome/components/lvgl/types.py +++ b/esphome/components/lvgl/types.py @@ -18,7 +18,9 @@ class LvType(cg.MockObjClass): self.value_property = None def get_arg_type(self): - return self.args[0][0] if len(self.args) else None + if len(self.args) == 0: + return None + return [arg[0] for arg in self.args] class LvNumber(LvType): @@ -40,6 +42,7 @@ 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()) +PauseTrigger = lvgl_ns.class_("PauseTrigger", automation.Trigger.template()) ObjUpdateAction = lvgl_ns.class_("ObjUpdateAction", automation.Action) LvglCondition = lvgl_ns.class_("LvglCondition", automation.Condition) LvglAction = lvgl_ns.class_("LvglAction", automation.Action) @@ -59,6 +62,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="") @@ -90,11 +94,13 @@ class LvBoolean(LvType): class LvSelect(LvType): def __init__(self, *args, **kwargs): + parens = kwargs.pop("parents", ()) + (LvCompound,) super().__init__( *args, - largs=[(cg.int_, "x")], - lvalue=lambda w: w.get_property("selected"), + largs=[(cg.int_, "x"), (cg.std_string, "text")], + lvalue=lambda w: [w.var.get_selected_index(), w.var.get_selected_text()], has_on_value=True, + parents=parens, **kwargs, ) diff --git a/esphome/components/lvgl/widgets/__init__.py b/esphome/components/lvgl/widgets/__init__.py index ae06bf20b0..e946a96000 100644 --- a/esphome/components/lvgl/widgets/__init__.py +++ b/esphome/components/lvgl/widgets/__init__.py @@ -52,31 +52,17 @@ from ..types import LV_STATE, LvType, WidgetType, lv_coord_t, lv_obj_t, lv_obj_t EVENT_LAMB = "event_lamb__" theme_widget_map = {} - - -class LvScrActType(WidgetType): - """ - A "widget" representing the active screen. - """ - - def __init__(self): - super().__init__("lv_scr_act()", lv_obj_t, ()) - - async def to_code(self, w, config: dict): - return [] +styles_used = set() class Widget: """ Represents a Widget. + This class has a lot of methods. Adding any more runs foul of lint checks ("too many public methods"). """ widgets_completed = False - @staticmethod - def set_completed(): - Widget.widgets_completed = True - def __init__(self, var, wtype: WidgetType, config: dict = None): self.var = var self.type = wtype @@ -89,6 +75,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): @@ -156,6 +144,7 @@ class Widget: def set_style(self, prop, value, state): if value is None: return + styles_used.add(prop) lv.call(f"obj_set_style_{prop}", self.obj, value, state) def __type_base(self): @@ -175,9 +164,20 @@ class Widget: def get_value(self): if isinstance(self.type.w_type, LvType): - return self.type.w_type.value(self) + result = self.type.w_type.value(self) + if isinstance(result, list): + return result[0] + return result return self.obj + def get_values(self): + if isinstance(self.type.w_type, LvType): + result = self.type.w_type.value(self) + if isinstance(result, list): + return result + return [result] + return [self.obj] + def get_number_value(self): value = self.type.mock_obj.get_value(self.obj) if self.scale == 1.0: @@ -209,6 +209,25 @@ class Widget: widget_map: dict[Any, Widget] = {} +class LvScrActType(WidgetType): + """ + A "widget" representing the active screen. + """ + + def __init__(self): + super().__init__("lv_scr_act()", lv_obj_t, ()) + + async def to_code(self, w, config: dict): + return [] + + +lv_scr_act_spec = LvScrActType() + + +def get_scr_act(lv_comp: MockObj) -> Widget: + return Widget.create(None, lv_comp.get_scr_act(), lv_scr_act_spec, {}) + + def get_widget_generator(wid): """ Used to wait for a widget during code generation. @@ -439,7 +458,3 @@ async def widget_to_code(w_cnfig, w_type: WidgetType, parent): 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, literal("lv_scr_act()"), lv_scr_act_spec, {}) diff --git a/esphome/components/lvgl/widgets/animimg.py b/esphome/components/lvgl/widgets/animimg.py index a973ca0702..3b20008c3d 100644 --- a/esphome/components/lvgl/widgets/animimg.py +++ b/esphome/components/lvgl/widgets/animimg.py @@ -2,13 +2,12 @@ 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 ..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 ..lvcode import lv from ..types import LvType, ObjUpdateAction, void_ptr from . import Widget, WidgetType, get_widgets from .img import CONF_IMAGE @@ -63,7 +62,7 @@ class AnimimgType(WidgetType): 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]] + srcs = [await lv_image.process(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) @@ -73,7 +72,7 @@ class AnimimgType(WidgetType): lv.animimg_start(w.obj) def get_uses(self): - return CONF_IMAGE, CONF_LABEL + return "img", CONF_IMAGE, CONF_LABEL animimg_spec = AnimimgType() diff --git a/esphome/components/lvgl/widgets/dropdown.py b/esphome/components/lvgl/widgets/dropdown.py index dc0346b080..a6bfc6bb88 100644 --- a/esphome/components/lvgl/widgets/dropdown.py +++ b/esphome/components/lvgl/widgets/dropdown.py @@ -1,4 +1,3 @@ -import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_OPTIONS @@ -6,29 +5,37 @@ from ..defines import ( CONF_DIR, CONF_INDICATOR, CONF_MAIN, + CONF_SCROLLBAR, + CONF_SELECTED, CONF_SELECTED_INDEX, + CONF_SELECTED_TEXT, CONF_SYMBOL, DIRECTIONS, literal, ) +from ..helpers import lvgl_components_required from ..lv_validation import lv_int, lv_text, option_string -from ..lvcode import LocalVariable, lv, lv_expr +from ..lvcode import LocalVariable, lv, lv_add, lv_expr from ..schemas import part_schema -from ..types import LvSelect, LvType, lv_obj_t +from ..types import LvCompound, LvSelect, LvType, lv_obj_t from . import Widget, WidgetType, set_obj_properties from .label import CONF_LABEL CONF_DROPDOWN = "dropdown" CONF_DROPDOWN_LIST = "dropdown_list" -lv_dropdown_t = LvSelect("lv_dropdown_t") +lv_dropdown_t = LvSelect("LvDropdownType", parents=(LvCompound,)) + lv_dropdown_list_t = LvType("lv_dropdown_list_t") -dropdown_list_spec = WidgetType(CONF_DROPDOWN_LIST, lv_dropdown_list_t, (CONF_MAIN,)) +dropdown_list_spec = WidgetType( + CONF_DROPDOWN_LIST, lv_dropdown_list_t, (CONF_MAIN, CONF_SELECTED, CONF_SCROLLBAR) +) DROPDOWN_BASE_SCHEMA = cv.Schema( { cv.Optional(CONF_SYMBOL): lv_text, - cv.Optional(CONF_SELECTED_INDEX): cv.templatable(cv.int_), + cv.Exclusive(CONF_SELECTED_INDEX, CONF_SELECTED_TEXT): lv_int, + cv.Exclusive(CONF_SELECTED_TEXT, CONF_SELECTED_TEXT): lv_text, cv.Optional(CONF_DIR, default="BOTTOM"): DIRECTIONS.one_of, cv.Optional(CONF_DROPDOWN_LIST): part_schema(dropdown_list_spec), } @@ -40,6 +47,12 @@ DROPDOWN_SCHEMA = DROPDOWN_BASE_SCHEMA.extend( } ) +DROPDOWN_UPDATE_SCHEMA = DROPDOWN_BASE_SCHEMA.extend( + { + cv.Optional(CONF_OPTIONS): cv.ensure_list(option_string), + } +) + class DropdownType(WidgetType): def __init__(self): @@ -48,18 +61,21 @@ class DropdownType(WidgetType): lv_dropdown_t, (CONF_MAIN, CONF_INDICATOR), DROPDOWN_SCHEMA, - DROPDOWN_BASE_SCHEMA, + modify_schema=DROPDOWN_UPDATE_SCHEMA, ) async def to_code(self, w: Widget, config): + lvgl_components_required.add(CONF_DROPDOWN) if options := config.get(CONF_OPTIONS): - text = cg.safe_exp("\n".join(options)) - lv.dropdown_set_options(w.obj, text) + lv_add(w.var.set_options(options)) if symbol := config.get(CONF_SYMBOL): - lv.dropdown_set_symbol(w.obj, await lv_text.process(symbol)) + lv.dropdown_set_symbol(w.var.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) + lv_add(w.var.set_selected_index(value, literal("LV_ANIM_OFF"))) + if (selected := config.get(CONF_SELECTED_TEXT)) is not None: + value = await lv_text.process(selected) + lv_add(w.var.set_selected_text(value, literal("LV_ANIM_OFF"))) if dirn := config.get(CONF_DIR): lv.dropdown_set_dir(w.obj, literal(dirn)) if dlist := config.get(CONF_DROPDOWN_LIST): diff --git a/esphome/components/lvgl/widgets/meter.py b/esphome/components/lvgl/widgets/meter.py index 7cf154d6f3..cd61d1c775 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,7 +18,9 @@ from esphome.const import ( from ..automation import action_to_code from ..defines import ( CONF_END_VALUE, + CONF_INDICATOR, CONF_MAIN, + CONF_OPA, CONF_PIVOT_X, CONF_PIVOT_Y, CONF_SRC, @@ -33,10 +36,11 @@ from ..lv_validation import ( lv_color, lv_float, lv_image, + opacity, requires_component, size, ) -from ..lvcode import LocalVariable, lv, lv_assign, lv_expr +from ..lvcode import LocalVariable, lv, lv_assign, lv_expr, lv_obj from ..types import LvType, ObjUpdateAction from . import Widget, WidgetType, get_widgets from .arc import CONF_ARC @@ -74,6 +78,7 @@ INDICATOR_LINE_SCHEMA = cv.Schema( cv.Optional(CONF_COLOR, default=0): lv_color, cv.Optional(CONF_R_MOD, default=0): size, cv.Optional(CONF_VALUE): lv_float, + cv.Optional(CONF_OPA): opacity, } ) INDICATOR_IMG_SCHEMA = cv.Schema( @@ -82,6 +87,7 @@ INDICATOR_IMG_SCHEMA = cv.Schema( cv.Required(CONF_PIVOT_X): pixels, cv.Required(CONF_PIVOT_Y): pixels, cv.Optional(CONF_VALUE): lv_float, + cv.Optional(CONF_OPA): opacity, } ) INDICATOR_ARC_SCHEMA = cv.Schema( @@ -92,6 +98,7 @@ INDICATOR_ARC_SCHEMA = cv.Schema( 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_OPA): opacity, } ) INDICATOR_TICKS_SCHEMA = cv.Schema( @@ -165,7 +172,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""" @@ -211,9 +223,7 @@ class MeterType(WidgetType): for indicator in scale_conf.get(CONF_INDICATORS, ()): (t, v) = next(iter(indicator.items())) iid = v[CONF_ID] - ivar = cg.new_variable( - iid, cg.nullptr, type_=lv_meter_indicator_t_ptr - ) + ivar = cg.Pvariable(iid, cg.nullptr, type_=lv_meter_indicator_t) # Enable getting the meter to which this belongs. wid = Widget.create(iid, var, obj_spec, v) wid.obj = ivar @@ -261,9 +271,7 @@ class MeterType(WidgetType): 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) + await set_indicator_values(var, ivar, v) meter_spec = MeterType() @@ -278,21 +286,22 @@ meter_spec = MeterType() 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_OPA): opacity, } ), ) 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) + await set_indicator_values(w.var, w.obj, config) return await action_to_code(widget, set_value, action_id, template_arg, args) -def set_indicator_values(meter, indicator, start_value, end_value): +async def set_indicator_values(meter, indicator, config): + start_value = await get_start_value(config) + end_value = await get_end_value(config) if start_value is not None: if end_value is None: lv.meter_set_indicator_value(meter, indicator, start_value) @@ -300,3 +309,6 @@ def set_indicator_values(meter, indicator, start_value, end_value): lv.meter_set_indicator_start_value(meter, indicator, start_value) if end_value is not None: lv.meter_set_indicator_end_value(meter, indicator, end_value) + if (opa := config.get(CONF_OPA)) is not None: + lv_assign(indicator.opa, await opacity.process(opa)) + lv_obj.invalidate(meter) diff --git a/esphome/components/lvgl/widgets/msgbox.py b/esphome/components/lvgl/widgets/msgbox.py index c377af6bde..be0f2100d7 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, @@ -19,14 +20,14 @@ from ..lvcode import ( EVENT_ARG, LambdaContext, LocalVariable, + lv, lv_add, lv_assign, lv_expr, lv_obj, lv_Pvariable, ) -from ..schemas import STYLE_SCHEMA, STYLED_TEXT_SCHEMA, container_schema -from ..styles import TOP_LAYER +from ..schemas import STYLE_SCHEMA, STYLED_TEXT_SCHEMA, container_schema, part_schema from ..types import LV_EVENT, char_ptr, lv_obj_t from . import Widget, set_obj_properties from .button import button_spec @@ -48,16 +49,17 @@ 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), } ), ) -async def msgbox_to_code(conf): +async def msgbox_to_code(top_layer, conf): """ Construct a message box. This consists of a full-screen translucent background enclosing a centered container with an optional title, body, close button and a button matrix. And any other widgets the user cares to add @@ -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,12 +98,10 @@ 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_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) @@ -111,25 +115,33 @@ 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) -async def msgboxes_to_code(config): +async def msgboxes_to_code(lv_component, config): + top_layer = lv.disp_get_layer_top(lv_component.get_disp()) for conf in config.get(CONF_MSGBOXES, ()): - await msgbox_to_code(conf) + await msgbox_to_code(top_layer, conf) diff --git a/esphome/components/lvgl/widgets/obj.py b/esphome/components/lvgl/widgets/obj.py index 20a24c86f6..afb4c97f33 100644 --- a/esphome/components/lvgl/widgets/obj.py +++ b/esphome/components/lvgl/widgets/obj.py @@ -1,7 +1,7 @@ from esphome import automation from ..automation import update_to_code -from ..defines import CONF_MAIN, CONF_OBJ +from ..defines import CONF_MAIN, CONF_OBJ, CONF_SCROLLBAR from ..schemas import create_modify_schema from ..types import ObjUpdateAction, WidgetType, lv_obj_t @@ -12,7 +12,9 @@ class ObjType(WidgetType): """ def __init__(self): - super().__init__(CONF_OBJ, lv_obj_t, (CONF_MAIN,), schema={}, modify_schema={}) + super().__init__( + CONF_OBJ, lv_obj_t, (CONF_MAIN, CONF_SCROLLBAR), schema={}, modify_schema={} + ) async def to_code(self, w, config): return [] diff --git a/esphome/components/lvgl/widgets/qrcode.py b/esphome/components/lvgl/widgets/qrcode.py new file mode 100644 index 0000000000..742b538938 --- /dev/null +++ b/esphome/components/lvgl/widgets/qrcode.py @@ -0,0 +1,54 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import CONF_SIZE, CONF_TEXT +from esphome.cpp_generator import MockObjClass + +from ..defines import CONF_MAIN, literal +from ..lv_validation import color, color_retmapper, lv_text +from ..lvcode import LocalVariable, lv, lv_expr +from ..schemas import TEXT_SCHEMA +from ..types import WidgetType, lv_obj_t +from . import Widget + +CONF_QRCODE = "qrcode" +CONF_DARK_COLOR = "dark_color" +CONF_LIGHT_COLOR = "light_color" + +QRCODE_SCHEMA = TEXT_SCHEMA.extend( + { + cv.Optional(CONF_DARK_COLOR, default="black"): color, + cv.Optional(CONF_LIGHT_COLOR, default="white"): color, + cv.Required(CONF_SIZE): cv.int_, + } +) + + +class QrCodeType(WidgetType): + def __init__(self): + super().__init__( + CONF_QRCODE, + lv_obj_t, + (CONF_MAIN,), + QRCODE_SCHEMA, + modify_schema=TEXT_SCHEMA, + ) + + def get_uses(self): + return ("canvas", "img") + + def obj_creator(self, parent: MockObjClass, config: dict): + dark_color = color_retmapper(config[CONF_DARK_COLOR]) + light_color = color_retmapper(config[CONF_LIGHT_COLOR]) + size = config[CONF_SIZE] + return lv_expr.call("qrcode_create", parent, size, dark_color, light_color) + + async def to_code(self, w: Widget, config): + if (value := config.get(CONF_TEXT)) is not None: + value = await lv_text.process(value) + with LocalVariable( + "qr_text", cg.const_char_ptr, value, modifier="" + ) as str_obj: + lv.qrcode_update(w.obj, str_obj, literal(f"strlen({str_obj})")) + + +qr_code_spec = QrCodeType() diff --git a/esphome/components/lvgl/widgets/roller.py b/esphome/components/lvgl/widgets/roller.py index 50fdf6113c..6f9fee47d4 100644 --- a/esphome/components/lvgl/widgets/roller.py +++ b/esphome/components/lvgl/widgets/roller.py @@ -1,4 +1,3 @@ -import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_MODE, CONF_OPTIONS @@ -7,36 +6,40 @@ from ..defines import ( CONF_MAIN, CONF_SELECTED, CONF_SELECTED_INDEX, + CONF_SELECTED_TEXT, CONF_VISIBLE_ROW_COUNT, ROLLER_MODES, literal, ) -from ..lv_validation import animated, lv_int, option_string -from ..lvcode import lv +from ..helpers import lvgl_components_required +from ..lv_validation import animated, lv_int, lv_text, option_string +from ..lvcode import lv_add from ..types import LvSelect from . import WidgetType from .label import CONF_LABEL CONF_ROLLER = "roller" -lv_roller_t = LvSelect("lv_roller_t") +lv_roller_t = LvSelect("LvRollerType") ROLLER_BASE_SCHEMA = cv.Schema( { - cv.Optional(CONF_SELECTED_INDEX): cv.templatable(cv.int_), + cv.Exclusive(CONF_SELECTED_INDEX, CONF_SELECTED_TEXT): lv_int, + cv.Exclusive(CONF_SELECTED_TEXT, CONF_SELECTED_TEXT): lv_text, cv.Optional(CONF_VISIBLE_ROW_COUNT): lv_int, + cv.Optional(CONF_MODE): ROLLER_MODES.one_of, } ) 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, + cv.Optional(CONF_OPTIONS): cv.ensure_list(option_string), } ) @@ -52,15 +55,19 @@ class RollerType(WidgetType): ) async def to_code(self, w, config): + lvgl_components_required.add(CONF_ROLLER) + if mode := config.get(CONF_MODE): + mode = await ROLLER_MODES.process(mode) + lv_add(w.var.set_mode(mode)) 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) + lv_add(w.var.set_options(options)) + animopt = literal(config.get(CONF_ANIMATED, "LV_ANIM_OFF")) + if (selected := config.get(CONF_SELECTED_INDEX)) is not None: + value = await lv_int.process(selected) + lv_add(w.var.set_selected_index(value, animopt)) + if (selected := config.get(CONF_SELECTED_TEXT)) is not None: + value = await lv_text.process(selected) + lv_add(w.var.set_selected_text(value, animopt)) await w.set_property( CONF_VISIBLE_ROW_COUNT, await lv_int.process(config.get(CONF_VISIBLE_ROW_COUNT)), diff --git a/esphome/components/lvgl/widgets/tileview.py b/esphome/components/lvgl/widgets/tileview.py index 05259fbd3c..3865d404e2 100644 --- a/esphome/components/lvgl/widgets/tileview.py +++ b/esphome/components/lvgl/widgets/tileview.py @@ -9,6 +9,7 @@ from ..defines import ( CONF_COLUMN, CONF_DIR, CONF_MAIN, + CONF_SCROLLBAR, CONF_TILE_ID, CONF_TILES, TILE_DIRECTIONS, @@ -56,7 +57,7 @@ class TileviewType(WidgetType): super().__init__( CONF_TILEVIEW, lv_tileview_t, - (CONF_MAIN,), + (CONF_MAIN, CONF_SCROLLBAR), schema=TILEVIEW_SCHEMA, modify_schema={}, ) diff --git a/esphome/components/max17043/__init__.py b/esphome/components/max17043/__init__.py new file mode 100644 index 0000000000..1db25ccdd6 --- /dev/null +++ b/esphome/components/max17043/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@blacknell"] diff --git a/esphome/components/max17043/automation.h b/esphome/components/max17043/automation.h new file mode 100644 index 0000000000..44729d119b --- /dev/null +++ b/esphome/components/max17043/automation.h @@ -0,0 +1,20 @@ + +#pragma once +#include "esphome/core/automation.h" +#include "max17043.h" + +namespace esphome { +namespace max17043 { + +template class SleepAction : public Action { + public: + explicit SleepAction(MAX17043Component *max17043) : max17043_(max17043) {} + + void play(Ts... x) override { this->max17043_->sleep_mode(); } + + protected: + MAX17043Component *max17043_; +}; + +} // namespace max17043 +} // namespace esphome diff --git a/esphome/components/max17043/max17043.cpp b/esphome/components/max17043/max17043.cpp new file mode 100644 index 0000000000..4a83320455 --- /dev/null +++ b/esphome/components/max17043/max17043.cpp @@ -0,0 +1,98 @@ +#include "max17043.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace max17043 { + +// MAX174043 is a 1-Cell Fuel Gauge with ModelGauge and Low-Battery Alert +// Consult the datasheet at https://www.analog.com/en/products/max17043.html + +static const char *const TAG = "max17043"; + +static const uint8_t MAX17043_VCELL = 0x02; +static const uint8_t MAX17043_SOC = 0x04; +static const uint8_t MAX17043_CONFIG = 0x0c; + +static const uint16_t MAX17043_CONFIG_POWER_UP_DEFAULT = 0x971C; +static const uint16_t MAX17043_CONFIG_SAFE_MASK = 0xFF1F; // mask out sleep bit (7), unused bit (6) and alert bit (4) +static const uint16_t MAX17043_CONFIG_SLEEP_MASK = 0x0080; + +void MAX17043Component::update() { + uint16_t raw_voltage, raw_percent; + + if (this->voltage_sensor_ != nullptr) { + if (!this->read_byte_16(MAX17043_VCELL, &raw_voltage)) { + this->status_set_warning("Unable to read MAX17043_VCELL"); + } else { + float voltage = (1.25 * (float) (raw_voltage >> 4)) / 1000.0; + this->voltage_sensor_->publish_state(voltage); + this->status_clear_warning(); + } + } + if (this->battery_remaining_sensor_ != nullptr) { + if (!this->read_byte_16(MAX17043_SOC, &raw_percent)) { + this->status_set_warning("Unable to read MAX17043_SOC"); + } else { + float percent = (float) ((raw_percent >> 8) + 0.003906f * (raw_percent & 0x00ff)); + this->battery_remaining_sensor_->publish_state(percent); + this->status_clear_warning(); + } + } +} + +void MAX17043Component::setup() { + ESP_LOGCONFIG(TAG, "Setting up MAX17043..."); + + uint16_t config_reg; + if (this->write(&MAX17043_CONFIG, 1) != i2c::ERROR_OK) { + this->status_set_warning(); + return; + } + + if (this->read(reinterpret_cast(&config_reg), 2) != i2c::ERROR_OK) { + this->status_set_warning(); + return; + } + + config_reg = i2c::i2ctohs(config_reg) & MAX17043_CONFIG_SAFE_MASK; + ESP_LOGV(TAG, "MAX17043 CONFIG register reads 0x%X", config_reg); + + if (config_reg != MAX17043_CONFIG_POWER_UP_DEFAULT) { + ESP_LOGE(TAG, "Device does not appear to be a MAX17043"); + this->status_set_error("unrecognised"); + this->mark_failed(); + return; + } + + // need to write back to config register to reset the sleep bit + if (!this->write_byte_16(MAX17043_CONFIG, MAX17043_CONFIG_POWER_UP_DEFAULT)) { + this->status_set_error("sleep reset failed"); + this->mark_failed(); + return; + } +} + +void MAX17043Component::dump_config() { + ESP_LOGCONFIG(TAG, "MAX17043:"); + LOG_I2C_DEVICE(this); + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with MAX17043 failed"); + } + LOG_UPDATE_INTERVAL(this); + LOG_SENSOR(" ", "Battery Voltage", this->voltage_sensor_); + LOG_SENSOR(" ", "Battery Level", this->battery_remaining_sensor_); +} + +float MAX17043Component::get_setup_priority() const { return setup_priority::DATA; } + +void MAX17043Component::sleep_mode() { + if (!this->is_failed()) { + if (!this->write_byte_16(MAX17043_CONFIG, MAX17043_CONFIG_POWER_UP_DEFAULT | MAX17043_CONFIG_SLEEP_MASK)) { + ESP_LOGW(TAG, "Unable to write the sleep bit to config register"); + this->status_set_warning(); + } + } +} + +} // namespace max17043 +} // namespace esphome diff --git a/esphome/components/max17043/max17043.h b/esphome/components/max17043/max17043.h new file mode 100644 index 0000000000..540b977789 --- /dev/null +++ b/esphome/components/max17043/max17043.h @@ -0,0 +1,29 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/i2c/i2c.h" + +namespace esphome { +namespace max17043 { + +class MAX17043Component : public PollingComponent, public i2c::I2CDevice { + public: + void setup() override; + void dump_config() override; + float get_setup_priority() const override; + void update() override; + void sleep_mode(); + + void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; } + void set_battery_remaining_sensor(sensor::Sensor *battery_remaining_sensor) { + battery_remaining_sensor_ = battery_remaining_sensor; + } + + protected: + sensor::Sensor *voltage_sensor_{nullptr}; + sensor::Sensor *battery_remaining_sensor_{nullptr}; +}; + +} // namespace max17043 +} // namespace esphome diff --git a/esphome/components/max17043/sensor.py b/esphome/components/max17043/sensor.py new file mode 100644 index 0000000000..3da0f953b0 --- /dev/null +++ b/esphome/components/max17043/sensor.py @@ -0,0 +1,77 @@ +from esphome import automation +from esphome.automation import maybe_simple_id +import esphome.codegen as cg +from esphome.components import i2c, sensor +import esphome.config_validation as cv +from esphome.const import ( + CONF_BATTERY_LEVEL, + CONF_BATTERY_VOLTAGE, + CONF_ID, + DEVICE_CLASS_BATTERY, + DEVICE_CLASS_VOLTAGE, + ENTITY_CATEGORY_DIAGNOSTIC, + STATE_CLASS_MEASUREMENT, + UNIT_PERCENT, + UNIT_VOLT, +) + +DEPENDENCIES = ["i2c"] + +max17043_ns = cg.esphome_ns.namespace("max17043") +MAX17043Component = max17043_ns.class_( + "MAX17043Component", cg.PollingComponent, i2c.I2CDevice +) + +# Actions +SleepAction = max17043_ns.class_("SleepAction", automation.Action) + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(MAX17043Component), + cv.Optional(CONF_BATTERY_VOLTAGE): sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT, + accuracy_decimals=3, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + accuracy_decimals=3, + device_class=DEVICE_CLASS_BATTERY, + state_class=STATE_CLASS_MEASUREMENT, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x36)) +) + + +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 voltage_config := config.get(CONF_BATTERY_VOLTAGE): + sens = await sensor.new_sensor(voltage_config) + cg.add(var.set_voltage_sensor(sens)) + + if CONF_BATTERY_LEVEL in config: + sens = await sensor.new_sensor(config[CONF_BATTERY_LEVEL]) + cg.add(var.set_battery_remaining_sensor(sens)) + + +MAX17043_ACTION_SCHEMA = maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(MAX17043Component), + } +) + + +@automation.register_action("max17043.sleep_mode", SleepAction, MAX17043_ACTION_SCHEMA) +async def max17043_sleep_mode_to_code(config, action_id, template_arg, args): + paren = await cg.get_variable(config[CONF_ID]) + return cg.new_Pvariable(action_id, template_arg, paren) diff --git a/esphome/components/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/components/md5/__init__.py b/esphome/components/md5/__init__.py index f70ffa9520..1af9ee0b29 100644 --- a/esphome/components/md5/__init__.py +++ b/esphome/components/md5/__init__.py @@ -1 +1,7 @@ +import esphome.codegen as cg + CODEOWNERS = ["@esphome/core"] + + +async def to_code(config): + cg.add_define("USE_MD5") diff --git a/esphome/components/md5/md5.cpp b/esphome/components/md5/md5.cpp index 620b6749f3..31f52634be 100644 --- a/esphome/components/md5/md5.cpp +++ b/esphome/components/md5/md5.cpp @@ -1,6 +1,7 @@ #include #include #include "md5.h" +#ifdef USE_MD5 #include "esphome/core/helpers.h" namespace esphome { @@ -65,3 +66,4 @@ bool MD5Digest::equals_hex(const char *expected) { } // namespace md5 } // namespace esphome +#endif diff --git a/esphome/components/md5/md5.h b/esphome/components/md5/md5.h index 4ec8a8a12c..cb6accf46f 100644 --- a/esphome/components/md5/md5.h +++ b/esphome/components/md5/md5.h @@ -1,6 +1,7 @@ #pragma once #include "esphome/core/defines.h" +#ifdef USE_MD5 #ifdef USE_ESP_IDF #include "esp_rom_md5.h" @@ -66,3 +67,4 @@ class MD5Digest { } // namespace md5 } // namespace esphome +#endif diff --git a/esphome/components/media_player/__init__.py b/esphome/components/media_player/__init__.py index 423cb065dc..a46b30db29 100644 --- a/esphome/components/media_player/__init__.py +++ b/esphome/components/media_player/__init__.py @@ -21,6 +21,7 @@ media_player_ns = cg.esphome_ns.namespace("media_player") MediaPlayer = media_player_ns.class_("MediaPlayer") + PlayAction = media_player_ns.class_( "PlayAction", automation.Action, cg.Parented.template(MediaPlayer) ) @@ -60,7 +61,11 @@ AnnoucementTrigger = media_player_ns.class_( "AnnouncementTrigger", automation.Trigger.template() ) IsIdleCondition = media_player_ns.class_("IsIdleCondition", automation.Condition) +IsPausedCondition = media_player_ns.class_("IsPausedCondition", automation.Condition) IsPlayingCondition = media_player_ns.class_("IsPlayingCondition", automation.Condition) +IsAnnouncingCondition = media_player_ns.class_( + "IsAnnouncingCondition", automation.Condition +) async def setup_media_player_core_(var, config): @@ -159,9 +164,15 @@ async def media_player_play_media_action(config, action_id, template_arg, args): @automation.register_condition( "media_player.is_idle", IsIdleCondition, MEDIA_PLAYER_ACTION_SCHEMA ) +@automation.register_condition( + "media_player.is_paused", IsPausedCondition, MEDIA_PLAYER_ACTION_SCHEMA +) @automation.register_condition( "media_player.is_playing", IsPlayingCondition, MEDIA_PLAYER_ACTION_SCHEMA ) +@automation.register_condition( + "media_player.is_announcing", IsAnnouncingCondition, MEDIA_PLAYER_ACTION_SCHEMA +) async def media_player_action(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) diff --git a/esphome/components/media_player/automation.h b/esphome/components/media_player/automation.h index f0e0a5dd31..7b9220c4a5 100644 --- a/esphome/components/media_player/automation.h +++ b/esphome/components/media_player/automation.h @@ -68,5 +68,15 @@ template class IsPlayingCondition : public Condition, pub bool check(Ts... x) override { return this->parent_->state == MediaPlayerState::MEDIA_PLAYER_STATE_PLAYING; } }; +template class IsPausedCondition : public Condition, public Parented { + public: + bool check(Ts... x) override { return this->parent_->state == MediaPlayerState::MEDIA_PLAYER_STATE_PAUSED; } +}; + +template class IsAnnouncingCondition : public Condition, public Parented { + public: + bool check(Ts... x) override { return this->parent_->state == MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING; } +}; + } // namespace media_player } // namespace esphome diff --git a/esphome/components/media_player/media_player.cpp b/esphome/components/media_player/media_player.cpp index 586345ac9f..b5190d8573 100644 --- a/esphome/components/media_player/media_player.cpp +++ b/esphome/components/media_player/media_player.cpp @@ -37,6 +37,10 @@ const char *media_player_command_to_string(MediaPlayerCommand command) { return "UNMUTE"; case MEDIA_PLAYER_COMMAND_TOGGLE: return "TOGGLE"; + case MEDIA_PLAYER_COMMAND_VOLUME_UP: + return "VOLUME_UP"; + case MEDIA_PLAYER_COMMAND_VOLUME_DOWN: + return "VOLUME_DOWN"; default: return "UNKNOWN"; } 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; diff --git a/esphome/components/micro_wake_word/__init__.py b/esphome/components/micro_wake_word/__init__.py index a8aa590951..0862406e46 100644 --- a/esphome/components/micro_wake_word/__init__.py +++ b/esphome/components/micro_wake_word/__init__.py @@ -419,6 +419,13 @@ async def to_code(config): repo="https://github.com/espressif/esp-tflite-micro", ref="v1.3.1", ) + # add esp-nn dependency for tflite-micro to work around https://github.com/espressif/esp-nn/issues/17 + # ...remove after switching to IDF 5.1.4+ + esp32.add_idf_component( + name="esp-nn", + repo="https://github.com/espressif/esp-nn", + ref="v1.1.0", + ) cg.add_build_flag("-DTF_LITE_STATIC_MEMORY") cg.add_build_flag("-DTF_LITE_DISABLE_X86_NEON") diff --git a/esphome/components/mics_4514/sensor.py b/esphome/components/mics_4514/sensor.py index 80c3524f66..59ccba235a 100644 --- a/esphome/components/mics_4514/sensor.py +++ b/esphome/components/mics_4514/sensor.py @@ -1,10 +1,14 @@ import esphome.codegen as cg +from esphome.components import i2c, sensor import esphome.config_validation as cv - -from esphome.components import sensor, i2c - from esphome.const import ( + CONF_AMMONIA, + CONF_CARBON_MONOXIDE, + CONF_ETHANOL, + CONF_HYDROGEN, CONF_ID, + CONF_METHANE, + CONF_NITROGEN_DIOXIDE, STATE_CLASS_MEASUREMENT, UNIT_PARTS_PER_MILLION, ) @@ -12,13 +16,6 @@ from esphome.const import ( CODEOWNERS = ["@jesserockz"] DEPENDENCIES = ["i2c"] -CONF_CARBON_MONOXIDE = "carbon_monoxide" -CONF_NITROGEN_DIOXIDE = "nitrogen_dioxide" -CONF_METHANE = "methane" -CONF_ETHANOL = "ethanol" -CONF_HYDROGEN = "hydrogen" -CONF_AMMONIA = "ammonia" - mics_4514_ns = cg.esphome_ns.namespace("mics_4514") MICS4514Component = mics_4514_ns.class_( @@ -31,6 +28,7 @@ SENSORS = [ CONF_ETHANOL, CONF_HYDROGEN, CONF_AMMONIA, + CONF_NITROGEN_DIOXIDE, ] common_sensor_schema = sensor.sensor_schema( @@ -40,16 +38,7 @@ common_sensor_schema = sensor.sensor_schema( ) CONFIG_SCHEMA = ( - cv.Schema( - { - cv.GenerateID(): cv.declare_id(MICS4514Component), - cv.Optional(CONF_NITROGEN_DIOXIDE): sensor.sensor_schema( - unit_of_measurement=UNIT_PARTS_PER_MILLION, - state_class=STATE_CLASS_MEASUREMENT, - accuracy_decimals=2, - ), - } - ) + cv.Schema({cv.GenerateID(): cv.declare_id(MICS4514Component)}) .extend({cv.Optional(sensor_type): common_sensor_schema for sensor_type in SENSORS}) .extend(i2c.i2c_device_schema(0x75)) .extend(cv.polling_component_schema("60s")) @@ -62,10 +51,6 @@ async def to_code(config): await i2c.register_i2c_device(var, config) for sensor_type in SENSORS: - if sensor_type in config: - sens = await sensor.new_sensor(config[sensor_type]) + if sensor_config := config.get(sensor_type): + sens = await sensor.new_sensor(sensor_config) cg.add(getattr(var, f"set_{sensor_type}_sensor")(sens)) - - if CONF_NITROGEN_DIOXIDE in config: - sens = await sensor.new_sensor(config[CONF_NITROGEN_DIOXIDE]) - cg.add(var.set_nitrogen_dioxide_sensor(sens)) diff --git a/esphome/components/mlx90393/sensor.py b/esphome/components/mlx90393/sensor.py index 92ba30bea3..fe01d8ebfc 100644 --- a/esphome/components/mlx90393/sensor.py +++ b/esphome/components/mlx90393/sensor.py @@ -132,4 +132,4 @@ async def to_code(config): pin = await cg.gpio_pin_expression(config[CONF_DRDY_PIN]) cg.add(var.set_drdy_gpio(pin)) - cg.add_library("functionpointer/arduino-MLX90393", "1.0.0") + cg.add_library("functionpointer/arduino-MLX90393", "1.0.2") diff --git a/esphome/components/modbus/modbus.cpp b/esphome/components/modbus/modbus.cpp index f8dd4c18b9..8544b50261 100644 --- a/esphome/components/modbus/modbus.cpp +++ b/esphome/components/modbus/modbus.cpp @@ -15,23 +15,33 @@ void Modbus::setup() { void Modbus::loop() { const uint32_t now = millis(); - if (now - this->last_modbus_byte_ > 50) { - this->rx_buffer_.clear(); - this->last_modbus_byte_ = now; - } - // stop blocking new send commands after send_wait_time_ ms regardless if a response has been received since then - if (now - this->last_send_ > send_wait_time_) { - waiting_for_response = 0; - } - while (this->available()) { uint8_t byte; this->read_byte(&byte); if (this->parse_modbus_byte_(byte)) { this->last_modbus_byte_ = now; } else { + size_t at = this->rx_buffer_.size(); + if (at > 0) { + ESP_LOGV(TAG, "Clearing buffer of %d bytes - parse failed", at); + this->rx_buffer_.clear(); + } + } + } + + if (now - this->last_modbus_byte_ > 50) { + size_t at = this->rx_buffer_.size(); + if (at > 0) { + ESP_LOGV(TAG, "Clearing buffer of %d bytes - timeout", at); this->rx_buffer_.clear(); } + + // stop blocking new send commands after sent_wait_time_ ms after response received + if (now - this->last_send_ > send_wait_time_) { + if (waiting_for_response > 0) + ESP_LOGV(TAG, "Stop waiting for response from %d", waiting_for_response); + waiting_for_response = 0; + } } } @@ -39,7 +49,7 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) { size_t at = this->rx_buffer_.size(); this->rx_buffer_.push_back(byte); const uint8_t *raw = &this->rx_buffer_[0]; - ESP_LOGV(TAG, "Modbus received Byte %d (0X%x)", byte, byte); + ESP_LOGVV(TAG, "Modbus received Byte %d (0X%x)", byte, byte); // Byte 0: modbus address (match all) if (at == 0) return true; @@ -144,8 +154,10 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) { ESP_LOGW(TAG, "Got Modbus frame from unknown address 0x%02X! ", address); } - // return false to reset buffer - return false; + // reset buffer + ESP_LOGV(TAG, "Clearing buffer of %d bytes - parse succeeded", at); + this->rx_buffer_.clear(); + return true; } void Modbus::dump_config() { diff --git a/esphome/components/modbus_controller/__init__.py b/esphome/components/modbus_controller/__init__.py index 8146124c28..488baa245a 100644 --- a/esphome/components/modbus_controller/__init__.py +++ b/esphome/components/modbus_controller/__init__.py @@ -1,26 +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_MAX_CMD_RETRIES, CONF_MODBUS_CONTROLLER_ID, + CONF_OFFLINE_SKIP_UPDATES, CONF_ON_COMMAND_SENT, CONF_REGISTER_COUNT, CONF_REGISTER_TYPE, @@ -131,6 +134,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 +261,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/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/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/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"] diff --git a/esphome/components/mopeka_pro_check/mopeka_pro_check.cpp b/esphome/components/mopeka_pro_check/mopeka_pro_check.cpp index f79e40bb4e..9527f09f59 100644 --- a/esphome/components/mopeka_pro_check/mopeka_pro_check.cpp +++ b/esphome/components/mopeka_pro_check/mopeka_pro_check.cpp @@ -17,6 +17,8 @@ void MopekaProCheck::dump_config() { LOG_SENSOR(" ", "Temperature", this->temperature_); LOG_SENSOR(" ", "Battery Level", this->battery_level_); LOG_SENSOR(" ", "Reading Distance", this->distance_); + LOG_SENSOR(" ", "Read Quality", this->read_quality_); + LOG_SENSOR(" ", "Ignored Reads", this->ignored_reads_); } /** @@ -66,34 +68,49 @@ bool MopekaProCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device) this->battery_level_->publish_state(level); } + // Get the quality value + SensorReadQuality quality_value = this->parse_read_quality_(manu_data.data); + if (this->read_quality_ != nullptr) { + this->read_quality_->publish_state(static_cast(quality_value)); + } + + // Determine if we have a good enough quality of read to report level and distance + // sensors. This sensor is reported regardless of distance or level sensors being enabled + if (quality_value < this->min_signal_quality_) { + ESP_LOGW(TAG, "Read Quality too low to report distance or level"); + this->ignored_read_count_++; + } else { + // reset to zero since read quality was sufficient + this->ignored_read_count_ = 0; + } + // Report number of contiguous ignored reads if sensor defined + if (this->ignored_reads_ != nullptr) { + this->ignored_reads_->publish_state(this->ignored_read_count_); + } + // Get distance and level if either are sensors if ((this->distance_ != nullptr) || (this->level_ != nullptr)) { uint32_t distance_value = this->parse_distance_(manu_data.data); - SensorReadQuality quality_value = this->parse_read_quality_(manu_data.data); ESP_LOGD(TAG, "Distance Sensor: Quality (0x%X) Distance (%" PRId32 "mm)", quality_value, distance_value); - if (quality_value < QUALITY_HIGH) { - ESP_LOGW(TAG, "Poor read quality."); - } - if (quality_value < QUALITY_MED) { - // if really bad reading set to 0 - ESP_LOGW(TAG, "Setting distance to 0"); - distance_value = 0; - } - // update distance sensor - if (this->distance_ != nullptr) { - this->distance_->publish_state(distance_value); - } - - // update level sensor - if (this->level_ != nullptr) { - uint8_t tank_level = 0; - if (distance_value >= this->full_mm_) { - tank_level = 100; // cap at 100% - } else if (distance_value > this->empty_mm_) { - tank_level = ((100.0f / (this->full_mm_ - this->empty_mm_)) * (distance_value - this->empty_mm_)); + // only update distance and level sensors if read quality was sufficient. This can be determined by + // if the ignored_read_count is zero. + if (this->ignored_read_count_ == 0) { + // update distance sensor + if (this->distance_ != nullptr) { + this->distance_->publish_state(distance_value); + } + + // update level sensor + if (this->level_ != nullptr) { + uint8_t tank_level = 0; + if (distance_value >= this->full_mm_) { + tank_level = 100; // cap at 100% + } else if (distance_value > this->empty_mm_) { + tank_level = ((100.0f / (this->full_mm_ - this->empty_mm_)) * (distance_value - this->empty_mm_)); + } + this->level_->publish_state(tank_level); } - this->level_->publish_state(tank_level); } } @@ -131,6 +148,8 @@ uint32_t MopekaProCheck::parse_distance_(const std::vector &message) { uint8_t MopekaProCheck::parse_temperature_(const std::vector &message) { return (message[2] & 0x7F) - 40; } SensorReadQuality MopekaProCheck::parse_read_quality_(const std::vector &message) { + // Since a 8 bit value is being shifted and truncated to 2 bits all possible values are defined as enumeration + // value and the static cast is safe. return static_cast(message[4] >> 6); } diff --git a/esphome/components/mopeka_pro_check/mopeka_pro_check.h b/esphome/components/mopeka_pro_check/mopeka_pro_check.h index 8b4d47e4c6..c58406ac18 100644 --- a/esphome/components/mopeka_pro_check/mopeka_pro_check.h +++ b/esphome/components/mopeka_pro_check/mopeka_pro_check.h @@ -24,9 +24,9 @@ enum SensorType { }; // Sensor read quality. If sensor is poorly placed or tank level -// gets too low the read quality will show and the distanace +// gets too low the read quality will show and the distance // measurement may be inaccurate. -enum SensorReadQuality { QUALITY_HIGH = 0x3, QUALITY_MED = 0x2, QUALITY_LOW = 0x1, QUALITY_NONE = 0x0 }; +enum SensorReadQuality { QUALITY_HIGH = 0x3, QUALITY_MED = 0x2, QUALITY_LOW = 0x1, QUALITY_ZERO = 0x0 }; class MopekaProCheck : public Component, public esp32_ble_tracker::ESPBTDeviceListener { public: @@ -35,11 +35,14 @@ class MopekaProCheck : public Component, public esp32_ble_tracker::ESPBTDeviceLi 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_min_signal_quality(SensorReadQuality min) { this->min_signal_quality_ = min; }; void set_level(sensor::Sensor *level) { level_ = level; }; void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; }; void set_battery_level(sensor::Sensor *bat) { battery_level_ = bat; }; void set_distance(sensor::Sensor *distance) { distance_ = distance; }; + void set_signal_quality(sensor::Sensor *rq) { read_quality_ = rq; }; + void set_ignored_reads(sensor::Sensor *ir) { ignored_reads_ = ir; }; void set_tank_full(float full) { full_mm_ = full; }; void set_tank_empty(float empty) { empty_mm_ = empty; }; @@ -49,9 +52,13 @@ class MopekaProCheck : public Component, public esp32_ble_tracker::ESPBTDeviceLi sensor::Sensor *temperature_{nullptr}; sensor::Sensor *distance_{nullptr}; sensor::Sensor *battery_level_{nullptr}; + sensor::Sensor *read_quality_{nullptr}; + sensor::Sensor *ignored_reads_{nullptr}; uint32_t full_mm_; uint32_t empty_mm_; + uint32_t ignored_read_count_ = 0; + SensorReadQuality min_signal_quality_ = QUALITY_MED; uint8_t parse_battery_level_(const std::vector &message); uint32_t parse_distance_(const std::vector &message); diff --git a/esphome/components/mopeka_pro_check/sensor.py b/esphome/components/mopeka_pro_check/sensor.py index 0ba33e94de..95ade53013 100644 --- a/esphome/components/mopeka_pro_check/sensor.py +++ b/esphome/components/mopeka_pro_check/sensor.py @@ -5,9 +5,12 @@ from esphome.const import ( CONF_DISTANCE, CONF_MAC_ADDRESS, CONF_ID, + ICON_COUNTER, ICON_THERMOMETER, ICON_RULER, + ICON_SIGNAL, UNIT_PERCENT, + UNIT_EMPTY, CONF_LEVEL, CONF_TEMPERATURE, DEVICE_CLASS_TEMPERATURE, @@ -16,11 +19,15 @@ from esphome.const import ( STATE_CLASS_MEASUREMENT, CONF_BATTERY_LEVEL, DEVICE_CLASS_BATTERY, + ENTITY_CATEGORY_DIAGNOSTIC, ) CONF_TANK_TYPE = "tank_type" CONF_CUSTOM_DISTANCE_FULL = "custom_distance_full" CONF_CUSTOM_DISTANCE_EMPTY = "custom_distance_empty" +CONF_SIGNAL_QUALITY = "signal_quality" +CONF_MINIMUM_SIGNAL_QUALITY = "minimum_signal_quality" +CONF_IGNORED_READS = "ignored_reads" ICON_PROPANE_TANK = "mdi:propane-tank" @@ -56,6 +63,14 @@ MopekaProCheck = mopeka_pro_check_ns.class_( "MopekaProCheck", esp32_ble_tracker.ESPBTDeviceListener, cg.Component ) +SensorReadQuality = mopeka_pro_check_ns.enum("SensorReadQuality") +SIGNAL_QUALITIES = { + "ZERO": SensorReadQuality.QUALITY_ZERO, + "LOW": SensorReadQuality.QUALITY_LOW, + "MEDIUM": SensorReadQuality.QUALITY_MED, + "HIGH": SensorReadQuality.QUALITY_HIGH, +} + CONFIG_SCHEMA = ( cv.Schema( { @@ -89,6 +104,21 @@ CONFIG_SCHEMA = ( device_class=DEVICE_CLASS_BATTERY, state_class=STATE_CLASS_MEASUREMENT, ), + cv.Optional(CONF_SIGNAL_QUALITY): sensor.sensor_schema( + unit_of_measurement=UNIT_EMPTY, + icon=ICON_SIGNAL, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_IGNORED_READS): sensor.sensor_schema( + unit_of_measurement=UNIT_EMPTY, + icon=ICON_COUNTER, + accuracy_decimals=0, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + cv.Optional(CONF_MINIMUM_SIGNAL_QUALITY, default="MEDIUM"): cv.enum( + SIGNAL_QUALITIES, upper=True + ), } ) .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) @@ -119,6 +149,11 @@ async def to_code(config): cg.add(var.set_tank_empty(CONF_SUPPORTED_TANKS_MAP[t][0])) cg.add(var.set_tank_full(CONF_SUPPORTED_TANKS_MAP[t][1])) + if ( + minimum_signal_quality := config.get(CONF_MINIMUM_SIGNAL_QUALITY, None) + ) is not None: + cg.add(var.set_min_signal_quality(minimum_signal_quality)) + if CONF_TEMPERATURE in config: sens = await sensor.new_sensor(config[CONF_TEMPERATURE]) cg.add(var.set_temperature(sens)) @@ -131,3 +166,9 @@ async def to_code(config): if CONF_BATTERY_LEVEL in config: sens = await sensor.new_sensor(config[CONF_BATTERY_LEVEL]) cg.add(var.set_battery_level(sens)) + if CONF_SIGNAL_QUALITY in config: + sens = await sensor.new_sensor(config[CONF_SIGNAL_QUALITY]) + cg.add(var.set_signal_quality(sens)) + if CONF_IGNORED_READS in config: + sens = await sensor.new_sensor(config[CONF_IGNORED_READS]) + cg.add(var.set_ignored_reads(sens)) diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index 240b407819..8851581ea0 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -11,6 +11,7 @@ from esphome.const import ( CONF_BIRTH_MESSAGE, CONF_BROKER, CONF_CERTIFICATE_AUTHORITY, + CONF_CLEAN_SESSION, CONF_CLIENT_CERTIFICATE, CONF_CLIENT_CERTIFICATE_KEY, CONF_CLIENT_ID, @@ -40,6 +41,7 @@ from esphome.const import ( CONF_SHUTDOWN_MESSAGE, CONF_SSL_FINGERPRINTS, CONF_STATE_TOPIC, + CONF_SUBSCRIBE_QOS, CONF_TOPIC, CONF_TOPIC_PREFIX, CONF_TRIGGER_ID, @@ -209,6 +211,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_PORT, default=1883): cv.port, cv.Optional(CONF_USERNAME, default=""): cv.string, cv.Optional(CONF_PASSWORD, default=""): cv.string, + cv.Optional(CONF_CLEAN_SESSION, default=False): cv.boolean, cv.Optional(CONF_CLIENT_ID): cv.string, cv.SplitDefault(CONF_IDF_SEND_ASYNC, esp32_idf=False): cv.All( cv.boolean, cv.only_with_esp_idf @@ -325,6 +328,7 @@ async def to_code(config): cg.add(var.set_broker_port(config[CONF_PORT])) cg.add(var.set_username(config[CONF_USERNAME])) cg.add(var.set_password(config[CONF_PASSWORD])) + cg.add(var.set_clean_session(config[CONF_CLEAN_SESSION])) if CONF_CLIENT_ID in config: cg.add(var.set_client_id(config[CONF_CLIENT_ID])) @@ -515,6 +519,8 @@ async def register_mqtt_component(var, config): cg.add(var.set_qos(config[CONF_QOS])) if CONF_RETAIN in config: cg.add(var.set_retain(config[CONF_RETAIN])) + if CONF_SUBSCRIBE_QOS in config: + cg.add(var.set_subscribe_qos(config[CONF_SUBSCRIBE_QOS])) if not config.get(CONF_DISCOVERY, True): cg.add(var.disable_discovery()) if CONF_STATE_TOPIC in config: diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index c19b24c0cf..b5ac285026 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -147,6 +147,7 @@ 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()); + ESP_LOGCONFIG(TAG, " Clean Session: %s", YESNO(this->credentials_.clean_session)); if (this->is_discovery_ip_enabled()) { ESP_LOGCONFIG(TAG, " Discovery IP enabled"); } @@ -246,6 +247,7 @@ void MQTTClientComponent::start_connect_() { this->mqtt_backend_.disconnect(); this->mqtt_backend_.set_client_id(this->credentials_.client_id.c_str()); + this->mqtt_backend_.set_clean_session(this->credentials_.clean_session); const char *username = nullptr; if (!this->credentials_.username.empty()) username = this->credentials_.username.c_str(); diff --git a/esphome/components/mqtt/mqtt_client.h b/esphome/components/mqtt/mqtt_client.h index b0d3bbe66d..887800f201 100644 --- a/esphome/components/mqtt/mqtt_client.h +++ b/esphome/components/mqtt/mqtt_client.h @@ -51,6 +51,7 @@ struct MQTTCredentials { std::string username; std::string password; std::string client_id; ///< The client ID. Will automatically be truncated to 23 characters. + bool clean_session; ///< Whether the session will be cleaned or remembered between connects. }; /// Simple data struct for Home Assistant component availability. @@ -254,6 +255,7 @@ class MQTTClientComponent : public Component { void set_username(const std::string &username) { this->credentials_.username = username; } void set_password(const std::string &password) { this->credentials_.password = password; } void set_client_id(const std::string &client_id) { this->credentials_.client_id = client_id; } + void set_clean_session(const bool &clean_session) { this->credentials_.clean_session = clean_session; } void set_on_connect(mqtt_on_connect_callback_t &&callback); void set_on_disconnect(mqtt_on_disconnect_callback_t &&callback); diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index 295fbba5e5..3b9d367a7b 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -16,6 +16,8 @@ static const char *const TAG = "mqtt.component"; void MQTTComponent::set_qos(uint8_t qos) { this->qos_ = qos; } +void MQTTComponent::set_subscribe_qos(uint8_t qos) { this->subscribe_qos_ = qos; } + void MQTTComponent::set_retain(bool retain) { this->retain_ = retain; } std::string MQTTComponent::get_discovery_topic_(const MQTTDiscoveryInfo &discovery_info) const { @@ -76,6 +78,10 @@ bool MQTTComponent::send_discovery_() { config.command_topic = true; this->send_discovery(root, config); + // Set subscription QoS (default is 0) + if (this->subscribe_qos_ != 0) { + root[MQTT_QOS] = this->subscribe_qos_; + } // Fields from EntityBase if (this->get_entity()->has_own_name()) { diff --git a/esphome/components/mqtt/mqtt_component.h b/esphome/components/mqtt/mqtt_component.h index 147840d11f..01ba98ad40 100644 --- a/esphome/components/mqtt/mqtt_component.h +++ b/esphome/components/mqtt/mqtt_component.h @@ -89,6 +89,9 @@ class MQTTComponent : public Component { void disable_discovery(); bool is_discovery_enabled() const; + /// Set the QOS for subscribe messages (used in discovery). + void set_subscribe_qos(uint8_t qos); + /// Override this method to return the component type (e.g. "light", "sensor", ...) virtual std::string component_type() const = 0; @@ -204,6 +207,7 @@ class MQTTComponent : public Component { bool command_retain_{false}; bool retain_{true}; uint8_t qos_{0}; + uint8_t subscribe_qos_{0}; bool discovery_enabled_{true}; bool resend_state_{false}; }; diff --git a/esphome/components/mqtt/mqtt_const.h b/esphome/components/mqtt/mqtt_const.h index 71f169fbe8..c1c40c4b6d 100644 --- a/esphome/components/mqtt/mqtt_const.h +++ b/esphome/components/mqtt/mqtt_const.h @@ -180,6 +180,7 @@ 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"; +constexpr const char *const MQTT_QOS = "qos"; constexpr const char *const MQTT_RED_TEMPLATE = "r_tpl"; constexpr const char *const MQTT_RETAIN = "ret"; constexpr const char *const MQTT_RGB_COMMAND_TEMPLATE = "rgb_cmd_tpl"; @@ -441,6 +442,7 @@ constexpr const char *const MQTT_PRESET_MODE_COMMAND_TOPIC = "preset_mode_comman 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"; +constexpr const char *const MQTT_QOS = "qos"; constexpr const char *const MQTT_RED_TEMPLATE = "red_template"; constexpr const char *const MQTT_RETAIN = "retain"; constexpr const char *const MQTT_RGB_COMMAND_TEMPLATE = "rgb_command_template"; diff --git a/esphome/components/nau7802/__init__.py b/esphome/components/nau7802/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/nau7802/nau7802.cpp b/esphome/components/nau7802/nau7802.cpp new file mode 100644 index 0000000000..ea6c0258af --- /dev/null +++ b/esphome/components/nau7802/nau7802.cpp @@ -0,0 +1,323 @@ +#include "nau7802.h" +#include "esphome/core/log.h" +#include "esphome/core/hal.h" + +namespace esphome { +namespace nau7802 { + +static const char *const TAG = "nau7802"; + +// Only define what we need + +static const uint8_t READ_BIT = 0x01; + +static const uint8_t PU_CTRL_REG = 0x00; +static const uint8_t PU_CTRL_REGISTER_RESET = 0x01; +static const uint8_t PU_CTRL_POWERUP_DIGITAL = 0x02; +static const uint8_t PU_CTRL_POWERUP_ANALOG = 0x04; +static const uint8_t PU_CTRL_POWERUP_READY = 0x08; +static const uint8_t PU_CTRL_CYCLE_START = 0x10; +static const uint8_t PU_CTRL_CYCLE_READY = 0x20; +static const uint8_t PU_CTRL_AVDD_EXTERNAL = 0x80; + +static const uint8_t CTRL1_REG = 0x01; +static const uint8_t CTRL1_LDO_SHIFT = 3; +static const uint8_t CTRL1_LDO_MASK = (0x7 << CTRL1_LDO_SHIFT); +static const uint8_t CTRL1_GAIN_MASK = 0x7; + +static const uint8_t CTRL2_REG = 0x02; +static const uint8_t CTRL2_CRS_SHIFT = 4; +static const uint8_t CTRL2_CRS_MASK = (0x7 << CTRL2_CRS_SHIFT); +static const uint8_t CTRL2_CALS = 0x04; +static const uint8_t CTRL2_CAL_ERR = 0x08; +static const uint8_t CTRL2_GAIN_CALIBRATION = 0x03; +static const uint8_t CTRL2_CONFIG_MASK = 0xF0; + +static const uint8_t OCAL1_B2_REG = 0x03; +static const uint8_t GCAL1_B3_REG = 0x06; +static const uint8_t GCAL1_FRACTIONAL = 23; + +// only need the first data register for sequential read method +static const uint8_t ADCO_B2_REG = 0x12; + +static const uint8_t ADC_REG = 0x15; +static const uint8_t ADC_CHPS_DISABLE = 0x30; + +static const uint8_t PGA_REG = 0x1B; +static const uint8_t PGA_LDOMODE_ESR = 0x40; + +static const uint8_t POWER_REG = 0x1C; +static const uint8_t POWER_PGA_CAP_EN = 0x80; + +static const uint8_t DEVICE_REV = 0x1F; + +void NAU7802Sensor::setup() { + i2c::I2CRegister pu_ctrl = this->reg(PU_CTRL_REG); + ESP_LOGCONFIG(TAG, "Setting up NAU7802 '%s'...", this->name_.c_str()); + uint8_t rev; + + if (this->read_register(DEVICE_REV | READ_BIT, &rev, 1)) { + ESP_LOGE(TAG, "Failed I2C read during setup()"); + this->mark_failed(); + return; + } + ESP_LOGI(TAG, "Setting up NAU7802 Rev %d", rev); + + // reset + pu_ctrl |= PU_CTRL_REGISTER_RESET; + delay(10); + pu_ctrl &= ~PU_CTRL_REGISTER_RESET; + + // power up digital hw + pu_ctrl |= PU_CTRL_POWERUP_DIGITAL; + + delay(1); + if (!(pu_ctrl.get() & PU_CTRL_POWERUP_READY)) { + ESP_LOGE(TAG, "Failed to reset sensor during setup()"); + this->mark_failed(); + return; + } + + uint32_t gcal = (uint32_t) (round(this->gain_calibration_ * (1 << GCAL1_FRACTIONAL))); + this->write_value_(OCAL1_B2_REG, 3, this->offset_calibration_); + this->write_value_(GCAL1_B3_REG, 4, gcal); + + // turn on AFE + pu_ctrl |= PU_CTRL_POWERUP_ANALOG; + auto f = std::bind(&NAU7802Sensor::complete_setup_, this); + this->set_timeout(600, f); +} + +void NAU7802Sensor::complete_setup_() { + i2c::I2CRegister pu_ctrl = this->reg(PU_CTRL_REG); + i2c::I2CRegister ctrl1 = this->reg(CTRL1_REG); + i2c::I2CRegister ctrl2 = this->reg(CTRL2_REG); + pu_ctrl |= PU_CTRL_CYCLE_START; + + // set gain + ctrl1 &= ~CTRL1_GAIN_MASK; + ctrl1 |= this->gain_; + + // enable internal LDO + if (this->ldo_ != NAU7802_LDO_EXTERNAL) { + pu_ctrl |= PU_CTRL_AVDD_EXTERNAL; + ctrl1 &= ~CTRL1_LDO_MASK; + ctrl1 |= this->ldo_ << CTRL1_LDO_SHIFT; + } + + // set sps + ctrl2 &= ~CTRL2_CRS_MASK; + ctrl2 |= this->sps_ << CTRL2_CRS_SHIFT; + + // disable ADC chopper clock + i2c::I2CRegister adc_reg = this->reg(ADC_REG); + adc_reg |= ADC_CHPS_DISABLE; + + // use low ESR caps + i2c::I2CRegister pga_reg = this->reg(PGA_REG); + pga_reg &= ~PGA_LDOMODE_ESR; + + // PGA stabilizer cap on output + i2c::I2CRegister pwr_reg = this->reg(POWER_REG); + pwr_reg |= POWER_PGA_CAP_EN; + + this->setup_complete_ = true; +} + +void NAU7802Sensor::dump_config() { + LOG_SENSOR("", "NAU7802", this); + LOG_I2C_DEVICE(this); + + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with NAU7802 failed earlier, during setup"); + return; + } + // Note these may differ from the values on the device if calbration has been run + ESP_LOGCONFIG(TAG, " Offset Calibration: %s", to_string(this->offset_calibration_).c_str()); + ESP_LOGCONFIG(TAG, " Gain Calibration: %f", this->gain_calibration_); + + std::string voltage = "unknown"; + switch (this->ldo_) { + case NAU7802_LDO_2V4: + voltage = "2.4V"; + break; + case NAU7802_LDO_2V7: + voltage = "2.7V"; + break; + case NAU7802_LDO_3V0: + voltage = "3.0V"; + break; + case NAU7802_LDO_3V3: + voltage = "3.3V"; + break; + case NAU7802_LDO_3V6: + voltage = "3.6V"; + break; + case NAU7802_LDO_3V9: + voltage = "3.9V"; + break; + case NAU7802_LDO_4V2: + voltage = "4.2V"; + break; + case NAU7802_LDO_4V5: + voltage = "4.5V"; + break; + case NAU7802_LDO_EXTERNAL: + voltage = "External"; + break; + } + ESP_LOGCONFIG(TAG, " LDO Voltage: %s", voltage.c_str()); + int gain = 0; + switch (this->gain_) { + case NAU7802_GAIN_128: + gain = 128; + break; + case NAU7802_GAIN_64: + gain = 64; + break; + case NAU7802_GAIN_32: + gain = 32; + break; + case NAU7802_GAIN_16: + gain = 16; + break; + case NAU7802_GAIN_8: + gain = 8; + break; + case NAU7802_GAIN_4: + gain = 4; + break; + case NAU7802_GAIN_2: + gain = 2; + break; + case NAU7802_GAIN_1: + gain = 1; + break; + } + ESP_LOGCONFIG(TAG, " Gain: %dx", gain); + int sps = 0; + switch (this->sps_) { + case NAU7802_SPS_320: + sps = 320; + break; + case NAU7802_SPS_80: + sps = 80; + break; + case NAU7802_SPS_40: + sps = 40; + break; + case NAU7802_SPS_20: + sps = 20; + break; + case NAU7802_SPS_10: + sps = 10; + break; + } + ESP_LOGCONFIG(TAG, " Samples Per Second: %d", sps); + LOG_UPDATE_INTERVAL(this); +} + +void NAU7802Sensor::write_value_(uint8_t start_reg, size_t size, int32_t value) { + uint8_t data[4]; + for (int i = 0; i < size; i++) { + data[i] = 0xFF & (value >> (size - 1 - i) * 8); + } + this->write_register(start_reg, data, size); +} + +int32_t NAU7802Sensor::read_value_(uint8_t start_reg, size_t size) { + uint8_t data[4]; + this->read_register(start_reg, data, size); + int32_t result = 0; + for (int i = 0; i < size; i++) { + result |= data[i] << (size - 1 - i) * 8; + } + // extend sign bit + if (result & 0x800000 && size == 3) { + result |= 0xFF000000; + } + return result; +} + +bool NAU7802Sensor::calibrate_(enum NAU7802CalibrationModes mode) { + // check if already calbrating + if (this->state_ != CalibrationState::INACTIVE) { + ESP_LOGW(TAG, "Calibration already in progress"); + return false; + } + + this->state_ = mode == NAU7802_CALIBRATE_GAIN ? CalibrationState::GAIN : CalibrationState::OFFSET; + + i2c::I2CRegister ctrl2 = this->reg(CTRL2_REG); + // clear calibraye registers + ctrl2 &= CTRL2_CONFIG_MASK; + // Calibrate + ctrl2 |= mode; + ctrl2 |= CTRL2_CALS; + return true; +} + +void NAU7802Sensor::set_calibration_failure_(bool failed) { + switch (this->state_) { + case CalibrationState::GAIN: + this->gain_calibration_failed_ = failed; + break; + case CalibrationState::OFFSET: + this->offset_calibration_failed_ = failed; + break; + case CalibrationState::INACTIVE: + // shouldn't happen + break; + } +} + +void NAU7802Sensor::loop() { + i2c::I2CRegister ctrl2 = this->reg(CTRL2_REG); + + if (this->state_ != CalibrationState::INACTIVE && !(ctrl2.get() & CTRL2_CALS)) { + if (ctrl2.get() & CTRL2_CAL_ERR) { + this->set_calibration_failure_(true); + this->state_ = CalibrationState::INACTIVE; + ESP_LOGE(TAG, "Failed to calibrate sensor"); + this->status_set_error("Calibration Failed"); + return; + } + + this->set_calibration_failure_(false); + this->state_ = CalibrationState::INACTIVE; + + if (!this->offset_calibration_failed_ && !this->gain_calibration_failed_) + this->status_clear_error(); + + int32_t ocal = this->read_value_(OCAL1_B2_REG, 3); + ESP_LOGI(TAG, "New Offset: %s", to_string(ocal).c_str()); + uint32_t gcal = this->read_value_(GCAL1_B3_REG, 4); + float gcal_f = ((float) gcal / (float) (1 << GCAL1_FRACTIONAL)); + ESP_LOGI(TAG, "New Gain: %f", gcal_f); + } +} + +float NAU7802Sensor::get_setup_priority() const { return setup_priority::DATA; } + +void NAU7802Sensor::update() { + if (!this->is_data_ready_()) { + ESP_LOGW(TAG, "No measurements ready!"); + this->status_set_warning(); + return; + } + + this->status_clear_warning(); + + // Get the most recent sample to publish + int32_t result = this->read_value_(ADCO_B2_REG, 3); + + ESP_LOGD(TAG, "'%s': Got value %" PRId32, this->name_.c_str(), result); + this->publish_state(result); +} + +bool NAU7802Sensor::is_data_ready_() { return this->reg(PU_CTRL_REG).get() & PU_CTRL_CYCLE_READY; } + +bool NAU7802Sensor::can_proceed() { return this->setup_complete_; } + +} // namespace nau7802 +} // namespace esphome diff --git a/esphome/components/nau7802/nau7802.h b/esphome/components/nau7802/nau7802.h new file mode 100644 index 0000000000..3b0372aa89 --- /dev/null +++ b/esphome/components/nau7802/nau7802.h @@ -0,0 +1,121 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/automation.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/i2c/i2c.h" + +#include + +namespace esphome { +namespace nau7802 { + +enum NAU7802Gain { + NAU7802_GAIN_128 = 0b111, + NAU7802_GAIN_64 = 0b110, + NAU7802_GAIN_32 = 0b101, + NAU7802_GAIN_16 = 0b100, + NAU7802_GAIN_8 = 0b011, + NAU7802_GAIN_4 = 0b010, + NAU7802_GAIN_2 = 0b001, + NAU7802_GAIN_1 = 0b000, +}; + +enum NAU7802SPS { + NAU7802_SPS_320 = 0b111, + NAU7802_SPS_80 = 0b011, + NAU7802_SPS_40 = 0b010, + NAU7802_SPS_20 = 0b001, + NAU7802_SPS_10 = 0b000, +}; + +enum NAU7802LDO { + NAU7802_LDO_2V4 = 0b111, + NAU7802_LDO_2V7 = 0b110, + NAU7802_LDO_3V0 = 0b101, + NAU7802_LDO_3V3 = 0b100, + NAU7802_LDO_3V6 = 0b011, + NAU7802_LDO_3V9 = 0b010, + NAU7802_LDO_4V2 = 0b001, + NAU7802_LDO_4V5 = 0b000, + // Never write this to a register + NAU7802_LDO_EXTERNAL = 0b1000, +}; + +enum NAU7802CalibrationModes { + NAU7802_CALIBRATE_EXTERNAL_OFFSET = 0b10, + NAU7802_CALIBRATE_INTERNAL_OFFSET = 0b00, + NAU7802_CALIBRATE_GAIN = 0b11, +}; + +class NAU7802Sensor : public sensor::Sensor, public PollingComponent, public i2c::I2CDevice { + public: + void set_samples_per_second(NAU7802SPS sps) { this->sps_ = sps; } + void set_ldo_voltage(NAU7802LDO ldo) { this->ldo_ = ldo; } + void set_gain(NAU7802Gain gain) { this->gain_ = gain; } + void set_gain_calibration(float gain_calibration) { this->gain_calibration_ = gain_calibration; } + void set_offset_calibration(int32_t offset_calibration) { this->offset_calibration_ = offset_calibration; } + bool calibrate_external_offset() { return this->calibrate_(NAU7802_CALIBRATE_EXTERNAL_OFFSET); } + bool calibrate_internal_offset() { return this->calibrate_(NAU7802_CALIBRATE_INTERNAL_OFFSET); } + bool calibrate_gain() { return this->calibrate_(NAU7802_CALIBRATE_GAIN); } + + void setup() override; + void loop() override; + bool can_proceed() override; + void dump_config() override; + float get_setup_priority() const override; + void update() override; + + protected: + // + // Internal state + // + enum class CalibrationState : uint8_t { + INACTIVE, + OFFSET, + GAIN, + } state_{CalibrationState::INACTIVE}; + + float gain_calibration_; + int32_t offset_calibration_; + bool offset_calibration_failed_ = false; + bool gain_calibration_failed_ = false; + bool setup_complete_ = false; + + // + // Config values + // + NAU7802LDO ldo_; + NAU7802SPS sps_; + NAU7802Gain gain_; + + // + // Internal Methods + // + bool calibrate_(enum NAU7802CalibrationModes mode); + void complete_setup_(); + void write_value_(uint8_t start_reg, size_t size, int32_t value); + int32_t read_value_(uint8_t start_reg, size_t size); + bool is_data_ready_(); + void set_calibration_failure_(bool failed); +}; + +template +class NAU7802CalbrateExternalOffsetAction : public Action, public Parented { + public: + void play(Ts... x) override { this->parent_->calibrate_external_offset(); } +}; + +template +class NAU7802CalbrateInternalOffsetAction : public Action, public Parented { + public: + void play(Ts... x) override { this->parent_->calibrate_internal_offset(); } +}; + +template class NAU7802CalbrateGainAction : public Action, public Parented { + public: + void play(Ts... x) override { this->parent_->calibrate_gain(); } +}; + +} // namespace nau7802 +} // namespace esphome diff --git a/esphome/components/nau7802/sensor.py b/esphome/components/nau7802/sensor.py new file mode 100644 index 0000000000..9192f48f53 --- /dev/null +++ b/esphome/components/nau7802/sensor.py @@ -0,0 +1,134 @@ +from esphome import automation +from esphome.automation import maybe_simple_id +import esphome.codegen as cg +from esphome.components import i2c, sensor +import esphome.config_validation as cv +from esphome.const import CONF_GAIN, CONF_ID, ICON_SCALE, STATE_CLASS_MEASUREMENT + +CODEOWNERS = ["@cujomalainey"] +DEPENDENCIES = ["i2c"] + +CONF_GAIN_CALIBRATION = "gain_calibration" +CONF_OFFSET_CALIBRATION = "offset_calibration" +CONF_LDO_VOLTAGE = "ldo_voltage" +CONF_SAMPLES_PER_SECOND = "samples_per_second" + +nau7802_ns = cg.esphome_ns.namespace("nau7802") +NAU7802Sensor = nau7802_ns.class_( + "NAU7802Sensor", sensor.Sensor, cg.PollingComponent, i2c.I2CDevice +) +NAU7802CalbrateExternalOffsetAction = nau7802_ns.class_( + "NAU7802CalbrateExternalOffsetAction", + automation.Action, + cg.Parented.template(NAU7802Sensor), +) +NAU7802CalbrateInternalOffsetAction = nau7802_ns.class_( + "NAU7802CalbrateInternalOffsetAction", + automation.Action, + cg.Parented.template(NAU7802Sensor), +) +NAU7802CalbrateGainAction = nau7802_ns.class_( + "NAU7802CalbrateGainAction", automation.Action, cg.Parented.template(NAU7802Sensor) +) + +NAU7802Gain = nau7802_ns.enum("NAU7802Gain") +GAINS = { + 128: NAU7802Gain.NAU7802_GAIN_128, + 64: NAU7802Gain.NAU7802_GAIN_64, + 32: NAU7802Gain.NAU7802_GAIN_32, + 16: NAU7802Gain.NAU7802_GAIN_16, + 8: NAU7802Gain.NAU7802_GAIN_8, + 4: NAU7802Gain.NAU7802_GAIN_4, + 2: NAU7802Gain.NAU7802_GAIN_2, + 1: NAU7802Gain.NAU7802_GAIN_1, +} + +NAU7802SPS = nau7802_ns.enum("NAU7802SPS") +SAMPLES_PER_SECOND = { + 320: NAU7802SPS.NAU7802_SPS_320, + 80: NAU7802SPS.NAU7802_SPS_80, + 40: NAU7802SPS.NAU7802_SPS_40, + 20: NAU7802SPS.NAU7802_SPS_20, + 10: NAU7802SPS.NAU7802_SPS_10, +} + +NAU7802LDO = nau7802_ns.enum("NAU7802LDO") +LDO = { + "2.4V": NAU7802LDO.NAU7802_LDO_2V4, + "2.7V": NAU7802LDO.NAU7802_LDO_2V7, + "3.0V": NAU7802LDO.NAU7802_LDO_3V0, + "3.3V": NAU7802LDO.NAU7802_LDO_3V3, + "3.6V": NAU7802LDO.NAU7802_LDO_3V6, + "3.9V": NAU7802LDO.NAU7802_LDO_3V9, + "4.2V": NAU7802LDO.NAU7802_LDO_4V2, + "4.5V": NAU7802LDO.NAU7802_LDO_4V5, + "EXTERNAL": NAU7802LDO.NAU7802_LDO_EXTERNAL, + "EXT": NAU7802LDO.NAU7802_LDO_EXTERNAL, +} + +CONFIG_SCHEMA = ( + sensor.sensor_schema( + NAU7802Sensor, + icon=ICON_SCALE, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ) + .extend( + { + cv.Optional(CONF_LDO_VOLTAGE, default="3.0V"): cv.enum(LDO, upper=True), + cv.Optional(CONF_SAMPLES_PER_SECOND, default=10): cv.enum( + SAMPLES_PER_SECOND, int=True + ), + cv.Optional(CONF_GAIN, default=128): cv.enum(GAINS, int=True), + cv.Optional(CONF_OFFSET_CALIBRATION, default=0): cv.int_range( + min=-8388608, max=8388607 + ), + cv.Optional(CONF_GAIN_CALIBRATION, default=1.0): cv.float_range( + min=0, max=511.9999998807907 + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x2A)) +) + + +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) + await sensor.register_sensor(var, config) + + cg.add(var.set_samples_per_second(config[CONF_SAMPLES_PER_SECOND])) + cg.add(var.set_ldo_voltage(config[CONF_LDO_VOLTAGE])) + cg.add(var.set_gain(config[CONF_GAIN])) + cg.add(var.set_gain_calibration(config[CONF_GAIN_CALIBRATION])) + cg.add(var.set_offset_calibration(config[CONF_OFFSET_CALIBRATION])) + + +NAU7802_CALIBRATE_SCHEMA = maybe_simple_id( + { + cv.GenerateID(CONF_ID): cv.use_id(NAU7802Sensor), + } +) + + +@automation.register_action( + "nau7802.calibrate_internal_offset", + NAU7802CalbrateInternalOffsetAction, + NAU7802_CALIBRATE_SCHEMA, +) +@automation.register_action( + "nau7802.calibrate_external_offset", + NAU7802CalbrateExternalOffsetAction, + NAU7802_CALIBRATE_SCHEMA, +) +@automation.register_action( + "nau7802.calibrate_gain", + NAU7802CalbrateGainAction, + NAU7802_CALIBRATE_SCHEMA, +) +async def nau7802_calibrate_to_code(config, action_id, template_arg, args): + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + return var diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index caa873a746..be4e102930 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"] @@ -23,10 +17,17 @@ CONFIG_SCHEMA = cv.Schema( esp8266=False, esp32=False, rp2040=False, + bk72xx=False, ): 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), + bk72xx_libretiny=cv.Version(1, 7, 0), + ), cv.boolean_false, ), ), @@ -53,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/nextion/base_component.py b/esphome/components/nextion/base_component.py index d12434ec8f..2924f66d3c 100644 --- a/esphome/components/nextion/base_component.py +++ b/esphome/components/nextion/base_component.py @@ -27,6 +27,7 @@ CONF_BACKGROUND_PRESSED_COLOR = "background_pressed_color" CONF_FOREGROUND_PRESSED_COLOR = "foreground_pressed_color" CONF_FONT_ID = "font_id" CONF_EXIT_REPARSE_ON_START = "exit_reparse_on_start" +CONF_SKIP_CONNECTION_HANDSHAKE = "skip_connection_handshake" def NextionName(value): diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index ce45d25e7b..e403ba7ae8 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -23,6 +23,7 @@ from .base_component import ( CONF_START_UP_PAGE, CONF_AUTO_WAKE_ON_TOUCH, CONF_EXIT_REPARSE_ON_START, + CONF_SKIP_CONNECTION_HANDSHAKE, ) CODEOWNERS = ["@senexcrenshaw", "@edwardtfn"] @@ -72,6 +73,7 @@ CONFIG_SCHEMA = ( 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, + cv.Optional(CONF_SKIP_CONNECTION_HANDSHAKE, default=False): cv.boolean, } ) .extend(cv.polling_component_schema("5s")) @@ -118,6 +120,8 @@ async def to_code(config): cg.add(var.set_exit_reparse_on_start_internal(config[CONF_EXIT_REPARSE_ON_START])) + cg.add(var.set_skip_connection_handshake(config[CONF_SKIP_CONNECTION_HANDSHAKE])) + await display.register_display(var, config) for conf in config.get(CONF_ON_SETUP, []): diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index ddbd3328ef..a80f6efc91 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -43,6 +43,16 @@ bool Nextion::check_connect_() { if (this->get_is_connected_()) return true; + // Check if the handshake should be skipped for the Nextion connection + if (this->skip_connection_handshake_) { + // Log the connection status without handshake + ESP_LOGW(TAG, "Nextion display set as connected without performing handshake"); + // Set the connection status to true + this->is_connected_ = true; + // Return true indicating the connection is set + return true; + } + if (this->comok_sent_ == 0) { this->reset_(false); @@ -126,10 +136,14 @@ void Nextion::reset_(bool reset_nextion) { void Nextion::dump_config() { ESP_LOGCONFIG(TAG, "Nextion:"); - ESP_LOGCONFIG(TAG, " Device Model: %s", this->device_model_.c_str()); - ESP_LOGCONFIG(TAG, " Firmware Version: %s", this->firmware_version_.c_str()); - ESP_LOGCONFIG(TAG, " Serial Number: %s", this->serial_number_.c_str()); - ESP_LOGCONFIG(TAG, " Flash Size: %s", this->flash_size_.c_str()); + if (this->skip_connection_handshake_) { + ESP_LOGCONFIG(TAG, " Skip handshake: %s", YESNO(this->skip_connection_handshake_)); + } else { + ESP_LOGCONFIG(TAG, " Device Model: %s", this->device_model_.c_str()); + ESP_LOGCONFIG(TAG, " Firmware Version: %s", this->firmware_version_.c_str()); + ESP_LOGCONFIG(TAG, " Serial Number: %s", this->serial_number_.c_str()); + ESP_LOGCONFIG(TAG, " Flash Size: %s", this->flash_size_.c_str()); + } ESP_LOGCONFIG(TAG, " Wake On Touch: %s", YESNO(this->auto_wake_on_touch_)); ESP_LOGCONFIG(TAG, " Exit reparse: %s", YESNO(this->exit_reparse_on_start_)); @@ -262,6 +276,7 @@ void Nextion::loop() { this->goto_page(this->start_up_page_); } + // This could probably be removed from the loop area, as those are redundant. this->set_auto_wake_on_touch(this->auto_wake_on_touch_); this->set_exit_reparse_on_start(this->exit_reparse_on_start_); diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index 4546baa4d8..732ee9b455 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -926,6 +926,21 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe */ void set_exit_reparse_on_start(bool exit_reparse); + /** + * Sets whether the Nextion display should skip the connection handshake process. + * @param skip_handshake True or false. When skip_connection_handshake is true, + * the connection will be established without performing the handshake. + * This can be useful when using Nextion Simulator. + * + * Example: + * ```cpp + * it.set_skip_connection_handshake(true); + * ``` + * + * When set to true, the display will be marked as connected without performing a handshake. + */ + void set_skip_connection_handshake(bool skip_handshake) { this->skip_connection_handshake_ = skip_handshake; } + /** * Sets Nextion mode between sleep and awake * @param True or false. Sleep=true to enter sleep mode or sleep=false to exit sleep mode. @@ -1221,6 +1236,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe int16_t start_up_page_ = -1; bool auto_wake_on_touch_ = true; bool exit_reparse_on_start_ = false; + bool skip_connection_handshake_ = false; /** * Manually send a raw command to the display and don't wait for an acknowledgement packet. diff --git a/esphome/components/npi19/__init__.py b/esphome/components/npi19/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/npi19/npi19.cpp b/esphome/components/npi19/npi19.cpp new file mode 100644 index 0000000000..ca1fc39943 --- /dev/null +++ b/esphome/components/npi19/npi19.cpp @@ -0,0 +1,111 @@ +#include "npi19.h" +#include "esphome/core/log.h" +#include "esphome/core/helpers.h" +#include "esphome/core/hal.h" + +namespace esphome { +namespace npi19 { + +static const char *const TAG = "npi19"; + +static const uint8_t READ_COMMAND = 0xAC; + +void NPI19Component::setup() { + ESP_LOGCONFIG(TAG, "Setting up NPI19..."); + + uint16_t raw_temperature(0); + uint16_t raw_pressure(0); + i2c::ErrorCode err = this->read_(raw_temperature, raw_pressure); + if (err != i2c::ERROR_OK) { + ESP_LOGCONFIG(TAG, " I2C Communication Failed..."); + this->mark_failed(); + return; + } + + ESP_LOGCONFIG(TAG, " Success..."); +} + +void NPI19Component::dump_config() { + ESP_LOGCONFIG(TAG, "NPI19:"); + LOG_I2C_DEVICE(this); + LOG_UPDATE_INTERVAL(this); + LOG_SENSOR(" ", "Raw Pressure", this->raw_pressure_sensor_); + LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); +} + +float NPI19Component::get_setup_priority() const { return setup_priority::DATA; } + +i2c::ErrorCode NPI19Component::read_(uint16_t &raw_temperature, uint16_t &raw_pressure) { + // initiate data read from device + i2c::ErrorCode w_err = write(&READ_COMMAND, sizeof(READ_COMMAND), true); + if (w_err != i2c::ERROR_OK) { + return w_err; + } + + // read 4 bytes from senesor + uint8_t response[4] = {0x00, 0x00, 0x00, 0x00}; + i2c::ErrorCode r_err = this->read(response, 4); + + if (r_err != i2c::ERROR_OK) { + return r_err; + } + + // extract top 6 bits of first byte and all bits of second byte for pressure + raw_pressure = ((response[0] & 0x3F) << 8) | response[1]; + + // extract all bytes of 3rd byte and top 3 bits of fourth byte for temperature + raw_temperature = (response[2] << 3) | ((response[3] & 0xE0) >> 5); + + return i2c::ERROR_OK; +} + +inline float convert_temperature(uint16_t raw_temperature) { + /* + * Correspondance with Amphenol confirmed the appropriate equation for computing temperature is: + * T (°C) =(((((Th*8)+Tl)/2048)*200)-50), where Th is the high (third) byte and Tl is the low (fourth) byte. + * + * Tl is actually the upper 3 bits of the fourth data byte; the first 5 (LSBs) must be masked out. + * + * + * The NPI-19 I2C has a temperature output, however the manufacturer does + * not specify its accuracy on the published datasheet. They indicate + * that the sensor should not be used as a calibrated temperature + * reading; it’s only intended for curve fitting data during + * compensation. + */ + const float temperature_bits_span = 2048; + const float temperature_max = 150; + const float temperature_min = -50; + const float temperature_span = temperature_max - temperature_min; + + float temperature = (raw_temperature * temperature_span / temperature_bits_span) + temperature_min; + + return temperature; +} + +void NPI19Component::update() { + uint16_t raw_temperature(0); + uint16_t raw_pressure(0); + + i2c::ErrorCode err = this->read_(raw_temperature, raw_pressure); + + if (err != i2c::ERROR_OK) { + ESP_LOGW(TAG, "I2C Communication Failed"); + this->status_set_warning(); + return; + } + + float temperature = convert_temperature(raw_temperature); + + ESP_LOGD(TAG, "Got raw pressure=%d, temperature=%.1f°C", raw_pressure, temperature); + + if (this->temperature_sensor_ != nullptr) + this->temperature_sensor_->publish_state(temperature); + if (this->raw_pressure_sensor_ != nullptr) + this->raw_pressure_sensor_->publish_state(raw_pressure); + + this->status_clear_warning(); +} + +} // namespace npi19 +} // namespace esphome diff --git a/esphome/components/npi19/npi19.h b/esphome/components/npi19/npi19.h new file mode 100644 index 0000000000..df289dffc1 --- /dev/null +++ b/esphome/components/npi19/npi19.h @@ -0,0 +1,30 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/i2c/i2c.h" + +namespace esphome { +namespace npi19 { + +/// This class implements support for the npi19 pressure and temperature i2c sensors. +class NPI19Component : public PollingComponent, public i2c::I2CDevice { + public: + void set_temperature_sensor(sensor::Sensor *temperature_sensor) { this->temperature_sensor_ = temperature_sensor; } + void set_raw_pressure_sensor(sensor::Sensor *raw_pressure_sensor) { + this->raw_pressure_sensor_ = raw_pressure_sensor; + } + + float get_setup_priority() const override; + void setup() override; + void dump_config() override; + void update() override; + + protected: + i2c::ErrorCode read_(uint16_t &raw_temperature, uint16_t &raw_pressure); + sensor::Sensor *temperature_sensor_{nullptr}; + sensor::Sensor *raw_pressure_sensor_{nullptr}; +}; + +} // namespace npi19 +} // namespace esphome diff --git a/esphome/components/npi19/sensor.py b/esphome/components/npi19/sensor.py new file mode 100644 index 0000000000..d13e72f5f8 --- /dev/null +++ b/esphome/components/npi19/sensor.py @@ -0,0 +1,52 @@ +import esphome.codegen as cg +from esphome.components import i2c, sensor +import esphome.config_validation as cv +from esphome.const import ( + CONF_ID, + CONF_TEMPERATURE, + DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, +) + +CODEOWNERS = ["@bakerkj"] +DEPENDENCIES = ["i2c"] + +npi19_ns = cg.esphome_ns.namespace("npi19") + +NPI19Component = npi19_ns.class_("NPI19Component", cg.PollingComponent, i2c.I2CDevice) + +CONF_RAW_PRESSURE = "raw_pressure" + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(NPI19Component), + 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_RAW_PRESSURE): sensor.sensor_schema( + accuracy_decimals=0, state_class=STATE_CLASS_MEASUREMENT + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x28)) +) + + +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)) + + if raw_pressure_config := config.get(CONF_RAW_PRESSURE): + sens = await sensor.new_sensor(raw_pressure_config) + cg.add(var.set_raw_pressure_sensor(sens)) diff --git a/esphome/components/number/__init__.py b/esphome/components/number/__init__.py index ece738af49..f45cfd54f2 100644 --- a/esphome/components/number/__init__.py +++ b/esphome/components/number/__init__.py @@ -18,7 +18,7 @@ from esphome.const import ( CONF_TRIGGER_ID, CONF_UNIT_OF_MEASUREMENT, CONF_VALUE, - CONF_WEB_SERVER_ID, + CONF_WEB_SERVER, DEVICE_CLASS_APPARENT_POWER, DEVICE_CLASS_AQI, DEVICE_CLASS_ATMOSPHERIC_PRESSURE, @@ -254,10 +254,8 @@ async def setup_number_core_( 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) + if web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(var, web_server_config) async def register_number( diff --git a/esphome/components/online_image/__init__.py b/esphome/components/online_image/__init__.py index d9a7609543..dfb10137aa 100644 --- a/esphome/components/online_image/__init__.py +++ b/esphome/components/online_image/__init__.py @@ -125,7 +125,7 @@ async def online_image_action_to_code(config, action_id, template_arg, args): 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) + template_ = await cg.templatable(config[CONF_URL], args, cg.std_string) cg.add(var.set_url(template_)) return var diff --git a/esphome/components/online_image/online_image.cpp b/esphome/components/online_image/online_image.cpp index 480bad6aca..1786809dfa 100644 --- a/esphome/components/online_image/online_image.cpp +++ b/esphome/components/online_image/online_image.cpp @@ -215,16 +215,10 @@ void OnlineImage::draw_pixel_(int x, int y, Color color) { } 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); + if (this->has_transparency()) + this->buffer_[pos + 2] = color.w; break; } case ImageType::IMAGE_TYPE_RGBA: { diff --git a/esphome/components/online_image/online_image.h b/esphome/components/online_image/online_image.h index 775cc46e0b..017402a088 100644 --- a/esphome/components/online_image/online_image.h +++ b/esphome/components/online_image/online_image.h @@ -86,13 +86,9 @@ class OnlineImage : public PollingComponent, 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_buffer_size_(int width, int height) const { return (this->get_bpp() * width + 7u) / 8u * height; } - int get_position_(int x, int y) const { - return ((x + y * this->buffer_width_) * image::image_type_to_bpp(this->type_)) / 8; - } + int get_position_(int x, int y) const { return (x + y * this->buffer_width_) * this->get_bpp() / 8; } ESPHOME_ALWAYS_INLINE bool auto_resize_() const { return this->fixed_width_ == 0 || this->fixed_height_ == 0; } @@ -157,7 +153,7 @@ class OnlineImage : public PollingComponent, template class OnlineImageSetUrlAction : public Action { public: OnlineImageSetUrlAction(OnlineImage *parent) : parent_(parent) {} - TEMPLATABLE_VALUE(const char *, url) + TEMPLATABLE_VALUE(std::string, url) void play(Ts... x) override { this->parent_->set_url(this->url_.value(x...)); this->parent_->update(); @@ -170,7 +166,6 @@ template class OnlineImageSetUrlAction : public Action { 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: diff --git a/esphome/components/opentherm/__init__.py b/esphome/components/opentherm/__init__.py new file mode 100644 index 0000000000..ee19818a29 --- /dev/null +++ b/esphome/components/opentherm/__init__.py @@ -0,0 +1,59 @@ +from typing import Any + +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import pins +from esphome.const import CONF_ID, PLATFORM_ESP32, PLATFORM_ESP8266 +from . import generate + +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_SUMMER_MODE_ACTIVE = "summer_mode_active" +CONF_DHW_BLOCK = "dhw_block" +CONF_SYNC_MODE = "sync_mode" + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(generate.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_SUMMER_MODE_ACTIVE, False): cv.boolean, + cv.Optional(CONF_DHW_BLOCK, 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: + 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 in non_sensors: + continue + + cg.add(getattr(var, f"set_{key}")(value)) diff --git a/esphome/components/opentherm/const.py b/esphome/components/opentherm/const.py new file mode 100644 index 0000000000..1f997c5d9c --- /dev/null +++ b/esphome/components/opentherm/const.py @@ -0,0 +1,5 @@ +OPENTHERM = "opentherm" + +CONF_OPENTHERM_ID = "opentherm_id" + +SENSOR = "sensor" diff --git a/esphome/components/opentherm/generate.py b/esphome/components/opentherm/generate.py new file mode 100644 index 0000000000..6a97835a57 --- /dev/null +++ b/esphome/components/opentherm/generate.py @@ -0,0 +1,140 @@ +from collections.abc import Awaitable +from typing import Any, Callable + +import esphome.codegen as cg +from esphome.const import CONF_ID +from . import const +from .schema import TSchema + +opentherm_ns = cg.esphome_ns.namespace("opentherm") +OpenthermHub = opentherm_ns.class_("OpenthermHub", cg.Component) + + +def define_has_component(component_type: str, keys: list[str]) -> None: + cg.add_define( + f"OPENTHERM_{component_type.upper()}_LIST(F, sep)", + cg.RawExpression( + " sep ".join(map(lambda key: f"F({key}_{component_type.lower()})", keys)) + ), + ) + for key in keys: + cg.add_define(f"OPENTHERM_HAS_{component_type.upper()}_{key}") + + +def define_message_handler( + component_type: str, keys: list[str], schemas: dict[str, TSchema] +) -> None: + # The macros defined here should be able to generate things like this: + # // Parsing a message and publishing to sensors + # case MessageId::Message: + # // Can have multiple sensors here, for example for a Status message with multiple flags + # this->thing_binary_sensor->publish_state(parse_flag8_lb_0(response)); + # this->other_binary_sensor->publish_state(parse_flag8_lb_1(response)); + # break; + # // Building a message for a write request + # case MessageId::Message: { + # unsigned int data = 0; + # data = write_flag8_lb_0(some_input_switch->state, data); // Where input_sensor can also be a number/output/switch + # data = write_u8_hb(some_number->state, data); + # return opentherm_->build_request_(MessageType::WriteData, MessageId::Message, data); + # } + + messages: dict[str, list[tuple[str, str]]] = {} + for key in keys: + msg = schemas[key].message + if msg not in messages: + messages[msg] = [] + messages[msg].append((key, schemas[key].message_data)) + + cg.add_define( + f"OPENTHERM_{component_type.upper()}_MESSAGE_HANDLERS(MESSAGE, ENTITY, entity_sep, postscript, msg_sep)", + cg.RawExpression( + " msg_sep ".join( + [ + f"MESSAGE({msg}) " + + " entity_sep ".join( + [ + f"ENTITY({key}_{component_type.lower()}, {msg_data})" + for key, msg_data in keys + ] + ) + + " postscript" + for msg, keys in messages.items() + ] + ) + ), + ) + + +def define_readers(component_type: str, keys: list[str]) -> None: + for key in keys: + cg.add_define( + f"OPENTHERM_READ_{key}", + cg.RawExpression(f"this->{key}_{component_type.lower()}->state"), + ) + + +def add_messages(hub: cg.MockObj, keys: list[str], schemas: dict[str, TSchema]): + messages: set[tuple[str, bool]] = set() + for key in keys: + messages.add((schemas[key].message, schemas[key].keep_updated)) + for msg, keep_updated in messages: + msg_expr = cg.RawExpression(f"esphome::opentherm::MessageId::{msg}") + if keep_updated: + cg.add(hub.add_repeating_message(msg_expr)) + else: + cg.add(hub.add_initial_message(msg_expr)) + + +def add_property_set(var: cg.MockObj, config_key: str, config: dict[str, Any]) -> None: + if config_key in config: + cg.add(getattr(var, f"set_{config_key}")(config[config_key])) + + +Create = Callable[[dict[str, Any], str, cg.MockObj], Awaitable[cg.Pvariable]] + + +def create_only_conf( + create: Callable[[dict[str, Any]], Awaitable[cg.Pvariable]] +) -> Create: + return lambda conf, _key, _hub: create(conf) + + +async def component_to_code( + component_type: str, + schemas: dict[str, TSchema], + type: cg.MockObjClass, + create: Create, + config: dict[str, Any], +) -> list[str]: + """Generate the code for each configured component in the schema of a component type. + + Parameters: + - component_type: The type of component, e.g. "sensor" or "binary_sensor" + - schema_: The schema for that component type, a list of available components + - type: The type of the component, e.g. sensor.Sensor or OpenthermOutput + - create: A constructor function for the component, which receives the config, + the key and the hub and should asynchronously return the new component + - config: The configuration for this component type + + Returns: The list of keys for the created components + """ + cg.add_define(f"OPENTHERM_USE_{component_type.upper()}") + + hub = await cg.get_variable(config[const.CONF_OPENTHERM_ID]) + + keys: list[str] = [] + for key, conf in config.items(): + if not isinstance(conf, dict): + continue + id = conf[CONF_ID] + if id and id.type == type: + entity = await create(conf, key, hub) + cg.add(getattr(hub, f"set_{key}_{component_type.lower()}")(entity)) + keys.append(key) + + define_has_component(component_type, keys) + define_message_handler(component_type, keys, schemas) + add_messages(hub, keys, schemas) + + return keys diff --git a/esphome/components/opentherm/hub.cpp b/esphome/components/opentherm/hub.cpp new file mode 100644 index 0000000000..770bbd82b7 --- /dev/null +++ b/esphome/components/opentherm/hub.cpp @@ -0,0 +1,343 @@ +#include "hub.h" +#include "esphome/core/helpers.h" + +#include + +namespace esphome { +namespace opentherm { + +static const char *const TAG = "opentherm"; +namespace message_data { +bool parse_flag8_lb_0(OpenthermData &data) { return read_bit(data.valueLB, 0); } +bool parse_flag8_lb_1(OpenthermData &data) { return read_bit(data.valueLB, 1); } +bool parse_flag8_lb_2(OpenthermData &data) { return read_bit(data.valueLB, 2); } +bool parse_flag8_lb_3(OpenthermData &data) { return read_bit(data.valueLB, 3); } +bool parse_flag8_lb_4(OpenthermData &data) { return read_bit(data.valueLB, 4); } +bool parse_flag8_lb_5(OpenthermData &data) { return read_bit(data.valueLB, 5); } +bool parse_flag8_lb_6(OpenthermData &data) { return read_bit(data.valueLB, 6); } +bool parse_flag8_lb_7(OpenthermData &data) { return read_bit(data.valueLB, 7); } +bool parse_flag8_hb_0(OpenthermData &data) { return read_bit(data.valueHB, 0); } +bool parse_flag8_hb_1(OpenthermData &data) { return read_bit(data.valueHB, 1); } +bool parse_flag8_hb_2(OpenthermData &data) { return read_bit(data.valueHB, 2); } +bool parse_flag8_hb_3(OpenthermData &data) { return read_bit(data.valueHB, 3); } +bool parse_flag8_hb_4(OpenthermData &data) { return read_bit(data.valueHB, 4); } +bool parse_flag8_hb_5(OpenthermData &data) { return read_bit(data.valueHB, 5); } +bool parse_flag8_hb_6(OpenthermData &data) { return read_bit(data.valueHB, 6); } +bool parse_flag8_hb_7(OpenthermData &data) { return read_bit(data.valueHB, 7); } +uint8_t parse_u8_lb(OpenthermData &data) { return data.valueLB; } +uint8_t parse_u8_hb(OpenthermData &data) { return data.valueHB; } +int8_t parse_s8_lb(OpenthermData &data) { return (int8_t) data.valueLB; } +int8_t parse_s8_hb(OpenthermData &data) { return (int8_t) data.valueHB; } +uint16_t parse_u16(OpenthermData &data) { return data.u16(); } +int16_t parse_s16(OpenthermData &data) { return data.s16(); } +float parse_f88(OpenthermData &data) { return data.f88(); } + +void write_flag8_lb_0(const bool value, OpenthermData &data) { data.valueLB = write_bit(data.valueLB, 0, value); } +void write_flag8_lb_1(const bool value, OpenthermData &data) { data.valueLB = write_bit(data.valueLB, 1, value); } +void write_flag8_lb_2(const bool value, OpenthermData &data) { data.valueLB = write_bit(data.valueLB, 2, value); } +void write_flag8_lb_3(const bool value, OpenthermData &data) { data.valueLB = write_bit(data.valueLB, 3, value); } +void write_flag8_lb_4(const bool value, OpenthermData &data) { data.valueLB = write_bit(data.valueLB, 4, value); } +void write_flag8_lb_5(const bool value, OpenthermData &data) { data.valueLB = write_bit(data.valueLB, 5, value); } +void write_flag8_lb_6(const bool value, OpenthermData &data) { data.valueLB = write_bit(data.valueLB, 6, value); } +void write_flag8_lb_7(const bool value, OpenthermData &data) { data.valueLB = write_bit(data.valueLB, 7, value); } +void write_flag8_hb_0(const bool value, OpenthermData &data) { data.valueHB = write_bit(data.valueHB, 0, value); } +void write_flag8_hb_1(const bool value, OpenthermData &data) { data.valueHB = write_bit(data.valueHB, 1, value); } +void write_flag8_hb_2(const bool value, OpenthermData &data) { data.valueHB = write_bit(data.valueHB, 2, value); } +void write_flag8_hb_3(const bool value, OpenthermData &data) { data.valueHB = write_bit(data.valueHB, 3, value); } +void write_flag8_hb_4(const bool value, OpenthermData &data) { data.valueHB = write_bit(data.valueHB, 4, value); } +void write_flag8_hb_5(const bool value, OpenthermData &data) { data.valueHB = write_bit(data.valueHB, 5, value); } +void write_flag8_hb_6(const bool value, OpenthermData &data) { data.valueHB = write_bit(data.valueHB, 6, value); } +void write_flag8_hb_7(const bool value, OpenthermData &data) { data.valueHB = write_bit(data.valueHB, 7, value); } +void write_u8_lb(const uint8_t value, OpenthermData &data) { data.valueLB = value; } +void write_u8_hb(const uint8_t value, OpenthermData &data) { data.valueHB = value; } +void write_s8_lb(const int8_t value, OpenthermData &data) { data.valueLB = (uint8_t) value; } +void write_s8_hb(const int8_t value, OpenthermData &data) { data.valueHB = (uint8_t) value; } +void write_u16(const uint16_t value, OpenthermData &data) { data.u16(value); } +void write_s16(const int16_t value, OpenthermData &data) { data.s16(value); } +void write_f88(const float value, OpenthermData &data) { data.f88(value); } + +} // namespace message_data + +OpenthermData OpenthermHub::build_request_(MessageId request_id) const { + OpenthermData data; + data.type = 0; + data.id = 0; + data.valueHB = 0; + data.valueLB = 0; + + // We need this special logic for STATUS message because we have two options for specifying boiler modes: + // with static config values in the hub, or with separate switches. + if (request_id == MessageId::STATUS) { + // NOLINTBEGIN + bool const ch_enabled = this->ch_enable && OPENTHERM_READ_ch_enable && OPENTHERM_READ_t_set > 0.0; + bool const dhw_enabled = this->dhw_enable && OPENTHERM_READ_dhw_enable; + bool const cooling_enabled = + this->cooling_enable && OPENTHERM_READ_cooling_enable && OPENTHERM_READ_cooling_control > 0.0; + bool const otc_enabled = this->otc_active && OPENTHERM_READ_otc_active; + bool const ch2_enabled = this->ch2_active && OPENTHERM_READ_ch2_active && OPENTHERM_READ_t_set_ch2 > 0.0; + bool const summer_mode_is_active = this->summer_mode_active && OPENTHERM_READ_summer_mode_active; + bool const dhw_blocked = this->dhw_block && OPENTHERM_READ_dhw_block; + // NOLINTEND + + 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) | + (summer_mode_is_active << 5) | (dhw_blocked << 6); + + return data; + } + +// 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" + + switch (request_id) { OPENTHERM_SENSOR_MESSAGE_HANDLERS(OPENTHERM_MESSAGE_READ_MESSAGE, OPENTHERM_IGNORE, , , ) } + +#pragma GCC diagnostic pop + + // And if we get here, a message was requested which somehow wasn't handled. + // This shouldn't happen due to the way the defines are configured, so we + // log an error and just return a 0 message. + ESP_LOGE(TAG, "Tried to create a request with unknown id %d. This should never happen, so please open an issue.", + request_id); + return {}; +} + +OpenthermHub::OpenthermHub() : Component(), in_pin_{}, out_pin_{} {} + +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()); + + switch (data.id) { + OPENTHERM_SENSOR_MESSAGE_HANDLERS(OPENTHERM_MESSAGE_RESPONSE_MESSAGE, OPENTHERM_MESSAGE_RESPONSE_ENTITY, , + OPENTHERM_MESSAGE_RESPONSE_POSTSCRIPT, ) + } +} + +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_(); +} + +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, " Sensors: %s", SHOW(OPENTHERM_SENSOR_LIST(ID, ))); + ESP_LOGCONFIG(TAG, " Binary sensors: %s", SHOW(OPENTHERM_BINARY_SENSOR_LIST(ID, ))); + ESP_LOGCONFIG(TAG, " Switches: %s", SHOW(OPENTHERM_SWITCH_LIST(ID, ))); + ESP_LOGCONFIG(TAG, " Input sensors: %s", SHOW(OPENTHERM_INPUT_SENSOR_LIST(ID, ))); + ESP_LOGCONFIG(TAG, " Outputs: %s", SHOW(OPENTHERM_OUTPUT_LIST(ID, ))); + ESP_LOGCONFIG(TAG, " Numbers: %s", SHOW(OPENTHERM_NUMBER_LIST(ID, ))); + 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..3b90cdf427 --- /dev/null +++ b/esphome/components/opentherm/hub.h @@ -0,0 +1,123 @@ +#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" + +#ifdef OPENTHERM_USE_SENSOR +#include "esphome/components/sensor/sensor.h" +#endif + +#include +#include +#include +#include + +#include "opentherm_macros.h" + +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_; + + OPENTHERM_SENSOR_LIST(OPENTHERM_DECLARE_SENSOR, ) + + // 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) const; + 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; } + + OPENTHERM_SENSOR_LIST(OPENTHERM_SET_SENSOR, ) + + // 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 seven 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, + summer_mode_active = false, dhw_block = 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_summer_mode_active(bool value) { this->summer_mode_active = value; } + void set_dhw_block(bool value) { this->dhw_block = 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..4a23bb94cf --- /dev/null +++ b/esphome/components/opentherm/opentherm.cpp @@ -0,0 +1,571 @@ +/* + * 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, +#if defined(SOC_TIMER_GROUP_SUPPORT_XTAL) && ESP_IDF_VERSION_MAJOR < 5 + .clk_src = TIMER_SRC_CLK_APB +#endif + }; + + 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..23f4b39a1a --- /dev/null +++ b/esphome/components/opentherm/opentherm.h @@ -0,0 +1,346 @@ +/* + * 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 { + +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 ? set_bit(value, bit) : clear_bit(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/esphome/components/opentherm/opentherm_macros.h b/esphome/components/opentherm/opentherm_macros.h new file mode 100644 index 0000000000..0389e975ff --- /dev/null +++ b/esphome/components/opentherm/opentherm_macros.h @@ -0,0 +1,91 @@ +#pragma once +namespace esphome { +namespace opentherm { + +// ===== hub.h macros ===== + +// *_LIST macros will be generated in defines.h if at least one sensor from each platform is used. +// These lists will look like this: +// #define OPENTHERM_BINARY_SENSOR_LIST(F, sep) F(sensor_1) sep F(sensor_2) +// These lists will be used in hub.h to define sensor fields (passing macros like OPENTHERM_DECLARE_SENSOR as F) +// and setters (passing macros like OPENTHERM_SET_SENSOR as F) (see below) +// In order for things not to break, we define empty lists here in case some platforms are not used in config. +#ifndef OPENTHERM_SENSOR_LIST +#define OPENTHERM_SENSOR_LIST(F, sep) +#endif + +// Use macros to create fields for every entity specified in the ESPHome configuration +#define OPENTHERM_DECLARE_SENSOR(entity) sensor::Sensor *entity; + +// Setter macros +#define OPENTHERM_SET_SENSOR(entity) \ + void set_##entity(sensor::Sensor *sensor) { this->entity = sensor; } + +// ===== hub.cpp macros ===== + +// *_MESSAGE_HANDLERS are generated in defines.h and look like this: +// OPENTHERM_NUMBER_MESSAGE_HANDLERS(MESSAGE, ENTITY, entity_sep, postscript, msg_sep) MESSAGE(COOLING_CONTROL) +// ENTITY(cooling_control_number, f88) postscript msg_sep They contain placeholders for message part and entities parts, +// since one message can contain multiple entities. MESSAGE part is substituted with OPENTHERM_MESSAGE_WRITE_MESSAGE, +// OPENTHERM_MESSAGE_READ_MESSAGE or OPENTHERM_MESSAGE_RESPONSE_MESSAGE. ENTITY part is substituted with +// OPENTHERM_MESSAGE_WRITE_ENTITY or OPENTHERM_MESSAGE_RESPONSE_ENTITY. OPENTHERM_IGNORE is used for sensor read +// requests since no data needs to be sent or processed, just the data id. + +// In order for things not to break, we define empty lists here in case some platforms are not used in config. +#ifndef OPENTHERM_SENSOR_MESSAGE_HANDLERS +#define OPENTHERM_SENSOR_MESSAGE_HANDLERS(MESSAGE, ENTITY, entity_sep, postscript, msg_sep) +#endif + +// Read data request builder +#define OPENTHERM_MESSAGE_READ_MESSAGE(msg) \ + case MessageId::msg: \ + data.type = MessageType::READ_DATA; \ + data.id = request_id; \ + return data; + +// Data processing builders +#define OPENTHERM_MESSAGE_RESPONSE_MESSAGE(msg) case MessageId::msg: +#define OPENTHERM_MESSAGE_RESPONSE_ENTITY(key, msg_data) this->key->publish_state(message_data::parse_##msg_data(data)); +#define OPENTHERM_MESSAGE_RESPONSE_POSTSCRIPT break; + +#define OPENTHERM_IGNORE(x, y) + +// Default macros for STATUS entities +#ifndef OPENTHERM_READ_ch_enable +#define OPENTHERM_READ_ch_enable true +#endif +#ifndef OPENTHERM_READ_dhw_enable +#define OPENTHERM_READ_dhw_enable true +#endif +#ifndef OPENTHERM_READ_t_set +#define OPENTHERM_READ_t_set 0.0 +#endif +#ifndef OPENTHERM_READ_cooling_enable +#define OPENTHERM_READ_cooling_enable false +#endif +#ifndef OPENTHERM_READ_cooling_control +#define OPENTHERM_READ_cooling_control 0.0 +#endif +#ifndef OPENTHERM_READ_otc_active +#define OPENTHERM_READ_otc_active false +#endif +#ifndef OPENTHERM_READ_ch2_active +#define OPENTHERM_READ_ch2_active false +#endif +#ifndef OPENTHERM_READ_t_set_ch2 +#define OPENTHERM_READ_t_set_ch2 0.0 +#endif +#ifndef OPENTHERM_READ_summer_mode_active +#define OPENTHERM_READ_summer_mode_active false +#endif +#ifndef OPENTHERM_READ_dhw_block +#define OPENTHERM_READ_dhw_block false +#endif + +// These macros utilize the structure of *_LIST macros in order +#define ID(x) x +#define SHOW_INNER(x) #x +#define SHOW(x) SHOW_INNER(x) + +} // namespace opentherm +} // namespace esphome diff --git a/esphome/components/opentherm/schema.py b/esphome/components/opentherm/schema.py new file mode 100644 index 0000000000..6ed0029437 --- /dev/null +++ b/esphome/components/opentherm/schema.py @@ -0,0 +1,438 @@ +# This file contains a schema for all supported sensors, binary sensors and +# inputs of the OpenTherm component. + +from dataclasses import dataclass +from typing import Optional, TypeVar + +from esphome.const import ( + UNIT_CELSIUS, + UNIT_EMPTY, + UNIT_KILOWATT, + UNIT_MICROAMP, + UNIT_PERCENT, + UNIT_REVOLUTIONS_PER_MINUTE, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_PRESSURE, + DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, + STATE_CLASS_NONE, + STATE_CLASS_TOTAL_INCREASING, +) + + +@dataclass +class EntitySchema: + description: str + """Description of the item, based on the OpenTherm spec""" + + message: str + """OpenTherm message id used to read or write the value""" + + keep_updated: bool + """Whether the value should be read or write repeatedly (True) or only during + the initialization phase (False) + """ + + message_data: str + """Instructions on how to interpret the data in the message + - flag8_[hb|lb]_[0-7]: data is a byte of single bit flags, + this flag is set in the high (hb) or low byte (lb), + at position 0 to 7 + - u8_[hb|lb]: data is an unsigned 8-bit integer, + in the high (hb) or low byte (lb) + - s8_[hb|lb]: data is an signed 8-bit integer, + in the high (hb) or low byte (lb) + - f88: data is a signed fixed point value with + 1 sign bit, 7 integer bits, 8 fractional bits + - u16: data is an unsigned 16-bit integer + - s16: data is a signed 16-bit integer + """ + + +TSchema = TypeVar("TSchema", bound=EntitySchema) + + +@dataclass +class SensorSchema(EntitySchema): + accuracy_decimals: int + state_class: str + unit_of_measurement: Optional[str] = None + icon: Optional[str] = None + device_class: Optional[str] = None + disabled_by_default: bool = False + + +SENSORS: dict[str, SensorSchema] = { + "rel_mod_level": SensorSchema( + description="Relative modulation level", + unit_of_measurement=UNIT_PERCENT, + accuracy_decimals=2, + icon="mdi:percent", + state_class=STATE_CLASS_MEASUREMENT, + message="MODULATION_LEVEL", + keep_updated=True, + message_data="f88", + ), + "ch_pressure": SensorSchema( + description="Water pressure in CH circuit", + unit_of_measurement="bar", + accuracy_decimals=2, + device_class=DEVICE_CLASS_PRESSURE, + state_class=STATE_CLASS_MEASUREMENT, + message="CH_WATER_PRESSURE", + keep_updated=True, + message_data="f88", + ), + "dhw_flow_rate": SensorSchema( + description="Water flow rate in DHW circuit", + unit_of_measurement="l/min", + accuracy_decimals=2, + icon="mdi:waves-arrow-right", + state_class=STATE_CLASS_MEASUREMENT, + message="DHW_FLOW_RATE", + keep_updated=True, + message_data="f88", + ), + "t_boiler": SensorSchema( + description="Boiler water temperature", + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=2, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + message="FEED_TEMP", + keep_updated=True, + message_data="f88", + ), + "t_dhw": SensorSchema( + description="DHW temperature", + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=2, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + message="DHW_TEMP", + keep_updated=True, + message_data="f88", + ), + "t_outside": SensorSchema( + description="Outside temperature", + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=2, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + message="OUTSIDE_TEMP", + keep_updated=True, + message_data="f88", + ), + "t_ret": SensorSchema( + description="Return water temperature", + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=2, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + message="RETURN_WATER_TEMP", + keep_updated=True, + message_data="f88", + ), + "t_storage": SensorSchema( + description="Solar storage temperature", + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=2, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + message="SOLAR_STORE_TEMP", + keep_updated=True, + message_data="f88", + ), + "t_collector": SensorSchema( + description="Solar collector temperature", + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=0, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + message="SOLAR_COLLECT_TEMP", + keep_updated=True, + message_data="s16", + ), + "t_flow_ch2": SensorSchema( + description="Flow water temperature CH2 circuit", + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=2, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + message="FEED_TEMP_CH2", + keep_updated=True, + message_data="f88", + ), + "t_dhw2": SensorSchema( + description="Domestic hot water temperature 2", + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=2, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + message="DHW2_TEMP", + keep_updated=True, + message_data="f88", + ), + "t_exhaust": SensorSchema( + description="Boiler exhaust temperature", + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=0, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + message="EXHAUST_TEMP", + keep_updated=True, + message_data="s16", + ), + "fan_speed": SensorSchema( + description="Boiler fan speed", + unit_of_measurement=UNIT_REVOLUTIONS_PER_MINUTE, + accuracy_decimals=0, + device_class=DEVICE_CLASS_EMPTY, + state_class=STATE_CLASS_MEASUREMENT, + message="FAN_SPEED", + keep_updated=True, + message_data="u16", + ), + "flame_current": SensorSchema( + description="Boiler flame current", + unit_of_measurement=UNIT_MICROAMP, + accuracy_decimals=0, + device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, + message="FLAME_CURRENT", + keep_updated=True, + message_data="f88", + ), + "burner_starts": SensorSchema( + description="Number of starts burner", + accuracy_decimals=0, + icon="mdi:gas-burner", + state_class=STATE_CLASS_TOTAL_INCREASING, + message="BURNER_STARTS", + keep_updated=True, + message_data="u16", + ), + "ch_pump_starts": SensorSchema( + description="Number of starts CH pump", + accuracy_decimals=0, + icon="mdi:pump", + state_class=STATE_CLASS_TOTAL_INCREASING, + message="CH_PUMP_STARTS", + keep_updated=True, + message_data="u16", + ), + "dhw_pump_valve_starts": SensorSchema( + description="Number of starts DHW pump/valve", + accuracy_decimals=0, + icon="mdi:water-pump", + state_class=STATE_CLASS_TOTAL_INCREASING, + message="DHW_PUMP_STARTS", + keep_updated=True, + message_data="u16", + ), + "dhw_burner_starts": SensorSchema( + description="Number of starts burner during DHW mode", + accuracy_decimals=0, + icon="mdi:gas-burner", + state_class=STATE_CLASS_TOTAL_INCREASING, + message="DHW_BURNER_STARTS", + keep_updated=True, + message_data="u16", + ), + "burner_operation_hours": SensorSchema( + description="Number of hours that burner is in operation", + accuracy_decimals=0, + icon="mdi:clock-outline", + state_class=STATE_CLASS_TOTAL_INCREASING, + message="BURNER_HOURS", + keep_updated=True, + message_data="u16", + ), + "ch_pump_operation_hours": SensorSchema( + description="Number of hours that CH pump has been running", + accuracy_decimals=0, + icon="mdi:clock-outline", + state_class=STATE_CLASS_TOTAL_INCREASING, + message="CH_PUMP_HOURS", + keep_updated=True, + message_data="u16", + ), + "dhw_pump_valve_operation_hours": SensorSchema( + description="Number of hours that DHW pump has been running or DHW valve has been opened", + accuracy_decimals=0, + icon="mdi:clock-outline", + state_class=STATE_CLASS_TOTAL_INCREASING, + message="DHW_PUMP_HOURS", + keep_updated=True, + message_data="u16", + ), + "dhw_burner_operation_hours": SensorSchema( + description="Number of hours that burner is in operation during DHW mode", + accuracy_decimals=0, + icon="mdi:clock-outline", + state_class=STATE_CLASS_TOTAL_INCREASING, + message="DHW_BURNER_HOURS", + keep_updated=True, + message_data="u16", + ), + "t_dhw_set_ub": SensorSchema( + description="Upper bound for adjustment of DHW setpoint", + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=0, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + message="DHW_BOUNDS", + keep_updated=False, + message_data="s8_hb", + ), + "t_dhw_set_lb": SensorSchema( + description="Lower bound for adjustment of DHW setpoint", + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=0, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + message="DHW_BOUNDS", + keep_updated=False, + message_data="s8_lb", + ), + "max_t_set_ub": SensorSchema( + description="Upper bound for adjustment of max CH setpoint", + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=0, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + message="CH_BOUNDS", + keep_updated=False, + message_data="s8_hb", + ), + "max_t_set_lb": SensorSchema( + description="Lower bound for adjustment of max CH setpoint", + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=0, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + message="CH_BOUNDS", + keep_updated=False, + message_data="s8_lb", + ), + "t_dhw_set": SensorSchema( + description="Domestic hot water temperature setpoint", + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=2, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + message="DHW_SETPOINT", + keep_updated=True, + message_data="f88", + ), + "max_t_set": SensorSchema( + description="Maximum allowable CH water setpoint", + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=2, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + message="MAX_CH_SETPOINT", + keep_updated=True, + message_data="f88", + ), + "oem_fault_code": SensorSchema( + description="OEM fault code", + unit_of_measurement=UNIT_EMPTY, + accuracy_decimals=0, + state_class=STATE_CLASS_NONE, + message="FAULT_FLAGS", + keep_updated=True, + message_data="u8_lb", + ), + "oem_diagnostic_code": SensorSchema( + description="OEM diagnostic code", + unit_of_measurement=UNIT_EMPTY, + accuracy_decimals=0, + state_class=STATE_CLASS_NONE, + message="OEM_DIAGNOSTIC", + keep_updated=True, + message_data="u16", + ), + "max_capacity": SensorSchema( + description="Maximum boiler capacity (KW)", + unit_of_measurement=UNIT_KILOWATT, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + disabled_by_default=True, + message="MAX_BOILER_CAPACITY", + keep_updated=False, + message_data="u8_hb", + ), + "min_mod_level": SensorSchema( + description="Minimum modulation level", + unit_of_measurement=UNIT_PERCENT, + accuracy_decimals=0, + icon="mdi:percent", + disabled_by_default=True, + state_class=STATE_CLASS_MEASUREMENT, + message="MAX_BOILER_CAPACITY", + keep_updated=False, + message_data="u8_lb", + ), + "opentherm_version_device": SensorSchema( + description="Version of OpenTherm implemented by device", + unit_of_measurement=UNIT_EMPTY, + accuracy_decimals=0, + state_class=STATE_CLASS_NONE, + disabled_by_default=True, + message="OT_VERSION_DEVICE", + keep_updated=False, + message_data="f88", + ), + "device_type": SensorSchema( + description="Device product type", + unit_of_measurement=UNIT_EMPTY, + accuracy_decimals=0, + state_class=STATE_CLASS_NONE, + disabled_by_default=True, + message="VERSION_DEVICE", + keep_updated=False, + message_data="u8_hb", + ), + "device_version": SensorSchema( + description="Device product version", + unit_of_measurement=UNIT_EMPTY, + accuracy_decimals=0, + state_class=STATE_CLASS_NONE, + disabled_by_default=True, + message="VERSION_DEVICE", + keep_updated=False, + message_data="u8_lb", + ), + "device_id": SensorSchema( + description="Device ID code", + unit_of_measurement=UNIT_EMPTY, + accuracy_decimals=0, + state_class=STATE_CLASS_NONE, + disabled_by_default=True, + message="DEVICE_CONFIG", + keep_updated=False, + message_data="u8_lb", + ), + "otc_hc_ratio_ub": SensorSchema( + description="OTC heat curve ratio upper bound", + unit_of_measurement=UNIT_EMPTY, + accuracy_decimals=0, + state_class=STATE_CLASS_NONE, + disabled_by_default=True, + message="OTC_CURVE_BOUNDS", + keep_updated=False, + message_data="u8_hb", + ), + "otc_hc_ratio_lb": SensorSchema( + description="OTC heat curve ratio lower bound", + unit_of_measurement=UNIT_EMPTY, + accuracy_decimals=0, + state_class=STATE_CLASS_NONE, + disabled_by_default=True, + message="OTC_CURVE_BOUNDS", + keep_updated=False, + message_data="u8_lb", + ), +} diff --git a/esphome/components/opentherm/sensor/__init__.py b/esphome/components/opentherm/sensor/__init__.py new file mode 100644 index 0000000000..20224e0eda --- /dev/null +++ b/esphome/components/opentherm/sensor/__init__.py @@ -0,0 +1,35 @@ +from typing import Any + +import esphome.config_validation as cv +from esphome.components import sensor +from .. import const, schema, validate, generate + +DEPENDENCIES = [const.OPENTHERM] +COMPONENT_TYPE = const.SENSOR + + +def get_entity_validation_schema(entity: schema.SensorSchema) -> cv.Schema: + return sensor.sensor_schema( + unit_of_measurement=entity.unit_of_measurement + or sensor._UNDEF, # pylint: disable=protected-access + accuracy_decimals=entity.accuracy_decimals, + device_class=entity.device_class + or sensor._UNDEF, # pylint: disable=protected-access + icon=entity.icon or sensor._UNDEF, # pylint: disable=protected-access + state_class=entity.state_class, + ) + + +CONFIG_SCHEMA = validate.create_component_schema( + schema.SENSORS, get_entity_validation_schema +) + + +async def to_code(config: dict[str, Any]) -> None: + await generate.component_to_code( + COMPONENT_TYPE, + schema.SENSORS, + sensor.Sensor, + generate.create_only_conf(sensor.new_sensor), + config, + ) diff --git a/esphome/components/opentherm/validate.py b/esphome/components/opentherm/validate.py new file mode 100644 index 0000000000..d4507672a5 --- /dev/null +++ b/esphome/components/opentherm/validate.py @@ -0,0 +1,31 @@ +from typing import Callable + +from voluptuous import Schema + +import esphome.config_validation as cv + +from . import const, schema, generate +from .schema import TSchema + + +def create_entities_schema( + entities: dict[str, schema.EntitySchema], + get_entity_validation_schema: Callable[[TSchema], cv.Schema], +) -> Schema: + entity_schema = {} + for key, entity in entities.items(): + entity_schema[cv.Optional(key)] = get_entity_validation_schema(entity) + return cv.Schema(entity_schema) + + +def create_component_schema( + entities: dict[str, schema.EntitySchema], + get_entity_validation_schema: Callable[[TSchema], cv.Schema], +) -> Schema: + return ( + cv.Schema( + {cv.GenerateID(const.CONF_OPENTHERM_ID): cv.use_id(generate.OpenthermHub)} + ) + .extend(create_entities_schema(entities, get_entity_validation_schema)) + .extend(cv.COMPONENT_SCHEMA) + ) diff --git a/esphome/components/prometheus/prometheus_handler.cpp b/esphome/components/prometheus/prometheus_handler.cpp index 3e9cf81e6e..63b3fdf53f 100644 --- a/esphome/components/prometheus/prometheus_handler.cpp +++ b/esphome/components/prometheus/prometheus_handler.cpp @@ -50,6 +50,12 @@ void PrometheusHandler::handleRequest(AsyncWebServerRequest *req) { this->lock_row_(stream, obj); #endif +#ifdef USE_TEXT_SENSOR + this->text_sensor_type_(stream); + for (auto *obj : App.get_text_sensors()) + this->text_sensor_row_(stream, obj); +#endif + req->send(stream); } @@ -349,6 +355,43 @@ void PrometheusHandler::lock_row_(AsyncResponseStream *stream, lock::Lock *obj) } #endif +// Type-specific implementation +#ifdef USE_TEXT_SENSOR +void PrometheusHandler::text_sensor_type_(AsyncResponseStream *stream) { + stream->print(F("#TYPE esphome_text_sensor_value gauge\n")); + stream->print(F("#TYPE esphome_text_sensor_failed gauge\n")); +} +void PrometheusHandler::text_sensor_row_(AsyncResponseStream *stream, text_sensor::TextSensor *obj) { + if (obj->is_internal() && !this->include_internal_) + return; + if (obj->has_state()) { + // We have a valid value, output this value + stream->print(F("esphome_text_sensor_failed{id=\"")); + stream->print(relabel_id_(obj).c_str()); + stream->print(F("\",name=\"")); + stream->print(relabel_name_(obj).c_str()); + stream->print(F("\"} 0\n")); + // Data itself + stream->print(F("esphome_text_sensor_value{id=\"")); + stream->print(relabel_id_(obj).c_str()); + stream->print(F("\",name=\"")); + stream->print(relabel_name_(obj).c_str()); + stream->print(F("\",value=\"")); + stream->print(obj->state.c_str()); + stream->print(F("\"} ")); + stream->print(F("1.0")); + stream->print(F("\n")); + } else { + // Invalid state + stream->print(F("esphome_text_sensor_failed{id=\"")); + stream->print(relabel_id_(obj).c_str()); + stream->print(F("\",name=\"")); + stream->print(relabel_name_(obj).c_str()); + stream->print(F("\"} 1\n")); + } +} +#endif + } // namespace prometheus } // namespace esphome #endif diff --git a/esphome/components/prometheus/prometheus_handler.h b/esphome/components/prometheus/prometheus_handler.h index f5e49a1419..512e1bee4f 100644 --- a/esphome/components/prometheus/prometheus_handler.h +++ b/esphome/components/prometheus/prometheus_handler.h @@ -110,6 +110,13 @@ class PrometheusHandler : public AsyncWebHandler, public Component { void lock_row_(AsyncResponseStream *stream, lock::Lock *obj); #endif +#ifdef USE_TEXT_SENSOR + /// Return the type for prometheus + void text_sensor_type_(AsyncResponseStream *stream); + /// Return the lock Values state as prometheus data point + void text_sensor_row_(AsyncResponseStream *stream, text_sensor::TextSensor *obj); +#endif + web_server_base::WebServerBase *base_; bool include_internal_{false}; std::map relabel_map_id_; diff --git a/esphome/components/pulse_counter/pulse_counter_sensor.cpp b/esphome/components/pulse_counter/pulse_counter_sensor.cpp index 281a61a66a..bd3e4fcbef 100644 --- a/esphome/components/pulse_counter/pulse_counter_sensor.cpp +++ b/esphome/components/pulse_counter/pulse_counter_sensor.cpp @@ -53,12 +53,19 @@ pulse_counter_t BasicPulseCounterStorage::read_raw_value() { #ifdef HAS_PCNT bool HwPulseCounterStorage::pulse_counter_setup(InternalGPIOPin *pin) { static pcnt_unit_t next_pcnt_unit = PCNT_UNIT_0; + static pcnt_channel_t next_pcnt_channel = PCNT_CHANNEL_0; this->pin = pin; this->pin->setup(); this->pcnt_unit = next_pcnt_unit; + this->pcnt_channel = next_pcnt_channel; next_pcnt_unit = pcnt_unit_t(int(next_pcnt_unit) + 1); + if (int(next_pcnt_unit) >= PCNT_UNIT_0 + PCNT_UNIT_MAX) { + next_pcnt_unit = PCNT_UNIT_0; + next_pcnt_channel = pcnt_channel_t(int(next_pcnt_channel) + 1); + } ESP_LOGCONFIG(TAG, " PCNT Unit Number: %u", this->pcnt_unit); + ESP_LOGCONFIG(TAG, " PCNT Channel Number: %u", this->pcnt_channel); pcnt_count_mode_t rising = PCNT_COUNT_DIS, falling = PCNT_COUNT_DIS; switch (this->rising_edge_mode) { @@ -94,7 +101,7 @@ bool HwPulseCounterStorage::pulse_counter_setup(InternalGPIOPin *pin) { .counter_h_lim = 0, .counter_l_lim = 0, .unit = this->pcnt_unit, - .channel = PCNT_CHANNEL_0, + .channel = this->pcnt_channel, }; esp_err_t error = pcnt_unit_config(&pcnt_config); if (error != ESP_OK) { diff --git a/esphome/components/pulse_counter/pulse_counter_sensor.h b/esphome/components/pulse_counter/pulse_counter_sensor.h index ef9f73f95c..fc3d8711d1 100644 --- a/esphome/components/pulse_counter/pulse_counter_sensor.h +++ b/esphome/components/pulse_counter/pulse_counter_sensor.h @@ -55,6 +55,7 @@ struct HwPulseCounterStorage : public PulseCounterStorageBase { pulse_counter_t read_raw_value() override; pcnt_unit_t pcnt_unit; + pcnt_channel_t pcnt_channel; }; #endif diff --git a/esphome/components/qspi_amoled/display.py b/esphome/components/qspi_amoled/display.py index 77d1e3d095..00773b516a 100644 --- a/esphome/components/qspi_amoled/display.py +++ b/esphome/components/qspi_amoled/display.py @@ -1,143 +1,3 @@ -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 - - -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( - { - 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): 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, - } - ), - ), - 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_)) +CONFIG_SCHEMA = cv.invalid("The qspi_amoled component has been renamed to qspi_dbi") diff --git a/esphome/components/qspi_amoled/__init__.py b/esphome/components/qspi_dbi/__init__.py similarity index 100% rename from esphome/components/qspi_amoled/__init__.py rename to esphome/components/qspi_dbi/__init__.py diff --git a/esphome/components/qspi_dbi/display.py b/esphome/components/qspi_dbi/display.py new file mode 100644 index 0000000000..71ae31f182 --- /dev/null +++ b/esphome/components/qspi_dbi/display.py @@ -0,0 +1,185 @@ +from esphome import pins +import esphome.codegen as cg +from esphome.components import display, spi +import esphome.config_validation as cv +from esphome.const import ( + CONF_BRIGHTNESS, + CONF_COLOR_ORDER, + CONF_DIMENSIONS, + CONF_ENABLE_PIN, + CONF_HEIGHT, + CONF_ID, + CONF_INIT_SEQUENCE, + CONF_INVERT_COLORS, + CONF_LAMBDA, + CONF_MIRROR_X, + CONF_MIRROR_Y, + CONF_MODEL, + CONF_OFFSET_HEIGHT, + CONF_OFFSET_WIDTH, + CONF_RESET_PIN, + CONF_SWAP_XY, + CONF_TRANSFORM, + CONF_WIDTH, +) +from esphome.core import TimePeriod + +from .models import DriverChip + +DEPENDENCIES = ["spi"] + +qspi_dbi_ns = cg.esphome_ns.namespace("qspi_dbi") +QSPI_DBI = qspi_dbi_ns.class_( + "QspiDbi", display.Display, display.DisplayBuffer, cg.Component, spi.SPIDevice +) +ColorOrder = display.display_ns.enum("ColorMode") +Model = qspi_dbi_ns.enum("Model") + +COLOR_ORDERS = { + "RGB": ColorOrder.COLOR_ORDER_RGB, + "BGR": ColorOrder.COLOR_ORDER_BGR, +} +DATA_PIN_SCHEMA = pins.internal_gpio_output_pin_schema + +CONF_DRAW_FROM_ORIGIN = "draw_from_origin" +DELAY_FLAG = 0xFF + + +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 + + +def map_sequence(value): + """ + 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, DELAY_FLAG] + value = cv.Length(min=1, max=254)(value) + params = value[1:] + return [value[0], len(params)] + list(params) + + +def _validate(config): + chip = DriverChip.chips[config[CONF_MODEL]] + if not chip.initsequence: + if CONF_INIT_SEQUENCE not in config: + raise cv.Invalid(f"{chip.name} model requires init_sequence") + return config + + +CONFIG_SCHEMA = cv.All( + display.FULL_DISPLAY_SCHEMA.extend( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(QSPI_DBI), + cv.Required(CONF_MODEL): cv.one_of( + *DriverChip.chips.keys(), upper=True + ), + cv.Optional(CONF_INIT_SEQUENCE): cv.ensure_list(map_sequence), + cv.Required(CONF_DIMENSIONS): cv.Any( + cv.dimensions, + cv.Schema( + { + 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, + } + ), + ), + 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 + ), + cv.Optional(CONF_DRAW_FROM_ORIGIN, default=False): cv.boolean, + } + ).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) + + chip = DriverChip.chips[config[CONF_MODEL]] + if chip.initsequence: + cg.add(var.add_init_sequence(chip.initsequence)) + if init_sequences := config.get(CONF_INIT_SEQUENCE): + sequence = [] + for seq in init_sequences: + sequence.extend(seq) + cg.add(var.add_init_sequence(sequence)) + + 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])) + cg.add(var.set_draw_from_origin(config[CONF_DRAW_FROM_ORIGIN])) + 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_dbi/models.py b/esphome/components/qspi_dbi/models.py new file mode 100644 index 0000000000..071ea72d73 --- /dev/null +++ b/esphome/components/qspi_dbi/models.py @@ -0,0 +1,64 @@ +# Commands +SW_RESET_CMD = 0x01 +SLEEP_OUT = 0x11 +INVERT_OFF = 0x20 +INVERT_ON = 0x21 +ALL_ON = 0x23 +WRAM = 0x24 +MIPI = 0x26 +DISPLAY_OFF = 0x28 +DISPLAY_ON = 0x29 +RASET = 0x2B +CASET = 0x2A +WDATA = 0x2C +TEON = 0x35 +MADCTL_CMD = 0x36 +PIXFMT = 0x3A +BRIGHTNESS = 0x51 +SWIRE1 = 0x5A +SWIRE2 = 0x5B +PAGESEL = 0xFE + + +class DriverChip: + chips = {} + + def __init__(self, name: str): + name = name.upper() + self.name = name + self.chips[name] = self + self.initsequence = [] + + def cmd(self, c, *args): + """ + Add a command sequence to the init sequence + :param c: The command (8 bit) + :param args: zero or more arguments (8 bit values) + """ + self.initsequence.extend([c, len(args)] + list(args)) + + def delay(self, ms): + self.initsequence.extend([ms, 0xFF]) + + +chip = DriverChip("RM67162") +chip.cmd(PIXFMT, 0x55) +chip.cmd(BRIGHTNESS, 0) + +chip = DriverChip("RM690B0") +chip.cmd(PAGESEL, 0x20) +chip.cmd(MIPI, 0x0A) +chip.cmd(WRAM, 0x80) +chip.cmd(SWIRE1, 0x51) +chip.cmd(SWIRE2, 0x2E) +chip.cmd(PAGESEL, 0x00) +chip.cmd(0xC2, 0x00) +chip.delay(10) +chip.cmd(TEON, 0x00) + +chip = DriverChip("AXS15231") +chip.cmd(0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xA5) +chip.cmd(0xC1, 0x33) +chip.cmd(0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) + +DriverChip("Custom") diff --git a/esphome/components/qspi_amoled/qspi_amoled.cpp b/esphome/components/qspi_dbi/qspi_dbi.cpp similarity index 51% rename from esphome/components/qspi_amoled/qspi_amoled.cpp rename to esphome/components/qspi_dbi/qspi_dbi.cpp index b1f651025a..a649a25ea6 100644 --- a/esphome/components/qspi_amoled/qspi_amoled.cpp +++ b/esphome/components/qspi_dbi/qspi_dbi.cpp @@ -1,12 +1,12 @@ #ifdef USE_ESP_IDF -#include "qspi_amoled.h" +#include "qspi_dbi.h" #include "esphome/core/log.h" namespace esphome { -namespace qspi_amoled { +namespace qspi_dbi { -void QspiAmoLed::setup() { - esph_log_config(TAG, "Setting up QSPI_AMOLED"); +void QspiDbi::setup() { + ESP_LOGCONFIG(TAG, "Setting up QSPI_DBI"); this->spi_setup(); if (this->enable_pin_ != nullptr) { this->enable_pin_->setup(); @@ -22,13 +22,17 @@ void QspiAmoLed::setup() { } this->set_timeout(120, [this] { this->write_command_(SLEEP_OUT); }); this->set_timeout(240, [this] { this->write_init_sequence_(); }); + if (this->draw_from_origin_) + check_buffer_(); } -void QspiAmoLed::update() { +void QspiDbi::update() { if (!this->setup_complete_) { return; } this->do_update_(); + if (this->buffer_ == nullptr || this->x_low_ > this->x_high_ || this->y_low_ > this->y_high_) + return; // Start addresses and widths/heights must be divisible by 2 (CASET/RASET restriction in datasheet) if (this->x_low_ % 2 == 1) { this->x_low_--; @@ -42,10 +46,15 @@ void QspiAmoLed::update() { if (this->y_high_ % 2 == 0) { this->y_high_++; } + if (this->draw_from_origin_) { + this->x_low_ = 0; + this->y_low_ = 0; + this->x_high_ = this->width_ - 1; + } 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_); + this->write_to_display_(this->x_low_, this->y_low_, w, h, this->buffer_, this->x_low_, this->y_low_, + this->width_ - w - this->x_low_); // invalidate watermarks this->x_low_ = this->width_; this->y_low_ = this->height_; @@ -53,21 +62,19 @@ void QspiAmoLed::update() { this->y_high_ = 0; } -void QspiAmoLed::draw_absolute_pixel_internal(int x, int y, Color color) { +void QspiDbi::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; + check_buffer_(); 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); + uint16_t new_color = display::ColorUtil::color_to_565(color, display::ColorOrder::COLOR_ORDER_RGB); + if (this->buffer_[pos] != static_cast(new_color >> 8)) { + this->buffer_[pos] = static_cast(new_color >> 8); updated = true; } pos = pos + 1; @@ -90,7 +97,7 @@ void QspiAmoLed::draw_absolute_pixel_internal(int x, int y, Color color) { } } -void QspiAmoLed::reset_params_(bool ready) { +void QspiDbi::reset_params_(bool ready) { if (!ready && !this->is_ready()) return; this->write_command_(this->invert_colors_ ? INVERT_ON : INVERT_OFF); @@ -102,55 +109,64 @@ void QspiAmoLed::reset_params_(bool ready) { mad |= MADCTL_MX; if (this->mirror_y_) mad |= MADCTL_MY; - this->write_command_(MADCTL_CMD, &mad, 1); - this->write_command_(BRIGHTNESS, &this->brightness_, 1); + this->write_command_(MADCTL_CMD, mad); + this->write_command_(BRIGHTNESS, this->brightness_); + this->write_command_(NORON); + this->write_command_(DISPLAY_ON); } -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); +void QspiDbi::write_init_sequence_() { + for (const auto &seq : this->init_sequences_) { + this->write_sequence_(seq); } - 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"); + ESP_LOGCONFIG(TAG, "QSPI_DBI setup complete"); } -void QspiAmoLed::set_addr_window_(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { +void QspiDbi::set_addr_window_(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { + ESP_LOGVV(TAG, "Set addr %d/%d, %d/%d", x1, y1, x2, 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); + put16_be(buf, x1); + put16_be(buf + 2, x2); + this->write_command_(CASET, 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) { +void QspiDbi::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); + return Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, x_pad); + } else if (this->draw_from_origin_) { + auto stride = x_offset + w + x_pad; + for (int y = 0; y != h; y++) { + memcpy(this->buffer_ + ((y + y_start) * this->width_ + x_start) * 2, + ptr + ((y + y_offset) * stride + x_offset) * 2, w * 2); + } + ptr = this->buffer_; + w = this->width_; + h += y_start; + x_start = 0; + y_start = 0; + x_offset = 0; + y_offset = 0; } + this->write_to_display_(x_start, y_start, w, h, ptr, x_offset, y_offset, x_pad); +} + +void QspiDbi::write_to_display_(int x_start, int y_start, int w, int h, const uint8_t *ptr, int x_offset, int y_offset, + int 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. @@ -158,17 +174,50 @@ void QspiAmoLed::draw_pixels_at(int x_start, int y_start, int w, int h, const ui // 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; + uint16_t cmd = 0x2C00; 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->write_cmd_addr_data(8, 0x32, 24, cmd, ptr + ((y + y_offset) * stride + x_offset) * 2, w * 2, 4); + cmd = 0x3C00; } } this->disable(); } +void QspiDbi::write_command_(uint8_t cmd, const uint8_t *bytes, size_t len) { + ESP_LOGV(TAG, "Command %02X, length %d, bytes %s", cmd, len, format_hex_pretty(bytes, len).c_str()); + this->enable(); + this->write_cmd_addr_data(8, 0x02, 24, cmd << 8, bytes, len); + this->disable(); +} -void QspiAmoLed::dump_config() { - ESP_LOGCONFIG("", "QSPI AMOLED"); +void QspiDbi::write_sequence_(const std::vector &vec) { + size_t index = 0; + while (index != vec.size()) { + if (vec.size() - index < 2) { + ESP_LOGE(TAG, "Malformed init sequence"); + return; + } + uint8_t cmd = vec[index++]; + uint8_t x = vec[index++]; + if (x == DELAY_FLAG) { + ESP_LOGV(TAG, "Delay %dms", cmd); + delay(cmd); + } else { + uint8_t num_args = x & 0x7F; + if (vec.size() - index < num_args) { + ESP_LOGE(TAG, "Malformed init sequence"); + return; + } + const auto *ptr = vec.data() + index; + this->write_command_(cmd, ptr, num_args); + index += num_args; + } + } +} + +void QspiDbi::dump_config() { + ESP_LOGCONFIG("", "QSPI_DBI Display"); + ESP_LOGCONFIG("", "Model: %s", this->model_); ESP_LOGCONFIG(TAG, " Height: %u", this->height_); ESP_LOGCONFIG(TAG, " Width: %u", this->width_); LOG_PIN(" CS Pin: ", this->cs_); @@ -176,6 +225,6 @@ void QspiAmoLed::dump_config() { ESP_LOGCONFIG(TAG, " SPI Data rate: %dMHz", (unsigned) (this->data_rate_ / 1000000)); } -} // namespace qspi_amoled +} // namespace qspi_dbi } // namespace esphome #endif diff --git a/esphome/components/qspi_amoled/qspi_amoled.h b/esphome/components/qspi_dbi/qspi_dbi.h similarity index 80% rename from esphome/components/qspi_amoled/qspi_amoled.h rename to esphome/components/qspi_dbi/qspi_dbi.h index c766b4e685..ebb65a8a05 100644 --- a/esphome/components/qspi_amoled/qspi_amoled.h +++ b/esphome/components/qspi_dbi/qspi_dbi.h @@ -14,11 +14,12 @@ #include "esp_lcd_panel_rgb.h" namespace esphome { -namespace qspi_amoled { +namespace qspi_dbi { -constexpr static const char *const TAG = "display.qspi_amoled"; +constexpr static const char *const TAG = "display.qspi_dbi"; static const uint8_t SW_RESET_CMD = 0x01; static const uint8_t SLEEP_OUT = 0x11; +static const uint8_t NORON = 0x13; static const uint8_t INVERT_OFF = 0x20; static const uint8_t INVERT_ON = 0x21; static const uint8_t ALL_ON = 0x23; @@ -42,6 +43,7 @@ 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 +static const uint8_t DELAY_FLAG = 0xFF; // 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; @@ -49,15 +51,16 @@ static inline void put16_be(uint8_t *buf, uint16_t value) { } enum Model { + CUSTOM, RM690B0, RM67162, }; -class QspiAmoLed : public display::DisplayBuffer, - public spi::SPIDevice { +class QspiDbi : public display::DisplayBuffer, + public spi::SPIDevice { public: - void set_model(Model model) { this->model_ = model; } + void set_model(const char *model) { this->model_ = model; } void update() override; void setup() override; display::ColorOrder get_color_mode() { return this->color_mode_; } @@ -93,17 +96,27 @@ class QspiAmoLed : public display::DisplayBuffer, this->offset_x_ = offset_x; this->offset_y_ = offset_y; } + + void set_draw_from_origin(bool draw_from_origin) { this->draw_from_origin_ = draw_from_origin; } 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_; } + void add_init_sequence(const std::vector &sequence) { this->init_sequences_.push_back(sequence); } protected: + void check_buffer_() { + if (this->buffer_ == nullptr) + this->init_internal_(this->width_ * this->height_ * 2); + } + void write_sequence_(const std::vector &vec); 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; + void write_to_display_(int x_start, int y_start, int w, int h, const uint8_t *ptr, int x_offset, int y_offset, + int x_pad); /** * the RM67162 in quad SPI mode seems to work like this (not in the datasheet, this is deduced from the * sample code.) @@ -122,11 +135,7 @@ class QspiAmoLed : public display::DisplayBuffer, * @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, const uint8_t *bytes, size_t len); 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); } @@ -136,8 +145,8 @@ class QspiAmoLed : public display::DisplayBuffer, GPIOPin *reset_pin_{nullptr}; GPIOPin *enable_pin_{nullptr}; - uint16_t x_low_{0}; - uint16_t y_low_{0}; + uint16_t x_low_{1}; + uint16_t y_low_{1}; uint16_t x_high_{0}; uint16_t y_high_{0}; bool setup_complete_{}; @@ -151,12 +160,14 @@ class QspiAmoLed : public display::DisplayBuffer, bool swap_xy_{}; bool mirror_x_{}; bool mirror_y_{}; + bool draw_from_origin_{false}; uint8_t brightness_{0xD0}; - Model model_{RM690B0}; + const char *model_{"Unknown"}; + std::vector> init_sequences_{}; esp_lcd_panel_handle_t handle_{}; }; -} // namespace qspi_amoled +} // namespace qspi_dbi } // namespace esphome #endif diff --git a/esphome/components/radon_eye_ble/radon_eye_listener.cpp b/esphome/components/radon_eye_ble/radon_eye_listener.cpp index 340322c188..a4c79db753 100644 --- a/esphome/components/radon_eye_ble/radon_eye_listener.cpp +++ b/esphome/components/radon_eye_ble/radon_eye_listener.cpp @@ -1,5 +1,7 @@ #include "radon_eye_listener.h" #include "esphome/core/log.h" +#include +#include #ifdef USE_ESP32 @@ -10,9 +12,14 @@ 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: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(), + // Vector containing the prefixes to search for + std::vector prefixes = {"FR:R", "FR:I", "FR:H"}; + + // Check if the device name starts with any of the prefixes + if (std::any_of(prefixes.begin(), prefixes.end(), + [&](const std::string &prefix) { return device.get_name().rfind(prefix, 0) == 0; })) { + // Device found + ESP_LOGD(TAG, "Found Radon Eye device Name: %s (MAC: %s)", device.get_name().c_str(), device.address_str().c_str()); } } diff --git a/esphome/components/remote_transmitter/__init__.py b/esphome/components/remote_transmitter/__init__.py index d203ff3417..f979939739 100644 --- a/esphome/components/remote_transmitter/__init__.py +++ b/esphome/components/remote_transmitter/__init__.py @@ -1,10 +1,14 @@ +from esphome import automation, pins import esphome.codegen as cg +from esphome.components import esp32_rmt, remote_base import esphome.config_validation as cv -from esphome import pins -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"] + +CONF_ON_TRANSMIT = "on_transmit" +CONF_ON_COMPLETE = "on_complete" + remote_transmitter_ns = cg.esphome_ns.namespace("remote_transmitter") RemoteTransmitterComponent = remote_transmitter_ns.class_( "RemoteTransmitterComponent", remote_base.RemoteTransmitterBase, cg.Component @@ -19,6 +23,8 @@ CONFIG_SCHEMA = cv.Schema( cv.percentage_int, cv.Range(min=1, max=100) ), cv.Optional(CONF_RMT_CHANNEL): esp32_rmt.validate_rmt_channel(tx=True), + cv.Optional(CONF_ON_TRANSMIT): automation.validate_automation(single=True), + cv.Optional(CONF_ON_COMPLETE): automation.validate_automation(single=True), } ).extend(cv.COMPONENT_SCHEMA) @@ -32,3 +38,13 @@ async def to_code(config): await cg.register_component(var, config) cg.add(var.set_carrier_duty_percent(config[CONF_CARRIER_DUTY_PERCENT])) + + if on_transmit_config := config.get(CONF_ON_TRANSMIT): + await automation.build_automation( + var.get_transmit_trigger(), [], on_transmit_config + ) + + if on_complete_config := config.get(CONF_ON_COMPLETE): + await automation.build_automation( + var.get_complete_trigger(), [], on_complete_config + ) diff --git a/esphome/components/remote_transmitter/remote_transmitter.h b/esphome/components/remote_transmitter/remote_transmitter.h index a5896796c0..4abe687d23 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.h +++ b/esphome/components/remote_transmitter/remote_transmitter.h @@ -33,6 +33,9 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, void set_carrier_duty_percent(uint8_t carrier_duty_percent) { this->carrier_duty_percent_ = carrier_duty_percent; } + Trigger<> *get_transmit_trigger() const { return this->transmit_trigger_; }; + Trigger<> *get_complete_trigger() const { return this->complete_trigger_; }; + protected: void send_internal(uint32_t send_times, uint32_t send_wait) override; #if defined(USE_ESP8266) || defined(USE_LIBRETINY) @@ -57,6 +60,9 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, bool inverted_{false}; #endif uint8_t carrier_duty_percent_; + + Trigger<> *transmit_trigger_{new Trigger<>()}; + Trigger<> *complete_trigger_{new Trigger<>()}; }; } // namespace remote_transmitter diff --git a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp index eea35019ff..bce2408723 100644 --- a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp @@ -124,6 +124,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen ESP_LOGE(TAG, "Empty data"); return; } + this->transmit_trigger_->trigger(); for (uint32_t i = 0; i < send_times; i++) { esp_err_t error = rmt_write_items(this->channel_, this->rmt_temp_.data(), this->rmt_temp_.size(), true); if (error != ESP_OK) { @@ -135,6 +136,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen if (i + 1 < send_times) delayMicroseconds(send_wait); } + this->complete_trigger_->trigger(); } } // namespace remote_transmitter diff --git a/esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp b/esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp index 1c0eb94e61..613f00b7f5 100644 --- a/esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp @@ -76,6 +76,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen uint32_t on_time, off_time; this->calculate_on_off_time_(this->temp_.get_carrier_frequency(), &on_time, &off_time); this->target_time_ = 0; + this->transmit_trigger_->trigger(); for (uint32_t i = 0; i < send_times; i++) { for (int32_t item : this->temp_.get_data()) { if (item > 0) { @@ -93,6 +94,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen if (i + 1 < send_times) this->target_time_ += send_wait; } + this->complete_trigger_->trigger(); } } // namespace remote_transmitter diff --git a/esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp b/esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp index 78bb280482..ad9265fb14 100644 --- a/esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp @@ -78,6 +78,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen uint32_t on_time, off_time; this->calculate_on_off_time_(this->temp_.get_carrier_frequency(), &on_time, &off_time); this->target_time_ = 0; + this->transmit_trigger_->trigger(); for (uint32_t i = 0; i < send_times; i++) { InterruptLock lock; for (int32_t item : this->temp_.get_data()) { @@ -96,6 +97,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen if (i + 1 < send_times) this->target_time_ += send_wait; } + this->complete_trigger_->trigger(); } } // namespace remote_transmitter diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index 8f1d26f780..d612631a4c 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -17,7 +17,7 @@ from esphome.const import ( PLATFORM_RP2040, ) from esphome.core import CORE, EsphomeError, coroutine_with_priority -from esphome.helpers import copy_file_if_changed, mkdir_p, write_file +from esphome.helpers import copy_file_if_changed, mkdir_p, write_file, read_file from .const import KEY_BOARD, KEY_PIO_FILES, KEY_RP2040, rp2040_ns @@ -26,7 +26,7 @@ from .gpio import rp2040_pin_to_code # noqa _LOGGER = logging.getLogger(__name__) CODEOWNERS = ["@jesserockz"] -AUTO_LOAD = [] +AUTO_LOAD = ["preferences"] def set_core_data(config): @@ -71,6 +71,14 @@ def _format_framework_arduino_version(ver: cv.Version) -> str: # return f"~1.{ver.major}{ver.minor:02d}{ver.patch:02d}.0" +def _parse_platform_version(value): + value = cv.string(value) + if value.startswith("http"): + return value + + return f"https://github.com/maxgerhardt/platform-raspberrypi.git#{value}" + + # NOTE: Keep this in mind when updating the recommended version: # * The new version needs to be thoroughly validated before changing the # recommended version as otherwise a bunch of devices could be bricked @@ -82,10 +90,9 @@ def _format_framework_arduino_version(ver: cv.Version) -> str: # - https://api.registry.platformio.org/v3/packages/earlephilhower/tool/framework-arduinopico 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, 13, 0) +# The raspberrypi platform version to use for arduino frameworks +# - https://github.com/maxgerhardt/platform-raspberrypi/tags +RECOMMENDED_ARDUINO_PLATFORM_VERSION = "v1.2.0-gcc12" def _arduino_check_versions(value): @@ -111,7 +118,8 @@ def _arduino_check_versions(value): value[CONF_SOURCE] = source or _format_framework_arduino_version(version) value[CONF_PLATFORM_VERSION] = value.get( - CONF_PLATFORM_VERSION, _parse_platform_version(str(ARDUINO_PLATFORM_VERSION)) + CONF_PLATFORM_VERSION, + _parse_platform_version(RECOMMENDED_ARDUINO_PLATFORM_VERSION), ) if version != RECOMMENDED_ARDUINO_FRAMEWORK_VERSION: @@ -122,15 +130,6 @@ def _arduino_check_versions(value): return value -def _parse_platform_version(value): - try: - # if platform version is a valid version constraint, prefix the default package - cv.platformio_version_constraint(value) - return f"platformio/raspberrypi@{value}" - except cv.Invalid: - return value - - ARDUINO_FRAMEWORK_SCHEMA = cv.All( cv.Schema( { @@ -231,11 +230,14 @@ def generate_pio_files() -> bool: # Called by writer.py -def copy_files() -> bool: +def copy_files(): 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() + if generate_pio_files(): + path = CORE.relative_src_path("esphome.h") + content = read_file(path).rstrip("\n") + write_file(path, content + '\n#include "pio_includes.h"\n') 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..ba09171649 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,27 @@ 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)); +} + +int RpiDpiRgb::get_width() { + switch (this->rotation_) { + case display::DISPLAY_ROTATION_90_DEGREES: + case display::DISPLAY_ROTATION_270_DEGREES: + return this->get_height_internal(); + default: + return this->get_width_internal(); + } +} + +int RpiDpiRgb::get_height() { + switch (this->rotation_) { + case display::DISPLAY_ROTATION_90_DEGREES: + case display::DISPLAY_ROTATION_270_DEGREES: + return this->get_width_internal(); + default: + return this->get_height_internal(); + } } 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..7525040cd1 100644 --- a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h +++ b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h @@ -23,6 +23,8 @@ class RpiDpiRgb : public display::Display { public: void update() override { this->do_update_(); } void setup() override; + void loop() override; + float get_setup_priority() const override { return setup_priority::HARDWARE; } 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; @@ -43,8 +45,8 @@ class RpiDpiRgb : public display::Display { this->width_ = width; this->height_ = height; } - int get_width() override { return this->width_; } - int get_height() override { return this->height_; } + int get_width() override; + int get_height() override; 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; } diff --git a/esphome/components/rtttl/rtttl.cpp b/esphome/components/rtttl/rtttl.cpp index 495b5c1c8a..db4cc731e4 100644 --- a/esphome/components/rtttl/rtttl.cpp +++ b/esphome/components/rtttl/rtttl.cpp @@ -26,7 +26,10 @@ inline double deg2rad(double degrees) { return degrees * PI_ON_180; } -void Rtttl::dump_config() { ESP_LOGCONFIG(TAG, "Rtttl"); } +void Rtttl::dump_config() { + ESP_LOGCONFIG(TAG, "Rtttl:"); + ESP_LOGCONFIG(TAG, " Gain: %f", gain_); +} void Rtttl::play(std::string rtttl) { if (this->state_ != State::STATE_STOPPED && this->state_ != State::STATE_STOPPING) { diff --git a/esphome/components/rtttl/rtttl.h b/esphome/components/rtttl/rtttl.h index 3cb6e3f5fb..10c290c5fb 100644 --- a/esphome/components/rtttl/rtttl.h +++ b/esphome/components/rtttl/rtttl.h @@ -39,6 +39,7 @@ class Rtttl : public Component { #ifdef USE_SPEAKER void set_speaker(speaker::Speaker *speaker) { this->speaker_ = speaker; } #endif + float get_gain() { return gain_; } void set_gain(float gain) { if (gain < 0.1f) gain = 0.1f; diff --git a/esphome/components/select/__init__.py b/esphome/components/select/__init__.py index 2bc68d43ec..5a3271fdfd 100644 --- a/esphome/components/select/__init__.py +++ b/esphome/components/select/__init__.py @@ -14,7 +14,7 @@ from esphome.const import ( CONF_OPERATION, CONF_OPTION, CONF_TRIGGER_ID, - CONF_WEB_SERVER_ID, + CONF_WEB_SERVER, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_generator import MockObjClass @@ -104,9 +104,8 @@ 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) + if web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(var, web_server_config) async def register_select(var, config, *, options: list[str]): diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 867cdc1f48..27338b8608 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -36,7 +36,7 @@ from esphome.const import ( CONF_TYPE, CONF_UNIT_OF_MEASUREMENT, CONF_VALUE, - CONF_WEB_SERVER_ID, + CONF_WEB_SERVER, CONF_WINDOW_SIZE, DEVICE_CLASS_APPARENT_POWER, DEVICE_CLASS_AQI, @@ -800,9 +800,8 @@ 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) + if web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(var, web_server_config) async def register_sensor(var, config): diff --git a/esphome/components/sgp4x/sgp4x.cpp b/esphome/components/sgp4x/sgp4x.cpp index 7e474b9371..bf91c90832 100644 --- a/esphome/components/sgp4x/sgp4x.cpp +++ b/esphome/components/sgp4x/sgp4x.cpp @@ -111,7 +111,7 @@ void SGP4xComponent::setup() { number of records reported from being overwhelming. */ ESP_LOGD(TAG, "Component requires sampling of 1Hz, setting up background sampler"); - this->set_interval(1000, [this]() { this->update_gas_indices(); }); + this->set_interval(1000, [this]() { this->take_sample(); }); } void SGP4xComponent::self_test_() { @@ -146,31 +146,15 @@ void SGP4xComponent::self_test_() { }); } -/** - * @brief Combined the measured gasses, temperature, and humidity - * to calculate the VOC Index - * - * @param temperature The measured temperature in degrees C - * @param humidity The measured relative humidity in % rH - * @return int32_t The VOC Index - */ -bool SGP4xComponent::measure_gas_indices_(int32_t &voc, int32_t &nox) { - uint16_t voc_sraw; - uint16_t nox_sraw; - if (!measure_raw_(voc_sraw, nox_sraw)) - return false; - - this->status_clear_warning(); - - voc = voc_algorithm_.process(voc_sraw); - if (nox_sensor_) { - nox = nox_algorithm_.process(nox_sraw); - } - ESP_LOGV(TAG, "VOC = %" PRId32 ", NOx = %" PRId32, voc, nox); +void SGP4xComponent::update_gas_indices_() { + this->voc_index_ = this->voc_algorithm_.process(this->voc_sraw_); + if (this->nox_sensor_ != nullptr) + this->nox_index_ = this->nox_algorithm_.process(this->nox_sraw_); + ESP_LOGV(TAG, "VOC = %" PRId32 ", NOx = %" PRId32, this->voc_index_, this->nox_index_); // Store baselines after defined interval or if the difference between current and stored baseline becomes too // much if (this->store_baseline_ && this->seconds_since_last_store_ > SHORTEST_BASELINE_STORE_INTERVAL) { - voc_algorithm_.get_states(this->voc_state0_, this->voc_state1_); + this->voc_algorithm_.get_states(this->voc_state0_, this->voc_state1_); if (std::abs(this->voc_baselines_storage_.state0 - this->voc_state0_) > MAXIMUM_STORAGE_DIFF || std::abs(this->voc_baselines_storage_.state1 - this->voc_state1_) > MAXIMUM_STORAGE_DIFF) { this->seconds_since_last_store_ = 0; @@ -179,29 +163,27 @@ bool SGP4xComponent::measure_gas_indices_(int32_t &voc, int32_t &nox) { if (this->pref_.save(&this->voc_baselines_storage_)) { ESP_LOGI(TAG, "Stored VOC baseline state0: 0x%04" PRIX32 " ,state1: 0x%04" PRIX32, - this->voc_baselines_storage_.state0, voc_baselines_storage_.state1); + this->voc_baselines_storage_.state0, this->voc_baselines_storage_.state1); } else { ESP_LOGW(TAG, "Could not store VOC baselines"); } } } - return true; + if (this->samples_read_ < this->samples_to_stabilize_) { + this->samples_read_++; + ESP_LOGD(TAG, "Sensor has not collected enough samples yet. (%d/%d) VOC index is: %" PRIu32, this->samples_read_, + this->samples_to_stabilize_, this->voc_index_); + } } -/** - * @brief Return the raw gas measurement - * - * @param temperature The measured temperature in degrees C - * @param humidity The measured relative humidity in % rH - * @return uint16_t The current raw gas measurement - */ -bool SGP4xComponent::measure_raw_(uint16_t &voc_raw, uint16_t &nox_raw) { + +void SGP4xComponent::measure_raw_() { float humidity = NAN; static uint32_t nox_conditioning_start = millis(); if (!this->self_test_complete_) { ESP_LOGD(TAG, "Self-test not yet complete"); - return false; + return; } if (this->humidity_sensor_ != nullptr) { humidity = this->humidity_sensor_->state; @@ -243,61 +225,45 @@ bool SGP4xComponent::measure_raw_(uint16_t &voc_raw, uint16_t &nox_raw) { data[1] = tempticks; if (!this->write_command(command, data, 2)) { - this->status_set_warning(); ESP_LOGD(TAG, "write error (%d)", this->last_error_); - return false; + this->status_set_warning("measurement request failed"); + return; } - delay(measure_time_); - uint16_t raw_data[2]; - raw_data[1] = 0; - if (!this->read_data(raw_data, response_words)) { - this->status_set_warning(); - ESP_LOGD(TAG, "read error (%d)", this->last_error_); - return false; - } - voc_raw = raw_data[0]; - nox_raw = raw_data[1]; // either 0 or the measured NOx ticks - return true; + + this->set_timeout(this->measure_time_, [this, response_words]() { + uint16_t raw_data[2]; + raw_data[1] = 0; + if (!this->read_data(raw_data, response_words)) { + ESP_LOGD(TAG, "read error (%d)", this->last_error_); + this->status_set_warning("measurement read failed"); + this->voc_index_ = this->nox_index_ = UINT16_MAX; + return; + } + this->voc_sraw_ = raw_data[0]; + this->nox_sraw_ = raw_data[1]; // either 0 or the measured NOx ticks + this->status_clear_warning(); + this->update_gas_indices_(); + }); } -void SGP4xComponent::update_gas_indices() { +void SGP4xComponent::take_sample() { if (!this->self_test_complete_) return; - this->seconds_since_last_store_ += 1; - if (!this->measure_gas_indices_(this->voc_index_, this->nox_index_)) { - // Set values to UINT16_MAX to indicate failure - this->voc_index_ = this->nox_index_ = UINT16_MAX; - ESP_LOGE(TAG, "measure gas indices failed"); - return; - } - if (this->samples_read_ < this->samples_to_stabilize_) { - this->samples_read_++; - ESP_LOGD(TAG, "Sensor has not collected enough samples yet. (%d/%d) VOC index is: %" PRIu32, this->samples_read_, - this->samples_to_stabilize_, this->voc_index_); - return; - } + this->measure_raw_(); } void SGP4xComponent::update() { if (this->samples_read_ < this->samples_to_stabilize_) { return; } - if (this->voc_sensor_) { - if (this->voc_index_ != UINT16_MAX) { - this->status_clear_warning(); + if (this->voc_sensor_ != nullptr) { + if (this->voc_index_ != UINT16_MAX) this->voc_sensor_->publish_state(this->voc_index_); - } else { - this->status_set_warning(); - } } - if (this->nox_sensor_) { - if (this->nox_index_ != UINT16_MAX) { - this->status_clear_warning(); + if (this->nox_sensor_ != nullptr) { + if (this->nox_index_ != UINT16_MAX) this->nox_sensor_->publish_state(this->nox_index_); - } else { - this->status_set_warning(); - } } } @@ -329,7 +295,7 @@ void SGP4xComponent::dump_config() { } LOG_UPDATE_INTERVAL(this); - if (this->humidity_sensor_ != nullptr && this->temperature_sensor_ != nullptr) { + if (this->humidity_sensor_ != nullptr || this->temperature_sensor_ != nullptr) { ESP_LOGCONFIG(TAG, " Compensation:"); LOG_SENSOR(" ", "Temperature Source:", this->temperature_sensor_); LOG_SENSOR(" ", "Humidity Source:", this->humidity_sensor_); diff --git a/esphome/components/sgp4x/sgp4x.h b/esphome/components/sgp4x/sgp4x.h index aa5ae4b9d2..959ff12c27 100644 --- a/esphome/components/sgp4x/sgp4x.h +++ b/esphome/components/sgp4x/sgp4x.h @@ -73,7 +73,7 @@ class SGP4xComponent : public PollingComponent, public sensor::Sensor, public se void setup() override; void update() override; - void update_gas_indices(); + void take_sample(); void dump_config() override; float get_setup_priority() const override { return setup_priority::DATA; } void set_store_baseline(bool store_baseline) { store_baseline_ = store_baseline; } @@ -108,8 +108,10 @@ class SGP4xComponent : public PollingComponent, public sensor::Sensor, public se sensor::Sensor *temperature_sensor_{nullptr}; int16_t sensirion_init_sensors_(); - bool measure_gas_indices_(int32_t &voc, int32_t &nox); - bool measure_raw_(uint16_t &voc_raw, uint16_t &nox_raw); + void update_gas_indices_(); + void measure_raw_(); + uint16_t voc_sraw_; + uint16_t nox_sraw_; SgpType sgp_type_{SGP40}; uint64_t serial_number_; diff --git a/esphome/components/shelly_dimmer/shelly_dimmer.cpp b/esphome/components/shelly_dimmer/shelly_dimmer.cpp index 144236bfe1..b415840bdc 100644 --- a/esphome/components/shelly_dimmer/shelly_dimmer.cpp +++ b/esphome/components/shelly_dimmer/shelly_dimmer.cpp @@ -64,46 +64,46 @@ uint16_t shelly_dimmer_checksum(const uint8_t *buf, int len) { return std::accumulate(buf, buf + len, 0); } +bool ShellyDimmer::is_running_configured_version() const { + return this->version_major_ == USE_SHD_FIRMWARE_MAJOR_VERSION && + this->version_minor_ == USE_SHD_FIRMWARE_MINOR_VERSION; +} + +void ShellyDimmer::handle_firmware() { + // Reset the STM32 and check the firmware version. + this->reset_normal_boot_(); + this->send_command_(SHELLY_DIMMER_PROTO_CMD_VERSION, nullptr, 0); + ESP_LOGI(TAG, "STM32 current firmware version: %d.%d, desired version: %d.%d", this->version_major_, + this->version_minor_, USE_SHD_FIRMWARE_MAJOR_VERSION, USE_SHD_FIRMWARE_MINOR_VERSION); + + if (!is_running_configured_version()) { +#ifdef USE_SHD_FIRMWARE_DATA + if (!this->upgrade_firmware_()) { + ESP_LOGW(TAG, "Failed to upgrade firmware"); + this->mark_failed(); + return; + } + + this->reset_normal_boot_(); + this->send_command_(SHELLY_DIMMER_PROTO_CMD_VERSION, nullptr, 0); + if (!is_running_configured_version()) { + ESP_LOGE(TAG, "STM32 firmware upgrade already performed, but version is still incorrect"); + this->mark_failed(); + return; + } +#else + ESP_LOGW(TAG, "Firmware version mismatch, put 'update: true' in the yaml to flash an update."); +#endif + } +} + void ShellyDimmer::setup() { this->pin_nrst_->setup(); this->pin_boot0_->setup(); ESP_LOGI(TAG, "Initializing Shelly Dimmer..."); - // Reset the STM32 and check the firmware version. - for (int i = 0; i < 2; i++) { - this->reset_normal_boot_(); - this->send_command_(SHELLY_DIMMER_PROTO_CMD_VERSION, nullptr, 0); - ESP_LOGI(TAG, "STM32 current firmware version: %d.%d, desired version: %d.%d", this->version_major_, - this->version_minor_, USE_SHD_FIRMWARE_MAJOR_VERSION, USE_SHD_FIRMWARE_MINOR_VERSION); - if (this->version_major_ != USE_SHD_FIRMWARE_MAJOR_VERSION || - this->version_minor_ != USE_SHD_FIRMWARE_MINOR_VERSION) { -#ifdef USE_SHD_FIRMWARE_DATA - // Update firmware if needed. - ESP_LOGW(TAG, "Unsupported STM32 firmware version, flashing"); - if (i > 0) { - // Upgrade was already performed but the reported version is still not right. - ESP_LOGE(TAG, "STM32 firmware upgrade already performed, but version is still incorrect"); - this->mark_failed(); - return; - } - - if (!this->upgrade_firmware_()) { - ESP_LOGW(TAG, "Failed to upgrade firmware"); - this->mark_failed(); - return; - } - - // Firmware upgrade completed, do the checks again. - continue; -#else - ESP_LOGW(TAG, "Firmware version mismatch, put 'update: true' in the yaml to flash an update."); - this->mark_failed(); - return; -#endif - } - break; - } + this->handle_firmware(); this->send_settings_(); // Do an immediate poll to refresh current state. diff --git a/esphome/components/shelly_dimmer/shelly_dimmer.h b/esphome/components/shelly_dimmer/shelly_dimmer.h index 4701f3a32a..fd75caa797 100644 --- a/esphome/components/shelly_dimmer/shelly_dimmer.h +++ b/esphome/components/shelly_dimmer/shelly_dimmer.h @@ -20,6 +20,8 @@ class ShellyDimmer : public PollingComponent, public light::LightOutput, public public: float get_setup_priority() const override { return setup_priority::LATE; } + bool is_running_configured_version() const; + void handle_firmware(); void setup() override; void update() override; void dump_config() override; diff --git a/esphome/components/speaker/__init__.py b/esphome/components/speaker/__init__.py index d28b726d1f..7a668dc2f3 100644 --- a/esphome/components/speaker/__init__.py +++ b/esphome/components/speaker/__init__.py @@ -1,15 +1,18 @@ from esphome import automation from esphome.automation import maybe_simple_id import esphome.codegen as cg +from esphome.components import audio_dac import esphome.config_validation as cv -from esphome.const import CONF_DATA, CONF_ID +from esphome.const import CONF_DATA, CONF_ID, CONF_VOLUME from esphome.core import CORE from esphome.coroutine import coroutine_with_priority -CODEOWNERS = ["@jesserockz"] +CODEOWNERS = ["@jesserockz", "@kahrendt"] IS_PLATFORM_COMPONENT = True +CONF_AUDIO_DAC = "audio_dac" + speaker_ns = cg.esphome_ns.namespace("speaker") Speaker = speaker_ns.class_("Speaker") @@ -23,13 +26,25 @@ StopAction = speaker_ns.class_( FinishAction = speaker_ns.class_( "FinishAction", automation.Action, cg.Parented.template(Speaker) ) +VolumeSetAction = speaker_ns.class_( + "VolumeSetAction", automation.Action, cg.Parented.template(Speaker) +) +MuteOnAction = speaker_ns.class_( + "MuteOnAction", automation.Action, cg.Parented.template(Speaker) +) +MuteOffAction = speaker_ns.class_( + "MuteOffAction", 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): - pass + if audio_dac_config := config.get(CONF_AUDIO_DAC): + aud_dac = await cg.get_variable(audio_dac_config) + cg.add(var.set_audio_dac(aud_dac)) async def register_speaker(var, config): @@ -38,8 +53,11 @@ async def register_speaker(var, config): await setup_speaker_core_(var, config) -SPEAKER_SCHEMA = cv.Schema({}) - +SPEAKER_SCHEMA = cv.Schema( + { + cv.Optional(CONF_AUDIO_DAC): cv.use_id(audio_dac.AudioDac), + } +) SPEAKER_AUTOMATION_SCHEMA = maybe_simple_id({cv.GenerateID(): cv.use_id(Speaker)}) @@ -90,6 +108,34 @@ automation.register_condition( )(speaker_action) +@automation.register_action( + "speaker.volume_set", + VolumeSetAction, + cv.maybe_simple_value( + { + cv.GenerateID(): cv.use_id(Speaker), + cv.Required(CONF_VOLUME): cv.templatable(cv.percentage), + }, + key=CONF_VOLUME, + ), +) +async def speaker_volume_set_action(config, action_id, template_arg, args): + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + volume = await cg.templatable(config[CONF_VOLUME], args, float) + cg.add(var.set_volume(volume)) + return var + + +@automation.register_action( + "speaker.mute_off", MuteOffAction, SPEAKER_AUTOMATION_SCHEMA +) +@automation.register_action("speaker.mute_on", MuteOnAction, SPEAKER_AUTOMATION_SCHEMA) +async def speaker_mute_action_to_code(config, action_id, template_arg, args): + paren = await cg.get_variable(config[CONF_ID]) + return cg.new_Pvariable(action_id, template_arg, paren) + + @coroutine_with_priority(100.0) async def to_code(config): cg.add_global(speaker_ns.using) diff --git a/esphome/components/speaker/automation.h b/esphome/components/speaker/automation.h index 2716fe6100..c083796eea 100644 --- a/esphome/components/speaker/automation.h +++ b/esphome/components/speaker/automation.h @@ -34,6 +34,31 @@ template class PlayAction : public Action, public Parente std::vector data_static_{}; }; +template class VolumeSetAction : public Action, public Parented { + TEMPLATABLE_VALUE(float, volume) + void play(Ts... x) override { this->parent_->set_volume(this->volume_.value(x...)); } +}; + +template class MuteOnAction : public Action { + public: + explicit MuteOnAction(Speaker *speaker) : speaker_(speaker) {} + + void play(Ts... x) override { this->speaker_->set_mute_state(true); } + + protected: + Speaker *speaker_; +}; + +template class MuteOffAction : public Action { + public: + explicit MuteOffAction(Speaker *speaker) : speaker_(speaker) {} + + void play(Ts... x) override { this->speaker_->set_mute_state(false); } + + protected: + Speaker *speaker_; +}; + template class StopAction : public Action, public Parented { public: void play(Ts... x) override { this->parent_->stop(); } diff --git a/esphome/components/speaker/speaker.h b/esphome/components/speaker/speaker.h index 375ccc4e8c..96843e2d5a 100644 --- a/esphome/components/speaker/speaker.h +++ b/esphome/components/speaker/speaker.h @@ -4,6 +4,17 @@ #include #include +#ifdef USE_ESP32 +#include +#endif + +#include "esphome/core/defines.h" + +#include "esphome/components/audio/audio.h" +#ifdef USE_AUDIO_DAC +#include "esphome/components/audio_dac/audio_dac.h" +#endif + namespace esphome { namespace speaker { @@ -16,14 +27,33 @@ enum State : uint8_t { class Speaker { public: +#ifdef USE_ESP32 + /// @brief Plays the provided audio data. + /// If the speaker component doesn't implement this method, it falls back to the play method without this parameter. + /// @param data Audio data in the format specified by ``set_audio_stream_info`` method. + /// @param length The length of the audio data in bytes. + /// @param ticks_to_wait The FreeRTOS ticks to wait before writing as much data as possible to the ring buffer. + /// @return The number of bytes that were actually written to the speaker's internal buffer. + virtual size_t play(const uint8_t *data, size_t length, TickType_t ticks_to_wait) { + return this->play(data, length); + }; +#endif + + /// @brief Plays the provided audio data. + /// If the audio stream is not the default defined in "esphome/core/audio.h" and the speaker component implements it, + /// then this should be called after calling ``set_audio_stream_info``. + /// @param data Audio data in the format specified by ``set_audio_stream_info`` method. + /// @param length The length of the audio data in bytes. + /// @return The number of bytes that were actually written to the speaker's internal buffer. virtual size_t play(const uint8_t *data, size_t length) = 0; + size_t play(const std::vector &data) { return this->play(data.data(), data.size()); } 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. + // When finish() is not implemented on the platform component it should just do a normal stop. virtual void finish() { this->stop(); } virtual bool has_buffered_data() const = 0; @@ -31,8 +61,49 @@ class Speaker { bool is_running() const { return this->state_ == STATE_RUNNING; } bool is_stopped() const { return this->state_ == STATE_STOPPED; } + // Volume control is handled by a configured audio dac component. Individual speaker components can + // override and implement in software if an audio dac isn't available. + virtual void set_volume(float volume) { + this->volume_ = volume; +#ifdef USE_AUDIO_DAC + if (this->audio_dac_ != nullptr) { + this->audio_dac_->set_volume(volume); + } +#endif + }; + float get_volume() { return this->volume_; } + + virtual void set_mute_state(bool mute_state) { + this->mute_state_ = mute_state; +#ifdef USE_AUDIO_DAC + if (this->audio_dac_) { + if (mute_state) { + this->audio_dac_->set_mute_on(); + } else { + this->audio_dac_->set_mute_off(); + } + } +#endif + } + bool get_mute_state() { return this->mute_state_; } + +#ifdef USE_AUDIO_DAC + void set_audio_dac(audio_dac::AudioDac *audio_dac) { this->audio_dac_ = audio_dac; } +#endif + + void set_audio_stream_info(const audio::AudioStreamInfo &audio_stream_info) { + this->audio_stream_info_ = audio_stream_info; + } + protected: State state_{STATE_STOPPED}; + audio::AudioStreamInfo audio_stream_info_; + float volume_{1.0f}; + bool mute_state_{false}; + +#ifdef USE_AUDIO_DAC + audio_dac::AudioDac *audio_dac_{nullptr}; +#endif }; } // namespace speaker diff --git a/esphome/components/st7701s/display.py b/esphome/components/st7701s/display.py index 9310e9d760..e73c2467da 100644 --- a/esphome/components/st7701s/display.py +++ b/esphome/components/st7701s/display.py @@ -18,6 +18,7 @@ from esphome.const import ( CONF_HSYNC_PIN, CONF_ID, CONF_IGNORE_STRAPPING_WARNING, + CONF_INIT_SEQUENCE, CONF_INVERT_COLORS, CONF_LAMBDA, CONF_MIRROR_X, @@ -35,7 +36,6 @@ from esphome.core import TimePeriod from .init_sequences import ST7701S_INITS, cmd -CONF_INIT_SEQUENCE = "init_sequence" CONF_DE_PIN = "de_pin" CONF_PCLK_PIN = "pclk_pin" diff --git a/esphome/components/st7701s/st7701s.cpp b/esphome/components/st7701s/st7701s.cpp index 7f02fe1774..403bff789d 100644 --- a/esphome/components/st7701s/st7701s.cpp +++ b/esphome/components/st7701s/st7701s.cpp @@ -8,8 +8,14 @@ namespace st7701s { void ST7701S::setup() { esph_log_config(TAG, "Setting up ST7701S"); this->spi_setup(); + this->write_init_sequence_(); + 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 +27,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 +39,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 +171,12 @@ 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); - }); + // can't avoid this inline delay due to the need to complete setup before anything else tries to draw. + delay(120); // NOLINT + this->write_command_(SLEEP_OUT); + this->write_command_(DISPLAY_ON); + this->spi_teardown(); // SPI not needed after this + delay(10); } 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; diff --git a/esphome/components/statsd/statsd.cpp b/esphome/components/statsd/statsd.cpp index 68b24908d2..b7fad19332 100644 --- a/esphome/components/statsd/statsd.cpp +++ b/esphome/components/statsd/statsd.cpp @@ -2,6 +2,7 @@ #include "statsd.h" +#ifdef USE_NETWORK namespace esphome { namespace statsd { @@ -154,3 +155,4 @@ void StatsdComponent::send_(std::string *out) { } // namespace statsd } // namespace esphome +#endif diff --git a/esphome/components/statsd/statsd.h b/esphome/components/statsd/statsd.h index ef42579587..34f84cbe00 100644 --- a/esphome/components/statsd/statsd.h +++ b/esphome/components/statsd/statsd.h @@ -3,6 +3,7 @@ #include #include "esphome/core/defines.h" +#ifdef USE_NETWORK #include "esphome/core/component.h" #include "esphome/components/socket/socket.h" #include "esphome/components/network/ip_address.h" @@ -84,3 +85,4 @@ class StatsdComponent : public PollingComponent { } // namespace statsd } // namespace esphome +#endif diff --git a/esphome/components/switch/__init__.py b/esphome/components/switch/__init__.py index fef4f7f007..0f159f69ec 100644 --- a/esphome/components/switch/__init__.py +++ b/esphome/components/switch/__init__.py @@ -14,7 +14,7 @@ from esphome.const import ( CONF_ON_TURN_ON, CONF_RESTORE_MODE, CONF_TRIGGER_ID, - CONF_WEB_SERVER_ID, + CONF_WEB_SERVER, DEVICE_CLASS_EMPTY, DEVICE_CLASS_OUTLET, DEVICE_CLASS_SWITCH, @@ -156,9 +156,8 @@ 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 web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(var, web_server_config) if (device_class := config.get(CONF_DEVICE_CLASS)) is not None: cg.add(var.set_device_class(device_class)) diff --git a/esphome/components/tc74/__init__.py b/esphome/components/tc74/__init__.py new file mode 100644 index 0000000000..c1407c7cad --- /dev/null +++ b/esphome/components/tc74/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@sethgirvan"] diff --git a/esphome/components/tc74/sensor.py b/esphome/components/tc74/sensor.py new file mode 100644 index 0000000000..18fc2d9a42 --- /dev/null +++ b/esphome/components/tc74/sensor.py @@ -0,0 +1,32 @@ +import esphome.codegen as cg +from esphome.components import i2c, sensor +import esphome.config_validation as cv +from esphome.const import ( + DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, +) + +CODEOWNERS = ["@sethgirvan"] +DEPENDENCIES = ["i2c"] + +tc74_ns = cg.esphome_ns.namespace("tc74") +TC74Component = tc74_ns.class_("TC74Component", cg.PollingComponent, i2c.I2CDevice) + +CONFIG_SCHEMA = ( + sensor.sensor_schema( + TC74Component, + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x48)) +) + + +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/esphome/components/tc74/tc74.cpp b/esphome/components/tc74/tc74.cpp new file mode 100644 index 0000000000..2acb71f921 --- /dev/null +++ b/esphome/components/tc74/tc74.cpp @@ -0,0 +1,68 @@ +// Based on the TC74 datasheet https://ww1.microchip.com/downloads/en/DeviceDoc/21462D.pdf + +#include "tc74.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace tc74 { + +static const char *const TAG = "tc74"; + +static const uint8_t TC74_REGISTER_TEMPERATURE = 0x00; +static const uint8_t TC74_REGISTER_CONFIGURATION = 0x01; +static const uint8_t TC74_DATA_READY_MASK = 0x40; + +// It is possible the "Data Ready" bit will not be set if the TC74 has not been powered on for at least 250ms, so it not +// being set does not constitute a failure. +void TC74Component::setup() { + ESP_LOGCONFIG(TAG, "Setting up TC74..."); + uint8_t config_reg; + if (this->read_register(TC74_REGISTER_CONFIGURATION, &config_reg, 1) != i2c::ERROR_OK) { + this->mark_failed(); + return; + } + this->data_ready_ = config_reg & TC74_DATA_READY_MASK; +} + +void TC74Component::update() { this->read_temperature_(); } + +void TC74Component::dump_config() { + LOG_SENSOR("", "TC74", this); + LOG_I2C_DEVICE(this); + if (this->is_failed()) { + ESP_LOGE(TAG, "Connection with TC74 failed!"); + } + LOG_UPDATE_INTERVAL(this); +} + +void TC74Component::read_temperature_() { + if (!this->data_ready_) { + uint8_t config_reg; + if (this->read_register(TC74_REGISTER_CONFIGURATION, &config_reg, 1) != i2c::ERROR_OK) { + this->status_set_warning(); + return; + } + + if (config_reg & TC74_DATA_READY_MASK) { + this->data_ready_ = true; + } else { + ESP_LOGD(TAG, "TC74 not ready"); + return; + } + } + + uint8_t temperature_reg; + if (this->read_register(TC74_REGISTER_TEMPERATURE, &temperature_reg, 1) != i2c::ERROR_OK) { + this->status_set_warning(); + return; + } + + ESP_LOGD(TAG, "Got Temperature=%d °C", temperature_reg); + this->publish_state(temperature_reg); + this->status_clear_warning(); +} + +float TC74Component::get_setup_priority() const { return setup_priority::DATA; } + +} // namespace tc74 +} // namespace esphome diff --git a/esphome/components/tc74/tc74.h b/esphome/components/tc74/tc74.h new file mode 100644 index 0000000000..5d70c05420 --- /dev/null +++ b/esphome/components/tc74/tc74.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 tc74 { + +class TC74Component : public PollingComponent, public i2c::I2CDevice, public sensor::Sensor { + public: + /// Setup the sensor and check connection. + void setup() override; + void dump_config() override; + /// Update the sensor value (temperature). + void update() override; + + float get_setup_priority() const override; + + protected: + /// Internal method to read the temperature from the component after it has been scheduled. + void read_temperature_(); + + bool data_ready_ = false; +}; + +} // namespace tc74 +} // namespace esphome diff --git a/esphome/components/tca9555/__init__.py b/esphome/components/tca9555/__init__.py new file mode 100644 index 0000000000..db0451d4e6 --- /dev/null +++ b/esphome/components/tca9555/__init__.py @@ -0,0 +1,72 @@ +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, +) + +CODEOWNERS = ["@mobrembski"] + +AUTO_LOAD = ["gpio_expander"] +DEPENDENCIES = ["i2c"] +MULTI_CONF = True + +tca9555_ns = cg.esphome_ns.namespace("tca9555") + +TCA9555Component = tca9555_ns.class_("TCA9555Component", cg.Component, i2c.I2CDevice) +TCA9555GPIOPin = tca9555_ns.class_("TCA9555GPIOPin", cg.GPIOPin) + +CONF_TCA9555 = "tca9555" +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.Required(CONF_ID): cv.declare_id(TCA9555Component), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x21)) +) + + +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) + + +def validate_mode(value): + if not (value[CONF_INPUT] or value[CONF_OUTPUT]): + raise cv.Invalid("Mode must be either input or output") + if value[CONF_INPUT] and value[CONF_OUTPUT]: + raise cv.Invalid("Mode must be either input or output") + return value + + +TCA9555_PIN_SCHEMA = pins.gpio_base_schema( + TCA9555GPIOPin, + cv.int_range(min=0, max=15), + modes=[CONF_INPUT, CONF_OUTPUT], + mode_validator=validate_mode, + invertable=True, +).extend( + { + cv.Required(CONF_TCA9555): cv.use_id(TCA9555Component), + } +) + + +@pins.PIN_SCHEMA_REGISTRY.register(CONF_TCA9555, TCA9555_PIN_SCHEMA) +async def tca9555_pin_to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_parented(var, config[CONF_TCA9555]) + + cg.add(var.set_pin(config[CONF_NUMBER])) + 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/tca9555/tca9555.cpp b/esphome/components/tca9555/tca9555.cpp new file mode 100644 index 0000000000..cf0894427f --- /dev/null +++ b/esphome/components/tca9555/tca9555.cpp @@ -0,0 +1,140 @@ +#include "tca9555.h" +#include "esphome/core/log.h" + +static const uint8_t TCA9555_INPUT_PORT_REGISTER_0 = 0x00; +static const uint8_t TCA9555_INPUT_PORT_REGISTER_1 = 0x01; +static const uint8_t TCA9555_OUTPUT_PORT_REGISTER_0 = 0x02; +static const uint8_t TCA9555_OUTPUT_PORT_REGISTER_1 = 0x03; +static const uint8_t TCA9555_POLARITY_REGISTER_0 = 0x04; +static const uint8_t TCA9555_POLARITY_REGISTER_1 = 0x05; +static const uint8_t TCA9555_CONFIGURATION_PORT_0 = 0x06; +static const uint8_t TCA9555_CONFIGURATION_PORT_1 = 0x07; + +namespace esphome { +namespace tca9555 { + +static const char *const TAG = "tca9555"; + +void TCA9555Component::setup() { + ESP_LOGCONFIG(TAG, "Setting up TCA9555..."); + if (!this->read_gpio_modes_()) { + this->mark_failed(); + return; + } + if (!this->read_gpio_outputs_()) { + this->mark_failed(); + return; + } +} +void TCA9555Component::dump_config() { + ESP_LOGCONFIG(TAG, "TCA9555:"); + LOG_I2C_DEVICE(this) + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with TCA9555 failed!"); + } +} +void TCA9555Component::pin_mode(uint8_t pin, gpio::Flags flags) { + if (flags == gpio::FLAG_INPUT) { + // Set mode mask bit + this->mode_mask_ |= 1 << pin; + } else if (flags == gpio::FLAG_OUTPUT) { + // Clear mode mask bit + this->mode_mask_ &= ~(1 << pin); + } + // Write GPIO to enable input mode + this->write_gpio_modes_(); +} +void TCA9555Component::loop() { this->reset_pin_cache_(); } + +bool TCA9555Component::read_gpio_outputs_() { + if (this->is_failed()) + return false; + uint8_t data[2]; + if (!this->read_bytes(TCA9555_OUTPUT_PORT_REGISTER_0, data, 2)) { + this->status_set_warning("Failed to read output register"); + return false; + } + this->output_mask_ = (uint16_t(data[1]) << 8) | (uint16_t(data[0]) << 0); + this->status_clear_warning(); + return true; +} + +bool TCA9555Component::read_gpio_modes_() { + if (this->is_failed()) + return false; + uint8_t data[2]; + bool success = this->read_bytes(TCA9555_CONFIGURATION_PORT_0, data, 2); + if (!success) { + this->status_set_warning("Failed to read mode register"); + return false; + } + this->mode_mask_ = (uint16_t(data[1]) << 8) | (uint16_t(data[0]) << 0); + + this->status_clear_warning(); + return true; +} +bool TCA9555Component::digital_read_hw(uint8_t pin) { + if (this->is_failed()) + return false; + bool success; + uint8_t data[2]; + success = this->read_bytes(TCA9555_INPUT_PORT_REGISTER_0, data, 2); + this->input_mask_ = (uint16_t(data[1]) << 8) | (uint16_t(data[0]) << 0); + + if (!success) { + this->status_set_warning("Failed to read input register"); + return false; + } + + this->status_clear_warning(); + return true; +} + +void TCA9555Component::digital_write_hw(uint8_t pin, bool value) { + if (this->is_failed()) + return; + + if (value) { + this->output_mask_ |= (1 << pin); + } else { + this->output_mask_ &= ~(1 << pin); + } + + uint8_t data[2]; + data[0] = this->output_mask_; + data[1] = this->output_mask_ >> 8; + if (!this->write_bytes(TCA9555_OUTPUT_PORT_REGISTER_0, data, 2)) { + this->status_set_warning("Failed to write output register"); + return; + } + + this->status_clear_warning(); +} + +bool TCA9555Component::write_gpio_modes_() { + if (this->is_failed()) + return false; + uint8_t data[2]; + + data[0] = this->mode_mask_; + data[1] = this->mode_mask_ >> 8; + if (!this->write_bytes(TCA9555_CONFIGURATION_PORT_0, data, 2)) { + this->status_set_warning("Failed to write mode register"); + return false; + } + this->status_clear_warning(); + return true; +} + +bool TCA9555Component::digital_read_cache(uint8_t pin) { return this->input_mask_ & (1 << pin); } + +float TCA9555Component::get_setup_priority() const { return setup_priority::IO; } + +void TCA9555GPIOPin::setup() { this->pin_mode(this->flags_); } +void TCA9555GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); } +bool TCA9555GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; } +void TCA9555GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); } +std::string TCA9555GPIOPin::dump_summary() const { return str_sprintf("%u via TCA9555", this->pin_); } + +} // namespace tca9555 +} // namespace esphome diff --git a/esphome/components/tca9555/tca9555.h b/esphome/components/tca9555/tca9555.h new file mode 100644 index 0000000000..ea464db043 --- /dev/null +++ b/esphome/components/tca9555/tca9555.h @@ -0,0 +1,64 @@ +#pragma once + +#include "esphome/components/gpio_expander/cached_gpio.h" +#include "esphome/components/i2c/i2c.h" +#include "esphome/core/component.h" +#include "esphome/core/hal.h" + +namespace esphome { +namespace tca9555 { + +class TCA9555Component : public Component, + public i2c::I2CDevice, + public gpio_expander::CachedGpioExpander { + public: + TCA9555Component() = default; + + /// Check i2c availability and setup masks + void setup() override; + void pin_mode(uint8_t pin, gpio::Flags flags); + + float get_setup_priority() const override; + + void dump_config() override; + + void loop() override; + + protected: + bool digital_read_hw(uint8_t pin) override; + bool digital_read_cache(uint8_t pin) override; + void digital_write_hw(uint8_t pin, bool value) override; + + /// Mask for the pin mode - 1 means output, 0 means input + uint16_t mode_mask_{0x00}; + /// The mask to write as output state - 1 means HIGH, 0 means LOW + uint16_t output_mask_{0x00}; + /// The state read in digital_read_hw - 1 means HIGH, 0 means LOW + uint16_t input_mask_{0x00}; + + bool read_gpio_modes_(); + bool write_gpio_modes_(); + bool read_gpio_outputs_(); +}; + +/// Helper class to expose a TCA9555 pin as an internal input GPIO pin. +class TCA9555GPIOPin : public GPIOPin, public Parented { + 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_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: + uint8_t pin_; + bool inverted_; + gpio::Flags flags_; +}; + +} // namespace tca9555 +} // namespace esphome diff --git a/esphome/components/tcs34725/tcs34725.cpp b/esphome/components/tcs34725/tcs34725.cpp index 88c59eb761..0830004b5a 100644 --- a/esphome/components/tcs34725/tcs34725.cpp +++ b/esphome/components/tcs34725/tcs34725.cpp @@ -1,6 +1,8 @@ #include "tcs34725.h" #include "esphome/core/log.h" #include "esphome/core/hal.h" +#include +#include "esphome/core/helpers.h" namespace esphome { namespace tcs34725 { @@ -13,10 +15,7 @@ static const uint8_t TCS34725_REGISTER_ID = TCS34725_COMMAND_BIT | 0x12; static const uint8_t TCS34725_REGISTER_ATIME = TCS34725_COMMAND_BIT | 0x01; static const uint8_t TCS34725_REGISTER_CONTROL = TCS34725_COMMAND_BIT | 0x0F; static const uint8_t TCS34725_REGISTER_ENABLE = TCS34725_COMMAND_BIT | 0x00; -static const uint8_t TCS34725_REGISTER_CDATAL = TCS34725_COMMAND_BIT | 0x14; -static const uint8_t TCS34725_REGISTER_RDATAL = TCS34725_COMMAND_BIT | 0x16; -static const uint8_t TCS34725_REGISTER_GDATAL = TCS34725_COMMAND_BIT | 0x18; -static const uint8_t TCS34725_REGISTER_BDATAL = TCS34725_COMMAND_BIT | 0x1A; +static const uint8_t TCS34725_REGISTER_CRGBDATAL = TCS34725_COMMAND_BIT | 0x14; void TCS34725Component::setup() { ESP_LOGCONFIG(TAG, "Setting up TCS34725..."); @@ -74,20 +73,21 @@ float TCS34725Component::get_setup_priority() const { return setup_priority::DAT * @return Color temperature in degrees Kelvin */ void TCS34725Component::calculate_temperature_and_lux_(uint16_t r, uint16_t g, uint16_t b, uint16_t c) { - float r2, g2, b2; /* RGB values minus IR component */ - float sat; /* Digital saturation level */ - float ir; /* Inferred IR content */ + float sat; /* Digital saturation level */ - this->illuminance_ = 0; // Assign 0 value before calculation - this->color_temperature_ = 0; + this->illuminance_ = NAN; + this->color_temperature_ = NAN; - const float ga = this->glass_attenuation_; // Glass Attenuation Factor - static const float DF = 310.f; // Device Factor - static const float R_COEF = 0.136f; // - static const float G_COEF = 1.f; // used in lux computation - static const float B_COEF = -0.444f; // - static const float CT_COEF = 3810.f; // Color Temperature Coefficient - static const float CT_OFFSET = 1391.f; // Color Temperatuer Offset + const float ga = this->glass_attenuation_; // Glass Attenuation Factor + static const float DF = 310.f; // Device Factor + static const float R_COEF = 0.136f; // + static const float G_COEF = 1.f; // used in lux computation + static const float B_COEF = -0.444f; // + static const float CT_COEF = 3810.f; // Color Temperature Coefficient + static const float CT_OFFSET = 1391.f; // Color Temperatuer Offset + static const float MAX_ILLUMINANCE = 100000.0f; // Cap illuminance at 100,000 lux + static const float MAX_COLOR_TEMPERATURE = 15000.0f; // Maximum expected color temperature in Kelvin + static const float MIN_COLOR_TEMPERATURE = 1000.0f; // Maximum reasonable color temperature in Kelvin if (c == 0) { return; @@ -138,69 +138,66 @@ void TCS34725Component::calculate_temperature_and_lux_(uint16_t r, uint16_t g, u if (c >= sat) { if (this->integration_time_auto_) { ESP_LOGI(TAG, "Saturation too high, sample discarded, autogain ongoing"); + return; } else { - ESP_LOGW( - TAG, - "Saturation too high, sample with saturation %.1f and clear %d treat values carefully or use grey filter", - sat, c); - } - } - - /* AMS RGB sensors have no IR channel, so the IR content must be */ - /* calculated indirectly. */ - ir = ((r + g + b) > c) ? (r + g + b - c) / 2 : 0; - - /* Remove the IR component from the raw RGB values */ - r2 = r - ir; - g2 = g - ir; - b2 = b - ir; - - // discarding super low values? not recemmonded, and avoided by using auto gain. - if (r2 == 0) { - // legacy code - if (!this->integration_time_auto_) { ESP_LOGW(TAG, - "No light detected on red channel, switch to auto gain or adjust timing, values will be unreliable"); + "Saturation too high, sample with saturation %.1f and clear %d lux/color temperature cannot reliably " + "calculated, reduce integration/gain or use a grey filter.", + sat, c); return; } } // Lux Calculation (DN40 3.2) - float g1 = R_COEF * r2 + G_COEF * g2 + B_COEF * b2; + float g1 = R_COEF * (float) r + G_COEF * (float) g + B_COEF * (float) b; float cpl = (this->integration_time_ * this->gain_) / (ga * DF); - this->illuminance_ = g1 / cpl; + + this->illuminance_ = std::max(g1 / cpl, 0.0f); + + if (this->illuminance_ > MAX_ILLUMINANCE) { + ESP_LOGW(TAG, "Calculated illuminance greater than limit (%f), setting to NAN", this->illuminance_); + this->illuminance_ = NAN; + return; + } + + if (r == 0) { + ESP_LOGW(TAG, "Red channel is zero, cannot compute color temperature"); + return; + } // Color Temperature Calculation (DN40) /* A simple method of measuring color temp is to use the ratio of blue */ - /* to red light, taking IR cancellation into account. */ - this->color_temperature_ = (CT_COEF * b2) / /** Color temp coefficient. */ - r2 + - CT_OFFSET; /** Color temp offset. */ + /* to red light. */ + + this->color_temperature_ = (CT_COEF * (float) b) / (float) r + CT_OFFSET; + + // Ensure the color temperature stays within reasonable bounds + if (this->color_temperature_ < MIN_COLOR_TEMPERATURE) { + ESP_LOGW(TAG, "Calculated color temperature value too low (%f), setting to NAN", this->color_temperature_); + this->color_temperature_ = NAN; + } else if (this->color_temperature_ > MAX_COLOR_TEMPERATURE) { + ESP_LOGW(TAG, "Calculated color temperature value too high (%f), setting to NAN", this->color_temperature_); + this->color_temperature_ = NAN; + } } void TCS34725Component::update() { - uint16_t raw_c; - uint16_t raw_r; - uint16_t raw_g; - uint16_t raw_b; + uint8_t data[8]; // Buffer to hold the 8 bytes (2 bytes for each of the 4 channels) - if (this->read_data_register_(TCS34725_REGISTER_CDATAL, raw_c) != i2c::ERROR_OK) { - this->status_set_warning(); - return; - } - if (this->read_data_register_(TCS34725_REGISTER_RDATAL, raw_r) != i2c::ERROR_OK) { - this->status_set_warning(); - return; - } - if (this->read_data_register_(TCS34725_REGISTER_GDATAL, raw_g) != i2c::ERROR_OK) { - this->status_set_warning(); - return; - } - if (this->read_data_register_(TCS34725_REGISTER_BDATAL, raw_b) != i2c::ERROR_OK) { + // Perform burst + if (this->read_register(TCS34725_REGISTER_CRGBDATAL, data, 8) != i2c::ERROR_OK) { this->status_set_warning(); + ESP_LOGW(TAG, "Error reading TCS34725 sensor data"); return; } + + // Extract the data + uint16_t raw_c = encode_uint16(data[1], data[0]); // Clear channel + uint16_t raw_r = encode_uint16(data[3], data[2]); // Red channel + uint16_t raw_g = encode_uint16(data[5], data[4]); // Green channel + uint16_t raw_b = encode_uint16(data[7], data[6]); // Blue channel + ESP_LOGV(TAG, "Raw values clear=%d red=%d green=%d blue=%d", raw_c, raw_r, raw_g, raw_b); float channel_c; @@ -211,7 +208,7 @@ void TCS34725Component::update() { if (raw_c == 0) { channel_c = channel_r = channel_g = channel_b = 0.0f; } else { - float max_count = this->integration_time_ * 1024.0f / 2.4; + float max_count = this->integration_time_ <= 153.6f ? this->integration_time_ * 1024.0f / 2.4f : 65535.0f; float sum = raw_c; channel_r = raw_r / sum * 100.0f; channel_g = raw_g / sum * 100.0f; @@ -254,7 +251,8 @@ void TCS34725Component::update() { // change integration time an gain to achieve maximum resolution an dynamic range // calculate optimal integration time to achieve 70% satuaration float integration_time_ideal; - integration_time_ideal = 60 / ((float) raw_c / 655.35) * this->integration_time_; + + integration_time_ideal = 60 / ((float) std::max((uint16_t) 1, raw_c) / 655.35f) * this->integration_time_; uint8_t gain_reg_val_new = this->gain_reg_; // increase gain if less than 20% of white channel used and high integration time diff --git a/esphome/components/tem3200/__init__.py b/esphome/components/tem3200/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/tem3200/sensor.py b/esphome/components/tem3200/sensor.py new file mode 100644 index 0000000000..5cd27433d0 --- /dev/null +++ b/esphome/components/tem3200/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_ID, + CONF_TEMPERATURE, + DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, +) + +CODEOWNERS = ["@bakerkj"] +DEPENDENCIES = ["i2c"] + +tem3200_ns = cg.esphome_ns.namespace("tem3200") + +TEM3200Component = tem3200_ns.class_( + "TEM3200Component", cg.PollingComponent, i2c.I2CDevice +) + +CONF_RAW_PRESSURE = "raw_pressure" + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(TEM3200Component), + 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_RAW_PRESSURE): sensor.sensor_schema( + accuracy_decimals=0, state_class=STATE_CLASS_MEASUREMENT + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x28)) +) + + +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)) + + if raw_pressure_config := config.get(CONF_RAW_PRESSURE): + sens = await sensor.new_sensor(raw_pressure_config) + cg.add(var.set_raw_pressure_sensor(sens)) diff --git a/esphome/components/tem3200/tem3200.cpp b/esphome/components/tem3200/tem3200.cpp new file mode 100644 index 0000000000..d8ce48af90 --- /dev/null +++ b/esphome/components/tem3200/tem3200.cpp @@ -0,0 +1,151 @@ +#include "tem3200.h" +#include "esphome/core/log.h" +#include "esphome/core/helpers.h" +#include "esphome/core/hal.h" + +namespace esphome { +namespace tem3200 { + +static const char *const TAG = "tem3200"; + +enum ErrorCode { + NONE = 0, + RESERVED = 1, + STALE = 2, + FAULT = 3, +}; + +void TEM3200Component::setup() { + ESP_LOGCONFIG(TAG, "Setting up TEM3200..."); + + uint8_t status(NONE); + uint16_t raw_temperature(0); + uint16_t raw_pressure(0); + + i2c::ErrorCode err = this->read_(status, raw_temperature, raw_pressure); + if (err != i2c::ERROR_OK) { + ESP_LOGCONFIG(TAG, " I2C Communication Failed..."); + this->mark_failed(); + return; + } + + switch (status) { + case RESERVED: + ESP_LOGE(TAG, "Invalid RESERVED Device Status"); + this->mark_failed(); + return; + case FAULT: + ESP_LOGE(TAG, "FAULT condition in the SSC or sensing element"); + this->mark_failed(); + return; + case STALE: + ESP_LOGE(TAG, "STALE data. Data has not been updated since last fetch"); + this->status_set_warning(); + break; + } + ESP_LOGCONFIG(TAG, " Success..."); +} + +void TEM3200Component::dump_config() { + ESP_LOGCONFIG(TAG, "TEM3200:"); + LOG_I2C_DEVICE(this); + LOG_UPDATE_INTERVAL(this); + LOG_SENSOR(" ", "Raw Pressure", this->raw_pressure_sensor_); + LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); +} + +float TEM3200Component::get_setup_priority() const { return setup_priority::DATA; } + +i2c::ErrorCode TEM3200Component::read_(uint8_t &status, uint16_t &raw_temperature, uint16_t &raw_pressure) { + uint8_t response[4] = {0x00, 0x00, 0x00, 0x00}; + + // initiate data read + i2c::ErrorCode err = this->read(response, 4); + if (err != i2c::ERROR_OK) { + return err; + } + + // extract top 2 bits of first byte for status + status = (ErrorCode) (response[0] & 0xc0) >> 6; + if (status == RESERVED || status == FAULT) { + return i2c::ERROR_OK; + } + + // if data is stale; reread + if (status == STALE) { + // wait for measurement 2ms + delay(2); + + err = this->read(response, 4); + if (err != i2c::ERROR_OK) { + return err; + } + } + + // extract top 2 bits of first byte for status + status = (ErrorCode) (response[0] & 0xc0) >> 6; + if (status == RESERVED || status == FAULT) { + return i2c::ERROR_OK; + } + + // extract top 6 bits of first byte and all bits of second byte for pressure + raw_pressure = (((response[0] & 0x3f)) << 8 | response[1]); + + // extract all bytes of 3rd byte and top 3 bits of fourth byte for temperature + raw_temperature = ((response[2] << 3) | (response[3] & 0xe0) >> 5); + + return i2c::ERROR_OK; +} + +inline float convert_temperature(uint16_t raw_temperature) { + const float temperature_bits_span = 2048; + const float temperature_max = 150; + const float temperature_min = -50; + const float temperature_span = temperature_max - temperature_min; + + float temperature = (raw_temperature * temperature_span / temperature_bits_span) + temperature_min; + + return temperature; +} + +void TEM3200Component::update() { + uint8_t status(NONE); + uint16_t raw_temperature(0); + uint16_t raw_pressure(0); + i2c::ErrorCode err = this->read_(status, raw_temperature, raw_pressure); + + if (err != i2c::ERROR_OK) { + ESP_LOGW(TAG, "I2C Communication Failed"); + this->status_set_warning(); + return; + } + + switch (status) { + case RESERVED: + ESP_LOGE(TAG, "Failed: Device return RESERVED status"); + this->status_set_warning(); + return; + case FAULT: + ESP_LOGE(TAG, "Failed: FAULT condition in the SSC or sensing element"); + this->mark_failed(); + return; + case STALE: + ESP_LOGE(TAG, "Warning: STALE data. Data has not been updated since last fetch"); + this->status_set_warning(); + return; + } + + float temperature = convert_temperature(raw_temperature); + + ESP_LOGD(TAG, "Got raw pressure=%d, temperature=%.1f°C", raw_pressure, temperature); + + if (this->temperature_sensor_ != nullptr) + this->temperature_sensor_->publish_state(temperature); + if (this->raw_pressure_sensor_ != nullptr) + this->raw_pressure_sensor_->publish_state(raw_pressure); + + this->status_clear_warning(); +} + +} // namespace tem3200 +} // namespace esphome diff --git a/esphome/components/tem3200/tem3200.h b/esphome/components/tem3200/tem3200.h new file mode 100644 index 0000000000..c84a2aba21 --- /dev/null +++ b/esphome/components/tem3200/tem3200.h @@ -0,0 +1,30 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/i2c/i2c.h" + +namespace esphome { +namespace tem3200 { + +/// This class implements support for the tem3200 pressure and temperature i2c sensors. +class TEM3200Component : public PollingComponent, public i2c::I2CDevice { + public: + void set_temperature_sensor(sensor::Sensor *temperature_sensor) { this->temperature_sensor_ = temperature_sensor; } + void set_raw_pressure_sensor(sensor::Sensor *raw_pressure_sensor) { + this->raw_pressure_sensor_ = raw_pressure_sensor; + } + + float get_setup_priority() const override; + void setup() override; + void dump_config() override; + void update() override; + + protected: + i2c::ErrorCode read_(uint8_t &status, uint16_t &raw_temperature, uint16_t &raw_pressure); + sensor::Sensor *temperature_sensor_{nullptr}; + sensor::Sensor *raw_pressure_sensor_{nullptr}; +}; + +} // namespace tem3200 +} // namespace esphome diff --git a/esphome/components/template/binary_sensor/__init__.py b/esphome/components/template/binary_sensor/__init__.py index 4ce89503de..c93876380d 100644 --- a/esphome/components/template/binary_sensor/__init__.py +++ b/esphome/components/template/binary_sensor/__init__.py @@ -1,8 +1,10 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import automation +import esphome.codegen as cg from esphome.components import binary_sensor -from esphome.const import CONF_ID, CONF_LAMBDA, CONF_STATE +import esphome.config_validation as cv +from esphome.const import CONF_CONDITION, CONF_ID, CONF_LAMBDA, CONF_STATE +from esphome.cpp_generator import LambdaExpression + from .. import template_ns TemplateBinarySensor = template_ns.class_( @@ -13,7 +15,10 @@ CONFIG_SCHEMA = ( binary_sensor.binary_sensor_schema(TemplateBinarySensor) .extend( { - cv.Optional(CONF_LAMBDA): cv.returning_lambda, + cv.Exclusive(CONF_LAMBDA, CONF_CONDITION): cv.returning_lambda, + cv.Exclusive( + CONF_CONDITION, CONF_CONDITION + ): automation.validate_potentially_and_condition, } ) .extend(cv.COMPONENT_SCHEMA) @@ -24,9 +29,17 @@ async def to_code(config): var = await binary_sensor.new_binary_sensor(config) await cg.register_component(var, config) - if CONF_LAMBDA in config: + if lamb := config.get(CONF_LAMBDA): template_ = await cg.process_lambda( - config[CONF_LAMBDA], [], return_type=cg.optional.template(bool) + lamb, [], return_type=cg.optional.template(bool) + ) + cg.add(var.set_template(template_)) + if condition := config.get(CONF_CONDITION): + condition = await automation.build_condition( + condition, cg.TemplateArguments(), [] + ) + template_ = LambdaExpression( + f"return {condition.check()};", [], return_type=cg.optional.template(bool) ) cg.add(var.set_template(template_)) diff --git a/esphome/components/text/__init__.py b/esphome/components/text/__init__.py index 386baaf756..20e5a645d1 100644 --- a/esphome/components/text/__init__.py +++ b/esphome/components/text/__init__.py @@ -11,7 +11,7 @@ from esphome.const import ( CONF_ON_VALUE, CONF_TRIGGER_ID, CONF_VALUE, - CONF_WEB_SERVER_ID, + CONF_WEB_SERVER, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_helpers import setup_entity @@ -82,9 +82,8 @@ 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) + if web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(var, web_server_config) async def register_text( diff --git a/esphome/components/text_sensor/__init__.py b/esphome/components/text_sensor/__init__.py index ba8a2def41..12993d9ffc 100644 --- a/esphome/components/text_sensor/__init__.py +++ b/esphome/components/text_sensor/__init__.py @@ -15,7 +15,7 @@ from esphome.const import ( CONF_STATE, CONF_TO, CONF_TRIGGER_ID, - CONF_WEB_SERVER_ID, + CONF_WEB_SERVER, DEVICE_CLASS_DATE, DEVICE_CLASS_EMPTY, DEVICE_CLASS_TIMESTAMP, @@ -212,9 +212,8 @@ 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) + if web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(var, web_server_config) async def register_text_sensor(var, config): 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 diff --git a/esphome/components/thermostat/thermostat_climate.cpp b/esphome/components/thermostat/thermostat_climate.cpp index 26be6ba53a..f7b3410df9 100644 --- a/esphome/components/thermostat/thermostat_climate.cpp +++ b/esphome/components/thermostat/thermostat_climate.cpp @@ -502,8 +502,9 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu } this->action = action; this->prev_action_trigger_ = trig; - assert(trig != nullptr); - trig->trigger(); + if (trig != nullptr) { + trig->trigger(); + } // if enabled, call the fan_only action with cooling/heating actions if (trig_fan != nullptr) { ESP_LOGVV(TAG, "Calling FAN_ONLY action with HEATING/COOLING action"); @@ -564,7 +565,6 @@ void ThermostatClimate::trigger_supplemental_action_() { } if (trig != nullptr) { - assert(trig != nullptr); trig->trigger(); } } @@ -634,8 +634,9 @@ void ThermostatClimate::switch_to_fan_mode_(climate::ClimateFanMode fan_mode, bo this->prev_fan_mode_trigger_ = nullptr; } this->start_timer_(thermostat::TIMER_FAN_MODE); - assert(trig != nullptr); - trig->trigger(); + if (trig != nullptr) { + trig->trigger(); + } this->prev_fan_mode_ = fan_mode; this->prev_fan_mode_trigger_ = trig; } @@ -678,8 +679,9 @@ void ThermostatClimate::switch_to_mode_(climate::ClimateMode mode, bool publish_ mode = climate::CLIMATE_MODE_HEAT_COOL; // trig = this->auto_mode_trigger_; } - assert(trig != nullptr); - trig->trigger(); + if (trig != nullptr) { + trig->trigger(); + } this->mode = mode; this->prev_mode_ = mode; this->prev_mode_trigger_ = trig; @@ -718,8 +720,9 @@ void ThermostatClimate::switch_to_swing_mode_(climate::ClimateSwingMode swing_mo swing_mode = climate::CLIMATE_SWING_OFF; // trig = this->swing_mode_off_trigger_; } - assert(trig != nullptr); - trig->trigger(); + if (trig != nullptr) { + trig->trigger(); + } this->swing_mode = swing_mode; this->prev_swing_mode_ = swing_mode; this->prev_swing_mode_trigger_ = trig; @@ -867,8 +870,9 @@ void ThermostatClimate::check_temperature_change_trigger_() { } // trigger the action Trigger<> *trig = this->temperature_change_trigger_; - assert(trig != nullptr); - trig->trigger(); + if (trig != nullptr) { + trig->trigger(); + } } bool ThermostatClimate::cooling_required_() { @@ -998,9 +1002,10 @@ void ThermostatClimate::change_preset_(climate::ClimatePreset preset) { this->preset.value() != preset) { // Fire any preset changed trigger if defined Trigger<> *trig = this->preset_change_trigger_; - assert(trig != nullptr); this->preset = preset; - trig->trigger(); + if (trig != nullptr) { + trig->trigger(); + } this->refresh(); ESP_LOGI(TAG, "Preset %s applied", LOG_STR_ARG(climate::climate_preset_to_string(preset))); @@ -1023,9 +1028,10 @@ void ThermostatClimate::change_custom_preset_(const std::string &custom_preset) this->custom_preset.value() != 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(); + if (trig != nullptr) { + trig->trigger(); + } this->refresh(); ESP_LOGI(TAG, "Custom preset %s applied", custom_preset.c_str()); 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) diff --git a/esphome/components/touchscreen/touchscreen.cpp b/esphome/components/touchscreen/touchscreen.cpp index b9498de152..dfe723aedf 100644 --- a/esphome/components/touchscreen/touchscreen.cpp +++ b/esphome/components/touchscreen/touchscreen.cpp @@ -18,8 +18,8 @@ void Touchscreen::attach_interrupt_(InternalGPIOPin *irq_pin, esphome::gpio::Int void Touchscreen::call_setup() { if (this->display_ != nullptr) { - this->display_width_ = this->display_->get_native_width(); - this->display_height_ = this->display_->get_native_height(); + this->display_width_ = this->display_->get_width(); + this->display_height_ = this->display_->get_height(); } PollingComponent::call_setup(); } diff --git a/esphome/components/udp/udp_component.cpp b/esphome/components/udp/udp_component.cpp index 799ed813d3..a1c8889997 100644 --- a/esphome/components/udp/udp_component.cpp +++ b/esphome/components/udp/udp_component.cpp @@ -261,7 +261,8 @@ void UDPComponent::setup() { return; } } -#else +#endif +#ifdef USE_SOCKET_IMPL_LWIP_TCP // 8266 and RP2040 `Duino for (const auto &address : this->addresses_) { auto ipaddr = IPAddress(); @@ -370,7 +371,8 @@ void UDPComponent::loop() { for (;;) { #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) auto len = this->listen_socket_->read(buf, sizeof(buf)); -#else +#endif +#ifdef USE_SOCKET_IMPL_LWIP_TCP auto len = this->udp_client_.parsePacket(); if (len > 0) len = this->udp_client_.read(buf, sizeof(buf)); @@ -587,7 +589,8 @@ void UDPComponent::send_packet_(void *data, size_t len) { if (result < 0) ESP_LOGW(TAG, "sendto() error %d", errno); } -#else +#endif +#ifdef USE_SOCKET_IMPL_LWIP_TCP auto iface = IPAddress(0, 0, 0, 0); for (const auto &saddr : this->ipaddrs_) { if (this->udp_client_.beginPacketMulticast(saddr, this->port_, iface, 128) != 0) { diff --git a/esphome/components/udp/udp_component.h b/esphome/components/udp/udp_component.h index 69bf335a90..b4e11cf652 100644 --- a/esphome/components/udp/udp_component.h +++ b/esphome/components/udp/udp_component.h @@ -9,7 +9,8 @@ #endif #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) #include "esphome/components/socket/socket.h" -#else +#endif +#ifdef USE_SOCKET_IMPL_LWIP_TCP #include #endif #include @@ -125,7 +126,8 @@ class UDPComponent : public PollingComponent { std::unique_ptr broadcast_socket_ = nullptr; std::unique_ptr listen_socket_ = nullptr; std::vector sockaddrs_{}; -#else +#endif +#ifdef USE_SOCKET_IMPL_LWIP_TCP std::vector ipaddrs_{}; WiFiUDP udp_client_{}; #endif diff --git a/esphome/components/update/__init__.py b/esphome/components/update/__init__.py index ba3b2f20df..4729d954ee 100644 --- a/esphome/components/update/__init__.py +++ b/esphome/components/update/__init__.py @@ -8,7 +8,7 @@ from esphome.const import ( CONF_FORCE_UPDATE, CONF_ID, CONF_MQTT_ID, - CONF_WEB_SERVER_ID, + CONF_WEB_SERVER, DEVICE_CLASS_EMPTY, DEVICE_CLASS_FIRMWARE, ENTITY_CATEGORY_CONFIG, @@ -73,9 +73,8 @@ async def setup_update_core_(var, config): 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_ = await cg.get_variable(web_server_id_config) - web_server.add_entity_to_sorting_list(web_server_, var, config) + if web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(var, web_server_config) async def register_update(var, config): 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}; diff --git a/esphome/components/valve/__init__.py b/esphome/components/valve/__init__.py index 3c03bab857..e55bb522de 100644 --- a/esphome/components/valve/__init__.py +++ b/esphome/components/valve/__init__.py @@ -14,7 +14,7 @@ from esphome.const import ( CONF_STATE, CONF_STOP, CONF_TRIGGER_ID, - CONF_WEB_SERVER_ID, + CONF_WEB_SERVER, DEVICE_CLASS_EMPTY, DEVICE_CLASS_GAS, DEVICE_CLASS_WATER, @@ -124,9 +124,8 @@ 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) + if web_server_config := config.get(CONF_WEB_SERVER): + await web_server.add_entity_config(var, web_server_config) async def register_valve(var, config): 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/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 43c7428858..6f164f69d3 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -23,6 +23,8 @@ 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; +VoiceAssistant::VoiceAssistant() { global_voice_assistant = this; } + float VoiceAssistant::get_setup_priority() const { return setup_priority::AFTER_CONNECTION; } bool VoiceAssistant::start_udp_socket_() { @@ -68,12 +70,6 @@ bool VoiceAssistant::start_udp_socket_() { return true; } -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 @@ -396,6 +392,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; @@ -433,16 +433,18 @@ void VoiceAssistant::loop() { #ifdef USE_SPEAKER void VoiceAssistant::write_speaker_() { - if (this->speaker_buffer_size_ > 0) { - 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_LOGV(TAG, "Speaker buffer full, trying again next loop"); + if ((this->speaker_ != nullptr) && (this->speaker_buffer_ != nullptr)) { + if (this->speaker_buffer_size_ > 0) { + 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_LOGV(TAG, "Speaker buffer full, trying again next loop"); + } } } } @@ -751,7 +753,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") { @@ -772,16 +774,20 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { } case api::enums::VOICE_ASSISTANT_TTS_STREAM_START: { #ifdef USE_SPEAKER - this->wait_for_stream_end_ = true; - ESP_LOGD(TAG, "TTS stream start"); - this->defer([this] { this->tts_stream_start_trigger_->trigger(); }); + if (this->speaker_ != nullptr) { + this->wait_for_stream_end_ = true; + ESP_LOGD(TAG, "TTS stream start"); + this->defer([this] { this->tts_stream_start_trigger_->trigger(); }); + } #endif break; } case api::enums::VOICE_ASSISTANT_TTS_STREAM_END: { #ifdef USE_SPEAKER - this->stream_ended_ = true; - ESP_LOGD(TAG, "TTS stream end"); + if (this->speaker_ != nullptr) { + this->stream_ended_ = true; + ESP_LOGD(TAG, "TTS stream end"); + } #endif break; } @@ -802,14 +808,16 @@ 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(); - this->speaker_buffer_size_ += msg.data.length(); - this->speaker_bytes_received_ += 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"); + if ((this->speaker_ != nullptr) && (this->speaker_buffer_ != nullptr)) { + 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(); + ESP_LOGV(TAG, "Received audio: %u bytes from API", msg.data.length()); + } else { + ESP_LOGE(TAG, "Cannot receive audio, buffer is full"); + } } #endif } @@ -866,6 +874,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..0016d3157c 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -77,9 +77,22 @@ struct Timer { } }; +struct WakeWord { + std::string id; + std::string wake_word; + std::vector trained_languages; +}; + +struct Configuration { + std::vector available_wake_words; + std::vector active_wake_words; + uint32_t max_active_wake_words; +}; + class VoiceAssistant : public Component { public: - void setup() override; + VoiceAssistant(); + void loop() override; float get_setup_priority() const override; void start_streaming(); @@ -132,6 +145,9 @@ 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); + void on_set_configuration(const std::vector &active_wake_words){}; + const Configuration &get_configuration() { return this->config_; }; bool is_running() const { return this->state_ != State::IDLE; } void set_continuous(bool continuous) { this->continuous_ = continuous; } @@ -234,7 +250,7 @@ class VoiceAssistant : public Component { #ifdef USE_SPEAKER void write_speaker_(); speaker::Speaker *speaker_{nullptr}; - uint8_t *speaker_buffer_; + uint8_t *speaker_buffer_{nullptr}; size_t speaker_buffer_index_{0}; size_t speaker_buffer_size_{0}; size_t speaker_bytes_received_{0}; @@ -266,8 +282,8 @@ class VoiceAssistant : public Component { float volume_multiplier_; uint32_t conversation_timeout_; - uint8_t *send_buffer_; - int16_t *input_buffer_; + uint8_t *send_buffer_{nullptr}; + int16_t *input_buffer_{nullptr}; bool continuous_{false}; bool silence_detection_; @@ -278,6 +294,8 @@ class VoiceAssistant : public Component { AudioMode audio_mode_{AUDIO_MODE_UDP}; bool udp_socket_running_{false}; bool start_udp_socket_(); + + Configuration config_{}; }; template class StartAction : public Action, public Parented { diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index 02074dcf11..d846a3418b 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -17,13 +17,14 @@ from esphome.const import ( CONF_JS_URL, CONF_LOCAL, CONF_LOG, + CONF_NAME, CONF_OTA, CONF_PASSWORD, CONF_PORT, CONF_USERNAME, CONF_VERSION, + CONF_WEB_SERVER, CONF_WEB_SERVER_ID, - CONF_WEB_SERVER_SORTING_WEIGHT, PLATFORM_BK72XX, PLATFORM_ESP32, PLATFORM_ESP8266, @@ -34,9 +35,15 @@ import esphome.final_validate as fv AUTO_LOAD = ["json", "web_server_base"] +CONF_SORTING_GROUP_ID = "sorting_group_id" +CONF_SORTING_GROUPS = "sorting_groups" +CONF_SORTING_WEIGHT = "sorting_weight" + web_server_ns = cg.esphome_ns.namespace("web_server") WebServer = web_server_ns.class_("WebServer", cg.Component, cg.Controller) +sorting_groups = {} + def default_url(config): config = config.copy() @@ -70,42 +77,74 @@ 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], +def validate_sorting_groups(config): + if CONF_SORTING_GROUPS in config and config[CONF_VERSION] != 3: + raise cv.Invalid( + f"'{CONF_SORTING_GROUPS}' is only supported in 'web_server' version 3" ) - 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 +def _validate_no_sorting_component( + sorting_component: str, + webserver_version: int, + config: dict, + path: list[str] | None = None, +) -> None: + if path is None: + path = [] + if CONF_WEB_SERVER in config and sorting_component in config[CONF_WEB_SERVER]: + raise cv.FinalExternalInvalid( + f"{sorting_component} on entities is not supported in web_server version {webserver_version}", + path=path + [sorting_component], + ) + for p, value in config.items(): + if isinstance(value, dict): + _validate_no_sorting_component( + sorting_component, webserver_version, value, path + [p] + ) + elif isinstance(value, list): + for i, item in enumerate(value): + if isinstance(item, dict): + _validate_no_sorting_component( + sorting_component, webserver_version, item, path + [p, i] + ) +def _final_validate_sorting(config): + if (webserver_version := config.get(CONF_VERSION)) != 3: + _validate_no_sorting_component( + CONF_SORTING_WEIGHT, webserver_version, fv.full_config.get() + ) + _validate_no_sorting_component( + CONF_SORTING_GROUP_ID, webserver_version, fv.full_config.get() + ) + return config + + +FINAL_VALIDATE_SCHEMA = _final_validate_sorting + +sorting_group = { + cv.Required(CONF_ID): cv.declare_id(cg.int_), + cv.Required(CONF_NAME): cv.string, + cv.Optional(CONF_SORTING_WEIGHT): cv.float_, +} + 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_, - ), + cv.Optional(CONF_WEB_SERVER): cv.Schema( + { + cv.OnlyWith(CONF_WEB_SERVER_ID, "web_server"): cv.use_id(WebServer), + cv.Optional(CONF_SORTING_WEIGHT): cv.All( + cv.requires_component("web_server"), + cv.float_, + ), + cv.Optional(CONF_SORTING_GROUP_ID): cv.All( + cv.requires_component("web_server"), + cv.use_id(cg.int_), + ), + } + ) } ) @@ -145,24 +184,38 @@ CONFIG_SCHEMA = cv.All( ): cv.boolean, cv.Optional(CONF_LOG, default=True): cv.boolean, cv.Optional(CONF_LOCAL): cv.boolean, + cv.Optional(CONF_SORTING_GROUPS): cv.ensure_list(sorting_group), } ).extend(cv.COMPONENT_SCHEMA), cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_BK72XX, PLATFORM_RTL87XX]), default_url, validate_local, validate_ota, + validate_sorting_groups, ) -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] +def add_sorting_groups(web_server_var, config): + for group in config: + sorting_groups[group[CONF_ID]] = group[CONF_NAME] + group_sorting_weight = group.get(CONF_SORTING_WEIGHT, 50) + cg.add( + web_server_var.add_sorting_group( + hash(group[CONF_ID]), group[CONF_NAME], group_sorting_weight + ) + ) + + +async def add_entity_config(entity, config): + web_server = await cg.get_variable(config[CONF_WEB_SERVER_ID]) + sorting_weight = config.get(CONF_SORTING_WEIGHT, 50) + sorting_group_hash = hash(config.get(CONF_SORTING_GROUP_ID)) cg.add( - web_server.add_entity_to_sorting_list( + web_server.add_entity_config( entity, sorting_weight, + sorting_group_hash, ) ) @@ -241,3 +294,6 @@ async def to_code(config): cg.add(var.set_include_internal(config[CONF_INCLUDE_INTERNAL])) if CONF_LOCAL in config and config[CONF_LOCAL]: cg.add_define("USE_WEBSERVER_LOCAL") + + if (sorting_group_config := config.get(CONF_SORTING_GROUPS)) is not None: + add_sorting_groups(var, sorting_group_config) diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index 0f3f743a73..b5d7189137 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -12,7 +12,7 @@ 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, + 0x71, 0x6c, 0xc7, 0x72, 0xec, 0x38, 0x0c, 0xb7, 0x0c, 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, @@ -34,3984 +34,3994 @@ const uint8_t INDEX_GZ[] PROGMEM = { 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, 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}; + 0x3d, 0x21, 0xf5, 0x5e, 0xd9, 0x1e, 0x40, 0x3b, 0xd9, 0xfb, 0x5d, 0xb1, 0xbd, 0x4f, 0x0b, 0xa1, 0xe8, 0x98, 0x3d, + 0xbe, 0xba, 0xfa, 0xb4, 0x27, 0x8b, 0xbd, 0x4f, 0x99, 0x52, 0x9f, 0xf6, 0xb8, 0x50, 0x9a, 0xd1, 0x51, 0x12, 0xa1, + 0xae, 0xe9, 0x2c, 0x53, 0xea, 0x1d, 0xbb, 0xd5, 0x44, 0x63, 0xf3, 0xa9, 0x09, 0x5b, 0x4f, 0x98, 0xde, 0x53, 0xe5, + 0xbc, 0x62, 0xb4, 0xcc, 0x99, 0xde, 0xd3, 0xc4, 0xe4, 0x4b, 0x07, 0x7f, 0x66, 0x3f, 0x75, 0x97, 0x8f, 0xe3, 0x1b, + 0x71, 0x70, 0xa0, 0x4b, 0x40, 0xa3, 0xa5, 0x5b, 0x21, 0xc2, 0xf6, 0x7d, 0xda, 0xc1, 0x01, 0x4b, 0x72, 0x26, 0x26, + 0x7a, 0x4a, 0x08, 0x69, 0x77, 0xc5, 0xc1, 0x41, 0xac, 0xc9, 0x07, 0x91, 0x4c, 0x98, 0x8e, 0x19, 0x42, 0xb8, 0xaa, + 0x7d, 0x70, 0x10, 0x5b, 0x20, 0x48, 0xa2, 0x0d, 0xe0, 0x6a, 0x30, 0x46, 0x89, 0x83, 0xfe, 0xd5, 0x9d, 0xc8, 0xe2, + 0x70, 0xfc, 0x08, 0x8b, 0x83, 0x83, 0x0f, 0x22, 0x51, 0xd0, 0x22, 0xd6, 0x08, 0xad, 0x0b, 0xa6, 0x17, 0x85, 0xd8, + 0xd3, 0x6b, 0x2d, 0xaf, 0x74, 0xc1, 0xc5, 0x24, 0x46, 0x4b, 0x9f, 0x16, 0x54, 0x5c, 0xaf, 0xed, 0x70, 0x7f, 0x2b, + 0x08, 0x27, 0x97, 0xd0, 0xe3, 0x33, 0x19, 0x3b, 0x1c, 0xe4, 0x84, 0x44, 0xca, 0xd4, 0x8d, 0x7a, 0x3c, 0xe5, 0x8d, + 0x28, 0xc2, 0x76, 0x94, 0xf8, 0xb3, 0x40, 0x58, 0x68, 0x40, 0xdd, 0x24, 0x49, 0x34, 0x22, 0x97, 0x4b, 0x0f, 0x16, + 0x1e, 0x4c, 0xb4, 0xc7, 0xfb, 0xad, 0x41, 0xaa, 0x93, 0x82, 0x8d, 0x16, 0x19, 0x8b, 0x63, 0x81, 0x15, 0x96, 0x88, + 0x5c, 0x8a, 0x46, 0x5c, 0x90, 0x4b, 0x58, 0xef, 0xa2, 0xbe, 0xd8, 0x84, 0xec, 0xb7, 0x90, 0x1b, 0x64, 0xe1, 0x47, + 0x08, 0x20, 0x76, 0x03, 0x2a, 0x08, 0x89, 0xc4, 0x62, 0x36, 0x64, 0x45, 0x54, 0x16, 0xeb, 0xd6, 0xf0, 0x62, 0xa1, + 0xd8, 0x5e, 0xa6, 0xd4, 0xde, 0x78, 0x21, 0x32, 0xcd, 0xa5, 0xd8, 0x8b, 0x1a, 0x45, 0x23, 0xb2, 0xf8, 0x50, 0xa2, + 0x43, 0x84, 0xd6, 0x28, 0x56, 0xa8, 0xc1, 0xfb, 0xb2, 0xd1, 0x1e, 0x60, 0x18, 0x25, 0xea, 0xba, 0xf6, 0x1c, 0x04, + 0x18, 0xe6, 0x30, 0xc9, 0x35, 0xfe, 0xd3, 0xee, 0x7c, 0x98, 0xe2, 0x8d, 0xe8, 0xf1, 0x64, 0x7b, 0xa7, 0x10, 0x9d, + 0xcc, 0xe8, 0x3c, 0x66, 0xe4, 0x92, 0x19, 0xec, 0xa2, 0x22, 0x83, 0xb1, 0xd6, 0x16, 0xae, 0xc7, 0x52, 0x96, 0x54, + 0x38, 0x85, 0x52, 0x9d, 0x8c, 0x65, 0xf1, 0x94, 0x66, 0x53, 0xa8, 0x57, 0x62, 0xcc, 0xc8, 0x6f, 0xb8, 0xac, 0x60, + 0x54, 0xb3, 0xa7, 0x39, 0x83, 0xaf, 0x38, 0x32, 0x35, 0x23, 0x84, 0x15, 0x6c, 0xf5, 0x9c, 0xeb, 0x57, 0x52, 0x64, + 0xac, 0xab, 0x02, 0xfc, 0x32, 0x2b, 0xff, 0x50, 0xeb, 0x82, 0x0f, 0x17, 0x9a, 0xc5, 0x91, 0x80, 0x12, 0x11, 0x56, + 0x08, 0x8b, 0x44, 0xb3, 0x5b, 0xfd, 0x58, 0x0a, 0xcd, 0x84, 0x26, 0xcc, 0x43, 0x15, 0xf3, 0x84, 0xce, 0xe7, 0x4c, + 0x8c, 0x1e, 0x4f, 0x79, 0x3e, 0x8a, 0x05, 0x5a, 0xa3, 0x35, 0xfe, 0x5d, 0x10, 0x98, 0x24, 0xb9, 0xe4, 0x29, 0xfc, + 0xf3, 0xed, 0xe9, 0xc4, 0x9a, 0x5c, 0x9a, 0x6d, 0xc1, 0x48, 0x14, 0x75, 0xc7, 0xb2, 0x88, 0xdd, 0x14, 0xf6, 0x80, + 0x74, 0x41, 0x1f, 0x6f, 0x17, 0x39, 0x53, 0x88, 0x35, 0x88, 0x28, 0xd7, 0xd1, 0x41, 0xf8, 0xb7, 0x22, 0x66, 0xb0, + 0x00, 0x1c, 0xa5, 0xdc, 0x90, 0xc0, 0x97, 0xdc, 0x6d, 0xaa, 0x51, 0x49, 0xd4, 0x3e, 0x0a, 0x32, 0xe2, 0x89, 0x2e, + 0x16, 0x4a, 0xb3, 0xd1, 0xbb, 0xbb, 0x39, 0x53, 0xf8, 0xe7, 0x82, 0x7c, 0x14, 0xbd, 0x8f, 0x22, 0x61, 0xb3, 0xb9, + 0xbe, 0xbb, 0x32, 0xd4, 0x3c, 0x8d, 0x22, 0xfc, 0x8f, 0x29, 0x5a, 0x30, 0x9a, 0x01, 0x49, 0x73, 0x20, 0x7b, 0x23, + 0xf3, 0xbb, 0x31, 0xcf, 0xf3, 0xab, 0xc5, 0x7c, 0x2e, 0x0b, 0x8d, 0xb5, 0x20, 0x4b, 0x2d, 0x2b, 0xf8, 0xc0, 0x8a, + 0x2e, 0xd5, 0x0d, 0xd7, 0xd9, 0x34, 0xd6, 0x68, 0x99, 0x51, 0xc5, 0xf6, 0x1e, 0x49, 0x99, 0x33, 0x2a, 0x52, 0x4e, + 0x78, 0xef, 0xe7, 0x22, 0x15, 0x8b, 0x3c, 0xef, 0x0e, 0x0b, 0x46, 0x3f, 0x77, 0x4d, 0xb6, 0x3d, 0x1c, 0x52, 0xf3, + 0xfb, 0x61, 0x51, 0xd0, 0x3b, 0x28, 0x48, 0x08, 0x14, 0xeb, 0xf1, 0xf4, 0xe7, 0xab, 0xd7, 0xaf, 0x12, 0xbb, 0x57, + 0xf8, 0xf8, 0x2e, 0xe6, 0xe5, 0xfe, 0xe3, 0x6b, 0x3c, 0x2e, 0xe4, 0x6c, 0xa3, 0x6b, 0x0b, 0x3a, 0xde, 0xfd, 0xc6, + 0x10, 0x18, 0xe1, 0xfb, 0xb6, 0xe9, 0x70, 0x04, 0xaf, 0x0c, 0xe6, 0x43, 0x26, 0x71, 0xfd, 0xc2, 0x3f, 0xa9, 0x4d, + 0x8e, 0x39, 0xfa, 0xfe, 0x68, 0x75, 0x71, 0xb7, 0x64, 0xc4, 0x8c, 0x73, 0x0e, 0x07, 0x23, 0x8c, 0x31, 0xa3, 0x3a, + 0x9b, 0x2e, 0x99, 0x69, 0x6c, 0xed, 0x47, 0xcc, 0xd6, 0x6b, 0xfc, 0x55, 0x7a, 0xac, 0xd7, 0xfb, 0x84, 0x70, 0x43, + 0xaf, 0x88, 0x5e, 0xad, 0x38, 0x21, 0x1c, 0xe1, 0xb7, 0x9c, 0x2c, 0xa9, 0x9f, 0x10, 0x9c, 0x6c, 0xb0, 0x3d, 0x53, + 0x4b, 0x65, 0xe0, 0x04, 0xfc, 0xc2, 0x0a, 0xcd, 0x8a, 0x54, 0x0b, 0x5c, 0xb0, 0x71, 0x0e, 0xe3, 0xd8, 0x6f, 0xe3, + 0x29, 0x55, 0x8f, 0xa7, 0x54, 0x4c, 0xd8, 0x28, 0xfd, 0x2a, 0xd7, 0x98, 0x09, 0x12, 0x8d, 0xb9, 0xa0, 0x39, 0xff, + 0xca, 0x46, 0x91, 0x3b, 0x17, 0x1e, 0xe9, 0x3d, 0x76, 0xab, 0x99, 0x18, 0xa9, 0xbd, 0xe7, 0xef, 0x7e, 0x7d, 0xe9, + 0x16, 0xb3, 0x76, 0x56, 0xa0, 0xa5, 0x5a, 0xcc, 0x59, 0x11, 0x23, 0xec, 0xce, 0x8a, 0xa7, 0xdc, 0xd0, 0xc9, 0x5f, + 0xe9, 0xdc, 0xa6, 0x70, 0xf5, 0xfb, 0x7c, 0x44, 0x35, 0x7b, 0xc3, 0xc4, 0x88, 0x8b, 0x09, 0xd9, 0x6f, 0xdb, 0xf4, + 0x29, 0x75, 0x19, 0xa3, 0x32, 0xe9, 0xfa, 0xde, 0xd3, 0xdc, 0xcc, 0xbd, 0xfc, 0x5c, 0xc4, 0x68, 0xad, 0x34, 0xd5, + 0x3c, 0xdb, 0xa3, 0xa3, 0xd1, 0x0b, 0xc1, 0x35, 0x37, 0x23, 0x2c, 0x60, 0x89, 0x00, 0x57, 0x99, 0x3d, 0x35, 0xfc, + 0xc8, 0x63, 0x84, 0xe3, 0xd8, 0x9d, 0x05, 0x53, 0xe4, 0xd6, 0xec, 0xe0, 0xa0, 0xa2, 0xfc, 0x3d, 0x96, 0xda, 0x4c, + 0xd2, 0x1f, 0xa0, 0x64, 0xbe, 0x50, 0xb0, 0xd8, 0xbe, 0x0b, 0x38, 0x68, 0xe4, 0x50, 0xb1, 0xe2, 0x0b, 0x1b, 0x95, + 0x08, 0xa2, 0x62, 0xb4, 0xdc, 0xe8, 0xc3, 0x6d, 0x0f, 0x4d, 0xfa, 0x83, 0x6e, 0x48, 0xc2, 0x99, 0x43, 0x76, 0xcb, + 0xa9, 0x70, 0xa6, 0x4a, 0xa2, 0x12, 0xc3, 0x81, 0x5a, 0x12, 0x16, 0x45, 0xfc, 0xfc, 0xe6, 0xb1, 0x00, 0x1e, 0x22, + 0xa4, 0x1c, 0xfe, 0xcc, 0x7d, 0xfa, 0xc5, 0x1c, 0x1e, 0x0a, 0x0b, 0x84, 0xb5, 0x1d, 0xa9, 0x42, 0x68, 0x8d, 0xb0, + 0xf6, 0xc3, 0xb5, 0x44, 0xc9, 0xf3, 0x45, 0x70, 0x6a, 0x93, 0xb7, 0xdc, 0x1c, 0xdb, 0x40, 0xdb, 0xa8, 0x66, 0x07, + 0x07, 0x31, 0x4b, 0x4a, 0xc4, 0x20, 0xfb, 0x6d, 0xb7, 0x48, 0x01, 0xb4, 0xbe, 0x31, 0x6e, 0xe8, 0xd9, 0x30, 0x38, + 0xfb, 0x2c, 0x11, 0xf2, 0x61, 0x96, 0x31, 0xa5, 0x64, 0x71, 0x70, 0xb0, 0x6f, 0xca, 0x97, 0x9c, 0x05, 0x2c, 0xe2, + 0xeb, 0x1b, 0x51, 0x0d, 0x01, 0x55, 0xa7, 0xad, 0xe7, 0x9b, 0x48, 0xc5, 0x37, 0x79, 0x26, 0x24, 0x8d, 0xae, 0xaf, + 0xa3, 0x86, 0xc6, 0x0e, 0x0e, 0x13, 0xe6, 0xbb, 0xbe, 0x7b, 0xc2, 0x2c, 0x5b, 0x68, 0x98, 0x90, 0x2d, 0xd0, 0xec, + 0xe4, 0x07, 0xe3, 0xfa, 0x90, 0xb0, 0xc6, 0x0a, 0xad, 0x83, 0x15, 0xdd, 0xd9, 0xb4, 0xe1, 0x6f, 0xec, 0xd2, 0x2d, + 0x27, 0x86, 0xa7, 0x08, 0xd6, 0xb1, 0xcf, 0x06, 0x6b, 0x6c, 0x60, 0xef, 0x67, 0x23, 0xcd, 0x40, 0xfb, 0x7a, 0xd0, + 0x75, 0xf9, 0x44, 0x59, 0xc8, 0x15, 0xec, 0x9f, 0x05, 0x53, 0xda, 0x22, 0x72, 0xac, 0xb1, 0xc4, 0x70, 0x46, 0x6d, + 0x32, 0x9d, 0x35, 0x96, 0x74, 0xd7, 0xd8, 0x5e, 0xcf, 0xe1, 0x6c, 0x54, 0x80, 0xd4, 0xdf, 0xc7, 0x27, 0x18, 0xab, + 0x46, 0xab, 0xd5, 0x5b, 0xee, 0x5b, 0xa9, 0xd6, 0xb2, 0xe4, 0xd7, 0x36, 0x16, 0x85, 0x09, 0xe4, 0x0e, 0xe7, 0xfd, + 0xb6, 0x1b, 0xbf, 0x18, 0x90, 0xfd, 0x56, 0x89, 0xc5, 0x0e, 0xac, 0x76, 0x3c, 0x16, 0x8a, 0xaf, 0x6d, 0x53, 0xc8, + 0x9c, 0xf5, 0x35, 0x7c, 0x49, 0xa6, 0x5b, 0xb8, 0x3a, 0x25, 0x7d, 0xe0, 0x3a, 0x92, 0xe9, 0xe0, 0x5b, 0xf8, 0xe4, + 0x29, 0x42, 0xac, 0xb7, 0xf3, 0x2a, 0xc2, 0xf1, 0xa5, 0x4e, 0x38, 0x36, 0xa6, 0x11, 0xcd, 0xcb, 0x2a, 0x51, 0x89, + 0x66, 0x6e, 0xab, 0x57, 0x59, 0x58, 0x98, 0xc1, 0x54, 0x53, 0x0a, 0x9a, 0x78, 0x45, 0x67, 0x4c, 0xc5, 0x0c, 0xe1, + 0x6f, 0x15, 0xb0, 0xf8, 0x09, 0x45, 0x06, 0xc1, 0x19, 0xaa, 0xe0, 0x0c, 0x05, 0x76, 0x17, 0x98, 0xb4, 0xfa, 0x96, + 0x53, 0x98, 0xf5, 0xd5, 0xa0, 0xe2, 0xed, 0x82, 0xc9, 0x9b, 0xc3, 0xd9, 0x21, 0xb8, 0x87, 0x9f, 0x4d, 0xb3, 0x40, + 0x33, 0x2c, 0x84, 0x42, 0x78, 0xbf, 0xb5, 0xb9, 0x92, 0xbe, 0x54, 0x35, 0xc7, 0xfe, 0x00, 0xd6, 0xc1, 0x1c, 0x1b, + 0x09, 0x57, 0xe6, 0x6f, 0x6d, 0xab, 0x01, 0xd8, 0xae, 0x00, 0x33, 0x92, 0x71, 0x4e, 0x75, 0xdc, 0x3e, 0x6a, 0x01, + 0x63, 0xfa, 0x85, 0xc1, 0xa9, 0x82, 0xd0, 0xf6, 0x54, 0x58, 0xb2, 0x10, 0x6a, 0xca, 0xc7, 0x3a, 0xfe, 0x5d, 0x18, + 0xa2, 0xc2, 0x72, 0xc5, 0x40, 0xc2, 0x09, 0xd8, 0x63, 0x43, 0x70, 0x7e, 0x17, 0xd0, 0x4f, 0xb7, 0x3c, 0x88, 0xdc, + 0x48, 0x0d, 0xe1, 0x02, 0xf2, 0x50, 0xb1, 0xd6, 0x15, 0x99, 0x29, 0x19, 0x37, 0xe0, 0x1e, 0xdb, 0x3d, 0xdb, 0x62, + 0xea, 0xa8, 0x81, 0x08, 0x38, 0x58, 0x91, 0x86, 0x24, 0xc2, 0x25, 0xea, 0x44, 0xcb, 0x97, 0xf2, 0x86, 0x15, 0x8f, + 0x29, 0x0c, 0x3e, 0xb5, 0xd5, 0xd7, 0xf6, 0x28, 0x30, 0x14, 0x5f, 0x77, 0x3d, 0xbe, 0x5c, 0x9b, 0x89, 0xbf, 0x29, + 0xe4, 0x8c, 0x2b, 0x06, 0x7c, 0x9b, 0x85, 0xbf, 0x80, 0x8d, 0x66, 0x76, 0x24, 0x1c, 0x37, 0xac, 0xc4, 0xaf, 0x87, + 0x2f, 0xeb, 0xf8, 0x75, 0x7d, 0xef, 0xe9, 0xc4, 0x53, 0xc0, 0xfa, 0x3e, 0x46, 0x38, 0x76, 0xe2, 0x45, 0x70, 0xd2, + 0x25, 0x53, 0xe4, 0x8e, 0xf9, 0xd5, 0x4a, 0x07, 0x62, 0x5c, 0x8d, 0x73, 0x64, 0x76, 0xdb, 0xa0, 0x35, 0x1d, 0x8d, + 0x80, 0xc5, 0x2b, 0x64, 0x9e, 0x07, 0x87, 0x15, 0x16, 0xdd, 0xf2, 0x78, 0xba, 0xbe, 0xf7, 0xf4, 0xea, 0x7b, 0x27, + 0x14, 0xe4, 0x87, 0x87, 0x94, 0x1f, 0xa8, 0x18, 0xb1, 0x02, 0xe4, 0xca, 0x60, 0xb5, 0xdc, 0x39, 0xfb, 0x58, 0x0a, + 0xc1, 0x32, 0xcd, 0x46, 0x20, 0xb4, 0x08, 0xa2, 0x93, 0xa9, 0x54, 0xba, 0x4c, 0xac, 0x46, 0x2f, 0x42, 0x21, 0x34, + 0xc9, 0x68, 0x9e, 0xc7, 0x56, 0x40, 0x99, 0xc9, 0x2f, 0x6c, 0xc7, 0xa8, 0xbb, 0xb5, 0x21, 0x97, 0xcd, 0xb0, 0xa0, + 0x19, 0x96, 0xa8, 0x79, 0xce, 0x33, 0x56, 0x1e, 0x5e, 0x57, 0x09, 0x17, 0x23, 0x76, 0x0b, 0x74, 0x04, 0x5d, 0x5e, + 0x5e, 0xb6, 0x70, 0x1b, 0xad, 0x2d, 0xc0, 0x97, 0x5b, 0x80, 0xfd, 0xce, 0xb1, 0x69, 0x05, 0xf1, 0xe5, 0x4e, 0xb2, + 0x86, 0x82, 0xb3, 0x92, 0x7b, 0x41, 0xcb, 0x92, 0x67, 0x84, 0x47, 0x2c, 0x67, 0x9a, 0x79, 0x72, 0x0e, 0xcc, 0xb4, + 0xdd, 0xba, 0x6f, 0x4b, 0xf8, 0x95, 0xe8, 0xe4, 0x77, 0x99, 0x5f, 0x73, 0x55, 0x8a, 0xee, 0xd5, 0xf2, 0x54, 0xd0, + 0xee, 0x69, 0xbb, 0x3c, 0x54, 0x6b, 0x9a, 0x4d, 0xad, 0xc4, 0x1e, 0x6f, 0x4d, 0xa9, 0x6a, 0xc3, 0x91, 0xf6, 0x72, + 0x13, 0xfd, 0x59, 0xb8, 0x61, 0xee, 0x02, 0xc1, 0x95, 0x23, 0x0a, 0x0c, 0x84, 0x40, 0xbb, 0x6c, 0x8f, 0x69, 0x9e, + 0x0f, 0x69, 0xf6, 0xb9, 0x8e, 0xfd, 0x15, 0x1a, 0x90, 0x4d, 0x6a, 0x1c, 0x64, 0x05, 0x24, 0x2b, 0x9c, 0xb7, 0xa7, + 0xd2, 0xb5, 0x8d, 0x12, 0xef, 0xb7, 0x2a, 0xb4, 0xaf, 0x2f, 0xf4, 0x37, 0xb1, 0xdd, 0x8c, 0x48, 0xb8, 0x99, 0xc5, + 0x40, 0x05, 0xfe, 0x25, 0xc6, 0x79, 0x7a, 0xe0, 0xf0, 0x0e, 0x04, 0x8f, 0xf5, 0xc6, 0x40, 0x34, 0x5a, 0xae, 0x47, + 0x5c, 0x7d, 0x1b, 0x02, 0xff, 0x5b, 0x46, 0xf9, 0x24, 0xe8, 0xe1, 0xdf, 0x1d, 0x68, 0x49, 0xe3, 0x1c, 0xe3, 0x5c, + 0x8e, 0xcc, 0x31, 0x14, 0x9e, 0xd0, 0xfc, 0x02, 0xcc, 0x8b, 0xc1, 0xf7, 0xd7, 0x36, 0xcb, 0xf0, 0x65, 0x30, 0x0c, + 0xd5, 0x0d, 0x19, 0x8a, 0x1a, 0x0a, 0x38, 0xa2, 0x2a, 0xcc, 0x99, 0x2b, 0x6b, 0xa2, 0xa4, 0xe3, 0xda, 0xad, 0x38, + 0xee, 0x68, 0x6e, 0x41, 0xe2, 0x38, 0x56, 0x20, 0xcd, 0x79, 0xfe, 0xbe, 0x9a, 0x85, 0xda, 0x9a, 0x85, 0x4a, 0x02, + 0x69, 0x0b, 0x55, 0xc8, 0x1c, 0x54, 0x4f, 0xb5, 0x40, 0x61, 0x29, 0x60, 0x59, 0x13, 0xa0, 0xd0, 0xa8, 0x24, 0xb8, + 0x39, 0xd1, 0xb8, 0x70, 0xa2, 0x8e, 0xc3, 0x35, 0x20, 0x19, 0x55, 0x15, 0x89, 0xec, 0xe6, 0xa8, 0xc9, 0xbe, 0x12, + 0x17, 0x68, 0x83, 0xbf, 0x5f, 0xaf, 0x1d, 0x94, 0x18, 0x72, 0xab, 0x53, 0x63, 0x8c, 0x03, 0xb0, 0x60, 0x49, 0x1c, + 0x33, 0x6c, 0x59, 0x9f, 0x4d, 0xe0, 0x94, 0xed, 0xee, 0x13, 0x22, 0x2b, 0xd8, 0xd4, 0x98, 0x4a, 0xcf, 0x5d, 0x49, + 0x84, 0xa9, 0x67, 0x4b, 0x8b, 0x6a, 0xe2, 0x84, 0x44, 0x5e, 0x3b, 0x11, 0xf5, 0x96, 0x35, 0xe1, 0x30, 0x0d, 0x8a, + 0xad, 0x53, 0x20, 0xaa, 0xc5, 0x2e, 0x78, 0xef, 0xc2, 0x9a, 0x5a, 0x3b, 0x01, 0xc4, 0x8b, 0x1a, 0xc4, 0x03, 0xd0, + 0x4a, 0x4b, 0xbc, 0xe4, 0x80, 0xd0, 0x7a, 0xe5, 0x98, 0xe1, 0xc2, 0x2e, 0xc4, 0x16, 0x14, 0x37, 0xd9, 0x4f, 0x83, + 0x85, 0x20, 0xcb, 0x2a, 0xe0, 0xef, 0xc2, 0x23, 0x22, 0x86, 0xc1, 0x8b, 0xd5, 0x6a, 0x0b, 0xed, 0x76, 0x72, 0xa1, + 0x28, 0xa9, 0xa4, 0xc3, 0xd5, 0xea, 0xab, 0x44, 0xb1, 0xe3, 0x7f, 0x31, 0x43, 0x3d, 0x4f, 0x74, 0x1f, 0xbe, 0x84, + 0x52, 0x86, 0x1d, 0xad, 0x52, 0x4a, 0xc1, 0xa1, 0x8e, 0xb5, 0xf5, 0x85, 0xd2, 0x01, 0xe5, 0x7e, 0xbc, 0x45, 0xc0, + 0x4c, 0xa2, 0x3b, 0xa9, 0xab, 0x29, 0x3f, 0x76, 0x4d, 0x0b, 0x84, 0x50, 0xaa, 0x8c, 0x2c, 0xb3, 0xbf, 0x4b, 0xbe, + 0x3c, 0x38, 0x50, 0x41, 0x43, 0xd7, 0x25, 0xa5, 0xf8, 0x3b, 0x86, 0x53, 0x59, 0xdd, 0x09, 0xc3, 0xbe, 0xfc, 0xed, + 0xcf, 0xa1, 0x2d, 0xe9, 0xb4, 0xd5, 0x05, 0xc1, 0x9c, 0xde, 0x50, 0xae, 0xf7, 0xca, 0x56, 0xac, 0x60, 0x1e, 0x33, + 0xb4, 0x74, 0xdc, 0x46, 0x52, 0x30, 0xe0, 0x1f, 0x81, 0x2c, 0x78, 0x2e, 0xda, 0x22, 0x7e, 0x36, 0x65, 0xa0, 0xca, + 0xf6, 0x8c, 0x44, 0x29, 0x1e, 0xee, 0xbb, 0x83, 0xc4, 0x35, 0xbc, 0x7b, 0xec, 0xeb, 0xcd, 0xea, 0x35, 0x69, 0x60, + 0xce, 0x8a, 0xb1, 0x2c, 0x66, 0x3e, 0x6f, 0xbd, 0xf1, 0xed, 0x88, 0x23, 0x1f, 0xc7, 0x3b, 0xdb, 0x76, 0x22, 0x40, + 0x77, 0x43, 0xf6, 0xae, 0xa4, 0xf6, 0xda, 0x69, 0x5a, 0x1e, 0xc0, 0x56, 0x41, 0xe8, 0x31, 0x53, 0x85, 0x52, 0xbe, + 0x53, 0xaf, 0x76, 0xad, 0xee, 0x64, 0xbf, 0xdd, 0x2d, 0x25, 0x3f, 0x8f, 0x0d, 0x5d, 0xab, 0xe3, 0x70, 0xa7, 0xaa, + 0x5c, 0xe4, 0x23, 0x37, 0x58, 0x81, 0x30, 0x73, 0x78, 0x74, 0xc3, 0xf3, 0xbc, 0x4a, 0xfd, 0x4f, 0x48, 0xbb, 0x72, + 0xa4, 0x5d, 0x7a, 0xd2, 0x0e, 0xa4, 0x02, 0x48, 0xbb, 0x6d, 0xae, 0xaa, 0x2e, 0xb7, 0xb6, 0xa7, 0xb4, 0x44, 0x5d, + 0x19, 0x71, 0x1a, 0xfa, 0x5b, 0xf8, 0x11, 0xa0, 0x92, 0xf9, 0xfa, 0x1c, 0x3b, 0x7d, 0x0c, 0x88, 0x81, 0x56, 0xa7, + 0xc9, 0x42, 0x4d, 0xc5, 0xe7, 0x18, 0x61, 0xb5, 0x66, 0x25, 0x66, 0x3f, 0x7c, 0x0a, 0x4a, 0xbb, 0x60, 0x3a, 0x70, + 0x8e, 0x99, 0xe4, 0xff, 0x88, 0x8f, 0xf2, 0xb3, 0x13, 0x6e, 0x76, 0xca, 0xcf, 0x0e, 0x68, 0x7d, 0x35, 0xbb, 0xd1, + 0xf7, 0xa9, 0xbd, 0x99, 0x9e, 0x28, 0xa7, 0x57, 0xad, 0xf7, 0x6a, 0x15, 0x6f, 0xa4, 0x80, 0x46, 0xdf, 0x49, 0x29, + 0x45, 0xd9, 0x3a, 0xd0, 0x80, 0x10, 0x32, 0x90, 0xb0, 0xb6, 0x93, 0x2e, 0x4f, 0xb9, 0x97, 0xff, 0x4a, 0xcf, 0x63, + 0x14, 0xf7, 0xb6, 0xfe, 0x63, 0x39, 0x9b, 0x03, 0x43, 0xb6, 0x81, 0xd2, 0x13, 0xe6, 0x3a, 0xac, 0xf2, 0xd7, 0x3b, + 0xd2, 0x6a, 0x75, 0xcc, 0x7e, 0xac, 0x61, 0x53, 0x29, 0x35, 0xef, 0xb7, 0xd6, 0x8b, 0x32, 0xa9, 0x24, 0x1c, 0xbb, + 0x74, 0x2b, 0x8f, 0x37, 0x35, 0x33, 0x3e, 0xe3, 0x75, 0x2c, 0x2c, 0x1d, 0x16, 0x40, 0xeb, 0x02, 0xf2, 0xe3, 0xd1, + 0x3d, 0x5c, 0xff, 0x75, 0x05, 0x9c, 0xe5, 0x7a, 0x03, 0x7c, 0xcb, 0xf5, 0xfa, 0x91, 0x76, 0x92, 0x36, 0x7e, 0xb4, + 0x43, 0xee, 0x2d, 0xa1, 0x57, 0x65, 0x3a, 0x99, 0xb1, 0x3f, 0x80, 0xb4, 0x2d, 0x16, 0x92, 0x2c, 0x67, 0x72, 0xc4, + 0xd2, 0x48, 0xce, 0x99, 0x88, 0xd6, 0xa0, 0x67, 0x75, 0x08, 0xf0, 0x8f, 0x88, 0x97, 0x6f, 0xeb, 0xfa, 0xd6, 0xf4, + 0x91, 0x5e, 0x83, 0x2a, 0xec, 0x25, 0xdf, 0xa1, 0x8c, 0x7d, 0xcf, 0x0a, 0x65, 0x78, 0xd2, 0x92, 0xbd, 0x7d, 0xc9, + 0xab, 0x03, 0xea, 0x25, 0x4f, 0xbf, 0x5d, 0xa5, 0x12, 0x48, 0xa2, 0x76, 0x72, 0x96, 0x1c, 0x47, 0xc8, 0x68, 0x8c, + 0x9f, 0x79, 0x8d, 0xf1, 0xa2, 0xd4, 0x18, 0x3f, 0xd7, 0x64, 0xb1, 0xa1, 0x31, 0xfe, 0x43, 0x90, 0xe7, 0xba, 0xf7, + 0xdc, 0x6b, 0xd3, 0xdf, 0xc8, 0x9c, 0x67, 0x77, 0x71, 0x94, 0x73, 0xdd, 0x84, 0xdb, 0xc4, 0x08, 0x2f, 0x6d, 0x06, + 0xa8, 0x1a, 0x8d, 0xbe, 0x7b, 0xed, 0xe5, 0x3f, 0x2c, 0x04, 0x89, 0xee, 0xe5, 0x5c, 0xdf, 0x8b, 0xf0, 0x54, 0x93, + 0x4f, 0xf0, 0xeb, 0xde, 0x32, 0xfe, 0x95, 0xea, 0x69, 0x52, 0x50, 0x31, 0x92, 0xb3, 0x18, 0x35, 0xa2, 0x08, 0x25, + 0xca, 0x08, 0x21, 0x0f, 0xd0, 0xfa, 0xde, 0x27, 0xfc, 0x4a, 0x92, 0xa8, 0x17, 0x35, 0xa6, 0x1a, 0x6b, 0x4a, 0x3e, + 0x5d, 0xdc, 0x5b, 0xbe, 0x92, 0xeb, 0xcb, 0x4f, 0xf8, 0xa9, 0x2e, 0xd5, 0xfa, 0xf8, 0x96, 0x91, 0x18, 0x91, 0xcb, + 0xa7, 0x7e, 0x48, 0x8f, 0xe5, 0xcc, 0x2a, 0xf8, 0x23, 0x84, 0xbf, 0x80, 0x5e, 0xf7, 0x92, 0x57, 0x44, 0xc8, 0xdd, + 0xc1, 0xec, 0x93, 0x48, 0x1a, 0xe5, 0x41, 0x74, 0x70, 0x10, 0xa4, 0x95, 0x2c, 0x04, 0xfe, 0x5b, 0x92, 0x9a, 0xa8, + 0x8e, 0x19, 0x85, 0x96, 0xfe, 0x96, 0x31, 0x47, 0xbe, 0x99, 0xd8, 0x6b, 0xaa, 0xdd, 0x8e, 0xe5, 0x7d, 0xab, 0x7b, + 0x48, 0xb8, 0x66, 0x05, 0xd5, 0xb2, 0x18, 0xa0, 0x90, 0x2d, 0xc1, 0x5f, 0x39, 0xf9, 0xd4, 0xdf, 0xfb, 0x7f, 0xfe, + 0xc7, 0x5f, 0xe3, 0xbf, 0x8a, 0xc1, 0x27, 0x2c, 0x18, 0x39, 0xba, 0x88, 0x7b, 0x69, 0xbc, 0xdf, 0x6c, 0xae, 0xfe, + 0x3a, 0xea, 0xff, 0x37, 0x6d, 0x7e, 0x7d, 0xd8, 0xfc, 0x73, 0x80, 0x56, 0xf1, 0x5f, 0x47, 0xbd, 0xbe, 0xfb, 0xea, + 0xff, 0xf7, 0xe5, 0x5f, 0x6a, 0x70, 0x68, 0x13, 0xef, 0x21, 0x74, 0x34, 0xc1, 0xbf, 0x08, 0x72, 0xd4, 0x6c, 0x5e, + 0x1e, 0x4d, 0xf0, 0x4f, 0x82, 0x1c, 0xc1, 0xdf, 0x3b, 0x4d, 0xde, 0xb2, 0xc9, 0xd3, 0xdb, 0x79, 0xfc, 0xe9, 0x72, + 0x75, 0x6f, 0xf9, 0x95, 0xaf, 0xa1, 0xdd, 0xfe, 0x7f, 0xff, 0xf5, 0x97, 0x8a, 0x7e, 0xbc, 0x24, 0x47, 0x83, 0x06, + 0x8a, 0x4d, 0xf2, 0x21, 0xb1, 0x7f, 0xe2, 0x5e, 0xda, 0xff, 0x6f, 0x37, 0x94, 0xe8, 0xc7, 0xbf, 0x3e, 0x5d, 0x5c, + 0x92, 0xc1, 0x2a, 0x8e, 0x56, 0x3f, 0xa2, 0x15, 0x42, 0xab, 0x7b, 0xe8, 0x13, 0x8e, 0x26, 0x11, 0xc2, 0xbf, 0x09, + 0x72, 0xf4, 0xe3, 0xd1, 0x04, 0xff, 0x29, 0xc8, 0x51, 0x74, 0x34, 0xc1, 0xef, 0x25, 0x39, 0xfa, 0xef, 0xb8, 0x97, + 0x5a, 0x25, 0xdc, 0xca, 0xa8, 0x3f, 0x56, 0x70, 0x13, 0x42, 0x0b, 0x46, 0x57, 0x9a, 0xeb, 0x9c, 0xa1, 0x7b, 0x47, + 0x1c, 0x3f, 0x92, 0x00, 0xac, 0x58, 0x83, 0x92, 0xc6, 0x5c, 0xc2, 0x2e, 0xaf, 0x61, 0xe1, 0x01, 0x83, 0xee, 0xa5, + 0x1c, 0x5b, 0x3d, 0x81, 0x4a, 0xb5, 0xbd, 0xbd, 0x55, 0x70, 0x7d, 0x8b, 0x1f, 0x93, 0x47, 0x32, 0x6e, 0x23, 0xcc, + 0x29, 0xfc, 0xe8, 0x20, 0xfc, 0x41, 0xbb, 0x0b, 0x4f, 0xd8, 0xe6, 0x16, 0xc3, 0x84, 0xb4, 0xfc, 0x4c, 0x84, 0xf0, + 0xcb, 0x1d, 0x99, 0x7a, 0x0a, 0xea, 0x07, 0x84, 0x7f, 0xae, 0x5d, 0x8f, 0xe2, 0xc7, 0x9a, 0x94, 0xc8, 0xf1, 0xae, + 0x60, 0xec, 0x03, 0xcd, 0x3f, 0xb3, 0x22, 0x7e, 0xaa, 0x71, 0xbb, 0xf3, 0x00, 0x1b, 0x55, 0xf5, 0x7e, 0x1b, 0x75, + 0xcb, 0xdb, 0xad, 0xe7, 0xd2, 0xde, 0x27, 0xc0, 0x29, 0x5c, 0xd7, 0xd7, 0xc0, 0xda, 0xef, 0xf3, 0x2d, 0xa5, 0x56, + 0x41, 0x6f, 0x22, 0x54, 0xbf, 0x4a, 0xe5, 0xe2, 0x0b, 0xcd, 0xf9, 0x68, 0x4f, 0xb3, 0xd9, 0x3c, 0xa7, 0x9a, 0xed, + 0xb9, 0x39, 0xef, 0x51, 0x68, 0x28, 0x2a, 0x79, 0x8a, 0x3f, 0x44, 0xb5, 0x69, 0xff, 0x10, 0x49, 0xb5, 0x77, 0x62, + 0xb8, 0xcf, 0x72, 0x7c, 0x89, 0xa0, 0xe5, 0x75, 0xd9, 0xe6, 0x8d, 0x60, 0xb3, 0x0d, 0xca, 0xb2, 0x81, 0x39, 0xbf, + 0x15, 0x86, 0xfb, 0x4d, 0x42, 0x3a, 0xbd, 0xe8, 0x42, 0x7d, 0x99, 0x5c, 0x46, 0x70, 0x93, 0x53, 0x10, 0xc1, 0x8c, + 0xf2, 0x08, 0x4a, 0x50, 0xd2, 0xea, 0xd2, 0x0b, 0xd6, 0xa5, 0x8d, 0x86, 0x67, 0xb3, 0x33, 0xc2, 0xfb, 0xd4, 0xd6, + 0xcf, 0xf1, 0x14, 0x8f, 0x48, 0xb3, 0x8d, 0x17, 0xa4, 0x65, 0xaa, 0x74, 0x17, 0x17, 0x99, 0xeb, 0xe7, 0xe0, 0x20, + 0x2e, 0x92, 0x9c, 0x2a, 0xfd, 0x02, 0x34, 0x02, 0x64, 0x81, 0xa7, 0xa4, 0x48, 0xd8, 0x2d, 0xcb, 0xe2, 0x0c, 0xe1, + 0xa9, 0xa3, 0x41, 0xa8, 0x8b, 0x16, 0x24, 0x28, 0x06, 0x72, 0x06, 0x11, 0xac, 0x37, 0xed, 0xb7, 0x07, 0x84, 0x90, + 0x68, 0xbf, 0xd9, 0x8c, 0x7a, 0x05, 0xf9, 0x45, 0xa4, 0x90, 0x12, 0xb0, 0xd3, 0xe4, 0x27, 0x48, 0xea, 0x04, 0x49, + 0xf1, 0x7b, 0x99, 0x68, 0xa6, 0x74, 0x0c, 0xc9, 0xa0, 0x24, 0x50, 0x1e, 0xc3, 0xa3, 0x8b, 0xa3, 0xa8, 0x01, 0xa9, + 0x06, 0x45, 0x11, 0x2e, 0xc8, 0x9d, 0x46, 0xe9, 0xb4, 0x7f, 0x3c, 0x08, 0xcf, 0x08, 0x9b, 0x0a, 0xfd, 0xdf, 0xe9, + 0xde, 0xb4, 0xdf, 0x32, 0xfd, 0x5f, 0x46, 0xbd, 0xb8, 0x20, 0xca, 0xb2, 0x71, 0x3d, 0x95, 0x0a, 0x66, 0xe6, 0x8b, + 0x52, 0x37, 0x40, 0xd7, 0xf7, 0x88, 0x34, 0x3b, 0x69, 0x3c, 0x0a, 0x67, 0xd2, 0x84, 0x0e, 0x1d, 0x28, 0x70, 0x4e, + 0xa0, 0x3c, 0x2e, 0x08, 0x74, 0x5a, 0x55, 0xbb, 0xd3, 0xa9, 0x4b, 0xf8, 0x31, 0xfa, 0xb1, 0xf7, 0xa7, 0x48, 0x7f, + 0x13, 0x76, 0x04, 0x7f, 0x8a, 0xd5, 0x0a, 0xfe, 0xfe, 0x26, 0x7a, 0x30, 0x2c, 0x93, 0xf6, 0x8b, 0x4b, 0xfb, 0x09, + 0xd2, 0x04, 0x4b, 0xcd, 0x80, 0xb1, 0x2a, 0xf9, 0x31, 0xbb, 0x38, 0x63, 0x62, 0x67, 0x70, 0x70, 0xc0, 0xfb, 0xb4, + 0xd1, 0x1e, 0xc0, 0x8d, 0x40, 0xa1, 0xd5, 0x07, 0xae, 0xa7, 0x71, 0x74, 0x74, 0x19, 0xa1, 0x5e, 0xb4, 0x07, 0xab, + 0xdc, 0x95, 0x0d, 0xe2, 0x60, 0x9d, 0x35, 0x34, 0x4d, 0x47, 0x97, 0xa4, 0xd5, 0x8b, 0x85, 0x25, 0xf2, 0x39, 0xc2, + 0x99, 0xa3, 0xa9, 0x2d, 0x3c, 0x42, 0x0d, 0x21, 0x1a, 0xfe, 0x7b, 0x84, 0x1a, 0x53, 0xdd, 0x18, 0xa3, 0x34, 0x83, + 0xbf, 0xf1, 0x88, 0x10, 0xd2, 0xec, 0x94, 0x15, 0xfd, 0x61, 0x49, 0x51, 0x3a, 0xf6, 0xea, 0xd1, 0xbe, 0xd9, 0x1c, + 0xb2, 0x11, 0xf3, 0x3e, 0x1b, 0xac, 0x56, 0xd1, 0x45, 0xef, 0x32, 0x42, 0x8d, 0xd8, 0xa3, 0xdd, 0x91, 0xc7, 0x3b, + 0x84, 0xb0, 0x18, 0xac, 0xdd, 0x0d, 0xd4, 0x0d, 0xab, 0xdd, 0x36, 0x2d, 0xab, 0xfd, 0x1f, 0x90, 0x05, 0xb6, 0x2e, + 0xe5, 0x1e, 0xcb, 0xdf, 0xce, 0x61, 0xaa, 0x1e, 0xb7, 0x25, 0x69, 0xe1, 0x82, 0x78, 0x75, 0x37, 0x25, 0xba, 0xc2, + 0xff, 0x8c, 0x54, 0xc5, 0x71, 0x3f, 0xc7, 0xd3, 0x01, 0x11, 0xd4, 0xc8, 0x2f, 0x5d, 0xaf, 0x4c, 0x67, 0x39, 0xb9, + 0x61, 0x1b, 0xf7, 0xbf, 0x39, 0xdc, 0xc9, 0x3c, 0xd6, 0x49, 0xb6, 0x28, 0x0a, 0x26, 0xf4, 0x2b, 0x39, 0x72, 0x8c, + 0x1d, 0xcb, 0x41, 0xb6, 0x82, 0x8b, 0x5d, 0x0c, 0x5c, 0x5d, 0xc7, 0xef, 0x94, 0xd1, 0x56, 0xf6, 0x82, 0x8c, 0x2c, + 0xc3, 0x65, 0xae, 0x7b, 0xbb, 0x0b, 0x27, 0x4a, 0xc7, 0x08, 0x8f, 0xdc, 0x3d, 0x70, 0x9c, 0x24, 0xc9, 0x22, 0xc9, + 0x20, 0x1b, 0x3a, 0x50, 0x68, 0x6d, 0xf6, 0x55, 0xac, 0xc8, 0x63, 0x9d, 0x08, 0x76, 0x6b, 0xba, 0x8d, 0x51, 0x75, + 0x88, 0xfb, 0xfd, 0x76, 0x41, 0xbb, 0x86, 0x00, 0xa9, 0x44, 0xc8, 0x11, 0x03, 0x08, 0xc1, 0xdd, 0xbf, 0x4b, 0x9a, + 0x52, 0x15, 0xde, 0x6c, 0x55, 0x03, 0xec, 0x87, 0x2a, 0xef, 0x05, 0xe8, 0x89, 0x0d, 0x7b, 0x56, 0x16, 0xb6, 0xca, + 0x73, 0x84, 0xf8, 0x38, 0x5e, 0x24, 0x70, 0x23, 0x68, 0x30, 0x49, 0x08, 0xb4, 0x5a, 0x2d, 0x42, 0xdc, 0x9a, 0x56, + 0x8a, 0xe9, 0x31, 0x99, 0xf6, 0x8b, 0x46, 0xc3, 0x28, 0xaf, 0x47, 0x16, 0x2f, 0x16, 0x08, 0x8f, 0xcb, 0xbd, 0xe6, + 0xcb, 0xcd, 0x49, 0xbd, 0xab, 0x78, 0x5c, 0x57, 0x02, 0x37, 0x84, 0x40, 0x46, 0xbf, 0xa8, 0xa1, 0x75, 0x3c, 0x21, + 0x47, 0x71, 0x3f, 0xe9, 0xfd, 0xcf, 0x01, 0xea, 0xc5, 0xc9, 0x21, 0x3a, 0xb2, 0xb4, 0x64, 0x8c, 0xba, 0x99, 0xed, + 0x63, 0x69, 0x6e, 0x3f, 0xdb, 0xd8, 0x28, 0x20, 0x53, 0x89, 0x05, 0x9d, 0xb1, 0x74, 0x02, 0xbb, 0xde, 0x23, 0xcf, + 0x1c, 0x03, 0x32, 0xa5, 0x13, 0x47, 0x5b, 0x92, 0xa8, 0x27, 0x69, 0xf9, 0xd5, 0x8b, 0x7a, 0xb4, 0xfa, 0xfa, 0x9f, + 0x51, 0x2f, 0xa3, 0xe9, 0x63, 0xbe, 0x76, 0x4a, 0xf2, 0x5a, 0x1f, 0x67, 0xbe, 0x8f, 0xb5, 0x5d, 0x9c, 0x00, 0x78, + 0x23, 0xb4, 0xad, 0x1d, 0x59, 0xa0, 0x35, 0x1f, 0x97, 0xd4, 0x49, 0x25, 0x9a, 0x4e, 0x00, 0xaa, 0xc1, 0x22, 0xa8, + 0xd0, 0x36, 0x20, 0x98, 0x32, 0x60, 0x8b, 0x47, 0x5a, 0x80, 0xe6, 0xe2, 0xb2, 0x85, 0x96, 0xb5, 0xc2, 0x8e, 0xb3, + 0xaa, 0xdf, 0xc5, 0x97, 0xc4, 0x7b, 0x0c, 0x54, 0xf9, 0x62, 0xd1, 0x1d, 0x37, 0x1a, 0x48, 0x79, 0xfc, 0x1a, 0xf5, + 0xc7, 0x03, 0x7c, 0x0b, 0x28, 0x84, 0x6b, 0x18, 0x85, 0x6b, 0x73, 0xec, 0xb8, 0x39, 0x36, 0x1a, 0x72, 0x8d, 0xba, + 0x41, 0xe5, 0x85, 0xab, 0xbc, 0x5e, 0x5b, 0xc8, 0x6c, 0x62, 0xdc, 0x39, 0x32, 0x29, 0x60, 0x08, 0x46, 0x08, 0x79, + 0x25, 0xd1, 0xce, 0x66, 0xa1, 0x51, 0xa8, 0x6e, 0x76, 0x2f, 0x50, 0x54, 0x7b, 0x7a, 0xc4, 0x00, 0x0b, 0xa8, 0x5a, + 0xaa, 0x91, 0xa7, 0x1a, 0x8f, 0x1a, 0x6d, 0x83, 0xee, 0xcd, 0x76, 0xb7, 0xde, 0xd8, 0xfd, 0xaa, 0x31, 0x3c, 0x6a, + 0x90, 0x69, 0xb5, 0xc3, 0xd7, 0xb2, 0xd1, 0x58, 0xd7, 0xef, 0x4b, 0xfd, 0x26, 0xae, 0xdd, 0x5f, 0x3c, 0xdd, 0x32, + 0xf1, 0xf0, 0xa7, 0x6f, 0x75, 0xde, 0x8a, 0x84, 0x0b, 0xc1, 0x0a, 0x38, 0x61, 0x89, 0xc6, 0x62, 0xbd, 0x2e, 0x4f, + 0xfd, 0xdf, 0xb5, 0xb5, 0x19, 0x23, 0x1c, 0xe8, 0x90, 0x91, 0xda, 0xb0, 0xc4, 0x05, 0xa6, 0x86, 0x8a, 0x10, 0x42, + 0x3e, 0x68, 0x6f, 0x1e, 0xa3, 0x0d, 0x49, 0xca, 0x48, 0x70, 0x76, 0xc7, 0x8a, 0xb0, 0xe4, 0xfa, 0xde, 0x63, 0xf9, + 0x5d, 0x91, 0xae, 0x2f, 0x06, 0xa9, 0x29, 0x96, 0x3b, 0x42, 0x96, 0x93, 0x2f, 0x20, 0xe7, 0x94, 0x17, 0x2c, 0x89, + 0x21, 0x88, 0x4f, 0x78, 0xc1, 0x0c, 0xe3, 0x7e, 0xcf, 0xcb, 0x8d, 0x59, 0x9d, 0xd3, 0xcc, 0x42, 0xed, 0x0f, 0x40, + 0x33, 0x07, 0xe5, 0x90, 0x24, 0x5b, 0xc5, 0xae, 0xef, 0x3d, 0x7c, 0xbd, 0x4b, 0x86, 0x5e, 0xad, 0x9c, 0xf4, 0x9c, + 0x01, 0xeb, 0x83, 0xf3, 0x6a, 0xa8, 0x99, 0xfb, 0x91, 0xc6, 0x99, 0x61, 0xa2, 0xf2, 0x98, 0x03, 0x32, 0x5d, 0xdf, + 0x7b, 0xf8, 0x2e, 0xe6, 0x46, 0x37, 0x85, 0x70, 0x38, 0xef, 0xb8, 0x20, 0x31, 0x25, 0x0c, 0xd9, 0xc9, 0x97, 0x74, + 0xac, 0x08, 0x4e, 0xf7, 0x94, 0x9a, 0x4c, 0x10, 0x3b, 0xfa, 0x62, 0x40, 0x32, 0x07, 0x02, 0x92, 0x21, 0x9c, 0xd5, + 0xe4, 0x3a, 0x62, 0xd6, 0xc0, 0x74, 0x76, 0x05, 0x8b, 0x91, 0x58, 0xf6, 0x10, 0xe1, 0xcc, 0x74, 0xab, 0xd7, 0xf6, + 0x38, 0x51, 0x74, 0xd3, 0xd0, 0xad, 0x92, 0x67, 0xdf, 0x83, 0xe0, 0xe5, 0x3f, 0x5e, 0xb9, 0xb6, 0xcb, 0x84, 0x27, + 0xde, 0x22, 0xed, 0xfa, 0xde, 0xc3, 0x5f, 0x9d, 0x51, 0xda, 0x9c, 0x7a, 0xf2, 0xbf, 0x25, 0xa3, 0x3e, 0xfc, 0x35, + 0xa9, 0x72, 0x4d, 0xe1, 0xeb, 0x7b, 0x0f, 0x7f, 0xdf, 0x55, 0x0c, 0xd2, 0xd7, 0x8b, 0x4a, 0x49, 0x60, 0xc6, 0xb7, + 0x64, 0x79, 0xba, 0x74, 0x67, 0x45, 0x2a, 0xd6, 0xd8, 0x9c, 0x50, 0xa9, 0x5a, 0x97, 0xba, 0x95, 0x27, 0x58, 0x12, + 0x73, 0x95, 0x54, 0x5f, 0x36, 0x87, 0xc6, 0x5c, 0x8a, 0xab, 0x4c, 0xce, 0xd9, 0x37, 0xee, 0x97, 0x9e, 0x6a, 0x94, + 0xf0, 0x19, 0x18, 0xe2, 0x98, 0xb1, 0x0b, 0xbc, 0xdf, 0x42, 0xdd, 0x8d, 0xf3, 0x4c, 0x1a, 0x44, 0x2d, 0xea, 0x87, + 0x0d, 0xa6, 0xa4, 0x85, 0x33, 0xd2, 0xc2, 0x39, 0x51, 0xfd, 0x96, 0x3d, 0x31, 0xba, 0x79, 0xd9, 0xb4, 0x3d, 0x77, + 0x60, 0xbb, 0xe7, 0x76, 0xdf, 0xda, 0x43, 0x79, 0xda, 0xcd, 0x8d, 0xfe, 0xd2, 0x1c, 0xf4, 0x53, 0x83, 0x1a, 0x4f, + 0x58, 0x5c, 0xe0, 0xc2, 0xb4, 0x7c, 0xc5, 0x87, 0x39, 0xd8, 0xa9, 0xc0, 0xcc, 0xb0, 0x46, 0x69, 0x59, 0xb6, 0xed, + 0xca, 0xe6, 0x89, 0x59, 0xab, 0x02, 0xe7, 0x09, 0x90, 0x72, 0x9c, 0x3b, 0xbb, 0x1e, 0xb5, 0x5d, 0xe5, 0xec, 0xe0, + 0x20, 0x76, 0x95, 0x68, 0x5c, 0xf8, 0xfc, 0xea, 0x06, 0xf0, 0xbd, 0xa5, 0x1a, 0x53, 0x64, 0x26, 0xd0, 0x68, 0x64, + 0x83, 0x35, 0xdd, 0x27, 0x24, 0xce, 0xeb, 0x50, 0xf4, 0xa3, 0x37, 0xcc, 0xe0, 0x06, 0x00, 0x1a, 0x8d, 0xf2, 0xba, + 0x77, 0x03, 0x62, 0x4f, 0x35, 0x96, 0xeb, 0x2f, 0x71, 0x69, 0x4d, 0xd4, 0xda, 0xb2, 0xc3, 0xf2, 0xa3, 0x40, 0x22, + 0xc4, 0x5d, 0xe1, 0xe7, 0x13, 0x6c, 0x0d, 0x01, 0xe5, 0x5e, 0x38, 0x1b, 0x08, 0x6c, 0xac, 0xb6, 0x5c, 0x21, 0x4f, + 0xda, 0x3a, 0x28, 0xf5, 0x85, 0xe0, 0x82, 0x0b, 0x0a, 0x35, 0xd6, 0x0e, 0xcb, 0x9f, 0xb0, 0x6d, 0x73, 0x4e, 0xac, + 0x90, 0xd3, 0x96, 0x99, 0x61, 0x18, 0x80, 0x75, 0x4a, 0xc0, 0x3c, 0x27, 0x2f, 0xbf, 0x8d, 0xfa, 0x0f, 0x03, 0xd4, + 0x7f, 0x44, 0x58, 0xb0, 0x0d, 0xac, 0xae, 0x24, 0x91, 0x4e, 0x41, 0xa1, 0x7c, 0xd6, 0xe3, 0x39, 0x01, 0x6d, 0x5c, + 0x1d, 0xaa, 0xb5, 0x2b, 0xca, 0x6f, 0x50, 0x96, 0x70, 0xa7, 0x18, 0x7d, 0x26, 0xf6, 0xf7, 0xc9, 0x71, 0x75, 0x41, + 0x07, 0x5d, 0xef, 0x52, 0x0e, 0x86, 0xa4, 0xf0, 0xe1, 0xef, 0xdf, 0xbf, 0x5b, 0x7d, 0x3c, 0xdf, 0xde, 0xc1, 0x81, + 0x59, 0x29, 0xcc, 0x3a, 0xd8, 0xc0, 0x75, 0x23, 0x53, 0xe8, 0xbf, 0xbc, 0x13, 0xaf, 0x53, 0xa1, 0x8d, 0xcd, 0xe8, + 0x8f, 0x43, 0x18, 0x6d, 0xbb, 0x6d, 0x4a, 0xb0, 0xa0, 0x59, 0xa0, 0x4b, 0xd6, 0xb8, 0x95, 0x16, 0xdf, 0x20, 0x23, + 0x0f, 0x4d, 0x01, 0x26, 0x46, 0xbb, 0xb3, 0x1f, 0xad, 0x1d, 0x9e, 0xd8, 0xa1, 0xa1, 0xa5, 0x21, 0x84, 0x16, 0xef, + 0x01, 0x73, 0xec, 0x11, 0x01, 0x20, 0x7a, 0x69, 0x20, 0x55, 0x81, 0x2c, 0x8a, 0x2a, 0x45, 0xfe, 0xf3, 0x7d, 0x42, + 0x5e, 0x56, 0x8a, 0xcc, 0xb7, 0x95, 0x31, 0x17, 0x20, 0x06, 0x4a, 0xe1, 0x22, 0xa1, 0x4c, 0xb0, 0x97, 0xa1, 0x1f, + 0xb4, 0x2f, 0x6f, 0xa4, 0xcd, 0xa4, 0xe2, 0xc6, 0x83, 0x9b, 0x52, 0xa3, 0xe2, 0xb3, 0xf9, 0x1e, 0x12, 0x1b, 0xb9, + 0xf7, 0x20, 0x97, 0x51, 0x33, 0x48, 0xf8, 0x7e, 0x67, 0x4a, 0xfb, 0x76, 0xd7, 0x9f, 0x37, 0x2d, 0x62, 0x36, 0xd6, + 0x25, 0xe1, 0x42, 0xb1, 0x42, 0x3f, 0x62, 0x63, 0x59, 0xc0, 0xfd, 0x47, 0x09, 0x16, 0xb4, 0xbe, 0x17, 0xe8, 0x00, + 0xcd, 0x04, 0x83, 0x4b, 0x87, 0x8d, 0x19, 0x9a, 0x5f, 0x9f, 0xcd, 0x1d, 0xf8, 0xf5, 0x66, 0xad, 0x97, 0x07, 0x07, + 0x5f, 0x58, 0x05, 0x28, 0x37, 0x4c, 0x33, 0x8c, 0x80, 0x78, 0x59, 0x2e, 0xc7, 0xdd, 0x0c, 0xdf, 0x8b, 0x2b, 0x95, + 0x81, 0x27, 0x1c, 0x21, 0x11, 0x7a, 0x4e, 0xf4, 0x7a, 0xb2, 0x49, 0xef, 0x9d, 0x36, 0x43, 0x84, 0x62, 0x0d, 0x90, + 0x7b, 0x90, 0xcb, 0xad, 0x92, 0x49, 0x55, 0xb6, 0xb6, 0xe5, 0x20, 0x1e, 0x03, 0xb8, 0x62, 0x23, 0xa4, 0x04, 0x68, + 0xb8, 0x5b, 0x68, 0x79, 0x2e, 0x81, 0xfd, 0xc7, 0x2a, 0x01, 0x91, 0x16, 0xd5, 0x36, 0x2e, 0x42, 0xd8, 0x9a, 0xfa, + 0x04, 0xc6, 0x09, 0x0f, 0x9f, 0xef, 0xd2, 0x50, 0x7b, 0xd4, 0x66, 0xe6, 0x0c, 0x82, 0x12, 0x12, 0x95, 0x15, 0x92, + 0x2f, 0xb1, 0x70, 0xdc, 0x9c, 0xbf, 0x87, 0x03, 0x52, 0xac, 0x68, 0x6c, 0xef, 0xb6, 0xe0, 0xf8, 0x28, 0x92, 0x45, + 0x5c, 0xeb, 0xba, 0x5b, 0x98, 0x6a, 0xd8, 0x81, 0x8e, 0x86, 0x70, 0x2a, 0xcc, 0x3d, 0xe1, 0xe3, 0x8a, 0xa4, 0xfe, + 0x6c, 0x4d, 0xb4, 0xb5, 0x27, 0x86, 0x95, 0x69, 0x4a, 0x30, 0xff, 0x9f, 0xad, 0xd5, 0x75, 0x59, 0x08, 0x33, 0x33, + 0x8c, 0x1b, 0xbb, 0x0a, 0x6c, 0x0d, 0x38, 0xb6, 0xfc, 0x5b, 0x06, 0x8b, 0xea, 0x95, 0xe2, 0xa6, 0xd3, 0x80, 0x09, + 0x78, 0x0b, 0xd6, 0x33, 0x9b, 0x5b, 0xff, 0xb9, 0x39, 0x18, 0x05, 0x56, 0x35, 0x02, 0x2f, 0x0d, 0x81, 0x47, 0xc0, + 0xb8, 0x79, 0xd3, 0xf2, 0x9e, 0x33, 0xa2, 0x11, 0xfe, 0xc4, 0x73, 0x78, 0x66, 0x59, 0xee, 0xad, 0x8f, 0x8d, 0x15, + 0x49, 0x05, 0x01, 0xdb, 0x22, 0xec, 0x88, 0xbc, 0x44, 0x58, 0x35, 0x1a, 0x5d, 0x75, 0xc1, 0x2a, 0xad, 0x4a, 0x35, + 0x4c, 0x01, 0xb7, 0xc4, 0x80, 0xf7, 0xb5, 0x13, 0x15, 0x0c, 0x09, 0xbc, 0xf5, 0xb7, 0x02, 0xf5, 0xfd, 0xc3, 0xb7, + 0x71, 0x48, 0xdf, 0xc2, 0xb2, 0xe5, 0x45, 0x2c, 0x4c, 0x29, 0xae, 0xee, 0x70, 0xde, 0x7c, 0xdf, 0x6c, 0x04, 0xc6, + 0xbd, 0xdf, 0xc6, 0x60, 0xe3, 0x86, 0xba, 0xda, 0x92, 0x86, 0x72, 0x13, 0x76, 0x51, 0x65, 0xef, 0x18, 0x76, 0xd6, + 0xd5, 0x95, 0xb4, 0xab, 0x89, 0x5a, 0xaf, 0x15, 0xab, 0x8c, 0x06, 0x36, 0x0c, 0x3b, 0xcd, 0x31, 0xb3, 0xad, 0xc0, + 0x7f, 0x3c, 0x27, 0x1a, 0x07, 0xc8, 0xfa, 0xe6, 0x5b, 0xd7, 0x29, 0xd5, 0x30, 0x61, 0x7b, 0xbb, 0xf3, 0xf1, 0x31, + 0xdf, 0x75, 0x3e, 0x62, 0xe9, 0xb6, 0xbe, 0x39, 0x1b, 0xdb, 0xff, 0xc6, 0xd9, 0xe8, 0xd4, 0xf6, 0xfe, 0x78, 0x04, + 0xee, 0xa4, 0x76, 0x3c, 0xd6, 0xd7, 0x94, 0x48, 0x2c, 0xdc, 0x72, 0x5c, 0x76, 0x56, 0x2b, 0xd1, 0x6f, 0x81, 0xda, + 0x29, 0x8a, 0xe0, 0x67, 0xdb, 0xfe, 0x0c, 0x48, 0xb2, 0xd5, 0x21, 0xc7, 0xa2, 0x14, 0x65, 0x50, 0x02, 0x06, 0xd4, + 0xb1, 0xb1, 0xf5, 0x32, 0x88, 0xed, 0x70, 0xc8, 0x61, 0x39, 0x11, 0xe5, 0xd5, 0x15, 0x8c, 0xd8, 0x1c, 0x1b, 0x4e, + 0xc0, 0x8c, 0x77, 0x5a, 0x15, 0x7a, 0xf1, 0xf3, 0x5f, 0x33, 0xa7, 0xb5, 0x23, 0xc6, 0x72, 0x12, 0x35, 0x2b, 0x06, + 0x37, 0x02, 0xc7, 0x30, 0xee, 0x1b, 0x09, 0xb5, 0x3a, 0xd5, 0x51, 0xed, 0x48, 0xc2, 0x2d, 0x50, 0xbb, 0xed, 0x9b, + 0x73, 0x69, 0xb5, 0xda, 0x79, 0xb0, 0xe0, 0x22, 0xc0, 0xed, 0xe7, 0x44, 0xd7, 0x48, 0x0a, 0x25, 0x4e, 0x82, 0xc2, + 0xb9, 0x41, 0x55, 0x4d, 0x64, 0xbf, 0x35, 0x00, 0x9e, 0xb4, 0x9b, 0x5d, 0xc8, 0x4a, 0x48, 0xce, 0x1a, 0x0d, 0x94, + 0x97, 0x1d, 0xd3, 0xbe, 0x68, 0x64, 0x03, 0xcc, 0x70, 0x66, 0x05, 0x16, 0x38, 0xbd, 0xe2, 0xbc, 0xea, 0xba, 0x9f, + 0x0d, 0x10, 0x2e, 0x56, 0xab, 0xd8, 0x0e, 0x2d, 0x47, 0xab, 0x55, 0x1e, 0x0e, 0xcd, 0xe4, 0x43, 0xc5, 0x97, 0x3d, + 0x4d, 0x5e, 0x9a, 0xf3, 0xf0, 0x25, 0x0c, 0xb2, 0x41, 0xe2, 0xdc, 0xa9, 0x04, 0x73, 0xd0, 0x5c, 0x35, 0x64, 0x3f, + 0x6b, 0xb4, 0x07, 0x01, 0x0d, 0xeb, 0x67, 0x03, 0x92, 0xaf, 0xc1, 0x72, 0x56, 0xb9, 0x03, 0xf3, 0x6f, 0x38, 0xd8, + 0xfe, 0x36, 0xe7, 0x8c, 0x6d, 0x30, 0x5c, 0x93, 0x4d, 0x95, 0x41, 0x89, 0x57, 0x6e, 0x71, 0x7d, 0xb9, 0x9a, 0x81, + 0x45, 0x59, 0x08, 0xbb, 0x6b, 0xe6, 0x1e, 0x08, 0xff, 0x25, 0xb6, 0x4b, 0x5a, 0x1a, 0x71, 0x6f, 0x20, 0xbe, 0xb7, + 0xdd, 0x4e, 0x92, 0x84, 0x16, 0x13, 0x73, 0x25, 0xe2, 0x6f, 0x78, 0xcd, 0x1e, 0x38, 0x76, 0xe3, 0x0c, 0x7a, 0xee, + 0x97, 0x9d, 0x0d, 0x88, 0x1d, 0xbf, 0x67, 0x76, 0xbc, 0xe3, 0x4a, 0x41, 0x77, 0xeb, 0x22, 0xec, 0x60, 0xe8, 0xff, + 0xf2, 0x60, 0x4e, 0xdc, 0x60, 0x2c, 0x9a, 0x6c, 0xc0, 0xed, 0x1b, 0xf0, 0x28, 0xe8, 0x06, 0xdc, 0xbe, 0x0d, 0x5f, + 0x0f, 0xad, 0xec, 0x9b, 0x03, 0x0c, 0xc8, 0x84, 0x1d, 0x69, 0x95, 0x10, 0x0c, 0xf3, 0x74, 0x93, 0x23, 0xb3, 0x64, + 0x15, 0x0e, 0x57, 0x4d, 0x62, 0xb1, 0xb1, 0x17, 0x2a, 0x26, 0x35, 0x10, 0x8c, 0x45, 0xfa, 0x12, 0x85, 0x4a, 0x83, + 0xba, 0x71, 0x0c, 0x60, 0x95, 0xd3, 0xd6, 0xbf, 0x3c, 0x38, 0x00, 0xa1, 0x01, 0x58, 0xbb, 0x24, 0xa3, 0x73, 0xbd, + 0x28, 0x80, 0xbf, 0x52, 0xfe, 0x37, 0x24, 0x83, 0xdb, 0x89, 0x49, 0x83, 0x1f, 0x90, 0x30, 0xa7, 0x4a, 0xf1, 0x2f, + 0x36, 0xcd, 0xfd, 0xc6, 0x05, 0xf1, 0x18, 0xad, 0x2c, 0xa7, 0x28, 0x51, 0x57, 0x3a, 0x74, 0xad, 0x43, 0xee, 0xe9, + 0x17, 0x26, 0xf4, 0x4b, 0xae, 0x34, 0x13, 0x00, 0x80, 0x0a, 0xf1, 0x60, 0x4a, 0x0a, 0xc1, 0xd6, 0xad, 0xd5, 0xa2, + 0xa3, 0xd1, 0x77, 0xab, 0xe8, 0x3a, 0x5b, 0x34, 0xa5, 0x62, 0x94, 0xdb, 0x4e, 0x42, 0x9b, 0x49, 0x6f, 0x27, 0x5a, + 0x96, 0x0c, 0x2d, 0x76, 0x2a, 0xf6, 0xc3, 0xd0, 0xfa, 0x58, 0x10, 0x7f, 0x2e, 0xf8, 0xb3, 0xf4, 0xbb, 0x7c, 0x0c, + 0x5c, 0xa9, 0x7f, 0x63, 0x15, 0xc2, 0x99, 0x60, 0x1d, 0x90, 0xd7, 0xa4, 0x3e, 0x4e, 0x8f, 0x3a, 0xf9, 0x96, 0x72, + 0xa1, 0x34, 0x0a, 0xdb, 0x38, 0x29, 0x0c, 0xa6, 0x9c, 0x7d, 0x5b, 0xe2, 0xfa, 0xd5, 0x1f, 0x23, 0xfe, 0xe8, 0x10, + 0xff, 0x2e, 0x95, 0x46, 0xcb, 0x12, 0xc1, 0x90, 0xdf, 0x91, 0x5a, 0xc1, 0x55, 0x6c, 0xce, 0xf5, 0x73, 0x3d, 0xcb, + 0x37, 0x3c, 0x71, 0xba, 0x5a, 0x95, 0x52, 0x81, 0x8a, 0x6f, 0x18, 0x7e, 0xc2, 0xe0, 0xde, 0xf8, 0x19, 0x0f, 0xaa, + 0x6c, 0xdf, 0x17, 0x3f, 0x0b, 0xee, 0x8b, 0x9f, 0xf1, 0x74, 0xbb, 0x68, 0x70, 0x4f, 0xdc, 0x49, 0xce, 0x93, 0x56, + 0xe4, 0xf9, 0xa8, 0x29, 0xad, 0xfc, 0x2b, 0xed, 0xd6, 0xc0, 0x95, 0x4d, 0x1c, 0x18, 0xe7, 0xd5, 0x45, 0x28, 0xe6, + 0xcc, 0x19, 0x2d, 0x87, 0xff, 0xad, 0x75, 0x72, 0x27, 0x8f, 0xb4, 0x52, 0xc8, 0x1b, 0x5a, 0xe8, 0x7b, 0xb0, 0xe1, + 0x8a, 0x2d, 0x1f, 0x40, 0x4a, 0x40, 0xd9, 0xf6, 0xef, 0x75, 0x11, 0x88, 0xe3, 0xca, 0x3a, 0x1f, 0x85, 0xed, 0x93, + 0xa2, 0xe4, 0xea, 0xea, 0x42, 0xc8, 0xad, 0xd1, 0x12, 0x20, 0x4c, 0xbd, 0x6b, 0x1e, 0x73, 0x34, 0x99, 0xa5, 0xcb, + 0x75, 0xa9, 0x3a, 0x28, 0x2c, 0x57, 0xc7, 0x11, 0x2e, 0xd6, 0xe6, 0x06, 0xfd, 0x15, 0xc7, 0x7f, 0x73, 0x47, 0x23, + 0x7f, 0x2e, 0x29, 0xd0, 0xa3, 0xdd, 0xbe, 0x36, 0x3b, 0x48, 0xa4, 0x9d, 0x43, 0x69, 0x29, 0x00, 0x58, 0x6d, 0xf0, + 0x75, 0xed, 0x71, 0xea, 0x89, 0x74, 0xb3, 0xf9, 0xa6, 0x21, 0x2c, 0x66, 0xa5, 0x05, 0x8f, 0xe9, 0x66, 0x87, 0xe5, + 0xa8, 0x97, 0xc5, 0x75, 0xb9, 0xc7, 0x6a, 0xfd, 0xa2, 0x6f, 0x80, 0xb2, 0x32, 0x44, 0x5b, 0xad, 0xe2, 0x3a, 0xbc, + 0x89, 0x08, 0xae, 0x41, 0x10, 0x16, 0x81, 0x01, 0x47, 0x8d, 0xf1, 0xb6, 0x75, 0x62, 0xb4, 0x69, 0xbf, 0xe4, 0x59, + 0xf7, 0xda, 0x38, 0x42, 0x45, 0x83, 0xad, 0x1e, 0x6a, 0x1e, 0xb0, 0x9d, 0x5d, 0xd9, 0x51, 0x00, 0xa1, 0x29, 0xf5, + 0xc6, 0xb9, 0x95, 0x15, 0xed, 0x0e, 0xf8, 0xa2, 0xef, 0x98, 0xe7, 0x3a, 0xd0, 0x6d, 0xe7, 0x07, 0xb6, 0x4d, 0x4f, + 0xe4, 0xb7, 0x6c, 0x9b, 0x6a, 0x9c, 0xf0, 0x7e, 0x0b, 0x7d, 0xdf, 0x10, 0xd6, 0xf6, 0xb5, 0xbb, 0xc8, 0xff, 0x42, + 0x77, 0x6d, 0x40, 0x4f, 0x0b, 0x66, 0x4f, 0x63, 0x3e, 0xe8, 0xf5, 0xfa, 0xe7, 0xd2, 0x7f, 0xc1, 0xd8, 0x0a, 0xfd, + 0x6c, 0x77, 0x81, 0x13, 0x2b, 0x8d, 0x43, 0x70, 0xfc, 0x8a, 0x93, 0x49, 0x2e, 0x87, 0x34, 0x7f, 0x07, 0x3d, 0x56, + 0xb9, 0xcf, 0xef, 0x46, 0x05, 0xd5, 0xcc, 0xd1, 0x9a, 0x6a, 0x14, 0xaf, 0x78, 0x30, 0x8c, 0x57, 0xdc, 0x52, 0xee, + 0xaa, 0x05, 0xbc, 0x7c, 0x59, 0x36, 0x91, 0xfe, 0xbc, 0x2e, 0x65, 0x30, 0xb5, 0xbb, 0x97, 0x4d, 0x92, 0xc6, 0x4a, + 0x92, 0xc6, 0x54, 0xbc, 0xd9, 0x54, 0x1c, 0xff, 0xfd, 0x8d, 0xc1, 0x6e, 0x93, 0xb9, 0xbf, 0x03, 0x32, 0xf7, 0x37, + 0x4f, 0xbf, 0x5b, 0x2b, 0xa0, 0x78, 0xc7, 0xc9, 0xb1, 0xb1, 0x8c, 0xb1, 0xa3, 0x7e, 0xab, 0xc1, 0xa0, 0x41, 0x93, + 0xcb, 0xc0, 0xdb, 0xa1, 0x3a, 0xbd, 0xbc, 0xfd, 0x51, 0x9c, 0x2d, 0x94, 0x96, 0x33, 0xd7, 0xa8, 0x72, 0x3e, 0x4e, + 0x26, 0x13, 0x14, 0xd8, 0xe6, 0x0e, 0x3f, 0xad, 0xbb, 0x91, 0x2d, 0x3f, 0x73, 0x31, 0x4a, 0x15, 0x76, 0x67, 0x8b, + 0x4a, 0xe5, 0x9a, 0x78, 0x33, 0xe7, 0xed, 0x3c, 0x3c, 0xe6, 0x82, 0xab, 0x29, 0x2b, 0xe2, 0x02, 0x2d, 0xbf, 0xd5, + 0x59, 0x01, 0xb7, 0x39, 0xb6, 0x33, 0x3c, 0x2a, 0x2d, 0x07, 0x74, 0x02, 0xad, 0x81, 0xce, 0x68, 0xc6, 0xf4, 0x54, + 0x8e, 0xc0, 0xf0, 0x25, 0x19, 0x95, 0xee, 0x54, 0x07, 0x07, 0xfb, 0x71, 0x64, 0xf4, 0x17, 0xe0, 0x83, 0x1e, 0xe6, + 0xa0, 0xde, 0x12, 0x1c, 0x83, 0xaa, 0xae, 0x19, 0x5a, 0xb2, 0x4d, 0x1f, 0x1a, 0x9d, 0x7c, 0x66, 0x77, 0x98, 0xa3, + 0xf5, 0x3a, 0xb5, 0xa3, 0x8e, 0xc6, 0x9c, 0xe5, 0xa3, 0x08, 0x7f, 0x66, 0x77, 0x69, 0xe9, 0xb6, 0x6e, 0xbc, 0xac, + 0xcd, 0x22, 0x46, 0xf2, 0x46, 0x44, 0xb8, 0xea, 0x24, 0x5d, 0xae, 0xb1, 0x2c, 0xf8, 0x04, 0x70, 0xf4, 0x17, 0x76, + 0x97, 0xba, 0xf6, 0x02, 0x57, 0x41, 0xb4, 0xf4, 0xa0, 0x4f, 0x82, 0xe4, 0x70, 0x19, 0x9c, 0xc0, 0xd1, 0x37, 0x75, + 0x07, 0xa4, 0x56, 0xae, 0x12, 0x21, 0x11, 0x5a, 0xff, 0xbb, 0x53, 0xc1, 0x8b, 0xf0, 0x9c, 0xd3, 0x35, 0x8b, 0xdb, + 0x8d, 0x4a, 0x0c, 0x2a, 0x54, 0x16, 0x24, 0x1f, 0x63, 0xee, 0x77, 0x9f, 0xf3, 0x7e, 0x08, 0x74, 0x66, 0x0b, 0xea, + 0x1a, 0x4d, 0x47, 0xe6, 0x17, 0xaa, 0xee, 0xa0, 0x66, 0xba, 0xaa, 0xb8, 0xf7, 0x31, 0x06, 0xc0, 0x83, 0xb5, 0x0c, + 0x35, 0x0e, 0xa1, 0x6b, 0x6f, 0xa6, 0x3a, 0xa6, 0x24, 0x5e, 0xfa, 0x39, 0xa4, 0x3c, 0x04, 0xa3, 0x5e, 0x03, 0x1a, + 0x3a, 0x04, 0xb3, 0x96, 0x87, 0x7c, 0x1c, 0x8b, 0xad, 0x33, 0x54, 0x9a, 0x33, 0x34, 0x09, 0x40, 0xfe, 0x8d, 0x33, + 0x93, 0x19, 0x68, 0x18, 0xde, 0xd2, 0x1c, 0x80, 0x6e, 0x75, 0x1d, 0x0e, 0x85, 0x2b, 0x5a, 0x3a, 0xef, 0xd9, 0x45, + 0x97, 0xb5, 0x61, 0xc5, 0xa6, 0x1d, 0xb4, 0x4e, 0x61, 0x4a, 0xcc, 0x16, 0x58, 0x7b, 0xbd, 0x0f, 0xf7, 0x76, 0xb5, + 0x71, 0x91, 0xf8, 0x69, 0x11, 0x0f, 0x93, 0x98, 0xa2, 0x25, 0x8f, 0x29, 0x96, 0x60, 0x07, 0x59, 0xac, 0xcb, 0xf1, + 0xb3, 0x70, 0x39, 0x6a, 0x56, 0xd2, 0xbb, 0x1d, 0x0c, 0x81, 0xcb, 0xd7, 0x60, 0x1b, 0x8a, 0xb9, 0x27, 0x2c, 0x3c, + 0x36, 0x9e, 0x7e, 0xc1, 0xba, 0xcd, 0xed, 0x82, 0xf8, 0x15, 0x18, 0xd3, 0x78, 0x19, 0xcc, 0x22, 0x74, 0x2a, 0x77, + 0x0e, 0x87, 0xee, 0x9a, 0xb0, 0x32, 0x5e, 0x8d, 0x15, 0xd9, 0x38, 0x7a, 0xbe, 0x6f, 0xe3, 0xf9, 0xcf, 0x82, 0x15, + 0x77, 0x57, 0x0c, 0x6c, 0xac, 0x25, 0xb8, 0x1b, 0x57, 0xcb, 0x50, 0x19, 0xc8, 0xf7, 0xa4, 0x61, 0x5d, 0xd6, 0xf8, + 0xbb, 0x51, 0x31, 0xd6, 0xe6, 0x9e, 0x32, 0xd0, 0xd6, 0xd8, 0xed, 0xc2, 0xbe, 0xe9, 0xba, 0xc9, 0xba, 0x46, 0x11, + 0x57, 0x41, 0xda, 0xdd, 0x2d, 0xe0, 0x22, 0xf4, 0x87, 0xed, 0xab, 0xc1, 0xa6, 0xea, 0x06, 0x92, 0xe0, 0xda, 0x4f, + 0x7e, 0x7b, 0xaa, 0xbb, 0xac, 0x75, 0xbf, 0x3d, 0xd5, 0xda, 0x65, 0xa1, 0x31, 0x24, 0xc2, 0xae, 0x9f, 0xd2, 0x7f, + 0x5a, 0xac, 0xd7, 0x68, 0x0d, 0xc3, 0x7b, 0xcf, 0xbb, 0x71, 0xfc, 0xde, 0x5b, 0x28, 0x26, 0x70, 0x91, 0x7b, 0x95, + 0x4b, 0x4f, 0xc8, 0xab, 0x11, 0xbc, 0xe7, 0x5b, 0x43, 0x78, 0xcf, 0x03, 0xa7, 0x57, 0x90, 0x9a, 0x26, 0x82, 0x8d, + 0x3c, 0xfd, 0x44, 0x16, 0x09, 0x0d, 0x1f, 0xf7, 0x9a, 0x13, 0xa1, 0x3f, 0xa5, 0xc0, 0x7f, 0xe1, 0xe1, 0x42, 0x6b, + 0x29, 0x30, 0x17, 0xf3, 0x85, 0xc6, 0xca, 0x8c, 0x7e, 0x39, 0x96, 0x42, 0x37, 0xc7, 0x74, 0xc6, 0xf3, 0xbb, 0x74, + 0xc1, 0x9b, 0x33, 0x29, 0xa4, 0x9a, 0xd3, 0x8c, 0x61, 0x75, 0xa7, 0x34, 0x9b, 0x35, 0x17, 0x1c, 0x3f, 0x67, 0xf9, + 0x17, 0xa6, 0x79, 0x46, 0xf1, 0x5b, 0x39, 0x94, 0x5a, 0xe2, 0xd7, 0xb7, 0x77, 0x13, 0x26, 0xf0, 0xef, 0xc3, 0x85, + 0xd0, 0x0b, 0xac, 0xa8, 0x50, 0x4d, 0xc5, 0x0a, 0x3e, 0xee, 0x36, 0x9b, 0xf3, 0x82, 0xcf, 0x68, 0x71, 0xd7, 0xcc, + 0x64, 0x2e, 0x8b, 0xf4, 0xbf, 0x5a, 0xc7, 0xf4, 0xc1, 0xf8, 0xa4, 0xab, 0x0b, 0x2a, 0x14, 0x87, 0x85, 0x49, 0x69, + 0x9e, 0xef, 0x1d, 0x9f, 0xb6, 0x66, 0x6a, 0xdf, 0x5e, 0xf8, 0x51, 0xa1, 0xd7, 0x9f, 0xf0, 0x07, 0x09, 0xa3, 0x4c, + 0x86, 0x5a, 0xb8, 0x41, 0x2e, 0xb3, 0x45, 0xa1, 0x64, 0x91, 0xce, 0x25, 0x17, 0x9a, 0x15, 0xdd, 0xa1, 0x2c, 0x46, + 0xac, 0x68, 0x16, 0x74, 0xc4, 0x17, 0x2a, 0x3d, 0x99, 0xdf, 0x76, 0xeb, 0x3d, 0xd8, 0xfc, 0x54, 0x48, 0xc1, 0xba, + 0xc0, 0x6f, 0x4c, 0x0a, 0xb9, 0x10, 0x23, 0x37, 0x8c, 0x85, 0x50, 0x4c, 0x77, 0xe7, 0x74, 0x04, 0x76, 0xc0, 0xe9, + 0xf9, 0xfc, 0xb6, 0x6b, 0x66, 0x7d, 0xc3, 0xf8, 0x64, 0xaa, 0xd3, 0xd3, 0x56, 0xcb, 0x7e, 0x2b, 0xfe, 0x95, 0xa5, + 0xed, 0x4e, 0xd2, 0x39, 0x9d, 0xdf, 0x02, 0x07, 0xaf, 0x59, 0xd1, 0x04, 0x58, 0x40, 0xa5, 0x76, 0xd2, 0x7a, 0x70, + 0x7c, 0x1f, 0x32, 0xc0, 0xc6, 0xa1, 0x69, 0x26, 0x04, 0xc6, 0xee, 0xe9, 0x62, 0x3e, 0x67, 0x05, 0x78, 0xd1, 0x77, + 0x67, 0xb4, 0x98, 0x70, 0xd1, 0x2c, 0x4c, 0xa3, 0xcd, 0xf3, 0xf9, 0xed, 0x1a, 0xe6, 0x93, 0x5a, 0xb3, 0x55, 0x37, + 0x2d, 0xf7, 0xb5, 0x0c, 0x86, 0x68, 0x62, 0xd2, 0xa4, 0xc5, 0x64, 0x48, 0xe3, 0x76, 0xe7, 0x3e, 0xf6, 0xff, 0x4b, + 0x3a, 0x28, 0x00, 0x5b, 0x73, 0xb4, 0x28, 0xcc, 0x2d, 0x6a, 0xda, 0x56, 0xb6, 0xd9, 0xa9, 0xfc, 0xc2, 0x0a, 0xdf, + 0xaa, 0xf9, 0x58, 0x6e, 0xcd, 0xfb, 0x3f, 0x69, 0xf4, 0x13, 0x9e, 0x50, 0x58, 0x03, 0x83, 0x1c, 0x7d, 0x23, 0x0f, + 0xc2, 0x4c, 0x07, 0xcb, 0x1b, 0x3e, 0xd2, 0xd3, 0xb4, 0xdd, 0x6a, 0xfd, 0x50, 0xad, 0x58, 0x77, 0x6a, 0x41, 0xd7, + 0x2e, 0xd8, 0xac, 0xb6, 0x8e, 0x33, 0x5a, 0x62, 0xdb, 0x72, 0x2e, 0xdd, 0x92, 0x17, 0x2c, 0x37, 0xd1, 0x64, 0xd6, + 0x0e, 0xe5, 0xb6, 0xc6, 0xc9, 0xc5, 0x94, 0x15, 0x5c, 0x77, 0xeb, 0x5f, 0x55, 0xc7, 0xdb, 0xab, 0xbf, 0xb6, 0x72, + 0xe8, 0xd2, 0xd6, 0x70, 0x97, 0x9e, 0x8f, 0xe1, 0x63, 0x7b, 0xf5, 0xbf, 0xd0, 0x22, 0xde, 0x40, 0x4c, 0x1c, 0xd6, + 0x40, 0xeb, 0x60, 0xce, 0x05, 0x98, 0x64, 0x0e, 0xf0, 0x37, 0xa0, 0x90, 0xd1, 0x3c, 0x8b, 0x61, 0x44, 0x7b, 0xcd, + 0xbd, 0xe3, 0x82, 0xcd, 0x90, 0x07, 0x44, 0x72, 0xff, 0xb4, 0x60, 0xb3, 0x75, 0x62, 0xaa, 0x2f, 0x0d, 0x8a, 0xd0, + 0x9c, 0x4f, 0x44, 0x9a, 0x31, 0x40, 0xdf, 0x75, 0xc2, 0x84, 0xe6, 0xfa, 0xae, 0x59, 0xc8, 0x9b, 0xe5, 0x88, 0xab, + 0x79, 0x4e, 0xef, 0xd2, 0x71, 0xce, 0x6e, 0xbb, 0xa6, 0x54, 0x93, 0x6b, 0x36, 0x53, 0xae, 0x6c, 0x17, 0xd2, 0x9b, + 0x23, 0x6b, 0x36, 0x01, 0xd0, 0x93, 0x37, 0x9b, 0xfb, 0x27, 0x39, 0x56, 0x7b, 0x8c, 0x2a, 0xd6, 0x94, 0x0b, 0xbd, + 0xd7, 0x52, 0xdd, 0x19, 0x17, 0x4d, 0x37, 0x90, 0x93, 0xd6, 0xfc, 0xb6, 0xbb, 0x0d, 0xf9, 0xa0, 0xff, 0x84, 0xdd, + 0xce, 0xa9, 0x18, 0xb1, 0xd1, 0x32, 0xa8, 0xd6, 0x81, 0x7a, 0x61, 0xa9, 0x54, 0xe8, 0x69, 0xd3, 0xd8, 0x7a, 0xc5, + 0x1d, 0x81, 0xbe, 0x81, 0x5a, 0x0f, 0x5a, 0xd8, 0xfe, 0x7f, 0xd2, 0x46, 0x61, 0xe5, 0x3d, 0x08, 0xbb, 0xc4, 0xc7, + 0x77, 0x4d, 0xf8, 0xbb, 0x04, 0xdf, 0x22, 0x9e, 0xd1, 0xdc, 0x41, 0x64, 0xc6, 0x47, 0xa3, 0xbc, 0x36, 0xa2, 0xcb, + 0xa0, 0xb3, 0x36, 0x5a, 0xc2, 0xfc, 0xd3, 0xd6, 0x5e, 0x6b, 0xcf, 0xcc, 0xc5, 0x6d, 0xf3, 0x93, 0x93, 0xfb, 0xc7, + 0x0f, 0x58, 0x37, 0xe7, 0x82, 0xd5, 0xa6, 0xfa, 0x5d, 0x50, 0x87, 0x0d, 0x77, 0x5c, 0xc3, 0xed, 0xbd, 0xf6, 0xde, + 0x49, 0xeb, 0x07, 0xbf, 0x5b, 0x73, 0x36, 0xd6, 0x69, 0xfb, 0x6c, 0x7e, 0x5b, 0xdf, 0xbe, 0xe7, 0xbe, 0xe9, 0x9b, + 0x82, 0xce, 0x53, 0x21, 0xe1, 0x4f, 0x17, 0x36, 0xd9, 0x38, 0x97, 0x37, 0xe9, 0x94, 0x8f, 0x46, 0x4c, 0xd8, 0x02, + 0x65, 0x22, 0xcb, 0x73, 0x3e, 0x57, 0xdc, 0xae, 0x86, 0xc3, 0xdd, 0xd3, 0x0d, 0xa8, 0x86, 0x03, 0x3a, 0x0e, 0x06, + 0x74, 0x5a, 0x0d, 0xa8, 0xea, 0x3f, 0x1c, 0x61, 0x67, 0x63, 0xae, 0xa6, 0x54, 0xb7, 0x86, 0x49, 0x7f, 0x2f, 0x94, + 0x06, 0x98, 0x7b, 0x23, 0x0d, 0x43, 0xc5, 0x9b, 0x43, 0xa6, 0x6f, 0x18, 0x13, 0xdf, 0x1e, 0xc4, 0x65, 0x2a, 0x45, + 0x7e, 0x67, 0x3f, 0x97, 0x61, 0x97, 0x74, 0xa1, 0xe5, 0x3a, 0x19, 0x72, 0x41, 0x8b, 0xbb, 0x6b, 0xc5, 0x84, 0x92, + 0xc5, 0xb5, 0x1c, 0x8f, 0x97, 0xdf, 0x22, 0x2d, 0xf7, 0xd1, 0x3a, 0x51, 0x5c, 0x4c, 0x72, 0x66, 0x89, 0x92, 0x41, + 0x04, 0x47, 0xcc, 0x6d, 0xbb, 0xa6, 0xc9, 0xda, 0xa0, 0xd7, 0x49, 0x96, 0xf3, 0x19, 0xd5, 0xcc, 0xc0, 0x39, 0x20, + 0x35, 0x6e, 0xf2, 0x69, 0xbb, 0x35, 0xbf, 0xdd, 0x6b, 0xed, 0xd9, 0x3f, 0x55, 0x69, 0xd8, 0x46, 0x41, 0x61, 0xdf, + 0x24, 0x17, 0x06, 0x3f, 0x0c, 0x38, 0xcc, 0x2e, 0x32, 0xab, 0x67, 0xd6, 0x2e, 0x80, 0x1d, 0xcc, 0xae, 0xd6, 0xd4, + 0xa5, 0xa3, 0x4b, 0xb6, 0xc5, 0xd3, 0xd6, 0x0f, 0xf5, 0xdc, 0x9c, 0x0e, 0x59, 0xbe, 0xb4, 0x1b, 0xd5, 0x03, 0xd7, + 0x6d, 0xd5, 0x70, 0x99, 0x03, 0x92, 0x61, 0x40, 0x34, 0x48, 0xd3, 0xe6, 0x0d, 0x1b, 0x7e, 0xe6, 0xda, 0x6e, 0x99, + 0xa6, 0xba, 0x01, 0xe7, 0x1d, 0x33, 0xa6, 0x39, 0x2b, 0x96, 0xfe, 0x38, 0x6a, 0xd5, 0x08, 0xe8, 0x95, 0x30, 0x07, + 0xa1, 0xa6, 0xc3, 0x26, 0x84, 0x32, 0x63, 0xc5, 0x72, 0xd7, 0xe4, 0x66, 0xf4, 0xd6, 0xa1, 0xd8, 0x83, 0xd6, 0x0f, + 0xb5, 0xc3, 0xec, 0xa4, 0xd5, 0xf2, 0x07, 0x5d, 0xd3, 0xd6, 0x48, 0xdb, 0xc9, 0x29, 0x9b, 0x95, 0x89, 0x5a, 0xce, + 0xd3, 0x5a, 0xc2, 0x50, 0x6a, 0x2d, 0x67, 0x36, 0x6d, 0x07, 0x35, 0xaa, 0x93, 0xde, 0x76, 0x67, 0x7e, 0xbb, 0x67, + 0xfe, 0x69, 0xed, 0xb5, 0xb6, 0x49, 0xed, 0x36, 0x56, 0x1c, 0x23, 0x8f, 0xc7, 0xd0, 0x71, 0x9b, 0xcd, 0xba, 0x0b, + 0x05, 0xc7, 0xaa, 0x81, 0xb8, 0x39, 0xae, 0xd7, 0x66, 0xb2, 0x00, 0x58, 0xca, 0x05, 0x9c, 0x62, 0xf6, 0x24, 0x87, + 0x3e, 0x94, 0x04, 0xb3, 0xf3, 0x9d, 0x8d, 0xd6, 0x87, 0xd5, 0xda, 0xab, 0x06, 0x06, 0xff, 0xac, 0x3f, 0x55, 0x7c, + 0xf0, 0x0b, 0x16, 0xc8, 0x21, 0xbc, 0x91, 0x9c, 0xae, 0x5a, 0x4e, 0xf6, 0x18, 0xe9, 0x4a, 0x24, 0x32, 0x9e, 0x1b, + 0x33, 0x7a, 0x6b, 0x5d, 0x38, 0x66, 0x5c, 0x80, 0x81, 0x18, 0xc2, 0x3a, 0x30, 0xa5, 0x9f, 0x86, 0x0d, 0x8d, 0x74, + 0x0c, 0x0d, 0x1f, 0x76, 0x92, 0xd3, 0x53, 0x84, 0x5b, 0xb8, 0x73, 0x7a, 0x1a, 0xc8, 0x3e, 0x63, 0xbd, 0xab, 0xe8, + 0xae, 0x92, 0x72, 0x47, 0xc9, 0x23, 0xd3, 0xe8, 0x51, 0xbb, 0xd5, 0xc2, 0xc6, 0x4d, 0xbd, 0x2c, 0xcc, 0xd5, 0x8e, + 0x66, 0xdb, 0xad, 0x16, 0x34, 0x0b, 0x7f, 0xdc, 0xbc, 0x7e, 0x21, 0xcb, 0x56, 0xda, 0xc2, 0xed, 0xb4, 0x8d, 0x3b, + 0x69, 0x07, 0x1f, 0xa7, 0xc7, 0xf8, 0x24, 0x3d, 0xc1, 0xa7, 0xe9, 0x29, 0x3e, 0x4b, 0xcf, 0xf0, 0xfd, 0xf4, 0x3e, + 0x3e, 0x4f, 0xcf, 0xf1, 0x83, 0xf4, 0x01, 0x7e, 0x98, 0xb6, 0x5b, 0xf8, 0x51, 0xda, 0x6e, 0xe3, 0xc7, 0x69, 0xbb, + 0x83, 0x9f, 0xa4, 0xed, 0x63, 0xfc, 0x34, 0x6d, 0x9f, 0xe0, 0x67, 0x69, 0xfb, 0x14, 0x53, 0xc8, 0x1d, 0x42, 0x6e, + 0x06, 0xb9, 0x23, 0xc8, 0x65, 0x90, 0x3b, 0x4e, 0xdb, 0xa7, 0x6b, 0xac, 0x6c, 0x68, 0x8b, 0xa8, 0xd5, 0xee, 0x1c, + 0x9f, 0x9c, 0x9e, 0xdd, 0x3f, 0x7f, 0xf0, 0xf0, 0xd1, 0xe3, 0x27, 0x4f, 0x9f, 0x45, 0x03, 0x3c, 0x34, 0x1e, 0x26, + 0x4a, 0xf4, 0xf9, 0x41, 0xfb, 0x74, 0x80, 0xaf, 0xfd, 0x67, 0xcc, 0x0f, 0x3a, 0x27, 0x2d, 0x74, 0x79, 0x79, 0x32, + 0x68, 0x94, 0xb9, 0xef, 0x8d, 0x63, 0x4b, 0x95, 0x45, 0x08, 0x89, 0x21, 0x07, 0xe1, 0x3b, 0x53, 0xef, 0x3d, 0x8b, + 0x79, 0x52, 0xa0, 0x83, 0x03, 0xf3, 0x63, 0xe2, 0x7f, 0x0c, 0xfd, 0x0f, 0x1a, 0x2c, 0xd2, 0x2d, 0x8d, 0x9d, 0x67, + 0xb3, 0x2e, 0xfd, 0x0a, 0x4a, 0x93, 0x9d, 0x3d, 0xee, 0x8c, 0xe7, 0xff, 0x2b, 0xb2, 0xc6, 0x31, 0xe4, 0xc4, 0x2a, + 0xa0, 0x4e, 0x7b, 0x8c, 0x2c, 0x8b, 0xb4, 0x73, 0x7a, 0x7a, 0xf0, 0x4b, 0x9f, 0xf7, 0xdb, 0x83, 0xc1, 0x61, 0xfb, + 0x3e, 0x9e, 0x94, 0x09, 0x1d, 0x9b, 0x30, 0x2c, 0x13, 0x8e, 0x6d, 0x02, 0x4d, 0x6d, 0x6d, 0x48, 0x3a, 0x31, 0x49, + 0x50, 0x62, 0x9d, 0x9a, 0xb6, 0xef, 0xdb, 0xb6, 0x1f, 0x80, 0xd5, 0x96, 0x69, 0xde, 0x35, 0x7d, 0x71, 0x71, 0xb2, + 0x72, 0x8d, 0xe2, 0x49, 0xea, 0x5a, 0xf3, 0x89, 0x27, 0x83, 0x01, 0x1e, 0x9a, 0xc4, 0xd3, 0x2a, 0xf1, 0x6c, 0x30, + 0x70, 0x5d, 0x3d, 0x30, 0x5d, 0xdd, 0xaf, 0xb2, 0xce, 0x07, 0x03, 0xd3, 0x25, 0x72, 0x3e, 0xfa, 0x4a, 0xef, 0x7d, + 0x29, 0xf5, 0x24, 0xfc, 0xa2, 0x73, 0x7a, 0xda, 0x03, 0x0c, 0x33, 0xb6, 0xb7, 0x1e, 0x46, 0x37, 0x01, 0x8c, 0xee, + 0xe0, 0x77, 0x6f, 0x48, 0xd3, 0x6b, 0x5a, 0x02, 0xa9, 0x17, 0xfd, 0x57, 0xd4, 0xd0, 0x06, 0xe6, 0xe6, 0xcf, 0xc4, + 0xfe, 0x19, 0xa2, 0xc6, 0x17, 0x0a, 0xe0, 0x06, 0xcd, 0x8f, 0x57, 0xdd, 0x9a, 0x1e, 0x3f, 0x53, 0x70, 0xa5, 0x99, + 0xaa, 0x9c, 0xf6, 0x56, 0xd3, 0x9b, 0xe1, 0x6a, 0xaa, 0xbe, 0xa0, 0xbf, 0xe2, 0xbf, 0xd4, 0x61, 0xdc, 0x6f, 0x36, + 0x12, 0xf6, 0xd7, 0x08, 0x7c, 0x76, 0x7a, 0xe9, 0x88, 0x4d, 0x50, 0xaf, 0xff, 0x97, 0xc2, 0x83, 0x46, 0x90, 0xf1, + 0xc3, 0x76, 0x0a, 0x78, 0xf4, 0x6c, 0x26, 0xc6, 0x3f, 0xa0, 0x1e, 0xea, 0xfd, 0xa5, 0x0e, 0xff, 0x42, 0xf7, 0x8e, + 0xaa, 0xb9, 0xfc, 0x2e, 0xdd, 0x16, 0xae, 0xc2, 0xfc, 0x1c, 0x96, 0x5b, 0x98, 0xe1, 0x76, 0x93, 0x41, 0x50, 0x34, + 0x70, 0xf9, 0x26, 0xb1, 0x6c, 0xf0, 0xa3, 0xe3, 0x16, 0xfa, 0xa1, 0xdd, 0x01, 0x25, 0x46, 0x53, 0x1c, 0x6e, 0x6f, + 0xfa, 0xa2, 0x79, 0x8c, 0x1f, 0x34, 0x0b, 0xdc, 0x46, 0xb8, 0xd9, 0xf6, 0xda, 0xe5, 0xbe, 0x8a, 0x5b, 0x08, 0xab, + 0xf8, 0x1c, 0xfe, 0x39, 0x41, 0x83, 0x6a, 0x43, 0x5e, 0xd1, 0xcd, 0xde, 0xc1, 0x3f, 0x95, 0xc4, 0xaa, 0xc1, 0x8f, + 0xce, 0x5a, 0xe8, 0x87, 0x33, 0xd3, 0x11, 0x3b, 0xd4, 0x3b, 0xba, 0x92, 0xf8, 0xa4, 0x29, 0xa1, 0xa3, 0x56, 0xd9, + 0x8f, 0x88, 0x4f, 0x11, 0x16, 0xf1, 0x31, 0xfc, 0xd3, 0x0e, 0xfb, 0xf9, 0x75, 0xab, 0x1f, 0x33, 0xef, 0x36, 0x4e, + 0x4e, 0xad, 0xbb, 0xab, 0xb2, 0x77, 0xcf, 0x0d, 0x76, 0xd9, 0x36, 0x97, 0x66, 0xed, 0x23, 0xf8, 0x40, 0x58, 0x1f, + 0x12, 0x85, 0xd9, 0x21, 0xf8, 0xc9, 0x82, 0x79, 0x88, 0xba, 0x38, 0xee, 0xaa, 0x46, 0x03, 0x89, 0xbe, 0x1a, 0x1c, + 0x92, 0x76, 0x53, 0x37, 0x19, 0x86, 0xdf, 0x0d, 0x52, 0x06, 0x5f, 0x13, 0x55, 0xaf, 0x8f, 0x5d, 0xaf, 0xf6, 0x86, + 0xdd, 0x63, 0x07, 0x21, 0x44, 0xf5, 0x62, 0xdd, 0x64, 0xe8, 0x48, 0x34, 0x62, 0x7d, 0xc1, 0x7a, 0x67, 0x69, 0x0b, + 0x19, 0xec, 0x54, 0xbd, 0x98, 0x35, 0x39, 0xa4, 0x77, 0xd2, 0x98, 0x37, 0x35, 0xfc, 0x3a, 0x09, 0x66, 0x21, 0x00, + 0xef, 0x2a, 0xaf, 0x9f, 0xe2, 0xa8, 0x73, 0x7a, 0x8a, 0x05, 0xe1, 0xc9, 0xc4, 0xfc, 0x52, 0x84, 0x27, 0x43, 0xf3, + 0x4b, 0x92, 0x12, 0x5e, 0xb6, 0x77, 0x5c, 0x90, 0x60, 0x55, 0x4d, 0x0a, 0x85, 0x05, 0x2d, 0xd0, 0x51, 0xc7, 0x5f, + 0xbf, 0xe3, 0xa9, 0x9f, 0x03, 0xa8, 0x1b, 0x0a, 0x63, 0x79, 0x29, 0x9b, 0x05, 0xce, 0x09, 0xbd, 0x4c, 0x4e, 0x7b, + 0xd3, 0xa3, 0xb8, 0xd3, 0x94, 0xcd, 0x02, 0xa5, 0xd3, 0x23, 0x53, 0x13, 0x67, 0xe4, 0x31, 0xb5, 0xad, 0xe1, 0x29, + 0xdc, 0x99, 0x66, 0x24, 0x3b, 0x3c, 0x6b, 0x35, 0x92, 0x53, 0x84, 0xfb, 0xd9, 0xaa, 0x85, 0xf3, 0xd5, 0xaa, 0x85, + 0x69, 0xb0, 0x0c, 0x8f, 0x85, 0x07, 0x48, 0xa9, 0x11, 0xdb, 0x8c, 0x81, 0xd3, 0xe3, 0xb1, 0x86, 0xfb, 0x7f, 0x0d, + 0x5e, 0x35, 0x1a, 0xfc, 0x7d, 0x52, 0xee, 0x2e, 0xde, 0x90, 0x89, 0x02, 0x38, 0x0e, 0x75, 0x64, 0xaf, 0x85, 0x5f, + 0x57, 0x6f, 0xc1, 0x29, 0xe2, 0xdf, 0x25, 0xb6, 0x69, 0x41, 0x31, 0xba, 0x5d, 0xec, 0x57, 0xba, 0x55, 0xec, 0xcd, + 0x8e, 0x62, 0x57, 0xdb, 0xc5, 0x3e, 0xca, 0x40, 0xa3, 0xc7, 0x7f, 0x38, 0x3e, 0x6b, 0x35, 0x8e, 0x01, 0x59, 0x8f, + 0xcf, 0x5a, 0x55, 0xa1, 0x7b, 0xb4, 0x5a, 0x2b, 0x4d, 0x3e, 0x53, 0xeb, 0xd3, 0xc0, 0xbd, 0x73, 0xb5, 0x59, 0x38, + 0xeb, 0xda, 0x5d, 0xfa, 0x71, 0xf7, 0x4f, 0xc1, 0x66, 0x44, 0x18, 0x6a, 0xa7, 0xfb, 0x67, 0x83, 0xde, 0x94, 0xc5, + 0x0d, 0x48, 0x45, 0xe9, 0x58, 0xbb, 0x5f, 0xa8, 0xbc, 0x3a, 0xfe, 0x28, 0x21, 0xa9, 0x33, 0x40, 0x58, 0x92, 0x86, + 0xee, 0x1f, 0x0f, 0xcc, 0x79, 0x57, 0xc0, 0xef, 0x13, 0xf3, 0xbb, 0x54, 0xdc, 0x38, 0xc7, 0x87, 0xe9, 0xcd, 0x30, + 0xea, 0x09, 0xf2, 0x9a, 0xc6, 0xc6, 0x96, 0x1d, 0xa5, 0x65, 0x86, 0xfa, 0x02, 0x19, 0x6f, 0xca, 0x0c, 0x41, 0x5e, + 0x0b, 0xf7, 0x1b, 0x2f, 0x8b, 0x14, 0xec, 0x5a, 0xf0, 0x24, 0x05, 0x9b, 0x16, 0x3c, 0x4c, 0x05, 0xf8, 0x5d, 0xd0, + 0x94, 0x05, 0xd6, 0xf2, 0x0f, 0x9d, 0xa6, 0xcc, 0xdc, 0xee, 0x12, 0x83, 0xa5, 0x5d, 0x06, 0x27, 0xc5, 0x47, 0x19, + 0xc3, 0xdf, 0x86, 0x46, 0x98, 0x41, 0x9b, 0x0c, 0x61, 0x9e, 0x14, 0x04, 0xd2, 0x30, 0x4f, 0x26, 0x84, 0x41, 0x93, + 0x3c, 0x19, 0x12, 0xd6, 0xef, 0x04, 0x68, 0xf2, 0xd4, 0xc0, 0x0e, 0x80, 0xc3, 0xeb, 0x17, 0xe6, 0xda, 0x36, 0x0e, + 0x37, 0xf1, 0xd0, 0x84, 0x20, 0x5c, 0xc5, 0x30, 0x0b, 0xd8, 0x9c, 0xe6, 0x67, 0xa7, 0x0a, 0x33, 0xc9, 0x13, 0x6a, + 0xa8, 0xf7, 0x27, 0x20, 0xab, 0xf1, 0xbd, 0x25, 0x5b, 0xe3, 0xbd, 0x7b, 0x4b, 0xb1, 0xfe, 0x01, 0xfe, 0x28, 0xfb, + 0x07, 0x98, 0x87, 0x84, 0xa2, 0x35, 0xfa, 0x94, 0x42, 0xb1, 0x1d, 0xa5, 0xd0, 0x27, 0xef, 0x76, 0xa7, 0xc8, 0xf2, + 0x36, 0x8d, 0x46, 0xb4, 0xf8, 0x1c, 0xe1, 0x3f, 0xd3, 0x28, 0x07, 0x6e, 0x31, 0xc2, 0x1f, 0xd3, 0xa8, 0x60, 0x11, + 0xfe, 0x23, 0x8d, 0x86, 0xf9, 0x22, 0xc2, 0x1f, 0xd2, 0x68, 0x52, 0x44, 0xf8, 0x3d, 0x28, 0x45, 0x47, 0x7c, 0x31, + 0x8b, 0xf0, 0xef, 0x69, 0xa4, 0x8c, 0xd7, 0x01, 0x7e, 0x98, 0x46, 0x8c, 0x45, 0xf8, 0x5d, 0x1a, 0xc9, 0x3c, 0xc2, + 0x57, 0x69, 0x24, 0x8b, 0x08, 0x3f, 0x4a, 0xa3, 0x82, 0x46, 0xf8, 0x71, 0x1a, 0x41, 0xa1, 0x49, 0x84, 0x9f, 0xa4, + 0x11, 0xb4, 0xac, 0x22, 0xfc, 0x36, 0x8d, 0xb8, 0x88, 0xf0, 0x6f, 0x69, 0xa4, 0x17, 0xc5, 0x3f, 0x0b, 0xc9, 0x55, + 0x84, 0x9f, 0xa6, 0xd1, 0x94, 0x47, 0xf8, 0x4d, 0x1a, 0x15, 0x32, 0xc2, 0xaf, 0xd3, 0x88, 0xe6, 0x11, 0x7e, 0x95, + 0x46, 0x39, 0x8b, 0xf0, 0xaf, 0x69, 0x34, 0x62, 0x11, 0x7e, 0x99, 0x46, 0x77, 0x2c, 0xcf, 0x65, 0x84, 0x9f, 0xa5, + 0x11, 0x13, 0x11, 0xfe, 0x25, 0x8d, 0xb2, 0x69, 0x84, 0x7f, 0x4a, 0x23, 0x5a, 0x7c, 0x56, 0x11, 0x7e, 0x9e, 0x46, + 0x8c, 0x46, 0xf8, 0x85, 0xed, 0x68, 0x12, 0xe1, 0x9f, 0xd3, 0xe8, 0x66, 0x1a, 0xad, 0xb1, 0x52, 0x64, 0xf9, 0x9a, + 0x67, 0xec, 0x0f, 0x96, 0x46, 0xe3, 0xd6, 0xf8, 0x7c, 0x3c, 0x8e, 0x30, 0x15, 0x9a, 0xff, 0xb3, 0x60, 0x37, 0x4f, + 0x35, 0x24, 0x52, 0x36, 0x1c, 0xdd, 0x8f, 0x30, 0xfd, 0x67, 0x41, 0xd3, 0x68, 0x3c, 0x36, 0x05, 0xfe, 0x59, 0xd0, + 0x19, 0x2d, 0xde, 0xb2, 0x34, 0xba, 0x3f, 0x1e, 0x8f, 0x47, 0x27, 0x11, 0xa6, 0x5f, 0x17, 0x1f, 0x4d, 0x0b, 0xa6, + 0xc0, 0x90, 0xf1, 0x09, 0xd4, 0x3d, 0x1d, 0x9f, 0x8e, 0xb2, 0x08, 0x0f, 0xb9, 0xfa, 0x67, 0x01, 0xdf, 0x63, 0x76, + 0x92, 0x9d, 0x44, 0x78, 0x98, 0xd3, 0xec, 0x73, 0x1a, 0xb5, 0xcc, 0x2f, 0xf1, 0x0b, 0x1b, 0xbd, 0x9e, 0x49, 0x73, + 0x65, 0x30, 0x66, 0xc3, 0x6c, 0x14, 0x61, 0x33, 0x98, 0x31, 0xfc, 0xfd, 0xc2, 0xdf, 0x31, 0x9d, 0x46, 0xe7, 0xb4, + 0x33, 0x64, 0x9d, 0x08, 0x0f, 0xdf, 0xdc, 0x88, 0x34, 0xa2, 0xa7, 0x1d, 0xda, 0xa1, 0x11, 0x1e, 0x2e, 0x8a, 0xfc, + 0xee, 0x46, 0xca, 0x11, 0x00, 0x61, 0x78, 0x7e, 0x7e, 0x3f, 0xc2, 0x19, 0xfd, 0x55, 0x43, 0xed, 0xd3, 0xf1, 0x03, + 0x46, 0x5b, 0x11, 0xfe, 0x85, 0x16, 0xfa, 0xe3, 0x42, 0xb9, 0x81, 0xb6, 0x20, 0x45, 0x66, 0xef, 0x40, 0x9d, 0x1e, + 0x8d, 0x3a, 0x67, 0x0f, 0xda, 0x2c, 0xc2, 0xd9, 0xd5, 0x6b, 0xe8, 0xed, 0xfe, 0xf8, 0xb4, 0x05, 0x1f, 0x02, 0xe4, + 0x52, 0x56, 0x40, 0x23, 0x67, 0x27, 0x0f, 0x4e, 0xd9, 0xc8, 0x24, 0x2a, 0x9e, 0x7f, 0x36, 0xb3, 0x3f, 0x87, 0xf9, + 0x64, 0x05, 0x9f, 0x29, 0x29, 0xd2, 0x68, 0x94, 0xb5, 0x4f, 0x8e, 0x21, 0xe1, 0x8e, 0x0a, 0x0f, 0x9c, 0x5b, 0xa8, + 0x7a, 0x3e, 0x8c, 0xf0, 0xad, 0x4d, 0x3d, 0x1f, 0x9a, 0x8f, 0xc9, 0xbb, 0x5f, 0xc5, 0x9b, 0x51, 0x1a, 0x0d, 0xcf, + 0xcf, 0xcf, 0x5a, 0x90, 0xf0, 0x81, 0xde, 0xa5, 0x11, 0x7d, 0x00, 0xff, 0x41, 0xf6, 0xc7, 0x67, 0xd0, 0x21, 0x8c, + 0xf0, 0x76, 0xf2, 0x31, 0xcc, 0xf9, 0x3c, 0xa5, 0x9f, 0x79, 0x1a, 0x0d, 0x47, 0xc3, 0xfb, 0x67, 0x50, 0x6f, 0x46, + 0x27, 0xcf, 0x34, 0x85, 0x76, 0x5b, 0x2d, 0xd3, 0xf2, 0x3b, 0xfe, 0x85, 0x99, 0xea, 0xa7, 0xa7, 0x67, 0xc3, 0x0e, + 0x8c, 0xe0, 0x0a, 0x14, 0x2a, 0x30, 0x9e, 0xf3, 0xcc, 0x34, 0x78, 0x95, 0x3d, 0x1d, 0xa5, 0xd1, 0x83, 0x07, 0xc7, + 0x9d, 0x2c, 0x8b, 0xf0, 0xed, 0xc7, 0x91, 0xad, 0x6d, 0xf2, 0x14, 0xc0, 0x3e, 0x8d, 0xd8, 0x83, 0x07, 0x67, 0xf7, + 0x29, 0x7c, 0x3f, 0x37, 0x6d, 0x9d, 0x8f, 0x87, 0xd9, 0x39, 0xb4, 0xf5, 0x3b, 0x4c, 0xe7, 0xe4, 0xfc, 0x78, 0x64, + 0xfa, 0xfa, 0xdd, 0x8c, 0xba, 0x33, 0x3e, 0x19, 0x9f, 0x98, 0x4c, 0x33, 0xd4, 0xf2, 0xf3, 0x37, 0x96, 0x46, 0x19, + 0x1b, 0xb5, 0x23, 0x7c, 0xeb, 0x16, 0xee, 0xc1, 0x49, 0xab, 0x35, 0x3a, 0x8e, 0xf0, 0xe8, 0xe1, 0x7c, 0xfe, 0xd6, + 0x40, 0xb0, 0x7d, 0xf2, 0xc0, 0x7e, 0xab, 0xcf, 0x77, 0xd0, 0xf4, 0xd0, 0x00, 0x6d, 0xc4, 0x67, 0xa6, 0xe5, 0xb3, + 0x07, 0xf0, 0x9f, 0xf9, 0x36, 0x4d, 0x97, 0xdf, 0x72, 0x34, 0xb1, 0x8b, 0xd2, 0x66, 0x0f, 0x5a, 0x50, 0x63, 0xcc, + 0x3f, 0x0e, 0x0b, 0x0e, 0x68, 0x34, 0xec, 0xc0, 0xff, 0x45, 0x78, 0x9c, 0x5f, 0xbd, 0x76, 0x38, 0x3b, 0x1e, 0xd3, + 0x71, 0x2b, 0xc2, 0x63, 0xf9, 0x51, 0xe9, 0x0f, 0x0f, 0x45, 0x1a, 0x75, 0x3a, 0xe7, 0x43, 0x53, 0x66, 0xf1, 0x8b, + 0xe2, 0x06, 0x8f, 0x5b, 0xa6, 0x95, 0x09, 0x7d, 0xab, 0x86, 0x57, 0x12, 0x56, 0x12, 0xfe, 0x8b, 0xf0, 0x04, 0xb4, + 0x70, 0xae, 0x95, 0x73, 0xbb, 0x1d, 0x26, 0xef, 0x0c, 0x6a, 0x8e, 0xee, 0x03, 0xbc, 0xfc, 0x32, 0x8e, 0x28, 0x3d, + 0xed, 0xb4, 0x22, 0x6c, 0x46, 0x7d, 0xde, 0x82, 0xff, 0x22, 0x6c, 0x21, 0x67, 0xe0, 0x3a, 0xf9, 0xf8, 0xec, 0xe5, + 0x4d, 0x1a, 0xd1, 0xd1, 0x78, 0x0c, 0x4b, 0x62, 0x26, 0xe3, 0x8b, 0x4d, 0xa5, 0x60, 0x77, 0xbf, 0xde, 0xb8, 0xed, + 0x62, 0x12, 0xb4, 0x83, 0xce, 0xd9, 0x83, 0xe1, 0x49, 0x84, 0xdf, 0x8e, 0x38, 0x15, 0xb0, 0x4a, 0xd9, 0xe8, 0x34, + 0x3b, 0xcd, 0x4c, 0xc2, 0x44, 0xa6, 0xd1, 0x09, 0x2c, 0x79, 0x27, 0xc2, 0xfc, 0xcb, 0xd5, 0x9d, 0x45, 0x37, 0xa8, + 0xed, 0x10, 0x64, 0xdc, 0x62, 0x67, 0xe7, 0x59, 0x84, 0x73, 0xfa, 0xe5, 0xd9, 0xaf, 0x45, 0x1a, 0xb1, 0x33, 0x76, + 0x36, 0xa6, 0xfe, 0xfb, 0x0f, 0x35, 0x35, 0x35, 0x5a, 0xe3, 0x53, 0x48, 0xba, 0x11, 0x66, 0xac, 0xf7, 0xb3, 0xb1, + 0xc1, 0x90, 0x57, 0x33, 0x29, 0xb2, 0xa7, 0xe3, 0xb1, 0xb4, 0x58, 0x4c, 0x61, 0x13, 0xfe, 0x09, 0xd0, 0xa6, 0xa3, + 0xd1, 0x39, 0x3b, 0x8b, 0xf0, 0x9f, 0x76, 0x97, 0xb8, 0x09, 0xfc, 0x69, 0x31, 0x9b, 0xb9, 0xdd, 0xfe, 0xa7, 0x05, + 0x0a, 0xcc, 0x77, 0x4c, 0xc7, 0x74, 0xd4, 0x89, 0xf0, 0x9f, 0x06, 0x2e, 0xa3, 0x63, 0xf8, 0x0f, 0x0a, 0x40, 0x67, + 0x0f, 0x5a, 0x8c, 0x3d, 0x68, 0x99, 0xaf, 0x30, 0xcf, 0xcd, 0x7c, 0x78, 0x96, 0xb5, 0x23, 0xfc, 0xa7, 0x43, 0xc7, + 0xf1, 0x98, 0xb6, 0x00, 0x1d, 0xff, 0x74, 0xe8, 0xd8, 0x69, 0x0d, 0x3b, 0xd4, 0x7c, 0x5b, 0xac, 0x39, 0xbf, 0x9f, + 0x31, 0x98, 0xdc, 0x9f, 0x16, 0x21, 0xef, 0xdf, 0x3f, 0x3f, 0x7f, 0xf0, 0x00, 0x3e, 0x4d, 0xdb, 0xe5, 0xa7, 0xd2, + 0x0f, 0x73, 0x83, 0x64, 0xad, 0xec, 0x04, 0xe8, 0xe4, 0x9f, 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, 0x97, 0x7e, 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, 0x6a, 0x2e, 0x66, 0x69, 0x34, 0x1a, 0xd1, 0xd6, + 0x08, 0xee, 0x38, 0xe5, 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, 0xad, 0xef, 0x13, 0x1a, 0x7b, + 0xb6, 0x9d, 0x93, 0xe5, 0x1a, 0x97, 0xc1, 0x54, 0x3f, 0xb3, 0x3b, 0x15, 0x2b, 0x65, 0x38, 0xd9, 0x20, 0x05, 0x1c, + 0x1e, 0x9c, 0xfb, 0x80, 0xf3, 0x10, 0x05, 0x41, 0x52, 0x90, 0x56, 0x57, 0x5c, 0x78, 0xaf, 0xd5, 0xae, 0x80, 0x10, + 0x0b, 0x90, 0x5e, 0x10, 0x4a, 0x34, 0x44, 0xa2, 0xb1, 0xc2, 0xa4, 0x37, 0xe6, 0x37, 0x32, 0xa5, 0xb4, 0xee, 0x01, + 0x94, 0x50, 0x1f, 0x83, 0x1e, 0xae, 0xa4, 0x21, 0x4a, 0x13, 0xea, 0x4a, 0x62, 0x22, 0x4a, 0xbf, 0x10, 0x3a, 0x56, + 0xaa, 0x5f, 0x0c, 0x70, 0xfb, 0x0c, 0x61, 0x88, 0xd5, 0x40, 0xfa, 0xf2, 0xf2, 0xb2, 0x7d, 0x76, 0x60, 0x84, 0xbe, + 0xcb, 0xcb, 0x73, 0xfb, 0x03, 0xfe, 0x1d, 0x54, 0xf1, 0xb1, 0x61, 0x7c, 0x8f, 0x58, 0xa0, 0xd1, 0x33, 0xfc, 0xf5, + 0x23, 0xb6, 0x5a, 0xc5, 0x8f, 0x18, 0x81, 0x19, 0xe3, 0x47, 0x2c, 0x31, 0x77, 0x24, 0xd6, 0x13, 0x87, 0xf4, 0x41, + 0x73, 0xd6, 0xc2, 0x10, 0xb5, 0xdd, 0x73, 0xde, 0x8f, 0x58, 0x9f, 0xd7, 0xbd, 0xb8, 0xab, 0x50, 0xc9, 0x07, 0x07, + 0xcb, 0x22, 0xd5, 0x56, 0x4c, 0xd0, 0x56, 0x4c, 0xd0, 0x56, 0x4c, 0xd0, 0x55, 0xb0, 0xfa, 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, 0xb8, 0x1f, 0xba, 0x7f, 0xdf, 0x08, 0x66, 0x55, 0x30, 0xba, 0x06, 0x24, 0x75, 0x41, + 0x0a, 0x39, 0x37, 0x52, 0x5a, 0x81, 0xd2, 0x91, 0x8e, 0x0b, 0xd0, 0x50, 0x7a, 0x05, 0x65, 0x19, 0x33, 0xb5, 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, 0xc9, 0x2b, 0x51, 0x1f, 0x71, 0x13, 0x6d, + 0xe7, 0x82, 0x24, 0xad, 0xd6, 0x71, 0xfb, 0xb8, 0x75, 0xde, 0xe3, 0x87, 0xed, 0x4e, 0xf2, 0xa0, 0x93, 0x1a, 0x45, + 0xc4, 0x5c, 0xde, 0x80, 0x02, 0xe6, 0xa8, 0x93, 0x9c, 0xa0, 0xc3, 0x76, 0xd2, 0x3a, 0x3d, 0x6d, 0xc2, 0x3f, 0xf8, + 0xbd, 0x2e, 0xab, 0x9d, 0xb4, 0x4e, 0x4e, 0x7b, 0xfc, 0x68, 0xa3, 0x52, 0xcc, 0x1b, 0x50, 0x10, 0x1d, 0x99, 0x4a, + 0x18, 0xea, 0x57, 0xcb, 0xfb, 0x6c, 0x4b, 0xcf, 0xf3, 0x5e, 0xc7, 0xd2, 0xaa, 0xe2, 0x00, 0xaa, 0xfe, 0x6b, 0x62, + 0x80, 0xe8, 0xbf, 0x86, 0x65, 0x44, 0xdc, 0x65, 0x01, 0xa2, 0xf6, 0x23, 0x1e, 0x8b, 0x06, 0x3b, 0x8c, 0x6d, 0xbe, + 0x86, 0xba, 0x4d, 0x88, 0x52, 0x87, 0x27, 0x2e, 0x57, 0x85, 0xb9, 0x13, 0x84, 0x9a, 0x0a, 0x72, 0x87, 0x2e, 0x57, + 0x86, 0xb9, 0x43, 0x84, 0x9a, 0x12, 0x72, 0x69, 0xca, 0x13, 0x0a, 0x39, 0x3a, 0xa1, 0x4d, 0x03, 0xc9, 0x6a, 0x51, + 0x9e, 0x33, 0x3f, 0x6c, 0x3e, 0x86, 0xe5, 0x31, 0x04, 0xc5, 0x09, 0xd2, 0x02, 0x5e, 0x32, 0x29, 0xb5, 0x39, 0x2d, + 0x5c, 0xaa, 0x71, 0x20, 0xa3, 0x01, 0xff, 0x1c, 0x32, 0xf3, 0xbc, 0x45, 0xab, 0x77, 0x7c, 0xd6, 0x4a, 0xdb, 0xe0, + 0x92, 0x0d, 0xb2, 0xb6, 0xb0, 0xb2, 0xb6, 0xf0, 0xb2, 0xb6, 0xf0, 0xb2, 0x36, 0x08, 0xf0, 0x41, 0xdf, 0xff, 0xc8, + 0x9a, 0x99, 0x0b, 0x2f, 0x6d, 0x66, 0xac, 0x51, 0x44, 0xac, 0x57, 0xab, 0xe5, 0x1a, 0x2c, 0x9a, 0x2a, 0x95, 0xbb, + 0xaa, 0xd4, 0x9f, 0xcb, 0x22, 0x6d, 0xe1, 0x49, 0x0a, 0x5a, 0xee, 0x16, 0xa6, 0x66, 0x73, 0x7b, 0xaa, 0xb0, 0x19, + 0x2d, 0xa7, 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, 0x60, 0x81, 0xb1, + 0x26, 0x66, 0xd4, 0x1b, 0x9d, 0xb7, 0x21, 0x38, 0x9a, 0x2d, 0xa9, 0x13, 0x6a, 0x7c, 0xc4, 0xcb, 0x31, 0x7f, 0xad, + 0xa1, 0x7d, 0x02, 0x2f, 0xd7, 0x3c, 0xd4, 0x71, 0x0b, 0x4c, 0x44, 0xa2, 0x22, 0xea, 0x19, 0xb2, 0x90, 0x1a, 0x9d, + 0x8d, 0x33, 0xfd, 0xfe, 0xbc, 0xe1, 0x71, 0x6b, 0x29, 0x41, 0xf8, 0x5e, 0xc3, 0x67, 0x56, 0x85, 0x00, 0x28, 0x2d, + 0x5b, 0x9d, 0x59, 0x9a, 0x3d, 0x12, 0xba, 0x60, 0x9e, 0xee, 0x63, 0x4b, 0xf5, 0x04, 0x91, 0xca, 0x38, 0x47, 0x92, + 0x2a, 0x3a, 0x32, 0x38, 0x0b, 0x93, 0x5b, 0x6a, 0x5c, 0x67, 0x5e, 0xd8, 0x3f, 0x5f, 0x69, 0xe0, 0x5b, 0x58, 0x4c, + 0x86, 0xde, 0x25, 0xf7, 0xda, 0xc4, 0x10, 0x22, 0xfb, 0xfb, 0xd6, 0x72, 0xdc, 0x7c, 0x6d, 0x9a, 0x8e, 0x9b, 0x44, + 0x93, 0x0d, 0x3b, 0xd4, 0xaf, 0xd1, 0x3f, 0xde, 0x33, 0xae, 0x98, 0x0c, 0x51, 0x40, 0xb3, 0x0d, 0x58, 0x65, 0x05, + 0x2c, 0xe5, 0xea, 0x95, 0x0e, 0x93, 0xd0, 0xbb, 0x19, 0xf3, 0xba, 0x98, 0x0c, 0x77, 0x3e, 0x71, 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, 0x31, 0x47, 0x9a, 0x0c, 0x21, 0x26, 0x3d, + 0xfc, 0xb5, 0x91, 0x63, 0xba, 0x9e, 0x84, 0xc3, 0x2a, 0xc8, 0x5e, 0x72, 0x9a, 0x32, 0x4c, 0x49, 0xe7, 0xb0, 0x30, + 0xb1, 0x63, 0x44, 0x42, 0x9b, 0x2a, 0xa1, 0x38, 0x27, 0x71, 0x4c, 0x0f, 0x33, 0x88, 0x80, 0xd3, 0xee, 0xd1, 0x34, + 0xa6, 0x8d, 0x0c, 0x1d, 0xc5, 0xed, 0x06, 0x3d, 0xcc, 0x10, 0x6a, 0xb4, 0x41, 0x67, 0x2a, 0x49, 0xbb, 0x99, 0x43, + 0x4c, 0x4c, 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, 0x43, 0x91, 0xaf, 0x8d, 0x2d, 0xcf, 0x5c, 0xe6, + 0x2e, 0x38, 0x68, 0x05, 0xa4, 0xd2, 0xc1, 0x0a, 0xea, 0x3c, 0x0b, 0xc0, 0x84, 0xb5, 0xfd, 0xe3, 0x43, 0xdf, 0xad, + 0xb3, 0x5c, 0x8a, 0xc0, 0x81, 0x0c, 0x6c, 0xde, 0x3f, 0x3b, 0xb7, 0x19, 0x80, 0xea, 0x9a, 0xe6, 0xf3, 0x29, 0xdd, + 0xf2, 0xd2, 0x2d, 0x26, 0x43, 0xb7, 0xb3, 0xca, 0x66, 0x18, 0x2d, 0x6c, 0x48, 0xe9, 0xba, 0x3f, 0x25, 0x80, 0xda, + 0xfb, 0x70, 0x26, 0xd4, 0x28, 0xc9, 0x6d, 0x8d, 0x49, 0xc1, 0xee, 0x54, 0x46, 0x73, 0x16, 0x57, 0x07, 0x70, 0x35, + 0x4c, 0x46, 0x5e, 0x80, 0xe5, 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, + 0x94, 0xec, 0xdf, 0x18, 0x46, 0xc3, 0x0d, 0x43, 0xb0, 0x89, 0x8d, 0xae, 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, 0x67, 0x98, 0x35, 0x68, 0x0d, 0xbf, 0x57, 0xae, + 0xe9, 0x0b, 0x2a, 0xaa, 0xc1, 0xa4, 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, 0xc4, 0xd0, 0x33, 0xa7, 0x10, + 0x27, 0x5e, 0x8f, 0x0c, 0x49, 0xbc, 0xd1, 0x58, 0xa3, 0x38, 0x38, 0x6f, 0x9f, 0x86, 0x54, 0x75, 0x2b, 0xb0, 0x1e, + 0x21, 0xd1, 0x42, 0x58, 0xd3, 0xcb, 0x51, 0x14, 0xb0, 0x20, 0x4e, 0xbb, 0x5b, 0x3b, 0x20, 0x0e, 0x0e, 0x36, 0xcf, + 0x0b, 0xff, 0xc4, 0xc1, 0xd6, 0xb3, 0x06, 0x95, 0xdd, 0x9e, 0x7f, 0x78, 0xc9, 0x5a, 0xf4, 0xf2, 0x00, 0x51, 0x7c, + 0x88, 0xab, 0xfb, 0x86, 0xc2, 0xf7, 0xab, 0xf8, 0x7e, 0x2e, 0xa7, 0x79, 0x66, 0x32, 0x4c, 0x5f, 0x83, 0x60, 0x6c, + 0x6f, 0xc2, 0x09, 0x95, 0x36, 0x89, 0xff, 0xb2, 0xe3, 0xa0, 0x13, 0xf7, 0x30, 0x4c, 0xd8, 0xe8, 0xdf, 0xa1, 0x05, + 0x70, 0x05, 0x1b, 0xe7, 0xfb, 0xbd, 0x5a, 0xd5, 0x9e, 0x01, 0xb2, 0x8f, 0xcd, 0xa0, 0x83, 0x03, 0xae, 0x9e, 0x81, + 0xd1, 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, 0x93, 0xf0, 0xad, 0x07, 0xa9, 0x0e, 0x0e, 0x78, + 0x15, 0x16, 0x2a, 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, 0x40, + 0x46, 0x03, 0xe9, 0xd0, 0xc2, 0x1b, 0x95, 0x87, 0x39, 0x9d, 0xcf, 0xf3, 0x3b, 0xf3, 0x26, 0x57, 0xc0, 0x51, 0x55, + 0x17, 0x4d, 0x2e, 0x1a, 0x1e, 0x2e, 0x80, 0xa7, 0x07, 0xdc, 0x43, 0xc6, 0x9b, 0xb5, 0xbc, 0xdc, 0x16, 0x08, 0x24, + 0x33, 0x45, 0x64, 0xb3, 0xdd, 0x55, 0x97, 0x20, 0x97, 0x35, 0x9b, 0x48, 0xbb, 0x20, 0xe1, 0x98, 0x83, 0x4c, 0xa6, + 0xac, 0xc7, 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, 0x67, + 0x28, 0xca, 0xf9, 0x14, 0x2a, 0x78, 0xd6, 0x28, 0x10, 0x51, 0xf8, 0x6a, 0xb5, 0x0f, 0xaf, 0x06, 0xb9, 0x36, 0xc1, + 0xc5, 0xd5, 0xfd, 0xac, 0x5e, 0x08, 0x81, 0x71, 0x30, 0xd2, 0x32, 0x17, 0x85, 0x4e, 0xde, 0x64, 0x17, 0xa2, 0xdb, + 0x68, 0x30, 0x13, 0xd0, 0x89, 0x40, 0xf4, 0x36, 0xf0, 0x3f, 0x84, 0x3f, 0x36, 0x46, 0x93, 0x62, 0x36, 0xd2, 0x1d, + 0x84, 0xe0, 0xae, 0x25, 0xac, 0x56, 0xca, 0x46, 0x52, 0x31, 0x39, 0x36, 0xa6, 0x4a, 0xd9, 0x4f, 0x19, 0xb2, 0xb5, + 0x32, 0xe3, 0xe0, 0x6e, 0xab, 0xbf, 0xad, 0xf6, 0xf3, 0x1e, 0xb7, 0xd7, 0x78, 0xdc, 0xc4, 0x27, 0x30, 0x80, 0x5a, + 0x6e, 0x6c, 0x70, 0x6b, 0x4f, 0x1f, 0x5b, 0xe3, 0x5f, 0xb6, 0x09, 0x41, 0x51, 0xfa, 0xe3, 0xdb, 0x9b, 0x5b, 0x1f, + 0x9f, 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, 0x1a, 0xb1, 0x47, + 0x01, 0x2f, 0x18, 0x0d, 0xca, 0x10, 0x56, 0x66, 0xe3, 0x37, 0xdb, 0x55, 0x63, 0xef, 0x69, 0x85, 0x77, 0xb0, 0x3c, + 0xa6, 0xf1, 0x2d, 0xa7, 0xcf, 0x3e, 0x07, 0x78, 0xb3, 0x3e, 0x1f, 0x74, 0xdf, 0xc4, 0x0a, 0x1d, 0x1c, 0xbc, 0x89, + 0x25, 0xea, 0x5d, 0x31, 0x73, 0xe7, 0x06, 0x5e, 0xdf, 0x7d, 0x6e, 0x86, 0x2f, 0x03, 0x04, 0xb8, 0x62, 0x9b, 0x92, + 0xcd, 0x5b, 0x13, 0x63, 0x23, 0x85, 0x18, 0xde, 0x10, 0x49, 0xd8, 0x81, 0x04, 0x7a, 0x7d, 0x13, 0x42, 0xbb, 0xcb, + 0x08, 0x03, 0x16, 0xbe, 0xf4, 0xc9, 0x63, 0xc9, 0x8c, 0x15, 0x13, 0x56, 0xac, 0x56, 0xef, 0xa9, 0xf5, 0xb3, 0xdb, + 0x08, 0x09, 0xa9, 0xba, 0x8d, 0x06, 0x35, 0xe3, 0x07, 0xf1, 0x81, 0x0e, 0xf0, 0xfe, 0x9b, 0xb8, 0x40, 0x08, 0x2c, + 0x8c, 0xb8, 0x58, 0x78, 0x9f, 0xb2, 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, 0x04, 0x47, 0x52, 0x28, 0xdd, 0xa2, + 0xe8, 0xf5, 0x30, 0x9e, 0xce, 0x45, 0x04, 0x73, 0x13, 0x49, 0xc2, 0x2d, 0x07, 0xb8, 0x8b, 0x38, 0xaf, 0x43, 0x45, + 0x96, 0x51, 0x64, 0x22, 0xda, 0xe2, 0x5b, 0xf3, 0x27, 0xb9, 0xc5, 0x77, 0xf6, 0xc7, 0x5d, 0xa0, 0x4c, 0x7a, 0x5e, + 0xd3, 0x36, 0x70, 0x17, 0xff, 0x2d, 0x4a, 0x22, 0x40, 0x6b, 0x17, 0xcc, 0x50, 0xd4, 0xdf, 0x77, 0x53, 0x36, 0xec, + 0x84, 0x68, 0x10, 0x85, 0x45, 0x40, 0x3a, 0xff, 0xfa, 0x2b, 0x42, 0x3d, 0x01, 0x51, 0x83, 0xdc, 0xc9, 0xd6, 0x6c, + 0xa3, 0x46, 0x94, 0x44, 0x69, 0xec, 0x83, 0x52, 0xc0, 0xce, 0x88, 0xa2, 0xe0, 0x6d, 0x97, 0x72, 0x18, 0x1f, 0x6a, + 0xc3, 0x30, 0x83, 0xaa, 0xc2, 0x6c, 0x5c, 0x2e, 0x37, 0x83, 0x1a, 0x19, 0xa8, 0x0a, 0x13, 0x51, 0x06, 0xd9, 0x07, + 0xcf, 0x18, 0x61, 0x07, 0x07, 0xac, 0x2f, 0x06, 0xc1, 0x0b, 0x66, 0xd5, 0x75, 0xb8, 0x0e, 0x17, 0x2e, 0xa6, 0x10, + 0x55, 0x7e, 0xb5, 0xb2, 0x7f, 0xc9, 0x07, 0x23, 0xcd, 0xc0, 0x53, 0x74, 0xc1, 0x19, 0x2b, 0x76, 0xcb, 0x62, 0x89, + 0x96, 0xbf, 0x83, 0x65, 0x9f, 0x8b, 0x11, 0xc8, 0xdd, 0x54, 0xdb, 0x1e, 0xea, 0x73, 0xa3, 0x51, 0x08, 0x22, 0xf4, + 0x56, 0x47, 0x1a, 0x9e, 0xeb, 0x30, 0xaf, 0x16, 0x69, 0x37, 0x53, 0x65, 0xc0, 0x54, 0x38, 0x52, 0x12, 0xb0, 0x52, + 0x37, 0x74, 0x12, 0x7e, 0xd4, 0xa9, 0xa4, 0x63, 0x21, 0x01, 0x0a, 0x1c, 0x99, 0xcb, 0x79, 0x13, 0x10, 0x9f, 0xa1, + 0x1d, 0x44, 0x2e, 0x30, 0xa1, 0xa9, 0xcb, 0x96, 0x2e, 0x72, 0x55, 0x34, 0x93, 0x0b, 0xc5, 0x16, 0x73, 0x38, 0xdf, + 0xcb, 0xb4, 0x2c, 0xe7, 0xd9, 0xe7, 0x7a, 0x0a, 0x18, 0x44, 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, 0x43, 0x36, 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, 0x36, 0x94, 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, 0xfb, 0x4a, 0xb9, 0x71, 0xdc, 0x2f, 0x7e, 0x24, 0x50, 0x2d, 0x00, 0x4d, 0xcc, 0x56, 0x2d, 0x04, 0x4c, 0xa3, + 0xc9, 0x06, 0x73, 0xa0, 0x44, 0xc9, 0x42, 0xfb, 0x20, 0xfa, 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, 0xaf, 0x05, 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, + 0xa1, 0x10, 0x40, 0xf3, 0x54, 0xa9, 0xa0, 0xcc, 0x27, 0x96, 0x28, 0x18, 0xfa, 0x9f, 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, 0x78, 0x57, 0x1b, 0xfb, 0xb8, 0x6b, 0xdd, 0x10, 0x20, 0x87, 0x1a, 0x1d, 0x99, 0x87, 0x13, 0xbb, + 0x48, 0x1f, 0x92, 0x76, 0x0b, 0x82, 0xa5, 0xed, 0xa0, 0x7c, 0x3f, 0x6d, 0xc0, 0x54, 0x27, 0xb7, 0x4d, 0xa0, 0xd5, + 0xf0, 0x96, 0xd2, 0x5d, 0x93, 0x27, 0x77, 0x58, 0x05, 0x38, 0xc3, 0x0e, 0x59, 0x43, 0x1c, 0x0a, 0xe4, 0x82, 0xcc, + 0xda, 0x0d, 0xa0, 0xa9, 0xe8, 0xd8, 0x37, 0xfd, 0xbc, 0x71, 0xd4, 0x45, 0x33, 0x39, 0x3d, 0xfc, 0x7a, 0x70, 0x10, + 0xcb, 0x06, 0x79, 0x84, 0xf0, 0x92, 0x82, 0xcd, 0x36, 0xf8, 0xb8, 0x71, 0xcb, 0xc4, 0xa7, 0x2a, 0xa0, 0x8e, 0x0b, + 0x55, 0x3b, 0xd6, 0xaa, 0xce, 0xca, 0xdd, 0xe0, 0xc7, 0xd4, 0x41, 0x8d, 0x20, 0xcd, 0x8e, 0xae, 0x13, 0x42, 0xf9, + 0xb7, 0x9a, 0x43, 0x1a, 0x6c, 0xcb, 0xc6, 0x47, 0x8a, 0x7e, 0x78, 0xd4, 0xfc, 0x1a, 0x94, 0xa9, 0x99, 0x26, 0x3d, + 0x6a, 0x3c, 0x42, 0x3f, 0x3c, 0x0a, 0x5c, 0x0a, 0x79, 0xc5, 0x9e, 0x78, 0x6e, 0xe4, 0x37, 0xcb, 0x95, 0xfe, 0x06, + 0x92, 0x7d, 0x41, 0x7e, 0x03, 0x2c, 0xa7, 0xe4, 0xb7, 0x58, 0x36, 0x21, 0xd4, 0x22, 0xf9, 0x2d, 0x2e, 0xe0, 0x47, + 0x4e, 0x7e, 0x8b, 0x01, 0xdb, 0xf1, 0xd4, 0xfc, 0x28, 0x4a, 0x60, 0x80, 0x1b, 0x9b, 0xb4, 0xde, 0x6c, 0xc5, 0x6a, + 0x25, 0x0e, 0x0e, 0xa4, 0xfd, 0x45, 0x2f, 0xb3, 0x83, 0x83, 0xfc, 0x62, 0x1a, 0xd8, 0xde, 0xea, 0x5d, 0xf4, 0xc5, + 0x20, 0x14, 0x0e, 0x4c, 0xd3, 0x78, 0x0d, 0xaf, 0x6a, 0x94, 0x15, 0x1a, 0x68, 0x1e, 0x77, 0xee, 0x9f, 0x9d, 0x63, + 0xf8, 0xf7, 0x7e, 0x50, 0xf0, 0xe7, 0x92, 0xef, 0x22, 0x6d, 0xd6, 0x3c, 0xab, 0xea, 0x5c, 0x06, 0xf8, 0x8c, 0x19, + 0x6a, 0x8a, 0x83, 0x03, 0x7e, 0x11, 0xe0, 0x32, 0x66, 0xa8, 0x11, 0x58, 0xec, 0x3d, 0x2c, 0xed, 0xc9, 0x0c, 0xd7, + 0x04, 0x8f, 0xe8, 0xf2, 0x7e, 0x31, 0xb8, 0xd0, 0x8e, 0x9a, 0x84, 0xa1, 0xb6, 0x15, 0x69, 0xb9, 0x4d, 0xd6, 0x15, + 0x4d, 0x75, 0xd9, 0xee, 0x22, 0x49, 0x54, 0x43, 0x5c, 0x5e, 0xb6, 0x31, 0xa8, 0xe4, 0x7b, 0x8a, 0xc8, 0x54, 0x10, + 0xef, 0x0e, 0xb8, 0xcc, 0x65, 0xaa, 0xf0, 0x94, 0xa7, 0xc2, 0xcb, 0xd9, 0xaf, 0xbd, 0xf5, 0xb4, 0x71, 0xd0, 0x34, + 0x3d, 0x33, 0x2c, 0x7a, 0xaa, 0x74, 0x2c, 0x84, 0x4d, 0xaa, 0x06, 0xf0, 0x46, 0x61, 0x89, 0x79, 0xcc, 0x7a, 0xd3, + 0x31, 0x88, 0x01, 0xad, 0x1a, 0x6d, 0xc8, 0x84, 0xcf, 0x75, 0xaa, 0x60, 0xa0, 0xa6, 0xf0, 0x05, 0x90, 0xa9, 0xac, + 0x32, 0xcc, 0xf6, 0x0d, 0x43, 0x01, 0x01, 0x05, 0x2e, 0x09, 0x0b, 0x24, 0x78, 0xb8, 0xfd, 0x08, 0x08, 0x47, 0x9d, + 0x5c, 0xd8, 0xc9, 0x5d, 0x28, 0xe8, 0x4e, 0x0c, 0x2e, 0x74, 0x17, 0x89, 0x46, 0xc3, 0x71, 0xdb, 0x97, 0xc2, 0x0c, + 0xa2, 0xd9, 0x1e, 0x5c, 0xb2, 0x2e, 0x52, 0xcd, 0x66, 0x69, 0x00, 0x79, 0xd9, 0x5a, 0xad, 0xd4, 0x85, 0x6f, 0xa4, + 0xe7, 0xcf, 0x71, 0xc3, 0x77, 0x79, 0xc1, 0xf3, 0x37, 0x49, 0xfa, 0x11, 0x50, 0x55, 0xe0, 0xb3, 0xe5, 0x3c, 0xc2, + 0x91, 0x79, 0xbe, 0x0e, 0xfe, 0x9a, 0x67, 0xc7, 0x22, 0x1c, 0xb9, 0x17, 0xed, 0xa2, 0x41, 0x35, 0x58, 0x9e, 0x95, + 0xc1, 0xd8, 0x79, 0x72, 0x0d, 0x8c, 0x83, 0xfe, 0x5b, 0xa1, 0x65, 0xf5, 0x3b, 0xc9, 0x5d, 0x58, 0x12, 0xe5, 0x1f, + 0x59, 0x73, 0xa3, 0x5a, 0xef, 0x76, 0x04, 0xe5, 0x38, 0xf2, 0x55, 0xe1, 0xb1, 0x82, 0xef, 0xbc, 0xf2, 0xd8, 0x76, + 0x8f, 0x8b, 0x2f, 0xcb, 0x1e, 0x80, 0xf3, 0x5e, 0xaf, 0x11, 0xfe, 0x4d, 0xee, 0x7c, 0x69, 0x38, 0xba, 0x96, 0xe2, + 0x09, 0xd5, 0x34, 0x6a, 0xbc, 0x31, 0x86, 0x6f, 0x56, 0xce, 0xea, 0x7e, 0x6b, 0x1c, 0xec, 0xdf, 0xea, 0x1e, 0x02, + 0x45, 0xd4, 0x1e, 0x45, 0xb2, 0xb2, 0xaf, 0x09, 0x0f, 0x22, 0x03, 0xd3, 0xb7, 0x1d, 0xf0, 0xf0, 0x63, 0xa4, 0xe0, + 0xbe, 0x6c, 0xf9, 0x24, 0x0a, 0x11, 0x58, 0x6b, 0x4e, 0xd3, 0x90, 0x62, 0xfb, 0x30, 0x0e, 0xb6, 0x6b, 0x14, 0x72, + 0xdd, 0x63, 0x55, 0x27, 0xa6, 0x55, 0x37, 0x46, 0xea, 0x60, 0x9b, 0x2c, 0x38, 0xab, 0x7a, 0x37, 0x12, 0x4a, 0xf5, + 0x7e, 0x9c, 0x79, 0x03, 0xb4, 0xd9, 0x36, 0x8f, 0x2a, 0xdb, 0x57, 0xe6, 0x14, 0x18, 0xf2, 0xee, 0x97, 0xc1, 0xb1, + 0x2e, 0xe1, 0xd8, 0x8d, 0x03, 0xc8, 0x4a, 0x72, 0xb9, 0x74, 0x2f, 0xc0, 0xf1, 0xbe, 0x1c, 0xac, 0xcb, 0xf7, 0xe0, + 0x02, 0x3c, 0xa8, 0x46, 0x2a, 0xb2, 0x90, 0x33, 0xf0, 0x8f, 0x29, 0xd6, 0xf4, 0x43, 0xfc, 0x2b, 0x1c, 0xf0, 0x15, + 0x92, 0xa6, 0x56, 0xfd, 0x04, 0xef, 0x34, 0x81, 0xc2, 0xdb, 0xd6, 0xfd, 0x53, 0x86, 0x0e, 0xb1, 0x75, 0x9d, 0x8a, + 0xf5, 0x39, 0xad, 0x2b, 0x56, 0xca, 0xc2, 0x01, 0xd5, 0x8a, 0xd1, 0x3a, 0x75, 0xfe, 0xa9, 0xee, 0x71, 0xa7, 0x87, + 0x02, 0x7c, 0x63, 0xb8, 0x14, 0xcf, 0x0a, 0x88, 0xd6, 0x15, 0xea, 0xd3, 0x7e, 0x96, 0xe1, 0xeb, 0xc5, 0x7d, 0xb8, + 0x27, 0x2c, 0x79, 0xce, 0xf2, 0xc5, 0x6d, 0x58, 0x20, 0x05, 0x14, 0x4a, 0x61, 0xb1, 0x5a, 0xc5, 0x02, 0x02, 0x36, + 0xfc, 0xe9, 0x42, 0xf8, 0xba, 0xb7, 0x3a, 0x8c, 0xfe, 0x0e, 0xea, 0x62, 0xaf, 0x1e, 0x31, 0x26, 0xac, 0x28, 0xbc, + 0x74, 0x52, 0x59, 0xd0, 0xd7, 0xae, 0x3e, 0x44, 0x35, 0xe5, 0x5e, 0x6c, 0xf4, 0xbd, 0xef, 0xf8, 0x8c, 0xc9, 0x05, + 0x3c, 0x92, 0x84, 0x19, 0x51, 0x4c, 0xfb, 0x6f, 0xa0, 0x20, 0xf0, 0xd2, 0x0e, 0x0f, 0xf1, 0x11, 0xf8, 0x2a, 0x4f, + 0xeb, 0x64, 0xe6, 0x9f, 0xde, 0x88, 0x4c, 0x68, 0xcc, 0xa8, 0x17, 0x81, 0x17, 0x11, 0x88, 0x50, 0x84, 0x44, 0x4c, + 0x8c, 0xa2, 0x5e, 0x64, 0x5c, 0xb2, 0x22, 0xb0, 0x1a, 0x03, 0x25, 0x77, 0x84, 0xe7, 0xaa, 0x22, 0x62, 0x61, 0x4d, + 0x1d, 0x54, 0x62, 0xa9, 0x31, 0xd3, 0x3e, 0xea, 0x54, 0x20, 0x2c, 0xb2, 0x4d, 0x41, 0x59, 0x6f, 0xa8, 0x0b, 0xb0, + 0x24, 0xc6, 0xf4, 0x96, 0x27, 0xd7, 0xc0, 0xcd, 0xb1, 0x91, 0x2b, 0xba, 0xe4, 0x57, 0xa0, 0x9e, 0x4e, 0x0b, 0x7c, + 0x6d, 0x18, 0xb6, 0x51, 0x4a, 0xd7, 0x84, 0xe3, 0x8c, 0x14, 0x09, 0xbd, 0x85, 0x18, 0x16, 0x33, 0x2e, 0xd2, 0x1c, + 0xcf, 0xe8, 0x6d, 0x3a, 0xc5, 0x33, 0x2e, 0x9e, 0xd8, 0x65, 0x4f, 0x47, 0x90, 0xe4, 0x3f, 0x16, 0x6b, 0x62, 0x9e, + 0xe0, 0xfa, 0x5d, 0xb1, 0xe2, 0x11, 0xf0, 0x2a, 0x2a, 0x46, 0xdd, 0x91, 0xb1, 0x29, 0xe7, 0xba, 0x32, 0x5e, 0x7f, + 0xad, 0x63, 0x8a, 0x33, 0x9c, 0xa3, 0x24, 0x97, 0x98, 0xf5, 0x44, 0xfa, 0x1a, 0xe2, 0x57, 0x67, 0xd8, 0x3e, 0xdf, + 0xc5, 0x6f, 0x59, 0xfe, 0x4c, 0x16, 0xef, 0xcd, 0x96, 0xcf, 0x11, 0x14, 0x02, 0x17, 0x15, 0xd1, 0x84, 0xdb, 0xbd, + 0x45, 0x4f, 0x56, 0x4d, 0xd1, 0x5b, 0xdb, 0x94, 0x1b, 0xe2, 0x14, 0x02, 0xff, 0x26, 0x53, 0xde, 0x68, 0x63, 0xd6, + 0x6b, 0x7d, 0xa7, 0xd1, 0x29, 0x2a, 0x4b, 0x22, 0x0c, 0x6b, 0xd5, 0x54, 0xa9, 0x24, 0xa2, 0xa9, 0x9c, 0x84, 0xb7, + 0x34, 0xc0, 0x4e, 0x15, 0xce, 0xe4, 0x42, 0xe8, 0x54, 0x06, 0x78, 0x43, 0xab, 0xcd, 0xb5, 0xbc, 0xb5, 0x10, 0xd3, + 0xf8, 0xce, 0xfe, 0x60, 0xf8, 0xda, 0xa8, 0xf8, 0xdf, 0x82, 0x61, 0x8f, 0x4a, 0x05, 0xc0, 0x0f, 0x0c, 0x67, 0x01, + 0x72, 0x96, 0x9f, 0xbc, 0x05, 0xf0, 0x59, 0x16, 0xf2, 0x0e, 0x52, 0x99, 0x49, 0xbd, 0x83, 0x54, 0x06, 0xa9, 0xc6, + 0x73, 0x7d, 0x5f, 0x54, 0xca, 0xa2, 0xb0, 0x41, 0xa2, 0x70, 0xa9, 0x0e, 0x96, 0x44, 0x24, 0xd0, 0xae, 0x11, 0xe5, + 0x66, 0x5c, 0x40, 0x08, 0x43, 0x68, 0xdc, 0x7e, 0xd3, 0x5b, 0xf8, 0xbe, 0xb3, 0xf9, 0xcc, 0xe7, 0xdf, 0xd9, 0x7c, + 0xd3, 0x91, 0xc7, 0xf8, 0xfa, 0x6d, 0xa7, 0xb1, 0x8c, 0x97, 0x0e, 0x6b, 0x3f, 0x94, 0x0f, 0xc6, 0xb4, 0xcc, 0xc3, + 0xdc, 0xa4, 0x8d, 0x27, 0x01, 0x52, 0x36, 0x2b, 0x1e, 0xae, 0x83, 0xdb, 0xad, 0xc3, 0x98, 0x37, 0x49, 0x1b, 0xa1, + 0x43, 0x27, 0x5c, 0x89, 0xd8, 0x48, 0x4e, 0x87, 0x8f, 0x8e, 0xe0, 0xee, 0x65, 0xa6, 0x36, 0x7c, 0xa5, 0x6c, 0xb5, + 0x66, 0xbb, 0x75, 0xc8, 0x77, 0x56, 0x69, 0xb4, 0xf1, 0x8c, 0x91, 0x25, 0x78, 0xa0, 0xd1, 0xc2, 0xaa, 0x1a, 0xc0, + 0x65, 0xf5, 0x85, 0xf8, 0x6d, 0x41, 0x47, 0xe6, 0xfb, 0xd0, 0xa6, 0xbc, 0x5e, 0x68, 0x9f, 0xd4, 0xe4, 0x30, 0x88, + 0x0e, 0x72, 0x25, 0x83, 0x9c, 0x98, 0x1f, 0x91, 0xe4, 0x14, 0x5d, 0xb4, 0x7b, 0xc9, 0xe9, 0x21, 0x3f, 0xe4, 0x29, + 0xf0, 0xb0, 0x71, 0xd3, 0x57, 0x68, 0xb6, 0x7d, 0x9d, 0xc7, 0x8b, 0x21, 0xcf, 0x5c, 0xf3, 0x55, 0x07, 0x65, 0xaa, + 0x9d, 0x23, 0x64, 0x01, 0x8a, 0xf9, 0x5e, 0x82, 0xec, 0x7a, 0x37, 0x87, 0x3c, 0x85, 0x7e, 0xa0, 0x56, 0xc7, 0xd6, + 0x2a, 0x07, 0xf7, 0xdb, 0x02, 0x10, 0xcc, 0x77, 0x54, 0x9b, 0x8b, 0x4d, 0x6f, 0xc6, 0x55, 0x67, 0x87, 0xbc, 0x1a, + 0x61, 0x58, 0x66, 0xbb, 0x3f, 0x3f, 0xb5, 0xaa, 0xcb, 0xc3, 0x00, 0x22, 0xbf, 0x2d, 0xb8, 0x08, 0x3b, 0x0d, 0xbb, + 0x75, 0x39, 0x61, 0xa7, 0xf5, 0x59, 0x06, 0x45, 0xb6, 0x7b, 0xdd, 0x9a, 0x69, 0x7d, 0xb6, 0x57, 0xe0, 0x48, 0x08, + 0x93, 0x32, 0x2b, 0x9d, 0xc1, 0x15, 0xfa, 0xe1, 0x07, 0xe4, 0x5a, 0x7f, 0xbd, 0xd0, 0x3e, 0xbf, 0x44, 0x04, 0xc8, + 0xae, 0xba, 0x2e, 0xab, 0x43, 0x1f, 0x65, 0x13, 0x5f, 0x0f, 0x79, 0xb0, 0x72, 0x4f, 0x6f, 0xe7, 0x32, 0xf5, 0xf8, + 0xda, 0x6b, 0xa5, 0x5b, 0xc8, 0x09, 0xc4, 0xc3, 0x75, 0x17, 0x96, 0x05, 0x39, 0xbb, 0xb9, 0x85, 0x92, 0xe1, 0xc4, + 0x7d, 0xe9, 0x0f, 0xcc, 0x5e, 0x37, 0xf0, 0x8b, 0xe4, 0x14, 0xa6, 0xbe, 0xd9, 0xc3, 0x61, 0x07, 0xfa, 0x30, 0x70, + 0xd8, 0x6c, 0xd0, 0x67, 0x56, 0x10, 0x79, 0xcc, 0x0b, 0x8b, 0x67, 0x97, 0xa4, 0xdd, 0xe3, 0xa9, 0xdb, 0x4c, 0x46, + 0x34, 0x6a, 0x37, 0x79, 0x30, 0x33, 0xc0, 0x2f, 0x57, 0x36, 0x2c, 0xe2, 0xd7, 0x29, 0x80, 0x92, 0x2f, 0x56, 0xad, + 0x4f, 0x05, 0xaf, 0x7a, 0xc3, 0xe9, 0x66, 0xba, 0x5f, 0x37, 0xb8, 0xdd, 0xf5, 0xf0, 0x84, 0x07, 0x5f, 0x2c, 0x5a, + 0xfb, 0x89, 0x4f, 0x80, 0x03, 0x4a, 0x5a, 0xf7, 0x4f, 0xc1, 0x85, 0xb2, 0x84, 0xe5, 0x76, 0xb9, 0xd9, 0x56, 0x39, + 0x0b, 0x47, 0x5b, 0x32, 0xe0, 0x0e, 0x36, 0x21, 0x0a, 0x1d, 0x1c, 0x76, 0x70, 0xd2, 0x6e, 0x77, 0x4e, 0x71, 0x72, + 0x72, 0x0a, 0x03, 0x6d, 0x24, 0xa7, 0x87, 0x33, 0x65, 0x01, 0x18, 0xe4, 0xac, 0x5d, 0xbb, 0x8f, 0x20, 0x38, 0x54, + 0x28, 0x5e, 0xf3, 0xc3, 0x38, 0x6e, 0x27, 0xf7, 0x5b, 0xed, 0xd3, 0xf3, 0x06, 0x00, 0xa8, 0xe9, 0x3e, 0x5c, 0x8d, + 0xd7, 0x0b, 0x5d, 0xaf, 0x52, 0x22, 0x7c, 0xbd, 0x5a, 0xc3, 0x57, 0x6b, 0xb4, 0xd7, 0xd5, 0x14, 0x7c, 0x55, 0x27, + 0x9c, 0xdb, 0x22, 0x5e, 0x69, 0x13, 0x6e, 0x8b, 0xd8, 0x0e, 0x24, 0x06, 0xe9, 0x3c, 0x39, 0xed, 0x9c, 0x22, 0x3b, + 0x16, 0xed, 0xf0, 0xa3, 0xdc, 0x27, 0x5b, 0x45, 0x1a, 0x1a, 0x90, 0xa4, 0x9c, 0x9d, 0x5c, 0x80, 0x44, 0xcd, 0xc9, + 0x65, 0xbb, 0x39, 0x63, 0x89, 0x9f, 0x80, 0x49, 0x85, 0xe5, 0x2c, 0x57, 0xc1, 0x25, 0x05, 0x80, 0xb8, 0x00, 0xe3, + 0xa2, 0xfb, 0xa7, 0xbd, 0xfb, 0xc9, 0xe9, 0x59, 0xc7, 0x12, 0x3d, 0x7e, 0xd1, 0xa9, 0xa5, 0x99, 0xa9, 0x27, 0xa7, + 0x26, 0x0d, 0xba, 0x4e, 0xee, 0x9f, 0x42, 0x19, 0x97, 0x12, 0x96, 0x82, 0xa0, 0x16, 0x55, 0x31, 0x88, 0x64, 0x91, + 0xd6, 0x72, 0xcf, 0x6a, 0xd9, 0xe7, 0x27, 0xc7, 0xf7, 0x4f, 0x43, 0xa8, 0x95, 0xb3, 0x30, 0x0b, 0xed, 0x26, 0xe2, + 0x67, 0x07, 0x4b, 0x8b, 0x0e, 0x93, 0xd3, 0x74, 0x6b, 0x82, 0x76, 0xd3, 0x1c, 0x1a, 0x1c, 0x08, 0x14, 0x8e, 0x4f, + 0x85, 0xd3, 0x97, 0x04, 0xf7, 0x63, 0x95, 0xa1, 0x49, 0xa8, 0x70, 0xf6, 0xf7, 0x94, 0xc1, 0xbb, 0x95, 0xe1, 0x55, + 0xe5, 0x63, 0x2a, 0xbe, 0x50, 0xf5, 0x86, 0x42, 0xa4, 0x0e, 0x31, 0x88, 0x5c, 0x1c, 0xf1, 0x7a, 0xee, 0x4f, 0xe0, + 0x22, 0xcc, 0x04, 0x5c, 0x68, 0x7a, 0x25, 0x68, 0xc5, 0x0b, 0x0c, 0x43, 0x87, 0x5a, 0x33, 0xac, 0x1e, 0x4f, 0x9d, + 0x49, 0x41, 0xa8, 0xdb, 0x7a, 0xce, 0xbf, 0x57, 0x2e, 0x29, 0xaf, 0xb2, 0x93, 0x53, 0x94, 0xb8, 0xcb, 0xf2, 0xa4, + 0x8d, 0x92, 0xc0, 0x84, 0xc4, 0x1d, 0xc9, 0x59, 0x46, 0xfa, 0xd1, 0x6d, 0x84, 0xa3, 0xbb, 0x08, 0x47, 0xd6, 0x87, + 0xf9, 0x03, 0xf8, 0x71, 0x47, 0x38, 0xb2, 0xae, 0xcc, 0x11, 0x8e, 0x34, 0x13, 0x10, 0xc0, 0x2b, 0x1a, 0xe0, 0x1c, + 0x4a, 0x1b, 0xcf, 0xea, 0xb2, 0xf4, 0x63, 0xff, 0x55, 0xba, 0x5e, 0xdb, 0x94, 0x40, 0xca, 0x9c, 0x9a, 0x1d, 0x6a, + 0x1f, 0xa0, 0x8e, 0xa8, 0x67, 0xd6, 0x23, 0x0c, 0x02, 0x08, 0xbd, 0xf3, 0x0f, 0xd8, 0x55, 0xb1, 0x3f, 0xd8, 0x31, + 0xac, 0x34, 0xb8, 0xa2, 0x47, 0xe1, 0x19, 0x16, 0xe1, 0xb1, 0xf0, 0x85, 0x41, 0xac, 0xf0, 0xbf, 0x73, 0x29, 0xe7, + 0xfe, 0xb7, 0x96, 0xe5, 0x2f, 0x78, 0xf6, 0xc4, 0x59, 0xb4, 0x80, 0xe5, 0x96, 0x0d, 0x35, 0x34, 0x64, 0xf5, 0x11, + 0x5c, 0x8f, 0x5d, 0x38, 0x38, 0x90, 0x08, 0xaf, 0x8d, 0x40, 0xe5, 0xe5, 0xc3, 0x6b, 0x1b, 0x9a, 0xc8, 0x7c, 0x42, + 0x6c, 0x32, 0x08, 0x3f, 0x2c, 0xe1, 0x42, 0x63, 0x52, 0x30, 0xa5, 0x22, 0x1b, 0xb3, 0x2f, 0x92, 0xc2, 0x3f, 0xc2, + 0xe8, 0x53, 0xc6, 0x22, 0x32, 0x1d, 0xd6, 0x67, 0x6b, 0xc5, 0xe1, 0x5c, 0x16, 0x2a, 0xb5, 0x2f, 0xb2, 0x78, 0x30, + 0xce, 0xcb, 0xe7, 0x0e, 0xd3, 0x3c, 0x5b, 0x63, 0x7b, 0x87, 0x5d, 0x16, 0x72, 0x57, 0xda, 0x61, 0xa9, 0x2c, 0x5b, + 0x7f, 0x6b, 0x42, 0xaa, 0x36, 0xa3, 0x60, 0xa2, 0xd5, 0x80, 0xaa, 0xc0, 0x1d, 0x50, 0xd8, 0x06, 0x7f, 0x49, 0x97, + 0x65, 0xc9, 0x74, 0x59, 0x2e, 0xc3, 0x49, 0xab, 0xb5, 0x5e, 0xe3, 0x82, 0x99, 0x20, 0x34, 0x3b, 0x4b, 0x40, 0xbe, + 0x9a, 0xca, 0x9b, 0x20, 0x57, 0xa5, 0xe5, 0x2c, 0xcd, 0x12, 0x45, 0x81, 0x11, 0x6c, 0xb4, 0xc6, 0x5f, 0xb8, 0xe2, + 0x00, 0x4f, 0x37, 0xbb, 0xa1, 0x94, 0x39, 0xa3, 0x10, 0xab, 0x2c, 0x68, 0x72, 0x8d, 0xa7, 0x7c, 0xc4, 0x76, 0xb7, + 0x09, 0x66, 0xcc, 0xff, 0x5e, 0x8b, 0x1e, 0x81, 0x2c, 0xbb, 0x67, 0x50, 0x07, 0x16, 0x71, 0x05, 0x1d, 0x84, 0x32, + 0xf8, 0x28, 0xc4, 0xcd, 0x9c, 0xde, 0xc9, 0x85, 0x06, 0xb8, 0x2c, 0xb4, 0x7c, 0xe3, 0xc2, 0x21, 0xec, 0xb7, 0xb0, + 0x8f, 0x8c, 0xb0, 0x84, 0x90, 0x01, 0x2d, 0x6c, 0x23, 0x62, 0xb4, 0xb0, 0x0b, 0x54, 0xd0, 0xc2, 0x26, 0x3c, 0x45, + 0x6b, 0x5d, 0xc6, 0x10, 0xbb, 0x2e, 0x9f, 0xae, 0xac, 0x36, 0xc1, 0xc2, 0x49, 0x87, 0x9a, 0xe8, 0xe0, 0xf6, 0x90, + 0x11, 0xde, 0xf8, 0xf9, 0xea, 0xf5, 0x2b, 0x17, 0x21, 0x9a, 0x8f, 0xc1, 0x65, 0xd3, 0xa9, 0xc6, 0xae, 0xcd, 0x9b, + 0x4f, 0x71, 0xa5, 0x28, 0xb5, 0xc2, 0x29, 0xb4, 0xfc, 0x42, 0xe8, 0x3c, 0xb1, 0x97, 0x17, 0xcf, 0x64, 0x31, 0xa3, + 0xf6, 0xc6, 0x08, 0x5f, 0x2b, 0xf7, 0xc8, 0xbb, 0x79, 0x47, 0xa6, 0x9a, 0xe4, 0xbb, 0xcd, 0xab, 0x88, 0x45, 0x66, + 0xe4, 0x57, 0xd0, 0x06, 0x98, 0xca, 0xe5, 0x1b, 0xbd, 0x05, 0x71, 0x71, 0xf6, 0x03, 0xf2, 0xf2, 0xd6, 0x52, 0x97, + 0x28, 0x6a, 0x70, 0x83, 0x9f, 0xac, 0xe0, 0x59, 0x70, 0x5d, 0x68, 0xd8, 0x23, 0x27, 0x5e, 0x44, 0xad, 0xa8, 0xfe, + 0xc6, 0xad, 0x51, 0x25, 0xf8, 0x18, 0xad, 0x49, 0x2e, 0x41, 0xf4, 0x28, 0x9f, 0xd3, 0xe3, 0x20, 0x9a, 0xf8, 0xbb, + 0xe7, 0xcb, 0xb6, 0xa7, 0xb3, 0x79, 0xa5, 0x4e, 0x2c, 0xaf, 0x4c, 0xc0, 0xc3, 0xd1, 0x3e, 0x58, 0x83, 0x70, 0x90, + 0xc8, 0x4a, 0xed, 0xa1, 0xcf, 0x45, 0xdd, 0x38, 0xbf, 0x68, 0xb3, 0xe6, 0xc9, 0x6a, 0x95, 0x5f, 0xb6, 0x59, 0xfb, + 0xd4, 0x3e, 0x6f, 0x17, 0xa9, 0x0c, 0x68, 0x2e, 0x1f, 0xf3, 0x2c, 0x02, 0xed, 0xec, 0x38, 0x33, 0xe1, 0x14, 0x7c, + 0x40, 0x66, 0xb2, 0xd0, 0x55, 0x5f, 0x12, 0x8c, 0x4b, 0x89, 0xd5, 0xe3, 0x17, 0xa8, 0xd7, 0x4e, 0xb7, 0x5d, 0xa5, + 0x9b, 0xed, 0xc3, 0xe0, 0xc2, 0xa5, 0x40, 0xb8, 0x03, 0x21, 0x0f, 0x40, 0xbf, 0xbb, 0x14, 0x60, 0x1a, 0x04, 0xa8, + 0xac, 0x40, 0xa4, 0xe5, 0xb3, 0xc5, 0xec, 0x59, 0x41, 0xcd, 0x32, 0x3c, 0xe1, 0x13, 0xae, 0x55, 0x4a, 0x41, 0xba, + 0xdd, 0x95, 0xbe, 0xde, 0x2d, 0x41, 0x65, 0xb5, 0x38, 0xb7, 0x89, 0xe6, 0xd9, 0x67, 0xe5, 0x16, 0x0e, 0x61, 0xb3, + 0xb2, 0x02, 0x67, 0x68, 0x8d, 0x73, 0x39, 0xa1, 0x05, 0xd7, 0xd3, 0xd9, 0xbf, 0xb5, 0x3a, 0xac, 0xaf, 0x07, 0xe6, + 0xc2, 0x0a, 0x40, 0x42, 0xc5, 0x68, 0xb5, 0xe2, 0x47, 0xdf, 0xbf, 0x4f, 0xf2, 0x3e, 0xe1, 0x6d, 0xdc, 0xc1, 0xc7, + 0xf8, 0x14, 0xb7, 0x5b, 0xb8, 0x7d, 0x0a, 0x57, 0xf7, 0x59, 0xbe, 0x18, 0x31, 0x15, 0xc3, 0x3b, 0x67, 0xfa, 0x32, + 0x39, 0x3f, 0x2c, 0xa3, 0xfb, 0xeb, 0x22, 0x71, 0xe8, 0x12, 0x04, 0x99, 0x77, 0xd1, 0xf9, 0xa2, 0x28, 0x0c, 0x0d, + 0x37, 0x0e, 0x55, 0x27, 0xa5, 0x7e, 0xe1, 0xf2, 0xb8, 0x07, 0xf6, 0xdc, 0x76, 0x65, 0x9b, 0x60, 0xf6, 0x6d, 0x7f, + 0xa6, 0xd5, 0xcf, 0xa6, 0x2e, 0x11, 0xc3, 0x43, 0xaf, 0x42, 0x0f, 0x74, 0x49, 0xda, 0x07, 0x07, 0x60, 0x75, 0x14, + 0xcc, 0x86, 0xdb, 0xe8, 0x07, 0xbc, 0x59, 0x4b, 0x83, 0x60, 0x05, 0x60, 0xdc, 0xf9, 0x86, 0x93, 0xa5, 0x85, 0xad, + 0x06, 0x2a, 0xac, 0x8b, 0x30, 0x7e, 0x5d, 0x48, 0x2a, 0x8c, 0x10, 0x0d, 0x47, 0x98, 0x0b, 0x86, 0xb2, 0xdf, 0xc2, + 0x72, 0x3c, 0x56, 0x4c, 0xc3, 0xd1, 0x51, 0xb0, 0x2f, 0xac, 0x50, 0xe6, 0x14, 0x19, 0xb2, 0x09, 0x17, 0x0f, 0xf5, + 0x9f, 0xac, 0x90, 0xe6, 0xd3, 0x68, 0x30, 0xd2, 0xc8, 0xac, 0x62, 0x84, 0xb3, 0x9c, 0xcf, 0xa1, 0xea, 0xa4, 0x00, + 0xa7, 0x1f, 0xf8, 0xcb, 0x47, 0x69, 0xd8, 0x26, 0x90, 0xaf, 0x0f, 0x36, 0xa6, 0x0b, 0x1e, 0x15, 0xf4, 0xe6, 0xb5, + 0x78, 0x0c, 0x3b, 0xea, 0x61, 0xc1, 0x28, 0x64, 0x43, 0xd2, 0x3b, 0x68, 0x0a, 0x3e, 0xa0, 0xcd, 0x97, 0x06, 0x70, + 0xe9, 0xb9, 0xf9, 0xb0, 0x15, 0x7d, 0x8c, 0xc4, 0xa4, 0x6c, 0xcb, 0x64, 0x9a, 0x53, 0xba, 0xca, 0xb4, 0x51, 0xa8, + 0xca, 0x29, 0xac, 0xb1, 0x8b, 0x7a, 0x12, 0x0e, 0x66, 0x44, 0xd5, 0x34, 0xed, 0x0f, 0xcc, 0xdf, 0xd7, 0xb6, 0x64, + 0x0b, 0xbb, 0x88, 0x33, 0x6b, 0x6c, 0x1e, 0x28, 0x0d, 0xca, 0xb7, 0x31, 0xdc, 0xc3, 0xc2, 0x2b, 0x99, 0x35, 0xf2, + 0x79, 0xe2, 0xc9, 0xe6, 0xc9, 0x7a, 0x6d, 0x06, 0xa2, 0x52, 0xd0, 0x03, 0xbd, 0xf5, 0xdb, 0xa6, 0x05, 0xdb, 0xa3, + 0xfc, 0x3a, 0x6d, 0xe1, 0x19, 0x87, 0x47, 0x3f, 0x7d, 0x7b, 0x57, 0xba, 0x90, 0x9f, 0x1d, 0x48, 0x5a, 0x41, 0x8a, + 0x9d, 0x4e, 0xd0, 0xd9, 0x31, 0x0e, 0x46, 0x0e, 0xf4, 0xfc, 0xea, 0xb3, 0x85, 0xb5, 0xff, 0xfd, 0xa6, 0x2c, 0x68, + 0xe2, 0xe9, 0x94, 0x13, 0xca, 0xfc, 0xf9, 0xf9, 0x86, 0x27, 0x15, 0x2a, 0xb8, 0xd7, 0xb2, 0x60, 0x4f, 0xdb, 0x80, + 0x9a, 0x33, 0xfa, 0xb7, 0xfd, 0x61, 0x63, 0xf8, 0x94, 0x5a, 0xb6, 0xac, 0x90, 0x4a, 0x3d, 0xb4, 0x69, 0xf6, 0xe8, + 0x81, 0x23, 0xf2, 0x25, 0x74, 0x01, 0xbc, 0xfe, 0xa8, 0x90, 0x73, 0x83, 0x08, 0xee, 0xb7, 0x1b, 0xb7, 0xf1, 0x15, + 0x00, 0x6f, 0x87, 0xbd, 0xea, 0x9f, 0x16, 0xb0, 0xbf, 0x51, 0x59, 0xd2, 0x8f, 0xb7, 0x63, 0x8f, 0xff, 0x42, 0x42, + 0x74, 0x76, 0x8b, 0x87, 0x89, 0x43, 0xa7, 0x92, 0x35, 0x2b, 0x7f, 0x6e, 0x95, 0x04, 0x0c, 0xab, 0x17, 0x0c, 0xd9, + 0xb8, 0xad, 0xe2, 0x36, 0xf3, 0x3f, 0xa8, 0x60, 0xb0, 0xe0, 0x5b, 0x23, 0xa9, 0x58, 0x16, 0xbf, 0x7d, 0xea, 0xfc, + 0x57, 0x9d, 0xe3, 0xda, 0xd7, 0xb5, 0x17, 0x39, 0x87, 0x26, 0x1a, 0x72, 0x84, 0x0e, 0x0e, 0x36, 0x32, 0xe8, 0x18, + 0x00, 0x8f, 0x1c, 0xfb, 0xe5, 0x97, 0xcf, 0xb3, 0x63, 0x46, 0xf3, 0x58, 0x44, 0x21, 0x73, 0xe7, 0xb9, 0x39, 0x3b, + 0x91, 0x27, 0x54, 0x4d, 0x7d, 0x61, 0x80, 0xe3, 0xa3, 0xad, 0x54, 0xc0, 0xf7, 0x68, 0xbd, 0x63, 0x02, 0x1b, 0xfc, + 0x96, 0x9d, 0xd4, 0xae, 0x82, 0x7e, 0x81, 0x96, 0xbb, 0x98, 0xca, 0x8d, 0x05, 0x8e, 0x36, 0x27, 0xb2, 0x73, 0xe8, + 0x1b, 0x75, 0x4a, 0xd6, 0xe3, 0xc9, 0x6e, 0xa3, 0x2f, 0x29, 0x76, 0x25, 0x57, 0xb4, 0x6d, 0xc8, 0xaa, 0x57, 0x79, + 0x75, 0x65, 0xea, 0x54, 0x5d, 0xf3, 0x56, 0x96, 0x36, 0xa5, 0x5d, 0x92, 0xbd, 0xdb, 0x62, 0xe1, 0x55, 0x78, 0xa3, + 0x51, 0x5e, 0x84, 0x82, 0x3d, 0x96, 0x18, 0x74, 0x39, 0x81, 0xeb, 0x85, 0xd5, 0x2a, 0x86, 0x3f, 0xbb, 0xc6, 0xb0, + 0xcb, 0x74, 0xe9, 0x03, 0xdf, 0xe0, 0x57, 0x82, 0xc0, 0xc0, 0xce, 0x0e, 0x12, 0xac, 0xbb, 0xdc, 0xa0, 0xe1, 0x38, + 0xf1, 0x5f, 0xf0, 0x2c, 0xb5, 0xf6, 0x2e, 0x07, 0x93, 0xec, 0x1b, 0x4f, 0xd9, 0x95, 0xac, 0x65, 0x2d, 0xaa, 0xfc, + 0x86, 0x04, 0x43, 0xec, 0xa6, 0x74, 0x8e, 0x5b, 0x49, 0x1b, 0x45, 0xae, 0x58, 0x85, 0xfe, 0xdf, 0x2a, 0x92, 0xd9, + 0xcc, 0xff, 0x3a, 0x3b, 0x3b, 0x73, 0x29, 0xce, 0xe6, 0x4f, 0x19, 0x0f, 0x38, 0x93, 0xc0, 0xbe, 0xf0, 0x8c, 0x19, + 0x1d, 0xf2, 0x5b, 0x18, 0x0a, 0x11, 0xe4, 0x52, 0x38, 0x76, 0x09, 0x5e, 0x55, 0x04, 0xca, 0x03, 0xec, 0xdf, 0x93, + 0x8d, 0x72, 0xfe, 0x59, 0x26, 0x1f, 0xb6, 0xb8, 0x6c, 0x90, 0x7d, 0x31, 0x9f, 0x7d, 0x6b, 0x26, 0x03, 0x2f, 0x11, + 0x44, 0xd8, 0xfe, 0x36, 0x2c, 0xad, 0xb3, 0x94, 0xc1, 0x91, 0x96, 0x8b, 0x6c, 0x6a, 0x35, 0xff, 0xee, 0xc3, 0x94, + 0x75, 0x4f, 0xfa, 0x40, 0xe4, 0x2e, 0xb2, 0x74, 0xd1, 0x37, 0xa3, 0x1f, 0xcb, 0x40, 0x9b, 0x7b, 0xaf, 0xd8, 0x82, + 0xfd, 0x88, 0xf7, 0xaa, 0x14, 0xf8, 0x78, 0x58, 0x70, 0x9a, 0xff, 0x88, 0xf7, 0xaa, 0x80, 0x9b, 0xe0, 0x0a, 0x69, + 0x62, 0x56, 0x62, 0xf3, 0x7c, 0x75, 0x1a, 0x09, 0xa0, 0xa0, 0x79, 0x64, 0x0e, 0xb2, 0xe7, 0x2e, 0x46, 0x63, 0xd2, + 0xc1, 0x2e, 0x38, 0x98, 0x8d, 0xbc, 0x6a, 0x03, 0x96, 0x43, 0xdc, 0xba, 0x72, 0x36, 0xe6, 0xeb, 0xd1, 0xc6, 0x82, + 0x18, 0x65, 0x32, 0xb9, 0x7c, 0xce, 0xe3, 0xad, 0xc5, 0x42, 0x61, 0xb5, 0x60, 0x81, 0x6a, 0x55, 0xaa, 0xf4, 0xb0, + 0xf8, 0x76, 0xc1, 0x2c, 0x28, 0x62, 0xb6, 0xde, 0xc3, 0x5b, 0xae, 0x08, 0x48, 0xc9, 0x2e, 0x09, 0x5e, 0x20, 0x37, + 0x98, 0xea, 0x1f, 0x9c, 0x07, 0x42, 0xcf, 0x94, 0x8e, 0xb0, 0xc9, 0x53, 0x10, 0x49, 0x6c, 0xbf, 0x85, 0x1d, 0x6b, + 0xf4, 0x42, 0x78, 0x21, 0x05, 0xce, 0x55, 0xd3, 0xc4, 0x8c, 0x72, 0x13, 0x5d, 0xec, 0xa1, 0x9a, 0xb3, 0x4c, 0x5b, + 0x04, 0xd8, 0x77, 0x68, 0x28, 0xc5, 0x73, 0x03, 0x0a, 0xf3, 0x74, 0xb6, 0x4b, 0x79, 0x0c, 0x8b, 0x17, 0xa4, 0x00, + 0x51, 0xe3, 0x62, 0x52, 0xd6, 0x99, 0xe7, 0x8b, 0x09, 0x17, 0x15, 0x32, 0x14, 0x4c, 0xcd, 0xa5, 0x80, 0x97, 0x2b, + 0xca, 0x22, 0x86, 0x0e, 0xd5, 0xf0, 0xdd, 0x92, 0xb0, 0xb2, 0x8e, 0x39, 0xa6, 0xb8, 0xa8, 0x6a, 0x00, 0x73, 0xf1, + 0x30, 0x7c, 0xe2, 0x5e, 0xbd, 0x16, 0xef, 0xe4, 0xbc, 0xca, 0xf7, 0x34, 0xce, 0x07, 0x88, 0x77, 0x76, 0xc3, 0x68, + 0x6d, 0x1e, 0x97, 0x0a, 0xb6, 0xef, 0x07, 0x5e, 0x3d, 0xb8, 0xb6, 0x36, 0xcf, 0x53, 0x95, 0x59, 0x43, 0x56, 0xbe, + 0xc5, 0x50, 0xb5, 0x57, 0xaf, 0x2a, 0x85, 0xad, 0x08, 0x50, 0x29, 0xf8, 0x68, 0x2b, 0xff, 0x89, 0xb6, 0xf9, 0xf6, + 0x1c, 0x2a, 0xc3, 0x03, 0x79, 0x32, 0x54, 0xf5, 0x80, 0x8b, 0xf2, 0x43, 0x00, 0x8b, 0x1f, 0x99, 0x38, 0xbd, 0xbb, + 0x2e, 0x90, 0x39, 0x53, 0xb1, 0xc4, 0xcb, 0x3e, 0x1d, 0xa4, 0x56, 0x1e, 0x4a, 0x25, 0xd8, 0xf6, 0xdc, 0x14, 0x5c, + 0xfb, 0x80, 0xc0, 0xb8, 0xcf, 0x06, 0xe9, 0xb2, 0x1e, 0x34, 0xd8, 0x86, 0x2d, 0xf6, 0xe6, 0x9c, 0x26, 0xca, 0x2e, + 0x1d, 0xe0, 0x9c, 0x80, 0xed, 0xb1, 0x67, 0x4f, 0xdf, 0xc4, 0x19, 0xea, 0xd5, 0x39, 0xfc, 0xe5, 0x1a, 0xe7, 0x38, + 0x43, 0xe9, 0xc3, 0x18, 0x2e, 0xb0, 0xd6, 0x18, 0xc0, 0x97, 0x59, 0x52, 0x05, 0x1e, 0xa9, 0x99, 0x91, 0x58, 0xdd, + 0x45, 0x20, 0x5a, 0xea, 0xf0, 0x76, 0x9c, 0xf9, 0xb0, 0xdb, 0x86, 0x7b, 0x7d, 0x66, 0x84, 0xc3, 0x49, 0x16, 0xd7, + 0xce, 0x19, 0x4e, 0x2e, 0xf7, 0x79, 0xed, 0xc4, 0x04, 0x6b, 0xef, 0xf0, 0x54, 0x01, 0x3d, 0x1a, 0x9c, 0x2a, 0x96, + 0x86, 0x40, 0xcc, 0x04, 0xf0, 0x66, 0x0e, 0x8f, 0xb6, 0x00, 0xe7, 0xa3, 0x35, 0x0e, 0xbe, 0xd2, 0x5a, 0x57, 0x9b, + 0x4a, 0x94, 0xf5, 0x1a, 0xf7, 0xa7, 0x19, 0x1e, 0x65, 0x78, 0x9e, 0x0d, 0x82, 0xe3, 0x66, 0x96, 0x85, 0x26, 0x5d, + 0xab, 0xd5, 0x53, 0x67, 0x46, 0x88, 0xec, 0x4f, 0x4b, 0x7f, 0x50, 0x0f, 0x10, 0x3e, 0x85, 0x2c, 0xa0, 0x25, 0x3d, + 0xf7, 0xb7, 0x61, 0x5f, 0xe5, 0x46, 0x8d, 0x98, 0x27, 0x96, 0x8c, 0xf4, 0xfc, 0x8f, 0x32, 0xcb, 0xb6, 0xd6, 0x88, + 0xe6, 0xb7, 0x7b, 0x51, 0xc3, 0xb7, 0x17, 0x68, 0xd9, 0x4a, 0xb3, 0x1d, 0x40, 0x14, 0x6b, 0x9c, 0xa4, 0x83, 0x35, + 0x92, 0xab, 0x55, 0x6c, 0x53, 0x08, 0x4f, 0x66, 0x8c, 0xaa, 0x45, 0x61, 0x1e, 0xaa, 0x8b, 0x15, 0x4a, 0x0c, 0xbf, + 0x8b, 0x9d, 0x8d, 0x28, 0xbc, 0x0b, 0x27, 0xc1, 0x70, 0x23, 0x16, 0x44, 0xd6, 0x44, 0xee, 0x61, 0x56, 0x59, 0x06, + 0x09, 0x22, 0x8c, 0xc8, 0x6f, 0xaf, 0x4b, 0x85, 0x7d, 0x0a, 0xcf, 0xfe, 0x31, 0xbe, 0x80, 0x70, 0xf3, 0x36, 0xa1, + 0xc5, 0x90, 0x4e, 0x80, 0x8d, 0x85, 0x38, 0x84, 0x5b, 0x09, 0xab, 0x55, 0x7f, 0xd0, 0x15, 0x86, 0x3c, 0xbb, 0x87, + 0xfa, 0xca, 0x86, 0x76, 0x37, 0x00, 0x57, 0xdd, 0x96, 0x9a, 0x6b, 0xa3, 0xfb, 0xa1, 0xe6, 0x2d, 0x31, 0xee, 0x92, + 0xdc, 0x73, 0x20, 0xd5, 0x8b, 0xdf, 0x35, 0x0b, 0x70, 0x13, 0xba, 0x0a, 0x8f, 0xf0, 0xc2, 0xda, 0x70, 0x9a, 0x87, + 0xa3, 0xa8, 0x79, 0x2f, 0x0a, 0x9e, 0xa9, 0x26, 0xac, 0x9f, 0x0d, 0xf0, 0xc8, 0x87, 0x15, 0xdf, 0x7f, 0x1b, 0x8f, + 0x10, 0x2a, 0x88, 0x81, 0xa9, 0x75, 0xd9, 0x1e, 0x55, 0x76, 0xfb, 0x26, 0xd3, 0x30, 0x0c, 0xc6, 0x88, 0x79, 0x14, + 0x1a, 0x31, 0xe7, 0x8d, 0x06, 0x5a, 0x90, 0x11, 0x18, 0x31, 0x2f, 0x82, 0xd6, 0x16, 0xf6, 0x51, 0xd1, 0xa0, 0xbd, + 0x05, 0x42, 0x5d, 0x0e, 0x34, 0x4d, 0xc3, 0xf3, 0x21, 0xd5, 0xf3, 0xed, 0xfe, 0x31, 0xab, 0xa3, 0x0e, 0x28, 0x12, + 0xc6, 0x97, 0x7e, 0x12, 0xd6, 0x35, 0xdc, 0x8e, 0x7b, 0x6c, 0xc6, 0xed, 0x6c, 0x1b, 0x54, 0x5f, 0xf6, 0xb3, 0xc1, + 0xa0, 0x2b, 0xbd, 0x95, 0x44, 0x0b, 0x8f, 0xab, 0x07, 0x47, 0xaa, 0xc5, 0xfb, 0xa2, 0x37, 0xaf, 0xbc, 0xb9, 0x7f, + 0xc7, 0x74, 0xf3, 0x3c, 0x06, 0x0e, 0x68, 0x1f, 0xee, 0x87, 0xaa, 0xf8, 0x60, 0x47, 0x1d, 0x88, 0x82, 0x96, 0xb6, + 0x6a, 0x02, 0xa9, 0x35, 0xb3, 0x8b, 0x75, 0x53, 0xa1, 0x43, 0x01, 0x61, 0xc8, 0x54, 0xd5, 0xdd, 0x9d, 0x0a, 0x54, + 0x43, 0x1c, 0x4e, 0xfd, 0xc7, 0xd6, 0x88, 0x35, 0x8e, 0x3a, 0xa3, 0xc8, 0x18, 0x49, 0xda, 0xe5, 0x83, 0x37, 0x86, + 0xc0, 0x4a, 0xc0, 0xc7, 0x7a, 0x36, 0x49, 0xc6, 0x90, 0xe0, 0x2d, 0xcb, 0xb4, 0xe1, 0x43, 0xb8, 0x43, 0x50, 0x9e, + 0xd8, 0xa0, 0xb4, 0xae, 0x92, 0x85, 0x5c, 0xd5, 0xe5, 0x75, 0x80, 0x9e, 0x77, 0xe5, 0x6f, 0x6c, 0x38, 0xb2, 0x60, + 0x60, 0xd9, 0xd6, 0x3e, 0x01, 0x8f, 0x7c, 0x5c, 0x21, 0x88, 0x5f, 0x0a, 0x9d, 0x98, 0xb8, 0xd8, 0x57, 0xb0, 0x41, + 0xf1, 0x1c, 0x1c, 0x04, 0x9d, 0x04, 0x87, 0xc1, 0xbb, 0xcc, 0x6a, 0x92, 0x0d, 0x6e, 0xcd, 0x48, 0x3c, 0x5f, 0xad, + 0x5a, 0xe8, 0xf0, 0x1f, 0xf3, 0xf4, 0xf3, 0xb8, 0x54, 0xb8, 0x8f, 0x2b, 0x85, 0x3b, 0x58, 0x02, 0x92, 0x71, 0xa0, + 0x6b, 0xc7, 0x32, 0x54, 0xa3, 0x43, 0x54, 0xf2, 0x17, 0x10, 0xa3, 0xda, 0x1d, 0x4b, 0xa0, 0x67, 0xdf, 0x2a, 0x60, + 0x75, 0xed, 0x65, 0x09, 0x64, 0x04, 0x77, 0xbf, 0x09, 0x8c, 0x0a, 0xd1, 0xf8, 0xfc, 0x99, 0xd7, 0x23, 0x78, 0xe2, + 0xfc, 0xb9, 0x66, 0x86, 0x75, 0x2f, 0xe8, 0x8d, 0x69, 0x3e, 0x1e, 0xe3, 0xe6, 0xd8, 0x82, 0xf3, 0xa8, 0x03, 0x3f, + 0x2d, 0x44, 0x8f, 0x3a, 0xd8, 0xa5, 0xe2, 0x71, 0x09, 0xe4, 0x10, 0x3d, 0x9d, 0x81, 0x14, 0xb0, 0xd2, 0xb1, 0xd5, + 0x22, 0x4d, 0xd0, 0x6a, 0x35, 0xb9, 0x20, 0x2d, 0x84, 0x96, 0xea, 0x86, 0xeb, 0x6c, 0x0a, 0x3e, 0xd2, 0xa0, 0x18, + 0x78, 0x43, 0xf5, 0x34, 0x46, 0x78, 0x8c, 0x96, 0x23, 0x36, 0xa6, 0x8b, 0x5c, 0xa7, 0xaa, 0xc7, 0x13, 0x1b, 0xb8, + 0x97, 0xd9, 0x48, 0x70, 0x47, 0x1d, 0x3c, 0x31, 0xfc, 0xe5, 0x23, 0x63, 0x0e, 0x52, 0x64, 0x26, 0x79, 0x62, 0x12, + 0x30, 0x4f, 0xb2, 0x5c, 0x2a, 0x66, 0x9b, 0xe9, 0x5a, 0xdb, 0x72, 0x08, 0xfd, 0x1d, 0xe9, 0x82, 0x1b, 0x2b, 0xca, + 0x28, 0x9d, 0x12, 0xd5, 0x53, 0x47, 0x9d, 0x74, 0x82, 0x79, 0x02, 0x9c, 0xde, 0x3b, 0x19, 0xb3, 0x46, 0x79, 0x2b, + 0x3a, 0x43, 0x87, 0x53, 0x2c, 0xaa, 0x4b, 0xd4, 0x19, 0x3a, 0x9c, 0x20, 0x3c, 0x6b, 0x90, 0x5c, 0x81, 0xc7, 0x30, + 0x17, 0xff, 0x47, 0xca, 0x7f, 0x73, 0xd8, 0x10, 0x62, 0xfa, 0x2d, 0xec, 0x14, 0x36, 0x8a, 0xd2, 0x9c, 0x80, 0xd7, + 0x62, 0xfb, 0x0c, 0x67, 0x64, 0xd2, 0xcc, 0x7d, 0xc0, 0x3d, 0xd3, 0x4a, 0xe3, 0x56, 0xa3, 0xc3, 0x0c, 0x8f, 0x36, + 0x93, 0x62, 0x33, 0xd7, 0x66, 0x9e, 0x66, 0x70, 0xbe, 0x57, 0xa3, 0x70, 0xe5, 0x17, 0x9b, 0x49, 0x61, 0x79, 0x07, + 0xdc, 0xe6, 0x08, 0x8b, 0x26, 0xc5, 0x39, 0x9e, 0x35, 0xbf, 0xe2, 0x59, 0xf3, 0x43, 0x99, 0xd1, 0x58, 0x60, 0x01, + 0xc1, 0xfb, 0x20, 0x11, 0xcf, 0xaa, 0xe4, 0x11, 0x16, 0x0d, 0x53, 0x1e, 0xcf, 0x1a, 0x55, 0xe9, 0xe6, 0x02, 0x8b, + 0x86, 0x29, 0xdd, 0xf8, 0x80, 0x67, 0x8d, 0xaf, 0xff, 0x62, 0xd2, 0x51, 0x0a, 0xe8, 0x32, 0x47, 0xcb, 0xcc, 0x0e, + 0xf1, 0xea, 0xb7, 0xb7, 0xef, 0xda, 0xd7, 0x9d, 0xc3, 0x09, 0xf6, 0xeb, 0x97, 0x19, 0x1c, 0xcb, 0x74, 0xcc, 0x9a, + 0x00, 0xd1, 0x0c, 0x77, 0x0e, 0xa7, 0xb8, 0x73, 0x98, 0xb9, 0xa6, 0xd6, 0xb3, 0x06, 0xb9, 0xd5, 0x21, 0x14, 0x75, + 0x94, 0x86, 0xf0, 0xf1, 0x93, 0x4d, 0x27, 0xa8, 0x06, 0x4a, 0x74, 0x38, 0xa9, 0x81, 0x0a, 0xbe, 0x17, 0xb5, 0xef, + 0xaa, 0x5e, 0x85, 0x41, 0x16, 0x4a, 0x28, 0x5c, 0x73, 0x03, 0x9e, 0x5a, 0x8a, 0x81, 0x4c, 0x98, 0x62, 0x81, 0xf2, + 0x1d, 0x50, 0x18, 0xe5, 0x89, 0x19, 0x7a, 0x30, 0x1d, 0x93, 0xf8, 0xff, 0xf3, 0x64, 0xca, 0xa1, 0x97, 0x5b, 0x66, + 0x6b, 0x7a, 0x6e, 0x32, 0xe1, 0xf0, 0x81, 0xc7, 0xfa, 0xbf, 0x76, 0xa0, 0xd8, 0x80, 0x14, 0xff, 0x5f, 0x3a, 0xba, + 0x10, 0x8c, 0x90, 0x15, 0xa5, 0x85, 0x43, 0xfc, 0xef, 0x0f, 0x2b, 0xe8, 0xbe, 0xd8, 0xea, 0xbe, 0x30, 0xdd, 0x87, + 0x4d, 0x1b, 0x55, 0x4e, 0x5a, 0x55, 0xb2, 0xe4, 0xbf, 0x4e, 0xb7, 0xb6, 0x40, 0x23, 0x6a, 0xf4, 0x6c, 0x12, 0x36, + 0xb8, 0xdf, 0x4e, 0x77, 0x20, 0xf3, 0x9a, 0xdb, 0x97, 0x48, 0xe1, 0xf0, 0x0d, 0xee, 0x54, 0x2f, 0x5b, 0xe0, 0xbd, + 0xa9, 0x8c, 0xbe, 0x32, 0x0e, 0x2d, 0x07, 0xe9, 0xa6, 0x29, 0xb7, 0x31, 0x96, 0x4e, 0x4e, 0xb1, 0x71, 0x45, 0x84, + 0x4a, 0xb7, 0x97, 0xa0, 0x14, 0x1f, 0xeb, 0x26, 0x33, 0x5f, 0x17, 0x3a, 0x31, 0x97, 0x50, 0x0d, 0xf3, 0x79, 0x77, + 0xa9, 0x13, 0x2d, 0xe7, 0x36, 0xef, 0xee, 0x02, 0xfa, 0x04, 0x0d, 0x6b, 0x23, 0xb0, 0xdb, 0x67, 0x85, 0xd3, 0xef, + 0x54, 0x87, 0x60, 0x78, 0x00, 0x39, 0xd2, 0x62, 0xfb, 0xc0, 0xa6, 0x35, 0xec, 0xba, 0x68, 0x96, 0x89, 0xb6, 0xd5, + 0xa6, 0xc9, 0xb5, 0x7b, 0x98, 0xcf, 0x43, 0x9e, 0x82, 0x17, 0x56, 0x3f, 0xbe, 0x83, 0xdd, 0xb8, 0xad, 0x31, 0x12, + 0x75, 0x25, 0x53, 0x09, 0xfd, 0xe4, 0x16, 0xb3, 0xe4, 0xce, 0x78, 0x31, 0x2a, 0xe3, 0xef, 0x63, 0xe2, 0xf2, 0x47, + 0x95, 0x24, 0x07, 0x96, 0xfd, 0x0d, 0x96, 0xdc, 0x82, 0x79, 0x62, 0x59, 0x4d, 0x62, 0x9d, 0xdc, 0x05, 0x8b, 0x28, + 0x4d, 0x23, 0x6b, 0xc3, 0x80, 0x9a, 0x66, 0xac, 0x7a, 0x70, 0x1f, 0x02, 0x3d, 0xf4, 0xca, 0x52, 0xda, 0x75, 0x96, + 0xd6, 0xba, 0xd7, 0xa6, 0xfb, 0xcd, 0x01, 0x05, 0x7c, 0x61, 0xc0, 0x35, 0xfd, 0xab, 0x49, 0x24, 0x43, 0xf6, 0x95, + 0xb3, 0xe2, 0xf1, 0xa2, 0x30, 0x98, 0x26, 0x7a, 0x3a, 0xc9, 0xe6, 0x6d, 0x30, 0xd5, 0xcb, 0xe6, 0x9d, 0x5b, 0xec, + 0xbe, 0xef, 0xec, 0xf7, 0x1d, 0x16, 0x3d, 0x66, 0x32, 0x52, 0x66, 0x8a, 0xf9, 0xef, 0x3b, 0xfb, 0x7d, 0x87, 0xb7, + 0x07, 0x73, 0xe3, 0x2f, 0x14, 0x4b, 0x76, 0x86, 0x4b, 0x30, 0x21, 0x0f, 0xb8, 0x9b, 0x5a, 0x96, 0x09, 0x02, 0x5b, + 0x4b, 0x80, 0x38, 0x9f, 0x4f, 0xe3, 0x8a, 0x57, 0x43, 0xc0, 0x7d, 0x7a, 0xd7, 0xf6, 0x2a, 0x15, 0x78, 0x4c, 0xd0, + 0x88, 0x98, 0xd8, 0x36, 0xe6, 0x15, 0x31, 0xe0, 0xf2, 0x88, 0x2e, 0xf5, 0x24, 0x09, 0xf0, 0xaa, 0x46, 0xe5, 0x6d, + 0x8a, 0x94, 0x5f, 0x24, 0xc8, 0xf1, 0xc5, 0x1e, 0x51, 0xc5, 0x00, 0x56, 0x65, 0x49, 0x9f, 0x40, 0xea, 0xf9, 0xc1, + 0x44, 0x3f, 0x6f, 0x22, 0x8f, 0x7d, 0x4f, 0xf7, 0x33, 0xd3, 0xd3, 0x42, 0x2e, 0x26, 0x53, 0xf0, 0xa1, 0x05, 0x96, + 0xa1, 0x30, 0xf5, 0x2a, 0x5b, 0xff, 0x9a, 0xe4, 0x26, 0x80, 0xc2, 0xe9, 0xa6, 0x4c, 0x68, 0xa6, 0x17, 0x34, 0x37, + 0x96, 0xa4, 0x5c, 0x4c, 0x1e, 0xc9, 0xdb, 0x97, 0x80, 0xdd, 0x94, 0xe8, 0xc6, 0x8e, 0xbc, 0xb7, 0xb0, 0x03, 0x70, + 0x46, 0xd8, 0xae, 0x8a, 0x0f, 0x15, 0xe8, 0xfc, 0x71, 0x4e, 0xd8, 0xae, 0xaa, 0x4f, 0x98, 0xcd, 0x9e, 0x92, 0x8d, + 0xe1, 0xf6, 0xe2, 0xac, 0x91, 0xa3, 0xa3, 0x4e, 0x9a, 0x77, 0x3d, 0x31, 0xb0, 0x00, 0x0d, 0x80, 0xbb, 0xb5, 0x3d, + 0xcb, 0xbb, 0x1b, 0x02, 0x7a, 0x97, 0x4c, 0xda, 0xeb, 0x72, 0x93, 0xb2, 0x5a, 0x75, 0x2a, 0x2a, 0x58, 0xe0, 0x69, + 0xb0, 0x17, 0xa8, 0xfd, 0xda, 0x41, 0x71, 0xae, 0xb2, 0x4d, 0xd3, 0xf3, 0xb2, 0xef, 0xee, 0x8e, 0x45, 0xc6, 0x36, + 0xed, 0xed, 0x0e, 0x22, 0x61, 0x39, 0x61, 0x1d, 0x70, 0xc2, 0x55, 0xed, 0x80, 0x00, 0x5d, 0x07, 0x22, 0x37, 0x96, + 0x64, 0xb9, 0xae, 0x8c, 0xee, 0x03, 0xbf, 0x5b, 0x4a, 0xa4, 0x1b, 0x6d, 0x49, 0x30, 0x7d, 0x82, 0x51, 0xd3, 0x99, + 0x27, 0xa0, 0x6b, 0xaf, 0x1b, 0x6f, 0x8a, 0xb6, 0xfe, 0xad, 0x65, 0x6c, 0xb6, 0x87, 0x89, 0xa1, 0x0c, 0x62, 0xa0, + 0xf7, 0x11, 0xef, 0x36, 0x1a, 0x19, 0x02, 0x85, 0x4c, 0x36, 0xc0, 0x32, 0xf1, 0x5a, 0xf4, 0x83, 0x03, 0x03, 0x8f, + 0x2a, 0x01, 0x61, 0x0a, 0x42, 0x48, 0xd8, 0xb5, 0x41, 0xd8, 0x70, 0xb9, 0x6a, 0xb9, 0xb0, 0x91, 0x6a, 0x43, 0x07, + 0xff, 0xaf, 0x70, 0xd9, 0xea, 0x99, 0xe5, 0xa2, 0x18, 0xdc, 0xcc, 0x0d, 0x58, 0x24, 0x48, 0x8f, 0x36, 0xdb, 0x43, + 0x71, 0x77, 0x2e, 0x36, 0x1b, 0x02, 0x12, 0x73, 0x98, 0xa0, 0x68, 0x38, 0x37, 0xc6, 0x58, 0x25, 0x95, 0x96, 0xb5, + 0x26, 0x31, 0x07, 0xbe, 0x74, 0xe1, 0xba, 0x2f, 0x6f, 0x53, 0x86, 0xef, 0x52, 0x81, 0x6f, 0xc0, 0x93, 0x26, 0x95, + 0xd8, 0x3d, 0x5e, 0x50, 0xac, 0x89, 0xee, 0x7a, 0xf6, 0xb6, 0x80, 0x75, 0x36, 0x7b, 0x44, 0x04, 0xbf, 0xab, 0x5f, + 0x6d, 0xf0, 0xdd, 0xc2, 0x5f, 0xc1, 0xfa, 0x39, 0x38, 0x49, 0xb1, 0x68, 0xc8, 0x66, 0xe1, 0x8e, 0x0c, 0x28, 0x57, + 0xf1, 0xcb, 0x61, 0xea, 0x56, 0x31, 0x5c, 0xfb, 0xf8, 0x8a, 0x3f, 0x6c, 0xb4, 0xdb, 0x50, 0x65, 0x71, 0xbb, 0x37, + 0x45, 0x43, 0x56, 0x4d, 0xef, 0xc8, 0xdc, 0x48, 0xa9, 0x7f, 0x7d, 0xc0, 0xad, 0xad, 0xf6, 0xfd, 0x34, 0xdf, 0x7a, + 0x74, 0xae, 0x9a, 0xf6, 0xa9, 0xb5, 0x22, 0x38, 0xf8, 0xd9, 0xc2, 0xcd, 0xad, 0x01, 0x07, 0xf0, 0xf3, 0x77, 0x34, + 0x8f, 0x33, 0x88, 0x4e, 0x6f, 0x35, 0xe3, 0xab, 0xf8, 0xaf, 0x51, 0x23, 0xee, 0xa5, 0x7f, 0x25, 0x7f, 0x8d, 0x1a, + 0xa8, 0x87, 0xe2, 0xf9, 0xed, 0x8a, 0xcd, 0x56, 0x10, 0x6c, 0xed, 0xde, 0x11, 0x7e, 0x1d, 0x96, 0xe4, 0x9a, 0xe6, + 0x3c, 0x5b, 0xb9, 0x87, 0xf7, 0x56, 0xee, 0x55, 0xa2, 0x95, 0x79, 0x4b, 0x6a, 0x15, 0xcb, 0x61, 0x0e, 0x81, 0x85, + 0xe3, 0xbd, 0x66, 0xaf, 0xdf, 0x6a, 0x3e, 0x18, 0xd8, 0x7f, 0x4d, 0x84, 0x7b, 0x54, 0x8b, 0xd8, 0xf6, 0x66, 0x63, + 0xeb, 0xc7, 0x60, 0xd8, 0x01, 0xa1, 0xc0, 0x41, 0x2e, 0x7d, 0x9c, 0x21, 0xeb, 0x7b, 0xb2, 0x5a, 0x31, 0x17, 0xcd, + 0xda, 0x69, 0xf0, 0xcb, 0xd8, 0x4c, 0x87, 0xed, 0xa4, 0xd3, 0xf5, 0x62, 0x2c, 0x69, 0x40, 0xa4, 0x69, 0xcc, 0x20, + 0x90, 0xd4, 0xd2, 0x70, 0x58, 0xf3, 0xdb, 0x28, 0xad, 0xee, 0x8f, 0x20, 0xe5, 0x87, 0x28, 0xe5, 0x47, 0x04, 0x02, + 0x68, 0x5b, 0xe6, 0xa8, 0x6c, 0xc8, 0xfb, 0x2e, 0xdd, 0x33, 0xce, 0x0c, 0x0d, 0xbe, 0x5a, 0xb5, 0xaa, 0x61, 0x8a, + 0xa2, 0x3e, 0xcc, 0xe5, 0x1a, 0x0b, 0xf2, 0x06, 0x74, 0xcd, 0x8a, 0x88, 0x5e, 0xe8, 0x2a, 0x0f, 0xef, 0x0e, 0x63, + 0x49, 0xc0, 0x49, 0xbf, 0x27, 0x7a, 0x05, 0xb9, 0x7c, 0x18, 0x83, 0x8f, 0x19, 0xe6, 0x7d, 0xdd, 0x2f, 0x06, 0x03, + 0x94, 0x3a, 0xa7, 0xb3, 0xd4, 0x44, 0x5c, 0x09, 0xfc, 0x92, 0x0b, 0xf0, 0x4b, 0x56, 0x88, 0xf5, 0x8b, 0x01, 0xb9, + 0x97, 0xc5, 0x12, 0x9c, 0xf2, 0x77, 0xf8, 0x3c, 0x3e, 0x0c, 0x0d, 0x4c, 0xcd, 0xb0, 0xcc, 0x45, 0x36, 0x58, 0xcc, + 0x59, 0x4b, 0x20, 0xb8, 0x19, 0x70, 0x97, 0xda, 0x90, 0x68, 0xac, 0x81, 0xa2, 0xdb, 0x28, 0x34, 0x33, 0x7a, 0xba, + 0xd5, 0x46, 0x3f, 0x72, 0x78, 0x61, 0xae, 0x61, 0x2c, 0x02, 0x99, 0xcb, 0x55, 0x8f, 0xfd, 0xe5, 0x87, 0xcd, 0x0a, + 0x83, 0x57, 0x64, 0x3a, 0x74, 0xc7, 0x31, 0xe3, 0xab, 0x3c, 0x71, 0x0c, 0x41, 0x26, 0x96, 0x4a, 0x37, 0x1c, 0x13, + 0x57, 0xd2, 0x67, 0x62, 0xc8, 0x76, 0xc3, 0x33, 0x73, 0xa1, 0x9b, 0xed, 0x1f, 0xce, 0xed, 0x9c, 0x13, 0x6e, 0xb4, + 0x92, 0x46, 0x1b, 0xf5, 0xcc, 0x50, 0x55, 0x17, 0xcc, 0xef, 0xa1, 0xd3, 0xd2, 0x62, 0xe7, 0xea, 0xdd, 0x0d, 0x5f, + 0xc1, 0x2b, 0xe3, 0x6f, 0xb1, 0x2a, 0xb4, 0x22, 0xc3, 0xed, 0x16, 0xf2, 0xe6, 0x4c, 0x0f, 0xbd, 0x22, 0x17, 0xaa, + 0xc3, 0x5f, 0xd4, 0x15, 0xe6, 0x61, 0xcc, 0xa8, 0x21, 0x3c, 0xfa, 0xbd, 0xce, 0x40, 0xf9, 0x07, 0x13, 0x93, 0x39, + 0x4b, 0x6e, 0x68, 0x21, 0xe2, 0x1f, 0x5f, 0x08, 0x13, 0xab, 0x6a, 0x0f, 0x06, 0xb2, 0x67, 0x2a, 0xee, 0xc1, 0xad, + 0x09, 0x1f, 0x73, 0x36, 0x4a, 0xf7, 0xa2, 0x1f, 0x1b, 0xa2, 0xf1, 0x63, 0xf4, 0x23, 0xb8, 0x3b, 0xbb, 0x57, 0x18, + 0xcb, 0xb8, 0x10, 0xfe, 0x1e, 0xeb, 0x61, 0xa9, 0x52, 0xc6, 0xda, 0xeb, 0x96, 0xc3, 0x0b, 0xa9, 0x37, 0x59, 0xfc, + 0xd0, 0x11, 0x6b, 0x9b, 0x82, 0x75, 0x48, 0x49, 0xe1, 0xd9, 0x15, 0x73, 0xab, 0xc5, 0xdc, 0xa5, 0x96, 0xf0, 0xd7, + 0x57, 0x0f, 0x4b, 0x15, 0x34, 0x1c, 0x84, 0xae, 0xb4, 0x85, 0x04, 0x18, 0xb8, 0x94, 0x3e, 0x9d, 0xee, 0x4c, 0x22, + 0xb3, 0x2c, 0x86, 0x77, 0x0f, 0x2a, 0x98, 0xff, 0xce, 0x36, 0xc2, 0xaa, 0xc0, 0xe5, 0x4a, 0x15, 0xf5, 0x52, 0x12, + 0x08, 0x40, 0x5f, 0x7a, 0x0f, 0xca, 0x8b, 0xa2, 0xdb, 0x68, 0x48, 0xd0, 0xc2, 0x52, 0x73, 0xad, 0x8a, 0xe9, 0x7e, + 0xf8, 0x7a, 0x60, 0xf0, 0xe1, 0x1d, 0xd2, 0x36, 0x9e, 0xf0, 0xa4, 0x84, 0xda, 0x1d, 0xb4, 0x0f, 0x56, 0xd9, 0x41, + 0xf9, 0xb7, 0x31, 0x45, 0x36, 0xbf, 0xcf, 0x7e, 0xa0, 0xae, 0xc3, 0x81, 0x2b, 0x58, 0xf5, 0x52, 0x46, 0xc1, 0x80, + 0x95, 0x53, 0xa0, 0xf6, 0x4e, 0x32, 0x9a, 0x4d, 0x19, 0xa8, 0xfb, 0x6d, 0xd1, 0x6a, 0x6e, 0x4f, 0xea, 0x7e, 0x43, + 0xc6, 0xd9, 0x47, 0x18, 0x67, 0x1f, 0x05, 0x5e, 0x2c, 0x92, 0xfc, 0x21, 0x63, 0x8d, 0x63, 0xd5, 0x14, 0xe8, 0xa8, + 0x03, 0xdc, 0x19, 0x38, 0xf0, 0x80, 0x2d, 0xca, 0xc1, 0x01, 0x75, 0x16, 0xf7, 0xb4, 0x91, 0x79, 0x6f, 0x4f, 0xa8, + 0x5d, 0xc4, 0x02, 0x37, 0x6b, 0x66, 0x5a, 0xd0, 0x5a, 0x61, 0x9c, 0xc7, 0x03, 0xde, 0xe6, 0x59, 0x2d, 0x7e, 0xc2, + 0x86, 0x35, 0x55, 0xfd, 0x06, 0x9a, 0xa3, 0x5a, 0x90, 0x9b, 0x27, 0xc6, 0x5b, 0x95, 0xf4, 0xa3, 0x68, 0x60, 0x39, + 0x15, 0x62, 0x48, 0x46, 0xbf, 0x35, 0x08, 0x6e, 0xb5, 0x57, 0x2b, 0xee, 0x11, 0x5f, 0xd4, 0xbc, 0xd5, 0xcc, 0x2d, + 0x00, 0x2d, 0xe2, 0xa8, 0xbc, 0x37, 0x89, 0xc0, 0xfb, 0xb6, 0x8c, 0x90, 0xb6, 0xec, 0xdb, 0x27, 0x22, 0x4b, 0xc5, + 0xe6, 0x3b, 0x3a, 0x19, 0xa4, 0x91, 0x1d, 0x51, 0x84, 0xaf, 0x4b, 0x48, 0xc2, 0x55, 0xd2, 0xb5, 0xca, 0xe4, 0x9c, + 0xa9, 0x94, 0xe3, 0xeb, 0x42, 0x4a, 0x7d, 0x65, 0xbf, 0x24, 0xae, 0xee, 0x64, 0x04, 0xbe, 0x9e, 0x30, 0xfd, 0x8e, + 0x16, 0x13, 0x06, 0x7e, 0x45, 0xfe, 0x76, 0x2c, 0xa5, 0xe4, 0xf2, 0x89, 0x88, 0xfb, 0x14, 0xc3, 0xfb, 0xa6, 0x03, + 0xac, 0x4d, 0x08, 0x94, 0x12, 0x17, 0xe1, 0x82, 0xe8, 0x4d, 0x21, 0x6f, 0xef, 0xe2, 0x02, 0x3b, 0x07, 0xc0, 0xd2, + 0x69, 0x12, 0xe0, 0x5f, 0x3e, 0xe6, 0x63, 0x35, 0xe6, 0xd4, 0xe8, 0xfa, 0xdd, 0xef, 0xe4, 0x1a, 0xe8, 0x6d, 0xe9, + 0x28, 0xd8, 0x6f, 0x0d, 0x20, 0x17, 0xee, 0xc2, 0xe0, 0xe2, 0x2b, 0xac, 0x2d, 0x0b, 0xe3, 0x8d, 0x05, 0xd0, 0xfb, + 0x3b, 0x03, 0x0b, 0x36, 0xcc, 0x31, 0x85, 0xc7, 0x61, 0x27, 0x4c, 0x07, 0x51, 0x41, 0x9e, 0x94, 0xcf, 0x7f, 0xd6, + 0x6a, 0xbf, 0x65, 0x63, 0xb8, 0xc3, 0x48, 0xbe, 0x5d, 0x38, 0x71, 0xe0, 0x01, 0x99, 0x26, 0xb3, 0xcd, 0xbe, 0xf1, + 0x91, 0x47, 0x5e, 0x8f, 0xe3, 0x5d, 0x2d, 0x85, 0xf9, 0x66, 0x45, 0xd7, 0x18, 0x42, 0x51, 0x84, 0xfd, 0x7e, 0x51, + 0x31, 0x45, 0x95, 0x41, 0x1b, 0x34, 0x2c, 0x6f, 0xc4, 0x2f, 0x70, 0xc6, 0xd0, 0x7a, 0x21, 0x7b, 0x47, 0x67, 0x1d, + 0xce, 0x1c, 0x66, 0x4c, 0x09, 0x8c, 0x4a, 0xcb, 0x82, 0x4e, 0xc0, 0xd1, 0xb9, 0xfa, 0x20, 0x2a, 0xae, 0x8e, 0x15, + 0x80, 0x27, 0x99, 0xc2, 0x3f, 0xf9, 0x26, 0x58, 0xf7, 0x5b, 0x35, 0xc3, 0xd4, 0x5f, 0xf4, 0xb6, 0x6b, 0xf9, 0x32, + 0xc4, 0x91, 0x36, 0x86, 0xd0, 0x3a, 0xb7, 0x77, 0x80, 0x22, 0x2e, 0xe8, 0x45, 0xaa, 0xf1, 0xb5, 0x5a, 0x0c, 0xcd, + 0xfa, 0x1a, 0xd7, 0x31, 0x6d, 0x10, 0xc5, 0xba, 0x6b, 0xe2, 0xeb, 0xea, 0xb5, 0x55, 0x95, 0x2a, 0x38, 0x83, 0x04, + 0xc2, 0xaa, 0xbc, 0x6c, 0x48, 0x25, 0xb9, 0x34, 0x9d, 0x4a, 0xd3, 0x69, 0x85, 0x50, 0x2e, 0x3d, 0x29, 0xef, 0x5f, + 0x21, 0x84, 0x81, 0x29, 0xb3, 0x03, 0xab, 0xd4, 0x16, 0x56, 0xc1, 0xab, 0x17, 0x1b, 0x58, 0x25, 0xe1, 0x78, 0x2e, + 0xd1, 0xa8, 0xa8, 0x70, 0xc8, 0x90, 0xbe, 0x10, 0x8b, 0x20, 0x01, 0xb0, 0xe8, 0x5d, 0xe6, 0xf2, 0xbe, 0x87, 0x43, + 0x61, 0x4f, 0x32, 0x09, 0xa7, 0x9b, 0xd0, 0x1c, 0x9e, 0xe1, 0x55, 0x3d, 0x8f, 0x10, 0xb0, 0xf4, 0x1c, 0xc3, 0xf3, + 0xcb, 0xdf, 0x7f, 0xf6, 0xd5, 0x59, 0x90, 0xa7, 0xff, 0x12, 0x25, 0xa1, 0xb1, 0xff, 0x1c, 0x0f, 0x1d, 0x12, 0x86, + 0x03, 0xdf, 0x1c, 0x61, 0x85, 0x83, 0x5b, 0x45, 0x7c, 0x06, 0x77, 0xf8, 0x58, 0x87, 0x1e, 0x00, 0x96, 0x50, 0x1c, + 0x82, 0x7c, 0x03, 0xc5, 0x0c, 0x0e, 0x68, 0xb2, 0x0c, 0x2f, 0x70, 0xc1, 0x6a, 0xa1, 0xbc, 0xbf, 0x6d, 0x79, 0x29, + 0xad, 0x76, 0xc9, 0x6b, 0xcc, 0x81, 0xca, 0xcf, 0xf0, 0xc2, 0x57, 0x98, 0x77, 0xa1, 0xdd, 0x17, 0xbe, 0x76, 0x40, + 0x4f, 0x21, 0x60, 0xa4, 0xfb, 0xbd, 0x26, 0xdc, 0x53, 0xf4, 0x32, 0x17, 0x87, 0x6d, 0x07, 0xdd, 0x0b, 0xcc, 0xd5, + 0x55, 0x95, 0x35, 0x07, 0x53, 0x68, 0x70, 0x50, 0x85, 0x33, 0x02, 0x73, 0xf5, 0xa2, 0x2c, 0x38, 0x07, 0xf1, 0xbe, + 0x27, 0x4c, 0x4e, 0x19, 0x0d, 0xe0, 0x45, 0x56, 0x3e, 0x3a, 0xd5, 0xe3, 0xe0, 0x32, 0x6e, 0xd8, 0xc4, 0x17, 0xc2, + 0xa7, 0x02, 0x2b, 0x69, 0x8d, 0x43, 0x23, 0x3a, 0xa2, 0x73, 0x30, 0xdb, 0x00, 0x0a, 0xee, 0xce, 0x87, 0x8d, 0x85, + 0x0a, 0x9e, 0xbe, 0xad, 0xbd, 0x54, 0x4d, 0x88, 0x33, 0x69, 0x0a, 0xee, 0xb6, 0x0d, 0x32, 0x78, 0xf3, 0xdb, 0x7f, + 0x2b, 0x2c, 0x12, 0x0c, 0xa8, 0xd4, 0x24, 0x41, 0x78, 0x82, 0xd2, 0x48, 0xb7, 0x72, 0x33, 0x81, 0x74, 0x22, 0x6a, + 0x46, 0xdd, 0x1b, 0xe7, 0xab, 0xa3, 0x06, 0xa2, 0xa2, 0x06, 0x2a, 0xa0, 0x06, 0xb2, 0xbe, 0xfd, 0x0b, 0x58, 0x08, + 0x1b, 0xa1, 0x4a, 0x04, 0x01, 0x11, 0xe6, 0xda, 0xf0, 0x01, 0x45, 0x12, 0x42, 0xde, 0x00, 0x2a, 0xa6, 0xe4, 0x25, + 0x18, 0x8d, 0xc3, 0xeb, 0x3d, 0xe0, 0x7e, 0x69, 0x19, 0x06, 0xcf, 0x29, 0x98, 0xfc, 0xb7, 0x3e, 0x1f, 0xaa, 0x97, + 0xab, 0x83, 0x10, 0x7e, 0x01, 0xb1, 0x22, 0x1c, 0x7f, 0xf1, 0x0b, 0x90, 0x4d, 0x85, 0xe5, 0xc1, 0x81, 0x04, 0x81, + 0x1f, 0xa2, 0x08, 0x07, 0x3c, 0xc3, 0xcb, 0x6c, 0x83, 0xe8, 0xf9, 0x59, 0xa9, 0x6a, 0x56, 0x32, 0x98, 0x55, 0xe1, + 0x69, 0x1c, 0x5d, 0x13, 0x06, 0x82, 0x0b, 0xb5, 0xfb, 0x06, 0x21, 0x50, 0xb6, 0xdc, 0x18, 0xba, 0xf4, 0x14, 0xcc, + 0x47, 0xe3, 0xe8, 0x2d, 0x83, 0x07, 0x7c, 0x8d, 0xc9, 0x3f, 0xd3, 0x2c, 0xd3, 0x86, 0x79, 0x6c, 0x04, 0x4e, 0xea, + 0x14, 0x25, 0x7f, 0x4b, 0x2e, 0xe2, 0xa8, 0x79, 0x19, 0xa1, 0x06, 0xfc, 0xdb, 0xe0, 0xa8, 0x4b, 0x13, 0x3a, 0x1a, + 0xf9, 0xe0, 0x37, 0x19, 0x31, 0x9b, 0x6c, 0xb5, 0x12, 0x15, 0x41, 0x4f, 0xec, 0x06, 0x03, 0x56, 0xe2, 0x05, 0xb0, + 0x0f, 0x96, 0x83, 0x25, 0xef, 0x44, 0xac, 0xfc, 0x29, 0x85, 0xc1, 0xea, 0x39, 0x43, 0x08, 0x67, 0x41, 0xcc, 0xc6, + 0xff, 0x7c, 0xa6, 0xe1, 0xfa, 0xf9, 0xf9, 0x3a, 0x46, 0x44, 0xfa, 0x20, 0x72, 0x35, 0x76, 0x44, 0x04, 0x61, 0xcb, + 0x74, 0xdf, 0x95, 0xf9, 0xc1, 0x5b, 0x57, 0x0f, 0x6c, 0xb8, 0x38, 0x30, 0xa0, 0x46, 0x81, 0xd1, 0x0a, 0xce, 0x49, + 0x39, 0x70, 0x50, 0x42, 0x68, 0x56, 0xc4, 0x53, 0x72, 0x09, 0x91, 0xf0, 0x32, 0xd4, 0x05, 0xc3, 0x82, 0x40, 0x82, + 0x9a, 0x82, 0x04, 0x95, 0xf9, 0xda, 0x23, 0x98, 0x75, 0x6e, 0x66, 0x3b, 0x45, 0x5d, 0x17, 0xe4, 0xe7, 0x17, 0x1d, + 0x8f, 0x80, 0xa5, 0x3d, 0x38, 0x28, 0x20, 0x82, 0x18, 0x50, 0xf0, 0x52, 0x02, 0x0c, 0xc2, 0xf1, 0x15, 0x1b, 0x1a, + 0xf0, 0xb9, 0x36, 0x5e, 0x07, 0xc6, 0xd6, 0xa7, 0x0c, 0x72, 0xf1, 0xac, 0xda, 0xd3, 0x84, 0x90, 0xfd, 0x56, 0x4f, + 0xa7, 0xdb, 0x11, 0x12, 0x7b, 0x1f, 0xb5, 0x09, 0x34, 0xe6, 0x48, 0x77, 0xb5, 0x31, 0xbf, 0xd6, 0xf4, 0x88, 0xd5, + 0x24, 0xa4, 0x0b, 0xd2, 0xe5, 0xf9, 0xb4, 0x67, 0x70, 0xc5, 0x2a, 0x8d, 0x1c, 0x5c, 0x80, 0x3e, 0x1b, 0x10, 0xa0, + 0x40, 0xa5, 0xa9, 0x44, 0x51, 0xc4, 0x45, 0x52, 0xb2, 0x61, 0x98, 0x41, 0x98, 0xc2, 0x6a, 0x25, 0xe8, 0xc6, 0x1a, + 0x00, 0xef, 0xcc, 0xec, 0x9f, 0xd2, 0x07, 0x9b, 0xae, 0xbd, 0x79, 0x04, 0x10, 0x90, 0xfd, 0x76, 0xc9, 0xae, 0x8b, + 0x8d, 0xca, 0x2c, 0xac, 0x65, 0x6c, 0xe5, 0xb6, 0x3d, 0xc6, 0xde, 0x89, 0x6d, 0x3e, 0x01, 0x42, 0xd4, 0x96, 0x4c, + 0x23, 0x44, 0x48, 0x2c, 0x62, 0x5d, 0x1b, 0xb2, 0xd1, 0x86, 0xc2, 0x53, 0x89, 0x1c, 0xb8, 0x44, 0x13, 0x24, 0xdf, + 0x71, 0x09, 0x0e, 0xe1, 0x85, 0x47, 0xf8, 0x5b, 0x60, 0x91, 0x0a, 0xcc, 0xb0, 0x5c, 0xad, 0xa0, 0x9e, 0xc7, 0xfb, + 0x6c, 0x33, 0x38, 0xa9, 0xdc, 0x18, 0xbb, 0xb4, 0x13, 0x8f, 0xcb, 0x26, 0x24, 0xce, 0xa0, 0x5f, 0x5f, 0x11, 0xf5, + 0xf6, 0xdb, 0xe9, 0x13, 0xff, 0x5e, 0x99, 0xdb, 0x81, 0xd8, 0xb0, 0xde, 0x60, 0xf5, 0x01, 0xb4, 0xfc, 0x55, 0xe6, + 0x1f, 0x2a, 0x0b, 0x6e, 0x12, 0xd4, 0xe6, 0x22, 0x76, 0x59, 0x17, 0x31, 0x52, 0x5b, 0xdc, 0x1d, 0x42, 0xfc, 0xab, + 0xad, 0x28, 0x06, 0x3c, 0xa9, 0xf8, 0xe7, 0x18, 0x75, 0x21, 0x14, 0xb5, 0xf5, 0xb0, 0x01, 0x4a, 0xbb, 0x5c, 0x57, + 0x62, 0x64, 0x48, 0x20, 0xdf, 0xba, 0xf0, 0x82, 0xe6, 0x24, 0x52, 0x20, 0x27, 0x07, 0x51, 0x49, 0xb3, 0x0d, 0x61, + 0xae, 0xbb, 0x85, 0x63, 0xe6, 0x6a, 0x83, 0x16, 0xf1, 0x0b, 0x60, 0x67, 0xb8, 0x91, 0x2c, 0x1d, 0xf8, 0x54, 0x0d, + 0x7c, 0x7e, 0xcd, 0x0d, 0x45, 0x51, 0xa8, 0xf7, 0xce, 0x3e, 0x32, 0x07, 0xbf, 0xd3, 0x40, 0x7c, 0xa4, 0x4e, 0x47, + 0xb2, 0x11, 0x6a, 0xcd, 0xd9, 0xf1, 0xb2, 0xcd, 0x08, 0x83, 0xc2, 0x46, 0xef, 0xab, 0x90, 0x55, 0xec, 0xec, 0x54, + 0x04, 0x73, 0xfa, 0xa2, 0x2a, 0xe7, 0x54, 0x6e, 0x19, 0xd5, 0x52, 0xd3, 0x00, 0x11, 0xae, 0x7c, 0x22, 0x79, 0x9f, + 0x99, 0xf0, 0x0f, 0x06, 0xe3, 0xea, 0x91, 0xc2, 0xdf, 0xef, 0x8a, 0x1d, 0xb2, 0x1d, 0x1d, 0x6e, 0x23, 0x68, 0x5e, + 0xa8, 0xe0, 0x01, 0x47, 0x25, 0x4b, 0x88, 0x14, 0xb9, 0xdc, 0x57, 0x35, 0x53, 0xb6, 0xeb, 0x08, 0x21, 0xa4, 0x3d, + 0xce, 0xba, 0xa1, 0xd5, 0x43, 0x8f, 0x54, 0x51, 0x0e, 0xb7, 0x68, 0xae, 0x0b, 0x50, 0x61, 0x04, 0xd2, 0xe5, 0x67, + 0x76, 0x97, 0x4a, 0x88, 0x5e, 0xbe, 0x76, 0x21, 0x8c, 0x9d, 0x95, 0x25, 0x2e, 0xcc, 0xa8, 0x6d, 0x18, 0x5d, 0xb7, + 0x31, 0x9c, 0x0d, 0x8c, 0x99, 0x06, 0x25, 0x2d, 0x08, 0x75, 0xdd, 0xa5, 0x17, 0x99, 0x09, 0xf4, 0x98, 0x13, 0xda, + 0x60, 0x78, 0x4a, 0x34, 0x58, 0x36, 0x15, 0x60, 0xc1, 0xb7, 0x2c, 0x52, 0x6b, 0xb3, 0xc9, 0xe2, 0x8f, 0x3a, 0x36, + 0x4f, 0xfb, 0xe5, 0x15, 0xf3, 0x5c, 0x38, 0xea, 0xf6, 0x3c, 0xf3, 0xf1, 0xe8, 0x9e, 0xbe, 0xb9, 0x7a, 0xf1, 0xf2, + 0xf5, 0xab, 0xd5, 0xaa, 0xcd, 0x9a, 0xed, 0x13, 0xfc, 0x93, 0x2e, 0xe3, 0xc1, 0x96, 0x51, 0x80, 0x0e, 0x0e, 0xf6, + 0xb9, 0x71, 0xe1, 0xf9, 0xcc, 0xe7, 0x10, 0x37, 0x48, 0x0f, 0x70, 0x56, 0x94, 0x31, 0x41, 0x6e, 0xa3, 0x5e, 0x74, + 0x17, 0x81, 0x12, 0xaa, 0x22, 0x7f, 0x1f, 0x36, 0x67, 0xbf, 0x07, 0x81, 0x89, 0xa0, 0x3e, 0x44, 0x00, 0x81, 0x78, + 0xa5, 0xb8, 0x20, 0xcc, 0x27, 0x40, 0x14, 0xef, 0x05, 0x70, 0xa6, 0x26, 0x6a, 0xd5, 0x42, 0xc5, 0x05, 0x90, 0x44, + 0x1b, 0x8e, 0x92, 0x1e, 0x99, 0x00, 0xde, 0x10, 0x94, 0xd2, 0xfe, 0xea, 0xe6, 0xce, 0x5d, 0x2a, 0x47, 0xbd, 0x56, + 0x9a, 0xe3, 0xa9, 0xfb, 0x9c, 0xc2, 0xe7, 0xb4, 0xeb, 0x4f, 0x07, 0x71, 0x98, 0xe3, 0x05, 0x11, 0x87, 0xfe, 0x59, + 0xc4, 0xe5, 0xbc, 0x60, 0x5f, 0xb8, 0x5c, 0xa8, 0x74, 0x79, 0x9b, 0xca, 0xe4, 0xb6, 0x39, 0x3a, 0x8c, 0x8b, 0xe4, + 0xb6, 0xa9, 0x92, 0x5b, 0x84, 0xef, 0x52, 0x99, 0xdc, 0xd9, 0x94, 0xbb, 0xa6, 0x82, 0x9b, 0x2f, 0x2c, 0xe0, 0x50, + 0xb4, 0x45, 0x1b, 0x8b, 0xcd, 0xa2, 0x36, 0xc5, 0x15, 0x0d, 0x30, 0xf8, 0xf7, 0x1d, 0x1b, 0x3f, 0x0c, 0x5f, 0x82, + 0x4b, 0x93, 0x26, 0xf2, 0x13, 0x48, 0x3f, 0xad, 0xca, 0xc0, 0x7d, 0x4a, 0x5a, 0xdd, 0xe9, 0x85, 0x68, 0xb6, 0xbb, + 0x8d, 0xc6, 0x14, 0xf6, 0x6e, 0x46, 0x72, 0x5f, 0x6c, 0xda, 0x30, 0xf1, 0x75, 0xf6, 0xb3, 0xd5, 0x6a, 0x3f, 0x47, + 0x66, 0xc3, 0x4d, 0x58, 0xac, 0xfb, 0xd3, 0x01, 0x6e, 0xe1, 0xe7, 0x19, 0x42, 0x4b, 0xd6, 0x9f, 0x0e, 0x08, 0xeb, + 0x4f, 0x1b, 0xed, 0x81, 0x35, 0xb4, 0x33, 0x5b, 0x71, 0x0d, 0x21, 0x34, 0xa7, 0x83, 0x23, 0x53, 0x52, 0xba, 0x7c, + 0xfb, 0x45, 0xab, 0x80, 0x7e, 0xaa, 0x16, 0xbc, 0x4c, 0xe2, 0x0e, 0xf4, 0x45, 0x2f, 0xec, 0xd3, 0xad, 0x05, 0x39, + 0x3e, 0xaa, 0x5c, 0xed, 0x29, 0xc2, 0xa6, 0x27, 0x75, 0x58, 0x1c, 0x9a, 0x66, 0x5c, 0x97, 0xd2, 0x7d, 0x87, 0x9a, + 0x91, 0x8f, 0x0e, 0x16, 0x80, 0x20, 0x15, 0x3c, 0xb2, 0xc2, 0x85, 0x53, 0x0a, 0xe1, 0xe2, 0xa0, 0xb2, 0x05, 0x93, + 0x9c, 0xb4, 0xba, 0xb9, 0xb1, 0xf4, 0xcf, 0x5d, 0x44, 0x53, 0x8a, 0x29, 0xc9, 0x7c, 0xc9, 0xdc, 0x80, 0x85, 0x6e, + 0x52, 0x9e, 0x29, 0xe8, 0x95, 0x06, 0x78, 0x44, 0x20, 0x1e, 0x52, 0xb7, 0x30, 0x06, 0x5e, 0xf1, 0xb4, 0x59, 0xf4, + 0xd9, 0x00, 0x1d, 0x1d, 0x63, 0xda, 0xff, 0x94, 0xcd, 0xdb, 0xf0, 0x58, 0xe0, 0xa7, 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, 0xff, 0x0c, 0xe2, 0x38, 0xc6, 0x1c, 0xe2, 0x2a, 0x6a, 0x1b, 0x19, 0x0f, + 0x2e, 0x3c, 0xf7, 0x59, 0xa2, 0xca, 0xe5, 0x0f, 0x63, 0xc8, 0x6d, 0xd9, 0x4a, 0x18, 0xb7, 0x29, 0xa6, 0x20, 0x72, + 0xfa, 0xc1, 0x41, 0xe9, 0xee, 0x0c, 0x3e, 0xea, 0x29, 0xc7, 0x4b, 0xeb, 0x44, 0xfb, 0x07, 0xe8, 0xe4, 0xcd, 0xaf, + 0x8f, 0xa9, 0x5c, 0x13, 0xe1, 0x4c, 0xee, 0xf7, 0xdb, 0x9e, 0x52, 0xfc, 0x99, 0x99, 0xf0, 0xe4, 0x3c, 0xd1, 0x46, + 0x04, 0x41, 0x88, 0x12, 0x85, 0x33, 0x22, 0xed, 0x7e, 0xf7, 0xae, 0xf0, 0x46, 0x15, 0xe5, 0xcd, 0x4a, 0x1e, 0xe7, + 0xe0, 0xc4, 0x6e, 0xac, 0x30, 0x50, 0x17, 0x5c, 0x08, 0x32, 0x93, 0xf0, 0x47, 0x33, 0xb7, 0xe4, 0x2c, 0x2b, 0x93, + 0x3e, 0x36, 0x73, 0x43, 0xc0, 0x0a, 0xb2, 0xef, 0x61, 0xb6, 0xbc, 0x4d, 0xe9, 0xff, 0xcb, 0xde, 0xbb, 0x2e, 0xb7, + 0x8d, 0x64, 0xe9, 0xa2, 0xaf, 0x22, 0x31, 0x6c, 0x16, 0x60, 0x26, 0x29, 0xca, 0x7b, 0xcf, 0x44, 0x1c, 0x50, 0x29, + 0x86, 0x2f, 0xe5, 0x2e, 0x77, 0x97, 0x2f, 0x6d, 0xb9, 0xab, 0xab, 0x9a, 0xc1, 0xc3, 0x82, 0x80, 0xa4, 0x00, 0x17, + 0x08, 0xb0, 0x00, 0x50, 0x22, 0x4d, 0xe2, 0xdd, 0x77, 0xac, 0xb5, 0xf2, 0x0a, 0x82, 0xb2, 0x7b, 0x66, 0xcf, 0xaf, + 0x73, 0xfe, 0xd8, 0x62, 0x22, 0x91, 0xc8, 0x7b, 0xae, 0x5c, 0x97, 0xef, 0x63, 0xbb, 0x20, 0x62, 0xb7, 0xc5, 0x36, + 0x28, 0x6d, 0x5f, 0x10, 0x65, 0xf8, 0x5b, 0x7a, 0xbd, 0x3c, 0x84, 0x78, 0x9f, 0x5e, 0x9a, 0x9f, 0xa5, 0xad, 0x28, + 0xc0, 0x7d, 0x84, 0x1e, 0xd5, 0x81, 0x60, 0x27, 0x3c, 0xe1, 0x01, 0x9c, 0xac, 0x66, 0x15, 0x7f, 0x92, 0x82, 0x38, + 0x51, 0x70, 0x08, 0xb8, 0xda, 0xde, 0xa4, 0x5f, 0xc1, 0xf0, 0xa5, 0x83, 0x2d, 0x87, 0xb7, 0xc5, 0xb6, 0xc7, 0x4a, + 0xfe, 0x11, 0xd8, 0xb7, 0x7a, 0x32, 0x56, 0xb7, 0x07, 0xce, 0xba, 0x94, 0xa2, 0xe3, 0x4d, 0x71, 0x78, 0x7b, 0x3e, + 0xdb, 0x6f, 0x83, 0x88, 0xed, 0x82, 0x0c, 0x6b, 0x9d, 0x34, 0xfc, 0xaf, 0xb4, 0x75, 0xb0, 0x18, 0x61, 0xff, 0x97, + 0xf5, 0xc0, 0x4b, 0x48, 0x0d, 0x05, 0x2e, 0x06, 0x1b, 0x8e, 0xd6, 0x76, 0x99, 0x06, 0x6e, 0x6a, 0xd0, 0xeb, 0x7b, + 0x0a, 0x51, 0x5e, 0x32, 0x9a, 0x1b, 0xc1, 0xba, 0x31, 0xe4, 0xe2, 0x70, 0xdc, 0x2c, 0x87, 0xbc, 0xa4, 0xe9, 0x34, + 0x08, 0xa5, 0x3b, 0xcb, 0x1a, 0x92, 0x28, 0xfb, 0x20, 0xd4, 0xae, 0x2d, 0xfb, 0x6d, 0x60, 0xfb, 0xf2, 0x47, 0xc3, + 0xd8, 0xbf, 0x58, 0x3e, 0x13, 0xd2, 0x45, 0x3c, 0x07, 0x41, 0xd4, 0x7e, 0x9e, 0x0d, 0x37, 0xfe, 0xc5, 0xfa, 0x99, + 0x50, 0x7e, 0xe3, 0xb9, 0x2d, 0x87, 0xd4, 0x59, 0x0b, 0x5f, 0x18, 0x0f, 0x0f, 0xae, 0x0c, 0x6d, 0x87, 0x83, 0xd0, + 0x7f, 0x9b, 0x35, 0x82, 0x1b, 0x1b, 0xda, 0xe7, 0x0b, 0x1f, 0xb6, 0x36, 0x1a, 0x6b, 0x8a, 0xe9, 0x16, 0xfa, 0x37, + 0x99, 0x2d, 0xed, 0x69, 0x54, 0xf2, 0xe2, 0xd4, 0x34, 0x62, 0x21, 0x0c, 0x18, 0xfa, 0xc9, 0x7c, 0x04, 0xd5, 0xdc, + 0xf1, 0x08, 0x64, 0xf2, 0x81, 0x1e, 0xac, 0x49, 0xad, 0xfa, 0x6b, 0x98, 0xc9, 0xff, 0x23, 0x15, 0x16, 0xa3, 0xbb, + 0x6d, 0x98, 0xa9, 0x3f, 0x22, 0xf9, 0x07, 0xcb, 0xf9, 0x2e, 0xf5, 0x42, 0xed, 0xc7, 0xc2, 0x0a, 0x0c, 0x4a, 0x54, + 0x0d, 0xe8, 0x81, 0x08, 0xaa, 0x32, 0x48, 0x33, 0xac, 0xce, 0x41, 0xbf, 0x7b, 0x5a, 0x75, 0x24, 0x87, 0xb4, 0x56, + 0x43, 0x2a, 0x98, 0x2a, 0x35, 0xc8, 0x0f, 0x87, 0xbb, 0x94, 0xe9, 0x32, 0xe0, 0x92, 0x7e, 0x97, 0x2a, 0xa5, 0xf0, + 0x9f, 0x08, 0x40, 0xe7, 0xe0, 0x1e, 0x5f, 0x8e, 0x81, 0x34, 0xc3, 0xc2, 0x6f, 0xcd, 0x8e, 0xaf, 0x49, 0xb8, 0x4d, + 0x82, 0x8b, 0x01, 0xce, 0xd1, 0x55, 0x58, 0xde, 0xa5, 0x10, 0x41, 0x55, 0x42, 0x7d, 0x2b, 0xd3, 0xa0, 0xb4, 0xd5, + 0x20, 0xac, 0x49, 0xa8, 0x33, 0xc9, 0x46, 0xa5, 0xed, 0x46, 0x61, 0xb6, 0x88, 0xeb, 0x19, 0x61, 0xcd, 0xd9, 0x4c, + 0x35, 0x30, 0x69, 0x38, 0x6e, 0x1a, 0xad, 0x45, 0x85, 0x9a, 0xc2, 0xbc, 0xc6, 0x55, 0xa5, 0xaa, 0xbb, 0x39, 0xb5, + 0x94, 0x96, 0xed, 0x55, 0x37, 0xc9, 0x86, 0x5c, 0x86, 0x32, 0x0c, 0x36, 0x72, 0x04, 0x13, 0x48, 0x92, 0x33, 0x7f, + 0x23, 0xff, 0x50, 0x9b, 0xae, 0x05, 0xcc, 0x31, 0x66, 0xd9, 0xb0, 0xa0, 0x57, 0xe0, 0x1e, 0x68, 0xa5, 0xe7, 0xd3, + 0xec, 0x22, 0x0f, 0x92, 0x61, 0xa1, 0x97, 0x4d, 0xc6, 0xff, 0x14, 0x46, 0x9a, 0xcc, 0x58, 0xc9, 0x22, 0xdb, 0xd5, + 0x29, 0x71, 0x1e, 0x27, 0xb0, 0x3d, 0x9a, 0xde, 0xf2, 0x7d, 0x06, 0x51, 0x41, 0xa0, 0x60, 0xc6, 0x7c, 0xd9, 0xc5, + 0x73, 0xdf, 0x67, 0x96, 0xa9, 0xfb, 0x70, 0x30, 0x66, 0x6c, 0xbf, 0xdf, 0xcf, 0xfb, 0x7d, 0x35, 0xdf, 0xfa, 0xfd, + 0xe4, 0xda, 0xfc, 0xed, 0x01, 0x83, 0x82, 0x9c, 0x88, 0xa6, 0x42, 0x04, 0xff, 0x90, 0x3c, 0x43, 0x32, 0xba, 0xe3, + 0x3e, 0xb7, 0x9c, 0x2d, 0xab, 0x23, 0x10, 0xcc, 0xc3, 0xe1, 0x52, 0x81, 0x5d, 0x4b, 0x14, 0x09, 0x59, 0xfe, 0x33, + 0x30, 0x9e, 0xb9, 0x0f, 0xb0, 0x64, 0x00, 0xc2, 0x56, 0x79, 0xba, 0xde, 0xf3, 0x55, 0xf0, 0x4e, 0xc7, 0xbb, 0xc6, + 0x8a, 0x0c, 0xc4, 0x2d, 0xb0, 0x11, 0x6b, 0xed, 0x01, 0x39, 0x53, 0x80, 0xe3, 0xc5, 0xe1, 0x70, 0x2e, 0x7f, 0xe9, + 0x66, 0xeb, 0x04, 0x2a, 0x05, 0x6e, 0x8f, 0x4e, 0x0e, 0xfe, 0x3b, 0xd0, 0x0c, 0xca, 0x61, 0x5e, 0x6f, 0x7f, 0x67, + 0x4e, 0x7e, 0x7a, 0x8a, 0x7f, 0xc2, 0x43, 0x74, 0xfa, 0xed, 0xde, 0xfc, 0x41, 0x51, 0x79, 0x38, 0xa8, 0xc5, 0x7f, + 0xce, 0x79, 0x05, 0xbf, 0xf0, 0x4d, 0x60, 0x36, 0x99, 0x7a, 0x27, 0xdf, 0xe4, 0x39, 0x53, 0xaf, 0xf1, 0x8a, 0xc9, + 0x77, 0x38, 0x9c, 0x8b, 0x51, 0xbd, 0x1d, 0x39, 0xd1, 0x4e, 0x39, 0xc6, 0xc1, 0xe0, 0xbf, 0x88, 0xb6, 0x09, 0x01, + 0x86, 0xd4, 0x2d, 0x69, 0x66, 0xe3, 0xca, 0x12, 0xcf, 0xd2, 0xf9, 0xe5, 0xa4, 0x2e, 0x77, 0x5a, 0xf1, 0xb4, 0x07, + 0x16, 0xb7, 0x35, 0x78, 0x01, 0xdc, 0x5b, 0x6c, 0x5d, 0x29, 0x38, 0x5c, 0x40, 0x9c, 0xe2, 0x04, 0x44, 0xd0, 0x7e, + 0x5f, 0xe2, 0xbd, 0x82, 0x3e, 0xe9, 0x47, 0x08, 0x86, 0xfc, 0x59, 0x02, 0xee, 0x7a, 0xbd, 0x1a, 0xe3, 0x7b, 0x29, + 0x04, 0xd7, 0x67, 0x1a, 0x80, 0x16, 0xfc, 0x2e, 0x1f, 0xcb, 0xe9, 0x37, 0x11, 0x78, 0xb6, 0xec, 0x4d, 0x94, 0xbb, + 0x0d, 0x4f, 0xfb, 0x47, 0x0b, 0x01, 0x58, 0x8a, 0x67, 0x4a, 0xb0, 0x20, 0xa7, 0x98, 0x8b, 0xff, 0x17, 0x7c, 0xc4, + 0x7c, 0x4f, 0xba, 0x88, 0xad, 0xb7, 0x4f, 0x2e, 0x0c, 0x24, 0xd0, 0x74, 0x00, 0x7e, 0xbc, 0x0a, 0xe8, 0xca, 0xf8, + 0xf9, 0x59, 0xd6, 0x63, 0x7d, 0xfc, 0xa7, 0xe0, 0x3e, 0xfd, 0x4c, 0xe1, 0xa3, 0xc3, 0x71, 0x95, 0x8e, 0x76, 0x94, + 0x82, 0xe8, 0xe8, 0xf6, 0xf9, 0x94, 0x67, 0xdf, 0x55, 0x40, 0x6e, 0x39, 0x6a, 0x4f, 0x05, 0x60, 0xb1, 0xa5, 0x23, + 0xf0, 0x69, 0x96, 0x4f, 0xc8, 0xf7, 0x7a, 0x2a, 0xae, 0x2e, 0x75, 0xba, 0xb8, 0x1e, 0x4f, 0xe1, 0x7f, 0x20, 0xf6, + 0xb0, 0x4c, 0x91, 0x1d, 0xbb, 0x2e, 0x7e, 0x10, 0x6f, 0x6b, 0x3b, 0xfa, 0x63, 0x07, 0x91, 0x8e, 0x7b, 0x72, 0xa1, + 0xbe, 0x84, 0x54, 0x72, 0xa1, 0x6e, 0x20, 0x76, 0xa1, 0xc6, 0x3b, 0x2e, 0x62, 0xad, 0xbf, 0xab, 0x51, 0xb0, 0x12, + 0x70, 0xa6, 0xbd, 0x03, 0x83, 0x0d, 0xac, 0x5b, 0x96, 0xc1, 0xdf, 0x70, 0x4d, 0x13, 0xb8, 0x61, 0x91, 0xf5, 0xde, + 0x60, 0x2b, 0xbd, 0x03, 0x47, 0xcb, 0xc4, 0xb9, 0x94, 0x64, 0x65, 0x8b, 0x8c, 0xab, 0x47, 0x21, 0x55, 0xd3, 0xfd, + 0xad, 0xa8, 0x1f, 0x84, 0xc8, 0x83, 0x55, 0xca, 0xa2, 0x62, 0x05, 0x32, 0x7b, 0xf0, 0xf7, 0x90, 0x91, 0xa3, 0x1c, + 0x38, 0x0a, 0xfd, 0xbd, 0x09, 0x74, 0x9e, 0xbf, 0x86, 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, 0x75, 0x40, 0xa9, 0x3b, 0xc0, 0xc6, 0xdb, 0x06, + 0x1d, 0xf9, 0xb7, 0x3b, 0xa4, 0xd4, 0x4d, 0x06, 0x60, 0x37, 0x1a, 0xe0, 0x90, 0xa9, 0x5e, 0x8a, 0xac, 0x5e, 0xca, + 0x54, 0x2f, 0xc9, 0xca, 0x25, 0x58, 0x48, 0x4c, 0x95, 0xdb, 0xc8, 0xca, 0x2d, 0x1b, 0xae, 0x87, 0x83, 0xad, 0x15, + 0x97, 0xcd, 0x1d, 0xdc, 0x17, 0x56, 0x14, 0xf8, 0x7f, 0xcb, 0x16, 0xec, 0x5e, 0x1e, 0x03, 0xef, 0xd0, 0x31, 0x09, + 0x2e, 0x10, 0xf7, 0xec, 0x16, 0xec, 0xb0, 0xf0, 0x17, 0x5c, 0x27, 0xc7, 0x6c, 0x87, 0x8f, 0x42, 0xaf, 0x60, 0xb7, + 0x3e, 0x01, 0xed, 0x82, 0xad, 0x01, 0xb2, 0xb1, 0x2d, 0x3e, 0xba, 0x3b, 0x1c, 0xde, 0x79, 0x3e, 0x7b, 0xc0, 0x1f, + 0xe7, 0x77, 0x87, 0xc3, 0xce, 0x33, 0xea, 0xbd, 0x1b, 0x9e, 0xb0, 0x0f, 0x3c, 0x99, 0xdc, 0x5c, 0xf1, 0x78, 0x32, + 0x18, 0xdc, 0xf8, 0x0b, 0x5e, 0xcf, 0x6e, 0x40, 0x3b, 0x70, 0xbe, 0x90, 0xba, 0x66, 0xef, 0x96, 0x67, 0xde, 0x02, + 0xc7, 0xe6, 0x16, 0x8e, 0xde, 0x7e, 0xdf, 0xbb, 0xe3, 0x91, 0x77, 0x4b, 0x2a, 0xa6, 0x15, 0x57, 0x1c, 0x6f, 0x5b, + 0xdc, 0x4f, 0x57, 0x3c, 0x84, 0x47, 0x58, 0x95, 0xe9, 0x4d, 0xf0, 0xc1, 0x67, 0x2b, 0xcd, 0x02, 0xf7, 0x80, 0x39, + 0xd6, 0x64, 0x27, 0x34, 0x13, 0x7f, 0x85, 0xfd, 0x73, 0xa3, 0xfa, 0x87, 0xe6, 0x7f, 0xa9, 0xfb, 0x09, 0xdc, 0xbe, + 0xc8, 0x82, 0xc4, 0x3e, 0xf0, 0x1b, 0x76, 0xcf, 0x0d, 0xdb, 0xec, 0x99, 0x29, 0xfb, 0x44, 0xa9, 0xf1, 0x23, 0xa5, + 0xae, 0x2d, 0xc3, 0x4a, 0xe6, 0xee, 0xcb, 0x08, 0x1c, 0x0e, 0xc8, 0x4f, 0x77, 0x88, 0x83, 0xd0, 0xba, 0xc9, 0x6a, + 0xae, 0x28, 0xe7, 0x42, 0x5b, 0x66, 0x5e, 0x0e, 0x2c, 0x66, 0x29, 0x85, 0xc6, 0x02, 0x00, 0xc1, 0xa4, 0xd0, 0xda, + 0x7b, 0x19, 0x40, 0x4e, 0xd0, 0xf0, 0xc7, 0xe6, 0xaa, 0x28, 0x6b, 0xd9, 0x92, 0x10, 0x65, 0xbb, 0x1e, 0x5e, 0x22, + 0x64, 0x5a, 0xbf, 0x7f, 0x4e, 0x24, 0x6b, 0x93, 0xea, 0xaa, 0x46, 0x4b, 0x40, 0x45, 0x96, 0x80, 0x89, 0x5f, 0x69, + 0x3e, 0x01, 0x78, 0xd2, 0xf1, 0xa0, 0x7a, 0xca, 0x6b, 0x26, 0x88, 0x6c, 0xa3, 0xf2, 0x27, 0xc5, 0x35, 0x92, 0x11, + 0x14, 0x4f, 0x6b, 0x95, 0xb1, 0x30, 0xcc, 0x03, 0x05, 0xe4, 0xdd, 0xbb, 0x53, 0xdf, 0xda, 0x1f, 0x3b, 0xf6, 0x6c, + 0xad, 0x42, 0x2d, 0xd4, 0x14, 0x2e, 0x39, 0x44, 0x57, 0x90, 0x81, 0x42, 0xc6, 0x93, 0xd7, 0x83, 0xcb, 0x49, 0x74, + 0xc5, 0x05, 0x3a, 0xe3, 0xeb, 0x9b, 0x6e, 0x3a, 0x8b, 0x9e, 0x56, 0xf3, 0x09, 0x29, 0xc9, 0x0e, 0x87, 0x6c, 0x54, + 0xd5, 0xc5, 0x7a, 0x1a, 0xca, 0x9f, 0x1e, 0x82, 0xaf, 0x17, 0xd4, 0x6b, 0xb2, 0x4a, 0xf5, 0x53, 0xaa, 0x94, 0x17, + 0x0d, 0x2f, 0xfd, 0xa7, 0x95, 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, 0x53, 0xa9, 0x0d, 0x67, 0xae, 0x21, 0xb8, 0xcf, 0xcf, 0xd3, 0xd1, 0x02, 0x3e, 0xa4, 0xba, + 0xbd, 0xc4, 0xcf, 0x87, 0x0d, 0x8f, 0x80, 0xcc, 0x8e, 0xf8, 0xcc, 0x26, 0x92, 0x4e, 0xea, 0x5c, 0x01, 0xbb, 0x9d, + 0xbd, 0x03, 0x39, 0x62, 0xe6, 0xbe, 0x42, 0xf5, 0x2d, 0x1a, 0x70, 0x65, 0xac, 0x7d, 0x4d, 0x32, 0x16, 0x5e, 0x95, + 0xd3, 0x70, 0x00, 0x30, 0x74, 0x19, 0x7d, 0x6d, 0xb9, 0xc9, 0xb2, 0x9f, 0x0b, 0x08, 0x82, 0x28, 0x89, 0xc7, 0x07, + 0xbc, 0x2f, 0xab, 0xa1, 0x46, 0xc9, 0xc7, 0xb2, 0x91, 0x4a, 0xaf, 0x44, 0x7f, 0x37, 0xe6, 0x12, 0x03, 0xbe, 0xab, + 0xda, 0x82, 0xc2, 0x79, 0x7e, 0x38, 0x9c, 0xe7, 0x23, 0xe3, 0x59, 0x06, 0xaa, 0x95, 0x69, 0x1d, 0xc4, 0x66, 0xbe, + 0x58, 0xf8, 0x8b, 0x9d, 0x93, 0x88, 0x28, 0x08, 0xec, 0x48, 0x78, 0x10, 0xa9, 0x5f, 0x55, 0x9e, 0xee, 0x54, 0x9f, + 0xed, 0x17, 0x36, 0x91, 0x5e, 0x50, 0x32, 0xf9, 0x24, 0xd8, 0xab, 0xfe, 0x0e, 0xc2, 0x86, 0xf0, 0xe6, 0x55, 0xaf, + 0xb3, 0x4c, 0xcd, 0x4a, 0x90, 0x30, 0x63, 0x8e, 0xe0, 0x71, 0xd8, 0x69, 0x6c, 0xc3, 0x63, 0x0b, 0x8e, 0xce, 0x5b, + 0xb3, 0x3b, 0xb6, 0x62, 0xb7, 0xaa, 0x4e, 0x0b, 0x1e, 0x4e, 0x87, 0x97, 0x01, 0xae, 0xbe, 0xf5, 0x39, 0xe7, 0x77, + 0x74, 0x82, 0xad, 0x07, 0x3c, 0x9a, 0x88, 0xd9, 0xfa, 0x69, 0xa4, 0x16, 0xcf, 0x7a, 0xc8, 0x17, 0xb4, 0xfe, 0xc4, + 0xec, 0xce, 0x24, 0xdf, 0x0d, 0xf8, 0x62, 0xb2, 0x7e, 0x1a, 0xc1, 0xab, 0x4f, 0xc1, 0x8a, 0x91, 0x39, 0xb3, 0x6c, + 0xfd, 0x34, 0xc2, 0x31, 0xbb, 0x7b, 0x1a, 0xd1, 0xa8, 0xad, 0xe4, 0xbe, 0x74, 0xdb, 0x80, 0xb0, 0x72, 0xcb, 0x62, + 0x78, 0x0d, 0xc4, 0x33, 0x6d, 0x24, 0x5d, 0x4b, 0x43, 0x6f, 0xcc, 0xc3, 0x69, 0x1c, 0xac, 0xa9, 0x15, 0xf2, 0xcc, + 0x10, 0xb3, 0xf8, 0x69, 0x34, 0x67, 0x2b, 0xac, 0xc8, 0x86, 0xc7, 0x83, 0xcb, 0xc9, 0xe6, 0x8a, 0xaf, 0x81, 0xfc, + 0x6c, 0xb2, 0x31, 0x5b, 0xd4, 0x2d, 0x17, 0xb3, 0xcd, 0xd3, 0x68, 0x3e, 0x59, 0x41, 0xcf, 0xda, 0x03, 0xe6, 0xbd, + 0x01, 0x11, 0x4a, 0x42, 0x6a, 0xca, 0x4d, 0xaf, 0xc7, 0xd6, 0xe3, 0xe0, 0x8e, 0xad, 0x2f, 0x83, 0x5b, 0xb6, 0x1e, + 0x03, 0x11, 0x07, 0xf5, 0xbb, 0xb7, 0x81, 0xc5, 0x17, 0xb1, 0xf5, 0xa5, 0x49, 0xdb, 0x3c, 0x8d, 0x98, 0x3b, 0x38, + 0x0d, 0x5c, 0xb0, 0x36, 0x99, 0xb7, 0x62, 0x70, 0x09, 0x59, 0x7a, 0x31, 0xdb, 0x0c, 0x2f, 0xd9, 0x7a, 0x84, 0x53, + 0x3d, 0xf1, 0xd9, 0x1d, 0xbf, 0x65, 0x09, 0x5f, 0x35, 0xf1, 0xd5, 0x06, 0x34, 0xa2, 0x47, 0x19, 0xf4, 0x15, 0xd4, + 0xcc, 0x9c, 0x57, 0x16, 0x46, 0xe5, 0xbe, 0x05, 0x07, 0x14, 0xa4, 0x6d, 0x80, 0x20, 0x89, 0x67, 0xf7, 0x2a, 0x5c, + 0xdf, 0x48, 0x61, 0xc0, 0x4d, 0x60, 0x06, 0x0c, 0x4c, 0x3f, 0x83, 0x1f, 0x56, 0xba, 0x44, 0x88, 0xb3, 0x9f, 0x52, + 0x92, 0xcc, 0xf3, 0xd7, 0x22, 0xcd, 0xdd, 0xc2, 0x75, 0x0a, 0xb3, 0xa2, 0x40, 0xf5, 0x53, 0x52, 0x1a, 0x58, 0xa8, + 0x44, 0xa6, 0x52, 0xf0, 0xcb, 0xe6, 0x3c, 0xca, 0x8e, 0xd1, 0xb9, 0xce, 0x2f, 0x27, 0xce, 0xe9, 0xa4, 0xef, 0x3f, + 0x70, 0x0c, 0x5b, 0xc8, 0xc0, 0x85, 0x3f, 0xf5, 0x84, 0x71, 0x6a, 0x05, 0x62, 0x2a, 0x79, 0xf6, 0x14, 0x3e, 0x13, + 0x5a, 0x1d, 0x5d, 0xf8, 0x7e, 0x50, 0x68, 0x93, 0x74, 0x0b, 0x92, 0x14, 0x3c, 0x45, 0xcf, 0x39, 0x6f, 0x03, 0x95, + 0x62, 0x44, 0x0b, 0x22, 0x6d, 0x2d, 0x33, 0x07, 0x69, 0x4b, 0xf3, 0x5d, 0x13, 0x3f, 0x87, 0x05, 0x5c, 0x44, 0x0b, + 0x5b, 0xc3, 0xa3, 0x2a, 0x56, 0xee, 0x4d, 0x9e, 0x23, 0x9c, 0xd1, 0xa5, 0x4c, 0x00, 0x5c, 0xef, 0xd7, 0x61, 0xad, + 0xf0, 0x8a, 0x9a, 0x45, 0x5e, 0xd4, 0xf4, 0xc9, 0x16, 0xb8, 0x8f, 0x45, 0x89, 0x02, 0x67, 0x2d, 0x18, 0xb0, 0x15, + 0x96, 0xec, 0xa4, 0xb0, 0x29, 0x5a, 0x42, 0x6f, 0x8f, 0x9f, 0x0e, 0x6a, 0x26, 0x03, 0x68, 0x02, 0x68, 0x3c, 0xfe, + 0x05, 0xa0, 0xa6, 0x37, 0xb5, 0x58, 0x57, 0x41, 0xa9, 0x94, 0x9b, 0xf0, 0x33, 0x30, 0xcc, 0xf0, 0x43, 0x21, 0xb7, + 0x89, 0x12, 0x39, 0x3f, 0x16, 0xa5, 0x58, 0x96, 0xa2, 0x4a, 0xda, 0x0d, 0x05, 0x8f, 0x08, 0xb7, 0x41, 0x63, 0xe6, + 0xf6, 0x44, 0x17, 0xad, 0x08, 0xe5, 0xd8, 0xac, 0x63, 0xa4, 0x51, 0x66, 0x27, 0xbb, 0x4e, 0x16, 0xda, 0xef, 0xab, + 0x1c, 0xb2, 0x0e, 0x58, 0x23, 0xf9, 0x7a, 0xcd, 0xa1, 0xdb, 0x46, 0x79, 0xf1, 0xe0, 0xf9, 0x0a, 0x4e, 0x73, 0x3c, + 0xb1, 0xbb, 0x5e, 0x77, 0x8a, 0x44, 0xbc, 0xc2, 0x49, 0x95, 0x8f, 0x64, 0xe1, 0xb8, 0x73, 0xa7, 0xb5, 0x58, 0x55, + 0x2e, 0xeb, 0xa9, 0xc5, 0x11, 0x81, 0x4f, 0xe5, 0xd1, 0x5e, 0x68, 0x5b, 0x14, 0x0b, 0x61, 0xf4, 0xe8, 0x84, 0x9f, + 0x94, 0xc0, 0xfa, 0x3a, 0x1c, 0x96, 0x7e, 0xc4, 0xd1, 0xef, 0x34, 0x1a, 0x2d, 0x08, 0x69, 0x78, 0xea, 0x45, 0xa3, + 0x45, 0x5d, 0xd4, 0x61, 0x76, 0x9d, 0xeb, 0x81, 0xc2, 0x30, 0x02, 0xf5, 0x83, 0xab, 0x0c, 0x3e, 0x8b, 0x10, 0x35, + 0x0f, 0x4c, 0xb3, 0x21, 0x1c, 0x75, 0x81, 0x87, 0x56, 0xd0, 0x62, 0x66, 0x3e, 0x0a, 0x31, 0x7c, 0x48, 0x17, 0xe7, + 0x4f, 0xc8, 0xca, 0x07, 0xd8, 0x1d, 0xba, 0x0b, 0xe5, 0x9c, 0xa9, 0x18, 0xe0, 0x47, 0x01, 0xf9, 0x28, 0x01, 0x37, + 0x03, 0x64, 0x8f, 0x2c, 0x01, 0xc4, 0x8a, 0xd1, 0xd1, 0xe4, 0x73, 0xdf, 0x8b, 0x14, 0xbc, 0xb3, 0xcf, 0x72, 0x35, + 0x61, 0x28, 0x7c, 0x62, 0xa0, 0x9b, 0xdf, 0xf8, 0xed, 0x79, 0x0b, 0x46, 0x76, 0x49, 0x8a, 0xd7, 0x9a, 0xe1, 0x7e, + 0x03, 0x6e, 0x47, 0x40, 0x59, 0x53, 0x1d, 0x93, 0x6c, 0xd3, 0x10, 0xc9, 0x80, 0x19, 0x31, 0x22, 0xa8, 0x2c, 0x17, + 0xfe, 0x77, 0x2f, 0x8b, 0x02, 0x07, 0x70, 0x35, 0x93, 0xc1, 0x6b, 0x17, 0x46, 0x05, 0xc0, 0x39, 0x0d, 0x9d, 0xd2, + 0x5e, 0x55, 0x1d, 0x92, 0x55, 0xf3, 0x83, 0xd9, 0xbc, 0x69, 0x98, 0x18, 0x11, 0x44, 0x17, 0xe1, 0x04, 0xd3, 0x2b, + 0xd2, 0xd7, 0x4a, 0x4e, 0x47, 0xab, 0x8e, 0xd6, 0x12, 0x13, 0x73, 0x45, 0xf1, 0xd7, 0x80, 0xc7, 0x0d, 0x5e, 0x9d, + 0xa4, 0xe9, 0x44, 0xf5, 0xe8, 0xf1, 0xeb, 0x34, 0x9d, 0x94, 0xb8, 0x2b, 0xfc, 0x06, 0x5c, 0x34, 0xdb, 0x7c, 0xe8, + 0xc7, 0x2f, 0x28, 0xe2, 0xa2, 0x06, 0x57, 0xde, 0xa9, 0xbe, 0x52, 0x7d, 0x04, 0xb5, 0xf0, 0xc4, 0xc8, 0x5a, 0x78, + 0x72, 0xc9, 0x5a, 0x0b, 0x82, 0x99, 0xcd, 0x81, 0x0b, 0xf9, 0x95, 0x52, 0xc4, 0x9b, 0x48, 0xa8, 0xc5, 0xa0, 0xf5, + 0x98, 0x39, 0xab, 0x46, 0x0b, 0x95, 0x19, 0xa1, 0x7d, 0x5b, 0x8b, 0xce, 0x6f, 0xe4, 0xa7, 0x3c, 0xb5, 0x2f, 0xdb, + 0xe3, 0x7c, 0xbc, 0x47, 0x77, 0xd5, 0x59, 0x66, 0x52, 0xc6, 0x27, 0xb3, 0x04, 0x85, 0xbb, 0x04, 0x1b, 0x90, 0x64, + 0xbf, 0xd5, 0x01, 0x32, 0x6a, 0xaf, 0xfd, 0xae, 0xb3, 0x7c, 0x75, 0xb3, 0x35, 0x14, 0x95, 0x5a, 0x49, 0x8a, 0x83, + 0x0c, 0xd7, 0x6d, 0xe5, 0xc3, 0xc5, 0x05, 0xf4, 0x8c, 0x91, 0xc8, 0x3c, 0x7f, 0x22, 0x5f, 0x82, 0x73, 0xc6, 0x59, + 0x21, 0x30, 0x61, 0xac, 0xde, 0xb5, 0x96, 0x4a, 0x43, 0x8a, 0xb1, 0xa3, 0x51, 0x96, 0x55, 0x96, 0x2e, 0xb3, 0xb5, + 0x84, 0x2d, 0xab, 0xc8, 0x2d, 0x6c, 0x99, 0xc9, 0x6a, 0x7e, 0xa8, 0xb8, 0x83, 0xf2, 0xcd, 0xd6, 0x19, 0xdf, 0x4b, + 0x64, 0xef, 0x36, 0x50, 0xc2, 0xf5, 0xe8, 0x3f, 0x90, 0x7e, 0x9b, 0x61, 0x9c, 0x72, 0x5b, 0x49, 0x0b, 0x70, 0xfa, + 0x87, 0xc3, 0x87, 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, 0x43, 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, 0x0b, 0x28, 0x2c, 0x1a, 0xdf, 0x08, 0xd0, 0xd6, 0x50, 0x4d, 0x7b, 0xa5, 0xa8, 0x7a, 0x41, 0xaf, + 0x14, 0x5f, 0x7a, 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, 0x63, 0x30, 0x7d, 0x7d, 0xbb, 0x2d, 0xf2, 0x53, 0x13, 0x13, 0xd6, 0x63, 0x45, 0xdf, 0xbc, 0x0f, 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, 0xc9, 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, 0x3e, 0x90, 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, + 0xab, 0xc8, 0x97, 0xdf, 0xda, 0x39, 0x20, 0x68, 0x04, 0x02, 0x17, 0x0d, 0xb4, 0x6a, 0x97, 0x72, 0xde, 0x05, 0x84, + 0xf8, 0x2e, 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, 0xb1, 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, 0x49, 0x49, 0xfa, 0x4e, 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, 0xe2, 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, 0x7f, 0xfc, 0xcb, 0x8b, 0xcf, 0x6f, + 0x7f, 0xf9, 0x71, 0xf1, 0xf6, 0xfd, 0x9b, 0xb7, 0xef, 0xdf, 0x7e, 0xfe, 0x8d, 0x20, 0x3c, 0xa6, 0x42, 0x65, 0xf8, + 0xf8, 0xe1, 0xe6, 0xad, 0x93, 0xc1, 0xf6, 0x66, 0xc8, 0xda, 0x37, 0x72, 0x30, 0x04, 0x22, 0x1b, 0x84, 0x0c, 0xb2, + 0x53, 0x32, 0xc7, 0x4c, 0xcc, 0x31, 0xf6, 0x4e, 0x60, 0xb2, 0x05, 0x9c, 0x63, 0x99, 0x97, 0x8c, 0xc8, 0x55, 0xa1, + 0xf5, 0x03, 0x5a, 0xf0, 0x0e, 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, 0xb1, 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, 0x6a, 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, 0x2b, 0x1d, 0x6c, 0x39, 0x4d, 0x83, 0x23, 0xf1, 0x2b, 0xf5, 0xd9, 0x87, 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, 0x0f, + 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, 0x7d, 0x94, 0x4e, 0x12, 0xeb, 0x87, 0xae, 0x52, 0xc1, 0x66, 0x73, 0x83, 0xfa, 0xb2, 0xa3, 0xe4, 0x57, + 0xe0, 0xa4, 0xe3, 0x24, 0x8b, 0x1c, 0x44, 0x2d, 0x2a, 0xe7, 0x26, 0x09, 0x4b, 0xbb, 0x3a, 0xd5, 0x66, 0xbd, 0x2e, + 0xca, 0xba, 0x7a, 0x2d, 0x22, 0x45, 0xef, 0xa3, 0x1e, 0x3d, 0x91, 0x90, 0x0a, 0xad, 0x4a, 0xed, 0xf2, 0x08, 0xdc, + 0x36, 0xb5, 0x62, 0x5b, 0x2e, 0x61, 0x89, 0x1a, 0xff, 0x19, 0xfa, 0x28, 0x17, 0x0f, 0x32, 0x40, 0xa3, 0xe3, 0xa9, + 0x79, 0xeb, 0x91, 0x57, 0x8e, 0xf2, 0x4b, 0xab, 0x4d, 0xfa, 0x15, 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, 0x8f, 0x48, 0x28, 0xf3, 0x23, 0xf6, 0x76, 0xec, 0xf5, 0x20, 0x0b, 0x71, + 0x6c, 0x39, 0xd8, 0x6c, 0xbd, 0xcf, 0x65, 0x2a, 0xe2, 0xb3, 0xba, 0x38, 0xdb, 0x54, 0xe2, 0xac, 0x4e, 0xc4, 0xd9, + 0x0f, 0x90, 0xf3, 0x87, 0x33, 0x2a, 0xfa, 0xec, 0x21, 0xad, 0x93, 0x62, 0x53, 0xd3, 0x93, 0x37, 0x58, 0xc6, 0x0f, + 0x67, 0xc4, 0x55, 0x73, 0x46, 0x23, 0x19, 0x8f, 0xce, 0x3e, 0x66, 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, 0xdb, 0xd7, 0xfc, 0x85, 0x97, 0xab, 0xbf, 0xd9, 0x3f, 0x00, + 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, 0x37, 0x45, 0xf9, 0x36, 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, 0xfd, + 0x50, 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, 0x37, 0xf7, 0x15, 0xdc, 0xc6, 0xfb, 0xfd, 0x65, 0xe5, 0x99, 0x9f, 0xb8, 0x00, 0xec, 0x4d, 0x85, 0xd6, 0x09, + 0x94, 0x1a, 0xd6, 0xe1, 0xab, 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, 0xe3, 0x16, 0xe3, 0x5b, + 0x01, 0xd1, 0x48, 0x00, 0xf4, 0x13, 0xc0, 0xbc, 0xc8, 0x66, 0x76, 0x1f, 0x07, 0x54, 0x29, 0xd1, 0x34, 0xce, 0xe6, + 0xf9, 0x3d, 0xbd, 0x29, 0x3b, 0xe8, 0xd4, 0xa9, 0x02, 0x17, 0x5c, 0x95, 0x8c, 0x57, 0xd6, 0x13, 0xf9, 0xfc, 0xe6, + 0x76, 0x93, 0x66, 0xf1, 0x87, 0xf2, 0x1f, 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, 0xd7, 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, 0x89, 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, 0xe4, 0xc1, 0x16, 0xe7, + 0x4f, 0x37, 0xd4, 0x7e, 0xcc, 0x8d, 0x7a, 0x18, 0x68, 0x2d, 0x78, 0x53, 0x10, 0xeb, 0xef, 0xc7, 0x8e, 0x6c, 0x1f, + 0xb4, 0xc8, 0x68, 0xf2, 0xd9, 0xcf, 0x3f, 0x96, 0xe9, 0x2a, 0x85, 0xfb, 0x92, 0x93, 0x45, 0x33, 0x0f, 0x81, 0xbd, + 0x21, 0x86, 0xeb, 0xa3, 0xc2, 0x23, 0xca, 0xfa, 0x7d, 0xf8, 0x7d, 0x95, 0x81, 0x29, 0x06, 0xae, 0x2b, 0x04, 0xe3, + 0x21, 0x10, 0xc4, 0xc3, 0x34, 0x3a, 0x19, 0xd4, 0xa0, 0x0d, 0xdf, 0x00, 0x64, 0x06, 0x78, 0x64, 0x2e, 0x3d, 0x02, + 0xee, 0x02, 0xd7, 0x9e, 0x8c, 0xc7, 0xfe, 0xc4, 0x34, 0x34, 0x6a, 0x4a, 0x33, 0x3d, 0x37, 0x7e, 0xd3, 0x51, 0x2d, + 0xd7, 0xce, 0x7f, 0x7c, 0xc9, 0x6f, 0xd0, 0x0b, 0x5a, 0x5e, 0xee, 0x23, 0x75, 0xb9, 0xcf, 0x28, 0x2e, 0x13, 0xc9, + 0x61, 0x41, 0x2c, 0x4b, 0x38, 0xf0, 0x18, 0x95, 0x2c, 0xb6, 0xf4, 0x58, 0x15, 0x2d, 0x5f, 0x94, 0x1b, 0xa4, 0x43, + 0x27, 0x04, 0x4b, 0x54, 0x10, 0x2c, 0x81, 0x71, 0x11, 0x6b, 0xbe, 0x19, 0xe4, 0x2c, 0x9e, 0x6d, 0xe6, 0x1c, 0x09, + 0xeb, 0x92, 0xc3, 0xa1, 0x90, 0x60, 0x33, 0xd9, 0x6c, 0x3d, 0x67, 0x6b, 0x9f, 0x81, 0x12, 0xa0, 0x94, 0x69, 0x82, + 0xd2, 0xb4, 0x62, 0x2b, 0x6e, 0x5a, 0x83, 0xd5, 0x6a, 0xca, 0x56, 0x35, 0x65, 0xe7, 0x34, 0xe5, 0xa8, 0x82, 0x92, + 0x13, 0x4a, 0x51, 0x86, 0x01, 0x8c, 0xd8, 0x24, 0xba, 0xca, 0xd0, 0xc7, 0x3b, 0xe1, 0x11, 0x54, 0x11, 0x91, 0x4f, + 0x18, 0x42, 0x60, 0x22, 0x8a, 0x0b, 0x55, 0x28, 0x06, 0xc8, 0x88, 0x04, 0x82, 0x89, 0x4a, 0x9d, 0x02, 0xf3, 0xd1, + 0x54, 0x31, 0x6c, 0xda, 0x13, 0xe5, 0x7b, 0xea, 0xb8, 0x47, 0xd9, 0xe6, 0x6f, 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, 0x8f, 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, + 0x0a, 0xf3, 0x3b, 0xf1, 0xa6, 0x2c, 0x56, 0xaa, 0x2b, 0xda, 0x3e, 0x33, 0xf9, 0x8c, 0x74, 0x12, 0x2a, 0xa0, 0xa0, + 0x90, 0x6b, 0x7d, 0xfa, 0x3e, 0x7c, 0x1f, 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, 0x0e, 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, 0x87, 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, 0xbe, 0x78, 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, 0x8e, 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, + 0xbe, 0x78, 0x25, 0x9a, 0xf7, 0xd1, 0x8c, 0x53, 0x1a, 0x0d, 0x38, 0x4e, 0xa3, 0x70, 0xfb, 0xe1, 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, 0x6f, 0x8a, 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, 0x76, 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, 0x95, 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, 0x27, 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, + 0x9e, 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, 0xc7, 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, 0x55, 0x78, 0x6f, 0x2b, 0xef, 0x8e, 0x9c, 0x32, 0xef, 0xf4, 0x30, 0xba, 0x2e, 0x49, 0xdf, 0x25, 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, 0x77, 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, 0x4b, 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, 0xcd, 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, 0xdc, 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, 0x1b, 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, 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, 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, 0x4b, 0x35, 0x39, 0x42, 0x44, 0xbb, 0x08, 0x07, 0x00, 0x71, 0xa7, 0xa9, 0xac, 0x43, 0x0d, 0xd0, + 0x07, 0x04, 0xd6, 0xa1, 0x6f, 0x33, 0x80, 0x83, 0x3e, 0xda, 0x3c, 0x8b, 0x40, 0x5e, 0xf7, 0xee, 0xd9, 0x3b, 0xb6, + 0xf3, 0xf9, 0xf5, 0x2a, 0xf5, 0xee, 0xd1, 0x21, 0xf8, 0x7c, 0xec, 0x4f, 0x2f, 0x03, 0x83, 0x0b, 0xcd, 0xde, 0x3d, + 0x13, 0x6c, 0xc7, 0x76, 0xcf, 0x10, 0xa9, 0xa8, 0x3b, 0xff, 0xf0, 0xd2, 0x44, 0xcf, 0x3b, 0x2f, 0xdc, 0xf1, 0x25, + 0x80, 0x07, 0xb2, 0x18, 0x50, 0x7c, 0x96, 0xde, 0x3f, 0x59, 0x02, 0x6a, 0xf2, 0x5b, 0xbe, 0xf6, 0xbe, 0x52, 0xea, + 0x02, 0xfe, 0x1c, 0x50, 0xfa, 0x24, 0xe7, 0xde, 0xdd, 0xf0, 0xd6, 0xbf, 0x78, 0x0e, 0xce, 0x13, 0xab, 0xe1, 0x02, + 0xfe, 0x2a, 0xf8, 0xd0, 0xbb, 0x1b, 0x60, 0x62, 0xc9, 0x87, 0xde, 0x6a, 0x00, 0xa9, 0x0a, 0x17, 0x12, 0x63, 0x1f, + 0x7e, 0x0d, 0x72, 0x86, 0x7f, 0xfc, 0xa6, 0x31, 0x58, 0x7f, 0x0d, 0x0a, 0x8d, 0xc6, 0x5a, 0xaa, 0x90, 0xa5, 0x58, + 0x9c, 0x09, 0xb0, 0x09, 0xc7, 0xdd, 0xbe, 0x58, 0xd5, 0x66, 0x2d, 0xe8, 0xcf, 0x47, 0x7c, 0x8f, 0xc6, 0xea, 0xaa, + 0x9c, 0x8b, 0xf2, 0x13, 0xd2, 0xa7, 0x3a, 0x3e, 0x46, 0xc5, 0xa6, 0xee, 0x4e, 0xa7, 0x5a, 0x75, 0xa4, 0xfd, 0xa6, + 0x5c, 0x83, 0x1d, 0xaf, 0x93, 0x23, 0x4b, 0xe1, 0x59, 0x87, 0x9d, 0x97, 0x4e, 0x89, 0x0e, 0xc3, 0x78, 0xb7, 0x55, + 0xcf, 0x18, 0xca, 0x73, 0x83, 0x31, 0x5d, 0xf0, 0x88, 0x5f, 0x0f, 0x72, 0x19, 0x1a, 0xf3, 0x11, 0xd9, 0x30, 0x94, + 0x0f, 0x2d, 0x32, 0x24, 0x44, 0xbc, 0x87, 0x4a, 0xc0, 0xb6, 0x05, 0x65, 0x52, 0xc0, 0x59, 0x34, 0xf8, 0xad, 0xf6, + 0x72, 0xe0, 0x3d, 0x88, 0xfc, 0x46, 0xba, 0x94, 0x4b, 0x6c, 0x74, 0xe2, 0x58, 0x16, 0xda, 0x79, 0x5c, 0x7f, 0x1d, + 0x83, 0xfa, 0xbd, 0xd2, 0x6f, 0x50, 0xce, 0xfe, 0x24, 0x59, 0xa7, 0x8d, 0x27, 0xc6, 0xbf, 0x5c, 0xe5, 0x9f, 0xa2, + 0xa5, 0x1e, 0xfe, 0x3f, 0x63, 0x0a, 0xa5, 0x7f, 0x95, 0x96, 0xd1, 0x66, 0xb5, 0x14, 0xa5, 0xc8, 0x23, 0x71, 0xf2, + 0xb5, 0xc8, 0xce, 0xe5, 0x3b, 0x9f, 0x42, 0xbf, 0x00, 0xb4, 0xec, 0x13, 0x64, 0xf4, 0x4b, 0x26, 0xf8, 0xf0, 0xa5, + 0x76, 0xae, 0xcd, 0xf9, 0x78, 0x92, 0x5f, 0x59, 0x7b, 0xb7, 0xe3, 0x45, 0x62, 0x14, 0x63, 0xb9, 0xaf, 0xba, 0x59, + 0x39, 0x51, 0xc9, 0x81, 0x91, 0xae, 0xc9, 0x5e, 0xae, 0x64, 0xdd, 0x4e, 0xb7, 0x12, 0x88, 0xa8, 0x02, 0xef, 0x31, + 0xae, 0x62, 0x1f, 0xc1, 0x74, 0xdd, 0x71, 0x19, 0xed, 0x78, 0xcf, 0x78, 0x75, 0xa2, 0xac, 0xe0, 0x76, 0x23, 0xda, + 0x13, 0x3a, 0xfa, 0x69, 0x52, 0x5b, 0x16, 0x0e, 0x40, 0xee, 0x12, 0xc6, 0xb2, 0x21, 0x58, 0x31, 0x28, 0x7d, 0xbd, + 0xa6, 0x64, 0x59, 0x80, 0x45, 0x67, 0x97, 0x11, 0x88, 0x61, 0xdd, 0x34, 0x27, 0x74, 0xbc, 0x74, 0x71, 0xde, 0x6b, + 0x15, 0x29, 0x78, 0x46, 0x8b, 0x8e, 0xb9, 0xe9, 0x48, 0x37, 0x46, 0x7b, 0xfb, 0xd2, 0x20, 0xa4, 0x78, 0xfe, 0xc0, + 0x56, 0xeb, 0xe2, 0x22, 0xf1, 0x0a, 0x99, 0x68, 0x41, 0x2c, 0x45, 0x60, 0xc6, 0x0b, 0x4d, 0x23, 0x4c, 0x50, 0xa6, + 0x04, 0x8b, 0xd6, 0xe8, 0xd0, 0xfe, 0xb0, 0x84, 0xdd, 0x63, 0x8c, 0x00, 0x81, 0x2a, 0xd3, 0x97, 0xb0, 0x35, 0x61, + 0x36, 0x75, 0xb1, 0x01, 0xda, 0x2a, 0x86, 0x06, 0x61, 0x6d, 0x88, 0xf9, 0x94, 0xe6, 0x77, 0xff, 0xc4, 0x62, 0x6c, + 0x4f, 0x20, 0xb6, 0x77, 0xbb, 0x26, 0x61, 0xba, 0xd7, 0xe2, 0xc6, 0x7a, 0xb9, 0x3d, 0xe5, 0x98, 0xda, 0xb1, 0x36, + 0x6a, 0xc7, 0x5a, 0xea, 0x1d, 0x6b, 0xad, 0x77, 0xac, 0xbb, 0x86, 0x7f, 0xcc, 0xbc, 0x98, 0x25, 0xa0, 0xdf, 0x5d, + 0x71, 0xd5, 0x20, 0x68, 0xc6, 0x86, 0xdd, 0xc2, 0x6f, 0x89, 0xb5, 0x5b, 0xfa, 0x17, 0x4b, 0xb6, 0x30, 0x7d, 0xa0, + 0x5b, 0x07, 0x58, 0x46, 0xd4, 0xe4, 0x7b, 0xe4, 0xdd, 0x74, 0x56, 0x14, 0x6e, 0x4f, 0x6c, 0xe1, 0xb3, 0x77, 0xe6, + 0xcd, 0xfb, 0x67, 0x11, 0xe4, 0xde, 0x71, 0xef, 0x7e, 0xf8, 0xce, 0xbf, 0xd0, 0x2d, 0x90, 0x93, 0x59, 0xce, 0x40, + 0xea, 0x88, 0xcf, 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, 0x5e, + 0x9e, 0x16, 0xca, 0xb5, 0x9b, 0xb7, 0xf1, 0x9b, 0x56, 0x4b, 0x96, 0xd6, 0x7a, 0xc8, 0x4b, 0xcb, 0x22, 0x02, 0x01, + 0x0c, 0x47, 0xca, 0x2e, 0x96, 0x70, 0x8f, 0xb0, 0xba, 0x07, 0xa1, 0x64, 0x5e, 0xb8, 0x78, 0xce, 0x62, 0x48, 0x04, + 0xd8, 0xee, 0x50, 0xb1, 0x2d, 0x5c, 0x3c, 0x67, 0x1b, 0x5e, 0xf4, 0xfb, 0x99, 0xea, 0x14, 0xb2, 0xee, 0x2c, 0xf9, + 0x46, 0x35, 0xc7, 0x1a, 0x6a, 0xb6, 0x36, 0xc9, 0xd6, 0x38, 0xb7, 0x15, 0x1f, 0x77, 0x6d, 0xc5, 0xc7, 0xca, 0x5a, + 0x97, 0xee, 0xf5, 0x1e, 0xd5, 0x05, 0xb0, 0xf5, 0xdf, 0x1e, 0xaf, 0x5c, 0xcf, 0x67, 0x04, 0xf0, 0xb5, 0xe0, 0xe3, + 0xc9, 0x02, 0xbd, 0x4a, 0x16, 0xfe, 0xed, 0x40, 0x8d, 0xbf, 0xd3, 0xb9, 0x0b, 0x80, 0xae, 0xa4, 0xbc, 0x02, 0xf2, + 0x0e, 0x72, 0xcc, 0x2d, 0xbb, 0xf2, 0xfe, 0xe4, 0x3b, 0xec, 0x1d, 0xaf, 0x67, 0x8b, 0x39, 0xdb, 0x81, 0x53, 0x41, + 0x32, 0xb0, 0x97, 0x15, 0xdb, 0x05, 0xb1, 0x9d, 0xf0, 0x1b, 0x01, 0x53, 0xbe, 0x80, 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, 0xef, 0xa4, 0xd6, 0xc5, + 0x18, 0x7a, 0x80, 0xf8, 0xe9, 0x76, 0xc0, 0xef, 0x3b, 0xd6, 0x96, 0xf7, 0x8e, 0x2d, 0xd8, 0x0e, 0x2e, 0x41, 0x4d, + 0x7b, 0xd9, 0x9f, 0x54, 0x2e, 0x68, 0xc7, 0x2e, 0x89, 0x87, 0x33, 0x66, 0x95, 0x32, 0xb3, 0x4e, 0xaa, 0x2b, 0xd1, + 0x19, 0xd3, 0x59, 0xeb, 0xf9, 0x5c, 0xcd, 0x27, 0x85, 0x06, 0xf5, 0x3b, 0x27, 0x3e, 0xa2, 0xa2, 0xf3, 0x04, 0xb6, + 0x96, 0x15, 0xc4, 0x6a, 0x9f, 0x83, 0xb5, 0x56, 0xbb, 0xf4, 0x7b, 0xf9, 0x80, 0xdb, 0x94, 0xc3, 0x3a, 0x30, 0xa8, + 0x39, 0xb1, 0xa2, 0x1e, 0xb3, 0x1d, 0xe3, 0xe6, 0xa7, 0x97, 0x3f, 0x38, 0x61, 0xc9, 0x8a, 0xd5, 0xfe, 0xf4, 0xe5, + 0x33, 0x4f, 0x7f, 0xa7, 0xf6, 0x2f, 0x84, 0x1f, 0x8c, 0xff, 0x5d, 0xbb, 0xaf, 0xb5, 0x18, 0x95, 0xad, 0x72, 0x84, + 0xc6, 0xdd, 0x4a, 0x9a, 0x2c, 0x3f, 0x0b, 0x4f, 0x58, 0x0b, 0x9e, 0xe5, 0x7a, 0x89, 0x66, 0x05, 0xac, 0xb0, 0x96, + 0x49, 0xb8, 0xc2, 0x58, 0x2d, 0x6d, 0xf5, 0x2d, 0x9a, 0xe6, 0xf8, 0x70, 0xae, 0x0d, 0xca, 0x94, 0xb3, 0x33, 0x62, + 0x35, 0x5c, 0x86, 0xa5, 0x09, 0x45, 0xc8, 0xee, 0xed, 0xe0, 0xc6, 0x4e, 0x59, 0x4a, 0x19, 0xce, 0x31, 0x98, 0xf0, + 0x48, 0x8c, 0xaa, 0x7c, 0x7f, 0x5f, 0x52, 0xe4, 0xb4, 0x2d, 0x07, 0x55, 0x08, 0xfb, 0x48, 0xa2, 0x04, 0x6e, 0x45, + 0x5a, 0x28, 0x52, 0x16, 0x7f, 0x3b, 0x40, 0x17, 0x78, 0x01, 0x75, 0x35, 0xea, 0xf6, 0x87, 0x23, 0x1e, 0x3e, 0x32, + 0xf5, 0x81, 0x11, 0x4b, 0x02, 0xb5, 0xbd, 0xc8, 0xd2, 0x3b, 0x50, 0xe1, 0xf7, 0x70, 0x35, 0x11, 0xfb, 0xb9, 0x25, + 0x45, 0x45, 0x36, 0xd2, 0x1b, 0x5a, 0x83, 0x47, 0x68, 0x4d, 0x79, 0xe9, 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, 0x1f, 0x54, 0x82, 0x05, 0x4b, 0xda, 0x7d, 0xfc, 0x76, 0xd6, 0x0e, 0x44, 0x65, + 0xac, 0xd2, 0xb7, 0x24, 0x61, 0x4f, 0x0c, 0x3a, 0x85, 0xaa, 0xdc, 0xee, 0x8e, 0xb6, 0xc0, 0x75, 0xcc, 0x52, 0xf4, + 0xc2, 0x16, 0xb9, 0x5b, 0xfe, 0xdd, 0x73, 0x45, 0xce, 0x7e, 0x09, 0x08, 0x4e, 0xcd, 0x37, 0xc4, 0x97, 0x23, 0x3c, + 0xaa, 0x6e, 0x81, 0xe3, 0xf4, 0x1d, 0xc0, 0x3f, 0x1c, 0x2e, 0x41, 0x13, 0x10, 0x0b, 0xd6, 0x4b, 0xe3, 0x1e, 0xeb, + 0xc5, 0xc5, 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, 0x63, 0xfc, 0xb4, 0x67, 0x64, 0xe4, 0x71, 0xeb, + 0xb0, 0xfa, 0x5f, 0xff, 0x09, 0x01, 0x70, 0x78, 0x36, 0xf5, 0x2e, 0xc7, 0x90, 0x55, 0x96, 0x11, 0x48, 0x7e, 0x62, + 0xf0, 0xe5, 0x0b, 0x80, 0xaa, 0xcf, 0x74, 0xad, 0x26, 0x47, 0xed, 0x31, 0x87, 0xae, 0x18, 0x00, 0xb6, 0x61, 0x89, + 0xaa, 0x5a, 0xd8, 0x84, 0xc5, 0xed, 0x67, 0x18, 0xcd, 0x65, 0xd3, 0x0b, 0x1a, 0xa8, 0x47, 0x08, 0x7e, 0x69, 0x3d, + 0xb4, 0xd6, 0x32, 0xe5, 0xd0, 0xb5, 0x51, 0x54, 0xd9, 0x50, 0x97, 0xb0, 0x5a, 0x8b, 0xa8, 0x26, 0x8a, 0x94, 0x4b, + 0x46, 0x51, 0x2c, 0x55, 0xb0, 0xcf, 0xc4, 0x1d, 0x44, 0xcd, 0xd3, 0x56, 0x5b, 0x05, 0xfb, 0x3b, 0x40, 0x58, 0x0b, + 0x6b, 0x21, 0x9d, 0x41, 0xed, 0x9d, 0x7e, 0xa4, 0xfc, 0xe5, 0x85, 0xdc, 0xce, 0x2d, 0x14, 0xe1, 0xf6, 0x1c, 0x94, + 0x37, 0x75, 0x55, 0x2a, 0xa2, 0xd1, 0x12, 0x28, 0x65, 0x4e, 0x10, 0x59, 0x80, 0x00, 0x8e, 0x1b, 0x08, 0x7c, 0x5e, + 0xe3, 0x13, 0x68, 0x14, 0x02, 0xf9, 0x81, 0x55, 0xb8, 0xf6, 0x90, 0x96, 0x5a, 0x23, 0xa2, 0x44, 0xfc, 0xe8, 0xea, + 0x39, 0xb6, 0xaf, 0x9e, 0xc6, 0xda, 0x52, 0x9a, 0x20, 0x7e, 0x62, 0xb1, 0x85, 0x98, 0x20, 0xaa, 0x43, 0x74, 0x04, + 0xcb, 0x09, 0x21, 0x0a, 0x7f, 0x08, 0xfd, 0xd4, 0xc0, 0x5f, 0xb2, 0x65, 0x91, 0xd7, 0x04, 0x8b, 0x59, 0x31, 0x40, + 0xab, 0x22, 0xf0, 0x4c, 0x67, 0x4b, 0x65, 0x4e, 0xf3, 0xe8, 0xc8, 0x0e, 0xce, 0xbb, 0x0e, 0xf6, 0xd2, 0x97, 0xb1, + 0x93, 0x65, 0xd3, 0xa8, 0x8d, 0x0d, 0x91, 0xf0, 0x8a, 0xfc, 0x55, 0x96, 0x1a, 0xe7, 0xc8, 0x5c, 0xae, 0xef, 0xba, + 0xb8, 0xbb, 0xa3, 0x6d, 0xc2, 0x2a, 0x44, 0xa8, 0xdb, 0x86, 0xca, 0xa5, 0x30, 0x1b, 0x9b, 0xa6, 0x01, 0xbe, 0x50, + 0x54, 0x2a, 0x55, 0xa9, 0xad, 0x54, 0x72, 0xc2, 0xbb, 0xbe, 0xa9, 0x45, 0xea, 0x8a, 0x60, 0x1b, 0x33, 0xd4, 0x43, + 0xb9, 0x51, 0x63, 0xdf, 0x76, 0xac, 0xd2, 0x3b, 0x4c, 0x90, 0x33, 0xf2, 0x22, 0x07, 0x17, 0x25, 0x05, 0x99, 0xab, + 0x21, 0xcc, 0x1f, 0x35, 0x7c, 0x5a, 0x58, 0xee, 0xa1, 0x04, 0xcc, 0x8e, 0x1a, 0x5e, 0x46, 0x08, 0x44, 0x5c, 0x2a, + 0xfb, 0x8a, 0x89, 0xdf, 0x53, 0x30, 0x4b, 0x26, 0x74, 0x2f, 0x62, 0x61, 0x84, 0x36, 0x3e, 0x49, 0x92, 0xa9, 0xa7, + 0x29, 0xb8, 0x91, 0xcb, 0x30, 0x47, 0x23, 0xb4, 0xe4, 0x23, 0x07, 0xd2, 0xd7, 0x72, 0x2a, 0xc1, 0x47, 0xd4, 0x29, + 0xe0, 0x78, 0x7e, 0x5e, 0x58, 0x3f, 0x59, 0x2e, 0x31, 0x97, 0xb5, 0xf9, 0x2f, 0x3b, 0x3a, 0x06, 0xbb, 0x3c, 0x4d, + 0x1c, 0x57, 0xff, 0x51, 0x95, 0x14, 0x0f, 0x3f, 0xa7, 0x39, 0xa0, 0x08, 0x66, 0xf6, 0x14, 0xe3, 0x63, 0x9f, 0x65, + 0x0a, 0xf8, 0xdb, 0xf5, 0xd6, 0x92, 0x89, 0x5d, 0xd2, 0x6e, 0xae, 0x8c, 0x5f, 0x6a, 0xc3, 0x8e, 0x83, 0x73, 0x03, + 0x50, 0x9c, 0x35, 0x3a, 0x2c, 0xaf, 0x75, 0xdb, 0xaa, 0x50, 0x81, 0x5a, 0xff, 0x7b, 0xb7, 0x30, 0xe5, 0x6d, 0x5e, + 0x2a, 0x6f, 0xf3, 0xd0, 0x04, 0x08, 0x44, 0x66, 0xc8, 0xb3, 0xa6, 0x63, 0x92, 0xb8, 0x77, 0xa4, 0xa4, 0x7d, 0x47, + 0x8a, 0x1f, 0xbd, 0x23, 0x21, 0xdf, 0x12, 0x3a, 0xb2, 0x2f, 0x39, 0x39, 0x81, 0x32, 0x83, 0xbd, 0xbc, 0x66, 0xb2, + 0x7f, 0x40, 0x7b, 0xe1, 0x5c, 0x96, 0x57, 0xfc, 0x9d, 0xf0, 0xd6, 0xfe, 0x74, 0x7d, 0xda, 0x55, 0xf5, 0xf6, 0x1b, + 0x33, 0xf3, 0x70, 0x28, 0x0e, 0x87, 0xca, 0x04, 0xed, 0x2e, 0xb8, 0x18, 0xe4, 0xec, 0xde, 0x8d, 0x8f, 0x7f, 0xc7, + 0x51, 0xc4, 0x56, 0xca, 0x23, 0xe9, 0x42, 0x25, 0x86, 0x97, 0x06, 0x1e, 0x66, 0xc7, 0xc7, 0x93, 0xdd, 0xd5, 0xfd, + 0x64, 0x30, 0xd8, 0xa9, 0xbe, 0xdd, 0xf2, 0x7a, 0xb6, 0x9b, 0xb3, 0x07, 0x7e, 0x3b, 0xdd, 0x06, 0xfb, 0x06, 0xb6, + 0xdd, 0xdd, 0x95, 0x38, 0x1c, 0x76, 0xd7, 0x7c, 0xe1, 0xef, 0x1f, 0x10, 0xd0, 0x99, 0x9f, 0x8f, 0xdb, 0x18, 0x3f, + 0x37, 0x6d, 0x57, 0xad, 0x1d, 0xc0, 0xd3, 0xff, 0xe8, 0xdd, 0xcc, 0x96, 0x73, 0x9f, 0x3d, 0xe1, 0x0f, 0xe0, 0x9f, + 0x8f, 0x9b, 0x24, 0x52, 0x9f, 0x68, 0x97, 0xc9, 0x1b, 0x70, 0x20, 0xdf, 0xf9, 0xec, 0x2d, 0x7f, 0x98, 0x2d, 0xe7, + 0xbc, 0x38, 0x1c, 0x3e, 0x4c, 0x43, 0x24, 0x6b, 0x0a, 0x2b, 0x62, 0x49, 0xf1, 0xfc, 0x20, 0x3c, 0x7e, 0x2f, 0x22, + 0x43, 0xa4, 0xe5, 0xde, 0x1d, 0xb2, 0x1b, 0x16, 0xf9, 0x01, 0x7c, 0x90, 0xed, 0xfc, 0x89, 0xac, 0x29, 0xdd, 0x2f, + 0x9e, 0xf8, 0x87, 0x03, 0xfd, 0xf5, 0xd6, 0x3f, 0x1c, 0x3e, 0xb0, 0x07, 0x04, 0x47, 0xe7, 0x3b, 0xe8, 0x1f, 0x7d, + 0xeb, 0x80, 0xaa, 0x0c, 0xdf, 0xcd, 0x36, 0x73, 0xff, 0x7a, 0xc5, 0xee, 0x80, 0x0b, 0x45, 0x79, 0xa1, 0xdd, 0xb0, + 0x07, 0xf4, 0x3a, 0x23, 0x27, 0xa2, 0xd9, 0x6e, 0xee, 0xb3, 0x18, 0x9f, 0xab, 0xfb, 0x62, 0xf2, 0xcd, 0xfb, 0xe2, + 0x8e, 0x6d, 0xbb, 0xef, 0x8b, 0xf2, 0x4d, 0x77, 0xfd, 0x6c, 0xd9, 0x8e, 0x3d, 0xc0, 0x0c, 0x7b, 0xc7, 0x6f, 0x9a, + 0x63, 0xc7, 0xd8, 0x6f, 0xde, 0x18, 0x01, 0x94, 0xd9, 0x82, 0xc5, 0x82, 0x83, 0x52, 0xad, 0xda, 0x96, 0x44, 0x5e, + 0xe9, 0x40, 0xb5, 0x19, 0xc1, 0x7d, 0xb5, 0x90, 0x33, 0xcf, 0x0c, 0xf4, 0x6d, 0x85, 0x68, 0xe1, 0xb0, 0x01, 0x7f, + 0xa3, 0xad, 0x63, 0x0c, 0xd3, 0xac, 0x66, 0xda, 0x16, 0x75, 0xf9, 0x7d, 0xef, 0x99, 0xfc, 0x46, 0x06, 0xb6, 0x10, + 0x49, 0xe1, 0x38, 0xbe, 0x78, 0x7e, 0xc2, 0x7f, 0xd5, 0xf2, 0xa8, 0xd5, 0x7e, 0xa1, 0xd4, 0xa7, 0xaf, 0xe8, 0x88, + 0x26, 0xee, 0x45, 0x5b, 0x86, 0x35, 0xca, 0x9a, 0x5a, 0x3a, 0x0c, 0xe3, 0x1a, 0xf6, 0xe5, 0x81, 0x43, 0xdf, 0x01, + 0x81, 0xb6, 0x4a, 0xa5, 0x40, 0x0b, 0xc7, 0x30, 0x0a, 0xb3, 0x90, 0xf2, 0xb8, 0x30, 0x4b, 0x79, 0x8f, 0x05, 0x5a, + 0xdc, 0xaa, 0x7b, 0x4c, 0x6d, 0xb7, 0x20, 0xc2, 0xea, 0x2d, 0xe3, 0xfc, 0xb2, 0x51, 0x85, 0xdb, 0x02, 0x14, 0x45, + 0x50, 0x06, 0x7b, 0x92, 0xdb, 0x16, 0x4a, 0x9a, 0x8d, 0xc2, 0x5a, 0xdc, 0x15, 0xe5, 0xae, 0xd7, 0xb0, 0x05, 0x5e, + 0x50, 0xf5, 0x13, 0xc2, 0xb6, 0xec, 0x59, 0x87, 0x72, 0x91, 0xfe, 0x5b, 0x96, 0x9e, 0xef, 0xb7, 0xe6, 0xfc, 0x4f, + 0x5f, 0xd1, 0x47, 0xe5, 0xbf, 0x7f, 0x49, 0x3f, 0x19, 0x2c, 0x23, 0xa7, 0xd4, 0xcb, 0x68, 0x74, 0x9b, 0xe6, 0x84, + 0xb1, 0xe5, 0xeb, 0xa7, 0xdf, 0x21, 0x53, 0x90, 0x1c, 0x4a, 0xa9, 0xca, 0xc9, 0x1e, 0xfa, 0xc2, 0xeb, 0x3e, 0xcc, + 0x04, 0x03, 0x10, 0x5e, 0xa3, 0x4d, 0x35, 0x61, 0x12, 0x8f, 0xae, 0xe0, 0xff, 0x46, 0x10, 0x83, 0xf6, 0x89, 0xa2, + 0x8e, 0x6d, 0x23, 0x5d, 0xb7, 0x9d, 0x83, 0xe4, 0x4e, 0x5d, 0xf9, 0xa3, 0x72, 0xf2, 0xef, 0x68, 0x88, 0xbc, 0xe2, + 0x0a, 0xb1, 0xb2, 0xe0, 0x12, 0x8b, 0xa1, 0x22, 0x05, 0xb8, 0x86, 0x20, 0x52, 0x16, 0x25, 0x85, 0x5b, 0x0e, 0xaa, + 0x22, 0x00, 0xe3, 0x6a, 0x75, 0xd4, 0x89, 0xf0, 0x71, 0x6b, 0x2d, 0x42, 0xb0, 0xa2, 0x51, 0x2b, 0x6b, 0x05, 0xbe, + 0x20, 0x7d, 0xe9, 0x50, 0x10, 0xd3, 0xa3, 0x90, 0xaa, 0xd2, 0xa1, 0x40, 0x9a, 0x43, 0xc5, 0x37, 0x06, 0x1b, 0x45, + 0x45, 0x7a, 0xfe, 0xd2, 0xa4, 0xe4, 0xd2, 0x98, 0xf1, 0x51, 0x94, 0x91, 0xc8, 0xeb, 0xf0, 0x4e, 0x4c, 0x0b, 0xe4, + 0x1b, 0x3d, 0x7e, 0x10, 0x5c, 0xc2, 0xbb, 0x21, 0xf7, 0x0a, 0xb0, 0x25, 0x60, 0x07, 0xb8, 0x57, 0x66, 0x94, 0xeb, + 0xb4, 0xae, 0xdf, 0x5a, 0x0f, 0xc5, 0x30, 0x7c, 0x66, 0x09, 0x6c, 0x47, 0xeb, 0xe8, 0x48, 0x0f, 0x1f, 0xfe, 0xd7, + 0x55, 0xcd, 0x51, 0xa7, 0x72, 0x39, 0x3b, 0x9e, 0xb0, 0x14, 0x31, 0x83, 0xee, 0xaf, 0xdb, 0x57, 0x02, 0xe8, 0x76, + 0x59, 0xcc, 0xb3, 0xd1, 0x4e, 0xfe, 0x2d, 0xdd, 0x58, 0x51, 0xda, 0xc4, 0xbb, 0xac, 0x37, 0xf6, 0x87, 0xa3, 0xff, + 0x78, 0xf6, 0x75, 0x42, 0xa8, 0x3a, 0x1b, 0xb6, 0xd6, 0x71, 0x2e, 0xff, 0xeb, 0x3f, 0xc7, 0x64, 0x05, 0x41, 0x41, + 0x58, 0x76, 0x8a, 0x89, 0x0a, 0x46, 0x91, 0x62, 0xcd, 0xc7, 0x93, 0x35, 0xea, 0x84, 0xd7, 0xfe, 0x52, 0xeb, 0x84, + 0x89, 0x91, 0x95, 0xca, 0x5f, 0xb3, 0x8a, 0xdd, 0xa9, 0xcc, 0x02, 0x32, 0x0f, 0xf2, 0xc9, 0xda, 0x68, 0x30, 0x57, + 0xbc, 0x9e, 0xad, 0xe7, 0x52, 0xf9, 0x0c, 0xa6, 0x9c, 0xe5, 0xe0, 0x64, 0x29, 0xec, 0x9e, 0x04, 0x8a, 0xd6, 0x0c, + 0x5d, 0xfb, 0x53, 0x6c, 0xd5, 0xeb, 0xb4, 0xaa, 0x01, 0x1e, 0x10, 0x62, 0x60, 0xa8, 0xbd, 0x5a, 0x78, 0x68, 0x2d, + 0x80, 0xb5, 0x3f, 0x2a, 0xfd, 0x60, 0x3c, 0x59, 0xf2, 0x05, 0xf2, 0x2f, 0x47, 0x8e, 0xda, 0xbd, 0xdf, 0xf7, 0xee, + 0x41, 0x0a, 0x8e, 0x5c, 0x0b, 0x05, 0x12, 0x01, 0x2d, 0xf8, 0xc6, 0x57, 0x3e, 0x18, 0xef, 0x50, 0x5b, 0x0d, 0x0a, + 0x6a, 0x47, 0xb7, 0x3c, 0x76, 0xf4, 0xce, 0xf7, 0x27, 0xf4, 0xd5, 0x0b, 0x2d, 0x1c, 0x7f, 0xe3, 0x8c, 0x5c, 0xb3, + 0x55, 0x87, 0x1c, 0xd1, 0x4c, 0x3a, 0x84, 0x88, 0x15, 0x5b, 0xb3, 0x77, 0xa4, 0x72, 0xee, 0x1c, 0xb2, 0xd3, 0x47, + 0xa8, 0xd2, 0x6b, 0x3d, 0xbe, 0x9d, 0x28, 0xdd, 0xed, 0xf1, 0x6e, 0xf2, 0x3d, 0x9b, 0x88, 0x18, 0x0c, 0x68, 0x83, + 0x70, 0x46, 0xd6, 0x21, 0x52, 0xe9, 0x00, 0x21, 0x70, 0x4c, 0x40, 0xd3, 0x7f, 0x7d, 0x4b, 0xa2, 0x80, 0x23, 0x6d, + 0x84, 0xac, 0x65, 0x87, 0x43, 0x0e, 0x1a, 0xe5, 0xe6, 0x0f, 0xaf, 0x50, 0xa7, 0x39, 0x30, 0x4f, 0x97, 0xb0, 0xe7, + 0xe0, 0x91, 0x5e, 0x1c, 0x1f, 0xe9, 0xff, 0x1d, 0x4d, 0xd4, 0xf8, 0xdf, 0xd7, 0x44, 0x29, 0x2d, 0x92, 0xa3, 0x5a, + 0xfa, 0x2e, 0x75, 0x14, 0x5c, 0xe4, 0x1d, 0xb5, 0x90, 0x3d, 0xcb, 0xc6, 0x8d, 0x6a, 0xde, 0xff, 0xaf, 0x95, 0xf9, + 0xff, 0x9a, 0x56, 0x86, 0x29, 0xd9, 0xb1, 0x54, 0x33, 0x0f, 0xb4, 0x8a, 0x61, 0xf6, 0x33, 0x49, 0x88, 0x0c, 0x97, + 0x06, 0xfc, 0xa8, 0x82, 0x7d, 0x9c, 0x56, 0xeb, 0x2c, 0xdc, 0xa1, 0x12, 0xf5, 0x56, 0xdc, 0xa5, 0xf9, 0x8b, 0xfa, + 0x5f, 0xa2, 0x2c, 0x60, 0x6a, 0xdf, 0x95, 0x69, 0x1c, 0x90, 0x85, 0x3f, 0x0b, 0x4b, 0x9c, 0xdc, 0xd8, 0xc6, 0x9f, + 0xe5, 0x78, 0xda, 0xaf, 0x3a, 0x33, 0x0f, 0x24, 0x50, 0x03, 0xf1, 0x47, 0xce, 0x65, 0x65, 0xf1, 0x80, 0xd0, 0xcd, + 0x3f, 0x96, 0x65, 0x51, 0x7a, 0xbd, 0xcf, 0x49, 0x5a, 0x9d, 0xad, 0x44, 0x9d, 0x14, 0xb1, 0x82, 0xb2, 0x49, 0x01, + 0x46, 0x1f, 0x56, 0x9e, 0x88, 0x83, 0x33, 0x04, 0x6a, 0x38, 0xab, 0x93, 0x10, 0x80, 0x86, 0x15, 0xc2, 0xfe, 0x19, + 0xb4, 0xf0, 0x2c, 0x8c, 0xc3, 0x35, 0xc0, 0xe4, 0xa4, 0xd5, 0xd9, 0xba, 0x2c, 0xee, 0xd3, 0x58, 0xc4, 0xa3, 0x9e, + 0xa2, 0x64, 0x79, 0x93, 0xbb, 0x72, 0xae, 0xbf, 0xff, 0x83, 0x02, 0xd8, 0x0d, 0x98, 0x6d, 0x0b, 0xec, 0x00, 0x20, + 0x41, 0x81, 0x6c, 0xa1, 0x4e, 0xa3, 0x33, 0xb5, 0x54, 0xe0, 0x3d, 0xd7, 0x03, 0xfc, 0x4d, 0x0e, 0x58, 0xc6, 0x75, + 0x21, 0x03, 0x46, 0x10, 0xc0, 0x08, 0x1c, 0x94, 0x80, 0xa1, 0x33, 0xc4, 0x6d, 0x55, 0xce, 0x5a, 0x68, 0xae, 0x74, + 0x5b, 0x72, 0xd3, 0x28, 0x67, 0x2b, 0x11, 0x40, 0x5f, 0xdd, 0x94, 0x38, 0x5d, 0x2e, 0x5b, 0x49, 0xd8, 0xb7, 0x1f, + 0xda, 0xa9, 0x22, 0x8f, 0x8f, 0xd2, 0x90, 0x57, 0xe0, 0x49, 0xc6, 0x91, 0x24, 0x4a, 0x04, 0x6f, 0xf2, 0xc6, 0x8c, + 0xc3, 0x8b, 0x36, 0xe5, 0xd4, 0xde, 0xac, 0x17, 0x80, 0xf3, 0x04, 0x6d, 0x19, 0x60, 0x2c, 0x60, 0x70, 0x2e, 0xc4, + 0x92, 0xa7, 0x08, 0x7e, 0xe9, 0x44, 0x0a, 0xe3, 0x2e, 0x87, 0x61, 0x1e, 0x14, 0xbd, 0x4b, 0xea, 0x8f, 0x7e, 0x1f, + 0xb5, 0xc9, 0x60, 0x08, 0x2a, 0x01, 0x54, 0xd6, 0x0d, 0x12, 0x03, 0xab, 0xd2, 0x42, 0xe2, 0x12, 0xe2, 0x65, 0xbe, + 0x9a, 0xd6, 0x51, 0xf0, 0xa1, 0x9e, 0x10, 0xc2, 0x09, 0xc6, 0x87, 0xb8, 0x01, 0x02, 0x06, 0xab, 0xb8, 0xc0, 0x20, + 0x79, 0x2e, 0xd1, 0xfd, 0xf1, 0x7c, 0xc7, 0x00, 0x57, 0xce, 0x7b, 0xaa, 0x5d, 0x3d, 0xb0, 0x97, 0xab, 0x74, 0xc9, + 0x08, 0x61, 0xc5, 0xff, 0x45, 0xe4, 0x7d, 0x3b, 0x4c, 0x40, 0x6d, 0x23, 0x7f, 0x0c, 0x12, 0x73, 0x99, 0x28, 0x82, + 0x78, 0x94, 0x15, 0x2c, 0x49, 0x83, 0xcd, 0x28, 0x49, 0x41, 0xa3, 0x89, 0x31, 0x64, 0x2a, 0xb4, 0x43, 0xd2, 0x68, + 0x36, 0x26, 0xfb, 0x18, 0xf2, 0x1a, 0x2e, 0x16, 0x0b, 0xbc, 0xef, 0x67, 0xa1, 0x3a, 0xd8, 0x96, 0xe6, 0x10, 0x70, + 0x92, 0x60, 0x4f, 0x5d, 0x91, 0x92, 0x30, 0x1b, 0x7d, 0x0a, 0x39, 0x37, 0xa0, 0xe3, 0xa4, 0x31, 0x54, 0x1f, 0x98, + 0x84, 0x57, 0x11, 0x3a, 0x29, 0x2b, 0x84, 0x05, 0xdc, 0x37, 0x32, 0x1a, 0xad, 0xa4, 0x41, 0xe0, 0x6d, 0x86, 0xad, + 0xc0, 0x26, 0x34, 0xfc, 0x45, 0xe6, 0x61, 0x5a, 0xcd, 0x4a, 0x30, 0xe7, 0x1b, 0xa8, 0xc4, 0x78, 0xb2, 0xbc, 0xe2, + 0x1b, 0x17, 0x2b, 0x31, 0x99, 0x2d, 0xe7, 0x93, 0xb5, 0xa4, 0x9a, 0xcb, 0xbd, 0x35, 0xcb, 0xd8, 0x12, 0xf6, 0x0f, + 0x03, 0x43, 0xe9, 0xc0, 0x8e, 0xa6, 0x9a, 0x36, 0x09, 0x30, 0x99, 0xce, 0x39, 0x1f, 0x5e, 0x22, 0x9a, 0xac, 0x4e, + 0xdd, 0xc9, 0x54, 0xb5, 0x83, 0x6b, 0x72, 0x26, 0xa7, 0x47, 0xea, 0xa9, 0xd6, 0xbd, 0xe4, 0xa3, 0xed, 0xb0, 0x1a, + 0x6d, 0xfd, 0x00, 0xdc, 0x3a, 0x85, 0x9d, 0xbe, 0x1b, 0x56, 0xa3, 0x9d, 0xaf, 0x61, 0x77, 0x49, 0x21, 0x50, 0xfd, + 0x59, 0xd6, 0x64, 0x2e, 0x5e, 0x17, 0x0f, 0x5e, 0xc1, 0x9e, 0xfb, 0x03, 0xfd, 0xab, 0x64, 0xcf, 0x7d, 0x9b, 0xc9, + 0xf5, 0xcf, 0xb4, 0x6b, 0x34, 0x66, 0x3a, 0x5e, 0xbb, 0x02, 0x2b, 0x34, 0x40, 0x7e, 0xc1, 0x8e, 0xf6, 0x36, 0x07, + 0x81, 0x00, 0xdd, 0x4b, 0x70, 0x14, 0x05, 0x44, 0x4d, 0xab, 0xca, 0xa3, 0xd3, 0xbd, 0xbf, 0xc7, 0x37, 0x42, 0xc0, + 0x26, 0x4f, 0xad, 0x7b, 0xcb, 0xd8, 0x3f, 0x1c, 0x20, 0x84, 0x5e, 0x4e, 0xbf, 0xd1, 0x96, 0xd5, 0xa3, 0x1d, 0xcb, + 0x7d, 0xc3, 0xa8, 0xa7, 0x60, 0x0c, 0x43, 0x17, 0x56, 0x31, 0x92, 0x67, 0x40, 0xd6, 0xf8, 0x0d, 0xa2, 0x0b, 0x58, + 0xf4, 0x7a, 0xaf, 0x8f, 0x68, 0x10, 0x01, 0x95, 0x5e, 0xf3, 0x97, 0x22, 0x9f, 0xab, 0x42, 0xf4, 0xde, 0x5b, 0x3b, + 0x6f, 0x66, 0x24, 0xcb, 0xa4, 0x91, 0x6a, 0xb7, 0xb2, 0x58, 0x57, 0xde, 0xec, 0x84, 0x74, 0x31, 0xc7, 0x50, 0x19, + 0x3c, 0x0e, 0x40, 0xe9, 0xf9, 0x97, 0xd0, 0x2b, 0x19, 0x32, 0xcd, 0x12, 0xcd, 0xec, 0xae, 0xf1, 0x27, 0xab, 0xd4, + 0x8b, 0x11, 0x31, 0x1b, 0xd8, 0x42, 0xdc, 0x16, 0x95, 0x6e, 0x8b, 0x42, 0xd9, 0xa2, 0x48, 0x1f, 0x6a, 0x67, 0xba, + 0x33, 0x0b, 0x9f, 0x55, 0xa6, 0x7d, 0x6f, 0x33, 0x33, 0x36, 0x40, 0xdb, 0x45, 0xf8, 0x06, 0x3a, 0x50, 0x21, 0xe4, + 0x3f, 0x22, 0x22, 0x12, 0x01, 0xbb, 0x9c, 0xba, 0x13, 0x9b, 0x0e, 0xc9, 0x3c, 0xc4, 0xac, 0x50, 0xa3, 0xbc, 0xe4, + 0xc9, 0xd1, 0x80, 0x54, 0x84, 0xba, 0xdd, 0xef, 0x9f, 0x2f, 0x5d, 0x50, 0xfb, 0x35, 0xc5, 0x8e, 0xd1, 0x4d, 0x01, + 0xe7, 0x82, 0x47, 0x79, 0xcf, 0xbd, 0x73, 0x40, 0x73, 0x6c, 0x4f, 0x91, 0x35, 0xe0, 0xf4, 0xb6, 0x0b, 0x01, 0xb6, + 0xcf, 0x9a, 0xad, 0xfd, 0xc9, 0xea, 0x2a, 0x9a, 0x7a, 0x25, 0x9f, 0xe9, 0x2e, 0x4a, 0xdc, 0x2e, 0x8a, 0x65, 0x17, + 0x6d, 0x1a, 0x08, 0x76, 0x5c, 0xf9, 0x01, 0xf0, 0x86, 0x46, 0xfd, 0x7e, 0xd9, 0xea, 0xd9, 0x93, 0xaf, 0x1d, 0xf7, + 0x6c, 0xe6, 0xb3, 0xd2, 0xf4, 0xec, 0xaf, 0xa9, 0xdb, 0xb3, 0x72, 0xb2, 0x17, 0x9d, 0x93, 0x7d, 0x3a, 0x9b, 0x07, + 0x82, 0xcb, 0x9d, 0xfb, 0x3c, 0x9f, 0xea, 0x69, 0x57, 0xf9, 0x41, 0x6b, 0x88, 0xcc, 0x17, 0x3e, 0x57, 0xdd, 0xeb, + 0x0a, 0x16, 0xb0, 0x04, 0x77, 0xeb, 0xa5, 0xf9, 0xaf, 0xd8, 0xfd, 0xbd, 0xa0, 0x97, 0xe6, 0xbf, 0xd1, 0x9f, 0x14, + 0xc0, 0x01, 0x68, 0x4c, 0xed, 0x16, 0x78, 0x88, 0xa1, 0x82, 0xc2, 0xdd, 0xac, 0x9c, 0x7b, 0x35, 0xc0, 0x61, 0x92, + 0xbe, 0xa1, 0xd5, 0x2b, 0x2d, 0x76, 0xbd, 0x4c, 0xf6, 0x0a, 0xf0, 0x50, 0x85, 0x3c, 0x3c, 0x1c, 0xa2, 0x8e, 0x61, + 0x07, 0x75, 0x04, 0x0c, 0x7b, 0x08, 0x8d, 0x2d, 0xf0, 0x7c, 0xfc, 0x9c, 0xf1, 0xbd, 0x00, 0xb5, 0x11, 0xc2, 0xe3, + 0xd5, 0xa2, 0x0c, 0xb1, 0x65, 0x6f, 0x91, 0x4a, 0xea, 0x67, 0x81, 0x28, 0xa3, 0x55, 0x40, 0x5b, 0xed, 0x31, 0x4b, + 0xe3, 0x0d, 0x84, 0x8a, 0xa5, 0x3e, 0x86, 0xd0, 0xc0, 0xe1, 0x77, 0x38, 0x80, 0x04, 0x5f, 0x72, 0x4d, 0x36, 0xf7, + 0x36, 0xbf, 0xa7, 0x7d, 0xfe, 0x70, 0x38, 0xbf, 0x44, 0x50, 0xba, 0x14, 0x3e, 0x52, 0x89, 0xa8, 0x9e, 0xe2, 0xa6, + 0x84, 0x6c, 0x96, 0xac, 0xf4, 0x83, 0x5f, 0xd5, 0x2f, 0x00, 0x90, 0x85, 0x40, 0x9b, 0xc8, 0xec, 0x4f, 0x67, 0x2a, + 0xba, 0x00, 0x38, 0xc4, 0x1f, 0x3f, 0x41, 0xf4, 0x0d, 0x2d, 0xd3, 0xf2, 0x71, 0xc2, 0x43, 0xd0, 0xda, 0x92, 0x4e, + 0x22, 0x56, 0x0a, 0x6c, 0x88, 0x84, 0xef, 0xf7, 0xcf, 0x63, 0x49, 0x07, 0x1a, 0xb5, 0xba, 0x37, 0x6e, 0x75, 0xaf, + 0x7c, 0x5d, 0x77, 0x72, 0xe3, 0x83, 0xa2, 0x7d, 0x36, 0x6f, 0x54, 0xbe, 0xef, 0xeb, 0x9c, 0xdd, 0xe9, 0xde, 0x91, + 0x73, 0xe2, 0xfb, 0x7b, 0x08, 0x45, 0x0f, 0x4d, 0x91, 0x65, 0x49, 0x18, 0xd0, 0x5a, 0xbb, 0xf6, 0x2c, 0xa3, 0x83, + 0xd7, 0xbe, 0x21, 0x44, 0xe4, 0x29, 0x3e, 0x09, 0xb9, 0xc5, 0xf1, 0x41, 0x81, 0xfe, 0x99, 0xf1, 0x67, 0x4e, 0xfc, + 0xb0, 0xd5, 0x2f, 0x80, 0x73, 0xd3, 0xbd, 0x77, 0x27, 0x66, 0x3d, 0x86, 0x52, 0x36, 0xfe, 0xef, 0xf7, 0x89, 0x2c, + 0xd0, 0xe9, 0x88, 0x86, 0x81, 0xe0, 0x2e, 0xaa, 0xff, 0x7b, 0xc5, 0xeb, 0x9e, 0xb5, 0x3a, 0x5f, 0x7e, 0xea, 0xf4, + 0xa4, 0x57, 0x2f, 0xe3, 0x1e, 0x50, 0xa1, 0x03, 0x84, 0xf3, 0xba, 0xdf, 0xb0, 0xdd, 0x77, 0xbf, 0xbc, 0x3b, 0x7a, + 0x19, 0xd8, 0xa4, 0x48, 0x6c, 0x2b, 0xf9, 0xac, 0x07, 0x0a, 0xbf, 0x1e, 0xeb, 0xd5, 0xc5, 0xba, 0xc7, 0x7a, 0xa8, + 0x05, 0x44, 0x0f, 0x0b, 0x50, 0xff, 0xf5, 0xec, 0xd3, 0x50, 0x38, 0xc8, 0xc6, 0xa9, 0x02, 0x45, 0x16, 0xfc, 0x5a, + 0x8c, 0xd6, 0x05, 0x01, 0x22, 0x5b, 0x42, 0x5a, 0x75, 0x32, 0x7b, 0x5c, 0x6a, 0x49, 0x06, 0xdf, 0x04, 0x64, 0x76, + 0x60, 0xe5, 0x04, 0xa5, 0xe3, 0xd6, 0x80, 0x2b, 0x5b, 0x3c, 0xda, 0xed, 0x4f, 0x83, 0xec, 0xac, 0x39, 0x69, 0xb4, + 0x0f, 0xfb, 0x34, 0x0f, 0x10, 0x88, 0x64, 0x2a, 0x82, 0x5c, 0x73, 0x6f, 0x49, 0x1f, 0x1d, 0xce, 0x79, 0x21, 0xff, + 0x9c, 0x4a, 0x1d, 0xe2, 0x50, 0x62, 0x0d, 0x04, 0x2a, 0xcf, 0x50, 0xe5, 0xb0, 0x41, 0x8e, 0x7f, 0x76, 0x24, 0x33, + 0x89, 0xc9, 0x22, 0x77, 0x6b, 0xa6, 0xc2, 0x0f, 0x04, 0x1f, 0xb3, 0x9c, 0x03, 0x17, 0xd8, 0x6c, 0xee, 0xab, 0x29, + 0x2e, 0xae, 0xc0, 0x1f, 0x53, 0xf8, 0x15, 0x4f, 0x61, 0xa7, 0xdd, 0xaf, 0x8b, 0x2a, 0x45, 0xdd, 0x46, 0x61, 0x51, + 0xc9, 0x82, 0x69, 0x0d, 0x69, 0xa2, 0xc3, 0xe8, 0x0f, 0x72, 0x06, 0x0a, 0x42, 0x7e, 0xd9, 0x34, 0xc0, 0x48, 0x25, + 0x97, 0x07, 0x55, 0x12, 0x78, 0x01, 0xb6, 0x41, 0xc5, 0xd6, 0x05, 0x04, 0xd9, 0x26, 0x45, 0x99, 0x7e, 0x2d, 0xf2, + 0x3a, 0xcc, 0x82, 0x6a, 0x94, 0x56, 0x3f, 0xe9, 0x9f, 0xc0, 0xbc, 0x4d, 0xc5, 0xa8, 0x56, 0x31, 0xf9, 0x8d, 0x7e, + 0xbf, 0x18, 0xb4, 0x3e, 0x64, 0xf0, 0xd1, 0x6b, 0xd3, 0xe0, 0x4f, 0x4e, 0x83, 0x1d, 0x26, 0x1a, 0x01, 0x90, 0xcc, + 0xa9, 0x25, 0x0f, 0x45, 0x7f, 0x04, 0x39, 0xd6, 0xa8, 0x72, 0x0a, 0x06, 0xeb, 0x3f, 0x1e, 0xed, 0xc0, 0xd4, 0x8b, + 0xa3, 0x2d, 0xd9, 0x41, 0x2b, 0xdf, 0x00, 0xf7, 0x6b, 0x64, 0x8b, 0x59, 0x0e, 0xd0, 0xec, 0x35, 0x22, 0xe3, 0x93, + 0x17, 0xc0, 0x98, 0xad, 0xb3, 0x30, 0x12, 0x71, 0x30, 0x56, 0x8d, 0x19, 0x33, 0x30, 0x70, 0x81, 0xae, 0x65, 0x52, + 0x92, 0x86, 0x74, 0x30, 0x60, 0xa5, 0x6c, 0xe1, 0x80, 0x17, 0xcd, 0x71, 0x3b, 0xde, 0xb4, 0x68, 0x3c, 0xb0, 0x5d, + 0x6c, 0x7f, 0xff, 0xb2, 0xd8, 0xbe, 0x0b, 0xb7, 0xa4, 0x57, 0xc8, 0x59, 0x42, 0x3f, 0x7f, 0x92, 0x7d, 0xd6, 0x70, + 0x72, 0x2a, 0x34, 0x43, 0x4b, 0x91, 0x50, 0x8a, 0x77, 0x7a, 0x52, 0x60, 0x2c, 0x63, 0xe1, 0xef, 0x81, 0x73, 0xba, + 0x50, 0x44, 0xee, 0xc0, 0x71, 0x7c, 0x03, 0x15, 0x8c, 0x1a, 0x0e, 0x5e, 0xc6, 0xb0, 0x2d, 0x8a, 0x59, 0x48, 0x38, + 0x85, 0x70, 0xb1, 0xca, 0xfa, 0x7d, 0xf9, 0x8b, 0xba, 0xe8, 0x22, 0x93, 0x75, 0x9f, 0x84, 0x23, 0x33, 0x96, 0x53, + 0x2f, 0x24, 0xcf, 0x7b, 0x9e, 0x4c, 0x93, 0x67, 0x79, 0x10, 0x01, 0xe4, 0x73, 0x78, 0x1f, 0xa6, 0x19, 0x58, 0xa5, + 0x49, 0xf9, 0x11, 0x4a, 0x5f, 0x7c, 0x5e, 0xf9, 0x81, 0xce, 0x9e, 0x9b, 0x64, 0x78, 0xb3, 0x6a, 0xbd, 0x49, 0xad, + 0xeb, 0xe2, 0x01, 0xff, 0xea, 0x0c, 0x36, 0xce, 0x75, 0x26, 0x38, 0xf0, 0x22, 0xa9, 0xf5, 0x9a, 0xf1, 0xeb, 0x0c, + 0xd7, 0xa5, 0x6a, 0xa3, 0x8f, 0x42, 0x74, 0x0e, 0x99, 0x0a, 0x50, 0x28, 0xd2, 0xfe, 0x41, 0xa9, 0x95, 0x49, 0xa5, + 0x8d, 0x04, 0xd0, 0x3d, 0x4c, 0x1a, 0x6c, 0x31, 0x94, 0xb1, 0x34, 0x89, 0x72, 0xa7, 0x41, 0x5c, 0xd9, 0x9f, 0x2b, + 0x89, 0x43, 0xcb, 0x22, 0xf9, 0xf7, 0xae, 0xa7, 0xaf, 0x90, 0xba, 0x93, 0x05, 0x32, 0x63, 0xbc, 0xc8, 0xe3, 0xcf, + 0x40, 0x98, 0x0d, 0xda, 0xa8, 0x28, 0x84, 0x90, 0x0d, 0x62, 0xd0, 0x78, 0x91, 0xc7, 0x2f, 0x15, 0x8d, 0x87, 0x7c, + 0x14, 0xf9, 0xea, 0xaf, 0x52, 0xff, 0x15, 0xfa, 0xcc, 0x04, 0x8f, 0x50, 0x4d, 0xf4, 0xef, 0x9e, 0xcf, 0xee, 0x41, + 0x6d, 0x18, 0x85, 0x99, 0x29, 0xbf, 0xf2, 0x4d, 0x71, 0xf6, 0xfa, 0x2b, 0xba, 0xca, 0xb6, 0xee, 0x47, 0x9f, 0x8e, + 0x08, 0xac, 0x8d, 0xd1, 0x15, 0x37, 0x06, 0x90, 0xc3, 0xe4, 0xfd, 0x8a, 0xd2, 0x72, 0x48, 0x83, 0xd0, 0x41, 0x43, + 0xd0, 0x2b, 0x89, 0x3e, 0x90, 0x58, 0xc4, 0x18, 0x5e, 0x88, 0x67, 0xa4, 0x26, 0x13, 0x0d, 0xf1, 0x8a, 0xd8, 0x0f, + 0xd1, 0x92, 0x53, 0x13, 0xdd, 0x08, 0x53, 0x0c, 0x24, 0x76, 0x06, 0xc9, 0x49, 0x52, 0x2b, 0xbf, 0x78, 0x26, 0x09, + 0x4b, 0xec, 0x3c, 0xc4, 0x60, 0x52, 0x4b, 0x77, 0x7a, 0x53, 0xa5, 0xf7, 0x47, 0x5a, 0x0e, 0xda, 0x07, 0x60, 0x97, + 0x92, 0xde, 0x3f, 0x29, 0x14, 0xf1, 0x31, 0x8c, 0x63, 0x08, 0xdf, 0x22, 0xaa, 0x2b, 0x70, 0xae, 0x15, 0x68, 0xac, + 0x06, 0x1e, 0x9a, 0x59, 0x35, 0x1f, 0x72, 0xfa, 0xa9, 0xb4, 0xfc, 0x31, 0xa2, 0xb1, 0xd1, 0xba, 0x39, 0x1c, 0xf6, + 0xb4, 0xea, 0xa5, 0x73, 0xd0, 0x65, 0x33, 0x89, 0x89, 0x1b, 0x48, 0xd7, 0x8f, 0x7e, 0x33, 0x61, 0x2f, 0xa2, 0x42, + 0x2e, 0x85, 0xa0, 0xa0, 0xd5, 0x81, 0xc0, 0xa1, 0xf0, 0x16, 0x65, 0xbe, 0x88, 0x69, 0x03, 0x61, 0xf0, 0xf9, 0x81, + 0xfc, 0x7c, 0x53, 0x90, 0x8a, 0x1d, 0xeb, 0xda, 0xef, 0x6f, 0x4a, 0x0f, 0xf0, 0xe4, 0x4c, 0x92, 0xa7, 0xcd, 0x10, + 0x56, 0x04, 0xd0, 0x98, 0xd5, 0x64, 0x71, 0xc2, 0x95, 0x39, 0xfc, 0x54, 0x79, 0x25, 0x4b, 0x99, 0x3a, 0x4f, 0xf5, + 0x02, 0x88, 0x3a, 0xde, 0xa0, 0x15, 0xa9, 0x5f, 0xa1, 0xb3, 0xd7, 0xac, 0x84, 0x8c, 0x87, 0xe7, 0x9c, 0xa7, 0xa3, + 0x07, 0x96, 0xf0, 0x08, 0xff, 0x4a, 0x26, 0xfa, 0xf0, 0x7b, 0xe0, 0x70, 0x33, 0x4e, 0x78, 0xe4, 0x36, 0x7b, 0x5f, + 0x85, 0x2b, 0xb8, 0x99, 0x16, 0x80, 0xe4, 0x16, 0x24, 0x4d, 0x40, 0x09, 0x89, 0x4c, 0xc8, 0xac, 0x29, 0xf9, 0xa5, + 0xa5, 0x6d, 0xb0, 0x86, 0x49, 0xe7, 0x01, 0x2f, 0x5a, 0x7d, 0xb4, 0x9a, 0x68, 0x97, 0x59, 0x3e, 0x1f, 0xe2, 0x0c, + 0xd5, 0x1c, 0x77, 0x67, 0xf0, 0x73, 0xc0, 0x2b, 0x56, 0x35, 0xe9, 0x68, 0x37, 0xe0, 0xc2, 0x93, 0xeb, 0x3c, 0x1d, + 0x6d, 0xf1, 0x97, 0xdc, 0x1f, 0x00, 0x3a, 0x98, 0xba, 0x04, 0xfe, 0x54, 0x6d, 0x35, 0x95, 0xfa, 0xa5, 0xb5, 0x5f, + 0xd7, 0x9d, 0xd5, 0xca, 0x3d, 0xeb, 0x32, 0xb4, 0x47, 0x86, 0x9c, 0x31, 0x03, 0xfe, 0x9c, 0xb1, 0xe4, 0xcf, 0x19, + 0x2b, 0xfe, 0x9c, 0x71, 0x63, 0x64, 0x00, 0x25, 0xb8, 0x97, 0xfc, 0x7a, 0x8f, 0x98, 0x21, 0x56, 0x83, 0x4a, 0x60, + 0x65, 0x29, 0xe7, 0x3e, 0x72, 0x8a, 0x29, 0xa7, 0x0c, 0x2f, 0x9d, 0xce, 0xdc, 0x81, 0x9c, 0x07, 0x33, 0x77, 0x98, + 0x9c, 0xf5, 0x29, 0x8e, 0xa5, 0x31, 0x29, 0x2a, 0x48, 0xe7, 0x74, 0xb8, 0x79, 0x75, 0x9c, 0x27, 0x2c, 0xe3, 0xe3, + 0xf6, 0x99, 0x02, 0x21, 0xb6, 0x78, 0x86, 0x44, 0x4a, 0xd5, 0x2c, 0xb7, 0xf9, 0xc3, 0xa1, 0x1e, 0x3d, 0xe8, 0x9d, + 0x1e, 0x7e, 0x25, 0xec, 0x97, 0xcc, 0xb3, 0x4f, 0x10, 0xc0, 0x24, 0x91, 0x67, 0x12, 0x8e, 0x7e, 0x2c, 0x47, 0x7f, + 0xd3, 0xf0, 0xf7, 0x19, 0xaa, 0xbb, 0x43, 0x60, 0x62, 0xcb, 0x0e, 0x1c, 0x82, 0xd3, 0x55, 0x25, 0x12, 0x70, 0xb0, + 0xd9, 0xb0, 0x48, 0xef, 0xf1, 0x10, 0xe7, 0x83, 0xc2, 0x47, 0x68, 0x98, 0xd1, 0xfb, 0xfd, 0x8d, 0xf0, 0x2a, 0xd9, + 0xca, 0xc3, 0x21, 0xb1, 0xee, 0xc2, 0x8e, 0x3e, 0x8e, 0xf6, 0x28, 0xa1, 0xf6, 0xa3, 0x5a, 0x6f, 0x2a, 0xf5, 0x20, + 0x37, 0xbb, 0x90, 0x18, 0x54, 0x2c, 0xd5, 0xa7, 0x57, 0xaa, 0x0f, 0x35, 0xeb, 0xfc, 0xae, 0x8e, 0xfb, 0x54, 0x8c, + 0xd6, 0x72, 0x42, 0x80, 0xeb, 0x20, 0xd1, 0xe8, 0x00, 0x18, 0x67, 0x9b, 0x2d, 0x2f, 0xb5, 0x75, 0xa2, 0x74, 0x1c, + 0xe7, 0xfa, 0x38, 0x3e, 0x1c, 0xa4, 0x98, 0x71, 0x79, 0x24, 0x66, 0x5c, 0x36, 0x00, 0x6f, 0xd6, 0x79, 0x50, 0x1f, + 0x0e, 0x97, 0x74, 0x29, 0x32, 0x9d, 0x6d, 0x94, 0x9f, 0xf5, 0xe8, 0xe1, 0x59, 0x82, 0xe6, 0xde, 0x0a, 0x7b, 0x2f, + 0x92, 0xed, 0x99, 0xac, 0x53, 0x2f, 0x23, 0x9f, 0x5e, 0xb8, 0x67, 0x97, 0x5c, 0xfd, 0xb0, 0xfa, 0x7a, 0xfa, 0xab, + 0xf0, 0x22, 0x56, 0xd1, 0x6e, 0x5d, 0x32, 0x61, 0x6f, 0x29, 0x95, 0xb4, 0xca, 0xcb, 0xa7, 0x1b, 0x3f, 0xc0, 0xcc, + 0xb4, 0xa7, 0x0f, 0xb2, 0x11, 0xd5, 0x9f, 0x95, 0xa8, 0x95, 0x61, 0xb2, 0x70, 0x5e, 0x32, 0xf5, 0x64, 0xc0, 0x63, + 0x56, 0xf2, 0x48, 0x76, 0x7a, 0x63, 0x10, 0x04, 0xb0, 0xce, 0x49, 0xab, 0xce, 0x38, 0x1a, 0xad, 0x2a, 0x17, 0xa7, + 0xab, 0x5c, 0x60, 0xb8, 0xdd, 0x9a, 0x6d, 0x54, 0x9d, 0xe5, 0xa6, 0x56, 0x29, 0xdf, 0x01, 0x7c, 0x2c, 0xab, 0x5c, + 0xd0, 0x31, 0x65, 0xea, 0xbc, 0x81, 0x60, 0x6c, 0x55, 0xe3, 0xc2, 0xa9, 0x71, 0xc1, 0x23, 0x6a, 0x77, 0xd3, 0xd4, + 0xa3, 0x2d, 0xb0, 0x94, 0x8e, 0x76, 0xbc, 0x44, 0x95, 0xc2, 0xdf, 0x04, 0xdf, 0x87, 0x71, 0xfc, 0xb2, 0xd8, 0xaa, + 0x03, 0xf1, 0xb6, 0xd8, 0x22, 0xed, 0x8b, 0xfc, 0x0b, 0x71, 0xc0, 0x6b, 0x5d, 0x53, 0x5e, 0x5b, 0x73, 0x1a, 0xd8, + 0x1a, 0x46, 0x4a, 0x0a, 0xe7, 0xe6, 0xcf, 0xc3, 0x81, 0x56, 0x76, 0xad, 0xee, 0x0a, 0xb5, 0x1e, 0x73, 0xd8, 0xb0, + 0x17, 0x59, 0xb8, 0x13, 0x25, 0x38, 0x72, 0xc9, 0xbf, 0x0e, 0x07, 0xad, 0xb2, 0x54, 0x47, 0xfa, 0x6c, 0xff, 0x35, + 0x18, 0x33, 0x74, 0x69, 0x02, 0x96, 0x8d, 0x91, 0xfc, 0xab, 0x69, 0xe6, 0x0d, 0x93, 0x35, 0x53, 0x38, 0x0e, 0x0d, + 0x23, 0xa4, 0x01, 0xdd, 0x06, 0xb5, 0xe1, 0xc9, 0x7c, 0x53, 0x95, 0x5f, 0xdd, 0x91, 0x6a, 0x3f, 0x18, 0x5e, 0x4e, + 0xc4, 0x39, 0x5d, 0x92, 0xd4, 0x53, 0x09, 0x25, 0x21, 0xd8, 0xa5, 0x0f, 0xe4, 0xc4, 0x0a, 0xc8, 0x5a, 0xc6, 0xf2, + 0x5b, 0x3d, 0x20, 0xf4, 0x9f, 0x76, 0xeb, 0x85, 0xfe, 0xd3, 0x34, 0x5b, 0xa8, 0xeb, 0x0f, 0x93, 0xfb, 0x8e, 0x5e, + 0x7f, 0x70, 0x78, 0xa7, 0xae, 0x2a, 0xae, 0xe2, 0x51, 0x6d, 0x98, 0xe4, 0x46, 0x59, 0xb8, 0x2b, 0x36, 0xb5, 0x5a, + 0x9e, 0x8e, 0xc3, 0x08, 0xcc, 0x08, 0x0a, 0x90, 0x75, 0xdd, 0x46, 0xc4, 0xb0, 0x92, 0xcb, 0x84, 0x7c, 0x42, 0x40, + 0x16, 0xa5, 0xc6, 0xf9, 0xb8, 0x05, 0x2a, 0x11, 0x0c, 0x4e, 0x43, 0x6b, 0xd5, 0x4d, 0x7e, 0x52, 0xd9, 0xd8, 0x1d, + 0x90, 0x43, 0x92, 0xc9, 0xe2, 0x6e, 0x74, 0x2b, 0x96, 0x45, 0x29, 0x7e, 0xc6, 0x7a, 0xb8, 0x66, 0x0b, 0xf7, 0x19, + 0x10, 0xda, 0x4f, 0x94, 0xf6, 0x26, 0xd2, 0x04, 0xdd, 0x77, 0x6c, 0x05, 0x20, 0x03, 0x28, 0xea, 0x6a, 0xb7, 0x3e, + 0xe7, 0xe7, 0x48, 0x9a, 0xe1, 0x30, 0xba, 0x7d, 0x7a, 0x17, 0xdc, 0x0d, 0x2e, 0x51, 0x2b, 0x7d, 0xc9, 0xe2, 0x16, + 0x06, 0xd5, 0xde, 0x2c, 0xe1, 0xa0, 0x66, 0xd6, 0xda, 0x08, 0x04, 0x93, 0x3d, 0x14, 0x54, 0xcc, 0x15, 0xec, 0x83, + 0x82, 0xb5, 0xe4, 0x75, 0x70, 0xb8, 0xb5, 0x2f, 0x2b, 0xc5, 0xc5, 0xf3, 0x8b, 0xa4, 0x75, 0x61, 0x29, 0x2f, 0x9e, + 0x37, 0x60, 0x70, 0x39, 0xc2, 0xa6, 0xaa, 0xfc, 0xc9, 0x06, 0x40, 0xb7, 0x22, 0x8a, 0x78, 0x51, 0x0a, 0xdb, 0x56, + 0x3e, 0x73, 0xc2, 0x06, 0x1b, 0xf6, 0x00, 0xf7, 0xca, 0xa0, 0x64, 0x70, 0x21, 0xc6, 0xed, 0x66, 0x17, 0xe0, 0x0a, + 0x86, 0xc2, 0xd8, 0x9a, 0xbf, 0xc9, 0xbc, 0x48, 0x09, 0xb8, 0x19, 0xa2, 0x7c, 0x6d, 0xe0, 0x64, 0xd2, 0x93, 0x6b, + 0xc9, 0x62, 0xc0, 0x82, 0x06, 0xdf, 0x51, 0xeb, 0xef, 0x4c, 0xfe, 0x8d, 0xa7, 0x87, 0x7e, 0xf0, 0x25, 0xf3, 0x96, + 0x3e, 0x7b, 0x53, 0xc9, 0x68, 0x4d, 0x12, 0xe5, 0xd5, 0xc3, 0x25, 0xc8, 0x0d, 0xcb, 0xd1, 0x03, 0x5b, 0x82, 0x38, + 0xb1, 0x1c, 0x25, 0x94, 0xd1, 0x15, 0xee, 0x55, 0x66, 0xcb, 0x44, 0x20, 0xc5, 0x81, 0xa5, 0x94, 0x7b, 0x8b, 0x75, + 0xb0, 0xc4, 0xfd, 0x89, 0xe4, 0x02, 0x4a, 0x1e, 0x40, 0xb9, 0x52, 0x40, 0xc0, 0xa7, 0x03, 0x28, 0x5f, 0xca, 0x8b, + 0xf0, 0x27, 0x4e, 0xd4, 0x60, 0x39, 0x7a, 0x68, 0xd8, 0x4f, 0x5e, 0x68, 0xd9, 0x1f, 0xee, 0xb4, 0xa6, 0x61, 0xc5, + 0xef, 0x60, 0x5a, 0x4c, 0xdc, 0xbe, 0x5c, 0xd9, 0x55, 0xf1, 0xd9, 0x4a, 0x9d, 0xdd, 0xd4, 0x90, 0x84, 0x7d, 0x43, + 0x56, 0x01, 0x0e, 0x56, 0x45, 0xdc, 0xb3, 0x2c, 0xf7, 0x61, 0xf4, 0xe7, 0x26, 0x2d, 0x85, 0x85, 0x2a, 0xe9, 0xef, + 0x9b, 0x52, 0x20, 0x95, 0x89, 0x4e, 0xb4, 0x10, 0x5c, 0x81, 0x41, 0xe0, 0x5e, 0xe4, 0x35, 0x00, 0xc6, 0x80, 0x4b, + 0x81, 0xb2, 0x6c, 0x4b, 0x08, 0xa9, 0xee, 0x67, 0xa0, 0xb6, 0x13, 0xf7, 0x69, 0x44, 0xd6, 0x42, 0xf4, 0x55, 0x30, + 0x66, 0xce, 0x4b, 0xe9, 0x16, 0x9b, 0xae, 0x36, 0xab, 0x1b, 0x74, 0x2e, 0x6d, 0xb9, 0xf9, 0x09, 0x5b, 0xac, 0x15, + 0x28, 0x9b, 0x90, 0xb4, 0x9d, 0xf3, 0x1c, 0x65, 0x13, 0x5a, 0xda, 0x7b, 0xea, 0x51, 0xa1, 0x3a, 0xd9, 0x7a, 0xa9, + 0x9a, 0x5a, 0x84, 0xd5, 0xe2, 0xa2, 0xf2, 0x03, 0xd0, 0x4d, 0xa5, 0xd5, 0x8b, 0xba, 0x46, 0x53, 0xa8, 0xd5, 0xc2, + 0x71, 0xa3, 0x9d, 0x4d, 0x97, 0xe9, 0x1d, 0xe2, 0xac, 0x4a, 0x3b, 0xf4, 0xcb, 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, 0x5f, 0xaa, 0x1e, + 0xfb, 0x29, 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, 0x6b, 0xa5, + 0xb8, 0xac, 0x28, 0xfc, 0x1b, 0x89, 0xac, 0x7a, 0x46, 0x1c, 0xff, 0x67, 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, 0x42, 0xb4, 0x8c, 0xf5, 0x37, 0x64, 0x40, 0xc7, 0x93, 0xe1, 0x6d, 0xb1, 0xed, 0xb1, 0xaf, + 0xa8, 0xc1, 0xd2, 0xd7, 0x8f, 0x3f, 0x40, 0x42, 0xd5, 0xb5, 0x2f, 0x2c, 0x9e, 0x30, 0x4f, 0x89, 0xb6, 0x85, 0x0f, + 0x61, 0xa1, 0x5f, 0x21, 0x32, 0x12, 0xc2, 0x4d, 0x65, 0xf7, 0x28, 0x69, 0x17, 0xfa, 0xd2, 0xd7, 0xb2, 0xaf, 0x7c, + 0xe7, 0x02, 0x60, 0x65, 0x9f, 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, 0x87, 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, 0x29, 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, 0xc3, 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, 0x7b, 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, 0xf6, 0x3f, 0xd6, 0x96, 0x56, 0x95, 0xed, 0xd6, 0x38, 0xcd, + 0xfc, 0x6f, 0xb7, 0x85, 0xbe, 0xff, 0x4a, 0x28, 0x9e, 0x77, 0xbc, 0x6e, 0xbf, 0x87, 0xe8, 0x7d, 0xdd, 0xca, 0xbb, + 0x52, 0xbb, 0x61, 0xa6, 0xfc, 0x21, 0xcd, 0xe3, 0xe2, 0x61, 0x14, 0xb7, 0x8e, 0xbc, 0x49, 0x7a, 0xce, 0xf9, 0xfb, + 0xaa, 0xdf, 0xf7, 0xde, 0x03, 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, 0x91, 0xf3, 0xfd, 0x95, 0x90, + 0x37, 0x2b, 0xf9, 0xe1, 0xa3, 0x15, 0x06, 0xbe, 0xc7, 0xe9, 0x57, 0xd1, 0x63, 0x77, 0xa5, 0x0f, 0xdf, 0x95, 0x96, + 0x3e, 0xab, 0xa8, 0xbf, 0xa3, 0xa2, 0xe6, 0x95, 0x18, 0x11, 0xf1, 0x20, 0x68, 0x67, 0xdb, 0xa5, 0x76, 0x2d, 0x41, + 0xbb, 0x60, 0x53, 0xd8, 0xbf, 0x1e, 0x1d, 0xf2, 0x7e, 0xff, 0x53, 0xee, 0xb5, 0x78, 0xdd, 0x75, 0x68, 0xca, 0x5f, + 0x0b, 0x0f, 0x21, 0x80, 0xb5, 0x0c, 0x94, 0x71, 0x84, 0x49, 0x17, 0x79, 0x8d, 0xb2, 0xe9, 0x44, 0xe0, 0x63, 0x96, + 0x5d, 0x39, 0xc9, 0x34, 0xc0, 0x8c, 0x6a, 0x0a, 0x33, 0x01, 0x46, 0xea, 0x13, 0xd6, 0x4d, 0x4f, 0xab, 0xd0, 0xf2, + 0x35, 0x04, 0xeb, 0x22, 0xcb, 0x38, 0x8a, 0x99, 0x00, 0x60, 0xf3, 0x09, 0xe4, 0x2b, 0xba, 0x3a, 0x24, 0xad, 0x54, + 0x79, 0xbf, 0xce, 0x88, 0x8c, 0x26, 0x21, 0x9a, 0xdf, 0xc2, 0x03, 0xfb, 0xb6, 0x99, 0x51, 0xa5, 0x9e, 0x51, 0x95, + 0xcf, 0x70, 0x58, 0x0a, 0xc7, 0x88, 0xff, 0xb7, 0x54, 0xf5, 0x88, 0x40, 0xaf, 0xca, 0xb4, 0x8a, 0x8a, 0x3c, 0x17, + 0x11, 0x22, 0x54, 0x4b, 0xe7, 0x70, 0xe8, 0xc7, 0x7e, 0x1f, 0x07, 0xc2, 0xbc, 0xf8, 0xd7, 0xc7, 0xba, 0xf2, 0xaf, + 0x05, 0xae, 0x95, 0x14, 0x38, 0x15, 0x35, 0x42, 0x84, 0xf0, 0xfe, 0x04, 0x9e, 0xd5, 0xd4, 0xf7, 0x1b, 0xcb, 0x44, + 0xf7, 0x8f, 0x0c, 0x28, 0x7f, 0x40, 0xbe, 0xae, 0xa4, 0x38, 0x53, 0x27, 0x8f, 0x89, 0x33, 0x0e, 0x40, 0xcc, 0xb7, + 0x25, 0x1a, 0x8d, 0xfd, 0x0f, 0x48, 0x30, 0x54, 0x3f, 0xd8, 0xe9, 0xa6, 0xde, 0x3f, 0x33, 0x89, 0xa3, 0xe8, 0xd3, + 0x36, 0x79, 0x2c, 0x59, 0x1a, 0x2d, 0x1c, 0xbd, 0x47, 0x0c, 0xe3, 0x70, 0x3a, 0x1f, 0x93, 0x6c, 0x63, 0xb2, 0x0a, + 0x20, 0x9d, 0xcc, 0xd4, 0x31, 0xa5, 0x8e, 0xc6, 0xb9, 0x5e, 0x50, 0x85, 0x1e, 0xeb, 0x92, 0xe7, 0x60, 0x3d, 0xf9, + 0xd1, 0x2b, 0xfd, 0xa9, 0x90, 0x73, 0xd8, 0x48, 0x04, 0x85, 0x1f, 0xe0, 0x6a, 0xb0, 0x52, 0xc0, 0x60, 0xea, 0x5b, + 0xf8, 0x9a, 0x78, 0x8e, 0x82, 0x47, 0x61, 0x17, 0x63, 0x6b, 0xe5, 0x3b, 0x9f, 0x14, 0x94, 0x7b, 0x56, 0xcc, 0x79, + 0x05, 0x9c, 0xcb, 0xa0, 0x10, 0xa6, 0xe3, 0x59, 0xfe, 0xcf, 0x24, 0xaf, 0x27, 0x36, 0x04, 0xc8, 0xe0, 0x4f, 0x89, + 0xd3, 0xd2, 0x1d, 0xba, 0xf3, 0xd0, 0xb3, 0x88, 0xc3, 0x46, 0x4f, 0xd6, 0x65, 0xb1, 0x4d, 0x51, 0x2f, 0x61, 0x7e, + 0x20, 0x3f, 0x6f, 0xc9, 0xf7, 0x21, 0x8a, 0xb7, 0xc1, 0xaf, 0x19, 0x8b, 0x05, 0xfe, 0xf5, 0xb7, 0x8c, 0xd1, 0x44, + 0x0b, 0xfe, 0x95, 0x35, 0x48, 0x54, 0xfc, 0xd7, 0x6c, 0x02, 0xb0, 0x8e, 0x5c, 0x7d, 0xf8, 0x94, 0x18, 0x6f, 0xcd, + 0x86, 0x47, 0xbe, 0x59, 0x81, 0x4e, 0x7d, 0xee, 0xae, 0x6c, 0x4f, 0x55, 0xe3, 0x6f, 0xa9, 0xae, 0x46, 0xaa, 0xaa, + 0xf1, 0xb7, 0x94, 0xaa, 0xf1, 0x5b, 0x46, 0xf1, 0x3b, 0x95, 0xcf, 0x90, 0x39, 0xd9, 0xc4, 0x24, 0x9d, 0xbe, 0x37, + 0x9c, 0xd8, 0x65, 0xbf, 0x79, 0x9b, 0xc8, 0x4c, 0xa4, 0x90, 0x7b, 0x03, 0xd0, 0xf6, 0xbb, 0xdc, 0x70, 0x4a, 0x9c, + 0x9f, 0x7b, 0xb8, 0x62, 0xd3, 0xea, 0x15, 0x2d, 0x58, 0x60, 0xf3, 0x32, 0xcb, 0x53, 0x24, 0xb0, 0x6d, 0xca, 0xac, + 0x3f, 0xe7, 0x1e, 0x40, 0x30, 0x93, 0x9a, 0x00, 0x90, 0x16, 0xa2, 0x52, 0x88, 0xfc, 0x15, 0xce, 0xea, 0x73, 0xde, + 0xdb, 0xe4, 0x31, 0x91, 0x56, 0xf7, 0xfa, 0xfd, 0xf4, 0x2c, 0xcd, 0x29, 0xa8, 0xe1, 0x38, 0xeb, 0xf4, 0x65, 0x16, + 0xd4, 0x89, 0x5c, 0xa5, 0x7f, 0x77, 0x83, 0xbc, 0x8c, 0xef, 0xeb, 0xb6, 0xe7, 0x4f, 0xd4, 0xdf, 0x3b, 0xeb, 0x6f, + 0x0b, 0x04, 0x77, 0x72, 0xec, 0x27, 0xab, 0x52, 0x9e, 0x18, 0x97, 0xf6, 0x9e, 0xdf, 0xd4, 0x45, 0x91, 0xd5, 0xe9, + 0xfa, 0xa3, 0xd4, 0xd3, 0xe8, 0xbe, 0xd8, 0x83, 0x31, 0x78, 0x07, 0x80, 0x67, 0x3a, 0x34, 0x40, 0xfa, 0x9e, 0x91, + 0x87, 0xfb, 0xdc, 0x92, 0x9f, 0x54, 0xd6, 0x26, 0x09, 0x2b, 0x8a, 0xcd, 0x30, 0x46, 0x28, 0x19, 0xa7, 0xb1, 0xf5, + 0xfb, 0x7d, 0xf5, 0xf7, 0x0e, 0xa3, 0xa8, 0xa8, 0xb8, 0x63, 0x34, 0x2a, 0xab, 0x7a, 0xb4, 0x1d, 0x1c, 0x0e, 0xe7, + 0xb9, 0x8d, 0xa3, 0xad, 0x57, 0xc0, 0xde, 0x0a, 0x95, 0xb2, 0x57, 0x22, 0x2c, 0x3f, 0x5c, 0xf9, 0xfd, 0x3e, 0xfc, + 0x2b, 0x23, 0x2d, 0x3c, 0x7f, 0x8a, 0xbf, 0x16, 0x75, 0x81, 0xe1, 0x19, 0xb4, 0x46, 0x2b, 0x08, 0x26, 0xf8, 0x7b, + 0x07, 0xea, 0xa5, 0x95, 0xf6, 0x09, 0x74, 0x2b, 0xd0, 0x83, 0x7a, 0xe8, 0xd3, 0xa4, 0x7d, 0x21, 0x51, 0xb7, 0xb7, + 0x3a, 0x8d, 0xfe, 0xa8, 0xe0, 0x72, 0x0a, 0x93, 0xc3, 0x0d, 0x7d, 0x5a, 0x85, 0xdb, 0xcf, 0xf0, 0xf4, 0x67, 0xa0, + 0xdc, 0x3a, 0x1c, 0x72, 0x10, 0x5b, 0xc0, 0xcd, 0x63, 0x15, 0x7e, 0x29, 0x4a, 0x19, 0x51, 0x1f, 0x4f, 0x0b, 0xd0, + 0xde, 0x05, 0xe8, 0x80, 0xa5, 0x41, 0xbc, 0x42, 0xf2, 0x9c, 0x8d, 0x00, 0x96, 0x1d, 0x58, 0xce, 0x32, 0x4e, 0x61, + 0x9e, 0xe5, 0xb5, 0x5a, 0x69, 0x67, 0x65, 0xe2, 0xd5, 0x2c, 0x03, 0x67, 0x81, 0x8b, 0xca, 0x67, 0x99, 0x56, 0x3d, + 0x55, 0x09, 0xfa, 0xbc, 0x92, 0x13, 0x5c, 0x09, 0x4e, 0x36, 0x20, 0xbf, 0x00, 0x49, 0x9a, 0x52, 0xd6, 0x94, 0xd7, + 0x97, 0x74, 0x43, 0x46, 0xcf, 0x79, 0xcf, 0x8b, 0x86, 0xa1, 0x7f, 0xe1, 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, 0xb5, 0x99, 0xc4, 0x83, 0x81, 0xaf, 0x33, 0x16, 0xb3, 0x18, 0x68, 0x90, 0xe3, 0xc1, + 0xe5, 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, 0x0b, 0x31, 0xf0, 0xea, 0xe9, 0x38, 0xb8, 0xa4, 0x5b, 0xe1, 0x62, 0x15, 0x6e, + 0x7f, 0x96, 0x0f, 0x1c, 0x77, 0x54, 0xd2, 0x10, 0x18, 0xbc, 0x3d, 0x74, 0x37, 0x33, 0x34, 0xd4, 0x49, 0xfb, 0x30, + 0x0e, 0xe5, 0x10, 0xab, 0x56, 0x5c, 0x48, 0x6f, 0x04, 0xdf, 0x2e, 0x14, 0x63, 0xd9, 0xd8, 0xa5, 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, 0xca, 0xa9, 0x48, 0xa4, 0x19, 0x21, + 0xc0, 0x8f, 0x27, 0xe5, 0x95, 0xfe, 0x1c, 0x34, 0xad, 0x04, 0x2f, 0x19, 0x24, 0x8f, 0xc4, 0xcf, 0xa4, 0x60, 0x16, + 0x63, 0xd5, 0x60, 0x80, 0xe5, 0x54, 0xcf, 0x1c, 0x93, 0xf4, 0x5f, 0x3a, 0x9d, 0xb0, 0x5f, 0x78, 0xb9, 0xad, 0xe5, + 0x4d, 0x73, 0xef, 0x85, 0x57, 0xb1, 0x54, 0xc3, 0x32, 0xe8, 0xbf, 0x26, 0xda, 0x05, 0x5b, 0x5b, 0xc6, 0x84, 0x55, + 0x3f, 0x80, 0xb4, 0x47, 0xba, 0xbc, 0x6a, 0x98, 0x33, 0xc1, 0xa3, 0x0b, 0x6b, 0x1e, 0x44, 0x17, 0xc2, 0x47, 0x2e, + 0xbb, 0x49, 0x72, 0x35, 0x9e, 0xf8, 0xe1, 0x60, 0xa0, 0x00, 0x68, 0x69, 0x9d, 0x14, 0x83, 0xf0, 0x99, 0x90, 0x03, + 0x69, 0x74, 0x54, 0x05, 0x58, 0x2c, 0xb3, 0xab, 0x72, 0x92, 0x0d, 0x06, 0x3e, 0x88, 0x8d, 0x89, 0xdd, 0xd0, 0x6c, + 0xee, 0xb3, 0x13, 0x05, 0x59, 0x6d, 0x0e, 0x5b, 0x33, 0xdd, 0x02, 0x03, 0x80, 0x41, 0x44, 0xb0, 0xdc, 0xe7, 0x46, + 0x3e, 0xa2, 0x4e, 0x4f, 0x61, 0x04, 0x04, 0xbf, 0x9c, 0x08, 0x44, 0x2e, 0x12, 0xa8, 0x07, 0x98, 0x09, 0x30, 0xa3, + 0x8a, 0xe1, 0x25, 0xb0, 0x8b, 0xe7, 0xe6, 0x15, 0x83, 0xfe, 0x45, 0x93, 0x2c, 0xd1, 0x54, 0xe2, 0x68, 0x8c, 0x9c, + 0x4a, 0x63, 0x64, 0x40, 0xec, 0xe2, 0xf8, 0xf7, 0x94, 0x1e, 0x05, 0x29, 0xfb, 0x52, 0x19, 0xe2, 0x70, 0x14, 0x5f, + 0xc1, 0xaa, 0x71, 0x38, 0xd4, 0xe6, 0xf5, 0x74, 0x56, 0xcf, 0x07, 0x22, 0x80, 0xff, 0x86, 0x82, 0xfd, 0xa2, 0xa9, + 0xc8, 0x0d, 0x52, 0xe7, 0xe1, 0x90, 0x82, 0x7c, 0xaa, 0x9b, 0xfc, 0xb2, 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, 0xff, 0x29, 0xdd, 0x9b, 0x53, 0x1b, 0xe4, 0x00, 0xb6, 0x7b, 0x0f, 0xb7, + 0x63, 0xf4, 0x40, 0x06, 0x6f, 0x84, 0x9c, 0x73, 0x7e, 0x39, 0xb5, 0x66, 0x4c, 0x34, 0x2c, 0x58, 0x39, 0x8c, 0xfc, + 0x00, 0x19, 0x2f, 0xa7, 0xc0, 0xca, 0x7e, 0x54, 0xc4, 0xa5, 0x3f, 0x8c, 0xfc, 0x8b, 0xe7, 0x41, 0xc6, 0xbd, 0x68, + 0xd8, 0xf1, 0x05, 0xd8, 0xab, 0x2f, 0x9e, 0xb3, 0x68, 0xc0, 0xab, 0xab, 0x7a, 0x9a, 0x05, 0xc3, 0x8c, 0x45, 0x57, + 0xc5, 0x10, 0x7c, 0x68, 0xaf, 0xcb, 0x41, 0xe8, 0xfb, 0x66, 0xe7, 0xd0, 0xdd, 0x90, 0xc8, 0x23, 0xec, 0x27, 0x70, + 0xdb, 0xd5, 0x12, 0x33, 0x98, 0x6c, 0xee, 0x22, 0x66, 0xb0, 0xe5, 0x2f, 0x9e, 0x1b, 0x2e, 0xa1, 0xea, 0x5a, 0x6a, + 0x36, 0x0a, 0x34, 0x27, 0x57, 0x68, 0x4e, 0x56, 0x42, 0x2d, 0xf9, 0xa4, 0xc2, 0x09, 0x3b, 0x9f, 0xe4, 0xca, 0x6e, + 0x34, 0xc6, 0xc0, 0x45, 0x7b, 0x6e, 0x0b, 0x23, 0x33, 0x9d, 0xa5, 0x68, 0xc0, 0xc2, 0x33, 0x71, 0x4a, 0x63, 0x40, + 0xfb, 0x72, 0x60, 0x69, 0x43, 0x7e, 0x92, 0x33, 0x03, 0x6d, 0x43, 0x4a, 0xa3, 0x66, 0xe0, 0xcf, 0xd4, 0x84, 0xf9, + 0x15, 0xac, 0x44, 0x10, 0xd5, 0x05, 0x98, 0x24, 0x39, 0x19, 0x8d, 0x94, 0x95, 0x48, 0xce, 0x01, 0xef, 0x13, 0x78, + 0xb2, 0x88, 0x6d, 0xed, 0x4f, 0xe9, 0x7f, 0x75, 0xf8, 0x5c, 0xfa, 0xcf, 0x04, 0xb0, 0x90, 0x4b, 0x83, 0xc8, 0x40, + 0xe1, 0x90, 0x9a, 0x4a, 0xc4, 0x89, 0xe3, 0x19, 0xf8, 0x06, 0x2e, 0xd0, 0x14, 0xd0, 0x1f, 0xd4, 0x8c, 0x22, 0xb2, + 0xf0, 0x57, 0xcf, 0x6e, 0xea, 0x46, 0xcf, 0x33, 0xe7, 0x35, 0x68, 0x66, 0x20, 0xa4, 0xc7, 0xa9, 0x7a, 0x1b, 0x12, + 0x9d, 0x97, 0x97, 0xfa, 0x65, 0x42, 0x24, 0x2b, 0x22, 0x4f, 0xdf, 0xe7, 0x60, 0x1e, 0x51, 0x84, 0x0e, 0xae, 0xcc, + 0xc3, 0xe1, 0x5c, 0x50, 0xf8, 0x8e, 0xf2, 0x7c, 0xc0, 0x69, 0x16, 0x25, 0xa0, 0x0d, 0x64, 0xb9, 0x29, 0x73, 0x9d, + 0xb4, 0x4c, 0xdd, 0x7b, 0xb0, 0x12, 0x54, 0xe8, 0xe6, 0x14, 0x14, 0xca, 0x48, 0x50, 0x4a, 0xab, 0x41, 0x28, 0xd5, + 0x61, 0x11, 0x44, 0x0e, 0x59, 0x08, 0xb8, 0x99, 0x8a, 0x46, 0x4b, 0x1a, 0x1e, 0xe1, 0xdc, 0x40, 0x21, 0x00, 0x89, + 0x3d, 0x55, 0x94, 0x71, 0x39, 0x04, 0x7c, 0x94, 0x70, 0x88, 0xb3, 0x26, 0x6d, 0x79, 0x0e, 0xe2, 0x58, 0x2e, 0xf9, + 0xba, 0x42, 0x30, 0x88, 0xd0, 0x67, 0xc8, 0x9f, 0x2c, 0xe7, 0xdf, 0xad, 0xc3, 0xb4, 0x23, 0x7c, 0xd8, 0xd5, 0x16, + 0x5c, 0xcc, 0x6e, 0xe7, 0x13, 0x88, 0x6f, 0xb9, 0x9d, 0x1f, 0x63, 0x88, 0x2c, 0xfc, 0xc1, 0xdd, 0x50, 0x72, 0x45, + 0xa1, 0xcb, 0x7a, 0x44, 0x8a, 0xec, 0xe9, 0x9a, 0x23, 0x08, 0x0e, 0xb4, 0x6a, 0x90, 0xa1, 0x91, 0xf8, 0xe2, 0x39, + 0x64, 0x0d, 0xd6, 0xfc, 0x4b, 0x45, 0xce, 0xea, 0xfe, 0x64, 0x03, 0xd5, 0x24, 0x93, 0xb5, 0xa2, 0x72, 0xfe, 0x76, + 0x55, 0x96, 0x27, 0xab, 0x32, 0x5c, 0x0d, 0xba, 0xaa, 0xb2, 0xe4, 0x48, 0x6d, 0x80, 0xd6, 0x74, 0x85, 0x18, 0x0a, + 0x59, 0x83, 0xa5, 0x55, 0x95, 0x35, 0xf5, 0x09, 0x04, 0xfa, 0x00, 0xcb, 0xa8, 0xd9, 0x4f, 0x87, 0xff, 0x0c, 0xfe, + 0xa9, 0x42, 0x96, 0xea, 0xb4, 0xce, 0xc4, 0xaf, 0xc1, 0x92, 0xe1, 0x1f, 0xbf, 0x05, 0x6b, 0xc0, 0x12, 0x20, 0xcb, + 0xdd, 0xc6, 0x46, 0xeb, 0x95, 0x57, 0x88, 0xaf, 0xb5, 0xbe, 0xe8, 0xb7, 0x6e, 0x13, 0xb5, 0x02, 0x8c, 0x50, 0x68, + 0x11, 0x60, 0xab, 0x07, 0xee, 0x29, 0xf8, 0x81, 0x18, 0xce, 0x35, 0x69, 0x4d, 0x9d, 0xf0, 0x3a, 0x1b, 0x47, 0x22, + 0xaa, 0xb7, 0x70, 0x71, 0xaf, 0xb7, 0x16, 0x7f, 0xa3, 0x02, 0x01, 0x90, 0xc5, 0x14, 0x6b, 0xe7, 0x0d, 0xe9, 0x95, + 0x61, 0x27, 0xa1, 0xf7, 0x86, 0x9d, 0x40, 0x5e, 0x1c, 0x76, 0x0a, 0x5d, 0xa2, 0xed, 0x14, 0xa9, 0x89, 0xb6, 0x93, + 0x16, 0xab, 0xb0, 0x84, 0xe0, 0x57, 0xed, 0xad, 0xa3, 0x6c, 0x5f, 0x64, 0x09, 0xd3, 0x16, 0x30, 0xca, 0xad, 0xfa, + 0xcc, 0x29, 0x62, 0xa5, 0xec, 0x9d, 0x4e, 0xaa, 0xdc, 0x45, 0x3e, 0xb7, 0x9a, 0x22, 0x93, 0x5f, 0x1e, 0xb7, 0x48, + 0x3e, 0xf9, 0xb9, 0xdd, 0x30, 0x99, 0xfe, 0xe9, 0xe8, 0x0b, 0xe8, 0x8a, 0xec, 0xf4, 0x09, 0x04, 0x64, 0x2a, 0xa8, + 0x56, 0xb7, 0x8a, 0x69, 0xde, 0xae, 0xb2, 0xdb, 0x0b, 0x25, 0x86, 0xd3, 0xd9, 0x49, 0x78, 0xb4, 0x19, 0x32, 0x70, + 0x08, 0x02, 0x85, 0x50, 0x51, 0x0c, 0x8f, 0x40, 0xad, 0x91, 0x7c, 0x80, 0x1f, 0xed, 0x4e, 0x05, 0x91, 0xda, 0x4d, + 0xc5, 0x8d, 0x93, 0x9b, 0xae, 0x97, 0x02, 0xb5, 0x4e, 0xc9, 0x0a, 0xa0, 0x84, 0xa8, 0x3f, 0x8b, 0x6d, 0xfd, 0x0a, + 0xae, 0xd8, 0x7c, 0xdf, 0x28, 0x7a, 0x72, 0x7d, 0x8a, 0xba, 0x15, 0x57, 0xa7, 0x69, 0xab, 0x39, 0x76, 0x9c, 0x21, + 0x07, 0xcf, 0x0a, 0x82, 0xed, 0xa8, 0x44, 0xf9, 0xae, 0xdd, 0x74, 0x4c, 0x6c, 0xf5, 0xcf, 0xa2, 0xda, 0xdc, 0x41, + 0x45, 0x44, 0x7c, 0x94, 0xdd, 0x3c, 0x69, 0xbf, 0x83, 0x3d, 0xd6, 0x6a, 0x10, 0xd9, 0x67, 0x70, 0x95, 0xeb, 0xb4, + 0xc8, 0x6d, 0x19, 0x9c, 0x7f, 0x78, 0xb5, 0xab, 0xb0, 0xc9, 0xb1, 0xae, 0xae, 0x66, 0xaa, 0x93, 0x8a, 0x0d, 0x8c, + 0x35, 0xad, 0xa5, 0x9a, 0xc7, 0x90, 0x74, 0x57, 0x16, 0x67, 0x55, 0xd2, 0x4d, 0xcf, 0x8d, 0x33, 0x85, 0x18, 0x38, + 0x5b, 0x8d, 0x96, 0x33, 0x0c, 0xd1, 0xf5, 0x61, 0x96, 0xf8, 0xad, 0x9e, 0x72, 0x9f, 0x87, 0x5b, 0xbf, 0xab, 0x17, + 0x9c, 0x4c, 0xf6, 0x93, 0xe3, 0xdc, 0xed, 0x22, 0xed, 0x27, 0xbe, 0x0d, 0xf3, 0xaf, 0x6f, 0x10, 0x77, 0xa2, 0xfe, + 0x47, 0x05, 0x40, 0x83, 0x9b, 0x3c, 0x96, 0x28, 0xf5, 0x7b, 0x55, 0xfd, 0xa0, 0x66, 0xaa, 0xa6, 0x81, 0x60, 0x4e, + 0xa5, 0x80, 0x3f, 0xdc, 0x2e, 0x5c, 0xf1, 0x88, 0x1b, 0x16, 0xc6, 0x3f, 0xbd, 0x9a, 0x9d, 0x0a, 0x2a, 0x03, 0x37, + 0xe3, 0x3f, 0x3d, 0xc1, 0x4e, 0x61, 0xad, 0x80, 0xac, 0xf0, 0xa7, 0x97, 0x3f, 0xf2, 0x7e, 0xc5, 0xff, 0xf4, 0xaa, + 0x47, 0xde, 0x47, 0x9c, 0x97, 0x3f, 0x91, 0xd4, 0x09, 0x51, 0x5d, 0xfe, 0x24, 0x4c, 0xb1, 0x55, 0x9a, 0xbf, 0x26, + 0x85, 0x4f, 0xf0, 0x05, 0xf8, 0x0e, 0x57, 0xe1, 0xd6, 0xfc, 0x06, 0x8f, 0x1d, 0x8b, 0x6d, 0x97, 0xfa, 0x02, 0xca, + 0x11, 0x58, 0x44, 0x6e, 0xbf, 0x5d, 0xd9, 0xaf, 0x16, 0x46, 0x19, 0x63, 0xf7, 0x25, 0x2b, 0x51, 0x3a, 0xeb, 0xf7, + 0x0b, 0x29, 0x18, 0xd9, 0x85, 0x35, 0xda, 0xa3, 0x54, 0xbd, 0xfa, 0x2e, 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, 0xae, 0x73, 0x8c, 0xad, + 0xc8, 0x81, 0x03, 0x19, 0x7e, 0x40, 0xe0, 0xbd, 0xec, 0x5f, 0xc1, 0x60, 0x98, 0xe0, 0x46, 0x46, 0x9d, 0x9c, 0xb3, + 0x3f, 0x31, 0x30, 0x83, 0x7a, 0x52, 0xbb, 0xcf, 0xee, 0x55, 0x60, 0x2f, 0x9c, 0x01, 0xed, 0xdd, 0x18, 0xfd, 0xac, + 0x8a, 0xb5, 0x93, 0xfe, 0xb9, 0x58, 0x43, 0x32, 0x1d, 0x16, 0x47, 0xdb, 0x34, 0x3c, 0x92, 0x27, 0xc7, 0xf1, 0xa6, + 0x7f, 0x38, 0x8c, 0xf1, 0xe3, 0x28, 0xbf, 0xb6, 0x80, 0x57, 0x71, 0x0b, 0x69, 0x2c, 0x52, 0xf4, 0x0e, 0xc4, 0x1c, + 0x8a, 0x5e, 0xb2, 0xdf, 0x32, 0x5e, 0x4e, 0x04, 0xa5, 0x24, 0xb1, 0xe1, 0x1d, 0xe9, 0x69, 0x5a, 0x8f, 0xb6, 0x32, + 0x60, 0xbf, 0x1e, 0xed, 0xe8, 0x2f, 0x50, 0x3c, 0x5a, 0xf8, 0x4b, 0xfa, 0xbb, 0xb8, 0x9b, 0x7b, 0xce, 0x37, 0x8d, + 0xef, 0x88, 0x0b, 0x14, 0x6b, 0x76, 0x7f, 0x4d, 0x4b, 0x67, 0x1d, 0x08, 0x0e, 0x78, 0x8b, 0x5d, 0xb4, 0xef, 0x37, + 0xae, 0xd3, 0xd3, 0xfe, 0x7b, 0xb7, 0x46, 0xf9, 0xde, 0x3f, 0x24, 0xca, 0xc1, 0xfe, 0xb5, 0x8b, 0xe6, 0x6f, 0x3f, + 0x65, 0x48, 0x2a, 0x34, 0x37, 0xd8, 0x4e, 0xb6, 0x08, 0x6b, 0x63, 0x1c, 0x54, 0xec, 0xae, 0x0c, 0x23, 0x60, 0x50, + 0xc7, 0xfe, 0x47, 0x9f, 0x4d, 0x1b, 0xb2, 0x0f, 0x00, 0x95, 0xab, 0x10, 0xb0, 0x07, 0xe0, 0x44, 0x23, 0xdc, 0x00, + 0xb7, 0x1a, 0x2d, 0xe9, 0xa0, 0x6e, 0x0b, 0x06, 0xa2, 0x25, 0x6c, 0xe4, 0x6d, 0x57, 0xa7, 0x6f, 0x08, 0x1f, 0x6a, + 0x27, 0xa5, 0x43, 0xf9, 0x9b, 0xe7, 0xec, 0xbf, 0x77, 0x58, 0x53, 0x53, 0x6e, 0x00, 0x33, 0x67, 0x25, 0xf2, 0x0a, + 0xa1, 0x53, 0xe4, 0xf7, 0xaa, 0xae, 0xc4, 0x70, 0x59, 0x8b, 0xb2, 0x33, 0xbb, 0x75, 0xa2, 0x77, 0x4e, 0x41, 0x2d, + 0x95, 0x0d, 0x72, 0x92, 0x6a, 0xf3, 0x91, 0xb5, 0x82, 0x12, 0x75, 0x8d, 0x02, 0xc7, 0xa7, 0x5c, 0xbb, 0xff, 0x77, + 0xce, 0x04, 0x35, 0xdb, 0xa8, 0xee, 0xaf, 0xf5, 0x53, 0x55, 0x93, 0x58, 0x80, 0xcb, 0x49, 0x9a, 0x77, 0x3c, 0xc2, + 0xea, 0x1f, 0x27, 0x4b, 0x11, 0xe8, 0x75, 0x44, 0xbb, 0x12, 0x90, 0xa0, 0x9d, 0x9c, 0x85, 0x8a, 0x40, 0x81, 0xbe, + 0xfe, 0x72, 0x93, 0x66, 0xb1, 0x5c, 0xcd, 0xf6, 0x30, 0x51, 0x16, 0xeb, 0x21, 0x82, 0x9c, 0x99, 0x3a, 0xd8, 0xef, + 0x69, 0x46, 0xb3, 0xf0, 0xca, 0x94, 0xe0, 0x52, 0x5c, 0x45, 0x45, 0x0e, 0x3e, 0x87, 0xf8, 0xc2, 0xe7, 0x42, 0x6e, + 0x10, 0xd1, 0xf4, 0xa5, 0x44, 0xb5, 0x23, 0x05, 0x72, 0x28, 0xf9, 0x09, 0xf1, 0x97, 0xac, 0x8d, 0x71, 0xbf, 0x74, + 0xaa, 0xfd, 0x4a, 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, 0x49, 0x35, + 0xe3, 0xef, 0xd2, 0xfc, 0x89, 0x65, 0xbf, 0x69, 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, 0x17, 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, 0x15, 0xc5, 0x1f, 0x95, 0xbe, 0x23, 0xd0, 0xd1, 0x9d, + 0x17, 0x75, 0xba, 0xdc, 0x7d, 0x24, 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, 0x57, 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, 0x6b, 0x4f, 0xc0, 0x2e, 0x9e, 0x01, 0xba, 0x15, 0x9b, 0x15, 0x23, 0x44, + 0xc8, 0x64, 0x39, 0xab, 0xe9, 0x0c, 0xf2, 0xa9, 0x2f, 0xbe, 0xb3, 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, 0xf2, 0xd4, 0x61, 0x6c, 0x20, 0xc6, 0xac, 0x98, 0x19, 0xfd, 0x0f, 0xee, 0x92, 0xfe, 0x24, 0x04, 0xc0, + 0x4d, 0x34, 0x85, 0x4e, 0x9d, 0x27, 0x17, 0x79, 0xb0, 0xbc, 0xf0, 0xd0, 0x8a, 0x11, 0x0f, 0xfe, 0xf3, 0x3a, 0x44, + 0x10, 0x73, 0x4c, 0xf1, 0xf4, 0x0b, 0xa3, 0xff, 0x08, 0x2e, 0x31, 0x82, 0xd0, 0xdd, 0x3b, 0x87, 0x21, 0xdc, 0xec, + 0x41, 0x06, 0xf5, 0x87, 0x3a, 0x24, 0x6a, 0xf8, 0x53, 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, 0x31, 0xad, 0x3d, 0xaf, 0xdd, 0xee, 0xc1, 0x7f, 0xfa, 0x17, 0x21, 0x03, + 0x26, 0x4e, 0xdf, 0x67, 0x4e, 0xd6, 0xe8, 0x22, 0x93, 0xe9, 0x43, 0x27, 0x7d, 0xa3, 0xd3, 0x7d, 0x27, 0xfc, 0xa3, + 0x62, 0x16, 0x1f, 0x6e, 0xe9, 0x2b, 0x4d, 0x8a, 0x3b, 0x60, 0x65, 0xf3, 0xa8, 0x20, 0xd4, 0xb9, 0x88, 0xbe, 0x31, + 0xe5, 0x5b, 0x42, 0xcd, 0xbe, 0xb1, 0xa4, 0x94, 0xee, 0x35, 0xf4, 0x26, 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, 0x93, + 0x93, 0x5e, 0x18, 0xaf, 0x42, 0x29, 0x28, 0x0c, 0xe8, 0x0a, 0xa4, 0x80, 0x47, 0xed, 0x89, 0xce, 0xc2, 0x2e, 0xe1, + 0x1e, 0xdd, 0x04, 0x8c, 0xf5, 0xf9, 0x27, 0x40, 0x73, 0x17, 0xee, 0xf0, 0x62, 0x80, 0xda, 0xd4, 0xab, 0xbb, 0x8f, + 0x6b, 0x75, 0x0e, 0x87, 0xe0, 0x60, 0x35, 0x88, 0xe0, 0x74, 0x3e, 0x75, 0x34, 0xcb, 0x02, 0x54, 0x4e, 0x96, 0x1b, + 0x79, 0xf3, 0x68, 0xd1, 0xab, 0xfb, 0xde, 0x32, 0x2d, 0xab, 0x3a, 0xc8, 0x58, 0x16, 0x56, 0x80, 0xab, 0x43, 0xeb, + 0x07, 0xe1, 0xb2, 0x70, 0xfe, 0x40, 0x08, 0x62, 0xf7, 0x6a, 0x5b, 0xf2, 0x5c, 0xcd, 0xe1, 0x67, 0xcf, 0xd9, 0x9a, + 0x4b, 0xd4, 0x49, 0x67, 0x22, 0x00, 0xb1, 0xa7, 0x66, 0x15, 0x5d, 0x03, 0x49, 0x9d, 0x66, 0x15, 0x5d, 0x53, 0xb3, + 0x8d, 0x71, 0x20, 0x1f, 0xad, 0x52, 0xc0, 0xbe, 0x9b, 0x8e, 0x83, 0xd5, 0xb3, 0x58, 0x5e, 0x87, 0xee, 0x9e, 0x6d, + 0x94, 0xcf, 0xa0, 0x6e, 0xb5, 0x31, 0x26, 0xb6, 0x9b, 0x2f, 0xe7, 0xfa, 0xed, 0x60, 0xe9, 0xdb, 0x41, 0x73, 0x4e, + 0xd9, 0x77, 0xba, 0xec, 0x95, 0x5d, 0x36, 0xf5, 0xdc, 0x51, 0xd1, 0x6a, 0x0c, 0xe8, 0x0d, 0x2c, 0x58, 0x9f, 0x8b, + 0x34, 0x5b, 0x95, 0xaa, 0x04, 0xbc, 0x30, 0x56, 0xec, 0xce, 0x6f, 0x64, 0x86, 0x24, 0xcc, 0xe3, 0x4c, 0xbc, 0xa3, + 0x7b, 0x2d, 0x4c, 0x8e, 0x63, 0x91, 0x4c, 0x09, 0x9d, 0xd2, 0x9d, 0x6d, 0xe8, 0x5c, 0x85, 0x51, 0x44, 0x6b, 0x25, + 0x95, 0x46, 0x02, 0x53, 0x33, 0x40, 0xc9, 0x5c, 0x81, 0x53, 0xba, 0xdc, 0xff, 0x8e, 0xc4, 0x38, 0xf3, 0x45, 0xc9, + 0x0c, 0xe8, 0x96, 0x5f, 0x17, 0xeb, 0x56, 0x8a, 0x8c, 0x30, 0x6f, 0x8e, 0xdb, 0xeb, 0xfa, 0x10, 0xc8, 0xd5, 0xb2, + 0x47, 0xd1, 0x38, 0x28, 0x74, 0xb8, 0x54, 0x09, 0xb0, 0x2f, 0x12, 0x3f, 0x23, 0x6c, 0x69, 0x0f, 0xe4, 0xf6, 0xe8, + 0x4c, 0x98, 0x73, 0x4e, 0xca, 0xb2, 0x73, 0x69, 0x06, 0x97, 0x13, 0x57, 0x82, 0x8b, 0xf4, 0xb6, 0x3d, 0x4d, 0x5a, + 0xda, 0x3e, 0x36, 0x9c, 0xa3, 0xa1, 0x6d, 0xd0, 0x1d, 0xfb, 0x43, 0x73, 0xb1, 0x88, 0xad, 0x8b, 0xc5, 0xb0, 0x33, + 0xfb, 0xd1, 0x62, 0x01, 0x72, 0x00, 0x38, 0xea, 0x36, 0x7c, 0xcc, 0x96, 0xc0, 0x69, 0x35, 0xcd, 0xa6, 0xde, 0x86, + 0x57, 0xcf, 0x54, 0x4f, 0x2f, 0x79, 0xfe, 0x4c, 0x98, 0xb1, 0xd8, 0xf0, 0xfc, 0x99, 0x75, 0xe4, 0x54, 0xcf, 0x84, + 0x12, 0xad, 0x0b, 0x68, 0x06, 0x5e, 0x53, 0xc0, 0x88, 0x25, 0x93, 0x29, 0x55, 0xe4, 0x71, 0x6f, 0xba, 0x51, 0x83, + 0x17, 0x14, 0x0e, 0x81, 0x94, 0x4e, 0xbf, 0x78, 0xce, 0xf4, 0x7b, 0x17, 0xcf, 0x3b, 0x64, 0x6d, 0xc3, 0x74, 0xb9, + 0x19, 0x26, 0x83, 0xd2, 0x7f, 0x66, 0x26, 0xc6, 0x85, 0x35, 0x49, 0x00, 0xf1, 0x6f, 0xec, 0x77, 0x48, 0xe1, 0xe6, + 0xfd, 0xe5, 0x30, 0x7e, 0xe4, 0xfd, 0x18, 0xd9, 0x93, 0x34, 0x43, 0xac, 0x99, 0x54, 0xc8, 0xdd, 0x57, 0xeb, 0x1f, + 0x13, 0xbb, 0xc9, 0x1e, 0x58, 0x00, 0x62, 0x6b, 0xda, 0xea, 0x96, 0xf7, 0xfb, 0x9e, 0x29, 0x02, 0xfc, 0xa0, 0xfc, + 0xa3, 0x3b, 0x43, 0x32, 0x28, 0xbb, 0x6e, 0x08, 0xf1, 0xa0, 0x6c, 0x9a, 0xf6, 0x7a, 0xdb, 0x3b, 0xf3, 0x58, 0x5d, + 0xa7, 0x9d, 0xc5, 0xd5, 0x22, 0x83, 0xb4, 0xfa, 0x90, 0x1d, 0x67, 0xf6, 0xd9, 0xd1, 0x52, 0xe9, 0x7e, 0x1f, 0x22, + 0xe2, 0x8e, 0xb2, 0xb6, 0xdf, 0x6e, 0xc1, 0x35, 0x1c, 0x0d, 0x42, 0x57, 0xf6, 0x76, 0x19, 0x6d, 0x5c, 0x88, 0xe3, + 0x9e, 0xe9, 0x7c, 0xc1, 0x97, 0x47, 0x69, 0xe7, 0xc1, 0xa9, 0x9e, 0xe8, 0x73, 0xd3, 0x5d, 0x65, 0x72, 0xad, 0xc3, + 0x6a, 0x0c, 0x6a, 0xb3, 0xb0, 0x85, 0xbb, 0xb0, 0x8d, 0x0e, 0x5a, 0xfb, 0xb2, 0xe0, 0x9f, 0x32, 0x00, 0x5f, 0x7a, + 0xb6, 0x6c, 0x7b, 0x4d, 0x5a, 0xbd, 0x91, 0x51, 0x88, 0x2d, 0x6d, 0xaf, 0x3e, 0x1d, 0xe5, 0xe3, 0xe6, 0x84, 0xe2, + 0x42, 0x8e, 0xf2, 0xa3, 0xd7, 0x10, 0x75, 0xad, 0xeb, 0xb8, 0x58, 0x74, 0xb8, 0x71, 0xd5, 0x6d, 0x37, 0xae, 0x1f, + 0x11, 0x6f, 0x8d, 0x36, 0x29, 0xd4, 0xca, 0xd8, 0x11, 0xbc, 0x2c, 0x1f, 0x0e, 0x99, 0x18, 0x0e, 0x25, 0x64, 0xea, + 0x63, 0xf7, 0x86, 0xa6, 0x7d, 0x7e, 0xda, 0xfa, 0x11, 0x4b, 0x8d, 0xa3, 0xd8, 0xf0, 0x4e, 0xdf, 0x79, 0x6c, 0x8d, + 0x2b, 0xf9, 0x32, 0x98, 0xed, 0x0a, 0xaa, 0xad, 0xf1, 0x86, 0xbd, 0x9c, 0xbf, 0xac, 0xa4, 0x92, 0xbf, 0xfd, 0x19, + 0xae, 0xe1, 0xad, 0x2d, 0x1d, 0x34, 0xd5, 0x2c, 0x67, 0xb9, 0xbe, 0x17, 0x1c, 0x7f, 0xdc, 0xbd, 0x22, 0x18, 0xfc, + 0x9e, 0x8e, 0x82, 0x5c, 0x2c, 0xd5, 0x1a, 0x50, 0x90, 0x8e, 0xec, 0x98, 0xca, 0x02, 0xc3, 0x00, 0xde, 0x90, 0x01, + 0xf2, 0x98, 0xc2, 0xdd, 0x50, 0xe1, 0x85, 0xbf, 0x54, 0x64, 0x97, 0xc0, 0xb6, 0x66, 0x7c, 0xcc, 0x70, 0x07, 0x21, + 0xff, 0x08, 0x76, 0xc7, 0x56, 0xec, 0x96, 0x2d, 0x18, 0x92, 0x8d, 0xe3, 0x30, 0xc6, 0x7c, 0x3c, 0x89, 0xaf, 0xc4, + 0x24, 0x1e, 0xf0, 0x08, 0x1d, 0x23, 0xd6, 0xbc, 0x9e, 0xc5, 0x72, 0x00, 0xd9, 0x1d, 0x57, 0x3a, 0x20, 0x84, 0xc6, + 0x86, 0x96, 0xbc, 0x29, 0x0c, 0x2e, 0x76, 0xec, 0x33, 0x12, 0xc9, 0x38, 0x04, 0x8b, 0x56, 0x35, 0xb0, 0x30, 0xb1, + 0x5b, 0x5e, 0xcc, 0x56, 0x73, 0xfc, 0xe7, 0x70, 0x40, 0x00, 0xec, 0x60, 0xdf, 0xb0, 0xbb, 0x08, 0x91, 0xde, 0x16, + 0xfc, 0xce, 0xf2, 0x74, 0x61, 0xf7, 0xfc, 0x1d, 0x1f, 0xb3, 0xf3, 0x1f, 0x3d, 0x88, 0x9c, 0x3d, 0xff, 0x04, 0x68, + 0x88, 0xf7, 0xfc, 0x36, 0xf5, 0x2a, 0x76, 0x4b, 0x14, 0x84, 0xb7, 0xe0, 0x0c, 0x74, 0x0f, 0x11, 0xb0, 0xef, 0xf8, + 0x02, 0x63, 0xc5, 0xce, 0xd2, 0xa5, 0x87, 0x19, 0xa1, 0xf6, 0x74, 0xbe, 0xac, 0xd5, 0x24, 0xdc, 0x5c, 0x2d, 0x27, + 0x83, 0xc1, 0xc6, 0xdf, 0xf1, 0x35, 0xf0, 0xc1, 0x9c, 0xff, 0xe8, 0xed, 0xa8, 0x5c, 0xf8, 0xcf, 0xeb, 0x2c, 0x79, + 0xe7, 0xb3, 0x77, 0x03, 0xbe, 0x00, 0xbc, 0x25, 0x74, 0xe0, 0xba, 0xf7, 0x99, 0xc4, 0x6b, 0x7b, 0xa7, 0xaf, 0x11, + 0x48, 0xe4, 0x0b, 0xc0, 0x88, 0x89, 0xf9, 0xfd, 0x0e, 0x22, 0x30, 0x12, 0xf0, 0x6d, 0xd5, 0x1e, 0xf1, 0x5b, 0x6e, + 0x00, 0xbf, 0x32, 0x9f, 0x3d, 0xf0, 0x50, 0xff, 0x4c, 0x7c, 0x76, 0xc3, 0x3f, 0xf0, 0x6b, 0x4f, 0x4a, 0xd2, 0xe5, + 0xec, 0xc3, 0x1c, 0xae, 0x87, 0x52, 0x9e, 0x0e, 0xe9, 0x67, 0x63, 0x30, 0x80, 0x50, 0xc8, 0xbc, 0xf1, 0x80, 0x35, + 0x29, 0xc4, 0xbf, 0x80, 0x6f, 0x47, 0x09, 0x9b, 0x37, 0xde, 0xd6, 0xd7, 0xf2, 0xe6, 0x8d, 0xf7, 0xe0, 0x53, 0x14, + 0x60, 0x15, 0x94, 0xb2, 0xc0, 0x2a, 0x08, 0x1b, 0x6d, 0x84, 0x31, 0x70, 0xf5, 0xae, 0x31, 0xd4, 0xf5, 0x1c, 0xb1, + 0x6d, 0xa5, 0xef, 0xc3, 0xf7, 0x90, 0x01, 0x1f, 0xbc, 0x29, 0x4a, 0xa2, 0xcf, 0xa9, 0x29, 0x92, 0xd6, 0x3d, 0xf7, + 0x5b, 0xeb, 0x8e, 0xd6, 0x94, 0xfa, 0xc8, 0xd5, 0xf8, 0x70, 0xa8, 0xaf, 0x85, 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, 0x24, 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, 0xeb, 0xf1, 0xb4, 0x26, 0x96, 0xd4, 0xae, 0xc0, 0x18, 0x3d, + 0xae, 0x8a, 0xda, 0xa7, 0xbe, 0x86, 0x50, 0xa4, 0x5a, 0x33, 0xc7, 0x1a, 0x37, 0x46, 0xc4, 0x1d, 0x56, 0xae, 0x9d, + 0xda, 0xeb, 0x00, 0x2c, 0xaf, 0xc6, 0x05, 0x61, 0x93, 0x1c, 0x3b, 0x17, 0xb0, 0x1a, 0x0d, 0xa9, 0x76, 0xc3, 0xad, + 0x97, 0x9d, 0xdf, 0x3c, 0x4e, 0x6c, 0x6d, 0x84, 0x5b, 0x0a, 0x28, 0xa3, 0xfc, 0xc6, 0x72, 0xc2, 0xee, 0x54, 0xef, + 0x48, 0xd5, 0x8e, 0x38, 0x71, 0x01, 0xcb, 0x0d, 0x4f, 0xad, 0xbe, 0x89, 0xc1, 0x89, 0x50, 0xb5, 0xd2, 0xe1, 0x4e, + 0x26, 0x10, 0xf7, 0xab, 0xfb, 0xba, 0x57, 0x82, 0x9f, 0x84, 0xbc, 0x7e, 0xcb, 0x3b, 0x00, 0xac, 0xf8, 0x90, 0x17, + 0xd3, 0xc2, 0xd1, 0xba, 0x0c, 0xca, 0x00, 0x11, 0x9a, 0x01, 0xd0, 0xc9, 0xd5, 0x41, 0x94, 0x06, 0xae, 0xb8, 0x43, + 0x84, 0x9f, 0x46, 0xcf, 0xf2, 0xeb, 0xf0, 0x59, 0x35, 0x0d, 0x2f, 0xf2, 0x20, 0xba, 0xa8, 0x82, 0xe8, 0x59, 0x75, + 0x15, 0x3e, 0xcb, 0xa7, 0xd1, 0x45, 0x1e, 0x84, 0x17, 0x55, 0x63, 0xdf, 0xb5, 0xbb, 0x7b, 0x42, 0xde, 0x76, 0xf5, + 0x47, 0xce, 0x95, 0x3d, 0x65, 0x7a, 0x7e, 0x5e, 0xeb, 0x95, 0xda, 0x6d, 0xae, 0xd7, 0xa8, 0x99, 0xfa, 0x28, 0xfb, + 0x8b, 0x6d, 0x2c, 0x3c, 0x9a, 0x43, 0xe8, 0x33, 0xd2, 0x62, 0xee, 0x71, 0xae, 0x37, 0x7b, 0x52, 0x18, 0x18, 0x31, + 0xa9, 0x64, 0xe4, 0xf4, 0x02, 0x17, 0xa1, 0x0a, 0x31, 0xac, 0xa5, 0xab, 0x7d, 0xd6, 0xa5, 0x37, 0x50, 0xd7, 0x14, + 0xfb, 0x1a, 0x32, 0xf0, 0xa2, 0xe9, 0x65, 0x30, 0x06, 0xe4, 0x08, 0xbc, 0xe3, 0xb3, 0x25, 0x1c, 0x98, 0x6b, 0x80, + 0xbe, 0x79, 0xd4, 0xd7, 0xe5, 0x8e, 0xaf, 0x55, 0xdf, 0x4c, 0xd7, 0x23, 0xa5, 0xfc, 0x58, 0xf1, 0xbb, 0x8b, 0xe7, + 0xec, 0x96, 0x6b, 0x54, 0x94, 0x5f, 0xf4, 0x62, 0xbd, 0x07, 0xae, 0xba, 0x5f, 0xe0, 0x36, 0x8b, 0xc7, 0xae, 0x3c, + 0x60, 0xd9, 0x96, 0x3d, 0xb0, 0x1b, 0xf6, 0x81, 0x3d, 0x61, 0x6f, 0xd9, 0x7b, 0x56, 0x23, 0x44, 0x79, 0xa9, 0xa4, + 0x3c, 0x7f, 0xc1, 0x6f, 0xa5, 0xed, 0x51, 0xc2, 0x92, 0x3d, 0xd8, 0x76, 0x9a, 0xe1, 0x86, 0x7d, 0xe0, 0x8b, 0xe1, + 0x8a, 0xbd, 0x85, 0x6c, 0x28, 0x14, 0x0f, 0x56, 0xac, 0x86, 0x2b, 0x2c, 0x65, 0xd0, 0xa7, 0x61, 0x69, 0x09, 0x8b, + 0xa6, 0x50, 0x94, 0xa2, 0xdf, 0xf2, 0x9a, 0xb0, 0xd3, 0x6a, 0x2c, 0x44, 0x7e, 0x68, 0xb8, 0x62, 0x0f, 0x7c, 0x31, + 0x58, 0xb1, 0x0f, 0xda, 0x46, 0x34, 0xd8, 0xb8, 0xc5, 0x11, 0x98, 0x95, 0x2e, 0x4c, 0x0a, 0xd4, 0x5b, 0xfb, 0x26, + 0xb8, 0x61, 0x37, 0x58, 0xbf, 0x27, 0x58, 0x34, 0xca, 0xfc, 0x83, 0x15, 0x7b, 0xcf, 0x25, 0x86, 0x9a, 0x5b, 0x9e, + 0x74, 0x0c, 0xd5, 0x05, 0xd2, 0x15, 0xe1, 0x09, 0xa7, 0x17, 0xd9, 0x7b, 0x2c, 0x83, 0xbe, 0x32, 0x5c, 0xb1, 0x2d, + 0xd6, 0xee, 0xc6, 0x18, 0xb7, 0xac, 0xea, 0x49, 0x50, 0x60, 0x94, 0x55, 0x4a, 0xcb, 0xc5, 0x11, 0xcb, 0xa6, 0x8e, + 0x1a, 0xd4, 0x86, 0x01, 0x7d, 0x30, 0xfa, 0x0f, 0x5f, 0xbf, 0xfb, 0xd1, 0x2b, 0xf5, 0xcd, 0xf7, 0x17, 0xc7, 0xbb, + 0xb2, 0x44, 0xef, 0xca, 0x5f, 0x79, 0x39, 0xfb, 0x65, 0x3e, 0xd1, 0xb5, 0xa4, 0x4d, 0x86, 0xdc, 0x4d, 0x67, 0xbf, + 0x74, 0xf8, 0x5b, 0xfe, 0xea, 0xfb, 0x8d, 0xd5, 0xc7, 0xea, 0xbb, 0xba, 0x7b, 0x1f, 0x06, 0x9b, 0xc6, 0xa9, 0xf8, + 0xee, 0x74, 0xc5, 0xb1, 0x9d, 0xb5, 0xf6, 0xce, 0xfc, 0x1f, 0xae, 0xf5, 0x16, 0xc7, 0xee, 0x86, 0x6f, 0x87, 0x1b, + 0x7b, 0x18, 0xe4, 0xf7, 0xa5, 0xe2, 0x38, 0xab, 0xf9, 0x0b, 0xaf, 0x53, 0x92, 0x05, 0x54, 0xa3, 0xcf, 0x46, 0x1a, + 0xba, 0x64, 0x26, 0xa6, 0x21, 0xbe, 0xc8, 0x00, 0x9d, 0x0b, 0xc4, 0xb3, 0x7b, 0x3e, 0x9e, 0xdc, 0x5f, 0xc5, 0x93, + 0xfb, 0x01, 0xff, 0x6c, 0x5a, 0xd0, 0x5e, 0x70, 0xf7, 0x3e, 0xfb, 0x95, 0x17, 0xf6, 0x92, 0xfc, 0xc5, 0x67, 0x5f, + 0x85, 0xbb, 0x4a, 0x7f, 0xf1, 0xd9, 0x7b, 0xc1, 0x7f, 0x1d, 0x69, 0xb2, 0x0c, 0xf6, 0xbe, 0xe6, 0xbf, 0x8e, 0x90, + 0xf5, 0x83, 0x7d, 0x11, 0xfc, 0x2b, 0xf8, 0x7f, 0x57, 0x09, 0x5a, 0xc6, 0xbf, 0xd4, 0xea, 0xe7, 0x07, 0x19, 0x9b, + 0x03, 0x6f, 0x42, 0x2b, 0xe8, 0xcd, 0xdb, 0x5a, 0xfe, 0x24, 0x2e, 0x8e, 0x54, 0x3d, 0x35, 0x1c, 0xb4, 0x58, 0xcc, + 0xa2, 0x3e, 0x4a, 0xa7, 0xf2, 0x26, 0xef, 0x78, 0x26, 0x2d, 0xcc, 0xf7, 0x10, 0x0e, 0xfc, 0xce, 0x86, 0x29, 0xd8, + 0x71, 0xdc, 0x0c, 0xde, 0xb1, 0xf7, 0xc2, 0x67, 0xd9, 0x74, 0xcb, 0x6f, 0xf8, 0x13, 0xfe, 0x9e, 0xef, 0x82, 0x07, + 0xfe, 0x81, 0xbf, 0xe5, 0x75, 0xcd, 0x77, 0x6c, 0x29, 0x21, 0x4f, 0xeb, 0xed, 0x65, 0xb0, 0x65, 0xf5, 0xee, 0x32, + 0x78, 0x60, 0xf5, 0xf6, 0x79, 0x70, 0xc3, 0xea, 0xdd, 0xf3, 0xe0, 0x03, 0xdb, 0x5e, 0x06, 0x4f, 0xd8, 0xee, 0x32, + 0x78, 0xcb, 0xb6, 0xcf, 0x83, 0xf7, 0x6c, 0xf7, 0x3c, 0xa8, 0x15, 0xd2, 0xc3, 0x7b, 0x21, 0x99, 0x4e, 0xde, 0xd7, + 0xcc, 0xb0, 0xea, 0x06, 0x5f, 0x84, 0xf5, 0x8b, 0x6a, 0x19, 0x7c, 0xa9, 0x99, 0x6e, 0x73, 0x20, 0x04, 0xd3, 0x2d, + 0x0e, 0x6e, 0xe9, 0x89, 0x69, 0x57, 0x90, 0x0a, 0xd6, 0xd5, 0xd2, 0x60, 0x51, 0x37, 0xad, 0x93, 0xd9, 0xf1, 0x4e, + 0x8c, 0x3b, 0xbc, 0x13, 0x17, 0x6c, 0xd9, 0x74, 0xba, 0xea, 0x9c, 0x3e, 0x0f, 0xf4, 0x11, 0xa0, 0xf7, 0xfe, 0x4a, + 0x7a, 0xd0, 0x14, 0x0d, 0xcf, 0x95, 0xee, 0xb8, 0xb5, 0xdf, 0x87, 0xd6, 0x7e, 0xcf, 0xa4, 0x22, 0x2d, 0x62, 0x51, + 0x59, 0x54, 0x15, 0xf2, 0x89, 0x07, 0x99, 0xd6, 0xaa, 0x25, 0x8c, 0xd4, 0x99, 0x80, 0x49, 0x5f, 0xd0, 0x61, 0x90, + 0x93, 0x5d, 0x81, 0x2d, 0xf9, 0x66, 0x90, 0xb0, 0x35, 0x8f, 0xa7, 0xc3, 0x24, 0x58, 0xb2, 0x3b, 0x3e, 0xec, 0x16, + 0x0b, 0x56, 0x2a, 0x8c, 0x49, 0x5f, 0x9f, 0x8e, 0x76, 0x77, 0xde, 0x5b, 0xa5, 0x71, 0x9c, 0x09, 0xd4, 0xb9, 0x55, + 0x7a, 0x9b, 0xdf, 0x3a, 0xbb, 0xfa, 0x5a, 0xed, 0xf2, 0x20, 0x30, 0xfc, 0x0a, 0x44, 0x3b, 0xc4, 0x7b, 0x07, 0x35, + 0x46, 0xba, 0x25, 0xb3, 0xee, 0x2b, 0x7b, 0x5f, 0xdf, 0x9a, 0xad, 0xfa, 0xdf, 0x2d, 0x82, 0xf6, 0x72, 0xd9, 0xfb, + 0x9f, 0xcd, 0xab, 0xbf, 0x75, 0xbc, 0xba, 0xf1, 0x27, 0x0f, 0xfc, 0x33, 0x46, 0x27, 0x60, 0x22, 0xdb, 0xf1, 0xcf, + 0xa3, 0x6d, 0xe3, 0x94, 0x27, 0xf7, 0xf2, 0xff, 0x2b, 0x05, 0xda, 0xbb, 0x79, 0x65, 0x6f, 0x8a, 0x5b, 0xde, 0xb1, + 0x97, 0x2f, 0xad, 0x3d, 0xd1, 0x20, 0x94, 0x7c, 0xe6, 0x6e, 0x50, 0x34, 0xec, 0x89, 0xbf, 0xf0, 0x6a, 0xf6, 0x79, + 0x3e, 0xd9, 0xf2, 0xe3, 0x1d, 0xf1, 0x73, 0xc7, 0x8e, 0xf8, 0x8b, 0x3f, 0x58, 0x36, 0xdf, 0xea, 0xd5, 0xce, 0x9d, + 0xdc, 0xa9, 0xf4, 0x8e, 0x1f, 0xef, 0xe3, 0xc3, 0x7f, 0xbb, 0xd2, 0xbb, 0xef, 0xae, 0xb4, 0x5d, 0xe5, 0xee, 0xce, + 0x37, 0x1d, 0xdf, 0xc8, 0x5a, 0x63, 0xb8, 0x99, 0x51, 0x30, 0xc2, 0xb4, 0x85, 0x69, 0x1a, 0x44, 0x96, 0x62, 0x11, + 0x12, 0x35, 0x4a, 0xe7, 0x44, 0x9f, 0x05, 0x9d, 0x82, 0x2e, 0x6e, 0xf4, 0xb7, 0x7c, 0xcc, 0x16, 0xc6, 0x65, 0xf3, + 0xf6, 0x6a, 0x31, 0x19, 0x0c, 0x6e, 0xfd, 0xfd, 0x3d, 0x0f, 0x67, 0xb7, 0x73, 0xf6, 0x8e, 0xdf, 0xd3, 0x7a, 0x9a, + 0xa8, 0xc6, 0x17, 0x8f, 0x49, 0x60, 0xb7, 0xbe, 0x3f, 0xb1, 0x88, 0x60, 0xed, 0x1b, 0xe7, 0xad, 0x3f, 0x90, 0x66, + 0x69, 0xb9, 0xb5, 0x7f, 0x78, 0x5c, 0x43, 0x71, 0x0b, 0x42, 0xc6, 0x07, 0x5b, 0xe5, 0xf0, 0x96, 0x7f, 0xf2, 0xde, + 0xf9, 0xd3, 0x77, 0x3a, 0xf8, 0x66, 0xa2, 0xce, 0xa5, 0xb7, 0x17, 0xcf, 0xd9, 0xaf, 0xfc, 0xb3, 0x3c, 0x53, 0xbe, + 0x0a, 0x39, 0x6d, 0x6f, 0x90, 0xc4, 0x89, 0x8e, 0x8a, 0xf7, 0x6e, 0x22, 0x81, 0x42, 0x20, 0x1e, 0x47, 0xcd, 0x1f, + 0x26, 0xe5, 0xd4, 0xdb, 0x01, 0xc9, 0x2b, 0xb7, 0x15, 0xd1, 0xb7, 0x9c, 0xf3, 0xc5, 0xf0, 0x72, 0xfa, 0xbe, 0xdb, + 0xb7, 0x47, 0x85, 0xb5, 0xa9, 0x88, 0xb7, 0x5b, 0x0c, 0xc2, 0x3a, 0x99, 0x59, 0xe6, 0x92, 0x2f, 0xbd, 0xaf, 0xcd, + 0xdc, 0x63, 0x7a, 0xc7, 0x99, 0x66, 0xc8, 0xe8, 0x0b, 0xcc, 0x4c, 0x87, 0xc3, 0xdd, 0x39, 0x96, 0xc7, 0x87, 0x6f, + 0x9f, 0x3d, 0x19, 0x3c, 0xc1, 0x10, 0x2e, 0x2b, 0x2c, 0xe4, 0x3d, 0x1f, 0x66, 0x75, 0xeb, 0xda, 0x71, 0xf1, 0x7c, + 0xf8, 0x0b, 0xe4, 0x0d, 0xba, 0x1e, 0x9a, 0x22, 0x5a, 0xe5, 0x77, 0x14, 0x7d, 0xa2, 0xe4, 0xa0, 0xe3, 0x09, 0xd4, + 0x0e, 0xb9, 0x70, 0xdf, 0x3f, 0xe3, 0xa0, 0xe8, 0xc0, 0x52, 0xfb, 0xfd, 0xf3, 0xcf, 0x44, 0x28, 0x0d, 0xe3, 0xfd, + 0x32, 0x8c, 0xfe, 0x88, 0xcb, 0x62, 0x0d, 0x47, 0xec, 0x00, 0x3e, 0xf7, 0x4c, 0x5f, 0xc3, 0xee, 0x7c, 0xdf, 0x0f, + 0xbc, 0x2d, 0xbf, 0x61, 0xef, 0xb9, 0x77, 0x39, 0x7c, 0xeb, 0x3f, 0x7b, 0x02, 0xf2, 0x13, 0x8c, 0xcb, 0x17, 0x0c, + 0x89, 0xed, 0x28, 0x46, 0xad, 0xc3, 0x2f, 0x35, 0xc4, 0x6a, 0x7d, 0x46, 0xea, 0x2e, 0x48, 0xff, 0xa8, 0x90, 0xfd, + 0x84, 0xc0, 0x6a, 0x92, 0x3e, 0x05, 0x26, 0xf1, 0x6d, 0x0d, 0x09, 0xa4, 0x69, 0x81, 0x18, 0x1c, 0x28, 0x3e, 0x15, + 0xfc, 0xfd, 0xf0, 0x0b, 0xc9, 0x7f, 0x8b, 0x9a, 0x8f, 0xe1, 0x6f, 0x18, 0x9a, 0x49, 0xf5, 0x90, 0xd6, 0x51, 0xe2, + 0xd5, 0x70, 0xea, 0x85, 0x95, 0x50, 0x27, 0x43, 0x90, 0x8a, 0x21, 0x17, 0xe2, 0xe2, 0xf9, 0xe4, 0xb6, 0x14, 0xe1, + 0x1f, 0x13, 0x7c, 0x26, 0x57, 0x9a, 0x7c, 0x46, 0x4f, 0x1a, 0x59, 0xc0, 0x83, 0x7c, 0x5f, 0xf6, 0x6a, 0xb0, 0xa8, + 0x87, 0xfc, 0xb6, 0x76, 0xdf, 0x97, 0x73, 0x82, 0x1e, 0xd9, 0x0f, 0x68, 0x0e, 0x06, 0x6a, 0x06, 0x52, 0x86, 0xe0, + 0x16, 0x2e, 0xfd, 0x9e, 0x2a, 0xc8, 0x97, 0xdf, 0xfb, 0x22, 0x64, 0xe0, 0xca, 0x82, 0x30, 0xe5, 0x52, 0x21, 0x05, + 0x8e, 0xdb, 0x7a, 0xf0, 0x45, 0xa3, 0x93, 0x48, 0xf0, 0x29, 0x01, 0x49, 0xd2, 0xf2, 0x40, 0xd2, 0x88, 0xe9, 0x40, + 0x5c, 0x28, 0x4d, 0xb3, 0x92, 0x22, 0x0e, 0xb1, 0xab, 0xbe, 0x43, 0xc2, 0xb3, 0xe0, 0x03, 0x83, 0xb5, 0x23, 0x45, + 0x8b, 0xf7, 0xc6, 0x74, 0xac, 0xc3, 0x86, 0xee, 0x64, 0x71, 0xbf, 0x4a, 0xea, 0x34, 0x12, 0x57, 0xbe, 0x0a, 0xf9, + 0xf3, 0x9f, 0x4a, 0x04, 0xd2, 0xbb, 0x1a, 0x88, 0x41, 0xf0, 0x03, 0xf4, 0x1f, 0xb0, 0xc8, 0x41, 0x50, 0xaa, 0xcb, + 0x30, 0xaf, 0x32, 0x2a, 0x70, 0xb6, 0x63, 0xdb, 0x39, 0x53, 0x75, 0x0b, 0xbe, 0x08, 0xc3, 0x90, 0x76, 0xb6, 0x6a, + 0x4e, 0x6e, 0xf5, 0x06, 0xea, 0x99, 0xc4, 0x91, 0x5a, 0x8a, 0x23, 0x6d, 0xcd, 0x7d, 0xba, 0xf4, 0xba, 0xe5, 0x05, + 0x0d, 0x17, 0xa0, 0x17, 0xa5, 0xbb, 0xce, 0x27, 0x14, 0xba, 0xac, 0xc6, 0xd5, 0x50, 0xd4, 0xa1, 0x1c, 0x63, 0xed, + 0xcf, 0x95, 0x3c, 0xbf, 0x03, 0xeb, 0x11, 0x1a, 0xbe, 0x2a, 0x75, 0x10, 0xdb, 0x4f, 0xf4, 0xae, 0x53, 0xa9, 0xbf, + 0x01, 0x60, 0xe0, 0xd4, 0xf1, 0x50, 0x1f, 0xb5, 0x53, 0xc8, 0x76, 0xee, 0x2d, 0x31, 0x2a, 0x57, 0xc2, 0x53, 0xa5, + 0xe5, 0x29, 0x65, 0xd5, 0xd7, 0x82, 0x5b, 0xd9, 0x7d, 0x36, 0x80, 0x8c, 0x36, 0x28, 0x90, 0x67, 0xd4, 0xd6, 0x78, + 0x90, 0x6a, 0x9a, 0x25, 0x8e, 0xe1, 0x83, 0x22, 0xcd, 0x2a, 0xb0, 0x78, 0x99, 0x4b, 0xe6, 0xa0, 0x60, 0xb9, 0xde, + 0x6c, 0xa6, 0x99, 0xea, 0x8b, 0xdc, 0xde, 0x68, 0xbc, 0x4c, 0xff, 0xcd, 0x92, 0x01, 0x8f, 0x2e, 0x9e, 0xfb, 0x01, + 0xa4, 0x49, 0x8a, 0x07, 0x48, 0x82, 0xed, 0xc1, 0x2e, 0x76, 0x18, 0xb6, 0x8a, 0x95, 0x3d, 0x79, 0xba, 0xdc, 0xa1, + 0x29, 0x97, 0xe0, 0x92, 0x13, 0x73, 0x39, 0xf5, 0x7d, 0xc9, 0x7a, 0x43, 0x71, 0xca, 0xa6, 0x09, 0x28, 0x09, 0xb4, + 0x5b, 0xf0, 0x5f, 0xf8, 0xd4, 0xd0, 0x69, 0x01, 0x96, 0xda, 0x6e, 0xc0, 0x7f, 0xa1, 0x5f, 0x6c, 0x77, 0x51, 0x3f, + 0x30, 0x0f, 0xf6, 0x66, 0x71, 0x65, 0x0c, 0x38, 0x49, 0x5c, 0x69, 0x1e, 0xb9, 0x7e, 0x50, 0xf4, 0xe9, 0xb2, 0x76, + 0xe0, 0x4c, 0x71, 0x61, 0x95, 0xda, 0x24, 0xbd, 0xf6, 0x5b, 0x6a, 0xe2, 0x4d, 0x94, 0x54, 0x85, 0xed, 0x90, 0xf6, + 0x2f, 0x29, 0x67, 0xaa, 0xb8, 0x43, 0xf4, 0x64, 0x37, 0x71, 0x15, 0x78, 0x61, 0x55, 0xb1, 0x11, 0x6a, 0x33, 0xb2, + 0x9c, 0xc0, 0xe9, 0x1e, 0xab, 0x0b, 0x3e, 0xb6, 0xab, 0xd9, 0x05, 0x2b, 0xd9, 0x9a, 0x49, 0xf7, 0x79, 0x3b, 0xe6, + 0x42, 0x5e, 0xe9, 0x65, 0xd1, 0x0a, 0x68, 0x0f, 0x02, 0x87, 0x5f, 0x6a, 0xba, 0x47, 0xcf, 0x36, 0xdb, 0xd4, 0x66, + 0x63, 0x6b, 0x11, 0x42, 0x06, 0xa2, 0xa1, 0x2f, 0xe4, 0x8c, 0x22, 0x5f, 0xa5, 0xe5, 0x5a, 0x6d, 0xac, 0x32, 0x5e, + 0x60, 0x22, 0xc8, 0x70, 0x16, 0xde, 0xa3, 0xa7, 0xf5, 0x48, 0x53, 0x4c, 0x82, 0x93, 0x2e, 0xfe, 0x02, 0x6c, 0x28, + 0x4f, 0x72, 0x73, 0x40, 0x0e, 0xa0, 0x72, 0x29, 0x4a, 0xa5, 0x0c, 0xfe, 0x59, 0xdd, 0x91, 0x6d, 0xd5, 0x7f, 0xa7, + 0x81, 0x0c, 0xee, 0x40, 0xdf, 0xf6, 0x42, 0x6b, 0x47, 0x3b, 0x57, 0xb6, 0xa6, 0x6d, 0x99, 0xe6, 0x31, 0xb2, 0xd8, + 0x00, 0xf2, 0x89, 0x74, 0x0e, 0x44, 0x5e, 0x13, 0x8d, 0x77, 0x76, 0xcd, 0xc7, 0x53, 0xf1, 0x98, 0xbc, 0x57, 0xf9, + 0xbe, 0xb9, 0xd7, 0x07, 0x63, 0xec, 0x5b, 0x50, 0x26, 0x3e, 0x5a, 0x6d, 0xad, 0x4b, 0xac, 0xb7, 0x4a, 0x93, 0xe8, + 0x86, 0x2b, 0xe8, 0x38, 0x12, 0x37, 0x88, 0xc1, 0x31, 0xe3, 0xb5, 0x55, 0x96, 0xbe, 0xc2, 0x32, 0xd7, 0x31, 0x4b, + 0x86, 0x4c, 0xea, 0x3c, 0x51, 0xf0, 0xe4, 0xe7, 0x09, 0xc9, 0x88, 0xa8, 0xd9, 0x96, 0xa3, 0x94, 0x9b, 0x16, 0x70, + 0x99, 0x91, 0x01, 0x7c, 0x93, 0x26, 0x00, 0xe5, 0xf2, 0x25, 0x48, 0xa5, 0x21, 0x82, 0x6b, 0xb6, 0x97, 0x8c, 0x6e, + 0x1d, 0xad, 0x83, 0x2a, 0xc9, 0xdc, 0xc1, 0xb9, 0x9d, 0x45, 0x4a, 0xbd, 0xf9, 0x08, 0xc3, 0x4e, 0x3e, 0x86, 0x75, + 0x82, 0xdf, 0x06, 0xd4, 0xa4, 0xcf, 0x85, 0x17, 0x8d, 0x00, 0x4d, 0x7d, 0xa7, 0xca, 0xf8, 0x5c, 0x78, 0xd9, 0x68, + 0xcb, 0x32, 0x4a, 0xa1, 0xba, 0x60, 0x76, 0x6b, 0xba, 0x10, 0xf3, 0xaa, 0x1a, 0x68, 0x83, 0xdc, 0xae, 0x63, 0x06, + 0x34, 0x6a, 0xbb, 0xf2, 0xc8, 0x02, 0xdc, 0x9a, 0x89, 0xc0, 0xc8, 0xf9, 0x0f, 0xf9, 0x2b, 0x15, 0xce, 0xd3, 0xef, + 0x87, 0xde, 0x7e, 0x1b, 0x44, 0xa3, 0xed, 0x25, 0xdb, 0x05, 0xd1, 0x68, 0x77, 0xd9, 0x30, 0xfa, 0xfd, 0x9c, 0x7e, + 0x3f, 0x6f, 0x40, 0x55, 0x22, 0x4c, 0xc4, 0xbd, 0x7e, 0xa3, 0x96, 0xaf, 0xd4, 0xfa, 0x9d, 0x5a, 0xbe, 0x54, 0xc3, + 0x5b, 0x7b, 0x12, 0x09, 0x22, 0x4b, 0x63, 0xf3, 0x20, 0xd9, 0x52, 0x2d, 0x95, 0x8e, 0x51, 0x65, 0x44, 0x2d, 0x9d, + 0xcd, 0xb1, 0x62, 0xa4, 0x9d, 0x83, 0x92, 0x01, 0x99, 0x16, 0x57, 0x35, 0xa6, 0x9b, 0x15, 0x2d, 0x31, 0x19, 0x61, + 0x65, 0x5b, 0xde, 0x6e, 0x52, 0x35, 0x9d, 0x93, 0x9b, 0x5b, 0xa5, 0xdc, 0xdc, 0x0a, 0x9e, 0x7f, 0x43, 0xb7, 0x5c, + 0x72, 0xed, 0x65, 0x36, 0x2d, 0x94, 0x6e, 0x19, 0xd7, 0x60, 0x6b, 0xdf, 0x04, 0xb2, 0xcc, 0x47, 0x8a, 0x1a, 0xdb, + 0x8b, 0x46, 0xf9, 0x06, 0xd9, 0x8a, 0x18, 0x75, 0xca, 0x82, 0xf1, 0xb7, 0x3b, 0x7a, 0x20, 0x03, 0x55, 0x55, 0x6d, + 0x1c, 0xdc, 0x59, 0xe9, 0x0f, 0xcb, 0x8b, 0xe7, 0x2c, 0xb1, 0xd2, 0xc9, 0x85, 0x2a, 0xf4, 0x07, 0x21, 0xba, 0xa9, + 0x6c, 0x38, 0x38, 0xd4, 0xc5, 0x56, 0x06, 0x84, 0x1e, 0xa6, 0xf7, 0x36, 0x56, 0xb2, 0xdc, 0x35, 0xe5, 0x8b, 0x19, + 0x4f, 0x38, 0x8e, 0xbe, 0x5c, 0x2d, 0xc2, 0x5a, 0x2d, 0xb2, 0x13, 0xe0, 0xa1, 0xb5, 0x5a, 0x0a, 0xb9, 0x5a, 0x84, + 0x33, 0xd3, 0x85, 0x9a, 0xe9, 0x19, 0x28, 0x20, 0x85, 0x9a, 0xe5, 0x09, 0xc0, 0xc2, 0x0b, 0x33, 0xc3, 0x85, 0x99, + 0xe1, 0x38, 0xa4, 0xc6, 0xff, 0x41, 0xef, 0x75, 0xee, 0xb9, 0xe5, 0x6e, 0x74, 0x1a, 0xf1, 0xed, 0x68, 0x83, 0x39, + 0x3e, 0x08, 0x27, 0x10, 0x2a, 0x58, 0x22, 0x56, 0x8f, 0x46, 0xd8, 0x51, 0x43, 0xe5, 0x68, 0xbf, 0x2c, 0x2c, 0xc9, + 0x92, 0xb0, 0x24, 0xf7, 0x6a, 0x9c, 0x4b, 0xcb, 0xc5, 0xab, 0x24, 0x10, 0x89, 0x8c, 0x97, 0xd2, 0x04, 0x9f, 0xf0, + 0x72, 0x64, 0xa4, 0xe6, 0xc9, 0x22, 0xf5, 0x72, 0x96, 0xb1, 0x31, 0x62, 0x18, 0x85, 0x7e, 0x53, 0xf5, 0xfb, 0x69, + 0xe9, 0xe5, 0xd4, 0xce, 0xcf, 0xe0, 0x7a, 0x79, 0xea, 0x2c, 0x72, 0x84, 0xbc, 0x1a, 0x49, 0x85, 0xe5, 0xb5, 0x52, + 0x4f, 0x5f, 0x82, 0x0f, 0xea, 0xee, 0x8d, 0x02, 0x20, 0x2e, 0x72, 0xe9, 0x5f, 0x5b, 0xc2, 0xa5, 0x29, 0x37, 0x30, + 0xe8, 0x21, 0xcf, 0x49, 0x08, 0x95, 0x20, 0x24, 0x85, 0x75, 0xe3, 0xbe, 0x78, 0x3e, 0x71, 0xdd, 0x59, 0x6c, 0x60, + 0x82, 0xc3, 0x01, 0x10, 0x0f, 0xa6, 0x5e, 0x34, 0xe0, 0xa5, 0x9a, 0x33, 0x9f, 0xbc, 0x9c, 0x60, 0x32, 0x40, 0x55, + 0x31, 0x70, 0xca, 0x7a, 0x26, 0x1f, 0x19, 0x37, 0x33, 0xdf, 0x0f, 0xf0, 0xdd, 0xba, 0x90, 0xe8, 0x0f, 0x0a, 0xa0, + 0x20, 0x53, 0x00, 0x05, 0x89, 0x01, 0x28, 0x88, 0x0d, 0x40, 0xc1, 0xa6, 0xe1, 0x6b, 0xa9, 0xc3, 0x8d, 0x80, 0x2e, + 0xc2, 0x87, 0x9e, 0x85, 0x8d, 0x15, 0x8a, 0x67, 0x63, 0x36, 0x66, 0x85, 0xda, 0x79, 0x72, 0x39, 0x15, 0x3b, 0x8b, + 0xb1, 0xae, 0x22, 0xcb, 0xc4, 0x0b, 0x09, 0x45, 0xce, 0xb9, 0x91, 0xa8, 0xbb, 0x9f, 0x7b, 0x2f, 0xc9, 0x58, 0x32, + 0x6f, 0x68, 0xd4, 0x60, 0x5e, 0x76, 0x1d, 0xc0, 0xb4, 0xe4, 0xdb, 0x82, 0x06, 0xd3, 0xa9, 0xf2, 0x88, 0x34, 0x09, + 0x6a, 0xe7, 0x32, 0x29, 0x72, 0x42, 0x98, 0x04, 0xbd, 0x12, 0xfc, 0x46, 0xa2, 0xfc, 0x7f, 0xd3, 0x09, 0x1e, 0xe0, + 0x98, 0x68, 0x95, 0x7c, 0x05, 0x03, 0x66, 0xce, 0x5f, 0x48, 0xa7, 0x6c, 0x84, 0x62, 0x2c, 0xd3, 0x78, 0xf4, 0x95, + 0x0d, 0x11, 0xda, 0xea, 0x05, 0x9a, 0x98, 0xa0, 0x0e, 0xf0, 0x88, 0xfe, 0x1a, 0x7d, 0x35, 0x14, 0x2a, 0x5d, 0x8d, + 0xd4, 0x35, 0x3b, 0xe7, 0xfc, 0x6b, 0x6d, 0x38, 0x91, 0x31, 0x6d, 0x0a, 0x7c, 0x03, 0x02, 0xf9, 0x06, 0x02, 0xc0, + 0x55, 0xd3, 0x99, 0xbd, 0x02, 0x38, 0x07, 0x02, 0x78, 0x9c, 0x77, 0x3c, 0x7e, 0xa4, 0xbf, 0x8a, 0xe3, 0xde, 0x69, + 0x1a, 0xb6, 0xff, 0x0a, 0x8c, 0xc5, 0x50, 0x8e, 0xe7, 0x3b, 0x05, 0xc9, 0x1e, 0xa5, 0x2c, 0x5d, 0x35, 0x91, 0x1d, + 0x8a, 0xf5, 0x69, 0x4e, 0x19, 0x4b, 0xdb, 0x72, 0x8c, 0x36, 0x5e, 0x3f, 0xc6, 0xe3, 0x9b, 0x1b, 0x3d, 0xf9, 0xa0, + 0x07, 0xb7, 0xb7, 0xb7, 0xaf, 0x7b, 0xcc, 0xe6, 0x5b, 0xb1, 0x78, 0x56, 0xc4, 0x89, 0xd3, 0x3a, 0xe4, 0x00, 0x07, + 0x39, 0x09, 0x81, 0x74, 0x8c, 0x4b, 0x2d, 0x3a, 0xa8, 0x59, 0xce, 0x6b, 0x60, 0x99, 0x45, 0x90, 0x0d, 0x10, 0xd5, + 0x34, 0x15, 0xab, 0xe1, 0x41, 0xa9, 0x9a, 0x53, 0x2a, 0xb5, 0x6f, 0x38, 0x5b, 0x9d, 0x3e, 0xb1, 0x6a, 0x13, 0x6e, + 0xfd, 0x6b, 0xed, 0x09, 0xda, 0x4a, 0x1a, 0x08, 0xf5, 0x7c, 0x9d, 0xde, 0x51, 0x14, 0x8f, 0x33, 0x13, 0x4f, 0x55, + 0x60, 0xec, 0x5b, 0x3b, 0x82, 0x82, 0xa4, 0xe9, 0x3a, 0xe0, 0x30, 0x8d, 0x4e, 0x58, 0xfc, 0x53, 0xfa, 0x50, 0x5e, + 0xd4, 0x0a, 0x9c, 0xe4, 0xef, 0xc2, 0x45, 0x24, 0xb1, 0xd0, 0x2f, 0x09, 0x80, 0x44, 0x06, 0xaf, 0x46, 0xc5, 0x5a, + 0xa8, 0x00, 0x39, 0x45, 0xe9, 0xad, 0xe2, 0xe3, 0x52, 0x94, 0x2a, 0xa5, 0x32, 0x37, 0x2a, 0x05, 0x84, 0xb5, 0x81, + 0xa3, 0x0b, 0xf8, 0x02, 0x82, 0xd6, 0x72, 0xb7, 0xb6, 0x3d, 0x6f, 0x64, 0x3e, 0x33, 0xcd, 0xd3, 0xea, 0xa3, 0xfa, + 0xfb, 0xc3, 0x12, 0xc3, 0x6c, 0x3c, 0xfd, 0x7d, 0x9b, 0x21, 0xdc, 0xfc, 0x0d, 0x43, 0x74, 0x07, 0xe0, 0x98, 0xa5, + 0x3d, 0x14, 0xb2, 0x60, 0x82, 0x35, 0x54, 0xe5, 0x29, 0x9f, 0xbd, 0x7c, 0x72, 0x0b, 0x68, 0x6a, 0xe8, 0xe2, 0x46, + 0xa7, 0xba, 0x2a, 0x41, 0xf8, 0xbe, 0x2b, 0xd4, 0x63, 0x73, 0xc0, 0xa9, 0x01, 0xa0, 0x58, 0xe4, 0xb5, 0x1e, 0xdb, + 0x3f, 0xe8, 0x8d, 0x7a, 0x03, 0xc4, 0xd3, 0x39, 0x2f, 0xfc, 0x23, 0xfa, 0x75, 0xea, 0xcf, 0xb8, 0x10, 0x44, 0xbd, + 0x9e, 0x84, 0xf7, 0xe2, 0x2c, 0x8d, 0x83, 0xb3, 0xde, 0xc0, 0x5c, 0x04, 0x8a, 0xb3, 0x34, 0x3f, 0x03, 0xb1, 0x1c, + 0xe1, 0x11, 0x6b, 0x76, 0x07, 0x88, 0x81, 0xa5, 0x0e, 0x49, 0x56, 0x1d, 0xdb, 0xef, 0xbf, 0x19, 0x19, 0xde, 0x74, + 0x44, 0x84, 0xd1, 0xbf, 0x2b, 0x10, 0xa0, 0x60, 0x99, 0xd9, 0xce, 0x4c, 0xba, 0xda, 0xb3, 0x7a, 0xde, 0x6c, 0xf2, + 0xae, 0xde, 0xb1, 0x9a, 0x96, 0x53, 0xd3, 0x2a, 0xab, 0x69, 0x93, 0x1c, 0x6a, 0x26, 0xfa, 0x7d, 0x8d, 0x8f, 0x9a, + 0xcf, 0x01, 0x97, 0x0d, 0x93, 0xdf, 0xcc, 0xaa, 0x79, 0xbf, 0xef, 0xc9, 0x47, 0xf0, 0x0b, 0x89, 0xcb, 0xdc, 0x1a, + 0xcb, 0xa7, 0xaf, 0x89, 0xcf, 0xcc, 0x20, 0x1e, 0xdd, 0x1d, 0x41, 0x7d, 0xdd, 0x08, 0xaf, 0x63, 0xae, 0xb0, 0x99, + 0x98, 0xbe, 0x81, 0xc1, 0xf3, 0x84, 0x0f, 0xde, 0x72, 0xf4, 0x37, 0xd2, 0x99, 0x29, 0x58, 0xc8, 0xb9, 0x3f, 0x79, + 0x83, 0xd0, 0xc9, 0x88, 0xf4, 0xa0, 0xd3, 0x09, 0x1a, 0xb2, 0xdf, 0x5f, 0x41, 0x67, 0xb6, 0x52, 0x29, 0x5b, 0x15, + 0x95, 0xe9, 0xba, 0x2e, 0xca, 0x0a, 0x3a, 0x96, 0x7e, 0xde, 0x0a, 0x99, 0x59, 0x3f, 0xb3, 0x90, 0x9f, 0x56, 0x12, + 0x6b, 0xca, 0xb6, 0x4f, 0xd4, 0x06, 0x69, 0xd6, 0x85, 0xea, 0x02, 0xe7, 0xce, 0xda, 0xeb, 0x8d, 0x50, 0xff, 0x9c, + 0x8f, 0xd6, 0xc5, 0xda, 0x03, 0x97, 0x98, 0x59, 0x3a, 0x57, 0x1c, 0x1a, 0xb9, 0x3f, 0xfa, 0x52, 0xa4, 0x39, 0xe5, + 0x01, 0x1a, 0x44, 0x31, 0xb7, 0xdf, 0x02, 0xe9, 0x87, 0xde, 0x02, 0xd9, 0x47, 0xe7, 0x9c, 0xbc, 0x01, 0x70, 0x3a, + 0x44, 0xc4, 0xad, 0x48, 0xd0, 0xb1, 0x6a, 0x78, 0x6b, 0xe1, 0x9e, 0xf6, 0xd2, 0xb8, 0x97, 0xe6, 0x67, 0x69, 0xbf, + 0x6f, 0x00, 0x34, 0x53, 0x44, 0x86, 0xc7, 0x19, 0xb9, 0x48, 0x5a, 0x08, 0xa6, 0xb4, 0xff, 0x6a, 0x0c, 0x09, 0x02, + 0x01, 0xff, 0xbb, 0xf0, 0x9e, 0x00, 0xda, 0x26, 0x6d, 0xc0, 0x55, 0x8f, 0xe9, 0xc0, 0x6c, 0xc9, 0xd9, 0xaa, 0xb3, + 0x01, 0x28, 0xa7, 0x4a, 0xeb, 0x29, 0x8f, 0x6b, 0x8a, 0x88, 0x54, 0x59, 0xa8, 0xdf, 0x58, 0x4f, 0x26, 0xab, 0x5c, + 0x64, 0xc8, 0x51, 0x99, 0xbe, 0xd6, 0x8c, 0x10, 0xbb, 0xf4, 0xf3, 0x05, 0x2c, 0xd9, 0xf8, 0x13, 0x4e, 0xde, 0x12, + 0x20, 0x6d, 0x67, 0xed, 0xaa, 0xda, 0xe5, 0xb8, 0xb5, 0x9b, 0x03, 0x92, 0xaf, 0x37, 0x1a, 0x8d, 0xb4, 0x9f, 0x9c, + 0x80, 0xa1, 0xea, 0xa9, 0xa5, 0xd0, 0x63, 0xb5, 0xc2, 0xd6, 0xed, 0xc8, 0x65, 0x96, 0x0c, 0xe6, 0x0b, 0xe3, 0xf8, + 0x95, 0xf9, 0xe8, 0xe3, 0xa5, 0xb2, 0x76, 0x1d, 0xf1, 0xf5, 0x1f, 0x65, 0xb5, 0xbe, 0xe7, 0x5d, 0xd5, 0x04, 0x7c, + 0x51, 0xc5, 0x96, 0x7e, 0xc7, 0x7b, 0xb2, 0x77, 0xf1, 0xb5, 0x1b, 0xec, 0x92, 0xef, 0x79, 0x8b, 0x3a, 0xcf, 0x57, + 0xbe, 0x6e, 0x54, 0xe9, 0xf6, 0x5e, 0xb2, 0xc0, 0xb5, 0x77, 0xd4, 0x34, 0xd6, 0x33, 0x3f, 0x7a, 0x58, 0x84, 0x6c, + 0xe7, 0x63, 0xef, 0xab, 0xe6, 0xe9, 0x59, 0x43, 0x6f, 0x52, 0x43, 0x1f, 0x7b, 0x51, 0xb6, 0x4f, 0x4d, 0x23, 0x7a, + 0x0d, 0x1b, 0xfa, 0xd8, 0x5b, 0x72, 0x72, 0x48, 0x30, 0x38, 0x35, 0xe6, 0x8f, 0x0f, 0xa7, 0x33, 0xfc, 0x1d, 0x03, + 0x2a, 0x31, 0x99, 0x4f, 0x8f, 0x69, 0x47, 0x01, 0x66, 0x54, 0xe9, 0xed, 0xd3, 0x03, 0xdb, 0xf1, 0xb2, 0x1e, 0x5a, + 0x7a, 0xf7, 0xe4, 0xe8, 0x76, 0xbc, 0xaa, 0xc6, 0x97, 0x72, 0xc8, 0xf3, 0x7c, 0x36, 0x1a, 0x8d, 0x84, 0x41, 0xe7, + 0xae, 0xf4, 0x06, 0x56, 0x20, 0x83, 0x8b, 0xea, 0x43, 0xb9, 0xf4, 0x76, 0xea, 0xd0, 0xae, 0xfc, 0x49, 0x7e, 0x38, + 0x14, 0x23, 0x73, 0x8c, 0x03, 0xce, 0x49, 0xa1, 0xe4, 0x28, 0x59, 0x4b, 0x10, 0x9d, 0xd2, 0x78, 0x2a, 0xeb, 0xb5, + 0x15, 0x91, 0x57, 0x23, 0xe4, 0x43, 0xf0, 0x93, 0x07, 0x6a, 0xf1, 0x6b, 0x2d, 0x88, 0x3d, 0xf6, 0xa9, 0x52, 0x3a, + 0xc4, 0xab, 0x02, 0x42, 0x84, 0x01, 0x6f, 0xa0, 0x1d, 0x94, 0xe0, 0xb0, 0xc3, 0x7d, 0x44, 0x84, 0xe8, 0xd7, 0x5e, + 0x3e, 0x93, 0xe1, 0xca, 0xbd, 0x41, 0x35, 0x67, 0x80, 0x58, 0xe9, 0x33, 0x70, 0xc1, 0x04, 0xd4, 0x53, 0x7c, 0x8a, + 0xfe, 0xf5, 0xe6, 0x61, 0xd3, 0xf5, 0x69, 0x09, 0xa8, 0x88, 0x9e, 0xfd, 0x7c, 0x0c, 0xe0, 0x9d, 0x5d, 0x9b, 0x91, + 0xf6, 0xf2, 0x37, 0xc0, 0xb0, 0x52, 0x92, 0x68, 0xe7, 0x94, 0x08, 0xdc, 0xf9, 0xc8, 0x96, 0x7e, 0x94, 0x02, 0x31, + 0x77, 0x3c, 0x49, 0x64, 0x0f, 0x36, 0x72, 0x02, 0xb7, 0x18, 0xf0, 0xe8, 0x00, 0x54, 0xae, 0x14, 0xe4, 0x5e, 0x73, + 0x24, 0x77, 0xfc, 0xd0, 0xfb, 0x61, 0x50, 0x0f, 0x7e, 0xe8, 0x9d, 0xa5, 0x24, 0x77, 0x84, 0x67, 0x6a, 0x4a, 0x88, + 0xf8, 0xec, 0x87, 0x41, 0x3e, 0xc0, 0xb3, 0x44, 0x8b, 0xb4, 0xc8, 0xad, 0x26, 0x6a, 0xdc, 0x84, 0x17, 0x89, 0xa4, + 0x21, 0xda, 0x75, 0x1e, 0x11, 0x0b, 0x00, 0xc9, 0xe2, 0xb3, 0x79, 0x43, 0x51, 0xef, 0x26, 0x7c, 0x8b, 0xee, 0xb2, + 0xd8, 0xef, 0x6f, 0xf3, 0xb4, 0xee, 0xe9, 0x50, 0x19, 0x7c, 0x41, 0xaa, 0x09, 0xf0, 0x68, 0x7f, 0x6d, 0x8e, 0x57, + 0xaf, 0x36, 0x47, 0xca, 0x42, 0x95, 0xa8, 0xdf, 0x62, 0x35, 0xeb, 0x21, 0x22, 0x77, 0x96, 0x19, 0x7b, 0x7b, 0xc1, + 0x2b, 0x39, 0xab, 0x62, 0xbb, 0x1c, 0x5f, 0x11, 0xd6, 0x56, 0x12, 0xa0, 0xa3, 0xf5, 0x58, 0x9b, 0x62, 0xe4, 0x57, + 0x0a, 0x09, 0xb8, 0xe8, 0xd8, 0x5a, 0x28, 0x36, 0x5e, 0x80, 0xbe, 0x64, 0x67, 0x1a, 0x60, 0xbd, 0xd1, 0xab, 0x88, + 0xdb, 0xf2, 0x91, 0x0a, 0x6f, 0x72, 0x53, 0x65, 0x56, 0x36, 0x8b, 0x76, 0x3f, 0x55, 0xbc, 0x42, 0xdc, 0x7a, 0xa3, + 0xf6, 0x28, 0x40, 0xed, 0xa1, 0x85, 0x32, 0x40, 0x97, 0xa6, 0x19, 0x00, 0x32, 0x00, 0xc8, 0x54, 0x11, 0x9f, 0x09, + 0x50, 0x69, 0xab, 0x1b, 0x05, 0x4e, 0xa4, 0xd7, 0xc0, 0xb8, 0xc0, 0x4a, 0x1f, 0xd9, 0xc8, 0x60, 0xb1, 0x45, 0x80, + 0x5b, 0x8e, 0xf4, 0x61, 0x1a, 0x4e, 0xb6, 0xd1, 0x1c, 0x26, 0x69, 0x7e, 0x1f, 0x66, 0xa9, 0x84, 0x96, 0xf8, 0x51, + 0xd6, 0x18, 0xb1, 0x80, 0xf4, 0x7d, 0x7a, 0x51, 0x64, 0x31, 0x41, 0xc2, 0x59, 0x4f, 0x1d, 0x40, 0x35, 0x39, 0xd7, + 0x9a, 0x56, 0xcf, 0x6a, 0x93, 0x87, 0x2c, 0xd0, 0xd9, 0x83, 0x31, 0xa9, 0xe5, 0x86, 0x1e, 0xd9, 0x5f, 0x39, 0x9e, + 0x11, 0xbe, 0xeb, 0x19, 0x4e, 0xfd, 0x77, 0x53, 0x03, 0x29, 0x53, 0x02, 0x08, 0x32, 0x38, 0x9a, 0x10, 0xca, 0xd3, + 0x31, 0x99, 0xda, 0xfc, 0x08, 0x84, 0x23, 0x82, 0x57, 0xf0, 0xdc, 0xd0, 0xba, 0xe5, 0xc6, 0xce, 0x22, 0x4f, 0x13, + 0x40, 0x16, 0x2f, 0xf8, 0x16, 0x90, 0x39, 0xf5, 0xaa, 0x90, 0x3d, 0x7b, 0x2e, 0xa6, 0xb3, 0x79, 0xf0, 0x90, 0xd0, + 0xfe, 0xc5, 0x84, 0xdf, 0x74, 0x57, 0xc9, 0x95, 0xa9, 0x75, 0x6f, 0xa2, 0xc7, 0x5c, 0xee, 0xf4, 0x69, 0xc5, 0x31, + 0xe2, 0x19, 0xac, 0x02, 0x72, 0xce, 0x86, 0xfc, 0xfa, 0x1c, 0xb0, 0x5b, 0x56, 0xc2, 0x8b, 0xf8, 0x75, 0x28, 0xab, + 0x05, 0xc8, 0x8f, 0x9c, 0x47, 0xe6, 0x97, 0xaf, 0xb6, 0x43, 0x39, 0xa7, 0x28, 0xa2, 0xe5, 0xd4, 0xb4, 0xa4, 0x90, + 0x1d, 0x7a, 0x0a, 0x26, 0x53, 0x5b, 0xfe, 0xde, 0x26, 0x2e, 0xc9, 0x37, 0x93, 0xc8, 0xbe, 0x0e, 0xb0, 0x66, 0xad, + 0xba, 0x87, 0x6e, 0x08, 0x06, 0x88, 0x8c, 0x50, 0x66, 0x73, 0x7d, 0xb7, 0x1e, 0x0c, 0x14, 0xcc, 0xaf, 0xa0, 0x9b, + 0x16, 0x9d, 0xe2, 0x00, 0x39, 0x6b, 0x5d, 0xa3, 0x52, 0x55, 0x1c, 0x3a, 0xcc, 0xbb, 0x65, 0x55, 0x76, 0x59, 0x7a, + 0x21, 0x48, 0x8d, 0xba, 0x0a, 0x16, 0x29, 0x15, 0x51, 0xbc, 0x27, 0xbf, 0x06, 0x26, 0x9e, 0x59, 0x39, 0x4a, 0xe3, + 0x39, 0x20, 0x06, 0x29, 0x20, 0x4e, 0xf9, 0x15, 0xa0, 0x89, 0x2e, 0xa2, 0x30, 0x7b, 0x1b, 0x57, 0x41, 0x6d, 0x35, + 0xfd, 0xde, 0x81, 0x8c, 0x3d, 0xaf, 0xfb, 0xfd, 0x94, 0x18, 0xfd, 0x30, 0x0a, 0x03, 0xff, 0x1e, 0x4f, 0xf7, 0x4d, + 0x90, 0x9a, 0x57, 0x1e, 0xe0, 0x15, 0x5d, 0x6e, 0x6d, 0xca, 0x15, 0x8d, 0x0b, 0x7f, 0x8d, 0xe0, 0xf0, 0xa9, 0xa3, + 0xd8, 0x6e, 0x53, 0xe5, 0xd4, 0xc6, 0x60, 0x10, 0xc2, 0x7d, 0x2b, 0xe3, 0xf7, 0x89, 0x97, 0xcf, 0xa2, 0x39, 0x28, + 0x4a, 0x33, 0xcd, 0x17, 0x52, 0x48, 0x37, 0x01, 0xfa, 0x68, 0x10, 0x6a, 0x75, 0xe5, 0x1f, 0x89, 0x97, 0xaa, 0x69, + 0x6d, 0x9e, 0x62, 0x8d, 0x02, 0x31, 0x8b, 0xe6, 0x0d, 0xcb, 0xe8, 0x90, 0x54, 0x97, 0x4b, 0xd3, 0x8c, 0x3f, 0xac, + 0x66, 0xa8, 0x56, 0x1c, 0x35, 0x41, 0x8d, 0xd2, 0x0d, 0x5c, 0x00, 0xff, 0x46, 0x77, 0x1c, 0xd5, 0x28, 0x52, 0x34, + 0xe0, 0x13, 0xc4, 0x88, 0x35, 0x9b, 0x27, 0xac, 0x35, 0x75, 0xcd, 0xe8, 0xf7, 0x65, 0xc8, 0x90, 0x49, 0x42, 0x9e, + 0x3e, 0x5c, 0xae, 0x9f, 0x48, 0x75, 0x01, 0xfc, 0xca, 0x15, 0x9b, 0xf5, 0x7a, 0x73, 0x80, 0xeb, 0x85, 0xf5, 0x0b, + 0x1b, 0x57, 0x70, 0x7e, 0x49, 0xf0, 0xbb, 0xea, 0x47, 0x98, 0x65, 0x50, 0x05, 0x64, 0xfc, 0xb1, 0x90, 0xce, 0x73, + 0x17, 0x93, 0xfa, 0xcd, 0x48, 0x5d, 0x50, 0x66, 0xe9, 0xdc, 0xe2, 0x04, 0x01, 0xe7, 0x61, 0xf5, 0x04, 0x92, 0x7d, + 0xf9, 0xd8, 0xa7, 0x19, 0x05, 0xaa, 0x23, 0xc0, 0x67, 0xb3, 0x7e, 0x08, 0xfb, 0x07, 0x44, 0x16, 0xea, 0x6f, 0xde, + 0xc8, 0x59, 0x43, 0xf2, 0x40, 0xaa, 0xb9, 0x8f, 0xe1, 0xd4, 0x58, 0xe0, 0x4b, 0x8b, 0xde, 0x54, 0xf0, 0x9a, 0x90, + 0xb9, 0x17, 0x68, 0xed, 0x5b, 0xc0, 0x11, 0x22, 0xb8, 0x8c, 0x52, 0x9c, 0xf6, 0x76, 0xbd, 0x00, 0xb9, 0xcd, 0x2d, + 0xc8, 0xeb, 0x77, 0x2e, 0x7e, 0x71, 0x8a, 0xf4, 0x2c, 0xba, 0xc0, 0x40, 0x17, 0x64, 0xde, 0xf8, 0x67, 0x05, 0x2b, + 0x17, 0xd0, 0x7b, 0xa9, 0x58, 0xc9, 0xc9, 0xb6, 0x53, 0x7f, 0x94, 0xca, 0x7e, 0x7b, 0x66, 0x4d, 0xe0, 0x57, 0x89, + 0xfd, 0x12, 0x99, 0x7c, 0xd3, 0x63, 0x93, 0xaf, 0x0c, 0x8b, 0x4e, 0x2d, 0x83, 0x73, 0x7a, 0x64, 0x70, 0xee, 0xed, + 0xac, 0xda, 0x84, 0x30, 0x14, 0x24, 0x81, 0xa6, 0x4b, 0x0f, 0xeb, 0xa6, 0x3f, 0x3f, 0x69, 0x51, 0x6d, 0xd5, 0xbe, + 0x75, 0x3f, 0x0e, 0xb1, 0x8b, 0x5f, 0x25, 0x9e, 0x21, 0x22, 0xf5, 0x81, 0x0e, 0x4c, 0x06, 0x4f, 0x5c, 0xf6, 0xfb, + 0x50, 0xd8, 0x6c, 0x3c, 0x1f, 0xd5, 0xc5, 0xcf, 0xc5, 0x03, 0xa0, 0x3a, 0x54, 0x60, 0x97, 0x43, 0x19, 0xca, 0x88, + 0x4d, 0x6d, 0xb9, 0xe7, 0xf7, 0x57, 0x61, 0x0e, 0xf2, 0x8e, 0x86, 0xc7, 0x39, 0x03, 0x31, 0x0c, 0xbe, 0xfe, 0xc3, + 0x93, 0x7d, 0xda, 0xfc, 0x70, 0x06, 0xdf, 0x1d, 0x9d, 0x7d, 0x44, 0xba, 0x9b, 0xb3, 0x75, 0x59, 0xdc, 0xa7, 0xb1, + 0x38, 0xfb, 0x01, 0x52, 0x7f, 0x38, 0x2b, 0xca, 0xb3, 0x1f, 0x54, 0x65, 0x7e, 0x38, 0xa3, 0x05, 0x37, 0xfa, 0xdd, + 0x9a, 0x78, 0xff, 0xa8, 0x34, 0x03, 0xda, 0x12, 0x22, 0xb3, 0xb4, 0xfa, 0x11, 0x94, 0x88, 0x8a, 0x1f, 0x55, 0x46, + 0xb5, 0x5a, 0x3b, 0xce, 0x87, 0x44, 0x23, 0x65, 0xd3, 0x84, 0xc4, 0xd5, 0x12, 0xd6, 0xa1, 0x9e, 0x9d, 0x36, 0xdf, + 0x8e, 0xf3, 0x40, 0x1d, 0x10, 0x39, 0xbf, 0xce, 0x47, 0x5b, 0xfa, 0x1a, 0x7c, 0xeb, 0x70, 0xc8, 0x47, 0x3b, 0xf3, + 0xd3, 0x27, 0x6b, 0xa5, 0x8c, 0x3b, 0x52, 0xe4, 0x42, 0xc8, 0x19, 0xb7, 0xed, 0x31, 0xe0, 0x00, 0xf0, 0x0f, 0x07, + 0xfa, 0xbd, 0x93, 0xbf, 0xd5, 0x6e, 0x69, 0xd5, 0xf3, 0x63, 0x8b, 0x3b, 0xe3, 0x75, 0x6d, 0x88, 0xda, 0xf6, 0x12, + 0x5b, 0x7a, 0xdf, 0x34, 0xa8, 0x29, 0xa2, 0x9f, 0xb0, 0x9a, 0x58, 0xc5, 0x61, 0x41, 0x4a, 0x48, 0x62, 0x38, 0x46, + 0x3b, 0xf4, 0x38, 0x5d, 0x2c, 0x3d, 0xb9, 0xef, 0xf0, 0x72, 0xeb, 0xfb, 0x80, 0xa4, 0x55, 0x38, 0xff, 0xe8, 0x85, + 0x06, 0x1e, 0xbd, 0xc8, 0xab, 0x22, 0x13, 0x23, 0x41, 0xa3, 0xfc, 0x96, 0xc4, 0x99, 0x33, 0xac, 0xc5, 0x99, 0x02, + 0x0b, 0x0b, 0x09, 0xa0, 0xbb, 0x28, 0x29, 0x3d, 0x38, 0x7b, 0xb2, 0x2f, 0x9b, 0xdf, 0x09, 0x1e, 0x62, 0xb4, 0x00, + 0x46, 0x9c, 0x5d, 0xbb, 0xbc, 0x87, 0xb0, 0xcc, 0xbd, 0xdf, 0xdf, 0xde, 0xe5, 0x05, 0x84, 0x68, 0x9e, 0x49, 0xc5, + 0x6a, 0x79, 0x06, 0x8c, 0x79, 0x22, 0x3e, 0x0b, 0x2b, 0x39, 0x0d, 0xaa, 0x8e, 0x62, 0xf5, 0x36, 0x9e, 0x7b, 0x40, + 0xf1, 0xfd, 0x21, 0x01, 0x2e, 0x77, 0x9f, 0xbd, 0x51, 0xae, 0xa9, 0xa4, 0x47, 0x9e, 0x63, 0xb4, 0x64, 0x02, 0x14, + 0xcf, 0x10, 0x27, 0x29, 0xac, 0x9e, 0x9b, 0x20, 0x15, 0xf9, 0xfa, 0x84, 0xe2, 0x8b, 0xe6, 0x51, 0xd4, 0xb0, 0x90, + 0x25, 0x70, 0x3c, 0x24, 0xb3, 0x6c, 0x8e, 0x2c, 0xe5, 0x69, 0x7b, 0x8a, 0x74, 0x74, 0x62, 0x89, 0xdf, 0xd6, 0xfc, + 0x7a, 0x91, 0x8a, 0xc0, 0xa4, 0x9d, 0xad, 0xcc, 0xbd, 0x10, 0x86, 0x2a, 0xe1, 0xde, 0xeb, 0x7a, 0x16, 0xca, 0x4d, + 0xd1, 0xaa, 0x98, 0x3d, 0x4c, 0x89, 0x19, 0xa6, 0x58, 0x7f, 0x61, 0xc3, 0x6f, 0x12, 0x2f, 0x06, 0xc3, 0xf5, 0x92, + 0x97, 0xb3, 0x8d, 0x59, 0x08, 0x87, 0xc3, 0x66, 0x52, 0xcc, 0x96, 0x10, 0xe6, 0xba, 0x9c, 0x1f, 0x0e, 0x5d, 0x2d, + 0x5b, 0x0b, 0x0f, 0x1e, 0xaa, 0x16, 0x6e, 0x1a, 0x96, 0xc3, 0xcf, 0x64, 0x16, 0x63, 0xfb, 0x1a, 0x9f, 0xd9, 0x9f, + 0x2f, 0xba, 0x67, 0x09, 0x92, 0x6f, 0xac, 0x81, 0x76, 0x6c, 0xd6, 0xee, 0x70, 0x35, 0x02, 0x92, 0xd2, 0xdd, 0xe8, + 0xef, 0xca, 0x4e, 0x9e, 0x12, 0xe4, 0x8e, 0x56, 0x60, 0xbf, 0xfb, 0xc6, 0x9f, 0x68, 0xb1, 0x07, 0xed, 0x36, 0xb6, + 0x84, 0xa8, 0xa6, 0x3d, 0x97, 0x2b, 0xc5, 0xd2, 0xbc, 0x95, 0x36, 0x7a, 0x3e, 0xac, 0xcf, 0x7d, 0x23, 0x07, 0x0a, + 0xc6, 0x88, 0xa7, 0xd6, 0x41, 0x34, 0x9b, 0x03, 0x0d, 0x06, 0x9a, 0x47, 0x78, 0x6a, 0xa1, 0x83, 0x32, 0x6b, 0xc3, + 0x7e, 0x92, 0x9c, 0x2c, 0x8f, 0xc3, 0xb7, 0xf0, 0x2f, 0x9f, 0x61, 0x93, 0x98, 0x62, 0x7b, 0xfc, 0xad, 0x52, 0x54, + 0x78, 0x6c, 0x41, 0x5c, 0x6b, 0x37, 0xa2, 0x36, 0x54, 0x0e, 0xff, 0x12, 0xf6, 0x11, 0xf6, 0x1b, 0x9a, 0x20, 0x0c, + 0x76, 0xfd, 0x99, 0x40, 0x88, 0x58, 0x88, 0x17, 0xfc, 0xad, 0x92, 0x54, 0x74, 0xc2, 0x67, 0x8b, 0x12, 0x78, 0xeb, + 0x30, 0xa0, 0x4f, 0x28, 0x52, 0x0a, 0x61, 0x68, 0x26, 0xf4, 0x8e, 0xfe, 0x1b, 0xb1, 0x93, 0x4d, 0x72, 0x2b, 0xe4, + 0x03, 0x49, 0x25, 0xc1, 0x04, 0x2b, 0x2f, 0x94, 0x2f, 0xdc, 0x0b, 0xa5, 0xd6, 0x5a, 0xd0, 0xfa, 0xe5, 0x4f, 0x12, + 0xcf, 0xe0, 0xef, 0x81, 0x8c, 0x41, 0xb7, 0x11, 0xd5, 0x24, 0xc7, 0xf4, 0x51, 0x3a, 0xcf, 0x40, 0x05, 0x74, 0xb6, + 0xce, 0xc2, 0x7a, 0x59, 0x94, 0xab, 0x56, 0xa4, 0xa8, 0x2c, 0x7d, 0xa4, 0x1e, 0x63, 0x5e, 0x98, 0x27, 0x27, 0xf2, + 0xc1, 0x23, 0x00, 0xc6, 0xa3, 0x3c, 0xad, 0x3a, 0x4a, 0xeb, 0x07, 0x96, 0x01, 0x23, 0x70, 0xa2, 0x0c, 0x78, 0x84, + 0x65, 0x60, 0x9e, 0x76, 0x19, 0x6a, 0x10, 0x6b, 0x54, 0x5d, 0xa9, 0x0d, 0xe6, 0x44, 0x51, 0xf2, 0x29, 0x96, 0x56, + 0x18, 0x43, 0x53, 0x57, 0x1e, 0x59, 0x2f, 0x39, 0x61, 0x4f, 0x76, 0x03, 0xe9, 0x16, 0x36, 0x0a, 0x67, 0xd0, 0xb5, + 0x2c, 0x51, 0x2e, 0xba, 0x65, 0x44, 0x99, 0x08, 0xa9, 0x9f, 0x3d, 0x9c, 0x69, 0xb5, 0xdf, 0xd8, 0x49, 0xfb, 0xf6, + 0x48, 0xd1, 0x0b, 0x06, 0xed, 0xd3, 0x1e, 0x29, 0xf5, 0xac, 0x91, 0xcb, 0xc0, 0x96, 0x2e, 0x55, 0x3d, 0xff, 0x05, + 0xca, 0x77, 0x30, 0x33, 0xce, 0x66, 0xbf, 0xeb, 0xcd, 0xed, 0xc9, 0xbe, 0x6e, 0x7e, 0x67, 0xbd, 0x1e, 0x6c, 0x0d, + 0x32, 0xf1, 0x85, 0x62, 0xa1, 0xb2, 0x0a, 0xb1, 0x82, 0xb4, 0xff, 0x25, 0xbc, 0xdf, 0xe1, 0xad, 0x11, 0x9a, 0x95, + 0xf1, 0x30, 0x1f, 0x3d, 0xd9, 0x8b, 0xe6, 0xf7, 0xce, 0xb2, 0xad, 0x5c, 0x95, 0xcc, 0xf6, 0xfb, 0x51, 0xd2, 0x9c, + 0x3d, 0x5e, 0x23, 0xa9, 0x03, 0x7c, 0xbc, 0x3e, 0xc3, 0x47, 0x2a, 0xa1, 0xd4, 0x82, 0xaa, 0x06, 0xad, 0x8f, 0xfd, + 0xde, 0x7a, 0x4e, 0x1f, 0x3f, 0x96, 0xd3, 0x2d, 0x29, 0xc2, 0xf8, 0x81, 0xc1, 0x94, 0x9d, 0x38, 0x75, 0xc9, 0x9b, + 0x21, 0xbd, 0xeb, 0x56, 0x49, 0x5d, 0xf6, 0x28, 0x11, 0x84, 0x3a, 0x58, 0xbf, 0xd8, 0x0f, 0x61, 0x66, 0x8b, 0xfe, + 0xb0, 0x59, 0xcd, 0x09, 0x10, 0x11, 0xd0, 0x5a, 0xe5, 0x7d, 0xe0, 0x98, 0x2f, 0xcc, 0x9a, 0x1b, 0xd2, 0xad, 0x37, + 0x57, 0xda, 0x2b, 0x29, 0xa0, 0x9f, 0x83, 0xcc, 0xed, 0xa3, 0x5b, 0xae, 0x5a, 0xe6, 0xb9, 0xb4, 0xe5, 0x80, 0x45, + 0x0b, 0x81, 0x9a, 0x9d, 0x4b, 0x87, 0x03, 0x05, 0xa1, 0xae, 0x44, 0x15, 0x71, 0x75, 0x14, 0x2d, 0x44, 0xad, 0x56, + 0xed, 0x72, 0xb2, 0xa9, 0x90, 0x2d, 0x89, 0x20, 0xa3, 0x64, 0xaf, 0x84, 0xfa, 0x28, 0x57, 0x7b, 0xa6, 0xe1, 0x00, + 0x4d, 0xc0, 0xa6, 0x0d, 0xfe, 0x16, 0xb8, 0x97, 0xc1, 0x99, 0x69, 0x9f, 0x86, 0x11, 0x70, 0x9a, 0x43, 0xcc, 0x9f, + 0xdf, 0xf5, 0xa0, 0x82, 0x07, 0x1d, 0xe9, 0xaf, 0xeb, 0x59, 0x81, 0x67, 0xee, 0x89, 0xe7, 0x6f, 0x4e, 0xa4, 0x17, + 0x39, 0x3c, 0xd0, 0x34, 0x88, 0x19, 0x7f, 0x51, 0x96, 0xe1, 0x6e, 0xb4, 0x2c, 0x8b, 0x95, 0x17, 0xe9, 0x7d, 0x3c, + 0x93, 0x62, 0x20, 0x31, 0x63, 0x66, 0x74, 0x15, 0xeb, 0x38, 0x87, 0x71, 0x6f, 0x4f, 0xc2, 0x0a, 0xed, 0x9f, 0x25, + 0xf6, 0xba, 0x00, 0x2c, 0x87, 0xac, 0x41, 0x2b, 0xbc, 0xd3, 0xed, 0xed, 0x1e, 0x97, 0xec, 0x28, 0x6e, 0x00, 0xfd, + 0xac, 0x86, 0x96, 0x09, 0x6a, 0x99, 0x75, 0x27, 0x93, 0x29, 0x92, 0xcb, 0xb7, 0x61, 0x6f, 0x58, 0x91, 0xcf, 0x1b, + 0xb9, 0x3d, 0xbc, 0x0f, 0x57, 0x22, 0xd6, 0x16, 0x74, 0xd2, 0x91, 0x71, 0xb8, 0x17, 0x9a, 0x1b, 0xe9, 0xfe, 0x49, + 0x95, 0x84, 0xa5, 0x88, 0xe1, 0x16, 0xc8, 0xf6, 0x6a, 0x5b, 0x09, 0x4a, 0xe0, 0x83, 0xfd, 0x58, 0x8a, 0x65, 0xba, + 0x15, 0x80, 0xeb, 0xc0, 0xff, 0x94, 0x88, 0x84, 0xee, 0xce, 0x43, 0x14, 0x6b, 0xe4, 0x7d, 0x83, 0x68, 0xec, 0xaf, + 0x41, 0x4e, 0x03, 0x32, 0x91, 0x62, 0x24, 0x0b, 0x06, 0x3e, 0x80, 0x9c, 0xaf, 0xc1, 0x24, 0x37, 0xcd, 0x3d, 0x3f, + 0xc8, 0x75, 0x07, 0xd3, 0x3e, 0xe8, 0x5e, 0x5c, 0x6b, 0x96, 0x83, 0x57, 0x4c, 0xc4, 0xff, 0x56, 0x7b, 0x25, 0xcb, + 0x59, 0xe6, 0x37, 0xe6, 0xa2, 0x93, 0xc1, 0x55, 0x43, 0xf8, 0xc5, 0x2c, 0x9b, 0xf3, 0x68, 0x96, 0xe9, 0xa8, 0xff, + 0xa2, 0x39, 0x2a, 0x05, 0xe0, 0xd4, 0xf1, 0x02, 0xac, 0xa1, 0xaf, 0x74, 0xd3, 0x8a, 0x47, 0x1a, 0x63, 0x14, 0x54, + 0xe8, 0x20, 0xf4, 0xb7, 0x1a, 0x90, 0x36, 0x98, 0xa4, 0x49, 0xa8, 0x7c, 0x70, 0x41, 0x37, 0xcc, 0xcb, 0x95, 0xcb, + 0x55, 0x93, 0xaa, 0xe5, 0x97, 0x23, 0xea, 0xbb, 0x5a, 0x72, 0xa9, 0x36, 0x9f, 0x1a, 0x65, 0x8d, 0x20, 0x93, 0xa3, + 0xf4, 0xfb, 0x94, 0x0b, 0xb7, 0x32, 0x26, 0xeb, 0xc3, 0xc1, 0x2b, 0xb8, 0xa9, 0xf1, 0xeb, 0x9c, 0x08, 0x45, 0xed, + 0x21, 0x11, 0xb6, 0x76, 0x2b, 0x74, 0xef, 0x71, 0xa3, 0x34, 0x8f, 0xb2, 0x4d, 0x2c, 0x2a, 0xaf, 0x97, 0x80, 0xb5, + 0xb8, 0x07, 0xbc, 0xa8, 0xb4, 0xf4, 0x2b, 0x56, 0x00, 0x7a, 0x80, 0x14, 0x36, 0x7e, 0x44, 0x06, 0xac, 0x8f, 0x5e, + 0xea, 0xf7, 0xfb, 0xc6, 0x94, 0xff, 0xe1, 0x21, 0x07, 0x92, 0x42, 0x51, 0xd6, 0x3b, 0x98, 0x40, 0x70, 0xed, 0x24, + 0xed, 0x59, 0xcd, 0xaf, 0xd7, 0xb5, 0x07, 0xfc, 0x56, 0xbe, 0x45, 0x62, 0xf5, 0xda, 0xbe, 0xd8, 0xec, 0xd3, 0xea, + 0xc6, 0x68, 0x1c, 0x04, 0x4b, 0xab, 0xb7, 0x5a, 0xe5, 0x90, 0x37, 0xbc, 0x02, 0x91, 0xca, 0xba, 0xba, 0x56, 0xce, + 0xd5, 0xb5, 0xe0, 0xc8, 0x25, 0x5b, 0xf2, 0x1c, 0xfe, 0x0b, 0xb9, 0x57, 0x1e, 0x0e, 0x85, 0xdf, 0xef, 0xa7, 0x33, + 0xd2, 0xca, 0x02, 0x7b, 0xda, 0xba, 0xf6, 0x42, 0xff, 0x70, 0xf8, 0x11, 0xbc, 0x46, 0xfc, 0xc3, 0xa1, 0xec, 0xf7, + 0x3f, 0x99, 0x9b, 0xcc, 0xf9, 0x58, 0x29, 0x65, 0x2f, 0x51, 0xe9, 0xfe, 0x36, 0xe1, 0xbd, 0xff, 0x3d, 0xfa, 0xdf, + 0xa3, 0xcb, 0x9e, 0x0a, 0x01, 0x4b, 0xf8, 0x0c, 0x6f, 0xe8, 0x4c, 0x5d, 0xce, 0x99, 0x74, 0x77, 0x57, 0x7e, 0xe8, + 0x3d, 0x0d, 0x15, 0xdf, 0x9b, 0x9b, 0x36, 0xfe, 0x5a, 0x1d, 0x69, 0x12, 0x3a, 0x2e, 0xfa, 0x87, 0xc3, 0xe7, 0x44, + 0xeb, 0xd3, 0x52, 0xa5, 0x4f, 0x53, 0x38, 0x4a, 0x86, 0x18, 0xd7, 0x2d, 0x4c, 0x07, 0xf6, 0xe3, 0xe6, 0xab, 0xe4, + 0xc5, 0x59, 0x0a, 0xd7, 0xde, 0x7c, 0x96, 0xce, 0xa7, 0x60, 0x5d, 0x19, 0xe6, 0xb3, 0x7a, 0x1e, 0x40, 0xea, 0x10, + 0xd2, 0xac, 0x69, 0xf8, 0x97, 0xca, 0x15, 0xbc, 0xb5, 0xc7, 0xbb, 0x81, 0x8b, 0x52, 0x47, 0xfa, 0xa4, 0x8d, 0xa6, + 0x4b, 0x2a, 0xf9, 0x4f, 0x22, 0x8f, 0x31, 0x66, 0xe3, 0x35, 0xf1, 0x7e, 0x16, 0xf9, 0xab, 0x02, 0xb0, 0x8b, 0x00, + 0x0c, 0x39, 0x9d, 0x3b, 0x92, 0xf8, 0xcf, 0xc9, 0xf7, 0x7f, 0x4c, 0x97, 0xf6, 0xb1, 0x2c, 0xee, 0x4a, 0x51, 0x55, + 0x47, 0xa5, 0xed, 0x6c, 0xb9, 0x1e, 0x98, 0x44, 0xfb, 0x7d, 0xc9, 0x24, 0x9a, 0x62, 0x28, 0x0a, 0xdc, 0x1a, 0x7b, + 0xd3, 0x94, 0x2b, 0xc6, 0xea, 0x91, 0xb1, 0x7e, 0xbe, 0xdc, 0xbd, 0x8d, 0xbd, 0xd4, 0x0f, 0x52, 0x10, 0x84, 0x35, + 0x94, 0x52, 0x8a, 0x7c, 0x70, 0x3e, 0xc3, 0x54, 0xa2, 0xd6, 0xa5, 0x54, 0xf9, 0xc3, 0x48, 0xf3, 0x61, 0x0a, 0x7a, + 0xd9, 0xbf, 0x57, 0x30, 0xff, 0x75, 0x7b, 0xb0, 0x3e, 0xad, 0xcb, 0x34, 0xaa, 0x88, 0x2a, 0x2f, 0x4c, 0xb5, 0x09, + 0x44, 0xf0, 0x6b, 0x61, 0xf1, 0xfd, 0xfa, 0xe4, 0x48, 0xd0, 0x98, 0xc9, 0xf2, 0xe9, 0xc8, 0xfd, 0xc2, 0xbe, 0x72, + 0x1d, 0xcf, 0xff, 0xdc, 0xcc, 0xff, 0x01, 0x3a, 0x43, 0x16, 0xd7, 0xdc, 0x32, 0x58, 0xe0, 0xec, 0x97, 0xae, 0x1e, + 0xf0, 0x37, 0xf3, 0xc4, 0x35, 0xd0, 0x31, 0x5f, 0xa3, 0xab, 0x62, 0x3a, 0x2b, 0x06, 0xc0, 0x65, 0xeb, 0x37, 0xd6, + 0x9c, 0x78, 0x63, 0x51, 0x5e, 0xc9, 0x05, 0xa1, 0xaf, 0xab, 0x30, 0x1b, 0x57, 0xc5, 0xa6, 0x12, 0xc5, 0xa6, 0xee, + 0x91, 0x5a, 0x36, 0x9f, 0xd6, 0xb6, 0x42, 0xf6, 0xaf, 0xa2, 0xc5, 0xe0, 0x65, 0x58, 0x27, 0xa3, 0x2c, 0x5d, 0x4f, + 0x81, 0x5f, 0x2f, 0x80, 0xb3, 0xc8, 0xbc, 0xf2, 0xd5, 0xd9, 0x03, 0xb6, 0x68, 0x3c, 0x05, 0x72, 0x54, 0xfa, 0x23, + 0x6f, 0x8c, 0x4e, 0x4f, 0xf4, 0xfb, 0xf9, 0x94, 0x62, 0xbe, 0xfe, 0x0a, 0xf0, 0x5c, 0xb5, 0x5c, 0x80, 0xbe, 0x0c, + 0x75, 0x50, 0x89, 0x52, 0x2b, 0x86, 0x11, 0x0b, 0x7f, 0x15, 0x48, 0xe4, 0x4c, 0x81, 0xcd, 0x2a, 0x4a, 0x42, 0x25, + 0x2a, 0x25, 0x5b, 0x13, 0xd4, 0xd2, 0xfb, 0xa2, 0xac, 0xf7, 0x15, 0x38, 0x4a, 0x46, 0xda, 0x2c, 0x27, 0xcd, 0xb8, + 0x02, 0x65, 0x2e, 0xfa, 0xc1, 0xfe, 0x55, 0x79, 0x7e, 0x23, 0xf3, 0x59, 0xee, 0x3b, 0x3a, 0xa7, 0xed, 0xb8, 0x40, + 0x99, 0x5b, 0x4e, 0x5b, 0x2d, 0x79, 0x4c, 0xde, 0xb3, 0x60, 0xdb, 0x7f, 0x91, 0x20, 0xc5, 0x22, 0xcc, 0x27, 0x54, + 0xd9, 0xfc, 0x1d, 0x42, 0x6d, 0x71, 0x60, 0x8f, 0x5d, 0x98, 0x88, 0xff, 0x16, 0x2c, 0x89, 0x61, 0x56, 0x8a, 0x30, + 0xde, 0x81, 0xf7, 0xcf, 0xa6, 0x12, 0xa3, 0x33, 0x74, 0x72, 0x3f, 0x7b, 0x48, 0xeb, 0xe4, 0xec, 0xed, 0xeb, 0xb3, + 0x1f, 0x7a, 0x83, 0x62, 0x94, 0xc6, 0x83, 0xde, 0x0f, 0x67, 0xab, 0x0d, 0xa0, 0x65, 0x8a, 0xb3, 0x98, 0x4c, 0x69, + 0x22, 0x3e, 0x23, 0xc3, 0xe0, 0x59, 0x9d, 0x88, 0x33, 0x9a, 0x98, 0xee, 0x6b, 0x94, 0x26, 0xdf, 0x8e, 0xc2, 0x1c, + 0x5e, 0x2e, 0xc5, 0xa6, 0x12, 0x31, 0xd8, 0x29, 0xd5, 0x3c, 0xcb, 0xdb, 0x67, 0x71, 0x3e, 0xea, 0x90, 0x55, 0x3a, + 0xf0, 0xb7, 0x27, 0xd2, 0xae, 0x4a, 0x57, 0x40, 0xe8, 0x01, 0x70, 0xd2, 0x95, 0x3f, 0x0f, 0x07, 0x91, 0x40, 0xa8, + 0x05, 0x73, 0x32, 0x8d, 0xe8, 0x86, 0xf4, 0x0a, 0xfb, 0x0c, 0xcc, 0x42, 0x4a, 0xf3, 0xe0, 0xe6, 0x6a, 0x31, 0x74, + 0x57, 0xac, 0x1c, 0x85, 0xd5, 0x5a, 0x44, 0x35, 0xb2, 0x1e, 0x83, 0xf3, 0x0e, 0x44, 0x00, 0x28, 0x72, 0xf0, 0x8c, + 0x47, 0xfd, 0x7e, 0xa4, 0x82, 0x72, 0x12, 0xfa, 0x45, 0xa1, 0x5f, 0x1a, 0x8e, 0x32, 0xe6, 0xef, 0x43, 0xcd, 0x11, + 0x50, 0x6f, 0x79, 0xa8, 0xe8, 0x02, 0x70, 0x39, 0x47, 0xcc, 0x38, 0xef, 0x71, 0x17, 0x98, 0x53, 0x51, 0x50, 0xa8, + 0xeb, 0x60, 0xa9, 0x00, 0xe8, 0x4d, 0x7d, 0xa4, 0xe7, 0xa4, 0x49, 0xd0, 0x78, 0x6e, 0xe0, 0xf1, 0x6a, 0xb8, 0xa8, + 0x56, 0x42, 0xea, 0x2d, 0x74, 0x4a, 0x55, 0x87, 0x40, 0x20, 0xf0, 0x7f, 0x78, 0xfb, 0x16, 0xee, 0xb6, 0x6d, 0x6c, + 0xdd, 0xbf, 0x62, 0xf1, 0xa6, 0x2a, 0x11, 0x41, 0xb2, 0xe4, 0x24, 0x9d, 0x29, 0x65, 0x58, 0xc7, 0xcd, 0xa3, 0x4d, + 0xa7, 0x89, 0xd3, 0x38, 0xed, 0x74, 0xaa, 0xab, 0xe3, 0xd2, 0x24, 0x6c, 0xb1, 0xa1, 0x01, 0x95, 0xa4, 0xfc, 0x88, + 0xc4, 0xff, 0x7e, 0xd7, 0xde, 0x78, 0x92, 0xa2, 0x9d, 0xcc, 0xdc, 0x73, 0xef, 0xca, 0x5a, 0xb1, 0x08, 0x82, 0x78, + 0x63, 0x63, 0x63, 0x3f, 0xbe, 0xdd, 0x8c, 0x19, 0x76, 0xcb, 0x5d, 0x8e, 0x64, 0x5d, 0x14, 0x5c, 0xec, 0x04, 0x86, + 0x6e, 0xc6, 0x25, 0x33, 0x07, 0x57, 0x33, 0xac, 0x93, 0x8a, 0x02, 0xec, 0xea, 0x02, 0x64, 0x2f, 0x0c, 0x75, 0xdd, + 0xcc, 0x96, 0xeb, 0xc0, 0xd7, 0xa5, 0x0b, 0x5f, 0x52, 0xf0, 0x72, 0x25, 0x45, 0x99, 0x5d, 0xf3, 0x9f, 0xec, 0xcb, + 0x66, 0x2c, 0x29, 0xb4, 0x23, 0x7d, 0xd3, 0xee, 0x8e, 0x16, 0xe3, 0xd8, 0x72, 0x7c, 0x4b, 0xa5, 0x3b, 0x3d, 0xaa, + 0x5e, 0x08, 0x6d, 0x9d, 0x6b, 0x99, 0xa5, 0x29, 0x17, 0xaf, 0x45, 0x9a, 0x25, 0x5e, 0x72, 0xac, 0x63, 0x55, 0xbb, + 0x20, 0x58, 0x2e, 0x4c, 0xf2, 0x8b, 0xac, 0xc4, 0xd8, 0xc1, 0x8d, 0x46, 0xb5, 0xa2, 0x4e, 0x99, 0x18, 0x18, 0xf2, + 0x3d, 0x06, 0xdf, 0x66, 0x65, 0x02, 0x0c, 0x3f, 0x26, 0xea, 0x4b, 0x7a, 0x0a, 0x01, 0x1f, 0x54, 0x68, 0xee, 0x17, + 0x1c, 0xc1, 0xaf, 0xad, 0xca, 0x1c, 0x98, 0x6c, 0xad, 0x82, 0x44, 0xdc, 0xbb, 0x6c, 0xae, 0x17, 0xd1, 0x42, 0xdd, + 0x85, 0x7a, 0xf1, 0x76, 0xdb, 0x4b, 0x14, 0x1d, 0x70, 0xf2, 0xd3, 0xe0, 0x55, 0x9c, 0xe5, 0x3c, 0xdd, 0xab, 0xe4, + 0x9e, 0xda, 0x50, 0x7b, 0xca, 0x99, 0x03, 0x76, 0xde, 0xd7, 0xd5, 0x9e, 0x5e, 0xd3, 0x7b, 0xba, 0x9d, 0x7b, 0x70, + 0xc1, 0xc0, 0x9d, 0x7b, 0x99, 0x5d, 0x73, 0xb1, 0x07, 0xca, 0x40, 0x6b, 0x3c, 0x50, 0x97, 0xd5, 0x48, 0x4d, 0x8c, + 0x8e, 0x61, 0x9d, 0xe8, 0x83, 0x39, 0xa0, 0xdf, 0x43, 0x58, 0xfb, 0xd6, 0xdb, 0x95, 0x3e, 0x68, 0x03, 0xfa, 0xd3, + 0xd2, 0xf4, 0x41, 0x07, 0x8e, 0x57, 0xd1, 0x81, 0x1b, 0x43, 0xaa, 0x41, 0x5b, 0x8d, 0xac, 0x02, 0xc5, 0x1b, 0xde, + 0xe2, 0xdd, 0xb9, 0x96, 0x6c, 0xbc, 0x97, 0x88, 0xf1, 0x95, 0x89, 0x2a, 0xce, 0xc4, 0xb1, 0x97, 0xca, 0x6b, 0xed, + 0x24, 0x23, 0x8c, 0x6f, 0x59, 0x49, 0xfd, 0x1d, 0x62, 0x6e, 0x91, 0xe6, 0x30, 0x78, 0x19, 0x56, 0x64, 0xc6, 0xfb, + 0x7d, 0x39, 0x93, 0x51, 0x39, 0x13, 0xfb, 0x65, 0xa4, 0xc0, 0xda, 0xee, 0x13, 0x01, 0x3d, 0x28, 0x01, 0xf2, 0x05, + 0x40, 0xd5, 0x43, 0xc2, 0x9f, 0x87, 0xa4, 0x3e, 0x9d, 0x42, 0x9f, 0x42, 0x5b, 0xaf, 0xb8, 0x82, 0x78, 0x55, 0x37, + 0x46, 0xb6, 0x51, 0x41, 0x8b, 0xc7, 0xf2, 0xac, 0x36, 0x8c, 0xcd, 0xa9, 0xf5, 0xaf, 0x37, 0x1b, 0x4c, 0xd9, 0x5c, + 0xa8, 0x55, 0x18, 0x92, 0xe8, 0xa6, 0xf4, 0x22, 0x89, 0x58, 0xd8, 0xac, 0xd6, 0xe6, 0x37, 0x61, 0x40, 0x32, 0x91, + 0xe2, 0x7e, 0xb6, 0xc4, 0xb9, 0x8b, 0xc7, 0xf3, 0xaa, 0xaf, 0xb5, 0xb4, 0xc8, 0xb4, 0xf9, 0x4e, 0x5f, 0x86, 0x34, + 0x15, 0x35, 0xa4, 0x51, 0x67, 0x06, 0xdd, 0xb7, 0xcb, 0x5b, 0x56, 0x23, 0x4c, 0x80, 0x57, 0x3a, 0x83, 0x6e, 0x34, + 0x1e, 0x88, 0x65, 0x35, 0x2a, 0xd6, 0x42, 0x20, 0xf0, 0x30, 0xe4, 0x98, 0x59, 0x42, 0x92, 0x7d, 0xe2, 0xdf, 0xa9, + 0x38, 0x0b, 0x45, 0x7c, 0x63, 0x90, 0xbd, 0x2b, 0xeb, 0xda, 0x5d, 0x47, 0x7e, 0x4e, 0x2c, 0xac, 0xf6, 0x1f, 0x9a, + 0x47, 0xad, 0x71, 0x16, 0xd0, 0xd6, 0xb4, 0xba, 0xe1, 0x70, 0x8f, 0xea, 0x58, 0x94, 0x06, 0x9b, 0xd8, 0x23, 0xcb, + 0x45, 0xeb, 0x98, 0x41, 0x03, 0xfa, 0xdb, 0xec, 0x6a, 0x7d, 0x85, 0x00, 0x6e, 0x25, 0xb2, 0x4e, 0x52, 0xf9, 0x97, + 0xb4, 0x47, 0x5d, 0xdb, 0x53, 0xf9, 0xdf, 0xb6, 0xa9, 0x72, 0x68, 0x31, 0xe5, 0xb1, 0x9b, 0xb3, 0x40, 0x75, 0x24, + 0x88, 0x02, 0xb5, 0xf5, 0x82, 0xa9, 0x77, 0xca, 0x14, 0x1d, 0x20, 0xd0, 0x85, 0x39, 0xc3, 0xbe, 0xe0, 0x88, 0x31, + 0x4b, 0x25, 0x06, 0x53, 0x1f, 0x63, 0x54, 0xd3, 0x5a, 0x01, 0xba, 0x7e, 0xba, 0x81, 0x3f, 0x51, 0x51, 0xa3, 0xa1, + 0xd6, 0x48, 0x0a, 0x45, 0x13, 0x15, 0x8a, 0x2c, 0x2d, 0x74, 0x5c, 0x85, 0x4e, 0x22, 0x61, 0x09, 0x68, 0x98, 0x10, + 0x9d, 0x54, 0xe0, 0xad, 0x01, 0x9c, 0xf9, 0xb8, 0x28, 0xd7, 0x85, 0x36, 0x98, 0xfb, 0x21, 0xbe, 0xe6, 0xaf, 0x5f, + 0x38, 0xa3, 0xfa, 0x96, 0xb5, 0xbe, 0xa7, 0x05, 0xf9, 0x21, 0xe4, 0x14, 0x1d, 0x98, 0xd8, 0xd1, 0x06, 0x8d, 0x31, + 0xca, 0x5a, 0x47, 0xbd, 0x38, 0xd1, 0xa1, 0x58, 0xb4, 0x09, 0xde, 0x03, 0x9e, 0x22, 0xda, 0xf0, 0x50, 0x18, 0xab, + 0x6a, 0x7c, 0x2a, 0x59, 0x4b, 0x0f, 0x56, 0xf0, 0x74, 0x9d, 0xf0, 0x10, 0xf4, 0x48, 0x84, 0x1d, 0x85, 0xc5, 0x3c, + 0x5e, 0xc0, 0x71, 0x52, 0x10, 0x50, 0x3b, 0xe8, 0x2b, 0xf8, 0x7c, 0x81, 0xee, 0xaf, 0x12, 0x3d, 0xc0, 0xd0, 0x82, + 0xb8, 0x19, 0x05, 0x75, 0x74, 0x15, 0xaf, 0x1a, 0x2a, 0x12, 0x3e, 0x2f, 0xc0, 0x76, 0x48, 0xa9, 0xa7, 0x40, 0x0b, + 0x95, 0x28, 0xfd, 0x30, 0xf0, 0x1d, 0x1a, 0x03, 0x5b, 0xeb, 0x00, 0x0d, 0xfd, 0x8c, 0x69, 0x6a, 0x9d, 0xa1, 0xf2, + 0x99, 0x77, 0xcf, 0x8c, 0x96, 0x33, 0x8b, 0xc6, 0xa0, 0x6f, 0xa3, 0x29, 0x8a, 0x73, 0xf2, 0x59, 0x50, 0xc4, 0x69, + 0x16, 0xe7, 0xe0, 0xb7, 0x19, 0x17, 0x98, 0x31, 0x89, 0x2b, 0x7e, 0x29, 0x0b, 0xd0, 0x76, 0xe7, 0x2a, 0xb5, 0xae, + 0x41, 0x40, 0xf6, 0x03, 0x58, 0xbd, 0x34, 0x74, 0x54, 0xce, 0xbb, 0x4b, 0x9b, 0x42, 0xc4, 0x22, 0x04, 0x9b, 0x66, + 0xba, 0x64, 0xc7, 0xa1, 0xd2, 0xe6, 0x40, 0xa8, 0x23, 0x34, 0xee, 0x9f, 0x86, 0xb1, 0xd5, 0x14, 0x5b, 0xbb, 0xb7, + 0xed, 0xf6, 0xb7, 0xd2, 0x4b, 0xa7, 0x39, 0xe9, 0x31, 0xf6, 0x5b, 0x19, 0x16, 0x23, 0xdb, 0x11, 0x02, 0x4b, 0xce, + 0xfb, 0xd4, 0x7f, 0x45, 0xcb, 0x79, 0x02, 0xa6, 0x23, 0x3a, 0x58, 0x2e, 0x50, 0x76, 0x0c, 0xe8, 0x0e, 0x0c, 0xae, + 0xe8, 0xf7, 0xc1, 0x2a, 0xc3, 0x5c, 0x48, 0x96, 0x24, 0x65, 0xf0, 0x3c, 0xf5, 0xe0, 0xe0, 0xd7, 0x4c, 0x99, 0xbb, + 0x28, 0xeb, 0xd3, 0x25, 0x99, 0xa6, 0xc8, 0x40, 0xac, 0xc3, 0x4d, 0x96, 0x46, 0x89, 0x12, 0x91, 0x2d, 0xd1, 0x3f, + 0xd2, 0x50, 0x2c, 0x1d, 0xb9, 0x17, 0xa9, 0x12, 0xa1, 0x62, 0x9e, 0xe2, 0x49, 0x9d, 0xd6, 0xe9, 0x08, 0x43, 0x4f, + 0x82, 0x52, 0xae, 0x86, 0x81, 0x2a, 0xa9, 0x5e, 0x0a, 0x9b, 0x62, 0xbb, 0xd5, 0x17, 0x2b, 0x31, 0x8f, 0x17, 0xf8, + 0x52, 0xe0, 0x28, 0xfe, 0x83, 0x7b, 0x61, 0xa7, 0xd4, 0xf6, 0xa0, 0x76, 0x44, 0x09, 0xfd, 0x07, 0x87, 0x8b, 0xc4, + 0x77, 0x52, 0x87, 0x00, 0x44, 0x8b, 0x90, 0x33, 0x75, 0x90, 0x1a, 0x6e, 0x68, 0x47, 0xf8, 0x6f, 0xb8, 0x3e, 0xe3, + 0x8c, 0xde, 0x54, 0x33, 0x6a, 0x28, 0x5f, 0x0f, 0xda, 0x18, 0xf5, 0xd9, 0xc0, 0x61, 0x85, 0x28, 0xb4, 0x61, 0x47, + 0xa5, 0x12, 0x2d, 0x0c, 0xa5, 0xfa, 0x4b, 0xa8, 0x38, 0xe2, 0xce, 0x8c, 0xb2, 0x64, 0x7c, 0x5a, 0x1e, 0x8a, 0xe9, + 0x60, 0x50, 0x92, 0xca, 0x58, 0xe8, 0xc1, 0xf5, 0xc0, 0xf3, 0xef, 0x81, 0x5b, 0x88, 0x87, 0x8c, 0x2c, 0x86, 0xdc, + 0xe0, 0xe4, 0xb7, 0x38, 0xb9, 0x6a, 0x54, 0xaa, 0x38, 0xd6, 0x44, 0xb5, 0xe0, 0x1f, 0x65, 0x18, 0xa0, 0x4f, 0x52, + 0x00, 0x26, 0x83, 0x29, 0xbf, 0x05, 0x89, 0xd2, 0x99, 0xba, 0x21, 0xfd, 0x22, 0x0a, 0x7e, 0xc1, 0x0b, 0x2e, 0x12, + 0x57, 0x80, 0xe5, 0x1d, 0x6c, 0xaf, 0xa3, 0x8a, 0x2a, 0x4c, 0x5e, 0xd3, 0xe3, 0x88, 0x1b, 0xef, 0x3f, 0xd3, 0x63, + 0x8b, 0xd9, 0x6a, 0x1d, 0x1b, 0x7c, 0xe6, 0x18, 0x5c, 0xd0, 0xb5, 0xc4, 0xd6, 0x50, 0x0d, 0x2b, 0x02, 0x03, 0x17, + 0x70, 0x10, 0x96, 0x28, 0x8e, 0xad, 0xe4, 0x15, 0x69, 0x48, 0x69, 0x1f, 0x18, 0x8e, 0x36, 0xc9, 0xf1, 0x6d, 0x96, + 0xdd, 0x04, 0xce, 0x17, 0x9d, 0x93, 0x66, 0xc2, 0xda, 0xe0, 0x7d, 0xde, 0x9c, 0x5f, 0xf7, 0x0f, 0x09, 0x55, 0x71, + 0x6f, 0x78, 0x3b, 0xee, 0x8d, 0x13, 0x7e, 0xcd, 0xc5, 0x42, 0x87, 0x6a, 0x31, 0x97, 0x2c, 0xbf, 0xb5, 0xde, 0x2d, + 0x49, 0x6a, 0x05, 0xb4, 0xcf, 0xb2, 0xa0, 0x26, 0x02, 0x40, 0xfe, 0xf0, 0x17, 0x08, 0x9d, 0xe1, 0x6f, 0x8f, 0xc1, + 0x15, 0x29, 0xbc, 0x77, 0x08, 0x84, 0x35, 0xdd, 0xdc, 0xa9, 0x0d, 0xf8, 0x62, 0xdc, 0x9f, 0x31, 0xf5, 0xf4, 0xdb, + 0x4c, 0xee, 0xea, 0xba, 0x3d, 0xb2, 0x0c, 0x1f, 0xe1, 0x4a, 0x01, 0xdc, 0x4c, 0xf8, 0x8b, 0x61, 0x26, 0xd5, 0x27, + 0x80, 0xa9, 0xa6, 0x83, 0xfb, 0x04, 0x81, 0x01, 0x54, 0xa2, 0xc5, 0xe8, 0x5a, 0x39, 0xa2, 0x19, 0xb8, 0x35, 0xdd, + 0x0a, 0xe3, 0xad, 0x07, 0x2d, 0xf4, 0x4c, 0xc3, 0x89, 0xff, 0xa0, 0x99, 0x57, 0x05, 0x04, 0xd0, 0xca, 0x08, 0xde, + 0x5a, 0x1f, 0xcd, 0x11, 0xe2, 0x13, 0x96, 0x44, 0x13, 0x16, 0xcf, 0x14, 0x3f, 0x26, 0x74, 0xd3, 0xd4, 0x36, 0x7d, + 0x40, 0xfa, 0x8b, 0x6b, 0xd6, 0x4f, 0x59, 0xd6, 0xbe, 0x3d, 0x54, 0xbc, 0x98, 0x36, 0xe3, 0x20, 0x26, 0xaa, 0x18, + 0xff, 0x0b, 0xee, 0x4b, 0xad, 0x00, 0x91, 0xb9, 0xab, 0x9e, 0x7e, 0xbf, 0x99, 0x2d, 0x07, 0x42, 0xe5, 0x77, 0x06, + 0x49, 0x9f, 0x0e, 0xed, 0x07, 0x36, 0x89, 0xda, 0x42, 0xcf, 0x1f, 0x97, 0xba, 0x89, 0x97, 0xd7, 0xa6, 0x46, 0xb4, + 0x42, 0x86, 0xca, 0xd6, 0x01, 0xeb, 0xfb, 0x87, 0x70, 0x77, 0x51, 0xd3, 0x50, 0xeb, 0x9e, 0xbb, 0x16, 0x05, 0x27, + 0xfe, 0x00, 0x63, 0x71, 0x21, 0xa9, 0x75, 0x3c, 0x26, 0xfd, 0x68, 0x21, 0x93, 0x1b, 0x75, 0x75, 0x72, 0xa6, 0x98, + 0x27, 0x70, 0x01, 0x2e, 0xdb, 0xfe, 0x8a, 0x4a, 0x5d, 0xca, 0xed, 0x15, 0xa5, 0xe9, 0x21, 0x6d, 0xaf, 0xe2, 0xbc, + 0x2d, 0xb8, 0xe0, 0x5f, 0x28, 0xb8, 0xb0, 0x0e, 0xd6, 0x1d, 0x77, 0xca, 0x9e, 0xf0, 0x44, 0x99, 0xd6, 0x06, 0x77, + 0xdd, 0x60, 0x4c, 0x8c, 0xfd, 0xee, 0x92, 0x27, 0x1f, 0x91, 0x05, 0xff, 0x2e, 0x13, 0xe0, 0x99, 0xec, 0x5e, 0xa9, + 0xfc, 0x3f, 0xf8, 0x57, 0x5b, 0xfb, 0xce, 0x9a, 0x7f, 0x7a, 0xd6, 0xc3, 0x9d, 0xc3, 0xe4, 0xc7, 0xea, 0x0c, 0xe8, + 0xe6, 0x4a, 0xa6, 0x1c, 0x90, 0x01, 0xac, 0x45, 0x32, 0x1a, 0xf0, 0xa1, 0x95, 0x65, 0xdb, 0x77, 0x5a, 0x5d, 0x10, + 0xee, 0x25, 0x70, 0xd3, 0xfb, 0x6b, 0x33, 0x33, 0xa7, 0x6b, 0x25, 0x9a, 0x2e, 0x8d, 0xad, 0x65, 0xa9, 0xc2, 0x78, + 0xbf, 0xf7, 0x24, 0x9b, 0xe6, 0x87, 0xcb, 0x69, 0x6e, 0xa9, 0xdb, 0xc6, 0x2d, 0x1b, 0x40, 0x43, 0xec, 0x5a, 0x5b, + 0x39, 0xe0, 0xe5, 0xf6, 0x20, 0x9a, 0xaf, 0x15, 0xa1, 0xa7, 0x4a, 0x84, 0x3e, 0x4d, 0x9b, 0x7d, 0xb0, 0xab, 0x6a, + 0xdd, 0x08, 0x79, 0x34, 0x48, 0x35, 0x23, 0x7f, 0x72, 0xcd, 0x8b, 0x8b, 0x5c, 0xde, 0x00, 0x1c, 0x32, 0xa9, 0x8d, + 0xc2, 0xf2, 0x0a, 0xdc, 0xf9, 0xd1, 0x71, 0x9c, 0x89, 0x51, 0x8e, 0x71, 0x5b, 0x11, 0x29, 0x59, 0x27, 0xce, 0x00, + 0x0f, 0xd9, 0x9f, 0x34, 0x1d, 0xda, 0xb5, 0xc0, 0xf0, 0xbe, 0xc0, 0x5d, 0xe5, 0xec, 0x68, 0x93, 0xdb, 0x45, 0xdf, + 0x9c, 0x61, 0xdd, 0x91, 0xd2, 0xda, 0x58, 0x74, 0xdd, 0xc1, 0x5a, 0x33, 0x68, 0x8b, 0x50, 0xf2, 0x21, 0x77, 0xd2, + 0x7e, 0x0a, 0x68, 0x70, 0x96, 0xa5, 0xb7, 0xd6, 0x2a, 0x7f, 0xa3, 0x85, 0x38, 0x51, 0x4c, 0x9d, 0xf8, 0x26, 0x4a, + 0xf4, 0xf9, 0x99, 0x18, 0x37, 0x10, 0x48, 0xfd, 0x01, 0xe3, 0x6b, 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, + 0xee, 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, 0xdb, 0x6d, 0xaf, 0x77, + 0xaf, 0x88, 0xab, 0xc7, 0x58, 0xe5, 0xdd, 0xcc, 0xed, 0x9d, 0x6a, 0x2d, 0x76, 0x6f, 0xda, 0x7e, 0x8a, 0x1d, 0xb5, + 0xd6, 0x6e, 0x37, 0x9c, 0x50, 0x43, 0xbe, 0x15, 0x55, 0x5a, 0x9d, 0x6e, 0x0c, 0xda, 0x21, 0xb4, 0xb5, 0xc8, 0xe0, + 0x46, 0xf9, 0xc2, 0x09, 0x9d, 0x54, 0xc8, 0x55, 0xa7, 0x2e, 0xd8, 0x5c, 0xf1, 0x6a, 0x29, 0xd3, 0x48, 0x50, 0xb4, + 0x39, 0x8f, 0x4a, 0x9a, 0xc8, 0xb5, 0xa8, 0x22, 0x59, 0xa3, 0x5e, 0xd4, 0x6a, 0x0c, 0x10, 0x90, 0xe9, 0xac, 0xe9, + 0x41, 0x15, 0xcc, 0x86, 0x32, 0x92, 0xd3, 0xf7, 0x60, 0x69, 0x8f, 0x1c, 0x6b, 0x7d, 0x5f, 0x9d, 0x2d, 0xbe, 0xd5, + 0x13, 0x82, 0x29, 0xcc, 0x1e, 0x88, 0x08, 0xd7, 0x34, 0x86, 0x9c, 0x76, 0x89, 0xcb, 0x9a, 0x6e, 0x09, 0xf7, 0x70, + 0xbb, 0x92, 0x1d, 0xb9, 0x79, 0xd2, 0xdc, 0x5c, 0xc1, 0x8e, 0x8a, 0xf9, 0x18, 0xb4, 0x5f, 0x52, 0x5d, 0xbb, 0x34, + 0xb7, 0x1e, 0x0f, 0x02, 0x1a, 0x0c, 0x0a, 0xc3, 0xbf, 0x4e, 0x8c, 0x87, 0x27, 0x0d, 0x08, 0x92, 0x72, 0x11, 0x8e, + 0x7d, 0x23, 0xfa, 0xc9, 0x54, 0x1e, 0x72, 0xb4, 0x78, 0x87, 0x56, 0x27, 0x10, 0xd0, 0x4b, 0x84, 0x92, 0x18, 0x55, + 0xa1, 0x11, 0x41, 0x79, 0x5a, 0xfe, 0x52, 0x55, 0x87, 0x80, 0x42, 0xda, 0x57, 0x14, 0xca, 0x36, 0x89, 0xa1, 0x19, + 0x7e, 0x39, 0x9f, 0x2c, 0xf4, 0x0c, 0x0c, 0xe4, 0xfc, 0x60, 0xa1, 0x67, 0x61, 0x20, 0xe7, 0x4f, 0x16, 0xb5, 0x5b, + 0x07, 0x9a, 0x80, 0x78, 0x2e, 0x1c, 0x9d, 0x94, 0x56, 0x65, 0x0b, 0xe8, 0xe6, 0x21, 0x82, 0xfe, 0x0f, 0x7b, 0x08, + 0x3a, 0xb9, 0xd0, 0x8e, 0xdc, 0x80, 0xb6, 0x43, 0x12, 0xd8, 0x2b, 0x26, 0x15, 0x26, 0x16, 0xd1, 0x21, 0x1b, 0x83, + 0x21, 0xb6, 0xfa, 0xe0, 0x90, 0x8d, 0xa7, 0x3e, 0x09, 0x02, 0x46, 0xf7, 0x07, 0x03, 0x0e, 0x7e, 0x8b, 0x57, 0xe9, + 0xa3, 0x8d, 0x40, 0x37, 0x7d, 0x77, 0x37, 0xf4, 0x2e, 0xae, 0xe0, 0x54, 0xed, 0xee, 0x49, 0xe8, 0x26, 0xd3, 0x8e, + 0xd5, 0x6b, 0x88, 0x1b, 0xf2, 0x2b, 0xa3, 0xd1, 0xc8, 0xa6, 0x84, 0x84, 0x18, 0xce, 0xa1, 0x99, 0xd3, 0x72, 0xf9, + 0xea, 0xd6, 0xb3, 0x01, 0x19, 0x66, 0x7a, 0xcb, 0x64, 0xfd, 0x00, 0x65, 0xd5, 0x63, 0x68, 0x87, 0xde, 0x23, 0xc7, + 0x0f, 0x0f, 0xbe, 0xc9, 0xf8, 0x99, 0xc3, 0xb5, 0x87, 0x73, 0xe1, 0xbb, 0xac, 0x19, 0x99, 0x43, 0xe7, 0xd9, 0xc7, + 0xf1, 0x1e, 0xc6, 0xc9, 0xe7, 0x59, 0x28, 0x6f, 0xbc, 0xa6, 0xff, 0x51, 0xe9, 0xcd, 0x0e, 0x87, 0x9c, 0xae, 0x60, + 0xc5, 0xcd, 0xaa, 0xd0, 0xf0, 0xb3, 0xc8, 0x1b, 0x47, 0xbc, 0x26, 0x51, 0xd5, 0x7d, 0xde, 0xdb, 0x88, 0xa5, 0x1d, + 0xe3, 0x00, 0xe0, 0x44, 0xad, 0x1a, 0x76, 0xa5, 0x71, 0xad, 0x0e, 0x62, 0x44, 0x4a, 0xd8, 0x2a, 0x71, 0x24, 0x94, + 0xbf, 0x01, 0x08, 0x8b, 0xa1, 0x38, 0xde, 0x1a, 0xd6, 0x07, 0xd8, 0x0f, 0x5d, 0xa0, 0x69, 0x4e, 0xa9, 0x66, 0x00, + 0x90, 0x04, 0xfc, 0xd1, 0xd3, 0x4d, 0x43, 0x65, 0x9b, 0xe7, 0xa1, 0x65, 0x75, 0x05, 0x0f, 0xf4, 0xd4, 0x95, 0x0c, + 0x8c, 0xab, 0x3a, 0xf6, 0x36, 0xf7, 0xb7, 0x47, 0xab, 0xc8, 0x77, 0x36, 0xa9, 0x69, 0x16, 0x40, 0x8a, 0xc6, 0xa5, + 0x2f, 0xf4, 0x74, 0x02, 0xb4, 0x5e, 0x5b, 0x2a, 0xda, 0xef, 0xa3, 0x18, 0x35, 0x2e, 0x14, 0x58, 0x85, 0x09, 0x0a, + 0x87, 0x08, 0x23, 0x84, 0x7e, 0x5f, 0x86, 0x1b, 0x5f, 0x90, 0x41, 0x34, 0x5c, 0x8b, 0x0e, 0x45, 0xe4, 0x78, 0xd1, + 0xb6, 0x54, 0xd5, 0x9c, 0x34, 0x6d, 0x09, 0xbc, 0x89, 0x0c, 0xd8, 0xce, 0x3f, 0x6d, 0x88, 0x5c, 0x85, 0x0b, 0x18, + 0xbe, 0x23, 0xae, 0x05, 0xd1, 0x4d, 0x6d, 0xea, 0x6d, 0xd8, 0x21, 0x3a, 0x9a, 0xe2, 0xd1, 0x21, 0xf7, 0xdc, 0x3d, + 0xb7, 0x45, 0x7c, 0xf3, 0x19, 0x72, 0xd7, 0x74, 0xf6, 0x52, 0x84, 0x41, 0xdd, 0xb2, 0x81, 0x62, 0x1d, 0x3a, 0x41, + 0x01, 0x06, 0x70, 0xf9, 0x04, 0x74, 0x6c, 0x30, 0xa8, 0x08, 0x3e, 0x29, 0x6c, 0x9b, 0x06, 0xf9, 0x23, 0xde, 0x0d, + 0x1d, 0x5e, 0x5b, 0xf2, 0x40, 0xbc, 0xc2, 0x3e, 0x53, 0xc2, 0xfd, 0x0b, 0x0a, 0xba, 0xa3, 0xbc, 0x5c, 0x15, 0xae, + 0x4a, 0x03, 0x50, 0x65, 0xc7, 0x73, 0xad, 0x29, 0x69, 0x01, 0x2b, 0x25, 0x75, 0xe7, 0x37, 0xc1, 0x71, 0x4b, 0xa6, + 0xc2, 0xb7, 0xea, 0x46, 0x95, 0x87, 0x12, 0x45, 0x3a, 0xf6, 0x6c, 0xe7, 0x60, 0x0d, 0x80, 0xa7, 0xb0, 0xbd, 0x38, + 0x13, 0xf0, 0xb9, 0xd3, 0x2e, 0x5b, 0xe6, 0x12, 0x28, 0xea, 0x87, 0x71, 0x5e, 0x76, 0x7c, 0xb9, 0x3b, 0xda, 0xde, + 0x43, 0x6f, 0xc4, 0xc6, 0x78, 0x7d, 0x19, 0x35, 0xfd, 0xe2, 0x19, 0xae, 0x2c, 0x05, 0x79, 0xa0, 0xa9, 0x1e, 0x61, + 0x74, 0x08, 0x4c, 0x53, 0x7e, 0xc4, 0xc6, 0xd3, 0xe1, 0xd0, 0x90, 0x41, 0xaf, 0x99, 0x18, 0x0a, 0xec, 0x0b, 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, 0x7d, 0x5a, 0x5a, 0x87, 0x7d, 0xbb, 0x50, 0x68, 0xa1, 0x89, 0x5f, 0x65, 0x88, 0x9f, + 0xba, 0xce, 0xfc, 0xdb, 0xb4, 0x4f, 0x0d, 0x62, 0xe1, 0x48, 0x0c, 0x22, 0x7e, 0x71, 0xaa, 0x6c, 0x27, 0x84, 0x8a, + 0x8d, 0x87, 0xae, 0x75, 0xe3, 0x48, 0xaa, 0x30, 0x94, 0x42, 0xe3, 0xa9, 0xe1, 0xbe, 0x17, 0x3a, 0x7c, 0x1d, 0x66, + 0x71, 0x9b, 0x35, 0x92, 0x1a, 0xe3, 0x54, 0x98, 0x38, 0x95, 0x72, 0x15, 0x09, 0x0c, 0x94, 0x67, 0x0b, 0x83, 0x00, + 0x93, 0x98, 0x64, 0x6c, 0x2d, 0x84, 0x09, 0x63, 0xe7, 0x0a, 0xd3, 0xd4, 0x45, 0xea, 0x37, 0x03, 0x93, 0x05, 0x0d, + 0xf9, 0x3d, 0x1a, 0xad, 0xa9, 0x9a, 0x02, 0x0c, 0xe3, 0x28, 0xd5, 0xf8, 0xb7, 0x08, 0xb5, 0x19, 0x06, 0x00, 0xb6, + 0x79, 0x27, 0x33, 0x51, 0xbd, 0x16, 0x08, 0x81, 0xe6, 0xec, 0xa7, 0xe2, 0x6a, 0x67, 0x16, 0x8c, 0xa2, 0xdd, 0x5e, + 0xf9, 0x7c, 0xe0, 0x84, 0xf2, 0x58, 0x5d, 0xa0, 0x5e, 0xc9, 0xe2, 0x8d, 0x4c, 0x79, 0x2b, 0x44, 0xe6, 0x9e, 0x64, + 0x1f, 0xf2, 0x11, 0x9c, 0x57, 0xe8, 0x54, 0x6e, 0xb6, 0x89, 0x32, 0x4b, 0x92, 0x8c, 0x05, 0xc6, 0xe6, 0x25, 0x98, + 0x49, 0xcd, 0x8c, 0xe1, 0xd7, 0x10, 0x67, 0x6c, 0xe7, 0x24, 0xdc, 0xdc, 0xcf, 0x03, 0x43, 0x94, 0x72, 0xd1, 0x12, + 0x0d, 0x5b, 0x3b, 0x5e, 0x4f, 0xae, 0x09, 0xf7, 0x61, 0x23, 0xd6, 0x64, 0x8c, 0x71, 0x6d, 0x6e, 0x64, 0xfd, 0x68, + 0x81, 0x07, 0x63, 0xca, 0xfa, 0x13, 0xc8, 0xb4, 0x92, 0xb2, 0xce, 0x17, 0x46, 0xcc, 0xa4, 0x12, 0xbd, 0xdb, 0x37, + 0x3e, 0xab, 0xbb, 0x88, 0xfa, 0xad, 0xfd, 0x9e, 0xd4, 0xc3, 0x9d, 0xff, 0xa0, 0xb0, 0x06, 0x95, 0x11, 0x97, 0x11, + 0xe5, 0x99, 0x03, 0xdd, 0x34, 0x29, 0xe2, 0xf4, 0x6c, 0x15, 0x17, 0x25, 0x4f, 0xa1, 0x52, 0x4d, 0xdd, 0xa2, 0xde, + 0x04, 0xec, 0x0d, 0x91, 0x24, 0x59, 0x4b, 0x63, 0x2b, 0x76, 0x69, 0x90, 0x9e, 0x7b, 0x23, 0x2e, 0xbd, 0xaa, 0xd0, + 0x90, 0x96, 0x7a, 0x67, 0xa1, 0x92, 0xf9, 0x2b, 0xfe, 0x33, 0xa8, 0x15, 0xe8, 0x68, 0x93, 0x62, 0x3c, 0x07, 0x46, + 0x7c, 0x37, 0x98, 0xd5, 0x03, 0xc4, 0x45, 0x13, 0x94, 0x7a, 0x47, 0xec, 0xf8, 0xb9, 0xc9, 0xc3, 0xbb, 0x90, 0x73, + 0x06, 0x9f, 0x3e, 0xcc, 0x12, 0xb5, 0xd6, 0x91, 0x18, 0xa9, 0x19, 0x40, 0xd3, 0x41, 0x99, 0xf3, 0x58, 0x04, 0xb3, + 0x9e, 0x49, 0x8c, 0x7a, 0x5c, 0xff, 0x02, 0x0d, 0xb5, 0xdf, 0xac, 0x2c, 0xcf, 0xaa, 0xbb, 0x2f, 0xe1, 0xc0, 0xa6, + 0xb6, 0x82, 0x1e, 0xaf, 0x2b, 0x79, 0x79, 0xa9, 0xba, 0xed, 0x17, 0x62, 0xe4, 0x74, 0x8d, 0x6b, 0xe9, 0xbc, 0x5a, + 0xb0, 0x5e, 0x77, 0xba, 0x59, 0xdc, 0xcd, 0x32, 0x1a, 0x08, 0x6b, 0x3b, 0x9f, 0x68, 0xfe, 0xac, 0xd9, 0x76, 0x1f, + 0x6f, 0x41, 0xcc, 0x02, 0x80, 0x48, 0x0f, 0xa2, 0x60, 0x99, 0xa5, 0x3c, 0xa0, 0xf2, 0x3e, 0x8e, 0xb2, 0x50, 0x7a, + 0x39, 0xcb, 0xf8, 0x69, 0xd3, 0x58, 0xeb, 0xac, 0x50, 0x86, 0xd6, 0x46, 0x77, 0xba, 0xca, 0x10, 0xdb, 0x4f, 0xe2, + 0x6c, 0x01, 0xee, 0x8f, 0x19, 0x0a, 0x0d, 0x9d, 0x65, 0xa4, 0x89, 0x86, 0xef, 0xba, 0x67, 0x90, 0x51, 0x9c, 0xac, + 0xf3, 0x4a, 0xba, 0xd1, 0x67, 0x6d, 0x24, 0xcc, 0x3d, 0x44, 0xbf, 0x8a, 0xc1, 0xa3, 0xdc, 0xe7, 0xb5, 0xd1, 0xc9, + 0xb4, 0x8c, 0xb4, 0x3b, 0x3f, 0xa9, 0x97, 0x59, 0xaa, 0x75, 0xd8, 0x3e, 0xc3, 0xde, 0x1a, 0x93, 0xde, 0x84, 0xd4, + 0x30, 0x12, 0x9f, 0xcf, 0xa8, 0x11, 0x02, 0xda, 0x72, 0xfc, 0x1d, 0x3e, 0xc3, 0xd0, 0x14, 0x58, 0xaa, 0xb8, 0x85, + 0xdd, 0xf0, 0x35, 0x9f, 0xac, 0x5a, 0x00, 0x82, 0x59, 0xf9, 0x7a, 0x17, 0xaf, 0x84, 0xfa, 0x4c, 0x9b, 0x01, 0x20, + 0x0b, 0x4a, 0xb9, 0xe3, 0xa7, 0x54, 0x3a, 0x58, 0xa2, 0x68, 0x7b, 0x39, 0x7d, 0xa3, 0x63, 0xe3, 0x87, 0xf4, 0x5c, + 0xc0, 0x76, 0x21, 0xbf, 0x75, 0xaf, 0x5e, 0xa2, 0x22, 0xb5, 0x6d, 0xd6, 0x03, 0x7c, 0xb9, 0x41, 0x93, 0x30, 0x82, + 0x32, 0x65, 0x0a, 0x60, 0x70, 0x53, 0x8d, 0x82, 0x49, 0xab, 0x91, 0xb0, 0xa5, 0x9e, 0x64, 0xb9, 0xe9, 0x83, 0x53, + 0xdd, 0x23, 0xe8, 0xd1, 0x0e, 0x27, 0x2d, 0xfb, 0xb5, 0x82, 0xa3, 0x93, 0xab, 0x21, 0x6a, 0xe6, 0xbd, 0xb6, 0x23, + 0x43, 0xca, 0x65, 0x18, 0x08, 0xa6, 0x1c, 0xf3, 0xf4, 0xd8, 0x7a, 0x46, 0x44, 0x0f, 0x9c, 0x7d, 0xa6, 0x5b, 0x75, + 0x25, 0x01, 0xd1, 0xf1, 0x9b, 0xa7, 0xaf, 0xaf, 0xe2, 0x4b, 0x83, 0xa2, 0xd4, 0xb0, 0x88, 0x51, 0xa6, 0x7d, 0x95, + 0x84, 0xc1, 0xfb, 0xe5, 0xfd, 0x4f, 0x2a, 0x4b, 0xed, 0xf7, 0x60, 0x63, 0x45, 0x55, 0xbf, 0x94, 0xbc, 0x68, 0x0a, + 0xb0, 0xee, 0xb3, 0x44, 0x81, 0xdc, 0xef, 0x6d, 0x9a, 0xf9, 0x26, 0x6a, 0xdc, 0x6c, 0x58, 0x6f, 0x5c, 0xb7, 0x4b, + 0x6d, 0xc9, 0x8e, 0xac, 0x44, 0xce, 0x2c, 0x06, 0x33, 0x7e, 0x54, 0x18, 0x94, 0x86, 0x0d, 0xaa, 0x52, 0xf1, 0x7b, + 0x23, 0x82, 0x53, 0xc7, 0xaa, 0xc2, 0x98, 0x06, 0xcc, 0xb6, 0xa2, 0xd6, 0xa0, 0x0e, 0x4a, 0x69, 0x6b, 0x02, 0xb2, + 0xfd, 0xc6, 0x0a, 0x6a, 0x7e, 0xff, 0xcb, 0x18, 0xf2, 0x35, 0xa5, 0xa0, 0x92, 0x80, 0x9d, 0x41, 0xa3, 0xa7, 0x4a, + 0x18, 0x48, 0x41, 0xf0, 0x04, 0x28, 0x5f, 0x44, 0x8d, 0xd5, 0x6e, 0x5f, 0x9d, 0x1a, 0xa3, 0x2d, 0x20, 0xb4, 0x90, + 0x1e, 0x5d, 0xf6, 0x71, 0x1b, 0xeb, 0x40, 0xe2, 0xc1, 0x09, 0xb6, 0x73, 0x75, 0x8d, 0x46, 0x42, 0xf3, 0x87, 0x46, + 0x03, 0x5e, 0xd3, 0x0a, 0x14, 0xea, 0x39, 0x8e, 0x86, 0xce, 0x0e, 0x29, 0x88, 0xd8, 0xa0, 0x85, 0x7d, 0xf7, 0x7c, + 0x68, 0xf6, 0xf5, 0x3c, 0x59, 0x90, 0x9a, 0x4a, 0xf7, 0xb9, 0x5b, 0x42, 0xd6, 0xaa, 0x43, 0x59, 0x79, 0x80, 0xe3, + 0x85, 0x92, 0xf9, 0x3b, 0x4c, 0x6a, 0x94, 0xc6, 0x84, 0xc6, 0x88, 0x05, 0x2c, 0x09, 0xda, 0xeb, 0x81, 0xfa, 0x65, + 0x10, 0x2a, 0x9c, 0xe9, 0x89, 0xc4, 0xa7, 0x94, 0xab, 0x4f, 0x0b, 0x52, 0x4f, 0x0b, 0xe6, 0x40, 0x2f, 0x7d, 0x2b, + 0xbf, 0xb2, 0xf1, 0xd1, 0xee, 0xde, 0x35, 0x17, 0xd6, 0x31, 0xc4, 0xc5, 0x16, 0x7e, 0x73, 0x6a, 0x0a, 0xc0, 0x86, + 0xc7, 0xba, 0x2c, 0xdf, 0xa8, 0x89, 0xcc, 0xe2, 0x90, 0x44, 0x20, 0xd9, 0x6e, 0x6e, 0x6e, 0x23, 0xd8, 0xf6, 0x16, + 0x6a, 0x43, 0xfd, 0xe5, 0x6d, 0xf7, 0x7b, 0x86, 0x97, 0x7b, 0x72, 0xef, 0xa6, 0x0d, 0xe5, 0x0f, 0xf7, 0xaf, 0x92, + 0xff, 0xab, 0x4a, 0xee, 0xb7, 0xca, 0xac, 0xdb, 0xe2, 0xfd, 0xae, 0xe3, 0x96, 0x63, 0x34, 0x08, 0xac, 0x29, 0x30, + 0x90, 0x9e, 0x34, 0xa6, 0x89, 0x8e, 0xae, 0xcc, 0x98, 0xc1, 0xa3, 0x0b, 0xd0, 0x1c, 0xa6, 0xf3, 0x3c, 0x06, 0xe0, + 0x00, 0xff, 0xc8, 0x23, 0xd4, 0x3f, 0x9d, 0xe7, 0xc1, 0x59, 0x30, 0x28, 0x07, 0x81, 0xfe, 0xc4, 0x35, 0x27, 0x58, + 0x80, 0xce, 0x2d, 0x66, 0x10, 0x77, 0xd2, 0x9a, 0x39, 0xc4, 0x87, 0xc9, 0x74, 0x30, 0x88, 0xc9, 0x06, 0x40, 0xfa, + 0xe2, 0x85, 0x75, 0x0e, 0x2a, 0xf4, 0x82, 0x6c, 0xd5, 0x5d, 0x34, 0x2b, 0xf6, 0xaa, 0x9d, 0xe6, 0xfd, 0x7e, 0x3e, + 0x2f, 0x07, 0x41, 0xa3, 0xc2, 0xc2, 0x78, 0xff, 0xd1, 0xe6, 0x97, 0x46, 0x27, 0x4d, 0x30, 0x62, 0xed, 0x31, 0xaa, + 0x57, 0x3c, 0xcd, 0x68, 0xe3, 0x76, 0xac, 0x94, 0x2f, 0x20, 0x8a, 0x07, 0x86, 0xac, 0x95, 0x77, 0xe7, 0xe0, 0x75, + 0xb9, 0xf1, 0xe6, 0x88, 0x02, 0xec, 0xa6, 0x30, 0x4e, 0x6a, 0x2e, 0xba, 0xa8, 0x89, 0x67, 0xb0, 0xd3, 0xd5, 0x5b, + 0x89, 0x56, 0xe3, 0xbd, 0x78, 0xd7, 0x6c, 0xfc, 0xad, 0xdc, 0xd3, 0x65, 0xee, 0x5d, 0x00, 0xe2, 0xec, 0x5e, 0x5c, + 0xed, 0x61, 0xa9, 0x7b, 0xc1, 0xc0, 0x22, 0x87, 0xb4, 0xab, 0xd5, 0x43, 0x11, 0xa9, 0xf3, 0x18, 0x0c, 0x98, 0x4c, + 0x43, 0x6a, 0x32, 0xed, 0x15, 0x0a, 0xd2, 0xc6, 0x5a, 0x0b, 0x68, 0xc3, 0x61, 0xb1, 0x63, 0x37, 0xec, 0x4e, 0xb7, + 0x0e, 0x85, 0x12, 0x06, 0xb2, 0xae, 0x9b, 0x87, 0x5a, 0xc3, 0x13, 0x41, 0x0f, 0xaa, 0xd1, 0x7e, 0x7a, 0x28, 0x4f, + 0xda, 0x63, 0x01, 0x2e, 0x7a, 0xf8, 0xf2, 0xa5, 0xc0, 0x8b, 0xf6, 0x0e, 0xf2, 0x9c, 0xf9, 0x54, 0xf9, 0x20, 0x36, + 0xdc, 0x32, 0x7c, 0x68, 0x1f, 0xdf, 0x0a, 0x64, 0x52, 0x77, 0x34, 0xb5, 0xb5, 0x3b, 0x1a, 0xc7, 0x04, 0xfa, 0x4d, + 0x39, 0x4a, 0x99, 0x98, 0x5a, 0x96, 0xec, 0xa8, 0x97, 0x2b, 0x6f, 0xa8, 0x94, 0x1d, 0x2d, 0xdb, 0x9c, 0x5f, 0xda, + 0x48, 0xe8, 0xf7, 0xb5, 0x3b, 0x10, 0xbe, 0x51, 0xeb, 0x0d, 0x79, 0xd9, 0x10, 0xb1, 0x1c, 0x62, 0x06, 0x8e, 0x17, + 0x52, 0xb9, 0x76, 0x17, 0x4d, 0x55, 0xdd, 0xce, 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, 0x83, 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, 0x25, 0xf6, 0x0f, 0xf3, 0xaa, + 0x09, 0x1e, 0x79, 0x8d, 0xb7, 0xf7, 0x30, 0xf1, 0xa5, 0x52, 0x08, 0xaf, 0x52, 0x1a, 0x4a, 0x00, 0x06, 0x49, 0x50, + 0xc3, 0x95, 0xb6, 0xcd, 0x20, 0x95, 0x31, 0xec, 0x6e, 0xf5, 0x56, 0xff, 0xa7, 0x55, 0xb8, 0xa8, 0x64, 0x31, 0x26, + 0x81, 0xce, 0xa9, 0x96, 0x9b, 0xc0, 0x82, 0x67, 0xbb, 0xe4, 0x08, 0x14, 0x76, 0x02, 0xb8, 0xa1, 0x84, 0xfd, 0x82, + 0xb7, 0xa1, 0x9c, 0xbd, 0xb2, 0x92, 0x27, 0xb7, 0x2f, 0xa9, 0xa0, 0x09, 0x99, 0x0a, 0xbb, 0x7f, 0x5b, 0x1b, 0xf6, + 0x45, 0x28, 0x47, 0x52, 0xe0, 0xe2, 0xa0, 0x73, 0x00, 0xfb, 0x83, 0x5c, 0xc6, 0xe6, 0x33, 0xe9, 0xf7, 0xd5, 0xfb, + 0xe7, 0x79, 0x96, 0x7c, 0xdc, 0x79, 0x6f, 0x78, 0x9a, 0x25, 0x03, 0x2a, 0x11, 0x53, 0xeb, 0xaa, 0x18, 0x2e, 0xb5, + 0x8b, 0x71, 0x83, 0x64, 0xc4, 0xf7, 0x52, 0x87, 0x18, 0x31, 0xbe, 0xc8, 0x0e, 0x49, 0xc9, 0xe9, 0xb2, 0xee, 0xec, + 0xb9, 0x16, 0xcd, 0xa0, 0x31, 0xdc, 0x8e, 0xf7, 0x92, 0x5e, 0x01, 0x2a, 0x40, 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, + 0x0b, 0x00, 0x6a, 0x35, 0x48, 0xaf, 0xf4, 0x15, 0xa1, 0x2a, 0x09, 0xc1, 0xe8, 0x44, 0xc2, 0xcb, 0x80, 0xc6, 0x99, + 0x49, 0xb4, 0xb0, 0xc1, 0x01, 0x7d, 0x51, 0x99, 0x44, 0x63, 0x43, 0x1e, 0x50, 0x6e, 0xd3, 0x00, 0x06, 0x1f, 0x24, + 0x49, 0xf4, 0xf5, 0xd2, 0x24, 0x81, 0xa0, 0x04, 0xe5, 0x1b, 0xf4, 0xe7, 0xd2, 0xf3, 0xb1, 0xfc, 0xdd, 0x3b, 0x94, + 0x7e, 0x08, 0x0b, 0x90, 0x29, 0xea, 0x8a, 0x69, 0xc6, 0x8e, 0xb2, 0x6e, 0x63, 0x12, 0xcf, 0xd3, 0xee, 0xb6, 0x50, + 0x2e, 0x5d, 0xe0, 0x57, 0x96, 0x21, 0x8e, 0xf5, 0xf3, 0x78, 0xc5, 0x8e, 0x43, 0xae, 0xf1, 0xd2, 0x9f, 0xc7, 0x2b, + 0x9c, 0x21, 0x5a, 0xb5, 0x12, 0x88, 0xf2, 0x5f, 0xb5, 0x81, 0x43, 0xdc, 0x27, 0x18, 0xe4, 0xa2, 0xf2, 0x1e, 0x08, + 0xe4, 0x6d, 0x05, 0x11, 0x69, 0x66, 0xd7, 0x61, 0x44, 0xaa, 0x9d, 0x24, 0xf3, 0xe5, 0x8f, 0x32, 0x13, 0xde, 0x37, + 0xf0, 0xd8, 0x6c, 0x96, 0x4d, 0x31, 0x5f, 0xa8, 0x60, 0x0e, 0xee, 0x13, 0x15, 0x97, 0xa2, 0xf2, 0x9f, 0xb0, 0x0b, + 0x5e, 0x8c, 0x07, 0xaf, 0xd7, 0x08, 0xb0, 0x5f, 0xf9, 0x4f, 0xde, 0x98, 0xbd, 0xb5, 0x6e, 0x7c, 0x99, 0x89, 0xf8, + 0xc0, 0x47, 0xb7, 0x94, 0x8f, 0xee, 0xbc, 0x4c, 0x7f, 0x36, 0xa0, 0x44, 0x46, 0x65, 0xc5, 0x57, 0x2b, 0x9e, 0xce, + 0x6e, 0x93, 0x28, 0x1b, 0x55, 0x5c, 0xc0, 0xf4, 0x82, 0xe3, 0x5d, 0xb2, 0x3e, 0xcf, 0x92, 0xd7, 0x10, 0x7b, 0x60, + 0x25, 0x15, 0x16, 0x3f, 0x2c, 0x33, 0xb5, 0x98, 0x85, 0xac, 0xa4, 0xe0, 0xc1, 0xec, 0x3a, 0x89, 0xde, 0x2e, 0x3d, + 0x24, 0x35, 0x33, 0x65, 0x9b, 0xda, 0x11, 0x6a, 0xe3, 0xeb, 0x48, 0x37, 0xda, 0x02, 0x00, 0xee, 0xd9, 0x22, 0x8d, + 0x24, 0x13, 0xc3, 0x49, 0xcd, 0xb8, 0x49, 0x2f, 0x30, 0x35, 0xae, 0x59, 0x45, 0x13, 0x67, 0x21, 0x03, 0x7a, 0x7f, + 0xc0, 0xcb, 0xc1, 0xe7, 0x0c, 0xee, 0x3f, 0x68, 0x0d, 0x5c, 0x1e, 0x16, 0xfd, 0xbe, 0x3c, 0x2c, 0xb6, 0xdb, 0xf2, + 0x28, 0xee, 0xf7, 0xe5, 0x51, 0x6c, 0xf8, 0x07, 0xa5, 0xd8, 0x36, 0xe6, 0x06, 0x09, 0xcd, 0x25, 0x44, 0x2d, 0x1a, + 0xc1, 0x1f, 0x9a, 0xe5, 0x5c, 0x44, 0xf9, 0x61, 0xd2, 0xef, 0xf7, 0x96, 0x33, 0x31, 0xc8, 0x87, 0x49, 0x94, 0x0f, + 0x13, 0xcf, 0x09, 0xf1, 0x57, 0xcf, 0x09, 0x51, 0xd1, 0xc0, 0x15, 0x9c, 0x19, 0x80, 0x28, 0xe0, 0xd3, 0x3f, 0xaa, + 0x6b, 0x29, 0x74, 0x2d, 0xb1, 0xaa, 0x25, 0xd1, 0x15, 0xd4, 0xec, 0xba, 0x08, 0x4b, 0x2c, 0x85, 0x2e, 0xd9, 0x9f, + 0x4b, 0xe0, 0x89, 0x72, 0x5e, 0x6d, 0x80, 0x81, 0x8d, 0xf0, 0xce, 0x61, 0xc2, 0x49, 0xac, 0x6b, 0x40, 0x3b, 0xdd, + 0xd4, 0xf4, 0x82, 0xae, 0xe8, 0x25, 0xf2, 0xb3, 0x17, 0x60, 0xb0, 0x74, 0xc8, 0xf2, 0xe9, 0x60, 0x70, 0x41, 0x56, + 0xac, 0x9c, 0x87, 0xf1, 0x20, 0x5c, 0xcf, 0xf2, 0xe1, 0x45, 0x74, 0x41, 0xc8, 0x57, 0xc5, 0x82, 0xf6, 0x56, 0xa3, + 0xf2, 0x63, 0x06, 0xe1, 0xfd, 0xd2, 0x59, 0x98, 0x99, 0x38, 0x1f, 0xab, 0xd1, 0x2d, 0x5d, 0x41, 0xfc, 0x1a, 0xb8, + 0x91, 0x90, 0x08, 0x3a, 0x72, 0x49, 0x57, 0x74, 0x4d, 0xa5, 0x99, 0x61, 0x8c, 0xd6, 0x6d, 0x8f, 0x93, 0x04, 0x1c, + 0x93, 0x5d, 0xf1, 0xd1, 0x58, 0x15, 0xde, 0xf5, 0x1d, 0xa1, 0xbd, 0x5e, 0xe2, 0x06, 0xe9, 0xbb, 0xf6, 0x20, 0x01, + 0x23, 0x32, 0x52, 0x03, 0x65, 0x46, 0x46, 0x52, 0x33, 0xa9, 0x38, 0x24, 0xb1, 0x3f, 0x24, 0x6a, 0x1c, 0x12, 0x7f, + 0x1c, 0x72, 0x3d, 0x0e, 0xc8, 0xdd, 0x2f, 0xd9, 0x98, 0xa6, 0x6c, 0x4c, 0xd7, 0x6a, 0x54, 0xe8, 0x15, 0x3d, 0xd7, + 0xd4, 0xf1, 0x8c, 0xbd, 0x81, 0x03, 0x7b, 0x10, 0xe6, 0xb3, 0x78, 0xf8, 0x26, 0x7a, 0x43, 0xc8, 0x57, 0x92, 0x5e, + 0xab, 0x4b, 0x19, 0x04, 0x42, 0xbc, 0x02, 0xe7, 0x52, 0x17, 0xea, 0xe4, 0xca, 0xec, 0x38, 0x7c, 0xba, 0x6c, 0x3c, + 0x9d, 0x43, 0x44, 0x1f, 0xb4, 0x52, 0xe9, 0xf7, 0xc3, 0x0b, 0x56, 0xce, 0xcf, 0xc2, 0x31, 0x01, 0x1c, 0x1e, 0x3d, + 0x9c, 0x17, 0xa3, 0x5b, 0x7a, 0x31, 0xba, 0x23, 0x60, 0xe1, 0x35, 0x9e, 0xae, 0x0f, 0x59, 0x3c, 0x1d, 0x0c, 0xd6, + 0x48, 0xd5, 0x55, 0xee, 0x35, 0x59, 0xd0, 0x0b, 0x9c, 0x08, 0x02, 0x0c, 0x7d, 0x26, 0xd6, 0x86, 0x86, 0xbf, 0x61, + 0xf0, 0xf1, 0x1d, 0xbb, 0x18, 0xdd, 0xd1, 0x5b, 0xf6, 0x66, 0x3b, 0x9e, 0x02, 0x33, 0xb5, 0x9a, 0x85, 0x77, 0x87, + 0x97, 0xb3, 0x4b, 0x76, 0x17, 0xdd, 0x1d, 0x41, 0x43, 0xaf, 0xd8, 0x1d, 0x02, 0x2e, 0xa5, 0x8f, 0x97, 0x83, 0x37, + 0x64, 0x7f, 0x30, 0x48, 0x49, 0x14, 0x5e, 0x87, 0x5e, 0x2b, 0xdf, 0xd0, 0x3b, 0x42, 0x57, 0xec, 0x16, 0x47, 0xe3, + 0x92, 0xe1, 0x07, 0xe7, 0xec, 0xae, 0xbe, 0x0e, 0xbd, 0xdd, 0x9c, 0x88, 0x4e, 0x10, 0x23, 0xf4, 0x35, 0x70, 0x34, + 0xcb, 0x85, 0x99, 0x80, 0x27, 0x73, 0x91, 0xd1, 0xa2, 0xd0, 0x0c, 0xc4, 0x59, 0x09, 0x88, 0x25, 0x51, 0xf7, 0x9b, + 0x8d, 0xce, 0x60, 0x39, 0xf7, 0xfb, 0xbd, 0xca, 0xd0, 0x03, 0x44, 0xce, 0xec, 0xa4, 0x07, 0x3d, 0x9f, 0x1e, 0xe0, + 0x27, 0x7a, 0xd5, 0x20, 0x4e, 0xe6, 0x77, 0xcb, 0xe8, 0x57, 0x8f, 0x3e, 0xfc, 0xd0, 0x4d, 0x79, 0x44, 0xfe, 0xef, + 0x53, 0x9e, 0x32, 0x8f, 0xde, 0x54, 0x1e, 0x08, 0x9e, 0xb7, 0x26, 0x95, 0x46, 0xa2, 0x1a, 0x9d, 0xad, 0x62, 0xd0, + 0x46, 0xa2, 0xb6, 0x41, 0x3f, 0xa1, 0x85, 0x15, 0x44, 0xc8, 0x39, 0x78, 0x01, 0x06, 0xa9, 0x10, 0x2a, 0x47, 0x2d, + 0x4a, 0x34, 0x04, 0xc9, 0x65, 0xc9, 0x55, 0xf8, 0x1c, 0x42, 0xd5, 0xe9, 0xe3, 0x4c, 0x84, 0x0d, 0x3d, 0x0e, 0x7d, + 0x00, 0xf8, 0x5f, 0x76, 0xc8, 0x45, 0xc9, 0x2f, 0xf1, 0x6c, 0x6e, 0x13, 0x8c, 0x82, 0x25, 0xa2, 0x19, 0xda, 0x06, + 0xb1, 0x1f, 0x4b, 0x82, 0xf5, 0x48, 0x1a, 0x8f, 0x4a, 0x73, 0x44, 0xf8, 0x51, 0x7c, 0x14, 0x3d, 0x8d, 0x0d, 0x89, + 0xe4, 0x48, 0x22, 0xf9, 0x00, 0x08, 0x27, 0x41, 0x7f, 0x71, 0xd7, 0x64, 0xd7, 0x42, 0x62, 0xd0, 0x9f, 0x96, 0x4c, + 0xcb, 0xee, 0x55, 0x8f, 0x7d, 0x45, 0x90, 0x3b, 0xa6, 0xff, 0xf2, 0xfa, 0xf0, 0xaf, 0x25, 0xce, 0xa0, 0xf5, 0x7c, + 0x51, 0x9d, 0x99, 0x79, 0x83, 0x1b, 0x79, 0x5d, 0xd6, 0xae, 0xcb, 0x17, 0x7c, 0x8f, 0xdf, 0x56, 0x5c, 0xa4, 0xe5, + 0xde, 0xcf, 0x55, 0x1b, 0xcf, 0xa9, 0x5c, 0xaf, 0x5c, 0x9c, 0x15, 0x65, 0x9c, 0xea, 0x49, 0x5d, 0x8c, 0x35, 0x6c, + 0xc3, 0xef, 0x11, 0x75, 0x25, 0x2d, 0x47, 0x4f, 0x29, 0x57, 0xcd, 0x94, 0x8b, 0x75, 0x9e, 0xff, 0xb4, 0x93, 0x8a, + 0x53, 0xdc, 0x4c, 0x41, 0xaa, 0xd4, 0x72, 0x01, 0xd5, 0x73, 0xd4, 0x72, 0xb7, 0x34, 0x3b, 0xc0, 0xb9, 0x6d, 0xaa, + 0x8f, 0x95, 0xd9, 0x85, 0x97, 0xdc, 0xb8, 0x3f, 0x99, 0x32, 0x2c, 0x18, 0x85, 0x36, 0xab, 0xae, 0xb4, 0x7d, 0xa1, + 0x75, 0x1a, 0x86, 0x2b, 0x3f, 0x5e, 0x40, 0xba, 0x80, 0x71, 0xbc, 0x28, 0x99, 0x18, 0xb7, 0x47, 0x6f, 0x05, 0xf1, + 0x25, 0x5b, 0x81, 0xf4, 0xfb, 0x3d, 0xe1, 0xed, 0xba, 0x8e, 0xb6, 0x7b, 0xe2, 0x94, 0x51, 0xb9, 0x8a, 0xc5, 0xf7, + 0xf1, 0xca, 0x40, 0x26, 0xab, 0xe3, 0xb1, 0x31, 0xa6, 0xd3, 0x7f, 0x24, 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, 0x75, 0x3e, 0x09, 0x15, 0xbb, 0x60, 0xf7, 0x02, + 0x99, 0x5e, 0xcd, 0xf9, 0x42, 0x8d, 0x84, 0x2e, 0xf8, 0xca, 0x1a, 0x9b, 0xc4, 0x9e, 0xa0, 0x65, 0x16, 0xcf, 0xc7, + 0x8b, 0x28, 0xae, 0x61, 0x19, 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, 0xb3, 0x2d, 0xb2, 0x24, 0xeb, 0xc7, 0xd2, 0x28, 0x62, + 0xa0, 0x4a, 0x10, 0x51, 0x8b, 0x7f, 0x3d, 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, 0xe2, 0x4a, 0x7b, 0xac, 0xe9, 0x05, 0x81, 0xce, 0xf5, 0x64, 0xff, 0x00, + 0xa2, 0x22, 0x34, 0xe3, 0x6e, 0x96, 0x0d, 0x89, 0x8c, 0x1f, 0xa7, 0xb3, 0x6c, 0x08, 0x76, 0xb8, 0x17, 0x95, 0xb8, + 0x1c, 0xb5, 0x36, 0x38, 0x3d, 0x4b, 0x42, 0x08, 0xe5, 0x80, 0x95, 0xdd, 0xaa, 0x3f, 0x77, 0xca, 0x4c, 0x48, 0x4d, + 0x56, 0xb7, 0x53, 0xba, 0x87, 0x69, 0xbe, 0x67, 0x46, 0x70, 0xc0, 0xbd, 0xfd, 0x55, 0x7f, 0x0c, 0x93, 0x4c, 0x93, + 0x53, 0x24, 0xbf, 0x48, 0x4f, 0x21, 0x69, 0x87, 0x9e, 0x2a, 0x02, 0x38, 0xa1, 0xf6, 0x63, 0xf8, 0x0d, 0xe3, 0xfe, + 0x5d, 0xf3, 0xb5, 0x9b, 0x8a, 0xe8, 0x29, 0xc5, 0x32, 0x35, 0x39, 0x4d, 0xb2, 0x22, 0x81, 0xa8, 0x8d, 0xaa, 0x19, + 0xd1, 0x13, 0x17, 0xf3, 0x51, 0x11, 0x3e, 0xaf, 0xd6, 0xff, 0x19, 0xc2, 0x67, 0x14, 0x6e, 0x00, 0x97, 0x57, 0x5c, + 0x9e, 0x87, 0xcf, 0x9e, 0xd2, 0xbd, 0xc9, 0x37, 0x07, 0x74, 0xef, 0xe0, 0xc9, 0x33, 0x02, 0xb0, 0x68, 0x97, 0xe7, + 0xe1, 0xc1, 0xb3, 0x67, 0x74, 0xef, 0xdb, 0x6f, 0xe9, 0xde, 0xe4, 0xc9, 0x41, 0x23, 0x6d, 0xf2, 0xec, 0x5b, 0xba, + 0xf7, 0xcd, 0xd3, 0x46, 0xda, 0xc1, 0xf8, 0x19, 0xdd, 0xfb, 0xfb, 0x37, 0x26, 0xed, 0x6f, 0x90, 0xed, 0xdb, 0x03, + 0xfc, 0xcf, 0xa4, 0x4d, 0x9e, 0x3d, 0xa1, 0x7b, 0x93, 0x31, 0x54, 0xf2, 0xcc, 0x55, 0x32, 0x9e, 0xc0, 0xc7, 0x4f, + 0xe0, 0xbf, 0xbf, 0x91, 0x60, 0x41, 0x2b, 0xc9, 0x72, 0x81, 0xfa, 0x33, 0x14, 0x71, 0xa2, 0x6a, 0x22, 0xe1, 0x21, + 0x66, 0x56, 0xdf, 0xc4, 0x61, 0x40, 0x5c, 0x3a, 0x14, 0x44, 0xf7, 0xc6, 0xa3, 0x67, 0x24, 0xf0, 0xe1, 0xe9, 0x6e, + 0x7c, 0x90, 0xb1, 0x5c, 0xcc, 0xb3, 0xaf, 0x72, 0x13, 0x5b, 0xc1, 0x03, 0xb0, 0xfa, 0xe8, 0xe7, 0xaa, 0xe4, 0x3c, + 0xfb, 0xaa, 0x92, 0xbb, 0xb9, 0x7e, 0x6b, 0x01, 0xca, 0xfb, 0xab, 0x96, 0xdd, 0x14, 0x2a, 0x74, 0x5a, 0x6b, 0xf4, + 0xd9, 0x47, 0x4c, 0x1f, 0x0c, 0xbc, 0x1b, 0xf6, 0x3f, 0x76, 0xca, 0x69, 0x7d, 0xa3, 0x51, 0xa8, 0x51, 0x79, 0x48, + 0xd8, 0x11, 0x14, 0x3d, 0x18, 0x00, 0x4f, 0xe0, 0xe1, 0xbe, 0xfd, 0x9b, 0x65, 0x7c, 0xec, 0x28, 0xe3, 0x67, 0x94, + 0x21, 0xa0, 0x51, 0x0f, 0xb3, 0x9b, 0x1e, 0x36, 0xba, 0xd5, 0x4b, 0x96, 0xea, 0x64, 0x6a, 0x7a, 0x06, 0xfb, 0x5a, + 0xd7, 0x72, 0xcf, 0x88, 0xa2, 0xe5, 0xc5, 0x5e, 0xca, 0x67, 0x15, 0xfb, 0xc7, 0x12, 0xd5, 0x5b, 0x51, 0xe3, 0x8d, + 0xcc, 0x66, 0x15, 0xfb, 0xde, 0xbc, 0x01, 0x6e, 0x86, 0xfd, 0xa6, 0x9e, 0xfc, 0xc0, 0x19, 0x5c, 0xda, 0xf6, 0x28, + 0x13, 0x23, 0xc0, 0x0a, 0xc8, 0xc0, 0x81, 0x07, 0x40, 0x07, 0xfd, 0xd1, 0xde, 0x6e, 0x55, 0x4a, 0xb3, 0xcf, 0x16, + 0x06, 0xd0, 0x30, 0x6f, 0x13, 0x57, 0xf6, 0xef, 0x0d, 0x79, 0x09, 0x0a, 0xb7, 0x9a, 0xe5, 0xed, 0x14, 0x86, 0x10, + 0x82, 0x3f, 0x2e, 0x19, 0x00, 0x0e, 0x04, 0x18, 0x8c, 0xb5, 0x0c, 0xa8, 0xd9, 0xf2, 0xd1, 0x86, 0x2b, 0xf5, 0x24, + 0x70, 0x06, 0x17, 0xb2, 0x48, 0xf8, 0x89, 0x16, 0xfb, 0xa3, 0xf5, 0xa3, 0xef, 0xdb, 0xe3, 0xc1, 0xda, 0xf7, 0xf8, + 0x48, 0x7f, 0xd6, 0xb8, 0x0e, 0x6c, 0x5a, 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, 0xdf, + 0x97, 0x2a, 0x70, 0x54, 0xbf, 0xcf, 0xa5, 0xef, 0xf6, 0x64, 0xec, 0xc8, 0x71, 0xea, 0xa7, 0xc2, 0xc1, 0x7f, 0x93, + 0xba, 0x36, 0x96, 0x2b, 0x29, 0xb3, 0x2c, 0x0b, 0x3b, 0x0a, 0xb5, 0xdc, 0xa3, 0xf2, 0x20, 0xf9, 0x42, 0x0e, 0x91, + 0x2c, 0x30, 0x0a, 0x05, 0x19, 0x4e, 0xa8, 0x18, 0xad, 0x45, 0xb9, 0xcc, 0x2e, 0xaa, 0x70, 0xa3, 0x14, 0xca, 0x9c, + 0xa2, 0x6f, 0x37, 0x38, 0x90, 0x90, 0x28, 0x2b, 0xdf, 0xc6, 0x6f, 0x43, 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, 0x33, 0x88, 0x35, 0xac, 0x72, + 0x66, 0xaa, 0x6f, 0x84, 0x1d, 0x01, 0x70, 0x23, 0xb4, 0x46, 0x47, 0x26, 0xa9, 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, 0x94, 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, 0x1f, 0x71, 0x18, 0xc6, 0xc3, 0x82, 0xec, 0x4b, 0x7a, 0xb7, + 0x3f, 0xe1, 0x4f, 0xc8, 0x2c, 0xd4, 0xcd, 0x57, 0x0b, 0xce, 0xaa, 0xbc, 0x55, 0xae, 0x3b, 0x0a, 0xd6, 0x0a, 0x77, + 0x4c, 0x3d, 0x9d, 0xd0, 0x1b, 0x56, 0xd0, 0x53, 0x16, 0x93, 0xe8, 0x1a, 0x5a, 0x71, 0x3e, 0x2b, 0xa2, 0x1b, 0x7a, + 0xca, 0xce, 0x66, 0x71, 0x74, 0x4a, 0x4f, 0x58, 0x3e, 0x9c, 0x40, 0xde, 0xd3, 0xe1, 0x0d, 0xd9, 0x3f, 0x21, 0x51, + 0x78, 0xa2, 0x7f, 0xdf, 0xd1, 0x4b, 0x1e, 0x9e, 0x50, 0xaf, 0x9a, 0x13, 0x62, 0xaa, 0x6f, 0xd4, 0x7e, 0x42, 0x22, + 0x7f, 0x30, 0x4f, 0xac, 0x3d, 0xcd, 0x23, 0x47, 0x1b, 0xd3, 0x32, 0x04, 0x7d, 0x73, 0x19, 0xde, 0x10, 0x32, 0x6d, + 0x8e, 0x1d, 0x0c, 0xe8, 0xec, 0x51, 0x94, 0x10, 0x7a, 0xe3, 0x97, 0x7a, 0x83, 0x63, 0x68, 0x46, 0x48, 0xa5, 0x9d, + 0x62, 0x1a, 0xae, 0x83, 0xd7, 0x1a, 0xac, 0xe3, 0xbc, 0xdf, 0x0f, 0xd7, 0xfd, 0x3e, 0x44, 0xba, 0x2f, 0x66, 0x26, + 0xb6, 0x9b, 0x23, 0x9b, 0xf4, 0x06, 0xb4, 0xff, 0xaf, 0x07, 0x03, 0xe8, 0x8c, 0x57, 0x52, 0x78, 0x33, 0x78, 0xfd, + 0xf8, 0x8e, 0xa8, 0x3a, 0x0a, 0x2a, 0x64, 0x58, 0xd0, 0x37, 0x34, 0x03, 0xc0, 0xaf, 0xd7, 0x83, 0x01, 0x89, 0xcc, + 0x67, 0x64, 0xfa, 0xfa, 0xf0, 0x64, 0x3a, 0x18, 0xbc, 0x36, 0xdb, 0xe4, 0x2d, 0xbb, 0xa7, 0x14, 0x58, 0x7f, 0x67, + 0xfd, 0xfe, 0xdb, 0xa3, 0x98, 0x9c, 0x17, 0x3c, 0xfe, 0x38, 0x6d, 0xb6, 0xe5, 0xad, 0x8b, 0xaa, 0x76, 0xd6, 0xef, + 0xaf, 0xfb, 0xfd, 0x53, 0xc0, 0x2e, 0x9a, 0x39, 0x5f, 0x4f, 0x90, 0xb6, 0xcc, 0x1d, 0x45, 0xd2, 0x24, 0x87, 0xc6, + 0xd0, 0xb6, 0x58, 0xb5, 0x6d, 0xd6, 0x91, 0x81, 0xc5, 0x51, 0xb3, 0xa2, 0xb8, 0x26, 0x51, 0xd8, 0x3b, 0xdb, 0x6e, + 0x4f, 0x19, 0x63, 0x31, 0x01, 0xe9, 0x87, 0xff, 0xfa, 0xb4, 0x6e, 0xc4, 0x10, 0x13, 0x12, 0x99, 0xcd, 0xcd, 0xd2, + 0x1e, 0x02, 0x11, 0x87, 0x4d, 0xff, 0xde, 0xdc, 0xcb, 0x45, 0xed, 0xf8, 0xd6, 0xdf, 0x01, 0x84, 0x48, 0xb2, 0x90, + 0xcf, 0x70, 0x0c, 0xca, 0x0c, 0x80, 0xcc, 0x23, 0x35, 0xf3, 0x12, 0x40, 0x80, 0xc9, 0x76, 0x3b, 0x1a, 0x8f, 0x27, + 0xb4, 0x60, 0xa3, 0xbf, 0x3d, 0x7b, 0x5c, 0x3d, 0x0e, 0x83, 0x60, 0x90, 0x91, 0x96, 0x9e, 0xc2, 0x2e, 0xd6, 0x6a, + 0x1f, 0x8c, 0xe0, 0x35, 0xfb, 0x78, 0x9d, 0x7d, 0x31, 0xfb, 0x88, 0x84, 0xb5, 0xc1, 0x38, 0x72, 0x91, 0xb6, 0xf4, + 0x76, 0xf7, 0x30, 0x98, 0x5c, 0xa4, 0x9f, 0x61, 0x3b, 0x7d, 0xfe, 0xcd, 0x83, 0xf1, 0x84, 0x83, 0xd1, 0x5d, 0x14, + 0xf4, 0x99, 0xb6, 0xdd, 0x56, 0xfe, 0x25, 0xf0, 0x2d, 0xa6, 0x82, 0x8e, 0xcd, 0xb2, 0x70, 0x83, 0x8a, 0xa8, 0xa3, + 0x65, 0x50, 0xd5, 0xca, 0x76, 0x0e, 0xa8, 0x25, 0x56, 0x65, 0xe2, 0x16, 0x18, 0x86, 0x0c, 0x75, 0xb9, 0xc7, 0xd5, + 0xef, 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, 0xfa, 0xf2, 0xec, 0xf5, 0xdb, 0x57, 0xaf, 0xdf, + 0xbe, 0xfe, 0xf0, 0xaf, 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, 0x87, 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, 0x13, 0x37, 0x45, 0xfe, 0xff, 0xb8, 0x61, 0xdc, 0x77, 0x97, 0x30, 0x8b, 0xeb, 0x3a, 0x1b, 0xad, + 0x0a, 0x59, 0x49, 0xb8, 0x4d, 0x28, 0x51, 0xd8, 0x28, 0x5e, 0xad, 0x72, 0xed, 0x22, 0x36, 0xaf, 0x28, 0x80, 0xbb, + 0x40, 0x9c, 0x62, 0x60, 0xa1, 0x8d, 0x81, 0xdc, 0x27, 0x5e, 0x48, 0x66, 0xd5, 0x3e, 0xe6, 0x1e, 0xf9, 0x67, 0x08, + 0xc6, 0xa8, 0xe2, 0x68, 0x3c, 0x53, 0x58, 0x17, 0x9f, 0x93, 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, 0x27, 0x7c, 0x67, 0xea, 0x05, 0x5c, 0x42, 0x35, 0xb0, 0xeb, 0xcb, 0x4b, 0x5e, 0x02, 0x88, + 0x50, 0x26, 0xfa, 0xfd, 0xde, 0x9f, 0x06, 0x9a, 0xb4, 0xe4, 0xc5, 0x9b, 0x4c, 0x58, 0x67, 0x1c, 0x68, 0x2a, 0x50, + 0xff, 0x8f, 0x95, 0x7d, 0xa6, 0x63, 0x32, 0xf3, 0x1f, 0x87, 0x13, 0x12, 0x35, 0x5f, 0x93, 0xcf, 0x9c, 0xa6, 0x9f, + 0xb9, 0xa2, 0xfd, 0x07, 0x32, 0x73, 0xc3, 0x21, 0x43, 0xfd, 0xa5, 0x63, 0x9e, 0x8c, 0x5e, 0x27, 0x66, 0x47, 0x82, + 0x55, 0x33, 0x88, 0xc2, 0x5e, 0xc0, 0x83, 0xba, 0x96, 0xc5, 0x53, 0x98, 0x7d, 0x50, 0x23, 0x8a, 0x43, 0x36, 0x9e, + 0x85, 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, 0x05, 0xe3, 0x20, 0xfa, 0xcf, 0xf9, 0xc4, 0x7b, 0x79, 0xea, 0xab, 0x4c, 0x4c, 0xef, 0x61, + 0x9a, 0x7d, 0x82, 0x82, 0xb0, 0x8a, 0xbb, 0xf4, 0x64, 0x5d, 0xd9, 0x5b, 0x2b, 0x19, 0x62, 0x9e, 0x07, 0x58, 0xa3, + 0xb0, 0xf2, 0x80, 0xee, 0x51, 0xb5, 0x41, 0x9c, 0x08, 0x1e, 0xc6, 0xcc, 0x4a, 0xdf, 0xb7, 0x5b, 0xa3, 0xc2, 0x7c, + 0x90, 0x8b, 0x82, 0xec, 0xe6, 0xe3, 0xd9, 0x38, 0x0a, 0xb1, 0x01, 0xff, 0x31, 0x63, 0xd5, 0x90, 0xcd, 0x77, 0x32, + 0x52, 0x3b, 0x26, 0x4f, 0x93, 0x5d, 0xd2, 0x3b, 0xe0, 0x1d, 0xf2, 0x73, 0x70, 0x67, 0x93, 0x86, 0xdf, 0x92, 0x97, + 0x71, 0x91, 0x55, 0xcb, 0xab, 0x2c, 0x41, 0xa6, 0x0b, 0x5e, 0x7c, 0x31, 0xd3, 0xe5, 0x7d, 0xac, 0x0f, 0x18, 0x4f, + 0x29, 0x5e, 0x37, 0x44, 0xe9, 0xeb, 0x96, 0x67, 0x85, 0xba, 0x3c, 0xa9, 0x98, 0xed, 0x59, 0x09, 0x4e, 0xa7, 0x60, + 0x82, 0xaf, 0x7f, 0xba, 0xde, 0x27, 0x80, 0x0b, 0x0a, 0x35, 0xa7, 0x85, 0x5c, 0x19, 0x2c, 0x27, 0x0b, 0xdd, 0x09, + 0x98, 0xa1, 0x52, 0xe0, 0x05, 0x0a, 0xfe, 0xa2, 0x81, 0x11, 0x7d, 0xe5, 0x7e, 0x93, 0x81, 0x41, 0xba, 0x34, 0x27, + 0xc2, 0xd8, 0x71, 0x3b, 0x45, 0xda, 0x8a, 0x72, 0xc6, 0xd9, 0x7b, 0x75, 0xa5, 0x00, 0x03, 0xbc, 0xcd, 0x4d, 0x74, + 0x9e, 0xa0, 0xd7, 0x82, 0xd2, 0x79, 0x03, 0x77, 0xb3, 0x8c, 0x8c, 0x70, 0xf1, 0x71, 0xe5, 0xb1, 0xe0, 0x9e, 0xfd, + 0x42, 0x2c, 0x8d, 0x66, 0x1a, 0x8c, 0xd9, 0xbc, 0x60, 0x81, 0x42, 0x05, 0x0a, 0x2c, 0x67, 0xda, 0xd2, 0xb4, 0x1a, + 0xf2, 0xfd, 0x03, 0xb4, 0x36, 0xad, 0x06, 0x7c, 0xff, 0xa0, 0x8e, 0xb2, 0x43, 0xc8, 0x72, 0xe4, 0x67, 0x50, 0xaf, + 0xeb, 0xc8, 0xa4, 0x98, 0xec, 0x7e, 0x7d, 0xa9, 0x3f, 0xaa, 0x1b, 0x70, 0xfd, 0x00, 0x04, 0xb0, 0x01, 0x38, 0x04, + 0xaa, 0xc1, 0xd2, 0x88, 0x60, 0x51, 0xa6, 0xd0, 0xbe, 0x86, 0xde, 0x1b, 0x0d, 0xff, 0x05, 0xee, 0x22, 0x72, 0xe5, + 0x7f, 0x82, 0xc0, 0x5f, 0x51, 0xa6, 0x95, 0x29, 0xfe, 0x27, 0x5a, 0xbd, 0x42, 0x39, 0x6b, 0x5a, 0xf3, 0x41, 0xb4, + 0x26, 0x42, 0x35, 0x63, 0x08, 0xfe, 0xad, 0x2c, 0xd3, 0x96, 0xaa, 0x4a, 0x7d, 0x68, 0xbc, 0xd6, 0x0a, 0x67, 0xf9, + 0x38, 0xf2, 0x5e, 0x63, 0xe8, 0xd8, 0xc4, 0x59, 0xca, 0xa9, 0xd4, 0xd9, 0xa7, 0x7d, 0x19, 0x39, 0xc0, 0xe9, 0x84, + 0x8d, 0xa7, 0xc9, 0xa1, 0x9c, 0x26, 0x0e, 0x32, 0x3f, 0x67, 0x18, 0x59, 0xd5, 0x80, 0xb0, 0x28, 0x1b, 0x4a, 0x5b, + 0x80, 0x49, 0x4e, 0x08, 0x99, 0x62, 0x28, 0x8a, 0x7c, 0xa4, 0xfb, 0x61, 0xbd, 0x59, 0xdd, 0x17, 0xef, 0x34, 0xc0, + 0x69, 0x98, 0x40, 0x20, 0xf0, 0x22, 0xbe, 0xc9, 0xc4, 0x25, 0x78, 0x0c, 0x0f, 0xe0, 0x4b, 0x70, 0x93, 0x4b, 0xd9, + 0x6f, 0x55, 0x98, 0xe3, 0xda, 0x02, 0x06, 0x0d, 0x56, 0x0f, 0xa2, 0xc3, 0xa5, 0xb4, 0xd9, 0x55, 0x80, 0xd8, 0x98, + 0x42, 0x2c, 0x0b, 0xb6, 0xb6, 0xec, 0xd9, 0xcf, 0xaa, 0x69, 0x68, 0x9d, 0x70, 0x2c, 0x2e, 0x73, 0x88, 0xa2, 0x32, + 0x88, 0xc1, 0x1d, 0xc9, 0xe3, 0xf3, 0x1e, 0x89, 0xf0, 0x82, 0x80, 0x5b, 0x59, 0x2c, 0xc3, 0x15, 0x5d, 0x8e, 0x6e, + 0xe9, 0x7a, 0x74, 0x43, 0xc7, 0x74, 0xf2, 0xf7, 0x31, 0x58, 0x64, 0xeb, 0xd4, 0x3b, 0xba, 0x1e, 0x2d, 0xe9, 0xb7, + 0x63, 0x7a, 0xf0, 0x37, 0x30, 0xe1, 0xc3, 0xc3, 0x84, 0x5e, 0x80, 0x63, 0x17, 0xa9, 0xd1, 0x53, 0xd3, 0x37, 0x38, + 0xac, 0x46, 0xf9, 0x90, 0x8f, 0x72, 0xca, 0x47, 0xc5, 0xb0, 0x1a, 0x81, 0xa7, 0x63, 0x35, 0xe4, 0xa3, 0x8a, 0xf2, + 0xd1, 0xf9, 0xb0, 0x1a, 0x9d, 0x93, 0x66, 0xd3, 0x5f, 0x57, 0xfc, 0xaa, 0x64, 0x29, 0x6c, 0x0b, 0x58, 0xbe, 0x9e, + 0x57, 0x54, 0xea, 0xaf, 0x6a, 0x73, 0x32, 0x5b, 0xce, 0xde, 0x5e, 0x77, 0x39, 0xb1, 0x78, 0xdc, 0x36, 0x1d, 0xae, + 0xbe, 0x9c, 0xa8, 0x93, 0x5e, 0x21, 0x3f, 0x8c, 0xa7, 0x42, 0x9d, 0x43, 0x60, 0x26, 0x31, 0x0b, 0x63, 0x86, 0xcd, + 0xd4, 0x69, 0xa0, 0xc0, 0xc9, 0x46, 0x9e, 0x8b, 0x62, 0x36, 0xca, 0x29, 0xbc, 0x8f, 0x09, 0x89, 0x04, 0x9c, 0x55, + 0x47, 0xd5, 0xa8, 0x80, 0x98, 0x23, 0x2c, 0xc4, 0x47, 0xe8, 0x97, 0xfa, 0xc8, 0x43, 0x02, 0xcf, 0xb0, 0xaf, 0xc5, + 0x20, 0x86, 0x23, 0xde, 0x56, 0x56, 0xcd, 0xc2, 0x04, 0x2a, 0xab, 0x86, 0xa5, 0xa9, 0xac, 0xa0, 0xd9, 0xa8, 0xf2, + 0x2b, 0xab, 0x70, 0x8c, 0x12, 0x42, 0xa2, 0x52, 0x57, 0x06, 0xea, 0x93, 0x84, 0x85, 0xa5, 0xae, 0xec, 0x5c, 0x7d, + 0x74, 0xee, 0x57, 0x76, 0x0e, 0x2e, 0xa4, 0x83, 0xc4, 0xbf, 0x4a, 0xe5, 0x69, 0xfb, 0x3a, 0xd8, 0x58, 0x55, 0x74, + 0xc3, 0x6f, 0xab, 0x22, 0x8e, 0x4a, 0xea, 0x62, 0x40, 0xe3, 0xc2, 0x88, 0x24, 0xd5, 0x6b, 0x14, 0xfc, 0x21, 0x41, + 0x54, 0x1a, 0x83, 0x57, 0x67, 0xd2, 0xb5, 0x52, 0x2b, 0x2a, 0x06, 0xe5, 0xa0, 0x80, 0xfb, 0x53, 0xde, 0x5a, 0x48, + 0x3f, 0x43, 0x44, 0x65, 0x28, 0x6f, 0xf0, 0x4f, 0x0c, 0x9e, 0xcc, 0x56, 0x69, 0x98, 0x8c, 0xee, 0x68, 0x3c, 0x5a, + 0x22, 0x1c, 0x0c, 0x5b, 0xa7, 0x0a, 0x6f, 0xfd, 0x02, 0xd2, 0x6f, 0x69, 0x3c, 0xba, 0xa1, 0xa9, 0xb5, 0x39, 0x35, + 0x50, 0x57, 0xbd, 0x31, 0xbd, 0x8d, 0xe0, 0xf5, 0x5d, 0xb4, 0xa4, 0xb0, 0x95, 0x8e, 0xf3, 0xec, 0x52, 0x44, 0x29, + 0x45, 0x04, 0xc2, 0x35, 0x22, 0x07, 0x2e, 0x35, 0xda, 0xe0, 0x7a, 0x00, 0x65, 0x68, 0xb8, 0xc0, 0xe5, 0x20, 0x1e, + 0x2d, 0x3d, 0x32, 0xb5, 0xd4, 0x17, 0x59, 0x84, 0x8f, 0x76, 0x36, 0x5a, 0x8a, 0x67, 0xc4, 0xc2, 0xb8, 0x82, 0x21, + 0xd4, 0x85, 0x95, 0xa6, 0x20, 0xe9, 0x02, 0x47, 0xf6, 0xc2, 0xb8, 0x0a, 0x37, 0x60, 0x5a, 0x74, 0x07, 0xe6, 0x51, + 0xa0, 0x70, 0x70, 0x09, 0xd2, 0x4f, 0x28, 0xdb, 0x39, 0x4a, 0x93, 0xc3, 0x9b, 0xa0, 0x74, 0x67, 0x82, 0x90, 0x76, + 0x75, 0x93, 0x2d, 0xe9, 0x1b, 0x6c, 0xef, 0xd0, 0xa9, 0xa8, 0xa0, 0xfa, 0xdc, 0x82, 0xc9, 0x92, 0x0d, 0xc2, 0x96, + 0x30, 0x3d, 0xd3, 0x6b, 0xc0, 0x9e, 0xde, 0x3f, 0xd8, 0x99, 0xef, 0x62, 0xf6, 0x69, 0xbf, 0x8c, 0xc6, 0xca, 0x82, + 0x37, 0xb7, 0xc4, 0x6e, 0xc9, 0xc6, 0xd3, 0xe5, 0x61, 0x39, 0x5d, 0x22, 0xb1, 0x33, 0x74, 0x8b, 0xf1, 0xf9, 0x72, + 0x41, 0x13, 0x3c, 0xdb, 0x58, 0x35, 0x5f, 0x1a, 0xb4, 0x94, 0x94, 0xe1, 0x7a, 0x5b, 0xa2, 0xff, 0xbf, 0xba, 0xf8, + 0xa5, 0x00, 0x2f, 0xc1, 0x58, 0x00, 0x08, 0xf7, 0x60, 0x5a, 0x90, 0xda, 0x28, 0x1b, 0xcb, 0x34, 0x4c, 0x71, 0x11, + 0x98, 0x94, 0x7e, 0x3f, 0xcc, 0x59, 0x4a, 0x3c, 0xe8, 0x50, 0x77, 0x6a, 0xa7, 0xbe, 0x10, 0x04, 0x78, 0x24, 0x75, + 0x8e, 0x4d, 0xfe, 0x3e, 0x9e, 0x05, 0x6a, 0x20, 0x82, 0x28, 0x3b, 0xc4, 0x47, 0x0c, 0x5c, 0x14, 0xe9, 0xb8, 0x9d, + 0xae, 0x88, 0x8b, 0xdd, 0x63, 0x16, 0xe2, 0x24, 0x61, 0xae, 0x59, 0x36, 0x64, 0x55, 0x84, 0x09, 0xba, 0x30, 0x30, + 0xcb, 0x1b, 0xb2, 0x6a, 0xff, 0x00, 0x22, 0xb5, 0xda, 0x32, 0x56, 0x5d, 0x65, 0x7c, 0x0b, 0x40, 0xd6, 0x8c, 0xb1, + 0x83, 0xbf, 0x8d, 0x67, 0xea, 0x9b, 0x28, 0xe4, 0x47, 0x07, 0x7f, 0x83, 0xe4, 0xc3, 0x6f, 0x91, 0x99, 0x83, 0xe4, + 0x46, 0x41, 0x97, 0xcd, 0x59, 0xd7, 0x50, 0x9a, 0xb8, 0xf6, 0x4a, 0xbd, 0xf6, 0xa4, 0x59, 0x7b, 0x05, 0xba, 0x53, + 0x1b, 0xde, 0x43, 0xd9, 0xce, 0x82, 0x09, 0x3a, 0x9a, 0xdd, 0x81, 0x0e, 0xde, 0x29, 0x82, 0x5e, 0x26, 0xa1, 0xf1, + 0x08, 0x55, 0x46, 0xbd, 0x18, 0x0f, 0xaa, 0x93, 0x75, 0xc9, 0x3c, 0x03, 0xe6, 0xd8, 0x9e, 0x43, 0x62, 0x98, 0xab, + 0x83, 0x3a, 0x65, 0xe5, 0x30, 0xc7, 0x03, 0x78, 0xcd, 0xe4, 0x50, 0x0c, 0x72, 0x8d, 0xf2, 0x7d, 0xc1, 0x8a, 0x61, + 0x39, 0xc8, 0x35, 0x37, 0x33, 0x6d, 0xc6, 0xa6, 0x4d, 0x74, 0x78, 0xe6, 0x15, 0x3b, 0x5a, 0xf5, 0x80, 0x8f, 0x05, + 0x4f, 0x66, 0xdf, 0xf3, 0xf1, 0x0d, 0x70, 0x32, 0x9b, 0xdb, 0x68, 0x49, 0xef, 0xa2, 0x94, 0xde, 0x44, 0x6b, 0xba, + 0x8c, 0x2e, 0x8c, 0x89, 0x71, 0x52, 0xc3, 0x39, 0x00, 0xad, 0x02, 0x48, 0x3c, 0xf5, 0xeb, 0x3d, 0x4f, 0xaa, 0x70, + 0x49, 0x53, 0x70, 0x1b, 0xf6, 0xed, 0x33, 0xaf, 0x7c, 0x89, 0xd4, 0x06, 0x31, 0xd6, 0xac, 0xa1, 0xe2, 0xc6, 0x5b, + 0xf7, 0x91, 0xa8, 0x61, 0xe7, 0xba, 0xd8, 0x44, 0xd5, 0x70, 0x32, 0x2d, 0x01, 0xb1, 0xb5, 0x1c, 0x0e, 0xdd, 0x11, + 0xb2, 0x7b, 0xfc, 0xe8, 0x40, 0xcf, 0x3d, 0x69, 0xb1, 0x6d, 0x5b, 0xfe, 0xc0, 0x10, 0xa6, 0xf4, 0xf3, 0x47, 0x3e, + 0x20, 0x56, 0x5c, 0xc2, 0xd9, 0x08, 0xd4, 0xd1, 0x0a, 0x9d, 0x7e, 0xab, 0xc2, 0x42, 0x1f, 0xe0, 0x9b, 0xdb, 0x28, + 0xa1, 0x77, 0x51, 0xee, 0x91, 0xb5, 0x65, 0xcd, 0xe4, 0xf4, 0x2c, 0x0b, 0x79, 0xfb, 0x40, 0x2f, 0x17, 0x00, 0xa2, + 0x35, 0x88, 0x7d, 0xa9, 0xeb, 0x01, 0x38, 0x0d, 0xa1, 0x49, 0x68, 0x04, 0x57, 0x15, 0x84, 0x11, 0x70, 0x25, 0xe1, + 0x6f, 0x30, 0x51, 0x81, 0x2f, 0xc0, 0x45, 0x26, 0x4d, 0x73, 0x1e, 0xd4, 0xfe, 0x48, 0x9e, 0x16, 0x6d, 0x6f, 0x57, + 0x18, 0x4d, 0x30, 0xf6, 0x44, 0xfb, 0x3c, 0x52, 0x8e, 0xe2, 0x22, 0x09, 0xb3, 0xd1, 0xad, 0x3a, 0xcf, 0x69, 0x36, + 0xba, 0xd3, 0xbf, 0x2a, 0x3a, 0xa6, 0xdf, 0xe9, 0x80, 0x36, 0x4a, 0xfa, 0xd6, 0x71, 0x36, 0xa0, 0xf5, 0x62, 0x69, + 0xfc, 0xaf, 0xe5, 0xe8, 0x96, 0xca, 0xd1, 0x9d, 0x6f, 0x49, 0x35, 0x99, 0x16, 0x87, 0x02, 0x0d, 0xa9, 0x3a, 0xbf, + 0x2f, 0x80, 0x9f, 0x2b, 0x8d, 0xef, 0xb4, 0xf9, 0xde, 0x6b, 0xff, 0x79, 0x27, 0x4f, 0xa0, 0x58, 0xa2, 0x82, 0x55, + 0x23, 0xb0, 0x63, 0x5f, 0xe7, 0x71, 0x61, 0x46, 0x29, 0xa6, 0xd6, 0xa4, 0x1f, 0x03, 0x57, 0x4c, 0x7b, 0x05, 0xb8, + 0x5a, 0x82, 0x93, 0x00, 0xc4, 0xd0, 0x84, 0x3d, 0x3b, 0x86, 0xa8, 0xe7, 0xc6, 0x31, 0x4a, 0x36, 0xdc, 0x03, 0x62, + 0x2d, 0xf3, 0x56, 0x2e, 0x01, 0x09, 0xbc, 0xf5, 0x30, 0x29, 0x00, 0x63, 0xb0, 0x5c, 0x12, 0x9d, 0xc7, 0x43, 0x9f, + 0x50, 0x2f, 0x34, 0xea, 0x84, 0x6c, 0x6c, 0x09, 0x1c, 0x7f, 0x58, 0x1f, 0x02, 0xc1, 0xab, 0x3c, 0xd7, 0x5f, 0x69, + 0x5d, 0x7f, 0xa9, 0xf4, 0xdc, 0xb1, 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, 0x93, 0x54, 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, 0x73, 0x58, 0x3d, + 0xe6, 0x83, 0xdf, 0x71, 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, 0x73, 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, 0x25, 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, + 0x0b, 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, 0x27, 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, 0x0c, 0xeb, + 0xe8, 0xc2, 0x8f, 0xfe, 0x62, 0x5d, 0xd8, 0x33, 0x32, 0x95, 0x87, 0xe5, 0x70, 0x32, 0x1d, 0x0c, 0xa4, 0x8b, 0xe3, + 0x76, 0x9c, 0xcd, 0x7f, 0x99, 0xcb, 0xc5, 0x02, 0x75, 0xdf, 0x38, 0xaf, 0x33, 0xfd, 0x37, 0xd2, 0xce, 0x07, 0x6f, + 0x8e, 0x7f, 0x3b, 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, 0x65, 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, 0x40, 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, + 0x36, 0xe5, 0x0c, 0x0e, 0x51, 0x3a, 0x06, 0x19, 0xad, 0x80, 0xdf, 0x42, 0xfd, 0x6e, 0x9d, 0xf8, 0x3e, 0xf4, 0xab, + 0xa0, 0x17, 0x31, 0x30, 0x1c, 0xd1, 0x64, 0x3f, 0xe4, 0x83, 0xc9, 0x00, 0xb4, 0x25, 0xde, 0xee, 0x6b, 0x69, 0xc5, + 0xcd, 0xe9, 0xd2, 0xe9, 0xfe, 0x49, 0x9b, 0x20, 0x89, 0x54, 0xb2, 0x52, 0x11, 0x03, 0x08, 0x65, 0xa9, 0xb6, 0xc9, + 0x12, 0x2c, 0x2b, 0xcc, 0x92, 0xe6, 0x06, 0x25, 0x71, 0x77, 0x33, 0x70, 0x8c, 0x9a, 0x75, 0x1c, 0x96, 0x2d, 0x37, + 0x6a, 0x80, 0xcf, 0x49, 0x58, 0x61, 0x6f, 0x38, 0x33, 0xe9, 0x9d, 0xe9, 0x70, 0x75, 0xcc, 0xd9, 0x1b, 0x8e, 0x60, + 0x1c, 0x09, 0xde, 0x78, 0xe8, 0x92, 0x69, 0xa8, 0xc8, 0x94, 0x71, 0x30, 0xed, 0x01, 0xee, 0x3d, 0x07, 0xe3, 0x30, + 0x36, 0xa8, 0x2c, 0xa9, 0x4f, 0xbd, 0xbb, 0x10, 0x08, 0xd2, 0x5a, 0x2f, 0xf3, 0x19, 0x9e, 0x9e, 0x11, 0xca, 0xfe, + 0x90, 0xc3, 0x17, 0x60, 0x47, 0x41, 0x8e, 0x26, 0xfc, 0xd9, 0xe3, 0xdd, 0x40, 0x55, 0x7c, 0x10, 0xec, 0xc5, 0x22, + 0xdd, 0x0b, 0x06, 0x02, 0x7e, 0x15, 0x7c, 0xaf, 0x92, 0x72, 0xef, 0x22, 0x2e, 0xf6, 0xe2, 0x55, 0x5c, 0x54, 0x7b, + 0x37, 0x59, 0xb5, 0xdc, 0x33, 0x1d, 0x02, 0x68, 0xde, 0x60, 0x10, 0x0f, 0x82, 0xbd, 0x60, 0x50, 0x98, 0xa9, 0x5d, + 0xb1, 0xb2, 0x71, 0x9c, 0x99, 0x10, 0x65, 0x41, 0x33, 0x40, 0x58, 0xe3, 0x34, 0x00, 0x3e, 0x75, 0xcd, 0x52, 0x7a, + 0x81, 0xe1, 0x06, 0xc4, 0x74, 0x0d, 0x7d, 0x00, 0x1e, 0x79, 0x4d, 0x63, 0x58, 0x02, 0x17, 0x83, 0x01, 0x59, 0x43, + 0xe4, 0x82, 0x35, 0xb5, 0x41, 0x1c, 0xc2, 0xb5, 0xb2, 0xd3, 0xde, 0x05, 0x66, 0xda, 0x6e, 0x01, 0x51, 0x79, 0x42, + 0xfa, 0x7d, 0xfb, 0x0d, 0xf5, 0x2f, 0xd8, 0x4b, 0xb0, 0xbf, 0x2a, 0xaa, 0x30, 0x91, 0x4a, 0xf3, 0x7d, 0xc9, 0x8e, + 0x06, 0x2a, 0xe2, 0xf0, 0x8e, 0x23, 0x45, 0x1b, 0x95, 0xcb, 0xb2, 0x27, 0xcb, 0x86, 0xaf, 0xc4, 0x15, 0x77, 0x7e, + 0x5c, 0x95, 0x94, 0x79, 0x95, 0xad, 0x14, 0xfb, 0x37, 0xe3, 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, 0x17, 0xcd, 0x23, 0xc0, 0x5c, 0xfb, 0x6c, 0x05, + 0x05, 0xa9, 0xcf, 0x2a, 0xf4, 0x6e, 0x85, 0x84, 0x57, 0x9a, 0x5d, 0x7a, 0x18, 0x48, 0x19, 0xb7, 0x87, 0x96, 0x30, + 0x69, 0x79, 0x11, 0xde, 0x7b, 0xcd, 0x4d, 0xee, 0x45, 0x88, 0xd1, 0x8b, 0x3c, 0x3b, 0x01, 0x63, 0xdd, 0x25, 0x3b, + 0x1b, 0x9e, 0xf8, 0x0d, 0xcf, 0x59, 0x8b, 0x46, 0xd3, 0x25, 0x4b, 0xfa, 0xfd, 0x18, 0x4c, 0xbc, 0x53, 0x96, 0xc3, + 0xaf, 0x7c, 0x41, 0xd7, 0x0c, 0x30, 0xc5, 0xe8, 0x05, 0x24, 0xa4, 0x88, 0x44, 0xb2, 0x56, 0x27, 0xc9, 0x67, 0xba, + 0x0b, 0xc0, 0xe8, 0x17, 0xb3, 0x34, 0x5a, 0xde, 0x6b, 0x66, 0x81, 0xe4, 0x19, 0xfa, 0xae, 0x83, 0xed, 0x8d, 0x7d, + 0x90, 0x72, 0x7e, 0x28, 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, 0x0b, 0x1c, 0x61, 0x1e, 0xac, 0xdb, 0x7c, 0xb2, 0x6f, 0x0a, 0x1c, 0x22, 0x4f, 0xda, + 0x68, 0x0a, 0xe8, 0xde, 0xc5, 0xe3, 0xae, 0x7e, 0x5b, 0xba, 0x0b, 0x94, 0x68, 0xa7, 0xe2, 0x86, 0x1f, 0x13, 0x75, + 0x3a, 0xd3, 0x86, 0xd0, 0xbf, 0x32, 0xe2, 0xfe, 0xd2, 0xb8, 0x8a, 0x37, 0xbd, 0xcb, 0x67, 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, 0x8c, 0xc4, 0xe3, 0x62, 0x10, 0x3f, 0x96, + 0x75, 0xbd, 0x7b, 0xae, 0xdc, 0xdf, 0x47, 0xe4, 0x59, 0x77, 0xf6, 0x52, 0x09, 0x1b, 0x03, 0xcf, 0xae, 0x05, 0x84, + 0x53, 0xf0, 0x44, 0xb6, 0x96, 0x3e, 0x74, 0x6e, 0xf7, 0xb1, 0x65, 0x92, 0x20, 0xe8, 0x79, 0x9b, 0x4d, 0xa2, 0xd8, + 0xd9, 0xe6, 0xd1, 0x87, 0x53, 0x20, 0xa1, 0xdb, 0x6d, 0xb3, 0xae, 0xd6, 0x80, 0x62, 0x1a, 0x8e, 0xf9, 0x7e, 0x31, + 0xba, 0xf1, 0xdd, 0xf5, 0xf7, 0x8b, 0xd1, 0x92, 0x0c, 0x27, 0x66, 0xf2, 0xe3, 0xa3, 0xf1, 0x2c, 0x8e, 0x26, 0x75, + 0xc7, 0x69, 0xa1, 0xf1, 0x4f, 0xbd, 0x5b, 0x28, 0x02, 0xa7, 0x62, 0x04, 0x47, 0x4e, 0x85, 0x72, 0x52, 0x6a, 0x60, + 0xf8, 0xef, 0x55, 0x3b, 0xda, 0xb4, 0x37, 0x71, 0x95, 0x2c, 0x33, 0x71, 0xa9, 0xc3, 0x87, 0xeb, 0xe8, 0xe2, 0x36, + 0xa0, 0x9d, 0x77, 0x99, 0x76, 0xfc, 0x3a, 0x69, 0xd0, 0x13, 0x57, 0x33, 0x03, 0x6e, 0xdd, 0x8f, 0xd0, 0x0c, 0x81, + 0xd1, 0xf2, 0xfc, 0x1d, 0x62, 0x6e, 0xff, 0xaa, 0x6c, 0x7e, 0x15, 0xed, 0x73, 0x64, 0xa4, 0x6c, 0x93, 0x91, 0x0a, + 0x8c, 0x30, 0xa5, 0x48, 0xe2, 0x2a, 0x84, 0x40, 0xf6, 0x5f, 0x52, 0x5c, 0x8b, 0xa5, 0xf7, 0x1a, 0x84, 0x09, 0xb6, + 0x0b, 0xda, 0xaf, 0x6e, 0xe7, 0xb6, 0xd2, 0x62, 0x8f, 0xd4, 0xf7, 0xb9, 0xb3, 0x5d, 0xd1, 0xe4, 0xef, 0xcb, 0x06, + 0xb4, 0x01, 0x44, 0x79, 0x5f, 0x1f, 0x95, 0xc0, 0xc9, 0x88, 0x1b, 0x4a, 0x8c, 0x5e, 0xd0, 0xd5, 0x89, 0xdc, 0xb3, + 0x53, 0xf3, 0xa6, 0x62, 0xa6, 0xe2, 0xca, 0x37, 0x7b, 0xe6, 0x3f, 0x18, 0x0a, 0x2a, 0xc0, 0xc0, 0xdb, 0x9c, 0xf1, + 0xe8, 0x40, 0x77, 0x63, 0x74, 0x5a, 0xb0, 0x59, 0x50, 0x97, 0x75, 0xd3, 0xc6, 0x83, 0x46, 0x1c, 0x14, 0xc5, 0xaa, + 0x50, 0x23, 0xe1, 0x89, 0x40, 0xc0, 0x94, 0x5d, 0xf1, 0xc8, 0x08, 0x6a, 0x7a, 0x13, 0x0a, 0x1b, 0x0a, 0xfe, 0x2a, + 0x51, 0x4d, 0x6f, 0x42, 0x9b, 0x4c, 0x9c, 0x66, 0x10, 0xc1, 0x8c, 0xd8, 0xee, 0xb7, 0x80, 0x36, 0xb7, 0x66, 0xb4, + 0xa9, 0x6b, 0xab, 0xad, 0x42, 0x2e, 0x29, 0x52, 0x96, 0xff, 0x4e, 0x4d, 0x05, 0x25, 0xb5, 0x5c, 0xf4, 0x26, 0x4d, + 0x17, 0x3d, 0x9e, 0x19, 0x49, 0xa0, 0x72, 0xcb, 0x1d, 0xa3, 0x3f, 0x84, 0x05, 0x1e, 0x31, 0x71, 0x62, 0xc1, 0xdc, + 0xea, 0x88, 0x65, 0x73, 0xb1, 0x18, 0xad, 0x24, 0x84, 0x0d, 0x3e, 0x64, 0xd9, 0xbc, 0xd4, 0x0f, 0xa1, 0x2f, 0x2c, + 0x3d, 0x01, 0xbb, 0xd8, 0x60, 0x25, 0xcb, 0x00, 0x7c, 0x2f, 0xe8, 0x66, 0x25, 0xcb, 0x48, 0xaa, 0xee, 0xc7, 0x35, + 0x96, 0xa0, 0xd2, 0x0a, 0x95, 0x96, 0xd4, 0x58, 0x10, 0xf8, 0xaa, 0xea, 0xf2, 0x21, 0xd9, 0x55, 0xa0, 0x9e, 0x3a, + 0x6a, 0xc0, 0x29, 0x50, 0x55, 0x60, 0x41, 0x12, 0x54, 0x86, 0xae, 0x0a, 0x4c, 0x2b, 0x30, 0xcd, 0x54, 0xe1, 0xa2, + 0xcc, 0x0e, 0xa5, 0x59, 0x2f, 0xf9, 0x2c, 0x1e, 0x84, 0xc9, 0x30, 0x26, 0x8f, 0x11, 0x6a, 0x7f, 0x3f, 0x8f, 0x62, + 0x2d, 0x97, 0x5c, 0x39, 0xbf, 0xf8, 0x9b, 0xcf, 0xd8, 0xeb, 0x9e, 0x61, 0xb0, 0x00, 0x67, 0x69, 0x7b, 0x95, 0x89, + 0x77, 0xb2, 0x15, 0x1c, 0x07, 0xb3, 0x28, 0x87, 0x55, 0x4f, 0x8e, 0x68, 0x2e, 0x72, 0xed, 0x5d, 0x84, 0xc8, 0x41, + 0x66, 0x8f, 0x01, 0x76, 0x23, 0x7c, 0x1d, 0x5a, 0x9b, 0x5b, 0x5d, 0x21, 0xfe, 0x46, 0x89, 0xc4, 0x4f, 0x52, 0x7e, + 0x5c, 0xaf, 0x54, 0xae, 0xca, 0xe0, 0xb1, 0xea, 0x66, 0xf0, 0x4c, 0xfb, 0x1e, 0x6b, 0xff, 0xd6, 0x76, 0x73, 0xbc, + 0xf7, 0xe0, 0x41, 0xeb, 0x7f, 0xeb, 0x49, 0x08, 0xed, 0x95, 0x93, 0xd4, 0x1d, 0x35, 0x7a, 0x66, 0xb2, 0x46, 0x54, + 0xc2, 0xd4, 0xee, 0x54, 0x8e, 0x81, 0x9a, 0x0e, 0xe0, 0x5a, 0xa2, 0x26, 0xe8, 0x49, 0xc1, 0xc6, 0x70, 0xc4, 0x59, + 0x1c, 0xb4, 0xc3, 0x18, 0xc5, 0xcb, 0xb9, 0x12, 0x2f, 0xe7, 0x47, 0x8c, 0x03, 0xb4, 0x16, 0x20, 0xd5, 0x6b, 0xd8, + 0xcf, 0x5c, 0xc1, 0x02, 0x9b, 0x3b, 0xdf, 0x81, 0x05, 0x32, 0xc4, 0xc9, 0xe6, 0x38, 0xd9, 0xe3, 0x5a, 0xcf, 0xbd, + 0xc0, 0xc7, 0x49, 0xbd, 0xf0, 0xea, 0x2a, 0xdb, 0x75, 0x2d, 0x59, 0x39, 0x2f, 0x06, 0x13, 0x08, 0xca, 0x52, 0xce, + 0x8b, 0xe1, 0x64, 0x41, 0x73, 0xf8, 0xb1, 0x68, 0xa0, 0x43, 0x2c, 0x07, 0x09, 0x5c, 0x3a, 0x7b, 0x0c, 0x78, 0x43, + 0xa9, 0xc5, 0xdd, 0x58, 0x47, 0x8e, 0x75, 0x14, 0xfb, 0x61, 0x0c, 0xb8, 0xb2, 0x4e, 0xe0, 0x7d, 0xff, 0xf5, 0xb1, + 0x09, 0xc8, 0xaa, 0x5d, 0xe1, 0xd5, 0x28, 0x77, 0x5d, 0x69, 0xf4, 0x25, 0xa5, 0x27, 0xbc, 0xe0, 0xa9, 0x64, 0xbb, + 0xed, 0x19, 0x38, 0x5b, 0xe2, 0x21, 0xf1, 0x8e, 0x11, 0xbd, 0x98, 0x36, 0x32, 0x73, 0x02, 0x67, 0xb6, 0xbb, 0x6c, + 0x63, 0x7e, 0xec, 0x00, 0x07, 0x8b, 0x20, 0x24, 0x6e, 0x08, 0xc3, 0xc4, 0x8e, 0xca, 0xa1, 0x16, 0xc2, 0x75, 0x2d, + 0xbc, 0x8e, 0xd3, 0x32, 0x06, 0x17, 0x69, 0x6d, 0x9b, 0x78, 0x0f, 0x5d, 0xf7, 0xfc, 0x98, 0x5b, 0x1d, 0xa3, 0x2d, + 0xa4, 0xdf, 0x8e, 0x4e, 0xef, 0x39, 0x0c, 0x40, 0xd3, 0x83, 0x59, 0xd5, 0x3e, 0x93, 0xb8, 0x39, 0xed, 0x04, 0x21, + 0x11, 0x88, 0xa2, 0x74, 0x46, 0x98, 0xfe, 0x9d, 0xe6, 0xb2, 0x8a, 0x56, 0x0f, 0xf2, 0xcc, 0x21, 0xcf, 0x42, 0x6f, + 0x7b, 0xd0, 0xaa, 0xb9, 0x1b, 0x8c, 0x13, 0xb7, 0xdb, 0x3b, 0xff, 0x6f, 0x59, 0xd7, 0x56, 0x6b, 0xc4, 0xe3, 0x76, + 0xf5, 0x83, 0xc6, 0x5e, 0xed, 0xa9, 0x18, 0x30, 0x2b, 0xe9, 0x9d, 0x51, 0x25, 0x2f, 0x32, 0x5e, 0xe2, 0x49, 0xb5, + 0x6a, 0xf8, 0x78, 0xdf, 0x64, 0x23, 0xf3, 0x40, 0xa6, 0x80, 0x78, 0x7e, 0x93, 0x1a, 0xf5, 0x71, 0x8a, 0x12, 0xf0, + 0x77, 0x3a, 0xbe, 0x11, 0xfd, 0x68, 0x5f, 0x5c, 0xf2, 0xea, 0xe4, 0x46, 0x98, 0x17, 0x2f, 0xac, 0xce, 0x9f, 0xbe, + 0x29, 0x7c, 0xe8, 0x70, 0xd4, 0xde, 0x41, 0x91, 0x25, 0x13, 0x47, 0x13, 0x23, 0x6b, 0x13, 0xb3, 0x8f, 0x0a, 0x2e, + 0x26, 0xaa, 0xd0, 0xb3, 0xce, 0x9e, 0x30, 0x05, 0xe8, 0x1b, 0xc7, 0xa8, 0x64, 0x0c, 0x0b, 0x06, 0xea, 0x34, 0x25, + 0x44, 0x0f, 0xc5, 0x0c, 0xe3, 0x15, 0x03, 0x28, 0x4c, 0xa1, 0x40, 0x14, 0x9d, 0x7d, 0x38, 0xd0, 0x84, 0x7e, 0xff, + 0x26, 0xd5, 0x19, 0x68, 0x59, 0x4f, 0x0b, 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, 0x3f, 0x36, + 0xe8, 0x7a, 0x2b, 0xd6, 0x1a, 0xda, 0x9d, 0x20, 0x23, 0x34, 0x5f, 0xe8, 0x20, 0x64, 0xa8, 0x9c, 0x84, 0xae, 0x55, + 0x1a, 0xaf, 0xc0, 0x25, 0xd3, 0x6c, 0xb4, 0x8c, 0xcb, 0x30, 0xb0, 0x5f, 0x05, 0x16, 0x93, 0x03, 0x93, 0x4e, 0xd7, + 0xe7, 0xcf, 0xe5, 0xd5, 0x4a, 0x0a, 0x2e, 0x2a, 0x05, 0xd1, 0x6f, 0x70, 0xdf, 0x4d, 0x5c, 0x75, 0xd6, 0xac, 0x95, + 0x3e, 0xf4, 0xad, 0xcf, 0xda, 0xb8, 0x2f, 0x0c, 0x8e, 0xc1, 0xce, 0x47, 0xc4, 0x40, 0x1a, 0x54, 0xba, 0xc5, 0xa1, + 0x09, 0xd0, 0xa5, 0x43, 0x0a, 0x59, 0x32, 0x95, 0xa9, 0x12, 0x54, 0x7c, 0xe3, 0xf7, 0x52, 0x56, 0xa3, 0xbf, 0xd6, + 0xbc, 0xb8, 0x3b, 0xe5, 0x39, 0xc7, 0x31, 0x0a, 0x92, 0x58, 0x5c, 0xc7, 0x65, 0x40, 0x7c, 0xcb, 0xab, 0xe0, 0x20, + 0x35, 0x61, 0x63, 0x76, 0xaa, 0x46, 0xad, 0x57, 0x81, 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, 0x71, 0x92, 0xd5, 0x1f, 0xd1, 0x52, 0x62, 0x2c, 0x54, 0x5d, 0x7c, 0x7c, 0x5e, 0xca, 0x7c, 0x5d, 0x81, + 0x76, 0xf7, 0xa2, 0x8a, 0x0e, 0x9e, 0xae, 0x6e, 0xa7, 0xea, 0x06, 0x13, 0x3d, 0x3d, 0x58, 0xdd, 0xf6, 0xb2, 0xab, + 0x95, 0x2c, 0xaa, 0x58, 0x54, 0x53, 0x85, 0x48, 0x96, 0xc4, 0x79, 0x12, 0x4e, 0xc6, 0xe3, 0xaf, 0xf6, 0x86, 0x7b, + 0x90, 0x81, 0x4c, 0x3f, 0x0d, 0x95, 0xcb, 0xd1, 0x70, 0x32, 0x1e, 0x4f, 0xa5, 0xba, 0xdb, 0x45, 0xa3, 0x49, 0x8d, + 0xf5, 0x0c, 0x13, 0x3d, 0x33, 0x23, 0x7e, 0xbb, 0x8a, 0x45, 0x0a, 0xf1, 0xeb, 0x74, 0xf1, 0x07, 0x4f, 0xc7, 0x8d, + 0xf2, 0xed, 0xa7, 0xcf, 0xea, 0x3f, 0x6a, 0x13, 0xd6, 0xda, 0xb4, 0xfb, 0xf9, 0x1f, 0x87, 0x6a, 0xbe, 0x8f, 0x0e, + 0xf7, 0xf5, 0x8f, 0x3f, 0xea, 0x7a, 0xfa, 0xa6, 0x08, 0xe7, 0xff, 0x0a, 0xd5, 0x7c, 0x1e, 0x17, 0x45, 0x7c, 0x57, + 0x43, 0x24, 0x4f, 0xe1, 0xbc, 0x49, 0xa8, 0xb7, 0x0d, 0xe8, 0x01, 0x99, 0x5e, 0x08, 0x06, 0xdf, 0xbc, 0xaf, 0xc2, + 0x80, 0x97, 0xab, 0x21, 0x17, 0x55, 0x56, 0xdd, 0x0d, 0x31, 0x4f, 0x80, 0x9f, 0x1a, 0xde, 0xec, 0x79, 0x61, 0x88, + 0xcd, 0x45, 0xc1, 0xf9, 0x27, 0x1e, 0x2a, 0xe3, 0xe8, 0x31, 0x1a, 0x47, 0x8f, 0xa9, 0x1a, 0x8c, 0xc9, 0x37, 0x54, + 0x77, 0x66, 0xf2, 0x0d, 0x98, 0x20, 0x65, 0xed, 0x6f, 0x94, 0x71, 0x62, 0x34, 0xa6, 0xd7, 0xaf, 0xf2, 0x6c, 0x05, + 0x4c, 0xf0, 0x52, 0xff, 0xa8, 0x09, 0x7d, 0xcf, 0xdb, 0xd9, 0x47, 0xa3, 0xd1, 0xf3, 0x82, 0x8e, 0x46, 0xa3, 0x8f, + 0x59, 0x4d, 0xe8, 0x4a, 0x74, 0xbc, 0x7f, 0xcf, 0xe9, 0xb9, 0x4c, 0xef, 0xa2, 0x20, 0xa0, 0xcb, 0x2c, 0x4d, 0xb9, + 0x50, 0x65, 0x9d, 0xa6, 0xed, 0xbc, 0xaa, 0x85, 0x08, 0xfc, 0xa3, 0xdb, 0x88, 0x10, 0x44, 0x84, 0x9e, 0xec, 0xf4, + 0x6c, 0x34, 0x1a, 0x9d, 0xa6, 0xa6, 0x5a, 0xc7, 0x90, 0xbf, 0x41, 0xf3, 0x01, 0x67, 0x97, 0x0f, 0xd6, 0x37, 0x26, + 0xda, 0xc9, 0xfe, 0x7f, 0x0f, 0x67, 0xf3, 0xf1, 0xf0, 0xdb, 0xd1, 0xe2, 0xf1, 0x3e, 0x0d, 0x02, 0x1f, 0xb4, 0x3a, + 0xd4, 0xd6, 0x1c, 0xd3, 0xf2, 0x70, 0x3c, 0x25, 0xe5, 0x80, 0x3d, 0xb5, 0xbe, 0x34, 0x5f, 0x3d, 0x05, 0x24, 0x52, + 0x14, 0xa1, 0x06, 0x4e, 0xfa, 0x87, 0x57, 0x91, 0xd7, 0x02, 0xf0, 0xd1, 0x6c, 0x24, 0x03, 0xa3, 0x05, 0x1c, 0x47, + 0x50, 0x5e, 0x6d, 0x4d, 0x23, 0x7a, 0x8c, 0x65, 0x26, 0x2a, 0xe8, 0x78, 0x5a, 0xde, 0x64, 0x55, 0xb2, 0xc4, 0xc0, + 0x46, 0x71, 0xc9, 0x83, 0xaf, 0x82, 0xa8, 0x64, 0x07, 0xcf, 0xa6, 0x0a, 0xde, 0x17, 0x93, 0x52, 0x7e, 0x09, 0x89, + 0xdf, 0x8e, 0x11, 0x02, 0x95, 0x68, 0x8f, 0x45, 0xac, 0xf1, 0x55, 0x2e, 0x63, 0xf0, 0xe0, 0x2c, 0x35, 0xcf, 0x62, + 0x4f, 0x02, 0x6b, 0x7f, 0xd1, 0x6a, 0x8e, 0x84, 0xe6, 0x84, 0x92, 0xc9, 0xfd, 0x92, 0xca, 0xaf, 0x26, 0xe8, 0x15, + 0x04, 0x6e, 0xd5, 0x11, 0x1c, 0x77, 0xd6, 0xb2, 0x41, 0x2f, 0x9f, 0x94, 0xed, 0xcf, 0xff, 0x77, 0x49, 0x17, 0x83, + 0x7d, 0x37, 0x34, 0x27, 0xda, 0x7d, 0xb5, 0x42, 0x46, 0xa9, 0x0a, 0x9f, 0xa7, 0xc4, 0x1a, 0x9f, 0x72, 0x76, 0xb4, + 0x31, 0xdd, 0x19, 0x55, 0x45, 0x76, 0x15, 0x12, 0xdd, 0x2b, 0x07, 0x8a, 0x19, 0x44, 0xd9, 0x08, 0xd7, 0x0f, 0x58, + 0x8b, 0x78, 0x9d, 0xbc, 0xe6, 0x45, 0x95, 0x25, 0xea, 0xfd, 0x75, 0xe3, 0x3d, 0x50, 0x03, 0xd5, 0xa0, 0x77, 0x05, + 0x83, 0x79, 0x3e, 0x29, 0x00, 0xb4, 0xb3, 0xe4, 0xc5, 0x35, 0xf7, 0xe9, 0x46, 0x10, 0xd4, 0xae, 0x99, 0x97, 0x8d, + 0x60, 0x13, 0xf0, 0xd5, 0xbb, 0x02, 0x30, 0x37, 0x42, 0x90, 0x9a, 0x42, 0x28, 0x1c, 0xb8, 0xc0, 0x57, 0x55, 0x91, + 0x9d, 0xaf, 0x2b, 0x8e, 0xc1, 0x3e, 0xbc, 0xb8, 0x89, 0xca, 0x09, 0x8f, 0x87, 0x01, 0xfe, 0x08, 0xa8, 0x0a, 0xb8, + 0x61, 0x3c, 0xec, 0xe0, 0x85, 0xfa, 0xe5, 0xde, 0xa8, 0x3d, 0xc2, 0xde, 0xa4, 0x21, 0x04, 0xd7, 0xc1, 0x87, 0x00, + 0x96, 0x14, 0xa1, 0x27, 0x78, 0xaa, 0x86, 0xc1, 0x45, 0x9e, 0xad, 0x74, 0x52, 0x35, 0xea, 0x68, 0x3e, 0x94, 0xda, + 0x91, 0x1c, 0x50, 0x2f, 0x3d, 0xc6, 0xf4, 0x42, 0xa5, 0xab, 0xa2, 0x9c, 0x11, 0xca, 0x3b, 0x3d, 0x31, 0x2e, 0x4c, + 0x1f, 0x87, 0xc8, 0x2f, 0xef, 0x0a, 0x15, 0xfa, 0x85, 0x2f, 0x00, 0xfc, 0x0a, 0x6e, 0xf7, 0xbb, 0xf1, 0x5d, 0x54, + 0xf6, 0x33, 0xce, 0xf6, 0xff, 0x7b, 0x1e, 0x0f, 0x3f, 0x8d, 0x87, 0xdf, 0x2e, 0x06, 0xe1, 0xd0, 0xfe, 0x24, 0x8f, + 0x1f, 0xed, 0xd3, 0x57, 0xdc, 0x72, 0x25, 0xb0, 0xf0, 0x1b, 0xc1, 0x6d, 0xd4, 0x4a, 0x08, 0xa2, 0x00, 0x6f, 0x14, + 0x6e, 0x35, 0x4e, 0x00, 0xe0, 0x2f, 0xf8, 0xaf, 0x00, 0x8d, 0x84, 0xdc, 0x45, 0x03, 0xf4, 0x03, 0xea, 0xf7, 0xd1, + 0x93, 0x86, 0x81, 0x1c, 0x88, 0x27, 0x54, 0x0c, 0x14, 0xa2, 0xcb, 0x98, 0x28, 0xd8, 0x5f, 0x9b, 0x7d, 0xbb, 0xed, + 0xb5, 0x25, 0x3f, 0xf8, 0xa5, 0x9f, 0x69, 0x62, 0xe6, 0x1d, 0x6e, 0x28, 0x2b, 0xb9, 0x0a, 0x11, 0x1b, 0x4f, 0xff, + 0xca, 0x19, 0xc4, 0x9a, 0xbc, 0xce, 0xc0, 0x87, 0xc1, 0x7e, 0x31, 0x9e, 0x01, 0xdb, 0x00, 0x77, 0x9c, 0x82, 0x5f, + 0x64, 0xe0, 0xd6, 0x2c, 0x62, 0xbc, 0x60, 0xdb, 0x25, 0xd1, 0xef, 0xf7, 0xf2, 0x2c, 0xcc, 0x35, 0xce, 0x72, 0x5e, + 0x1b, 0xb1, 0x3b, 0xea, 0x84, 0x41, 0xdc, 0xae, 0x87, 0x60, 0xa8, 0x86, 0xa0, 0xe8, 0x68, 0x8b, 0xab, 0xd7, 0xd6, + 0x53, 0x98, 0xde, 0xaa, 0xfa, 0x8a, 0xd1, 0x9f, 0x32, 0x13, 0x58, 0x48, 0xbb, 0xe6, 0x58, 0xd7, 0x1c, 0x23, 0xed, + 0xe9, 0xf7, 0x45, 0x83, 0xfc, 0x74, 0x16, 0x1e, 0x04, 0xaa, 0x54, 0xb9, 0x53, 0x16, 0xe5, 0xb6, 0x34, 0x6f, 0x0c, + 0x6b, 0x9a, 0x67, 0x36, 0xae, 0xcb, 0xac, 0xd7, 0x0b, 0x43, 0x74, 0x68, 0xc4, 0x52, 0xb1, 0x36, 0x08, 0xef, 0x63, + 0x12, 0x46, 0x57, 0x20, 0xab, 0x0b, 0xcf, 0x38, 0x41, 0xbe, 0x0c, 0x4c, 0xd6, 0x54, 0xb5, 0x5e, 0x4e, 0x78, 0x6c, + 0xe4, 0xcb, 0x46, 0xd0, 0x20, 0x2f, 0x29, 0xea, 0x4d, 0xdc, 0x8e, 0x7d, 0xd4, 0x42, 0x6a, 0xdc, 0xd4, 0xd3, 0x9e, + 0x26, 0x15, 0x3d, 0xd6, 0xab, 0xd4, 0x2f, 0xb0, 0x2c, 0xb0, 0xe4, 0x83, 0xd0, 0x9e, 0xa6, 0x15, 0x98, 0xe1, 0xda, + 0x66, 0x30, 0xf4, 0xc3, 0xa1, 0x2d, 0x42, 0x67, 0xd4, 0xb6, 0x84, 0xb0, 0x6d, 0x83, 0xb0, 0xf2, 0x9e, 0xc8, 0x57, + 0x4f, 0x3d, 0x46, 0x38, 0xe4, 0x66, 0x33, 0x8b, 0x06, 0x86, 0xf9, 0x95, 0x6c, 0x36, 0x4f, 0x37, 0xd7, 0x8b, 0x8a, + 0x29, 0x60, 0xbb, 0xad, 0x04, 0xc1, 0xbf, 0x1f, 0xb3, 0x19, 0xfe, 0xcd, 0xfa, 0xfd, 0x5e, 0x88, 0xbf, 0x38, 0x06, + 0xef, 0x99, 0x8b, 0x05, 0xfb, 0x08, 0x32, 0x15, 0x12, 0x61, 0xaa, 0x32, 0x7e, 0x63, 0x15, 0x58, 0xc0, 0x99, 0x0f, + 0x54, 0x2e, 0xcc, 0x64, 0x2f, 0x2f, 0xae, 0x21, 0xc7, 0xad, 0x71, 0xca, 0x46, 0x59, 0xa2, 0x5c, 0x17, 0xb2, 0x51, + 0x9c, 0x67, 0x71, 0xc9, 0xcb, 0xed, 0x56, 0x1f, 0x8e, 0x49, 0xc1, 0x81, 0x3d, 0x55, 0x54, 0xaa, 0x64, 0x1d, 0xa9, + 0x6e, 0xfc, 0x65, 0x58, 0xe0, 0x3e, 0xe5, 0xf3, 0xc2, 0xd0, 0x88, 0x3d, 0xb8, 0xbc, 0x33, 0x75, 0x2b, 0xed, 0x85, + 0x05, 0x34, 0xaf, 0x24, 0x64, 0x83, 0xa9, 0x9e, 0x45, 0x6b, 0xcc, 0xc4, 0xbc, 0x58, 0x40, 0x18, 0x99, 0x62, 0x01, + 0x36, 0x53, 0x5c, 0x80, 0x17, 0x49, 0x0c, 0x30, 0x71, 0x31, 0x99, 0x42, 0x3c, 0x73, 0x55, 0x4e, 0xbc, 0x30, 0xf7, + 0xcb, 0xc4, 0x21, 0x65, 0xc0, 0xab, 0xda, 0xa0, 0x89, 0xd9, 0x86, 0xa3, 0x4e, 0x90, 0x13, 0x93, 0xdf, 0x4f, 0x15, + 0x84, 0xb8, 0x13, 0x47, 0xc2, 0x65, 0xc5, 0x76, 0xe1, 0x65, 0x07, 0x62, 0x8c, 0x1a, 0x9c, 0xf2, 0x33, 0x83, 0xa3, + 0x31, 0x38, 0x37, 0xde, 0x09, 0x52, 0x84, 0x31, 0xd9, 0x48, 0x76, 0x25, 0x43, 0x31, 0x8f, 0x17, 0xa0, 0xac, 0x8b, + 0x17, 0x60, 0x59, 0x63, 0x0c, 0x30, 0x41, 0x5e, 0xc5, 0xbd, 0xd0, 0x4f, 0x14, 0x57, 0x88, 0xf4, 0xac, 0x5c, 0x1f, + 0x15, 0xed, 0xd0, 0x17, 0x78, 0xbd, 0x57, 0xe6, 0xb8, 0x59, 0x8f, 0x05, 0x12, 0x1b, 0x02, 0xc6, 0x46, 0x3a, 0x4d, + 0xb5, 0xd6, 0xbd, 0x31, 0xf3, 0xc0, 0xa7, 0xd9, 0x48, 0xc8, 0xea, 0xec, 0x02, 0x44, 0x28, 0x3e, 0x1a, 0x3c, 0xf2, + 0x8b, 0xb8, 0xb3, 0xcc, 0x5b, 0xdb, 0xa2, 0x92, 0x1d, 0x6d, 0x00, 0xa4, 0x4f, 0x47, 0x8b, 0x52, 0x72, 0x8a, 0x92, + 0xd4, 0x6e, 0x53, 0xc0, 0x4a, 0xf2, 0x17, 0x30, 0x04, 0x1b, 0xdb, 0x13, 0x4e, 0xa7, 0x08, 0xf1, 0x89, 0xa6, 0x88, + 0xac, 0x18, 0x96, 0x14, 0xc7, 0xb6, 0x44, 0xd4, 0x4f, 0x5b, 0x96, 0x1d, 0x0c, 0x13, 0x15, 0xf7, 0x45, 0xea, 0x51, + 0xa2, 0x20, 0xa0, 0x7a, 0xc8, 0x41, 0x62, 0x6b, 0x1b, 0x08, 0x0f, 0xc8, 0x23, 0x7a, 0x63, 0xfd, 0x7d, 0xd6, 0x79, + 0x76, 0xa1, 0x39, 0x2a, 0xd7, 0xbb, 0xc2, 0x8c, 0x11, 0x9e, 0x64, 0x06, 0x26, 0xdf, 0x3b, 0xcf, 0x8c, 0x9a, 0xa2, + 0xe7, 0xe1, 0x93, 0x1d, 0x63, 0x44, 0xba, 0x7b, 0x06, 0xdd, 0x04, 0xaf, 0xea, 0xb0, 0xd1, 0xae, 0x14, 0x84, 0x84, + 0xa9, 0x45, 0x13, 0xb3, 0x9e, 0x35, 0xa0, 0xde, 0x6e, 0x7b, 0x7a, 0xae, 0xee, 0x9f, 0xbb, 0xed, 0xb6, 0x87, 0xdd, + 0x7a, 0x91, 0x76, 0x5b, 0x81, 0x57, 0xea, 0x83, 0xf6, 0xf8, 0x73, 0x37, 0xfe, 0xdc, 0x20, 0x79, 0x94, 0x8e, 0x66, + 0xda, 0xfa, 0x20, 0x1c, 0x6e, 0x7a, 0xd7, 0x68, 0xd2, 0xf7, 0x59, 0x28, 0xe9, 0x4a, 0x34, 0xaa, 0xab, 0x9d, 0x49, + 0xe5, 0x83, 0xeb, 0xff, 0xe1, 0x55, 0x80, 0x47, 0x9c, 0xda, 0xd9, 0xf7, 0x36, 0xa8, 0x68, 0xb4, 0x85, 0x23, 0x45, + 0xe8, 0x01, 0x49, 0xb8, 0xaf, 0x65, 0x2d, 0x6e, 0xf3, 0x34, 0x7b, 0x98, 0x3e, 0xbd, 0x4e, 0x7d, 0xab, 0x7b, 0xb7, + 0xcc, 0x32, 0x73, 0xe0, 0x55, 0x14, 0x07, 0x34, 0xea, 0xa2, 0x7d, 0x57, 0x59, 0x59, 0x82, 0x97, 0x07, 0x5c, 0x9f, + 0x4f, 0xb9, 0x0f, 0x37, 0x77, 0x59, 0x35, 0x37, 0xe9, 0x69, 0x36, 0xcf, 0x16, 0xdb, 0x6d, 0x88, 0x7f, 0xbb, 0x5a, + 0xe4, 0x68, 0xf2, 0x1c, 0x74, 0x78, 0x18, 0xb9, 0x87, 0xe9, 0xc6, 0x79, 0x9b, 0xff, 0x93, 0x68, 0x38, 0x09, 0x1c, + 0x03, 0xbd, 0x98, 0x3d, 0x02, 0x19, 0x8c, 0x71, 0xea, 0x17, 0x33, 0xbd, 0x66, 0x20, 0xfa, 0x96, 0x88, 0x00, 0x47, + 0x17, 0x1b, 0x89, 0x46, 0x16, 0x9c, 0xd4, 0x04, 0x2c, 0x36, 0x6d, 0x79, 0x1f, 0x2c, 0x6d, 0xab, 0x8a, 0x3b, 0x6f, + 0x49, 0x73, 0x5c, 0x07, 0xce, 0xb6, 0xdf, 0x0c, 0xb1, 0x29, 0xbb, 0x5a, 0x20, 0xf7, 0xcb, 0x6b, 0xda, 0x1b, 0xd7, + 0x09, 0xcc, 0xda, 0xa6, 0xb6, 0x8c, 0x9f, 0x2d, 0xfd, 0x27, 0x3d, 0xb8, 0xca, 0xf8, 0x69, 0x6e, 0xac, 0x12, 0xec, + 0xbe, 0xf1, 0x7c, 0x07, 0x20, 0x1c, 0x9b, 0x4f, 0x8f, 0x4f, 0x33, 0x8f, 0x1e, 0x03, 0xd1, 0x31, 0x1f, 0x95, 0xee, + 0x23, 0xbb, 0x7b, 0xfd, 0x00, 0x78, 0xf3, 0xaa, 0x5d, 0xd0, 0xbc, 0x5c, 0x40, 0x20, 0x51, 0xaf, 0xbc, 0xc2, 0xf2, + 0x99, 0x31, 0xbb, 0x04, 0x32, 0x54, 0x10, 0x08, 0x54, 0xdd, 0x75, 0x2e, 0xc4, 0xaa, 0xc3, 0xca, 0x7c, 0x24, 0x61, + 0x47, 0x21, 0x9a, 0x73, 0x06, 0xb3, 0xe0, 0xbf, 0x82, 0x41, 0x39, 0x08, 0xa2, 0x20, 0x0a, 0x02, 0x32, 0x28, 0xe0, + 0x17, 0xe2, 0x8c, 0x11, 0x8c, 0x51, 0x02, 0x1d, 0x7e, 0xc7, 0x99, 0xcf, 0x88, 0xbc, 0x6c, 0x84, 0xb1, 0x74, 0x03, + 0x70, 0x2e, 0x65, 0xce, 0x63, 0xf4, 0xb1, 0x78, 0xc7, 0x59, 0x46, 0xe8, 0x3b, 0xef, 0x54, 0x7e, 0xc4, 0x1b, 0xc1, + 0xed, 0x76, 0x87, 0xed, 0x15, 0x0f, 0x33, 0xda, 0x1b, 0xd3, 0x77, 0x9c, 0x44, 0x59, 0xc3, 0x79, 0x98, 0x43, 0xcf, + 0x2a, 0xcb, 0x5a, 0x51, 0x43, 0x6e, 0x50, 0xac, 0x8b, 0x2c, 0x93, 0x93, 0xe1, 0xaa, 0x39, 0x15, 0xb8, 0xee, 0xec, + 0x7a, 0x01, 0x49, 0x99, 0xd0, 0x2c, 0x9d, 0x0d, 0x5f, 0x6d, 0x5b, 0xf6, 0xa2, 0x75, 0x0a, 0x79, 0x0d, 0x51, 0xd1, + 0x0f, 0x1d, 0x01, 0x35, 0xb4, 0xe2, 0xb2, 0x02, 0x97, 0x5d, 0xd3, 0x1e, 0x6e, 0xda, 0x63, 0x9a, 0xf1, 0x01, 0x62, + 0xc4, 0x71, 0x6c, 0x19, 0xd8, 0x4d, 0x38, 0x3c, 0x1b, 0xe7, 0xfb, 0xb2, 0x4b, 0x6f, 0x5d, 0x2d, 0x1e, 0x61, 0xed, + 0x79, 0x2b, 0x24, 0x04, 0x48, 0x4b, 0x53, 0xe9, 0x76, 0x1b, 0x04, 0x30, 0xc0, 0xfd, 0x7e, 0x0f, 0xb8, 0x56, 0xc3, + 0x4e, 0x9a, 0x5b, 0xb3, 0x25, 0xf6, 0x8a, 0xc2, 0x63, 0x20, 0x4a, 0xcd, 0x7f, 0x06, 0x01, 0xc5, 0x73, 0x37, 0x04, + 0xfb, 0x4a, 0x76, 0xb4, 0x29, 0xfa, 0xfd, 0x17, 0x05, 0x3e, 0xa0, 0x1c, 0x14, 0xc4, 0xba, 0x3a, 0x6e, 0x85, 0x61, + 0x9f, 0xd4, 0x87, 0x38, 0x16, 0x79, 0x16, 0x3a, 0xc2, 0x52, 0x19, 0xc2, 0xc2, 0x15, 0x23, 0x1d, 0xc4, 0x41, 0x4d, + 0x3a, 0x07, 0xab, 0x72, 0xc1, 0x86, 0x7b, 0xbd, 0x4f, 0x00, 0x0b, 0x9e, 0x79, 0xc3, 0xf2, 0xde, 0x03, 0x00, 0xeb, + 0xf5, 0x70, 0xa1, 0xb8, 0x97, 0xaf, 0x1a, 0xe8, 0x93, 0xf8, 0xd2, 0xb2, 0xeb, 0x33, 0x2d, 0x2b, 0x19, 0x8d, 0x46, + 0x55, 0xad, 0x24, 0x1f, 0x8e, 0xbc, 0xb4, 0x50, 0x2b, 0x65, 0x9c, 0xf2, 0x14, 0x2c, 0xbd, 0x0d, 0xa5, 0x9b, 0x2f, + 0xe8, 0x8a, 0x8b, 0x54, 0xfd, 0xf4, 0xd0, 0x26, 0x1b, 0xc4, 0x35, 0x6b, 0xea, 0x2c, 0xec, 0xf0, 0x43, 0xc0, 0x47, + 0xfb, 0x30, 0x73, 0xe9, 0x1a, 0x96, 0x16, 0xc4, 0x91, 0x71, 0xc1, 0x43, 0x97, 0x07, 0xb0, 0xfe, 0xcc, 0x21, 0x89, + 0x9f, 0xc2, 0xcf, 0x99, 0x49, 0xeb, 0xf8, 0x0c, 0x67, 0x33, 0x2a, 0xd5, 0x8d, 0xa0, 0xfd, 0x1a, 0x12, 0x89, 0x41, + 0x36, 0x6e, 0x30, 0x14, 0xad, 0xbb, 0x0d, 0x5c, 0xf9, 0x2d, 0xbd, 0xf3, 0x69, 0x10, 0x60, 0x5b, 0x63, 0x31, 0x00, + 0x18, 0x8a, 0x3f, 0x50, 0x55, 0x63, 0xae, 0x28, 0xa6, 0x61, 0x2a, 0xd1, 0xde, 0x71, 0x5c, 0x47, 0x8d, 0xab, 0xac, + 0x60, 0xa5, 0xb5, 0xe5, 0x75, 0x6f, 0x69, 0x61, 0x4b, 0x40, 0x35, 0x18, 0xee, 0x04, 0xf0, 0x19, 0x91, 0xea, 0x40, + 0x90, 0xdd, 0x07, 0x07, 0x00, 0x9a, 0xe1, 0x79, 0x18, 0xc2, 0x1f, 0x58, 0x38, 0xb0, 0x2c, 0x55, 0x3f, 0x97, 0xd3, + 0x18, 0xce, 0xdd, 0x5c, 0xed, 0xf0, 0xd9, 0x12, 0x14, 0x79, 0x6a, 0x4e, 0xcd, 0xe5, 0x2b, 0x6f, 0xec, 0xf7, 0x98, + 0x60, 0x1e, 0x33, 0xdb, 0xf0, 0x5b, 0x4f, 0xb7, 0xf5, 0x85, 0x75, 0x03, 0x27, 0xed, 0x85, 0xd3, 0x5e, 0x6c, 0x97, + 0x06, 0xe2, 0xae, 0x6e, 0x08, 0x11, 0x5e, 0x6b, 0x62, 0x91, 0x35, 0x64, 0x3a, 0x16, 0x1b, 0x43, 0xb5, 0xa9, 0x78, + 0xae, 0x15, 0xe2, 0xe5, 0x54, 0x5d, 0x98, 0x5a, 0xa9, 0x4c, 0x18, 0x84, 0x99, 0x12, 0x16, 0x55, 0x06, 0x3e, 0xfb, + 0x15, 0x52, 0x5c, 0x5b, 0xcf, 0x5b, 0x5c, 0xbe, 0x99, 0x69, 0xb3, 0xfd, 0xf4, 0x55, 0x1e, 0x5f, 0x6e, 0xb7, 0x61, + 0xf7, 0x0b, 0x30, 0xbf, 0x2c, 0x95, 0x46, 0x0d, 0x9c, 0x1e, 0x42, 0xf4, 0x73, 0xbe, 0x27, 0xe7, 0xc4, 0x71, 0x72, + 0xed, 0xe6, 0xcd, 0x76, 0x52, 0x8c, 0xc0, 0x02, 0x4e, 0x5c, 0xa4, 0x03, 0x2d, 0x15, 0x9c, 0xb6, 0x8c, 0xf7, 0x36, + 0xbd, 0xa3, 0x54, 0x78, 0xb5, 0xd0, 0x24, 0xa4, 0x72, 0xf7, 0x12, 0x3b, 0x6a, 0xc0, 0x39, 0xa9, 0x3b, 0x08, 0x38, + 0xa9, 0xe9, 0xc6, 0x5a, 0xc5, 0xa9, 0x49, 0xf0, 0x5e, 0xe9, 0xa1, 0x4b, 0xb4, 0x13, 0xb7, 0xdb, 0x56, 0x65, 0x0b, + 0xf5, 0x71, 0x2f, 0x67, 0x89, 0x3a, 0x1e, 0x50, 0xe8, 0xa2, 0x8e, 0x86, 0x7c, 0x41, 0x0a, 0xbd, 0x72, 0xb4, 0x6a, + 0x75, 0x57, 0x32, 0x50, 0xaa, 0x55, 0x90, 0xd7, 0xc4, 0xba, 0x6b, 0x65, 0x8d, 0xc5, 0x95, 0x13, 0x52, 0xd8, 0x84, + 0x2f, 0x2d, 0xc5, 0xc2, 0x0a, 0xf6, 0xc6, 0xd4, 0x17, 0x2e, 0x11, 0xda, 0xee, 0x36, 0xc4, 0x24, 0x83, 0x75, 0xb3, + 0xdd, 0xbe, 0x2e, 0xc2, 0x79, 0xb6, 0xa0, 0x72, 0x94, 0xa5, 0x08, 0x21, 0x66, 0x3c, 0x74, 0x6d, 0x17, 0xcc, 0xc4, + 0x50, 0xd7, 0x1e, 0x2f, 0xc9, 0x14, 0x6b, 0x93, 0xe4, 0x28, 0x3e, 0x97, 0x85, 0x5a, 0x6b, 0x84, 0xe0, 0xe1, 0xfe, + 0x67, 0x0a, 0x31, 0xdc, 0xcc, 0xba, 0xfb, 0x75, 0xe7, 0x86, 0xf8, 0x27, 0x04, 0x12, 0x28, 0xd9, 0xeb, 0x62, 0x74, + 0x9e, 0x89, 0x14, 0x77, 0xaa, 0x8a, 0x8a, 0xab, 0xd6, 0x41, 0xb3, 0xe5, 0xf6, 0x5e, 0x6c, 0x89, 0x02, 0xc4, 0x35, + 0x16, 0x9a, 0xf1, 0xac, 0x9c, 0xa5, 0x48, 0x46, 0xb1, 0x21, 0x51, 0xe9, 0x45, 0x45, 0xf7, 0x79, 0x1a, 0xd3, 0x43, + 0xb7, 0x06, 0xc1, 0x55, 0x73, 0x67, 0x23, 0xcd, 0x17, 0x84, 0xa8, 0x09, 0x90, 0xb0, 0x51, 0xcd, 0xa9, 0x75, 0x29, + 0x1e, 0x66, 0x95, 0xcf, 0xf4, 0x41, 0x7c, 0x29, 0x80, 0x87, 0xf5, 0xb6, 0xf7, 0x95, 0xf0, 0x58, 0x1b, 0x7c, 0xbb, + 0xdd, 0x5e, 0x8a, 0x79, 0x10, 0x78, 0x8c, 0xe6, 0x77, 0x4a, 0x62, 0xde, 0x1b, 0x53, 0x58, 0xf1, 0xbe, 0x4b, 0x5b, + 0x37, 0xa9, 0xb5, 0x16, 0xa8, 0x3b, 0x5c, 0x1f, 0xf0, 0x3c, 0x25, 0x8e, 0x76, 0x54, 0x4e, 0xa5, 0xd5, 0x95, 0x63, + 0x57, 0x04, 0x06, 0x86, 0xfe, 0x21, 0x65, 0x1b, 0x30, 0xc7, 0x03, 0x6b, 0x1b, 0xf4, 0x53, 0x52, 0x5a, 0x98, 0x31, + 0x1a, 0xb3, 0xc8, 0x75, 0x15, 0x1d, 0x70, 0x1d, 0xbd, 0x9d, 0x47, 0x7f, 0x7b, 0x36, 0xa6, 0x45, 0x2c, 0x52, 0x79, + 0x05, 0x2a, 0x08, 0x50, 0x86, 0xa0, 0xe1, 0xbf, 0xa6, 0x06, 0xa0, 0x41, 0x70, 0x03, 0xf0, 0xcf, 0x4e, 0xa7, 0x41, + 0x5b, 0x93, 0x8f, 0x49, 0xaa, 0x8a, 0x9c, 0xb5, 0xa1, 0xcc, 0x54, 0x72, 0x48, 0x1e, 0x97, 0x80, 0xe7, 0x88, 0xcd, + 0x52, 0x36, 0x17, 0x6a, 0xb3, 0xa9, 0xd7, 0x8a, 0x1d, 0xb9, 0x6d, 0x14, 0x6d, 0xd6, 0xa2, 0xb6, 0x93, 0x98, 0x2f, + 0xa6, 0xb7, 0x56, 0x18, 0x38, 0x35, 0xad, 0xb9, 0xd9, 0x81, 0x4e, 0xb3, 0xf5, 0x99, 0xdc, 0x04, 0x88, 0x03, 0x0c, + 0xd7, 0xed, 0xfc, 0x66, 0x41, 0xe8, 0x2d, 0xbb, 0xb5, 0x62, 0xd5, 0x1b, 0x2b, 0x17, 0x31, 0x69, 0x37, 0x83, 0x09, + 0x5c, 0xc6, 0x59, 0x61, 0x5f, 0x68, 0x75, 0x43, 0xd1, 0xd1, 0x36, 0x69, 0x3f, 0xef, 0x68, 0x37, 0x5c, 0xf0, 0xad, + 0x58, 0xc7, 0xb9, 0x21, 0x4d, 0x15, 0x7a, 0x74, 0xa0, 0xb7, 0x43, 0x40, 0x73, 0x36, 0xa6, 0x4b, 0x9a, 0xe2, 0x05, + 0x9a, 0xae, 0xc1, 0x2c, 0xe5, 0x02, 0xfa, 0xda, 0xed, 0x93, 0x7c, 0xa1, 0x7a, 0x22, 0xbc, 0x25, 0x0a, 0xbe, 0x1c, + 0x29, 0x78, 0x65, 0xe5, 0x3c, 0x36, 0x73, 0x08, 0x78, 0x2c, 0xaa, 0x44, 0xef, 0xa4, 0xb8, 0x04, 0x65, 0x2a, 0x1c, + 0x81, 0xa6, 0x6a, 0xc4, 0x12, 0x0e, 0x70, 0x7b, 0xf1, 0x34, 0x20, 0x14, 0xa4, 0xba, 0x6b, 0xbb, 0x22, 0x6f, 0xd9, + 0xd1, 0xe6, 0x16, 0xcc, 0x62, 0xab, 0x75, 0xd9, 0xfa, 0xca, 0x26, 0xbb, 0x8f, 0x6b, 0x82, 0x6d, 0xf7, 0x36, 0x48, + 0x78, 0x4b, 0x6f, 0xc8, 0xe6, 0xa6, 0xdf, 0x0f, 0xa1, 0x3f, 0x84, 0xea, 0x0e, 0xdd, 0x76, 0x76, 0xe8, 0xd6, 0x67, + 0x7e, 0xad, 0x9e, 0x4f, 0x79, 0x43, 0x7c, 0x40, 0x13, 0x2d, 0xba, 0x8a, 0xef, 0x60, 0x53, 0x47, 0x15, 0x55, 0x95, + 0x47, 0x09, 0x05, 0x15, 0x70, 0xc6, 0xcb, 0x53, 0x8e, 0xb1, 0x4d, 0xf5, 0xd3, 0x3b, 0xcd, 0xab, 0xad, 0xcd, 0xda, + 0x2c, 0xd7, 0xe7, 0x60, 0x11, 0x70, 0xce, 0xa3, 0x2b, 0x4d, 0x4b, 0x2e, 0x3d, 0xa6, 0xfe, 0x0c, 0x47, 0x25, 0xb8, + 0x88, 0xb3, 0x9c, 0xa7, 0x01, 0xbd, 0x68, 0xf6, 0x3f, 0xd4, 0xb6, 0x52, 0xcb, 0xc6, 0x99, 0x7b, 0x1d, 0x92, 0xcd, + 0xff, 0xd8, 0x40, 0xbd, 0x09, 0x31, 0x22, 0xaa, 0x59, 0xd0, 0x27, 0x0c, 0x62, 0x63, 0x06, 0xe5, 0x3a, 0x49, 0x78, + 0x59, 0x06, 0x46, 0xa9, 0xb5, 0x66, 0x6b, 0x73, 0x9e, 0x3d, 0x62, 0x47, 0x8f, 0x7a, 0x8c, 0xdd, 0x12, 0x9a, 0x68, + 0x9d, 0x90, 0xa9, 0x31, 0xf2, 0xb4, 0x40, 0xba, 0x43, 0x51, 0x76, 0x11, 0x9e, 0xa0, 0x90, 0xa5, 0xbd, 0xcf, 0xcd, + 0x89, 0xac, 0xbe, 0xd1, 0x46, 0x17, 0x91, 0x4a, 0x04, 0xd9, 0xf8, 0x0d, 0x02, 0xf6, 0x42, 0xb3, 0x03, 0xb2, 0x59, + 0xb2, 0x53, 0x7a, 0x66, 0x4d, 0x60, 0xe0, 0xf5, 0x89, 0x4a, 0x34, 0xa3, 0xac, 0x88, 0xae, 0x32, 0x72, 0xb9, 0x0b, + 0x49, 0x74, 0x16, 0x12, 0x3f, 0x37, 0x2c, 0xad, 0xeb, 0x10, 0xc5, 0xcc, 0x66, 0xc3, 0xab, 0xee, 0x3e, 0x6a, 0x6c, + 0x2b, 0xe3, 0x53, 0x7d, 0x6b, 0xd3, 0xc8, 0x14, 0xfa, 0x3a, 0x9c, 0xf4, 0xfb, 0xf0, 0x57, 0xd3, 0x0f, 0xbc, 0xa5, + 0xe0, 0x2f, 0xf6, 0x88, 0xd4, 0x09, 0x0b, 0x00, 0x8e, 0x30, 0xe7, 0x55, 0x73, 0x02, 0x1f, 0xb1, 0xa3, 0xcd, 0xa3, + 0xf0, 0xb4, 0x31, 0x73, 0x77, 0x21, 0x5e, 0xaa, 0x92, 0x9e, 0x37, 0x4f, 0x66, 0x20, 0x56, 0xa1, 0xd9, 0xaf, 0xb7, + 0xcc, 0xea, 0x13, 0x80, 0x48, 0xdd, 0x5a, 0x87, 0x52, 0xfc, 0xd8, 0x74, 0x99, 0x6c, 0x52, 0xd6, 0x66, 0xa2, 0x94, + 0x8a, 0xa4, 0xb9, 0x08, 0xa0, 0xdf, 0x30, 0x1c, 0x35, 0xc0, 0x7b, 0xeb, 0xb1, 0x37, 0x43, 0xe3, 0x8d, 0xa9, 0xa1, + 0x67, 0x1b, 0xbd, 0xbc, 0x1d, 0x85, 0x30, 0x63, 0x11, 0xdd, 0xba, 0x63, 0x31, 0x3c, 0xa5, 0x27, 0x50, 0xe1, 0x9b, + 0x10, 0xa3, 0xe9, 0x92, 0xba, 0x9e, 0xae, 0xd5, 0x56, 0xba, 0x21, 0x34, 0xc7, 0x28, 0x3e, 0x5e, 0xdb, 0xee, 0xa8, + 0x11, 0xda, 0x13, 0xca, 0xc3, 0x5b, 0x5a, 0xd1, 0x1b, 0xcb, 0x22, 0x38, 0xf9, 0xb1, 0x97, 0x9f, 0xd0, 0x73, 0x4f, + 0x60, 0x52, 0xb4, 0x35, 0x80, 0x3f, 0xa0, 0x7e, 0x38, 0xab, 0xa7, 0x56, 0xca, 0xe1, 0x29, 0x7c, 0xc9, 0x06, 0xe4, + 0x0a, 0x7a, 0xb1, 0xc6, 0xec, 0x28, 0x06, 0x1d, 0xd4, 0xce, 0xee, 0xf0, 0x26, 0xa5, 0x0c, 0xd1, 0xfa, 0xce, 0x41, + 0x3c, 0xfd, 0x13, 0x34, 0x7d, 0x90, 0x16, 0xa6, 0x74, 0x8d, 0x02, 0x1e, 0xd0, 0x37, 0xf5, 0xfb, 0x39, 0x3e, 0xd7, + 0x9e, 0x25, 0x16, 0xf6, 0x78, 0x49, 0xe8, 0xd2, 0x8b, 0x1b, 0x05, 0xd2, 0x66, 0xc7, 0x2a, 0x00, 0x2b, 0x92, 0x40, + 0x23, 0x12, 0xb0, 0xd4, 0xf1, 0xc4, 0x65, 0x1b, 0x34, 0x20, 0x89, 0x4a, 0x0a, 0x59, 0x22, 0x09, 0xfc, 0x30, 0x82, + 0x10, 0x45, 0x31, 0x88, 0x7b, 0xf5, 0xf2, 0x8a, 0x6b, 0x6a, 0xc0, 0x89, 0x22, 0x98, 0x60, 0x9d, 0x4e, 0x81, 0xd8, + 0x8a, 0xf5, 0x0a, 0x3c, 0x2f, 0x1d, 0x27, 0x8e, 0x2c, 0x01, 0x1a, 0xa4, 0xf9, 0xd2, 0x69, 0xb7, 0xbc, 0x3d, 0xd1, + 0x52, 0xc5, 0xe6, 0xde, 0x8b, 0x85, 0xe5, 0x1e, 0x2b, 0x7f, 0x3b, 0xd0, 0x5e, 0x58, 0xed, 0x88, 0xa8, 0xc1, 0xca, + 0xae, 0x6d, 0xd7, 0x86, 0xd2, 0x50, 0xdd, 0x2b, 0xc7, 0x04, 0x54, 0x74, 0x15, 0x57, 0xcb, 0x28, 0x1b, 0xc1, 0x9f, + 0xed, 0x36, 0xd8, 0x0f, 0xc0, 0x02, 0xf2, 0x97, 0xf7, 0x3f, 0x45, 0x18, 0x9e, 0xe9, 0x97, 0xf7, 0x3f, 0x6d, 0xb7, + 0xcf, 0xc6, 0x63, 0xc3, 0x15, 0x38, 0xb5, 0x0e, 0xf0, 0x07, 0x86, 0x6d, 0xb0, 0x4b, 0x76, 0xbb, 0x7d, 0x06, 0x1c, + 0x84, 0x62, 0x1b, 0xcc, 0x2e, 0x56, 0x8e, 0x5c, 0x8a, 0xd5, 0xd0, 0x3b, 0x12, 0xb0, 0xea, 0x76, 0x58, 0x8a, 0x5d, + 0xea, 0xa3, 0x42, 0x30, 0xea, 0x45, 0xff, 0xb2, 0x53, 0x60, 0x49, 0xc1, 0x74, 0x35, 0x58, 0x56, 0xd5, 0xaa, 0x8c, + 0xf6, 0xf7, 0xe3, 0x55, 0x36, 0x2a, 0x33, 0xd8, 0xe6, 0xe5, 0xf5, 0x25, 0x00, 0x2a, 0x04, 0xb4, 0xf1, 0x6e, 0x2d, + 0x32, 0xf3, 0x62, 0x41, 0x97, 0x19, 0xae, 0x49, 0x30, 0x3b, 0xc8, 0xb9, 0xd5, 0x4d, 0x4e, 0x89, 0x7d, 0x00, 0x9b, + 0xc3, 0xed, 0xb6, 0xc1, 0x2f, 0x1c, 0x8d, 0x9e, 0xcd, 0x96, 0x99, 0x36, 0xe8, 0xe4, 0x66, 0xff, 0x93, 0xc8, 0x4b, + 0x43, 0xc5, 0x27, 0x99, 0xbe, 0xcc, 0x80, 0xcf, 0x63, 0x6f, 0x45, 0xe8, 0xb3, 0x5c, 0x8d, 0xd6, 0x00, 0x1b, 0x9b, + 0x5d, 0xdc, 0x8d, 0x52, 0x0e, 0x11, 0x29, 0x02, 0xab, 0xae, 0x59, 0x66, 0xc4, 0xb7, 0xa9, 0xb8, 0x6b, 0xa9, 0xc2, + 0xde, 0x0a, 0xcf, 0x59, 0x85, 0x1b, 0x47, 0x99, 0xde, 0x24, 0x0a, 0x5f, 0xa2, 0x10, 0x95, 0xa3, 0x31, 0x9d, 0x13, + 0x48, 0x65, 0x1e, 0x13, 0x8a, 0x39, 0xdc, 0xbb, 0x5f, 0x52, 0x67, 0x2e, 0xe3, 0x0b, 0xf7, 0x5e, 0xfa, 0x32, 0x93, + 0x5b, 0x09, 0xa0, 0x48, 0xaa, 0xf6, 0x9f, 0x3f, 0x23, 0x35, 0xfe, 0x57, 0xaa, 0x35, 0x00, 0xbd, 0x9f, 0xa1, 0x26, + 0x47, 0x10, 0xb0, 0x15, 0x53, 0x1f, 0x4d, 0xdf, 0x4a, 0xe6, 0x3f, 0xa0, 0x6e, 0x47, 0xb0, 0x8d, 0x8a, 0x9f, 0x13, + 0x55, 0xb4, 0xe0, 0xe9, 0x5a, 0xa4, 0xb1, 0x48, 0xee, 0x22, 0x5e, 0x4f, 0xb1, 0x24, 0x66, 0x23, 0x64, 0xfd, 0xdc, + 0xec, 0xc2, 0x4f, 0x45, 0xc3, 0x04, 0x9c, 0x96, 0xfe, 0xb6, 0xf2, 0x36, 0x93, 0x65, 0x9c, 0x91, 0x29, 0x57, 0x88, + 0xdd, 0x56, 0xdf, 0x63, 0x4e, 0xf0, 0xa7, 0x07, 0x4f, 0x09, 0xbd, 0x95, 0xd3, 0x12, 0x41, 0xe9, 0x44, 0x6a, 0x5d, + 0x35, 0xb1, 0x5f, 0x53, 0x88, 0xe2, 0x20, 0x18, 0x84, 0xee, 0x34, 0xed, 0x53, 0x7c, 0x9f, 0x2d, 0xfb, 0xad, 0x29, + 0x5b, 0x92, 0x8d, 0x80, 0x8e, 0x49, 0xe7, 0xed, 0xe9, 0xed, 0xd9, 0x99, 0xf7, 0x1b, 0x34, 0xe1, 0xa0, 0xba, 0x81, + 0x76, 0x15, 0x64, 0x1a, 0xa3, 0xd8, 0x2c, 0xc6, 0xda, 0xad, 0x89, 0x08, 0x82, 0x4e, 0x97, 0xb3, 0xb0, 0xdd, 0x4e, + 0x88, 0x2f, 0x81, 0x04, 0x0a, 0x5c, 0xb9, 0x28, 0x27, 0x21, 0x51, 0x17, 0x32, 0x3d, 0x59, 0xd7, 0x92, 0x05, 0x7a, + 0x8d, 0x1d, 0x04, 0xf4, 0x98, 0xdb, 0xa7, 0x80, 0xbe, 0x2f, 0xd8, 0x31, 0x1f, 0x04, 0x43, 0x8c, 0xaf, 0x1a, 0xd0, + 0x1b, 0xa9, 0x1e, 0xc1, 0x43, 0x18, 0x58, 0x2e, 0xfa, 0xaa, 0x60, 0x08, 0x2b, 0xf4, 0x57, 0xca, 0x26, 0xdf, 0xfc, + 0xdd, 0xcd, 0xef, 0xb9, 0x16, 0xb3, 0x83, 0x50, 0xdc, 0x5e, 0x4f, 0x80, 0xf8, 0x55, 0xfc, 0x0a, 0xac, 0xab, 0xb5, + 0xc4, 0xdb, 0x4d, 0xcf, 0x9f, 0xc2, 0x97, 0xa3, 0xdb, 0x4f, 0x4a, 0xf3, 0x09, 0x04, 0xa9, 0x71, 0x92, 0x72, 0xf7, + 0xdd, 0x47, 0xe9, 0x2a, 0x82, 0xd1, 0x02, 0xc4, 0xba, 0x7b, 0x2b, 0x39, 0x6b, 0x0a, 0xff, 0xb1, 0xce, 0xf7, 0x18, + 0x3b, 0x44, 0x9e, 0xe2, 0xf4, 0x37, 0xc0, 0xb0, 0xef, 0xfc, 0x5b, 0x99, 0x35, 0x24, 0x3a, 0x57, 0x1f, 0x01, 0xfd, + 0x1f, 0xeb, 0xf1, 0x3b, 0x46, 0x49, 0x5f, 0x12, 0xe7, 0x08, 0x57, 0xc4, 0x4b, 0x34, 0xd5, 0xeb, 0x8d, 0x6b, 0xfa, + 0xa9, 0x30, 0x2f, 0xb4, 0x82, 0xc3, 0xbe, 0x35, 0x0a, 0x0f, 0x3c, 0xf3, 0x7e, 0x15, 0x0d, 0x41, 0xf7, 0x6f, 0xb8, + 0x37, 0x7e, 0x15, 0x2c, 0xc3, 0x9b, 0x72, 0x96, 0x99, 0x3b, 0xdc, 0x4d, 0x26, 0x52, 0x79, 0xc3, 0x58, 0xb0, 0x16, + 0xca, 0x7c, 0x35, 0x0d, 0x66, 0x9b, 0x3a, 0x52, 0xc9, 0xee, 0xfb, 0xb7, 0x8d, 0x13, 0x36, 0x1b, 0x04, 0xa7, 0x95, + 0x2c, 0xe2, 0x4b, 0x1e, 0x4c, 0xb5, 0x8a, 0x22, 0xcb, 0xfa, 0xfd, 0x0c, 0x90, 0x61, 0x9c, 0xf6, 0x0e, 0x9e, 0x2c, + 0x35, 0x33, 0x21, 0xae, 0xad, 0xce, 0x02, 0xde, 0x9a, 0xd1, 0x3c, 0xae, 0x60, 0x97, 0xf9, 0x4a, 0x8a, 0x3f, 0x5b, + 0x92, 0x6c, 0xac, 0xbf, 0x21, 0xc3, 0xb6, 0xf2, 0x99, 0x73, 0xc0, 0x98, 0xb9, 0x91, 0x2a, 0xc8, 0x5d, 0x0f, 0x18, + 0x21, 0x24, 0x02, 0xc2, 0x59, 0x4c, 0xdc, 0x09, 0x13, 0xfe, 0xd1, 0x05, 0xc6, 0x89, 0x31, 0x30, 0xce, 0x47, 0x19, + 0x72, 0x7a, 0xcc, 0x07, 0x49, 0x63, 0xb6, 0xfe, 0x54, 0x25, 0xd2, 0x6b, 0x49, 0xe8, 0x19, 0xfc, 0x1e, 0xb7, 0x78, + 0xa0, 0x46, 0x70, 0x4a, 0x77, 0x73, 0xda, 0x7f, 0x55, 0x90, 0xe1, 0x5f, 0xe0, 0xdd, 0x15, 0xdb, 0xcb, 0x72, 0x02, + 0x8b, 0x3b, 0xf6, 0x8a, 0xa7, 0xb9, 0x6a, 0x71, 0x42, 0x3c, 0x62, 0x91, 0xfb, 0xc4, 0x02, 0x46, 0xd4, 0x30, 0x1a, + 0x3f, 0x9e, 0x9e, 0xbc, 0xd5, 0x98, 0x4d, 0xb9, 0xff, 0x01, 0x8c, 0xa8, 0x96, 0xb6, 0xdb, 0x01, 0x5f, 0x8e, 0xd0, + 0x60, 0x3b, 0x75, 0x83, 0xdd, 0xef, 0x9b, 0xb4, 0xa3, 0xd2, 0xcb, 0xe6, 0xc4, 0xa0, 0x3b, 0x4a, 0x9b, 0xa5, 0x32, + 0xa8, 0xed, 0x2a, 0x1c, 0xcd, 0x67, 0x8d, 0x58, 0xd5, 0xfb, 0x30, 0x5c, 0xd2, 0xd8, 0xca, 0xca, 0xed, 0x6e, 0xc2, + 0x91, 0x4d, 0x80, 0xeb, 0x53, 0x50, 0x56, 0xcd, 0x39, 0x68, 0x41, 0x67, 0x02, 0x47, 0xb4, 0xdd, 0x86, 0x10, 0x81, + 0xa3, 0x18, 0x4e, 0x66, 0x61, 0x31, 0x1c, 0xaa, 0x81, 0x2f, 0x08, 0x89, 0x3e, 0x15, 0xf3, 0x6c, 0xa1, 0x10, 0x7b, + 0xfc, 0x9d, 0xf4, 0x6b, 0xa1, 0x38, 0xe5, 0xde, 0xaf, 0x82, 0x6c, 0x7e, 0x4b, 0x31, 0xe6, 0xa0, 0xd3, 0x6c, 0x66, + 0x20, 0x61, 0x3d, 0xae, 0x88, 0x5a, 0x47, 0x76, 0x36, 0x40, 0x15, 0x8b, 0xa6, 0xb0, 0xa0, 0x6e, 0xf1, 0xc4, 0x7a, + 0x46, 0xef, 0x41, 0x25, 0x88, 0x6a, 0xc1, 0x6e, 0x0c, 0xd7, 0xda, 0x27, 0x11, 0x4a, 0xca, 0x49, 0x93, 0x99, 0xb1, + 0xa2, 0xc1, 0x02, 0x84, 0xa4, 0x71, 0x59, 0xbd, 0x91, 0x69, 0x76, 0x91, 0x01, 0x62, 0x82, 0xf3, 0x9f, 0x93, 0x8d, + 0x37, 0xcf, 0xd5, 0xbc, 0x74, 0x25, 0xce, 0x2c, 0xcc, 0x47, 0xd7, 0x5b, 0x5a, 0x90, 0xa8, 0x00, 0x1a, 0xe5, 0x6b, + 0x79, 0xfe, 0xb1, 0x63, 0x15, 0xb2, 0xfb, 0xe1, 0x54, 0xd9, 0x0e, 0xf1, 0x23, 0x56, 0x11, 0xef, 0xb4, 0xae, 0x94, + 0x48, 0xa3, 0xa3, 0x6d, 0x40, 0x0c, 0x5b, 0xf6, 0x2d, 0x6a, 0xf8, 0x20, 0xcc, 0xa0, 0x93, 0xfc, 0xa0, 0x67, 0x74, + 0x6c, 0x0d, 0x24, 0x7d, 0x2d, 0x82, 0xaf, 0xd1, 0x91, 0x4e, 0x94, 0x69, 0x24, 0xa6, 0x90, 0xe8, 0xd7, 0x0b, 0xad, + 0xb1, 0x8c, 0xb2, 0xaf, 0xc8, 0xff, 0x5e, 0x77, 0xef, 0x57, 0xb1, 0xdd, 0xc2, 0x24, 0x7b, 0x1e, 0x57, 0xb0, 0xa9, + 0x51, 0x2b, 0x84, 0xb3, 0x73, 0x5c, 0xa1, 0x76, 0xac, 0x17, 0x96, 0x40, 0x1e, 0xc0, 0x56, 0xa4, 0x41, 0x19, 0x24, + 0xfb, 0x54, 0xcc, 0xc5, 0xc2, 0x89, 0x72, 0xa4, 0xc2, 0xfb, 0x92, 0xa3, 0x94, 0xc3, 0x55, 0x2c, 0x2c, 0x18, 0xf2, + 0xab, 0xa3, 0x8b, 0x42, 0x5e, 0x81, 0xa4, 0xc4, 0x30, 0x54, 0x96, 0xd7, 0xc5, 0x55, 0x5b, 0x12, 0xda, 0x3b, 0x03, + 0x10, 0x96, 0x02, 0x04, 0x2f, 0x8d, 0x1a, 0x62, 0xb6, 0x51, 0xbb, 0x2b, 0xba, 0x97, 0x1c, 0x50, 0xa7, 0xbb, 0x76, + 0xeb, 0x4d, 0xd9, 0x66, 0x5b, 0x71, 0xe1, 0x9f, 0x50, 0xfa, 0x31, 0x1f, 0x14, 0x3e, 0x95, 0xc0, 0x8d, 0xaf, 0x36, + 0x59, 0x76, 0x71, 0x87, 0x4b, 0xbf, 0x6a, 0x8c, 0x5f, 0xbf, 0xdf, 0x53, 0x0b, 0xa1, 0x91, 0x0a, 0xcc, 0xb7, 0xcf, + 0x4c, 0x55, 0x46, 0x53, 0x6a, 0x2f, 0xc1, 0x95, 0xb3, 0x1f, 0x41, 0x45, 0x5c, 0x57, 0x64, 0x32, 0x35, 0x40, 0x7b, + 0x5e, 0x56, 0xb8, 0x95, 0x05, 0x78, 0xec, 0x04, 0x64, 0xbb, 0xe5, 0x61, 0xa0, 0x0f, 0x9d, 0xc0, 0xdf, 0x92, 0xa7, + 0xc8, 0xac, 0xd9, 0xc7, 0x9f, 0xb5, 0xe0, 0x1f, 0x5b, 0xf0, 0x13, 0x8a, 0x3b, 0xad, 0xcc, 0xbf, 0x95, 0xd6, 0x2d, + 0xee, 0xdf, 0xc9, 0x34, 0xa1, 0xa8, 0x4c, 0xa8, 0xfd, 0x4a, 0x7f, 0x37, 0xc1, 0x92, 0x54, 0xf6, 0x0f, 0x12, 0x3e, + 0x98, 0x35, 0x9e, 0x58, 0xe3, 0xc9, 0x70, 0xba, 0x95, 0x86, 0x21, 0x40, 0xa1, 0x9f, 0x97, 0xb9, 0xa2, 0xfa, 0xf9, + 0xe7, 0x35, 0x5f, 0xf3, 0x66, 0x8b, 0x6d, 0xd2, 0x03, 0x0d, 0xf6, 0xf2, 0x68, 0x4a, 0xe1, 0x24, 0xea, 0xdc, 0x48, + 0xd4, 0x45, 0xcd, 0x32, 0x54, 0x27, 0x78, 0x35, 0x4f, 0xf5, 0xb0, 0x37, 0x13, 0xd1, 0x5a, 0x49, 0x59, 0x62, 0xc0, + 0x5a, 0x47, 0x1e, 0x92, 0xbb, 0xb5, 0x8e, 0x3b, 0x0d, 0x75, 0x69, 0x0a, 0x25, 0xc0, 0x0a, 0x17, 0xe0, 0x08, 0xfa, + 0xa9, 0x08, 0x39, 0x5c, 0x53, 0x95, 0x7e, 0x41, 0x53, 0xf2, 0xc4, 0x53, 0xd4, 0x6a, 0x45, 0xba, 0xfd, 0x28, 0xc7, + 0x6e, 0xf8, 0xc6, 0x09, 0x39, 0x31, 0x42, 0x7f, 0x77, 0x2c, 0xe5, 0x0c, 0x2d, 0x1e, 0xd4, 0x09, 0xd6, 0xcb, 0x5b, + 0x0a, 0x14, 0x73, 0x74, 0x59, 0x75, 0xcd, 0x6b, 0xb4, 0x7d, 0x59, 0xf6, 0xfb, 0xb9, 0xad, 0x27, 0x65, 0x47, 0x9b, + 0xa5, 0xd9, 0x87, 0xa8, 0x98, 0xc2, 0x5d, 0x9f, 0x68, 0xfe, 0x2a, 0xd4, 0x57, 0x6d, 0x99, 0xf3, 0x11, 0x47, 0x5c, + 0x8c, 0x9c, 0xd4, 0x3f, 0xab, 0xa9, 0x57, 0xe2, 0x7e, 0x55, 0xc9, 0x77, 0xc2, 0x58, 0x31, 0x3a, 0xa0, 0xfe, 0x54, + 0xa9, 0xbc, 0x5f, 0x16, 0x00, 0xf7, 0x24, 0xd8, 0x27, 0xb0, 0xaf, 0xd0, 0x08, 0xbf, 0x2d, 0x01, 0xff, 0x46, 0x71, + 0x03, 0x56, 0x81, 0x01, 0x46, 0x93, 0xed, 0x39, 0x4d, 0xe0, 0x80, 0x13, 0x5a, 0x45, 0x41, 0x85, 0x19, 0x1a, 0x6a, + 0x0b, 0xa3, 0xa7, 0x28, 0xe3, 0x56, 0x99, 0xbd, 0x1b, 0x63, 0xa7, 0x05, 0x5e, 0xc3, 0x9f, 0xcf, 0x0b, 0x3d, 0x6c, + 0xd4, 0x41, 0x7a, 0x74, 0x12, 0xd3, 0x1f, 0xb7, 0x70, 0x72, 0xb3, 0x70, 0x96, 0x35, 0x4b, 0xa0, 0x3b, 0x70, 0x41, + 0x8c, 0xfb, 0xfd, 0x1c, 0x8e, 0x4c, 0x33, 0xf2, 0x05, 0xcb, 0x69, 0xcc, 0x96, 0x54, 0x7b, 0xda, 0x5d, 0x56, 0x61, + 0x4e, 0x97, 0x56, 0xc6, 0x9b, 0x32, 0x50, 0x19, 0x6d, 0xb7, 0x21, 0xfc, 0xe9, 0xb6, 0x76, 0x49, 0xe7, 0x4b, 0xc8, + 0x00, 0x7f, 0x40, 0x22, 0x8a, 0xd8, 0xd7, 0xff, 0x56, 0xe3, 0x94, 0x9e, 0x28, 0xad, 0x59, 0x42, 0xd7, 0x4c, 0xd7, + 0x4f, 0x2f, 0xd8, 0xba, 0xb1, 0x14, 0xb6, 0xdb, 0xb0, 0x99, 0xc0, 0x34, 0xe7, 0x4a, 0xa6, 0x17, 0xa8, 0x93, 0x02, + 0x2a, 0x16, 0x5e, 0xe0, 0xf2, 0x4b, 0x09, 0x85, 0xe6, 0xce, 0x97, 0x0b, 0xa3, 0xc4, 0x84, 0x56, 0xc9, 0x2f, 0x1f, + 0x2a, 0xf3, 0xb5, 0xf1, 0x88, 0xfb, 0x3d, 0x0d, 0x13, 0x53, 0x24, 0x2a, 0x44, 0x67, 0xbf, 0x82, 0x2c, 0x47, 0x00, + 0x8e, 0xe5, 0xa9, 0xac, 0xe9, 0x8f, 0x29, 0xc4, 0x41, 0x87, 0x06, 0xbd, 0x2b, 0xe4, 0x55, 0x56, 0xf2, 0x10, 0xef, + 0x09, 0x9e, 0x66, 0xf4, 0x7e, 0x83, 0x0f, 0x6d, 0xed, 0xd1, 0x13, 0x64, 0xe3, 0x29, 0xf7, 0xeb, 0xef, 0x44, 0x38, + 0x87, 0x68, 0x95, 0x0b, 0xaa, 0xd5, 0xd5, 0x0e, 0x80, 0xca, 0xb3, 0xbd, 0x7a, 0x04, 0xa7, 0x9b, 0xbe, 0xbe, 0x55, + 0xa1, 0x33, 0x07, 0x90, 0xf6, 0x90, 0xac, 0x6b, 0xae, 0x77, 0x80, 0x3b, 0x12, 0xab, 0x35, 0xd0, 0x58, 0xb7, 0x35, + 0x3b, 0xed, 0x51, 0x3c, 0x26, 0x32, 0x33, 0x16, 0x29, 0xc6, 0xdc, 0xad, 0xd3, 0xa2, 0x68, 0x83, 0x66, 0x08, 0xbb, + 0x77, 0x1d, 0xbe, 0x6e, 0x45, 0x58, 0xbf, 0xdf, 0xf6, 0x05, 0x46, 0xc3, 0x98, 0x6b, 0xf7, 0x3c, 0x43, 0x37, 0x6c, + 0xb0, 0x8d, 0x9c, 0x87, 0xc8, 0x87, 0x99, 0x3a, 0x10, 0x65, 0x6d, 0x0d, 0xd8, 0x1e, 0x71, 0xbd, 0x69, 0x15, 0x3f, + 0xaf, 0x62, 0xce, 0xf6, 0xac, 0x71, 0x4a, 0xeb, 0x6b, 0x5c, 0x73, 0x5c, 0x15, 0x22, 0x6a, 0xeb, 0x19, 0x0f, 0xc3, + 0xce, 0x17, 0xb8, 0x33, 0x2b, 0x0c, 0x5e, 0x84, 0xa5, 0x92, 0x9d, 0xca, 0xf5, 0xe7, 0xb0, 0xc5, 0x41, 0x2a, 0x5f, + 0x7a, 0xfd, 0xfd, 0xdd, 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, 0xf1, 0x6a, 0x95, 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, + 0x61, 0x8c, 0xb5, 0x0e, 0x27, 0x64, 0xa6, 0x4a, 0xf4, 0xde, 0x25, 0xeb, 0x02, 0xac, 0xfd, 0x14, 0x96, 0xb1, 0xca, + 0x35, 0xc3, 0xca, 0x54, 0x45, 0x66, 0x56, 0xd6, 0x6c, 0x3f, 0xb4, 0x4e, 0x34, 0x73, 0xf4, 0x16, 0xd0, 0x0f, 0x64, + 0xff, 0x92, 0x96, 0x6b, 0xe6, 0xf9, 0xd8, 0x34, 0x5e, 0x3f, 0xda, 0xbf, 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, 0x7d, 0xde, 0x32, 0xb5, 0x6d, 0x5b, 0xc7, 0x79, 0x9a, 0x7c, 0x65, + 0xba, 0x2f, 0xd6, 0x36, 0x22, 0xba, 0x72, 0xee, 0x73, 0x5e, 0xc1, 0xad, 0x6f, 0x4a, 0x43, 0xaf, 0x25, 0x00, 0xd1, + 0x69, 0x03, 0xfe, 0x82, 0x95, 0xeb, 0x51, 0xc5, 0xcb, 0x0a, 0x24, 0x2c, 0x28, 0xc2, 0x9b, 0x62, 0x6f, 0x0a, 0x77, + 0xe3, 0xf4, 0x1c, 0x76, 0xe0, 0x62, 0x8a, 0xee, 0x38, 0x31, 0x99, 0x95, 0x46, 0x2b, 0x1a, 0xe9, 0x5f, 0xae, 0x2f, + 0xb1, 0xee, 0x8b, 0x56, 0xe6, 0xd9, 0x9c, 0x0a, 0x8b, 0xdd, 0x55, 0x2e, 0x9d, 0xa8, 0xdf, 0x32, 0xe1, 0xca, 0x95, + 0x20, 0x20, 0xd3, 0x82, 0xf5, 0x0a, 0xb3, 0x8b, 0xe4, 0x1a, 0x08, 0x19, 0x18, 0xbe, 0x06, 0x6b, 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, 0xca, 0x52, 0xda, 0x4b, 0xd0, 0x34, 0x5e, 0xb1, 0x95, 0xf2, 0x01, 0xa0, 0xe7, 0x6c, 0xa5, + 0x8c, 0xfd, 0xf1, 0xeb, 0x33, 0xb6, 0xd2, 0xd2, 0xe0, 0xe9, 0xd5, 0xec, 0x7c, 0x76, 0x36, 0x60, 0x07, 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, 0xd9, 0x9b, + 0x40, 0x2a, 0x66, 0x66, 0xaa, 0x30, 0x36, 0x26, 0x11, 0xc4, 0x3b, 0xed, 0xac, 0x17, 0xca, 0xed, 0xae, 0xd1, 0x40, + 0xae, 0x0c, 0xbe, 0xa8, 0xe2, 0xc9, 0xde, 0xb0, 0xab, 0x62, 0x1c, 0x85, 0x6b, 0xa3, 0x7c, 0x3b, 0x3b, 0x04, 0xf0, + 0xda, 0xb3, 0xa1, 0x2f, 0x97, 0x38, 0xdb, 0x7f, 0x4a, 0x1e, 0x3f, 0x25, 0xf4, 0x8c, 0x9d, 0x7d, 0xf5, 0x94, 0x9e, + 0x29, 0x72, 0xb2, 0x37, 0x89, 0xae, 0x99, 0xc5, 0x7c, 0x39, 0x50, 0x4d, 0xa0, 0x97, 0xa3, 0xb5, 0x50, 0x0b, 0x4c, + 0x3b, 0x34, 0x85, 0xdf, 0x8e, 0xf7, 0x82, 0xc1, 0x75, 0xbb, 0xe9, 0xd7, 0xed, 0xb6, 0x7a, 0x5e, 0x5d, 0x7b, 0x07, + 0xd1, 0x6e, 0x31, 0x93, 0xbf, 0x8f, 0xf7, 0xdc, 0x1c, 0x60, 0x7d, 0x0f, 0x8f, 0x89, 0x69, 0xd2, 0xce, 0xa8, 0xf8, + 0x35, 0x3d, 0xc1, 0x3e, 0x34, 0x8b, 0xec, 0xe8, 0xc3, 0xf0, 0xdf, 0xea, 0x44, 0x7d, 0xf6, 0xd5, 0x01, 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, 0x7d, 0x78, 0xb9, 0x87, 0xab, 0x08, 0x50, 0xb2, + 0x58, 0xf0, 0xf5, 0xe0, 0x52, 0x6f, 0xee, 0xbd, 0x80, 0x0c, 0xbe, 0x0e, 0x8e, 0xbe, 0x1e, 0xc8, 0x41, 0x70, 0xb8, + 0x7f, 0x79, 0x14, 0x38, 0xe3, 0x7e, 0x08, 0xf1, 0xa8, 0x2a, 0x8a, 0x99, 0x30, 0x55, 0x24, 0xb6, 0xf6, 0xdc, 0xd6, + 0xab, 0x8c, 0xcf, 0x68, 0x3a, 0xb5, 0xc8, 0xdf, 0x61, 0xca, 0x62, 0xf3, 0x3b, 0x98, 0xf0, 0xab, 0x20, 0x72, 0x41, + 0x50, 0x67, 0x79, 0x14, 0xd3, 0x25, 0xbb, 0x15, 0x61, 0x4a, 0x93, 0xfd, 0x9c, 0x90, 0x28, 0x5c, 0x2a, 0xf0, 0x3c, + 0xf5, 0x3a, 0x81, 0x38, 0xae, 0xee, 0xf3, 0x5b, 0x11, 0x2e, 0x69, 0xbe, 0x9f, 0x90, 0x56, 0x11, 0x2e, 0x22, 0xcb, + 0xa6, 0xa6, 0x17, 0x2c, 0x5c, 0xd1, 0x4b, 0x60, 0xa6, 0xe4, 0x3a, 0xbc, 0x04, 0x2e, 0x6f, 0x3d, 0x5f, 0x2d, 0xd8, + 0x65, 0x43, 0xfa, 0x66, 0xf8, 0xe2, 0x0b, 0xeb, 0x93, 0x07, 0x3c, 0xa4, 0xf3, 0xc3, 0x4b, 0xc1, 0x06, 0xe0, 0x3a, + 0xe3, 0x37, 0xdf, 0xc9, 0x5b, 0x3d, 0x2f, 0xed, 0x29, 0xc6, 0x99, 0x69, 0x27, 0x26, 0xed, 0x84, 0xdc, 0xbf, 0x6f, + 0x6f, 0x62, 0x73, 0xb2, 0x97, 0xd1, 0x5a, 0xb9, 0xac, 0x5a, 0x86, 0xa4, 0x58, 0x33, 0xe4, 0xef, 0x51, 0x72, 0x6a, + 0x05, 0x9e, 0xec, 0x82, 0x57, 0xc9, 0xd2, 0x3f, 0xa8, 0xac, 0xd5, 0x80, 0x3d, 0x46, 0x2c, 0x0b, 0x85, 0x63, 0xff, + 0x26, 0x63, 0xc5, 0xda, 0x17, 0x68, 0xc4, 0xc8, 0xbd, 0xbd, 0xc9, 0x98, 0x17, 0x73, 0x35, 0x59, 0x7b, 0xa1, 0xea, + 0xbc, 0xf4, 0xbc, 0xc5, 0x7b, 0x39, 0xa5, 0x86, 0x91, 0x88, 0xee, 0x8d, 0x95, 0x19, 0xa5, 0x4a, 0xd4, 0x1a, 0x34, + 0x22, 0xd8, 0xd8, 0x05, 0xbf, 0x04, 0x27, 0x54, 0xee, 0xa9, 0xb3, 0x7d, 0x3b, 0xa5, 0xd2, 0x03, 0x96, 0xa5, 0x46, + 0x55, 0xee, 0x96, 0x99, 0x64, 0xd5, 0x20, 0x18, 0xfd, 0x59, 0x4a, 0x31, 0xc3, 0x3b, 0x23, 0x0b, 0xa6, 0x60, 0x25, + 0xa8, 0x6a, 0x19, 0x96, 0x43, 0x8e, 0x5a, 0x3c, 0xe3, 0x93, 0x2a, 0xf5, 0x8f, 0x8e, 0x20, 0xb9, 0xcb, 0x75, 0x2b, + 0x48, 0xee, 0xd3, 0xf1, 0x53, 0x3d, 0xd0, 0xe9, 0x5a, 0x3b, 0x1e, 0xfa, 0xfc, 0x36, 0xe2, 0x6b, 0xeb, 0xde, 0x53, + 0xad, 0x55, 0x28, 0x03, 0x2d, 0x56, 0x54, 0xae, 0xd4, 0x92, 0xde, 0xef, 0x22, 0x00, 0x16, 0xb1, 0x31, 0x1b, 0xef, + 0xda, 0x66, 0x85, 0xa0, 0xd1, 0x65, 0x47, 0x9b, 0x78, 0xc0, 0x12, 0xdd, 0xda, 0xc1, 0x84, 0xc6, 0x47, 0xac, 0xec, + 0xf7, 0xf3, 0x23, 0xa0, 0xa7, 0xda, 0x88, 0xa9, 0x80, 0x23, 0xff, 0x4b, 0x2b, 0x32, 0x45, 0x81, 0xcd, 0x9a, 0xba, + 0x5b, 0x63, 0x19, 0x89, 0xbe, 0x4c, 0xe9, 0xf2, 0x84, 0x67, 0xc0, 0xb4, 0x5e, 0xb7, 0x1c, 0x57, 0x76, 0x15, 0x47, + 0x9e, 0x0a, 0xcb, 0x8a, 0xf3, 0x2a, 0x1c, 0x6f, 0x3d, 0xbe, 0xc1, 0xbe, 0x61, 0xd3, 0x2e, 0xfc, 0x21, 0x84, 0x85, + 0xf0, 0x26, 0x83, 0xdb, 0x88, 0xb6, 0x93, 0x40, 0xe5, 0x8d, 0xb9, 0x4e, 0x28, 0x9b, 0xdb, 0xf5, 0xda, 0x33, 0x48, + 0x27, 0xe6, 0x40, 0xa9, 0x46, 0xd0, 0x1a, 0xcd, 0x82, 0xaa, 0x11, 0x8f, 0x1c, 0x0f, 0xef, 0x0c, 0x62, 0xb5, 0x7c, + 0x49, 0x53, 0x29, 0x1a, 0x80, 0x71, 0x01, 0x5c, 0x9e, 0x7e, 0x79, 0xff, 0xd3, 0x29, 0x8f, 0x8b, 0x64, 0xf9, 0x2e, + 0x2e, 0xe2, 0xab, 0x32, 0xdc, 0xa8, 0x31, 0x8a, 0x6b, 0x32, 0x15, 0x03, 0x26, 0xcd, 0x4a, 0x6a, 0xee, 0x4a, 0x4d, + 0x88, 0xb1, 0xce, 0x64, 0x5d, 0x56, 0xf2, 0xaa, 0x51, 0xe9, 0xba, 0xc8, 0xf0, 0xe3, 0x96, 0xcf, 0xe9, 0x3e, 0x00, + 0x79, 0x1a, 0x17, 0xd2, 0x48, 0xea, 0x42, 0x8c, 0xb9, 0x88, 0xd7, 0xf5, 0xf1, 0xb8, 0xd1, 0xf5, 0x92, 0x3d, 0x1b, + 0x3f, 0x99, 0xbe, 0xc9, 0xc2, 0x6c, 0x20, 0xc8, 0xa8, 0x5a, 0x72, 0xd1, 0x32, 0xe5, 0x54, 0x26, 0x01, 0xe8, 0xe3, + 0xd9, 0x63, 0xec, 0x60, 0x3c, 0x26, 0x9b, 0xb6, 0x78, 0x80, 0x87, 0xcb, 0x75, 0x58, 0x90, 0x99, 0xae, 0x23, 0x0a, + 0x04, 0xbf, 0xad, 0x02, 0x40, 0x72, 0xb4, 0x55, 0x19, 0x2e, 0x8d, 0x3d, 0x1b, 0x4f, 0xa8, 0xc4, 0x6e, 0x87, 0xa4, + 0xf6, 0x2a, 0x74, 0x33, 0x2f, 0x7d, 0x8f, 0x22, 0x69, 0x5c, 0x96, 0x76, 0x2a, 0x95, 0x6a, 0xcf, 0xcc, 0x5c, 0xd7, + 0x20, 0x06, 0x43, 0xa8, 0xeb, 0x2e, 0xbd, 0xba, 0x77, 0x9b, 0x6b, 0xcd, 0x76, 0xc0, 0x7b, 0x0d, 0x9a, 0xa1, 0xe4, + 0x2d, 0xe6, 0xad, 0x2b, 0xa2, 0xa6, 0xab, 0x35, 0x98, 0x15, 0xa3, 0x6c, 0x29, 0x4a, 0xd7, 0x14, 0x94, 0x82, 0xd1, + 0xc5, 0xda, 0x5b, 0xb8, 0x6f, 0x64, 0xe3, 0xc2, 0x92, 0xe9, 0xd5, 0xa2, 0xa4, 0x84, 0xea, 0xa6, 0x62, 0xa4, 0x84, + 0x91, 0xd2, 0xf0, 0x54, 0xbe, 0x17, 0x78, 0x9c, 0xe7, 0x41, 0xd4, 0xf2, 0x02, 0x3b, 0xae, 0xc8, 0x31, 0x38, 0x7a, + 0x99, 0x9c, 0x86, 0x02, 0xff, 0x98, 0x29, 0x10, 0xd3, 0xa1, 0xba, 0xdf, 0xe0, 0xe6, 0xff, 0x67, 0xc1, 0x02, 0x8f, + 0x6f, 0xbd, 0xc4, 0x6d, 0xf4, 0xcf, 0xc2, 0xa7, 0xa5, 0xcf, 0xa5, 0xef, 0xea, 0xe2, 0x49, 0x7b, 0xb3, 0x51, 0xb2, + 0xcc, 0xf2, 0xf4, 0xad, 0x4c, 0x39, 0x88, 0xcc, 0xd0, 0x1a, 0x94, 0x1d, 0x89, 0xc6, 0x0d, 0x0f, 0x8c, 0x18, 0x1b, + 0x37, 0xbe, 0x1f, 0x33, 0x90, 0x0d, 0x83, 0xd5, 0x37, 0x4b, 0x65, 0xb2, 0xbe, 0x02, 0x4c, 0x11, 0x25, 0x3f, 0x79, + 0x99, 0x73, 0x78, 0x0a, 0xf5, 0xf5, 0x0b, 0xdc, 0xe6, 0x4a, 0xdf, 0xe7, 0xfc, 0xc7, 0x8c, 0xfe, 0x88, 0x40, 0x27, + 0xf1, 0x0a, 0xe4, 0x1e, 0xcf, 0xa1, 0x6e, 0x84, 0xa9, 0xe5, 0x18, 0x1c, 0x08, 0xd1, 0x40, 0x44, 0xc5, 0x02, 0x05, + 0x75, 0x61, 0x80, 0x35, 0xd4, 0x05, 0x73, 0x78, 0x9e, 0xcb, 0xe4, 0xe3, 0xd4, 0xf8, 0xcc, 0x0f, 0x63, 0x8c, 0x99, + 0x1c, 0x0c, 0xc2, 0x6a, 0x16, 0x0c, 0xc7, 0xa3, 0xc9, 0xc1, 0x33, 0x38, 0xb7, 0x83, 0x71, 0x40, 0x06, 0x41, 0x5d, + 0xae, 0x62, 0x41, 0xcb, 0xeb, 0x4b, 0x5b, 0x06, 0x7e, 0x5c, 0x07, 0x83, 0x7f, 0x16, 0x9e, 0xe2, 0x1d, 0x34, 0x27, + 0x67, 0x32, 0x04, 0x1b, 0xfb, 0x35, 0x01, 0x49, 0x59, 0x4f, 0xf3, 0x93, 0xfa, 0x70, 0x63, 0x4a, 0xfb, 0x67, 0x0e, + 0x2f, 0x38, 0xec, 0x90, 0x40, 0x81, 0x34, 0x9e, 0x66, 0xa3, 0xd7, 0x4a, 0x91, 0xfb, 0xae, 0xe0, 0x70, 0x67, 0xee, + 0x39, 0xd3, 0x23, 0xa7, 0x90, 0x68, 0x66, 0x01, 0x37, 0xf2, 0xd7, 0xe2, 0x3a, 0xce, 0xb3, 0x74, 0xaf, 0xf9, 0x66, + 0xaf, 0xbc, 0x13, 0x55, 0x7c, 0x3b, 0x0a, 0x8c, 0x35, 0x21, 0xf7, 0x55, 0x4f, 0x80, 0x9e, 0x00, 0x5b, 0x00, 0x0c, + 0x88, 0x77, 0xcc, 0x4c, 0x66, 0x3c, 0x02, 0x8f, 0xc0, 0xa6, 0x0f, 0x64, 0x71, 0xe7, 0x5c, 0x92, 0xfc, 0xcd, 0x54, + 0xda, 0xab, 0x5e, 0xb9, 0x53, 0x90, 0xf5, 0x6a, 0x2b, 0x77, 0xdd, 0xfa, 0xec, 0x9b, 0x0e, 0xaf, 0xc0, 0x73, 0x09, + 0x6e, 0x91, 0xfd, 0x7e, 0x53, 0x50, 0x29, 0x8c, 0x8a, 0x78, 0x27, 0xb9, 0x46, 0xff, 0x76, 0x6f, 0x6c, 0x14, 0xc9, + 0x2d, 0x1f, 0x1e, 0x40, 0x9d, 0xc9, 0xbb, 0xe2, 0x76, 0x0e, 0x51, 0x5b, 0x77, 0xe3, 0x81, 0xd5, 0x06, 0xed, 0xb2, + 0xe6, 0x08, 0x2e, 0xbc, 0xd8, 0xcb, 0x60, 0x2c, 0x70, 0x56, 0x46, 0x4a, 0x8d, 0x6b, 0x48, 0x2d, 0xf8, 0x24, 0x4f, + 0xef, 0x21, 0x4b, 0x3d, 0x09, 0x8a, 0x1c, 0xcf, 0x62, 0xc8, 0x34, 0xde, 0x06, 0x1e, 0xbf, 0x93, 0x21, 0x48, 0xd3, + 0xb6, 0xdb, 0xe6, 0x08, 0x94, 0xdd, 0x03, 0x53, 0x92, 0xba, 0x36, 0xa6, 0x06, 0x1a, 0x6a, 0x0f, 0x35, 0x52, 0x11, + 0x67, 0x47, 0x6f, 0x40, 0x87, 0x08, 0xbe, 0xdf, 0x69, 0x56, 0x76, 0xbc, 0x98, 0x10, 0x3c, 0x79, 0x5f, 0xde, 0x66, + 0x65, 0x55, 0x46, 0xef, 0x53, 0x34, 0x84, 0x4a, 0xa4, 0x88, 0x5e, 0x41, 0x3c, 0xbd, 0x12, 0x7f, 0x97, 0xd1, 0x4f, + 0x29, 0x8d, 0xd3, 0x14, 0xd3, 0x5f, 0x14, 0xf0, 0xf3, 0x39, 0xa0, 0x3a, 0xe2, 0x4e, 0x88, 0xce, 0x25, 0xd8, 0xab, + 0x41, 0x34, 0xab, 0x8a, 0x03, 0x86, 0x66, 0x74, 0x2b, 0x28, 0x62, 0xb4, 0x61, 0xf6, 0x1f, 0x0a, 0x14, 0x0a, 0xa9, + 0x62, 0xbe, 0x13, 0xf6, 0x21, 0xfa, 0x11, 0x8b, 0x3c, 0x7e, 0xf7, 0xda, 0x0c, 0x69, 0x74, 0x27, 0xa9, 0xde, 0xda, + 0x78, 0x6c, 0x61, 0xe0, 0xb2, 0xe8, 0x72, 0x4d, 0xcf, 0xe2, 0x55, 0x16, 0x6d, 0x00, 0x7f, 0xe2, 0xdd, 0xeb, 0xe7, + 0xca, 0xc2, 0xe4, 0x45, 0x06, 0x8a, 0x83, 0xe3, 0x77, 0xaf, 0xdf, 0xc8, 0x74, 0x9d, 0xf3, 0xe8, 0x4c, 0x22, 0x69, + 0x3d, 0x7e, 0xf7, 0xfa, 0x67, 0x34, 0xf7, 0xfa, 0xa9, 0x80, 0xf7, 0xaf, 0x80, 0xb7, 0x8c, 0xe2, 0x35, 0xf4, 0x49, + 0xfd, 0x4e, 0xd6, 0xd8, 0x29, 0xaf, 0xd6, 0x32, 0xfa, 0x25, 0xad, 0x3d, 0x69, 0xd5, 0xbf, 0x0a, 0x9f, 0xda, 0x79, + 0x02, 0x9e, 0xdb, 0x3c, 0x13, 0x1f, 0x23, 0x2b, 0xda, 0x09, 0xa2, 0xaf, 0xf7, 0x6e, 0xaf, 0x72, 0x51, 0x46, 0xf8, + 0x82, 0xa1, 0x5d, 0x50, 0xb4, 0xbf, 0x7f, 0x73, 0x73, 0x33, 0xba, 0x79, 0x32, 0x92, 0xc5, 0xe5, 0xfe, 0xe4, 0xdb, + 0x6f, 0xbf, 0xdd, 0xc7, 0xb7, 0xc1, 0xd7, 0x6d, 0xb7, 0xf7, 0x8a, 0xf0, 0x01, 0x0b, 0x10, 0xa1, 0xfa, 0x6b, 0xb8, + 0xa2, 0x80, 0x16, 0x6e, 0xf0, 0x75, 0xf0, 0xb5, 0x3e, 0x74, 0xbe, 0x3e, 0x2c, 0xaf, 0x2f, 0x55, 0xf9, 0x5d, 0x25, + 0x1f, 0x8c, 0xc7, 0xe3, 0x7d, 0x90, 0x40, 0x7d, 0x3d, 0xe0, 0x83, 0xe0, 0x28, 0x18, 0x64, 0x70, 0xa1, 0x29, 0xaf, + 0x2f, 0x8f, 0x02, 0xcf, 0x34, 0xb7, 0xc1, 0x22, 0x3a, 0x10, 0x97, 0x60, 0xff, 0x92, 0x06, 0x5f, 0x07, 0xc4, 0xa5, + 0x7c, 0x05, 0x29, 0x5f, 0x1d, 0x3c, 0xf3, 0xd3, 0xfe, 0x97, 0x4a, 0x7b, 0xe2, 0xa7, 0x1d, 0x62, 0xda, 0x93, 0xe7, + 0x7e, 0xda, 0x91, 0x4a, 0x7b, 0xe9, 0xa7, 0xfd, 0xef, 0x72, 0x00, 0xa9, 0x7b, 0xbe, 0xf5, 0xdf, 0xb9, 0xd7, 0x1a, + 0x3c, 0x85, 0xa2, 0xec, 0x2a, 0xbe, 0xe4, 0xd0, 0xe8, 0xc1, 0xed, 0x55, 0x4e, 0x83, 0x01, 0xb6, 0xd7, 0x33, 0x09, + 0xf1, 0x3e, 0xf8, 0x7a, 0x5d, 0xe4, 0x61, 0xf0, 0xf5, 0x00, 0x0b, 0x19, 0x7c, 0x1d, 0x90, 0xaf, 0x8d, 0x81, 0x8c, + 0x60, 0x9b, 0xc0, 0x85, 0x22, 0x1d, 0xda, 0x00, 0x61, 0xbe, 0x34, 0xae, 0xa6, 0x7f, 0x15, 0xdd, 0xd9, 0xf0, 0x96, + 0xa8, 0xdc, 0x74, 0x83, 0x9a, 0x9e, 0x80, 0x77, 0x02, 0x34, 0x2a, 0x0a, 0xae, 0xe3, 0x22, 0x1c, 0x0e, 0xcb, 0xeb, + 0x4b, 0x02, 0x76, 0x99, 0x2b, 0x1e, 0x57, 0x51, 0x20, 0xe4, 0x50, 0xfd, 0x0c, 0x54, 0xe4, 0xab, 0x00, 0x01, 0x91, + 0xe0, 0xbf, 0xa0, 0xa6, 0xef, 0x24, 0xdb, 0x04, 0xc3, 0x1b, 0x7e, 0xfe, 0x31, 0xab, 0x86, 0x4a, 0xb4, 0x78, 0x2d, + 0x28, 0xfc, 0x80, 0xbf, 0xae, 0xea, 0xe8, 0x2f, 0x70, 0xe3, 0x6e, 0x6a, 0xd8, 0xdf, 0x49, 0xc7, 0xa2, 0xbe, 0x93, + 0xf3, 0x6c, 0x31, 0x6d, 0x1d, 0xe8, 0x27, 0x92, 0x54, 0xf3, 0x6c, 0x10, 0x0c, 0x83, 0x01, 0x5f, 0xb0, 0x13, 0x39, + 0xe7, 0x9e, 0xf9, 0xd4, 0x23, 0xe9, 0x4f, 0xf3, 0x2c, 0x1b, 0x80, 0x6f, 0x0a, 0xf2, 0x23, 0xfb, 0xff, 0x3d, 0x1f, + 0xa2, 0xf0, 0x70, 0xf0, 0x68, 0x9f, 0xcc, 0x82, 0xd5, 0x2d, 0x7a, 0x74, 0x46, 0x41, 0x26, 0x96, 0xbc, 0xc8, 0x2a, + 0x6f, 0xa9, 0xdc, 0xad, 0xdb, 0x5e, 0x1e, 0xf7, 0x9e, 0xcd, 0xab, 0x58, 0x04, 0xea, 0x9c, 0x03, 0xc5, 0x1b, 0xca, + 0x9e, 0xca, 0xa6, 0x84, 0x54, 0x1b, 0xf2, 0x86, 0xe5, 0x80, 0x05, 0x87, 0xbd, 0xe1, 0x70, 0x2f, 0x18, 0x38, 0x75, + 0xee, 0x20, 0xd8, 0x1b, 0x0e, 0x8f, 0x02, 0x77, 0x1f, 0xca, 0x46, 0xee, 0xce, 0x48, 0x0b, 0xf6, 0xaf, 0x22, 0x2c, + 0x29, 0x88, 0xc7, 0xa4, 0x16, 0x7f, 0x69, 0x70, 0x99, 0x01, 0x40, 0x1f, 0x29, 0x09, 0x98, 0x81, 0x95, 0x19, 0x40, + 0x68, 0x6e, 0x1a, 0xb3, 0x33, 0x60, 0x1e, 0x81, 0x63, 0x1e, 0x21, 0xe3, 0x00, 0x88, 0x25, 0x01, 0xce, 0x5d, 0x10, + 0xc5, 0xba, 0x90, 0x47, 0x00, 0x7a, 0x8f, 0x3f, 0x89, 0x29, 0x05, 0x93, 0x74, 0xac, 0x42, 0x10, 0xc4, 0xf1, 0xd9, + 0xb5, 0x68, 0x4d, 0xce, 0x12, 0x1d, 0xcc, 0x48, 0x02, 0x6c, 0x88, 0x81, 0x9d, 0x83, 0xfb, 0x39, 0x28, 0x3d, 0xac, + 0xde, 0x09, 0xb9, 0xe0, 0x3b, 0xee, 0xc9, 0x66, 0xe1, 0xea, 0x09, 0x07, 0xc1, 0x1d, 0xd7, 0x2c, 0xc0, 0xa8, 0x2a, + 0xd6, 0x65, 0xc5, 0xd3, 0x0f, 0x77, 0x2b, 0x88, 0x7d, 0x87, 0x03, 0xfa, 0x4e, 0xe6, 0x59, 0x72, 0x17, 0x3a, 0x7b, + 0xae, 0x8d, 0x4a, 0xff, 0xe1, 0xc3, 0x9b, 0x9f, 0x22, 0x10, 0x39, 0xd6, 0x86, 0xd2, 0xdf, 0x71, 0x3c, 0x9b, 0xfc, + 0x08, 0x4f, 0xfe, 0xc6, 0xbe, 0xe3, 0xf6, 0xf4, 0xe8, 0xf7, 0xa1, 0x6e, 0x7a, 0xc7, 0x67, 0x77, 0x7c, 0xe4, 0x8a, + 0x43, 0x75, 0x85, 0xfb, 0xfa, 0x66, 0xed, 0x1b, 0x21, 0x3d, 0x3c, 0xcf, 0x94, 0x37, 0xe6, 0x47, 0x3b, 0x18, 0x06, + 0xc1, 0x54, 0x0b, 0x25, 0x21, 0xea, 0x06, 0x53, 0x02, 0x86, 0x68, 0x4f, 0x2f, 0xab, 0x29, 0x72, 0x6e, 0x6a, 0x64, + 0xe1, 0xfd, 0x80, 0x69, 0xa1, 0x43, 0x23, 0x87, 0xf2, 0x83, 0xc3, 0x09, 0x63, 0x16, 0x7e, 0xab, 0x84, 0xe9, 0x57, + 0x8b, 0xca, 0x39, 0x88, 0xee, 0x81, 0x31, 0xae, 0xe0, 0x05, 0x74, 0x85, 0x5d, 0xaf, 0x55, 0x54, 0x0c, 0x04, 0x8f, + 0x43, 0x0e, 0xd0, 0xc3, 0x2e, 0x68, 0x59, 0x59, 0xaa, 0x5b, 0x95, 0xb3, 0x54, 0x51, 0x97, 0xa1, 0xac, 0x8c, 0x15, + 0xe6, 0x7b, 0xc9, 0x7e, 0x28, 0xd0, 0xb3, 0x7c, 0x2a, 0xba, 0xe0, 0x85, 0x50, 0x82, 0xe5, 0xba, 0xde, 0x89, 0x40, + 0xd4, 0xf9, 0xa1, 0x77, 0xd5, 0xd7, 0x38, 0x76, 0x3c, 0x7d, 0x23, 0x53, 0xae, 0x4d, 0x28, 0x34, 0x9f, 0x2f, 0x7d, + 0xc5, 0x44, 0xc1, 0x6e, 0xa0, 0x5f, 0x6d, 0x1b, 0x7d, 0x76, 0xb7, 0xd6, 0x9b, 0x41, 0x89, 0x8e, 0x79, 0x8d, 0x82, + 0x6b, 0xa5, 0x50, 0x30, 0xda, 0xdb, 0xf8, 0x33, 0x1c, 0xb9, 0xd5, 0xed, 0xa1, 0xf7, 0x5b, 0x15, 0x5f, 0xbe, 0x45, + 0xdf, 0x4e, 0xfb, 0x73, 0x54, 0xc9, 0x5f, 0x56, 0x2b, 0xf0, 0xa1, 0x82, 0xc8, 0x22, 0x16, 0x97, 0x16, 0xea, 0x39, + 0x7d, 0x77, 0xfc, 0x16, 0xfc, 0x28, 0xf1, 0xf7, 0xaf, 0xdf, 0x07, 0x35, 0x99, 0xc6, 0xb3, 0xc2, 0x7c, 0x68, 0x73, + 0x40, 0x68, 0x12, 0x97, 0x66, 0xdf, 0xcf, 0xe2, 0x26, 0xfb, 0xae, 0xd9, 0x7a, 0x5a, 0x34, 0x91, 0xa4, 0x0c, 0xb7, + 0x0f, 0x06, 0x04, 0xfa, 0x00, 0x51, 0x9c, 0x7d, 0x41, 0x63, 0x48, 0xf3, 0x99, 0x7d, 0x3f, 0x22, 0xde, 0xcb, 0x9d, + 0x10, 0x62, 0x5c, 0x61, 0xd1, 0xe8, 0x21, 0x9f, 0xf1, 0x48, 0x19, 0x16, 0xbd, 0xc7, 0x04, 0xe2, 0x0c, 0xa7, 0xd5, + 0x7b, 0xc4, 0x3c, 0xc6, 0xbb, 0x81, 0x96, 0x3d, 0x44, 0x19, 0x75, 0xd9, 0x1b, 0x16, 0xdf, 0x1f, 0xd7, 0x61, 0x66, + 0x2d, 0x2f, 0x87, 0xf0, 0x37, 0xd0, 0x06, 0xe0, 0x94, 0x23, 0xcb, 0x57, 0x99, 0x8d, 0xae, 0x96, 0x98, 0xde, 0x44, + 0x10, 0x8b, 0x47, 0xa7, 0xc3, 0xda, 0xd5, 0xa9, 0x7a, 0x57, 0x3b, 0x9f, 0x89, 0x5e, 0x05, 0x5a, 0xb9, 0xb6, 0x3d, + 0x1e, 0xc2, 0x5d, 0x6a, 0x69, 0x85, 0x8d, 0x28, 0xe7, 0xe2, 0xe9, 0xce, 0xb1, 0x39, 0x01, 0x0d, 0xae, 0x64, 0x0a, + 0xc0, 0x59, 0x5a, 0x8d, 0x46, 0x8d, 0xb0, 0xcf, 0xca, 0xf9, 0x1c, 0xb6, 0x16, 0xe2, 0x69, 0x01, 0x18, 0x6e, 0x13, + 0x83, 0x92, 0x77, 0x63, 0x50, 0x4e, 0x3f, 0x2a, 0x78, 0xeb, 0xe0, 0xac, 0x5c, 0xc6, 0xa9, 0xbc, 0x01, 0x2c, 0xc6, + 0xc0, 0x4f, 0xc5, 0x52, 0xbd, 0x84, 0x64, 0xc9, 0x93, 0x8f, 0x68, 0xb5, 0x91, 0x06, 0xc0, 0x55, 0x4e, 0x8d, 0xe5, + 0x9e, 0x02, 0x09, 0x75, 0xa5, 0xa8, 0x84, 0xb8, 0xaa, 0xe2, 0x64, 0x79, 0x8a, 0xa9, 0xe1, 0x06, 0x7a, 0x11, 0x05, + 0x72, 0xc5, 0x05, 0x90, 0xf4, 0x9c, 0xfd, 0x9e, 0x69, 0xac, 0xf1, 0xe7, 0x12, 0x05, 0x4c, 0x1a, 0x35, 0x18, 0x2b, + 0x65, 0x2f, 0xa5, 0x89, 0xf6, 0x16, 0x04, 0xb5, 0x7b, 0xf9, 0x17, 0xd4, 0xfd, 0x1c, 0x5a, 0x11, 0x36, 0xc0, 0x10, + 0xe5, 0x39, 0xee, 0xd0, 0xd4, 0x2e, 0x39, 0x0f, 0x18, 0xd1, 0x79, 0x9f, 0xd5, 0x76, 0xab, 0x3f, 0x5f, 0x02, 0xb6, + 0x69, 0x6a, 0x7c, 0x0a, 0xc3, 0x84, 0x98, 0xd8, 0xc0, 0x56, 0x59, 0x69, 0x37, 0x94, 0x69, 0x27, 0x5d, 0x32, 0xaf, + 0x85, 0xd3, 0xbc, 0xc7, 0xd8, 0x72, 0xa4, 0x72, 0xf7, 0xfb, 0xa1, 0xf9, 0xc9, 0x72, 0xfa, 0x5c, 0x87, 0x6c, 0xf6, + 0xc6, 0x83, 0xe6, 0x44, 0xab, 0xab, 0x3a, 0xfa, 0x01, 0x1d, 0x80, 0x99, 0xb6, 0x00, 0x99, 0x2e, 0xd8, 0xb4, 0xaf, + 0x44, 0xc5, 0x25, 0x09, 0x4b, 0x25, 0x81, 0x9d, 0xdd, 0x94, 0xec, 0x6c, 0x02, 0xe2, 0x19, 0xee, 0x7a, 0x5a, 0xec, + 0x84, 0x34, 0xe1, 0x2d, 0xf6, 0x12, 0x10, 0x75, 0xa8, 0xea, 0x12, 0xb2, 0x31, 0x86, 0x2e, 0xfe, 0x45, 0x29, 0x4c, + 0x58, 0xcb, 0xa4, 0x2a, 0x31, 0x41, 0x90, 0xca, 0xdd, 0x16, 0x81, 0x25, 0x0a, 0x76, 0x00, 0x7b, 0xef, 0x46, 0xdd, + 0x8c, 0x9a, 0xaa, 0x4e, 0xbd, 0x04, 0x1f, 0xa7, 0x59, 0x57, 0x41, 0x66, 0x61, 0x57, 0xc5, 0x9a, 0x07, 0x3a, 0x36, + 0x95, 0x32, 0x26, 0xee, 0xd2, 0x22, 0x43, 0x3c, 0x60, 0x8c, 0xa5, 0x0b, 0x81, 0x7c, 0xb3, 0xdd, 0x71, 0xd3, 0x13, + 0x84, 0x7e, 0xc2, 0x86, 0x12, 0xb8, 0xe9, 0x6c, 0x4f, 0x4d, 0x33, 0x1f, 0x10, 0x71, 0x18, 0x50, 0x20, 0xd9, 0x38, + 0xa4, 0x39, 0xd2, 0x17, 0x24, 0x4d, 0x18, 0x18, 0x5a, 0xf1, 0x9c, 0x20, 0x2b, 0x0a, 0x3d, 0x5b, 0x57, 0x6d, 0x9c, + 0x2b, 0xc3, 0x1c, 0x2d, 0x39, 0x15, 0x3e, 0x27, 0xc8, 0xc4, 0xee, 0x69, 0x9b, 0x99, 0x0c, 0x47, 0xc9, 0x02, 0xf3, + 0x2b, 0x88, 0x12, 0x77, 0xa6, 0x59, 0x95, 0x83, 0x71, 0x01, 0x0b, 0xb4, 0xf2, 0x3d, 0xa8, 0x1b, 0x6b, 0x68, 0xa3, + 0x61, 0x88, 0xdd, 0xfe, 0x04, 0xfb, 0xb5, 0x76, 0x5a, 0x97, 0x29, 0x96, 0x97, 0x29, 0x44, 0x7b, 0x21, 0xf3, 0x1b, + 0x45, 0xa2, 0x3b, 0x45, 0x18, 0x12, 0xd6, 0x51, 0xf6, 0xa4, 0x4d, 0x0d, 0xa0, 0xa7, 0x5e, 0xc0, 0xf3, 0xce, 0xb5, + 0x0c, 0xbb, 0x48, 0xf7, 0x57, 0x05, 0x9f, 0xd2, 0x0d, 0x82, 0x14, 0xbd, 0x49, 0xc1, 0x9c, 0xd7, 0xa3, 0xa4, 0xde, + 0x9c, 0xb6, 0xcc, 0xa8, 0x3a, 0x2a, 0x42, 0xca, 0x09, 0xfe, 0x93, 0x97, 0x52, 0x13, 0x9b, 0x30, 0xc1, 0x03, 0x1f, + 0xe6, 0x19, 0x36, 0xf0, 0x76, 0xfb, 0x2e, 0x0d, 0x93, 0x36, 0xdb, 0x90, 0x82, 0xb4, 0xc2, 0xc4, 0xc5, 0x80, 0xca, + 0x5e, 0xe3, 0x7e, 0xc1, 0x76, 0xd2, 0x14, 0x3c, 0x08, 0x1b, 0x0d, 0x4c, 0xdc, 0xea, 0xe2, 0xeb, 0x30, 0xa1, 0xe1, + 0x92, 0x6a, 0x67, 0x27, 0x2d, 0x69, 0x6e, 0xaf, 0xcb, 0x0b, 0xdb, 0x07, 0x1d, 0x3b, 0xac, 0x6b, 0x78, 0xa0, 0x79, + 0xcd, 0x2e, 0xae, 0x98, 0xa6, 0x89, 0xc6, 0x7a, 0x48, 0x59, 0x72, 0xac, 0xeb, 0xe9, 0x0a, 0x57, 0xcb, 0x4c, 0x03, + 0xbb, 0x4b, 0xbc, 0xd0, 0x03, 0x1e, 0x76, 0xb8, 0x22, 0xd1, 0x05, 0x36, 0x9b, 0xad, 0x6a, 0x32, 0xcd, 0xef, 0xcb, + 0x96, 0x9b, 0x80, 0x70, 0x96, 0xfa, 0xe6, 0x3e, 0x39, 0xd6, 0xb4, 0xcd, 0x4f, 0x02, 0x1c, 0x6f, 0xaf, 0x80, 0xa4, + 0x63, 0x09, 0xba, 0xf8, 0x96, 0xfe, 0x20, 0x52, 0x33, 0x15, 0xf4, 0xde, 0xf9, 0x22, 0x75, 0xf3, 0x0b, 0xb0, 0x8d, + 0xda, 0x18, 0xd3, 0xac, 0x6c, 0x1d, 0x26, 0xca, 0xc2, 0x1a, 0x59, 0xc8, 0x25, 0xf8, 0x60, 0xee, 0x36, 0x75, 0x7a, + 0xdc, 0x41, 0x84, 0xfd, 0x2e, 0x7a, 0x3c, 0xc2, 0x58, 0xb1, 0x06, 0x89, 0x61, 0x15, 0xd6, 0xb4, 0xb9, 0x1c, 0xa2, + 0x9c, 0x9a, 0x25, 0x13, 0x2d, 0xa9, 0x4f, 0x29, 0xa2, 0x14, 0xcc, 0x8d, 0xa7, 0x65, 0xc3, 0x94, 0x10, 0x21, 0x2b, + 0xa4, 0x03, 0xaa, 0xb5, 0xd0, 0x52, 0x4d, 0xd0, 0xeb, 0xd0, 0xcb, 0x42, 0x63, 0x0a, 0xa2, 0x8f, 0xc8, 0x70, 0x23, + 0x8e, 0x8c, 0xee, 0x8e, 0x51, 0x4c, 0x20, 0x54, 0xb5, 0x97, 0x17, 0x56, 0x9f, 0x96, 0x6d, 0x75, 0x10, 0x57, 0x88, + 0x7c, 0xdf, 0x4d, 0x50, 0x63, 0x14, 0xb4, 0x39, 0xdd, 0xe8, 0x2f, 0x45, 0xe8, 0xdb, 0x85, 0x63, 0x37, 0x0a, 0x22, + 0x21, 0x02, 0xab, 0xd7, 0x54, 0x0c, 0xc8, 0x3a, 0x8f, 0x5d, 0x84, 0x26, 0xdd, 0x2d, 0x44, 0x79, 0xa3, 0xb2, 0xfe, + 0xb8, 0x0e, 0xc9, 0x76, 0x8b, 0x65, 0x81, 0x2f, 0xfb, 0xe9, 0xfa, 0x1e, 0xc8, 0xef, 0x37, 0xeb, 0xcf, 0x42, 0x7e, + 0xbf, 0xce, 0xbe, 0x04, 0xf2, 0xfb, 0xcd, 0xfa, 0x7f, 0x1a, 0xf2, 0xfb, 0x74, 0xed, 0x41, 0x7e, 0xab, 0xc1, 0xf8, + 0xad, 0x60, 0xc1, 0xc9, 0xdb, 0x80, 0xbe, 0x90, 0x2c, 0x38, 0x79, 0xf5, 0xca, 0x37, 0x02, 0x11, 0x1a, 0xb9, 0xde, + 0xc8, 0x82, 0x11, 0xb7, 0x05, 0x5e, 0xa1, 0xd6, 0xc9, 0x07, 0x2a, 0xca, 0x00, 0x78, 0xbd, 0xfc, 0x67, 0x56, 0x2d, + 0xc3, 0x60, 0x3f, 0x20, 0x33, 0x07, 0x09, 0x3a, 0x9c, 0xc0, 0xed, 0x0d, 0x4a, 0xf9, 0xfe, 0x8b, 0xd0, 0xc3, 0x47, + 0xa3, 0x51, 0x5c, 0x5c, 0xe2, 0x9d, 0xce, 0xec, 0x23, 0xc4, 0x3b, 0xce, 0x78, 0x69, 0x23, 0x44, 0x2c, 0xe3, 0xf2, + 0x4c, 0x87, 0x66, 0x29, 0xed, 0x4e, 0x84, 0x80, 0xf3, 0x67, 0x00, 0x53, 0x6f, 0xb7, 0x66, 0x8c, 0xdd, 0x50, 0x0c, + 0xb1, 0x8e, 0x1f, 0xfb, 0x7c, 0xad, 0xdf, 0x9d, 0xc7, 0x25, 0x7f, 0x17, 0x57, 0x4b, 0x06, 0x9d, 0xd4, 0xdb, 0xb5, + 0x90, 0xeb, 0x15, 0x54, 0x02, 0x37, 0x13, 0xc1, 0x93, 0xca, 0x63, 0xa2, 0x14, 0x6c, 0x79, 0x46, 0x0d, 0x70, 0x79, + 0x47, 0x0e, 0x1a, 0xda, 0x61, 0xd2, 0x3e, 0xc1, 0x46, 0xda, 0x9c, 0x81, 0x11, 0xe3, 0xcb, 0x6b, 0x2e, 0xaa, 0x9f, + 0x00, 0x5f, 0x5d, 0xf0, 0x02, 0x6e, 0x0d, 0xc8, 0xd5, 0x02, 0xd8, 0x0a, 0x94, 0x5c, 0x58, 0xc6, 0x99, 0xd3, 0xd2, + 0xf7, 0xf7, 0x50, 0x67, 0xa5, 0x81, 0x2b, 0x6c, 0x0c, 0x07, 0xde, 0x8f, 0xd0, 0xe7, 0x13, 0xdd, 0x57, 0xc1, 0xb5, + 0xf0, 0xaf, 0x35, 0x3f, 0xcb, 0x52, 0x04, 0xb6, 0xc9, 0x52, 0x6d, 0x35, 0xa4, 0xa4, 0x19, 0x98, 0xb0, 0x51, 0x5e, + 0x17, 0xf0, 0xdb, 0xc3, 0x2f, 0xa5, 0x09, 0xda, 0xf3, 0x94, 0x34, 0x95, 0x80, 0xce, 0x1d, 0xc5, 0x00, 0x71, 0x6a, + 0x0b, 0x8b, 0x20, 0x37, 0xcd, 0xd2, 0x28, 0xb6, 0xea, 0x35, 0x87, 0x5a, 0x4a, 0x15, 0x14, 0xf5, 0x59, 0x12, 0x57, + 0xfc, 0x52, 0x82, 0x9b, 0xea, 0xa8, 0x95, 0x42, 0xc1, 0xba, 0x3a, 0x13, 0x97, 0x67, 0x38, 0xba, 0x11, 0x04, 0x17, + 0x1f, 0x35, 0x92, 0x48, 0x4f, 0x6d, 0xef, 0x22, 0xfa, 0x7e, 0xf4, 0xf2, 0xed, 0x87, 0xd7, 0x1f, 0xfe, 0x75, 0xf6, + 0xfc, 0xf8, 0xc3, 0xcb, 0xef, 0x4f, 0xde, 0xbf, 0x7e, 0x79, 0x3a, 0xb7, 0xce, 0x51, 0x3b, 0x05, 0x93, 0xc5, 0x76, + 0x6b, 0xbf, 0xf8, 0xe5, 0xed, 0x8b, 0x97, 0xaf, 0x5e, 0xbf, 0x7d, 0xf9, 0x82, 0xe2, 0x21, 0x72, 0x26, 0xd6, 0x57, + 0xbc, 0xc8, 0x92, 0xb3, 0x65, 0x56, 0x56, 0xd0, 0xac, 0xb9, 0x8e, 0xfb, 0xb5, 0xa8, 0xa7, 0x09, 0xae, 0x1e, 0xb5, + 0x34, 0x98, 0x59, 0x4d, 0xc7, 0x86, 0xdc, 0x50, 0xff, 0xb5, 0x01, 0xa0, 0x6f, 0x2e, 0xb7, 0x71, 0x6b, 0x55, 0x1a, + 0xd5, 0x6e, 0x2b, 0x55, 0xe1, 0x2c, 0x01, 0x79, 0xd7, 0x53, 0x7c, 0x41, 0x57, 0xd6, 0x06, 0x37, 0xbc, 0x60, 0xb9, + 0x1d, 0x86, 0x1b, 0x25, 0xc4, 0xd1, 0xe3, 0x70, 0x11, 0xe5, 0x0a, 0x5e, 0x68, 0xcd, 0xc2, 0x15, 0x5b, 0xde, 0x93, + 0x6b, 0x15, 0x2d, 0x1b, 0x40, 0x61, 0x79, 0x73, 0x50, 0x0f, 0x97, 0xcd, 0xe7, 0xd9, 0x70, 0x12, 0xb5, 0xb2, 0x30, + 0xc6, 0xda, 0x99, 0x60, 0xe1, 0xac, 0x67, 0xaa, 0xfa, 0x51, 0x25, 0x7f, 0x92, 0x37, 0xe6, 0x5a, 0x7d, 0xb8, 0xec, + 0x48, 0x84, 0x42, 0x27, 0x51, 0x7a, 0xb8, 0x56, 0x3f, 0x00, 0xf8, 0x45, 0x13, 0xe3, 0xbf, 0xd6, 0xdc, 0x40, 0xe3, + 0x87, 0xda, 0x3f, 0xd1, 0x29, 0x12, 0xf4, 0x54, 0x78, 0x26, 0x7d, 0x7a, 0x59, 0xce, 0xc1, 0x9c, 0xcc, 0x1f, 0xc3, + 0xb9, 0xd4, 0x31, 0xbc, 0xdb, 0xf3, 0xb9, 0x98, 0xc6, 0x1a, 0x91, 0x52, 0x73, 0x56, 0xf4, 0xcb, 0xbe, 0x03, 0xaf, + 0x46, 0x15, 0xec, 0x63, 0xf8, 0x6c, 0x4c, 0x6a, 0x6d, 0x69, 0x8f, 0x0b, 0xdc, 0xfe, 0x56, 0x9b, 0xc0, 0x3d, 0xdb, + 0x8d, 0x40, 0x9b, 0x3e, 0x12, 0xed, 0x1a, 0x69, 0x79, 0x4f, 0xf7, 0xc1, 0x2e, 0xbc, 0xba, 0x87, 0x32, 0x54, 0x5d, + 0x94, 0xc1, 0x9f, 0x13, 0x45, 0x21, 0x3e, 0x43, 0x1b, 0x4c, 0xbc, 0x2c, 0x45, 0xc0, 0x3c, 0xb2, 0x50, 0xb0, 0xa3, + 0xa2, 0x09, 0x8a, 0xa5, 0xcd, 0x3f, 0x37, 0xda, 0x6e, 0x02, 0xb6, 0x7d, 0x3d, 0xf5, 0x3f, 0x36, 0xb6, 0x09, 0x7e, + 0x9a, 0x5a, 0xca, 0x70, 0xda, 0x02, 0x99, 0x69, 0x2e, 0xc8, 0xc3, 0xa4, 0x95, 0x80, 0x8b, 0x01, 0x7b, 0xed, 0x13, + 0xd5, 0x8e, 0xbd, 0x8d, 0xb0, 0x7d, 0x1a, 0x1a, 0x31, 0xdc, 0x68, 0xfb, 0xdb, 0x66, 0x59, 0x91, 0xa8, 0x49, 0xb3, + 0x29, 0x0a, 0x9b, 0x08, 0x33, 0x77, 0x6c, 0xfe, 0xd6, 0xd7, 0xc3, 0x49, 0x4d, 0x6a, 0xb7, 0xbb, 0xad, 0xcc, 0xf1, + 0x0f, 0xc5, 0xe7, 0x9c, 0x3d, 0xda, 0x64, 0x7a, 0xba, 0xeb, 0x3f, 0x32, 0x1b, 0xa1, 0xb0, 0x71, 0x68, 0xd4, 0x7a, + 0xdf, 0xfb, 0x00, 0x81, 0x1d, 0xd9, 0x34, 0x71, 0x62, 0x59, 0xe7, 0xc9, 0x33, 0x52, 0x8f, 0x5c, 0x05, 0x6c, 0xeb, + 0xce, 0xc2, 0x6f, 0x79, 0x12, 0x76, 0x35, 0x4c, 0xdd, 0x09, 0x4d, 0x17, 0x10, 0x33, 0x15, 0x34, 0x41, 0xe1, 0x1f, + 0x8f, 0x36, 0xcd, 0x93, 0xac, 0xde, 0xf7, 0x3e, 0xc3, 0xdf, 0x59, 0x0a, 0x7f, 0xab, 0xfa, 0x0f, 0xba, 0xb9, 0xe2, + 0xd5, 0x52, 0xa6, 0x51, 0xf0, 0xee, 0xe4, 0xf4, 0x43, 0xa0, 0xb1, 0xf8, 0xf1, 0x46, 0x6a, 0x6c, 0x10, 0xcc, 0x32, + 0x03, 0x9d, 0x5c, 0x2e, 0x2f, 0x11, 0x8e, 0x52, 0xc7, 0x33, 0x38, 0x5d, 0xca, 0x9b, 0xe3, 0x3c, 0xf7, 0xaf, 0x4d, + 0xe6, 0xac, 0xd5, 0x37, 0x89, 0xc6, 0x89, 0x14, 0x82, 0xf4, 0x77, 0x94, 0x95, 0x67, 0x5a, 0x5f, 0x97, 0x9e, 0x9d, + 0xdf, 0x9d, 0x69, 0x99, 0xa0, 0xc5, 0x03, 0x7d, 0xfe, 0xc7, 0x61, 0x9a, 0x5d, 0xef, 0x21, 0x43, 0xc0, 0x02, 0x70, + 0xa6, 0xc8, 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, 0x8e, 0xfd, 0x71, 0x1d, 0x1c, + 0x41, 0x5b, 0xf7, 0x8e, 0xf3, 0xfc, 0x70, 0x5f, 0x7d, 0x71, 0x74, 0xb8, 0x9f, 0x66, 0xd7, 0x47, 0x5e, 0x68, 0x06, + 0xad, 0xb7, 0x60, 0x1a, 0x02, 0xcf, 0x5a, 0x7a, 0x94, 0xe8, 0x53, 0x9d, 0xf0, 0xd0, 0x31, 0x9f, 0x80, 0xf5, 0xa0, + 0xda, 0x1b, 0x26, 0x28, 0xce, 0xca, 0x81, 0xd5, 0xda, 0x6e, 0x43, 0x6b, 0x07, 0xb6, 0xf4, 0x40, 0x92, 0x50, 0xcc, + 0x8e, 0x59, 0x28, 0x22, 0x3d, 0x90, 0xd0, 0x40, 0x39, 0xe5, 0x84, 0x26, 0x35, 0x05, 0xf6, 0xe3, 0x4d, 0xbc, 0x02, + 0x89, 0xbf, 0xfe, 0xe9, 0x71, 0xa4, 0x09, 0x44, 0x71, 0xf5, 0x16, 0x3a, 0xf1, 0x64, 0x9e, 0x8a, 0xce, 0x6b, 0x9c, + 0x2e, 0x10, 0x56, 0x62, 0x3d, 0x4a, 0x0e, 0x19, 0xe6, 0x04, 0xa2, 0x08, 0x59, 0x70, 0x8c, 0xb8, 0x36, 0x71, 0x7b, + 0xcc, 0xb8, 0xcc, 0x1a, 0x33, 0x14, 0xb5, 0xe7, 0xcb, 0xa0, 0xb6, 0xf5, 0xca, 0xfb, 0xa6, 0x0c, 0x64, 0xe8, 0x61, + 0x45, 0x5b, 0x74, 0x09, 0xbc, 0x6a, 0x3c, 0xc1, 0x2d, 0xa7, 0xe1, 0xbc, 0xa4, 0x72, 0xe1, 0xf6, 0x72, 0xa9, 0x8e, + 0xe2, 0x48, 0xd6, 0x0e, 0x40, 0x55, 0xcd, 0xfa, 0xd1, 0xa3, 0x8d, 0xc0, 0xcd, 0x5f, 0xb2, 0xa3, 0xe6, 0x3a, 0xa8, + 0xe2, 0xf3, 0xe1, 0x92, 0x83, 0xa7, 0x57, 0xb0, 0xf7, 0x5f, 0xe9, 0x79, 0x6e, 0x27, 0x5b, 0xad, 0xf4, 0x65, 0x2c, + 0xd2, 0x9c, 0x7f, 0x88, 0xcf, 0x7f, 0xf8, 0x3f, 0xcd, 0x3d, 0xed, 0x76, 0xdb, 0x36, 0xb2, 0xff, 0xfb, 0x14, 0x0c, + 0x93, 0x4d, 0xc9, 0x84, 0xa4, 0x49, 0xca, 0xb2, 0x15, 0xc9, 0xb2, 0xdb, 0xe6, 0x63, 0x37, 0xbd, 0x6e, 0xd3, 0x93, + 0xb8, 0xb9, 0xbb, 0xeb, 0xfa, 0x58, 0x94, 0x04, 0x49, 0xdc, 0x50, 0xa4, 0x0e, 0x49, 0xf9, 0xa3, 0x0a, 0xf7, 0x59, + 0xf6, 0x11, 0xee, 0x33, 0xf4, 0xc9, 0xee, 0x99, 0x19, 0x80, 0x04, 0xbf, 0x24, 0x65, 0x93, 0x76, 0xf7, 0xb4, 0x49, + 0x44, 0x10, 0x00, 0x31, 0x03, 0x60, 0x30, 0x33, 0x98, 0x0f, 0xac, 0xf3, 0x62, 0x1c, 0x3c, 0x87, 0x0a, 0x99, 0x7a, + 0xfa, 0x68, 0x43, 0xe4, 0xad, 0x89, 0x25, 0xc8, 0x68, 0x09, 0x54, 0xbf, 0x03, 0x1b, 0xdb, 0xf3, 0x43, 0x16, 0x53, + 0x6b, 0x1c, 0x2c, 0x91, 0x24, 0x8a, 0x23, 0x59, 0x1e, 0x19, 0x4f, 0xb9, 0x01, 0x6b, 0x53, 0xe1, 0x7b, 0x0c, 0xc6, + 0x15, 0x89, 0xfd, 0x26, 0xaf, 0x4c, 0x79, 0xb0, 0x2f, 0xb1, 0xdd, 0xdb, 0xe8, 0x56, 0x8c, 0x94, 0x23, 0x80, 0x42, + 0xc4, 0x9d, 0x3d, 0x1f, 0x9d, 0xc8, 0x6a, 0x59, 0xd4, 0x5d, 0x51, 0xbf, 0xf0, 0x2b, 0x53, 0x15, 0x6e, 0x22, 0xaa, + 0x42, 0x86, 0x13, 0xf5, 0xf4, 0xe4, 0x40, 0xae, 0x7d, 0x3a, 0xea, 0x9f, 0x4b, 0xc0, 0x61, 0xaf, 0x80, 0x84, 0x72, + 0x59, 0x8d, 0x83, 0x81, 0x1c, 0x5c, 0x05, 0x8f, 0x43, 0xcb, 0x43, 0x50, 0xb9, 0x48, 0xef, 0xe7, 0x73, 0x44, 0xa6, + 0x4f, 0xa2, 0xb7, 0x11, 0xff, 0xb7, 0x80, 0x19, 0x55, 0x49, 0x2c, 0x4c, 0xa2, 0x58, 0x05, 0x38, 0xaa, 0x89, 0x49, + 0x14, 0x29, 0x01, 0x10, 0x42, 0xd4, 0x78, 0x22, 0x03, 0x46, 0x0e, 0xaa, 0x4d, 0x25, 0xc0, 0x46, 0x7a, 0xf1, 0x43, + 0xe1, 0xc0, 0x54, 0xa8, 0x52, 0x3e, 0xc0, 0xf6, 0x04, 0x32, 0x97, 0x6f, 0x7c, 0xe3, 0x7f, 0x23, 0x63, 0xee, 0x19, + 0x4b, 0xcf, 0x78, 0x17, 0x5e, 0x65, 0x8d, 0xb3, 0x93, 0x27, 0x27, 0x32, 0xd8, 0x40, 0x83, 0x10, 0x27, 0x5c, 0xf0, + 0xe4, 0xe2, 0x98, 0x6f, 0xf1, 0x4b, 0xd9, 0x0b, 0x2f, 0x9e, 0x33, 0x91, 0x13, 0x48, 0xbc, 0x4d, 0x39, 0x56, 0x74, + 0x09, 0x2d, 0x10, 0xff, 0xe7, 0x01, 0xb7, 0x5d, 0xf1, 0xad, 0x49, 0x1a, 0x07, 0xff, 0xc3, 0xee, 0x41, 0x1c, 0x48, + 0xd2, 0x68, 0x05, 0x42, 0xa1, 0x37, 0xe7, 0x4a, 0x3e, 0x43, 0x63, 0xfb, 0x7d, 0xee, 0xe3, 0x47, 0x66, 0xe1, 0x92, + 0x04, 0x7e, 0xc1, 0x4a, 0xa3, 0xf9, 0x3c, 0x60, 0x9a, 0x2a, 0xb2, 0xd4, 0xa8, 0x46, 0xfe, 0x99, 0xb3, 0x07, 0xb6, + 0x08, 0x0d, 0xab, 0x67, 0x6d, 0x3b, 0x47, 0x40, 0xcc, 0xf2, 0xd8, 0x89, 0x24, 0x23, 0xe1, 0x25, 0xc0, 0x0d, 0xde, + 0xa3, 0xf1, 0x79, 0x29, 0x76, 0xa6, 0x39, 0x8d, 0xd6, 0xe3, 0x80, 0x99, 0xb8, 0xdc, 0xe1, 0x93, 0x9b, 0xf1, 0x7a, + 0x3c, 0x86, 0x74, 0x40, 0x0f, 0x6c, 0x03, 0x02, 0x1c, 0x45, 0x09, 0x2a, 0x1e, 0x32, 0x7d, 0x00, 0x40, 0x59, 0x69, + 0x75, 0xf8, 0x60, 0x94, 0x04, 0x3a, 0x45, 0xfa, 0x40, 0x0a, 0x4a, 0x86, 0xfa, 0xa6, 0x1d, 0xaa, 0xef, 0x60, 0xf1, + 0x25, 0xea, 0xa0, 0x81, 0x73, 0x18, 0x5e, 0xaa, 0xef, 0x10, 0xc3, 0x98, 0x24, 0xfb, 0x39, 0xad, 0x5d, 0xd5, 0x50, + 0xc9, 0xb6, 0x62, 0x8d, 0xe9, 0x32, 0xe0, 0x6e, 0xe1, 0x85, 0xef, 0xcd, 0xc3, 0x28, 0x49, 0xfd, 0x89, 0x7a, 0x35, + 0x78, 0xed, 0x6b, 0x97, 0xcb, 0x54, 0xd3, 0xaf, 0x8c, 0x3f, 0xcb, 0x89, 0x76, 0x04, 0x29, 0xc4, 0x3c, 0x3b, 0x2d, + 0x75, 0xe4, 0xdd, 0xb3, 0xad, 0x9e, 0x20, 0xb9, 0x58, 0xe7, 0xcf, 0x43, 0xa8, 0x55, 0x49, 0xd9, 0x83, 0xb9, 0xc7, + 0x20, 0x65, 0xcf, 0x9f, 0xf5, 0x01, 0x09, 0xc3, 0xcf, 0xd7, 0x1b, 0x3c, 0xfa, 0xd3, 0xe2, 0x74, 0xc5, 0x28, 0xd3, + 0xc2, 0x35, 0x8b, 0x9e, 0x1f, 0xc8, 0x66, 0xc5, 0xa5, 0x73, 0x7a, 0xf4, 0x6d, 0x99, 0x8f, 0x80, 0xf3, 0x1e, 0x6c, + 0x7a, 0xc2, 0x28, 0x55, 0x20, 0x74, 0x12, 0x7c, 0x70, 0x54, 0x35, 0x43, 0xe4, 0xbd, 0x6a, 0x7a, 0xc6, 0xa9, 0xc0, + 0x77, 0x78, 0x58, 0x6a, 0x3c, 0x80, 0x5e, 0x29, 0x46, 0x0a, 0xdd, 0x94, 0x87, 0x30, 0x73, 0x25, 0xee, 0x5f, 0xa2, + 0xe9, 0x3b, 0xcf, 0x6a, 0x4d, 0xc8, 0x40, 0x22, 0x6f, 0xa4, 0xc6, 0x45, 0x59, 0xc1, 0x18, 0x55, 0x36, 0x13, 0x9a, + 0x16, 0x09, 0x9e, 0x27, 0x05, 0x4b, 0x44, 0xa4, 0xf1, 0x40, 0x8b, 0xf8, 0xb1, 0x3e, 0xca, 0xae, 0x45, 0x72, 0x6e, + 0x91, 0x1a, 0xdb, 0x88, 0xe4, 0xbc, 0x4b, 0x7e, 0xb8, 0x5a, 0xa7, 0x18, 0xcc, 0x19, 0x06, 0xc0, 0x32, 0x55, 0x41, + 0x3e, 0x18, 0xc8, 0x73, 0xc1, 0xd2, 0x67, 0xaa, 0xe2, 0x4f, 0xeb, 0x65, 0x5c, 0x40, 0x01, 0xaa, 0x85, 0x84, 0x1d, + 0x55, 0xa1, 0xf0, 0x18, 0x73, 0x30, 0x26, 0x46, 0x91, 0x09, 0x41, 0x9b, 0xe0, 0x95, 0x61, 0x03, 0x49, 0x98, 0x50, + 0x3f, 0x03, 0x2d, 0x68, 0x04, 0x16, 0x02, 0xbc, 0x96, 0xc0, 0x1c, 0x3d, 0xda, 0x84, 0xd9, 0xd9, 0xa3, 0x4d, 0x92, + 0x0d, 0x1f, 0x6d, 0xbc, 0xdc, 0x1a, 0x45, 0xbd, 0x50, 0xc9, 0x14, 0x65, 0x84, 0x68, 0x18, 0x65, 0xd7, 0x85, 0x6f, + 0x58, 0x01, 0x2f, 0x2c, 0x32, 0x2a, 0x57, 0xd0, 0x38, 0x64, 0xc8, 0x4d, 0x40, 0x56, 0xb1, 0xbf, 0xf4, 0xe2, 0x7b, + 0xb2, 0x18, 0x31, 0x64, 0xb3, 0x12, 0x5d, 0x55, 0x88, 0xc2, 0x13, 0x02, 0x88, 0xd8, 0xab, 0xca, 0x37, 0x79, 0x99, + 0xd0, 0x4d, 0xe4, 0xd7, 0xe6, 0xf0, 0xad, 0x6b, 0xf5, 0x29, 0xb3, 0xa6, 0x2c, 0xf5, 0xfc, 0x80, 0x9a, 0x0c, 0xb4, + 0xa4, 0x05, 0xbc, 0xa4, 0x0c, 0x5e, 0x58, 0x5e, 0x3f, 0x08, 0x0c, 0xd1, 0x7e, 0x1a, 0x37, 0x42, 0x86, 0x79, 0xd2, + 0x9a, 0x67, 0x94, 0xde, 0xfd, 0xa1, 0xd3, 0xc1, 0x60, 0x3a, 0x42, 0x98, 0x0e, 0x16, 0x4e, 0xa2, 0x29, 0xfb, 0xf9, + 0xed, 0xeb, 0x3c, 0x31, 0x1b, 0xe8, 0x18, 0x47, 0x7c, 0x61, 0x26, 0xc8, 0x38, 0xc4, 0xc8, 0x34, 0x50, 0x0a, 0x35, + 0x25, 0x5f, 0x42, 0x71, 0xa6, 0x2a, 0x67, 0x34, 0x76, 0x36, 0xa5, 0x51, 0x0f, 0x23, 0x6c, 0x15, 0x67, 0x27, 0x07, + 0x54, 0x9b, 0x8e, 0x39, 0xaa, 0x04, 0x68, 0x88, 0x01, 0xc2, 0x02, 0x0b, 0x90, 0x43, 0x76, 0xe8, 0x14, 0x02, 0x88, + 0xb5, 0xc4, 0x9b, 0x1c, 0xe7, 0xac, 0xcc, 0xa3, 0x60, 0x2b, 0xf5, 0xf4, 0x04, 0xb3, 0xc2, 0xc1, 0x41, 0x0d, 0x71, + 0x64, 0x4e, 0x0e, 0xe8, 0x51, 0xa9, 0xec, 0x88, 0xa2, 0x13, 0x21, 0x86, 0xf7, 0x79, 0x07, 0x9f, 0xb4, 0x55, 0x92, + 0x94, 0xad, 0xa0, 0xd4, 0xcb, 0x54, 0x65, 0xc9, 0x79, 0x22, 0x1e, 0xb0, 0x0a, 0xa2, 0x59, 0xd8, 0xb0, 0x77, 0x55, + 0x65, 0xe9, 0xdd, 0x21, 0xe4, 0xe2, 0x8d, 0x77, 0xa7, 0x39, 0xfc, 0x55, 0xb1, 0xd7, 0x92, 0xf2, 0x5e, 0x9b, 0xf0, + 0xc9, 0x05, 0x57, 0x15, 0xc1, 0x0b, 0x6b, 0x0b, 0x34, 0x01, 0x68, 0x98, 0xdc, 0x85, 0x98, 0xdc, 0x69, 0xcb, 0xe4, + 0x4e, 0xb7, 0x4c, 0x6e, 0xc0, 0x27, 0x52, 0xc9, 0x51, 0x17, 0xa3, 0xfb, 0x61, 0x8e, 0x3c, 0xce, 0x61, 0xf4, 0xf9, + 0x3e, 0x43, 0x3c, 0x99, 0x49, 0x00, 0xe6, 0x77, 0x2d, 0xb8, 0x6a, 0xc2, 0x8b, 0x84, 0x88, 0x3a, 0xe0, 0xf9, 0xae, + 0x13, 0x70, 0x43, 0x96, 0x57, 0x2d, 0xa8, 0xc2, 0x0b, 0xab, 0x94, 0x32, 0xd8, 0x6b, 0x8b, 0x16, 0x48, 0x17, 0x5b, + 0x20, 0x9d, 0x94, 0xb6, 0x2e, 0x07, 0x9b, 0x36, 0xa1, 0x0c, 0x14, 0xac, 0x41, 0x30, 0x49, 0xc6, 0x25, 0x53, 0x5e, + 0x87, 0xed, 0x34, 0x56, 0x5a, 0x51, 0x2b, 0x2f, 0x49, 0x6e, 0xa3, 0x18, 0xee, 0xf4, 0xa0, 0x9b, 0x4f, 0x5b, 0x52, + 0x4b, 0x3f, 0xe4, 0xe1, 0x82, 0x5a, 0x17, 0x53, 0xf1, 0x5e, 0x5e, 0x52, 0x6e, 0xb7, 0x4b, 0x35, 0x56, 0x5e, 0x9a, + 0xb2, 0x18, 0x91, 0xee, 0x41, 0x5c, 0xf9, 0xff, 0x92, 0x65, 0xd6, 0x40, 0x43, 0x02, 0x89, 0xaa, 0x23, 0x85, 0x5e, + 0x01, 0x53, 0x15, 0x8b, 0x83, 0x58, 0x0a, 0x3d, 0x18, 0xe7, 0x88, 0xff, 0x11, 0xb7, 0xab, 0x16, 0x4b, 0xce, 0x71, + 0xce, 0x91, 0x6e, 0xad, 0xbc, 0xe9, 0x3b, 0xb8, 0x3a, 0xd6, 0x5c, 0x03, 0xcc, 0xc0, 0xe5, 0x40, 0x83, 0x31, 0x71, + 0x79, 0x93, 0x82, 0x48, 0x22, 0x95, 0xe4, 0x46, 0x76, 0xe0, 0x9f, 0xeb, 0x99, 0xb3, 0xab, 0x8d, 0x9b, 0x1d, 0xcc, + 0x7d, 0xbd, 0x46, 0x35, 0x81, 0xb4, 0x05, 0xc3, 0xd3, 0x5c, 0x13, 0x1b, 0x18, 0xce, 0x91, 0x0e, 0x77, 0x0b, 0x97, + 0x90, 0x31, 0xd7, 0x16, 0xf2, 0xef, 0x28, 0x86, 0x53, 0xeb, 0xd2, 0xbe, 0xca, 0x1e, 0xcf, 0xf1, 0x97, 0x73, 0x95, + 0x3d, 0x1e, 0xe3, 0x2f, 0xf7, 0x0a, 0x73, 0x23, 0x36, 0x08, 0xfe, 0x12, 0xcc, 0xea, 0x69, 0x69, 0x3d, 0x91, 0x85, + 0xe3, 0x27, 0x2c, 0x1b, 0x3e, 0xc1, 0x0f, 0x1f, 0x6d, 0x12, 0xf0, 0xe9, 0x95, 0x61, 0x08, 0xad, 0x58, 0xcf, 0x1a, + 0xcb, 0xe7, 0x2d, 0xe5, 0x63, 0xfd, 0x0f, 0x3e, 0xf8, 0x71, 0x95, 0x44, 0xc5, 0x99, 0x52, 0x56, 0x5b, 0x5c, 0x8f, + 0xfd, 0xd0, 0x8b, 0xef, 0xaf, 0x49, 0xae, 0xd0, 0x04, 0xd3, 0x9e, 0xab, 0x63, 0x88, 0xbb, 0x2c, 0x5f, 0xa8, 0xa6, + 0xd2, 0x65, 0xc1, 0x3d, 0x3f, 0xe8, 0x87, 0x7f, 0x8d, 0x25, 0xb6, 0xad, 0x24, 0x79, 0xf2, 0x09, 0x29, 0x7d, 0xe8, + 0xfa, 0xd1, 0x46, 0x63, 0xf5, 0x6e, 0x2a, 0xd0, 0x56, 0xf8, 0x42, 0x98, 0x1e, 0x94, 0x62, 0x97, 0x53, 0xbf, 0x8f, + 0x37, 0xa6, 0xe3, 0xe8, 0xce, 0x7c, 0xb4, 0x49, 0xcf, 0xd4, 0xa5, 0x17, 0x7f, 0x60, 0x53, 0x73, 0xe2, 0xc7, 0x93, + 0x80, 0xa9, 0x7d, 0x75, 0x1c, 0x78, 0xe1, 0x07, 0xfe, 0x68, 0x46, 0xeb, 0x14, 0x6d, 0x20, 0x76, 0x0a, 0xbd, 0x02, + 0x27, 0xa4, 0x5e, 0x45, 0x66, 0xb5, 0x01, 0x0b, 0xca, 0xf3, 0x5c, 0x41, 0x56, 0x30, 0x8a, 0x45, 0x2d, 0x03, 0x4c, + 0x78, 0xc1, 0x2c, 0x03, 0x7c, 0xa2, 0x0d, 0x15, 0xe7, 0x4b, 0x35, 0x64, 0x50, 0x49, 0xb1, 0x9c, 0x27, 0xf5, 0xbc, + 0xc6, 0x1e, 0xfe, 0xfd, 0xcf, 0x51, 0xba, 0xf5, 0xfd, 0x3f, 0x97, 0xf7, 0xf2, 0x79, 0x10, 0x42, 0xa9, 0x49, 0xbe, + 0x38, 0x9f, 0xf0, 0x71, 0xce, 0x60, 0xb6, 0x7f, 0x5a, 0x6e, 0xec, 0x25, 0xc9, 0x7a, 0xc9, 0xa6, 0x74, 0xf7, 0x7c, + 0x56, 0x0c, 0xaa, 0x2c, 0x59, 0xc8, 0x03, 0xfb, 0x65, 0xed, 0x1e, 0x1f, 0x3e, 0x07, 0x9b, 0x18, 0x60, 0x28, 0xa3, + 0xd9, 0x4c, 0x2d, 0x84, 0xfb, 0x1d, 0xcd, 0x9c, 0xc3, 0x5f, 0xd6, 0xaf, 0x5e, 0xda, 0xaf, 0xf2, 0xc6, 0x21, 0x30, + 0xc6, 0xe2, 0x82, 0x9f, 0xf3, 0xc5, 0xd2, 0x78, 0x05, 0x44, 0x33, 0x2f, 0x6c, 0x07, 0xe7, 0xb2, 0xb4, 0xc4, 0x57, + 0x8c, 0x4d, 0x81, 0xe1, 0x36, 0x6a, 0xa5, 0xd7, 0x01, 0xbb, 0x61, 0xb9, 0xf1, 0x40, 0xfd, 0x63, 0x0d, 0x2d, 0x30, + 0xba, 0x21, 0x37, 0x4a, 0xe0, 0x5c, 0x9d, 0x04, 0xd2, 0x08, 0x61, 0xe0, 0x90, 0xcb, 0x5b, 0xac, 0xb2, 0xa5, 0x46, + 0x86, 0x2a, 0x0d, 0xa0, 0x75, 0x64, 0x67, 0x2d, 0xe5, 0x7d, 0x4c, 0x6d, 0xde, 0x3c, 0x36, 0xc3, 0xd1, 0xfb, 0x10, + 0x0d, 0x9e, 0xe3, 0x29, 0x80, 0x9d, 0xa7, 0x15, 0x7a, 0x90, 0x36, 0x8c, 0x35, 0x69, 0xc7, 0x54, 0x52, 0xbb, 0x08, + 0x7b, 0x5a, 0x34, 0x2c, 0x17, 0x0a, 0xa8, 0xc6, 0xb9, 0x51, 0xca, 0x90, 0x8f, 0x31, 0x65, 0x70, 0xc8, 0x92, 0xa4, + 0x15, 0x61, 0xf9, 0xa4, 0x1b, 0x6a, 0x51, 0xbb, 0x8c, 0x8f, 0xa2, 0xdc, 0xb0, 0x0d, 0x60, 0x09, 0x10, 0xc0, 0xea, + 0xb7, 0xf0, 0x78, 0xb9, 0x5e, 0x72, 0x8b, 0xa8, 0x78, 0x3e, 0x56, 0xb9, 0xb5, 0x4a, 0xdb, 0xfb, 0x5b, 0x95, 0x0f, + 0xaa, 0x74, 0x4c, 0x37, 0x0e, 0x4d, 0x2b, 0x91, 0xde, 0x9a, 0x9e, 0x08, 0x3b, 0x10, 0x63, 0xaa, 0xd0, 0x57, 0x36, + 0x9b, 0xb1, 0x49, 0x9a, 0xe8, 0x42, 0x6b, 0x94, 0xc7, 0x27, 0x06, 0xbf, 0xb4, 0x07, 0x43, 0xf5, 0x47, 0x88, 0xd2, + 0x20, 0xc2, 0x78, 0xf1, 0x01, 0x09, 0x99, 0xa9, 0x19, 0x4d, 0xd4, 0x63, 0x19, 0x45, 0xfc, 0x2b, 0xa0, 0x38, 0x6e, + 0x28, 0xc7, 0xa1, 0xf1, 0xf3, 0xa7, 0x58, 0x17, 0x51, 0x6e, 0x37, 0xb5, 0x9d, 0x14, 0x6d, 0xdb, 0xbe, 0x1b, 0xe7, + 0x55, 0xd7, 0xb1, 0x33, 0xd5, 0x00, 0xef, 0xc0, 0x0f, 0xfb, 0x6e, 0x7a, 0x6c, 0xd5, 0x81, 0x56, 0xeb, 0xf0, 0x53, + 0xda, 0xb9, 0xce, 0x33, 0x47, 0x35, 0xc8, 0x28, 0x53, 0xa2, 0x6d, 0x93, 0xe8, 0x86, 0xc5, 0x9f, 0x0d, 0x4a, 0xb9, + 0xf3, 0xfd, 0xc6, 0x73, 0xe4, 0xd8, 0x40, 0x84, 0xd3, 0x68, 0xf5, 0x09, 0x20, 0x74, 0x54, 0x43, 0x9d, 0x04, 0x51, + 0xc2, 0x64, 0x18, 0x48, 0x09, 0xf2, 0x99, 0x40, 0xfc, 0xf4, 0xf6, 0xe5, 0xbb, 0x77, 0xaa, 0x81, 0xb9, 0x66, 0x13, + 0xb9, 0x77, 0xbe, 0xa0, 0x76, 0x50, 0xff, 0xc6, 0x75, 0x47, 0x27, 0x0c, 0x09, 0xb5, 0xe5, 0x35, 0x47, 0x65, 0xb5, + 0x25, 0xc7, 0x4f, 0x1e, 0xfe, 0x65, 0x92, 0x44, 0xf7, 0x82, 0xab, 0x81, 0x36, 0x6c, 0x3f, 0xde, 0x4a, 0x25, 0x4b, + 0x3f, 0xbc, 0x6e, 0x28, 0xf5, 0xee, 0x1a, 0x4a, 0x41, 0x94, 0xab, 0xd1, 0xaa, 0x75, 0xb4, 0x94, 0x58, 0x03, 0x48, + 0x15, 0xbe, 0x0b, 0x5d, 0x92, 0x3c, 0xf5, 0x19, 0x83, 0xe6, 0xb9, 0x02, 0xaa, 0xa3, 0x6e, 0x28, 0xe6, 0x42, 0x50, + 0x8e, 0xdb, 0x49, 0x00, 0x26, 0xa5, 0x4c, 0xbe, 0xc5, 0x2b, 0xb3, 0x8d, 0xdc, 0x20, 0x7c, 0x58, 0xe1, 0xd0, 0xa9, + 0x19, 0xdd, 0x7c, 0x70, 0xfa, 0xbe, 0xf2, 0xa6, 0x60, 0xa7, 0x69, 0x8e, 0xa3, 0x34, 0x8d, 0x96, 0x7d, 0xc7, 0x5e, + 0xdd, 0xa9, 0xca, 0x40, 0x28, 0x1e, 0xb8, 0x19, 0x69, 0xff, 0xb7, 0x7f, 0x55, 0x48, 0x2e, 0x95, 0x5f, 0xa7, 0x6c, + 0xb9, 0x62, 0xb1, 0x97, 0xae, 0x63, 0x96, 0x29, 0xbf, 0xfd, 0xdf, 0xf3, 0x8a, 0x90, 0x3d, 0x90, 0xdb, 0x10, 0x7b, + 0x2d, 0x37, 0xb9, 0x0e, 0xa2, 0xdb, 0x07, 0x85, 0xc3, 0xc8, 0x8e, 0xca, 0x0b, 0x7f, 0xbe, 0xc8, 0x6b, 0x9f, 0xa5, + 0x5b, 0x60, 0x13, 0xa3, 0x27, 0x6d, 0xbb, 0x72, 0x1e, 0xdd, 0xf6, 0x7f, 0xfb, 0x57, 0xae, 0x3c, 0xd9, 0xb9, 0xea, + 0x9a, 0x07, 0x5a, 0x9e, 0xd1, 0xe6, 0x3a, 0xb5, 0x29, 0x86, 0xf7, 0xb5, 0x09, 0xae, 0x15, 0xd2, 0xaa, 0xac, 0x5f, + 0x6d, 0x6d, 0x81, 0xe9, 0x2f, 0xfe, 0x7c, 0xf1, 0xb9, 0x40, 0x01, 0x42, 0x77, 0x42, 0x05, 0x95, 0xbe, 0x00, 0x58, + 0xa3, 0xfe, 0xfe, 0x13, 0xf6, 0x99, 0x70, 0xed, 0x02, 0xe9, 0x4b, 0x40, 0xc3, 0xb5, 0xa8, 0xcf, 0x47, 0xa3, 0x3c, + 0xd7, 0xa2, 0xdc, 0x1e, 0x5c, 0x5e, 0xce, 0x6a, 0x25, 0xfc, 0xa8, 0xef, 0xdb, 0x3a, 0xc5, 0xa2, 0xd8, 0x03, 0x21, + 0x68, 0xbc, 0xd9, 0x80, 0x8e, 0x76, 0x7a, 0x4d, 0x3e, 0x18, 0xb5, 0x6f, 0xd7, 0x88, 0x35, 0x94, 0x62, 0x9e, 0xbe, + 0xfc, 0x4e, 0xce, 0x68, 0x1e, 0xce, 0x6d, 0xec, 0xad, 0x48, 0x61, 0xaf, 0xe0, 0x7d, 0x04, 0x28, 0x40, 0x84, 0x44, + 0x8b, 0x69, 0x80, 0xde, 0xb4, 0x99, 0x4e, 0xfe, 0xb4, 0xdb, 0x74, 0xf2, 0x62, 0x2f, 0xd3, 0xc9, 0x9f, 0xbe, 0xb8, + 0xe9, 0xe4, 0x1b, 0xd9, 0x74, 0x12, 0xe6, 0xf2, 0x25, 0xdb, 0xcb, 0xa0, 0x51, 0x98, 0x05, 0x45, 0xb7, 0xc9, 0xd0, + 0xe1, 0x7c, 0x78, 0x32, 0x59, 0x30, 0x50, 0x6c, 0x70, 0xac, 0x07, 0xd1, 0x7c, 0xbb, 0xdd, 0xe1, 0x97, 0xb2, 0x3a, + 0x0c, 0xa2, 0xb9, 0x2a, 0x05, 0x42, 0x0e, 0x79, 0x20, 0xe4, 0x22, 0xb8, 0x19, 0x59, 0xf8, 0xd9, 0x86, 0x08, 0x85, + 0x66, 0x1e, 0xea, 0x52, 0xb2, 0xf7, 0xdc, 0xa8, 0xd3, 0x15, 0x36, 0x80, 0x7d, 0x15, 0xc2, 0xa2, 0xe4, 0x0d, 0xdd, + 0xa7, 0x22, 0xe4, 0x8b, 0xdc, 0x43, 0x6e, 0x3c, 0x4f, 0xe1, 0x53, 0x36, 0xea, 0x2f, 0x77, 0xce, 0x77, 0x97, 0xce, + 0xa0, 0xe3, 0x40, 0xcc, 0x02, 0x10, 0x8b, 0xb1, 0xc0, 0x1e, 0x74, 0x3a, 0x50, 0x70, 0x2b, 0x15, 0xb8, 0x50, 0xe0, + 0x4b, 0x05, 0x5d, 0x28, 0x98, 0x48, 0x05, 0x47, 0x50, 0x30, 0x95, 0x0a, 0x8e, 0xa1, 0xe0, 0x46, 0xcd, 0x2e, 0xc3, + 0x7c, 0xb8, 0xc7, 0xfa, 0x95, 0x41, 0x92, 0x90, 0x28, 0x3b, 0x36, 0x1c, 0xb0, 0xe3, 0xf3, 0xe6, 0xfd, 0xc8, 0x20, + 0x95, 0x68, 0x3f, 0x36, 0x6e, 0x17, 0x8c, 0xe2, 0xa7, 0xbf, 0xc0, 0x83, 0xd2, 0x4a, 0x23, 0x70, 0x27, 0x10, 0x71, + 0x49, 0x04, 0x1e, 0x14, 0x55, 0x07, 0x2d, 0xd7, 0x20, 0x9f, 0xb9, 0xb2, 0x01, 0x20, 0xce, 0x65, 0xf1, 0x8e, 0x3e, + 0x67, 0xe6, 0x4b, 0xa0, 0x30, 0xab, 0xd1, 0x64, 0x55, 0xea, 0x97, 0x30, 0x82, 0x78, 0xc1, 0xc6, 0xeb, 0xb9, 0x72, + 0x1e, 0xcd, 0x77, 0x1a, 0x3c, 0xc8, 0xaf, 0x60, 0x94, 0x2a, 0xdd, 0x19, 0x99, 0x62, 0x59, 0xf2, 0x6f, 0xd1, 0x63, + 0x56, 0xae, 0x9f, 0xc2, 0xd8, 0x94, 0x94, 0x28, 0x0e, 0x7c, 0x07, 0x70, 0x24, 0x59, 0x1c, 0x9c, 0x03, 0x9e, 0xa5, + 0xe7, 0x0b, 0x4f, 0x1a, 0xcf, 0xe9, 0x0f, 0x2c, 0x49, 0xbc, 0xb9, 0xa8, 0x5f, 0x1f, 0x27, 0x58, 0x26, 0xe5, 0x42, + 0x23, 0x22, 0x10, 0xd4, 0x8f, 0x7e, 0xcd, 0x50, 0x24, 0x8e, 0x6e, 0x15, 0x30, 0x71, 0x82, 0x05, 0x55, 0x58, 0x55, + 0xf8, 0x16, 0x4c, 0x61, 0xd9, 0xfe, 0x01, 0x36, 0xff, 0x0d, 0x0b, 0xaa, 0x85, 0xa9, 0x37, 0xaf, 0x16, 0xd1, 0x3a, + 0xc8, 0xe4, 0xb1, 0xe5, 0xe6, 0x07, 0xa5, 0xc2, 0xcf, 0xb9, 0x4f, 0x0f, 0xa2, 0xf9, 0xef, 0x7a, 0x99, 0xbe, 0xc5, + 0x08, 0xe2, 0x5d, 0x68, 0x84, 0xe9, 0xc8, 0x42, 0x1c, 0x2b, 0x16, 0xa0, 0xb0, 0x1f, 0xa6, 0x0b, 0x13, 0x3d, 0x2e, + 0x35, 0x37, 0xd4, 0x0d, 0x0b, 0xe7, 0x76, 0x53, 0xf5, 0x33, 0xef, 0xc7, 0xf3, 0xb1, 0xa7, 0x39, 0xee, 0xb1, 0x21, + 0xfe, 0x58, 0x76, 0x57, 0xcf, 0xb0, 0x07, 0x65, 0xea, 0xdf, 0x6c, 0x66, 0x51, 0x98, 0x9a, 0x33, 0x6f, 0xe9, 0x07, + 0xf7, 0xfd, 0x65, 0x14, 0x46, 0xc9, 0xca, 0x9b, 0xb0, 0x41, 0xa1, 0x05, 0x18, 0x60, 0x04, 0x13, 0xee, 0x44, 0xeb, + 0x58, 0x6e, 0xcc, 0x96, 0xd4, 0x3a, 0x0f, 0x50, 0x32, 0x0b, 0xd8, 0x5d, 0xc6, 0x3f, 0x5f, 0xaa, 0x4c, 0x55, 0x71, + 0xc9, 0x51, 0x0b, 0x60, 0xa3, 0x79, 0xf4, 0x13, 0x88, 0xf9, 0x35, 0xe0, 0xbc, 0x68, 0xdf, 0x72, 0xbb, 0x31, 0x5b, + 0x2a, 0x56, 0xb7, 0xb5, 0xf3, 0x38, 0xba, 0x3d, 0x85, 0xd1, 0x62, 0x63, 0x33, 0x61, 0xc1, 0x0c, 0xdf, 0x98, 0xe8, + 0x70, 0x25, 0xfa, 0x31, 0x51, 0x7b, 0x00, 0xbd, 0xb1, 0xe5, 0x00, 0x5e, 0xf7, 0x5d, 0xc5, 0x1e, 0x2c, 0xfd, 0xd0, + 0x24, 0x70, 0x8e, 0xed, 0x95, 0xd4, 0x97, 0x8c, 0x3f, 0x7d, 0x83, 0xd5, 0x1d, 0xc5, 0x1e, 0x80, 0x84, 0x39, 0x0b, + 0xa2, 0xdb, 0xfe, 0xc2, 0x9f, 0x4e, 0x59, 0x38, 0xc0, 0x31, 0xe7, 0x85, 0x2c, 0x08, 0xfc, 0x55, 0xe2, 0x27, 0x83, + 0xa5, 0x77, 0xc7, 0x7b, 0x3d, 0x6c, 0xeb, 0xb5, 0xc3, 0x7b, 0xed, 0xec, 0xdd, 0xab, 0xd4, 0x0d, 0x38, 0x77, 0x51, + 0x3f, 0x7c, 0x68, 0x5d, 0xc5, 0xae, 0xc0, 0xb9, 0x77, 0xaf, 0xab, 0x98, 0x6d, 0x96, 0x5e, 0x3c, 0xf7, 0xc3, 0xbe, + 0x9d, 0x59, 0x37, 0x1b, 0x5a, 0x18, 0x0f, 0x7b, 0xbd, 0x5e, 0x66, 0x4d, 0xc5, 0x93, 0x3d, 0x9d, 0x66, 0xd6, 0x44, + 0x3c, 0xcd, 0x66, 0xb6, 0x3d, 0x9b, 0x65, 0x96, 0x2f, 0x0a, 0x3a, 0xee, 0x64, 0xda, 0x71, 0x33, 0xeb, 0x56, 0xaa, + 0x91, 0x59, 0x8c, 0x3f, 0xc5, 0x6c, 0x3a, 0xc0, 0x85, 0xc4, 0x8d, 0x37, 0x8f, 0x6d, 0x3b, 0x43, 0x0a, 0x70, 0x59, + 0xa2, 0x4d, 0xa8, 0xa0, 0xba, 0xda, 0xec, 0x5d, 0x53, 0x29, 0x3e, 0x37, 0x99, 0x34, 0xd6, 0x9b, 0x7a, 0xf1, 0x87, + 0x2b, 0x45, 0x82, 0xc2, 0xf3, 0xa8, 0xda, 0x46, 0xa0, 0xc1, 0xbc, 0xeb, 0x43, 0x24, 0xbb, 0xc1, 0x38, 0x8a, 0x61, + 0xcf, 0xc6, 0xde, 0xd4, 0x5f, 0x27, 0x7d, 0xc7, 0x5d, 0xdd, 0x89, 0x22, 0xbe, 0xd6, 0x8b, 0x02, 0xdc, 0x7b, 0xfd, + 0x24, 0x0a, 0xfc, 0xa9, 0x28, 0x6a, 0xdb, 0x4b, 0x8e, 0xab, 0x0f, 0x30, 0x8e, 0x83, 0x8f, 0xd1, 0x48, 0xbc, 0x20, + 0x50, 0xac, 0x4e, 0xa2, 0x30, 0x2f, 0x41, 0xa5, 0xb8, 0x62, 0x27, 0x84, 0x17, 0x8c, 0xd9, 0xe0, 0x1c, 0xae, 0xee, + 0xf2, 0x35, 0xef, 0x1c, 0xad, 0xee, 0xb2, 0x6f, 0x96, 0x6c, 0xea, 0x7b, 0x8a, 0x56, 0xac, 0x26, 0xc7, 0x06, 0xc5, + 0xb9, 0xbe, 0x69, 0x59, 0xa6, 0x62, 0x5b, 0x40, 0xc4, 0xcf, 0x07, 0xfe, 0x72, 0x15, 0xc5, 0xa9, 0x17, 0xa6, 0x59, + 0x36, 0xba, 0xca, 0xb2, 0xc1, 0x85, 0xaf, 0x5d, 0xfe, 0x4d, 0xa3, 0x73, 0x9a, 0x2e, 0x9a, 0x32, 0xfd, 0xca, 0x78, + 0xc9, 0x64, 0x33, 0x17, 0x38, 0xc6, 0xd0, 0xc4, 0x45, 0xae, 0x4c, 0xa7, 0x64, 0xbd, 0x32, 0x21, 0x39, 0xaf, 0x4e, + 0x56, 0x33, 0xe5, 0x2a, 0x78, 0x02, 0x41, 0x85, 0x97, 0x6c, 0x78, 0x21, 0xd9, 0xcc, 0x00, 0xb3, 0x82, 0x95, 0xc9, + 0xdd, 0xe6, 0x51, 0x1b, 0xcf, 0xf8, 0xed, 0x6e, 0x9e, 0xf1, 0xef, 0xe9, 0x3e, 0x3c, 0xe3, 0xb7, 0x5f, 0x9c, 0x67, + 0x7c, 0x54, 0x77, 0xb7, 0x79, 0x1d, 0x0d, 0xd5, 0xfc, 0x5a, 0x04, 0x8e, 0xa6, 0x98, 0x02, 0x59, 0xbd, 0x4e, 0xff, + 0x5d, 0xf7, 0x18, 0xd1, 0x1b, 0xa5, 0x66, 0xa4, 0x93, 0x1b, 0x94, 0xc8, 0x6f, 0xc2, 0xe1, 0x5f, 0x63, 0xf9, 0x79, + 0x36, 0x1b, 0xbe, 0x88, 0xa4, 0x82, 0xfc, 0x89, 0x5b, 0x8c, 0x94, 0x82, 0x8e, 0xd0, 0x1b, 0x61, 0x10, 0x8a, 0x69, + 0x59, 0x20, 0x66, 0x01, 0x99, 0xb5, 0x4f, 0x73, 0x5b, 0xb9, 0x41, 0x79, 0x08, 0x5a, 0x6e, 0x7d, 0x2a, 0x3c, 0xd3, + 0x6a, 0xfa, 0xcf, 0x39, 0x4b, 0xb9, 0x2b, 0xf9, 0x77, 0xf7, 0xaf, 0xa7, 0xda, 0xeb, 0x48, 0xcf, 0xfc, 0xe4, 0x4d, + 0xd5, 0x2f, 0x8c, 0x5f, 0x58, 0x0d, 0x65, 0x70, 0x32, 0x6e, 0xef, 0x26, 0xe7, 0x5d, 0x87, 0xd7, 0xd4, 0xfc, 0xac, + 0x04, 0x69, 0x5f, 0x6e, 0xc8, 0xf3, 0xbf, 0xd5, 0x0e, 0x63, 0xee, 0x84, 0xb3, 0xe1, 0x1c, 0x20, 0xa6, 0xb4, 0x43, + 0x77, 0xfa, 0x29, 0x35, 0xf7, 0xa7, 0x59, 0xa6, 0x0f, 0x04, 0x22, 0xa4, 0x83, 0x96, 0xed, 0x62, 0xe2, 0x92, 0x42, + 0x1e, 0xe3, 0xd7, 0x9a, 0x74, 0x67, 0xf9, 0x1a, 0xac, 0x00, 0xf8, 0x0d, 0x27, 0xc7, 0x99, 0xaa, 0x10, 0xfa, 0xc8, + 0x3a, 0x44, 0x02, 0x08, 0xae, 0xad, 0x73, 0xfc, 0x8b, 0x57, 0xa2, 0xa0, 0x6e, 0x71, 0x4a, 0xc8, 0x41, 0x33, 0x06, + 0x08, 0x7e, 0x21, 0x94, 0x35, 0x44, 0x76, 0x78, 0x1d, 0x7c, 0xc8, 0xd4, 0x9c, 0xf7, 0xc3, 0xe5, 0x77, 0x7a, 0x72, + 0x00, 0x0d, 0x4e, 0x2b, 0x8a, 0x98, 0x1d, 0xf6, 0x94, 0xc0, 0x4a, 0x24, 0xb7, 0x86, 0x95, 0xdc, 0x2a, 0x4f, 0x36, + 0x22, 0x70, 0x4c, 0xea, 0xad, 0x4c, 0x90, 0xfe, 0x91, 0xf6, 0x72, 0x8a, 0x27, 0xc5, 0xa8, 0x19, 0xac, 0x13, 0xa0, + 0x8d, 0x28, 0x88, 0x22, 0xfd, 0x19, 0x4c, 0xd6, 0x71, 0x12, 0xc5, 0xfd, 0x55, 0xe4, 0x87, 0x29, 0x8b, 0x33, 0x44, + 0xd5, 0x25, 0xe2, 0x47, 0xa0, 0xe7, 0x6a, 0x13, 0xad, 0xbc, 0x89, 0x9f, 0xde, 0xf7, 0x6d, 0xce, 0x52, 0xd8, 0x03, + 0xce, 0x1d, 0xd8, 0x8d, 0xf5, 0xfb, 0x1c, 0x9b, 0x4f, 0x91, 0xf1, 0x8b, 0xeb, 0xec, 0x8c, 0xbc, 0xcc, 0x07, 0xd2, + 0x5b, 0x0a, 0x9d, 0x03, 0xec, 0x87, 0x17, 0x9b, 0x73, 0xa0, 0xf2, 0x30, 0xd5, 0xf6, 0x94, 0xcd, 0x0d, 0xa4, 0xda, + 0x70, 0x99, 0x20, 0xfe, 0x58, 0x5d, 0x5d, 0xb1, 0x9b, 0x8b, 0x81, 0xe3, 0xd1, 0xf7, 0x19, 0x59, 0xdf, 0x83, 0x44, + 0x73, 0xc6, 0x3e, 0x35, 0xc7, 0x6c, 0x16, 0xc5, 0x8c, 0xc2, 0x2c, 0x3b, 0xbd, 0xd5, 0xdd, 0xfe, 0xdd, 0x6f, 0x07, + 0xbf, 0xb9, 0x9f, 0x30, 0x4a, 0x35, 0xd1, 0x99, 0xbe, 0xa3, 0xb7, 0xfa, 0x79, 0x06, 0xac, 0x21, 0x61, 0x7e, 0x42, + 0x11, 0xed, 0xfa, 0xaa, 0x3a, 0x68, 0x8c, 0x66, 0xb7, 0x8a, 0xf8, 0x99, 0x17, 0xb3, 0xc0, 0x4b, 0xfd, 0x1b, 0xc1, + 0x33, 0x76, 0x8e, 0x56, 0x77, 0x62, 0x8e, 0xf1, 0xc0, 0xfb, 0x84, 0x49, 0xaa, 0x0c, 0x45, 0x4c, 0x52, 0xb5, 0x18, + 0x27, 0x69, 0x50, 0x83, 0x46, 0x04, 0x78, 0xa9, 0x9c, 0xf4, 0xdd, 0xd5, 0x9d, 0x7c, 0x44, 0x17, 0xcd, 0xf2, 0x93, + 0xba, 0x1a, 0x99, 0x6f, 0xe9, 0x4f, 0xa7, 0x01, 0xcb, 0x4a, 0x13, 0x5d, 0x9e, 0x4b, 0x09, 0x39, 0x39, 0x1e, 0xbc, + 0x71, 0x12, 0x05, 0xeb, 0x94, 0x35, 0xa3, 0x8b, 0x90, 0xe3, 0xda, 0x05, 0x72, 0xf0, 0x77, 0x79, 0xac, 0x5d, 0x60, + 0xb7, 0x61, 0x99, 0xd8, 0x03, 0x08, 0xc4, 0x6d, 0x76, 0xca, 0x43, 0x87, 0x57, 0xf9, 0xa0, 0x8d, 0x06, 0x40, 0x0c, + 0x38, 0x96, 0x88, 0x7a, 0x2b, 0x96, 0xc3, 0xcb, 0xf2, 0x60, 0xc4, 0x79, 0x51, 0x56, 0x06, 0xe6, 0xf7, 0xd9, 0x63, + 0xcf, 0x9a, 0xf7, 0xd8, 0x33, 0xb1, 0xc7, 0xb6, 0xaf, 0xcc, 0x87, 0x33, 0x07, 0xfe, 0x1b, 0x14, 0x00, 0xf5, 0x6d, + 0xa5, 0xb3, 0xba, 0x53, 0x9c, 0xd5, 0x9d, 0x62, 0xba, 0xab, 0x3b, 0x05, 0xbb, 0x46, 0x23, 0x16, 0xc3, 0x72, 0x75, + 0xc3, 0x56, 0xa0, 0x10, 0xfe, 0xd8, 0xa5, 0x57, 0xce, 0x21, 0xbc, 0x83, 0x56, 0xdd, 0xfa, 0x3b, 0x77, 0xfb, 0x56, + 0xa7, 0xbd, 0x24, 0x88, 0xb6, 0x6e, 0xa5, 0xde, 0x78, 0xcc, 0xa6, 0xfd, 0x59, 0x34, 0x59, 0x27, 0xff, 0xe4, 0xe3, + 0xe7, 0x48, 0xdc, 0x4a, 0x08, 0x2a, 0xfd, 0x88, 0xa6, 0x70, 0xbb, 0x73, 0xc3, 0x44, 0x0f, 0x9b, 0x7c, 0x9e, 0xfa, + 0x14, 0x35, 0xdc, 0xb5, 0x0e, 0x1b, 0x16, 0x79, 0x33, 0xa2, 0x7f, 0xb7, 0x59, 0x6a, 0x27, 0x31, 0x9f, 0x81, 0x96, + 0xad, 0xe8, 0xf8, 0x74, 0x6c, 0xf0, 0xd9, 0xb4, 0x7b, 0xcd, 0xc3, 0xbd, 0x14, 0x5f, 0xba, 0x12, 0x87, 0x0a, 0x3f, + 0xb7, 0xb8, 0x8f, 0xcc, 0xf6, 0x5e, 0xdb, 0xd6, 0x48, 0xad, 0xd7, 0x2d, 0x07, 0x42, 0x51, 0x77, 0x4f, 0x2a, 0xff, + 0xf0, 0xd9, 0x21, 0xfc, 0x47, 0x5c, 0xfd, 0xdf, 0xd3, 0x26, 0x46, 0xfd, 0x75, 0x5a, 0x62, 0xd4, 0x89, 0x55, 0x42, + 0x46, 0x7c, 0xff, 0xfa, 0xb3, 0xd9, 0xa7, 0x35, 0xd8, 0xbb, 0x36, 0xd9, 0x7f, 0x55, 0x6b, 0x7f, 0x17, 0x45, 0x90, + 0xd1, 0xb6, 0x5e, 0x5d, 0xa0, 0x87, 0xcc, 0xf3, 0xd3, 0x21, 0x34, 0x12, 0x72, 0x04, 0x99, 0x1e, 0xa8, 0xd8, 0x86, + 0x44, 0x89, 0x97, 0x6d, 0xa2, 0xc4, 0x8b, 0xdd, 0xa2, 0xc4, 0xf7, 0x7b, 0x89, 0x12, 0x2f, 0xbe, 0xb8, 0x28, 0xf1, + 0xb2, 0x2e, 0x4a, 0x5c, 0x44, 0xc2, 0xe8, 0xd7, 0x78, 0xbd, 0xe6, 0x3f, 0xdf, 0xd3, 0x4d, 0xe2, 0x79, 0x34, 0xec, + 0xda, 0x14, 0x09, 0xfc, 0xe2, 0xdf, 0x16, 0x2c, 0x70, 0x21, 0xbe, 0x45, 0x1b, 0xb8, 0x42, 0xb4, 0xe0, 0x94, 0x1d, + 0xbf, 0x23, 0x15, 0x07, 0x51, 0x38, 0xff, 0x09, 0x6e, 0x92, 0x41, 0x1d, 0x18, 0x4b, 0x2f, 0xfc, 0xe4, 0xa7, 0x68, + 0xb5, 0x5e, 0xbd, 0x86, 0xbe, 0xde, 0xfb, 0x89, 0x3f, 0x0e, 0x58, 0xee, 0xa1, 0x4f, 0x36, 0x7b, 0x5c, 0x27, 0x0e, + 0x66, 0xb2, 0xe2, 0xa7, 0x77, 0x27, 0x7e, 0xa2, 0x21, 0x2d, 0xff, 0x4d, 0xc6, 0x80, 0x6a, 0xb3, 0x20, 0x02, 0xa1, + 0xac, 0x2a, 0x83, 0xfe, 0x74, 0x61, 0xe4, 0x22, 0xd2, 0x1b, 0xa0, 0x14, 0x46, 0x1a, 0xad, 0xfd, 0xb0, 0x9a, 0x50, + 0xb3, 0xd6, 0x8d, 0x3c, 0x32, 0x5d, 0x5d, 0x0d, 0xbf, 0x8c, 0xd6, 0x09, 0x9b, 0x46, 0xb7, 0xa1, 0x6a, 0x84, 0xb9, + 0x67, 0x04, 0x5c, 0xcb, 0xe6, 0x6d, 0x30, 0xa7, 0xea, 0x3b, 0x64, 0x94, 0xa3, 0x58, 0x53, 0x21, 0xa5, 0xef, 0x7a, + 0x65, 0xd2, 0xfd, 0xb8, 0x89, 0x20, 0xaa, 0x79, 0xf2, 0xaf, 0x07, 0x9a, 0x16, 0x0d, 0x3f, 0xad, 0xa5, 0xb0, 0x2f, + 0x89, 0x2c, 0xae, 0x15, 0x4e, 0xb4, 0x50, 0x28, 0x17, 0x45, 0x78, 0x98, 0x86, 0x89, 0xe3, 0x6f, 0xc8, 0x37, 0xba, + 0x78, 0x0b, 0xc1, 0x75, 0xb2, 0x35, 0x9f, 0x0f, 0x1e, 0x2c, 0x85, 0x1e, 0x9f, 0x4b, 0x68, 0x7c, 0x73, 0xc3, 0xe2, + 0xc0, 0xbb, 0xd7, 0xf4, 0x2c, 0x0a, 0x7f, 0x00, 0x04, 0xbc, 0x88, 0x6e, 0x43, 0xb9, 0x02, 0xe6, 0x30, 0x6a, 0x58, + 0x4b, 0x8d, 0x61, 0x7d, 0xc0, 0xd7, 0x46, 0x1a, 0x01, 0x64, 0x8f, 0x9e, 0xb3, 0xbf, 0x1a, 0xf4, 0xef, 0xdf, 0xf4, + 0xcc, 0x38, 0x8f, 0xf2, 0x0f, 0xfd, 0xbc, 0xda, 0xe3, 0x33, 0x8f, 0x1f, 0x3f, 0x68, 0x07, 0x5b, 0x83, 0x44, 0xda, + 0x22, 0x27, 0xb4, 0xd6, 0xd0, 0x5a, 0x6f, 0xdd, 0x05, 0x30, 0x8a, 0x8b, 0x68, 0x3d, 0x59, 0xa0, 0x75, 0xee, 0x97, + 0x83, 0x37, 0x85, 0x3e, 0x31, 0x79, 0x6f, 0x0e, 0x7a, 0xa5, 0xa8, 0xc0, 0x02, 0x7e, 0xff, 0x25, 0xc4, 0xa5, 0xfd, + 0x0f, 0xa2, 0xa1, 0xbe, 0x6a, 0x72, 0x5f, 0xdc, 0x4f, 0x5a, 0xbc, 0x03, 0xc8, 0x31, 0xcb, 0x23, 0xbe, 0x88, 0xcb, + 0xb5, 0x66, 0x22, 0x93, 0x55, 0x91, 0x26, 0x47, 0x57, 0x6c, 0x0b, 0x1c, 0x29, 0xbe, 0xc2, 0x2c, 0x12, 0xd3, 0xb9, + 0x77, 0x84, 0xc1, 0x38, 0xb5, 0xaa, 0x10, 0x19, 0x6e, 0xa7, 0xc1, 0x90, 0x7c, 0x55, 0xdf, 0x2d, 0xfd, 0xd0, 0xc0, + 0xe4, 0x08, 0xf5, 0x37, 0xde, 0x1d, 0x84, 0x07, 0x07, 0xe2, 0x56, 0x7d, 0x05, 0x85, 0x86, 0xec, 0xe5, 0x07, 0x19, + 0xd0, 0xd4, 0x46, 0x4c, 0x88, 0x5b, 0xbc, 0xd1, 0x57, 0x8a, 0xa2, 0x28, 0xb9, 0x18, 0xa1, 0xe4, 0x72, 0x04, 0x96, + 0xa3, 0x38, 0x00, 0xb7, 0x25, 0xd9, 0xea, 0x8e, 0x4a, 0x40, 0x32, 0xc0, 0x9b, 0x59, 0x51, 0xc0, 0x23, 0x60, 0x76, + 0x6d, 0x51, 0x20, 0x04, 0x7a, 0x88, 0x5e, 0xe8, 0xc5, 0x10, 0x28, 0xbb, 0xaf, 0xa0, 0xc0, 0x8e, 0x6f, 0xb9, 0x26, + 0x58, 0xb1, 0xe9, 0x71, 0x34, 0x60, 0xcd, 0xa1, 0x12, 0x43, 0x89, 0x0a, 0xc2, 0xad, 0x43, 0x25, 0xf2, 0xb9, 0xc1, + 0x1a, 0x68, 0x23, 0xca, 0x45, 0x77, 0xe9, 0x92, 0x85, 0x6b, 0x15, 0x53, 0xa5, 0x61, 0xe8, 0x4a, 0xa8, 0xf3, 0x82, + 0x98, 0x2d, 0xa0, 0x36, 0xcd, 0x2d, 0x17, 0x74, 0x16, 0x26, 0x9c, 0xa4, 0x7a, 0xc6, 0x84, 0x5f, 0x6c, 0x26, 0x9c, + 0xb6, 0x55, 0x4f, 0x08, 0x3e, 0xa5, 0x51, 0xd5, 0xfb, 0x8c, 0xcc, 0xb7, 0x31, 0x2e, 0x0b, 0x2a, 0x8d, 0xb8, 0xba, + 0x48, 0xa0, 0x5d, 0xf3, 0xaa, 0x93, 0x96, 0xdf, 0xc8, 0x78, 0x15, 0x45, 0x51, 0xac, 0xd7, 0xbb, 0xe1, 0xe3, 0x84, + 0x78, 0x5d, 0xad, 0xfd, 0x4c, 0x6a, 0xfd, 0xb4, 0x00, 0xfd, 0x81, 0xdd, 0xd3, 0x41, 0x42, 0xa8, 0xfa, 0xc0, 0xee, + 0xc1, 0x60, 0xf1, 0x25, 0x68, 0x53, 0xd4, 0x2d, 0xe4, 0xda, 0x80, 0x0c, 0x18, 0x13, 0x88, 0xe1, 0xb6, 0x65, 0x03, + 0xd9, 0xd9, 0x16, 0x2a, 0x8e, 0x28, 0x86, 0x64, 0xe7, 0x62, 0x13, 0x73, 0xbf, 0x04, 0xad, 0x11, 0xc7, 0x66, 0xc3, + 0xd6, 0xd0, 0x9f, 0x38, 0xb6, 0x7d, 0x50, 0xab, 0x0f, 0x8a, 0xec, 0xa6, 0xda, 0xba, 0x91, 0x0e, 0x1d, 0xdb, 0xf4, + 0x9f, 0x58, 0xee, 0xa0, 0x76, 0x46, 0x4b, 0x21, 0x56, 0x47, 0xa8, 0xfe, 0x3a, 0x7d, 0xb4, 0xd1, 0x6a, 0x1b, 0x52, + 0xaf, 0xda, 0xf9, 0xe3, 0xd8, 0x32, 0xae, 0xff, 0x1a, 0xd5, 0x8f, 0x7e, 0x0a, 0xf0, 0x4a, 0xe9, 0x7e, 0x46, 0x10, + 0x24, 0x5c, 0x83, 0x6d, 0xf4, 0x27, 0xe5, 0xa9, 0xa2, 0xd1, 0xf6, 0xd1, 0xf5, 0x51, 0x9e, 0x45, 0x5e, 0x38, 0xc2, + 0xc9, 0x1d, 0x54, 0xbe, 0x98, 0x54, 0x29, 0x1c, 0x0f, 0x47, 0xcc, 0x8a, 0x1b, 0xbd, 0xad, 0xdc, 0x02, 0xf6, 0xdf, + 0x72, 0x7c, 0x5a, 0x63, 0x08, 0xbe, 0x00, 0x35, 0x20, 0xa5, 0xc0, 0xce, 0x0e, 0x21, 0xb6, 0x88, 0xdc, 0x5d, 0xf9, + 0x90, 0xdc, 0xbf, 0x33, 0x3c, 0x74, 0xf0, 0x0e, 0x2d, 0xef, 0xaf, 0xf9, 0xb8, 0xfb, 0xc4, 0x2e, 0x59, 0x38, 0x2d, + 0x77, 0x58, 0x39, 0xbf, 0xf6, 0xef, 0xae, 0x44, 0x51, 0x20, 0xd7, 0x46, 0xd4, 0x40, 0x51, 0xb2, 0x28, 0xc4, 0xc5, + 0x4f, 0xdb, 0xcd, 0xdf, 0x8b, 0x8b, 0xc1, 0x06, 0x14, 0x28, 0x2f, 0x6f, 0x26, 0x29, 0xc5, 0x21, 0xa0, 0x3b, 0x7a, + 0x31, 0x6b, 0x82, 0x11, 0x6d, 0x5d, 0x89, 0xa9, 0x30, 0x84, 0x2c, 0xda, 0xf8, 0x3c, 0x44, 0xeb, 0xbe, 0x5a, 0x6b, + 0x7f, 0xb7, 0xd6, 0x3a, 0xdd, 0xa5, 0xb5, 0x26, 0x1f, 0x30, 0xb2, 0xde, 0xc9, 0x7d, 0xe1, 0x04, 0x73, 0x2e, 0x7b, + 0x13, 0x96, 0x54, 0xdd, 0xe8, 0x32, 0x26, 0x5a, 0xd5, 0x7a, 0x23, 0xd3, 0x46, 0x54, 0x7f, 0x4b, 0x02, 0x8a, 0xb8, + 0x50, 0x97, 0x75, 0xe3, 0x17, 0x85, 0x6e, 0x9c, 0xa4, 0x9a, 0xc2, 0xfb, 0x47, 0x70, 0xff, 0x92, 0x67, 0x5d, 0x2e, + 0x1d, 0x14, 0x1e, 0x76, 0xc5, 0x48, 0x25, 0x9f, 0xb1, 0x42, 0xd0, 0x90, 0x3c, 0x11, 0x85, 0x94, 0x51, 0x76, 0x48, + 0x2c, 0x57, 0x2d, 0x5c, 0xc6, 0x8a, 0x72, 0xd0, 0xba, 0xe3, 0x90, 0xf3, 0x62, 0x79, 0xd9, 0x94, 0x7d, 0x86, 0xe4, + 0xd7, 0xd2, 0x22, 0xc9, 0x9d, 0x7b, 0x08, 0xc1, 0x42, 0x4d, 0x5f, 0xb9, 0xd7, 0xce, 0x6d, 0x20, 0x70, 0x90, 0x0d, + 0xbe, 0x88, 0xbb, 0xb5, 0xf3, 0x94, 0x46, 0xa4, 0xb8, 0xba, 0x76, 0xf0, 0x74, 0xa7, 0x9b, 0x60, 0x59, 0x1f, 0x81, + 0xb8, 0xbe, 0x92, 0x34, 0x08, 0x7d, 0x5b, 0xb1, 0x07, 0x0d, 0x0c, 0x00, 0x9e, 0xff, 0xd5, 0x67, 0xce, 0x0a, 0x80, + 0x26, 0x52, 0xb1, 0xe5, 0x3b, 0x7f, 0xdc, 0xc4, 0x26, 0x99, 0x1f, 0x63, 0xd5, 0xfa, 0x37, 0x49, 0xdf, 0xb3, 0xe1, + 0x9e, 0x3f, 0x65, 0x75, 0x3e, 0xaf, 0xd1, 0x17, 0xe3, 0xe0, 0xab, 0x2c, 0x5e, 0x87, 0x98, 0x1d, 0xc2, 0x4c, 0x63, + 0x6f, 0xf2, 0x61, 0x23, 0x7d, 0x8f, 0xab, 0x44, 0x41, 0x5d, 0x5c, 0xbe, 0x54, 0x18, 0x78, 0x18, 0x4c, 0x95, 0xf5, + 0x2d, 0x37, 0x91, 0x14, 0x35, 0xfd, 0x87, 0x76, 0xc7, 0x7b, 0x36, 0x3b, 0xac, 0xe8, 0x4f, 0xdd, 0x6e, 0x59, 0xbb, + 0x9e, 0x8f, 0x63, 0x19, 0xfd, 0xca, 0x7d, 0x24, 0xff, 0xf8, 0x4f, 0x27, 0xfc, 0x9b, 0x95, 0x39, 0xfa, 0x9c, 0x21, + 0x40, 0xfb, 0xd2, 0xc5, 0xb4, 0x7c, 0x4d, 0x53, 0x2b, 0x69, 0x1b, 0xd6, 0xcc, 0x0f, 0x02, 0x33, 0x00, 0x4f, 0x95, + 0xcd, 0x67, 0x81, 0x87, 0xfd, 0xac, 0x21, 0x8c, 0xf7, 0x67, 0xf4, 0x53, 0x5e, 0x29, 0xe9, 0x62, 0xbd, 0x1c, 0x6f, + 0x64, 0x45, 0xb9, 0xa4, 0x3f, 0xaf, 0xeb, 0xcc, 0xe5, 0xcf, 0xce, 0x66, 0xb3, 0xb2, 0xd6, 0xd8, 0x56, 0x0e, 0x51, + 0xf3, 0xfb, 0xd0, 0xb6, 0xed, 0x2a, 0x7e, 0xdb, 0x36, 0x0a, 0x6d, 0x0c, 0x13, 0x95, 0xf0, 0xbd, 0xdd, 0x6b, 0xea, + 0x0f, 0x1a, 0x2d, 0x75, 0xd5, 0xb6, 0x1f, 0x69, 0xa9, 0xfd, 0x57, 0x0c, 0x05, 0x49, 0xc3, 0xae, 0xed, 0x5f, 0x5f, + 0x2b, 0x5b, 0x7a, 0xaa, 0x6e, 0xe0, 0x4f, 0x6b, 0xbc, 0x63, 0xad, 0xef, 0xd1, 0xb4, 0x6d, 0x79, 0x67, 0x56, 0x71, + 0xec, 0x96, 0x6c, 0x96, 0x06, 0x64, 0xa9, 0xe4, 0xa7, 0x6c, 0x99, 0xf4, 0x27, 0x0c, 0x2f, 0x48, 0x2d, 0xe9, 0xb4, + 0x45, 0xab, 0x1e, 0x73, 0x0e, 0x76, 0x5c, 0x8e, 0xa0, 0xc3, 0xb6, 0x82, 0x97, 0x55, 0xb5, 0x9b, 0x35, 0xf1, 0x11, + 0x3c, 0xc5, 0x36, 0xf5, 0x0b, 0x27, 0x5c, 0xa6, 0x5d, 0xfb, 0x4f, 0xa5, 0x7a, 0x0a, 0x70, 0xa7, 0x1b, 0x61, 0x6d, + 0x42, 0x97, 0x27, 0xf8, 0x77, 0x7e, 0x39, 0xf7, 0x6c, 0x75, 0x57, 0x36, 0xee, 0xea, 0xc1, 0x75, 0x53, 0x71, 0x94, + 0xd1, 0xa8, 0x9b, 0x48, 0x5f, 0x6e, 0x02, 0x34, 0x93, 0xad, 0x5b, 0xc0, 0x82, 0xa6, 0x94, 0xb4, 0xaa, 0xe1, 0x6e, + 0x0c, 0xc5, 0x59, 0x58, 0x79, 0x85, 0x7e, 0xbf, 0x48, 0xb9, 0x0a, 0x30, 0x18, 0x4f, 0x7b, 0x78, 0xb9, 0x57, 0x5a, + 0xaa, 0x68, 0x2a, 0x83, 0x6b, 0x40, 0x48, 0xa4, 0xca, 0x3a, 0x0e, 0x4c, 0xca, 0xe8, 0xa4, 0xe9, 0x9b, 0x3a, 0xdc, + 0xed, 0xdd, 0x3b, 0x5d, 0xb8, 0xd7, 0xa8, 0xa3, 0x6a, 0xaf, 0xab, 0xbd, 0xea, 0x1d, 0xb6, 0x18, 0x27, 0xcc, 0x00, + 0x78, 0x52, 0x28, 0x68, 0x34, 0xa4, 0x54, 0x68, 0x1f, 0x01, 0x9d, 0xbf, 0x95, 0x89, 0xb5, 0x80, 0x13, 0xbb, 0x6b, + 0xae, 0x42, 0x7d, 0x8b, 0x9b, 0x41, 0xc0, 0x1d, 0xa7, 0x4e, 0xf8, 0x6c, 0xc2, 0x8a, 0x91, 0xc9, 0x95, 0x83, 0x2b, + 0x08, 0x77, 0xa9, 0x89, 0x7c, 0x72, 0x42, 0xbb, 0x14, 0xef, 0x12, 0xbe, 0x6f, 0x54, 0xde, 0x5f, 0x94, 0xb4, 0xf1, + 0xdc, 0x9d, 0xc5, 0xd5, 0xf7, 0xaa, 0xbd, 0xf4, 0xc3, 0xfd, 0xeb, 0x7a, 0x77, 0x7b, 0xd7, 0x05, 0xe6, 0x70, 0xef, + 0xca, 0xc0, 0x5d, 0x92, 0x95, 0x52, 0x3a, 0xfc, 0x5e, 0xba, 0x3c, 0x90, 0xc3, 0x22, 0xa8, 0xd8, 0x8a, 0x24, 0xfa, + 0x8b, 0xf5, 0x70, 0x74, 0x72, 0x76, 0xb7, 0x0c, 0x94, 0x1b, 0x16, 0x43, 0x76, 0xbb, 0xa1, 0xea, 0x58, 0xb6, 0xaa, + 0xa0, 0x93, 0xbf, 0x1f, 0xce, 0x87, 0xea, 0xcf, 0x17, 0xaf, 0xcc, 0x9e, 0x7a, 0x06, 0xe6, 0x18, 0x37, 0x73, 0x64, + 0x71, 0xcf, 0xbd, 0x7b, 0x16, 0x5f, 0xbb, 0xaa, 0x82, 0x49, 0xec, 0x88, 0xb9, 0xc5, 0x32, 0xc5, 0x55, 0xf7, 0xc8, + 0x95, 0xa4, 0x88, 0x74, 0xa7, 0x2a, 0x10, 0x56, 0xc7, 0xed, 0x29, 0x8e, 0x7b, 0x68, 0x1d, 0xf5, 0xd4, 0xd3, 0xaf, + 0x14, 0xe5, 0x64, 0xca, 0x66, 0xc9, 0x29, 0xaa, 0x63, 0x4e, 0x90, 0x1f, 0xa4, 0xdf, 0x8a, 0x62, 0x4d, 0x82, 0xc4, + 0x74, 0x94, 0x0d, 0x7f, 0x54, 0x14, 0x20, 0x46, 0x7d, 0xe5, 0xe1, 0xcc, 0x9d, 0x1d, 0xce, 0x9e, 0x0d, 0x78, 0x71, + 0xf6, 0x55, 0xa9, 0xba, 0x41, 0xff, 0xba, 0x52, 0xb3, 0x24, 0x8d, 0xa3, 0x0f, 0x8c, 0xf3, 0x92, 0x4a, 0xae, 0x28, + 0xaa, 0x36, 0x75, 0xeb, 0x5f, 0x72, 0x7a, 0xe3, 0xc9, 0xcc, 0x2d, 0xaa, 0xe3, 0x18, 0x0f, 0xf2, 0x41, 0x9e, 0x1c, + 0x88, 0xa1, 0x9f, 0xc8, 0x68, 0x72, 0xcc, 0x26, 0x44, 0x39, 0x2a, 0x87, 0x71, 0x2e, 0xe0, 0x3b, 0x81, 0x50, 0xc4, + 0x85, 0x03, 0x42, 0x82, 0xcd, 0x86, 0xea, 0x0f, 0x8e, 0xdb, 0x33, 0x1c, 0xe7, 0xc8, 0x3a, 0xea, 0x4d, 0x6c, 0xe3, + 0xd0, 0x3a, 0x34, 0x3b, 0xd6, 0x91, 0xd1, 0x33, 0x7b, 0x46, 0xef, 0x2f, 0xbd, 0x89, 0x79, 0x68, 0x1d, 0x1a, 0xb6, + 0xd9, 0x83, 0x42, 0xb3, 0x67, 0xf6, 0x6e, 0xcc, 0xc3, 0xde, 0xc4, 0xc6, 0x52, 0xd7, 0xea, 0x76, 0x4d, 0xc7, 0xb6, + 0xba, 0x5d, 0xa3, 0x6b, 0x1d, 0x1d, 0x99, 0x4e, 0xc7, 0x3a, 0x3a, 0x3a, 0xef, 0xf6, 0xac, 0x0e, 0xbc, 0xeb, 0x74, + 0x26, 0x1d, 0xcb, 0x71, 0x4c, 0xf8, 0xcb, 0xe8, 0x59, 0x2e, 0xfd, 0x70, 0x1c, 0xab, 0xe3, 0x18, 0x76, 0xd0, 0x75, + 0xad, 0xa3, 0x67, 0x06, 0xfe, 0x8d, 0xd5, 0x0c, 0xfc, 0x0b, 0xba, 0x31, 0x9e, 0x59, 0xee, 0x11, 0xfd, 0xc2, 0x0e, + 0x6f, 0x0e, 0x7b, 0x7f, 0x57, 0x0f, 0x5a, 0x61, 0x70, 0x08, 0x86, 0x5e, 0xd7, 0xea, 0x74, 0x8c, 0x43, 0xc7, 0xea, + 0x75, 0x16, 0xe6, 0xa1, 0x6b, 0x1d, 0x1d, 0x4f, 0x4c, 0xc7, 0x3a, 0x3e, 0x36, 0x6c, 0xb3, 0x63, 0xb9, 0x86, 0x63, + 0x1d, 0x76, 0xf0, 0x47, 0xc7, 0x72, 0x6f, 0x8e, 0x9f, 0x59, 0x47, 0xdd, 0xc5, 0x91, 0x75, 0xf8, 0xfe, 0xb0, 0x67, + 0xb9, 0x9d, 0x45, 0xe7, 0xc8, 0x72, 0x8f, 0x6f, 0x8e, 0xac, 0xc3, 0x85, 0xe9, 0x1e, 0x6d, 0x6d, 0xe9, 0xb8, 0x16, + 0xe0, 0x08, 0x5f, 0xc3, 0x0b, 0x83, 0xbf, 0x80, 0x3f, 0x0b, 0x6c, 0xfb, 0x07, 0x76, 0x93, 0xd4, 0x9b, 0x3e, 0xb3, + 0x7a, 0xc7, 0x13, 0xaa, 0x0e, 0x05, 0xa6, 0xa8, 0x01, 0x4d, 0x6e, 0x4c, 0xfa, 0x2c, 0x76, 0x67, 0x8a, 0x8e, 0xc4, + 0x1f, 0xfe, 0xb1, 0x1b, 0x13, 0x3e, 0x4c, 0xdf, 0xfd, 0x8f, 0xf6, 0x93, 0x4f, 0x39, 0x24, 0x6f, 0xfe, 0x8a, 0xff, + 0x43, 0x79, 0xcf, 0x46, 0xc6, 0x79, 0xdb, 0xa5, 0xe4, 0xdb, 0xdd, 0x97, 0x92, 0xaf, 0xd6, 0xfb, 0x5c, 0x4a, 0xbe, + 0xfd, 0xe2, 0x97, 0x92, 0xe7, 0x55, 0x9f, 0x98, 0xb7, 0xd5, 0xf4, 0x2c, 0xdf, 0x6f, 0xaa, 0x2a, 0x07, 0xdf, 0xd3, + 0x2e, 0x2f, 0xd6, 0x57, 0x10, 0xf7, 0xed, 0x6d, 0x34, 0x7c, 0xb5, 0x2e, 0x19, 0x7c, 0x46, 0x40, 0x63, 0xdf, 0x46, + 0x44, 0x63, 0x7f, 0x5d, 0x0f, 0xc1, 0xca, 0x8c, 0xb3, 0x39, 0xfe, 0xd4, 0x5c, 0x78, 0xc1, 0x2c, 0x67, 0x91, 0xa0, + 0x64, 0x80, 0xc5, 0xe0, 0x77, 0x05, 0xc7, 0x33, 0x48, 0x32, 0xeb, 0x65, 0x98, 0x80, 0x45, 0x30, 0x58, 0x72, 0xcc, + 0xe2, 0xac, 0xd2, 0xd8, 0x12, 0x91, 0xf2, 0xae, 0xb9, 0x07, 0x54, 0xeb, 0x7b, 0x34, 0x00, 0x6e, 0xee, 0xdd, 0xa9, + 0xf7, 0xab, 0x80, 0x65, 0x9d, 0x30, 0x90, 0x06, 0x6e, 0xbf, 0xe9, 0x7d, 0xd9, 0x0c, 0xb7, 0x62, 0x78, 0xdd, 0x3e, + 0x52, 0x18, 0x49, 0xb5, 0xbd, 0x53, 0x36, 0xe3, 0xdd, 0x05, 0x66, 0xc3, 0xe7, 0x4b, 0xcd, 0xb7, 0xd8, 0x10, 0xe7, + 0x1d, 0x57, 0x51, 0x55, 0x49, 0x2e, 0xda, 0x88, 0x90, 0x42, 0x40, 0x2d, 0x0c, 0x8d, 0x0b, 0x4e, 0xd5, 0x56, 0x90, + 0xdf, 0xb1, 0xa5, 0x77, 0xa5, 0x3e, 0x65, 0xe3, 0xe4, 0x27, 0x1b, 0x94, 0x2b, 0xfc, 0x5f, 0x81, 0x13, 0xe5, 0x1c, + 0xcf, 0x38, 0x92, 0xf1, 0xbc, 0x91, 0xfa, 0x25, 0x6d, 0x44, 0xb6, 0x70, 0x36, 0x75, 0x5e, 0xb4, 0xd5, 0x2d, 0xc1, + 0x61, 0x4b, 0xc1, 0x05, 0xe1, 0xe7, 0xc9, 0x09, 0x20, 0x23, 0x47, 0x0d, 0xf4, 0x73, 0xd8, 0xd6, 0x99, 0xa8, 0xf7, + 0x10, 0x16, 0xb1, 0xc1, 0x1f, 0xe4, 0xc0, 0x25, 0x9b, 0x59, 0x10, 0x79, 0x69, 0x1f, 0xd9, 0x34, 0x89, 0xe5, 0x75, + 0xd1, 0x63, 0x61, 0xb0, 0xc5, 0x98, 0x4e, 0xee, 0x98, 0x77, 0x82, 0x9e, 0x0f, 0xdb, 0xec, 0xef, 0x72, 0x47, 0xb1, + 0x4d, 0xc9, 0x1c, 0xc5, 0xe9, 0x1e, 0x1b, 0xce, 0x91, 0x61, 0x1d, 0x77, 0xf5, 0x4c, 0x6c, 0x38, 0xb9, 0xcb, 0x12, + 0x42, 0xc0, 0x01, 0x22, 0x1f, 0xa6, 0x1f, 0xfa, 0xa9, 0xef, 0x05, 0x19, 0xf0, 0xc3, 0x65, 0x21, 0xe5, 0x1f, 0xeb, + 0x24, 0x05, 0x18, 0x05, 0xd3, 0x8b, 0xce, 0x1f, 0xe6, 0x98, 0xa5, 0xb7, 0x8c, 0x85, 0x2d, 0x86, 0x31, 0x55, 0x5f, + 0x92, 0xdf, 0xcf, 0xb2, 0x3e, 0x23, 0xab, 0xb5, 0x71, 0x1a, 0xf2, 0xf5, 0x21, 0x1c, 0x1f, 0xb2, 0x91, 0xf1, 0x63, + 0x1b, 0xc1, 0xfd, 0xc7, 0x6e, 0x82, 0x9b, 0xb2, 0x7d, 0x08, 0xee, 0x3f, 0xbe, 0x38, 0xc1, 0xfd, 0x51, 0x26, 0xb8, + 0x25, 0xbf, 0xbf, 0xe2, 0x86, 0xe9, 0x1d, 0x3e, 0x6b, 0x90, 0xd8, 0xe0, 0xa9, 0x7a, 0x40, 0x0c, 0xbc, 0x2a, 0xe5, + 0x9b, 0x7f, 0x5f, 0x4a, 0xa0, 0x87, 0x0a, 0x50, 0x8c, 0x68, 0x4e, 0xc9, 0xba, 0x20, 0x17, 0xbb, 0x9d, 0x27, 0xec, + 0x62, 0xb7, 0xca, 0xeb, 0x30, 0x0d, 0xac, 0xb7, 0x5c, 0x8e, 0x84, 0x0b, 0xdd, 0x57, 0x51, 0xbc, 0xf4, 0x30, 0x34, + 0xa8, 0x8a, 0x89, 0x77, 0xe1, 0xc1, 0x06, 0x5f, 0xd2, 0x49, 0x14, 0x4e, 0xf3, 0x5b, 0x49, 0x36, 0xbc, 0x24, 0x8e, + 0x5b, 0xbd, 0x67, 0x5e, 0xac, 0x1a, 0xf4, 0x1a, 0x26, 0xf7, 0x49, 0xc7, 0x7e, 0xe2, 0x1e, 0x3e, 0x39, 0xb2, 0xe1, + 0x7f, 0x87, 0x75, 0x32, 0x83, 0x57, 0x5c, 0x46, 0x21, 0xe4, 0xfe, 0x12, 0x35, 0xdb, 0xaa, 0xdd, 0x32, 0xf6, 0xa1, + 0xa8, 0x75, 0xdc, 0x5c, 0x69, 0xea, 0xdd, 0x17, 0x75, 0x1a, 0x6b, 0x2c, 0xa2, 0xb5, 0x34, 0xac, 0x86, 0xd1, 0xf8, + 0xe1, 0x1a, 0xf4, 0xec, 0x52, 0x0d, 0xf9, 0x35, 0x07, 0xb7, 0x80, 0x8b, 0x75, 0xb2, 0xab, 0x22, 0xc1, 0xa0, 0x48, + 0x74, 0xb6, 0x13, 0x83, 0xfc, 0x8a, 0xd2, 0xc6, 0x60, 0xd0, 0x18, 0x96, 0x1d, 0x42, 0x41, 0xe7, 0x69, 0xe1, 0x3c, + 0x9a, 0xa0, 0x34, 0x5e, 0x87, 0x13, 0x0d, 0x7f, 0x7a, 0xe3, 0x44, 0xf3, 0x0f, 0x62, 0x8b, 0x7f, 0x58, 0xc7, 0x59, + 0xf3, 0x4e, 0xed, 0x22, 0x1b, 0x53, 0x22, 0x66, 0xc5, 0x7b, 0x92, 0x1a, 0x31, 0xe5, 0x70, 0xc7, 0xa9, 0x35, 0x87, + 0xde, 0x93, 0xbc, 0xe1, 0x93, 0xd4, 0x80, 0x3c, 0xea, 0x30, 0xdd, 0x8f, 0x1f, 0x53, 0x2d, 0xc8, 0x6c, 0x4c, 0x60, + 0x9d, 0x4d, 0x8a, 0xf8, 0x93, 0x8a, 0x37, 0x8f, 0x28, 0x04, 0x65, 0x7f, 0x62, 0x44, 0x4f, 0x9f, 0x9e, 0x0e, 0x1d, + 0x9d, 0xe7, 0xe5, 0x2e, 0x25, 0x91, 0x3c, 0xdf, 0xcf, 0xd0, 0x48, 0x6f, 0x74, 0x81, 0x5d, 0x81, 0xcc, 0x64, 0x0b, + 0x77, 0x04, 0x4e, 0xbd, 0x20, 0xa9, 0x13, 0x19, 0x14, 0x78, 0xc2, 0xe0, 0x47, 0xd4, 0xc9, 0xa5, 0xae, 0x8e, 0x65, + 0x5b, 0xb6, 0x9a, 0x37, 0x9c, 0xf9, 0xf3, 0xe1, 0x26, 0x4a, 0x3d, 0x48, 0x8f, 0x17, 0x44, 0x73, 0xf0, 0xa3, 0x4b, + 0xfd, 0x34, 0x80, 0x5c, 0x6b, 0xe0, 0x50, 0xb7, 0x24, 0xb9, 0x3c, 0xe3, 0xde, 0x0d, 0x5e, 0xfc, 0x01, 0xf3, 0xed, + 0x0a, 0x17, 0x5a, 0x0c, 0x89, 0xf6, 0x03, 0x1c, 0x86, 0x9a, 0xaa, 0x81, 0x6e, 0x80, 0xc5, 0x89, 0x29, 0x7b, 0x0b, + 0xf5, 0x15, 0x68, 0xa3, 0xab, 0x1c, 0x88, 0x59, 0xec, 0x2d, 0x21, 0x2f, 0xc9, 0x26, 0x33, 0x38, 0xa5, 0x55, 0x39, + 0xa9, 0x55, 0x9c, 0x67, 0x47, 0x86, 0xe2, 0x3a, 0x86, 0x62, 0x03, 0xb9, 0x55, 0x33, 0x63, 0x93, 0x5d, 0x0d, 0x76, + 0x19, 0x3c, 0x10, 0x7d, 0x79, 0x48, 0x70, 0x90, 0xa9, 0x03, 0xbf, 0x4a, 0x4a, 0x29, 0xb8, 0xad, 0x26, 0x85, 0xff, + 0xf7, 0xe9, 0xd2, 0xf3, 0x82, 0xdd, 0xa5, 0x3a, 0xe6, 0x22, 0xe3, 0x55, 0x7c, 0x7d, 0x83, 0x8e, 0xbe, 0x7e, 0xa8, + 0xf8, 0x1f, 0x3f, 0x6a, 0x3e, 0x38, 0x33, 0x0d, 0x25, 0xfc, 0xc0, 0xb3, 0x5e, 0x42, 0x98, 0x5f, 0x5c, 0xd3, 0x23, + 0xb2, 0xc0, 0xd3, 0x10, 0xfe, 0x2d, 0x8a, 0xc5, 0x0f, 0x6e, 0x26, 0x61, 0x05, 0x5e, 0x38, 0x07, 0x92, 0xe6, 0x85, + 0xf3, 0x9a, 0x39, 0x16, 0xf9, 0x2a, 0x57, 0x4a, 0x8b, 0xae, 0x0a, 0x53, 0xa9, 0xe4, 0xbb, 0xfb, 0x0b, 0xca, 0xb5, + 0xa8, 0xa9, 0x70, 0xca, 0xa1, 0x63, 0x6d, 0x71, 0x93, 0xfb, 0x74, 0xf8, 0xf5, 0xc9, 0x92, 0xa5, 0x1e, 0x5d, 0x03, + 0x81, 0xf0, 0x0b, 0xec, 0x80, 0x32, 0x11, 0x79, 0xd2, 0xf1, 0x68, 0x18, 0x4e, 0xd9, 0x8d, 0x3f, 0xe1, 0x72, 0xa9, + 0xa1, 0xf0, 0x73, 0xca, 0x44, 0x8b, 0xcf, 0xa1, 0x63, 0x90, 0xc3, 0xc1, 0xc4, 0xc3, 0x38, 0xb8, 0xc3, 0x30, 0x52, + 0x4f, 0xbf, 0xce, 0x7d, 0x33, 0xdb, 0x26, 0x01, 0x12, 0x1e, 0x5f, 0xc6, 0x2c, 0xf8, 0xe7, 0xf0, 0x6b, 0x38, 0xb8, + 0xbf, 0xbe, 0x52, 0xf5, 0x41, 0x6a, 0x2d, 0x62, 0x36, 0x1b, 0x7e, 0xdd, 0x90, 0xf8, 0x17, 0xc5, 0x7b, 0x1a, 0x8b, + 0xda, 0x71, 0x8b, 0xe8, 0x65, 0x9d, 0xbd, 0x84, 0xfa, 0x53, 0x2e, 0xad, 0x83, 0x04, 0xb8, 0x29, 0xc9, 0xd8, 0xce, + 0x00, 0xe5, 0xe7, 0x71, 0xe0, 0x4d, 0x3e, 0x0c, 0xe8, 0x4d, 0xe9, 0xc1, 0x84, 0xd3, 0x7a, 0xe2, 0xad, 0xfa, 0x78, + 0xbc, 0xca, 0x85, 0xe0, 0x9a, 0x4d, 0xa5, 0x39, 0x67, 0xd7, 0xb8, 0x96, 0x71, 0x29, 0x6f, 0xf0, 0xcb, 0xf8, 0xa9, + 0xdb, 0x85, 0x9f, 0x32, 0xf1, 0x29, 0x7c, 0xc8, 0x32, 0x21, 0xa8, 0x93, 0x88, 0x8a, 0x82, 0xb5, 0xd5, 0x51, 0x9c, + 0xde, 0x5f, 0xba, 0x37, 0x8e, 0xbd, 0x70, 0x1d, 0xab, 0xf7, 0xde, 0xe9, 0x2d, 0x3a, 0xd6, 0x71, 0x60, 0x76, 0xac, + 0x63, 0xf8, 0xf3, 0xfe, 0xd8, 0xea, 0x2d, 0x4c, 0xd7, 0x3a, 0x7c, 0xef, 0xb8, 0x81, 0xd9, 0xb3, 0x8e, 0xe1, 0xcf, + 0x39, 0xb5, 0x02, 0x01, 0x88, 0xe4, 0x9d, 0xaf, 0x4b, 0x54, 0x40, 0xfa, 0x9d, 0xdf, 0xc9, 0x1a, 0xa5, 0xe3, 0xad, + 0xe1, 0x5e, 0x17, 0x48, 0x46, 0x91, 0x41, 0x27, 0x1c, 0x68, 0xe1, 0x90, 0x51, 0x46, 0x0c, 0x61, 0xde, 0x26, 0x7c, + 0xd0, 0x45, 0x22, 0x97, 0xc6, 0x6d, 0xc4, 0xdb, 0x34, 0x67, 0xef, 0x10, 0xc9, 0x19, 0xe9, 0x22, 0xf8, 0xe7, 0x15, + 0x46, 0x59, 0x13, 0xf9, 0x46, 0x24, 0xaa, 0x54, 0x24, 0x08, 0xce, 0x76, 0x0f, 0x1c, 0xbd, 0xf0, 0x59, 0x9e, 0xa0, + 0xee, 0x8b, 0xf6, 0x2d, 0xe5, 0x15, 0xfa, 0xac, 0x7e, 0x30, 0x2f, 0x7b, 0x91, 0x7d, 0x04, 0xc2, 0x4d, 0x4f, 0xfd, + 0x38, 0x1f, 0x9e, 0x44, 0xa2, 0x9d, 0xe6, 0xb4, 0x27, 0x3a, 0x64, 0xf2, 0x7a, 0x0d, 0x5c, 0xf2, 0x8d, 0x17, 0x48, + 0x86, 0x6c, 0x52, 0xcb, 0x07, 0x39, 0xe5, 0x7f, 0xfc, 0xb8, 0x18, 0x9c, 0x59, 0x19, 0xf7, 0x89, 0xd3, 0x85, 0x63, + 0xb7, 0xcb, 0x3a, 0x5b, 0x6d, 0x2a, 0x77, 0x07, 0x2a, 0x2f, 0xe2, 0x19, 0x0b, 0xbb, 0x29, 0x61, 0xb1, 0xd1, 0x6a, + 0xd8, 0x59, 0xb3, 0xd7, 0x80, 0x10, 0xef, 0x15, 0x51, 0x47, 0xd5, 0x07, 0xa1, 0x30, 0x3f, 0x08, 0xb7, 0x04, 0x67, + 0xe7, 0xb2, 0x98, 0x0a, 0xa8, 0xd9, 0x02, 0xc7, 0x0e, 0x07, 0xf1, 0xff, 0x34, 0x10, 0xe8, 0xac, 0x09, 0xf6, 0x12, + 0x95, 0xdd, 0x5a, 0x72, 0xde, 0xcb, 0xcf, 0x55, 0x3a, 0x50, 0x59, 0x72, 0xa6, 0x42, 0x11, 0xa4, 0x78, 0xc4, 0xac, + 0xae, 0xb9, 0xb1, 0x68, 0x7e, 0x5a, 0x14, 0x05, 0x86, 0x8f, 0x99, 0x2e, 0x84, 0xe3, 0xa8, 0xfe, 0xf8, 0x71, 0xeb, + 0x21, 0x44, 0xc6, 0x39, 0x72, 0x72, 0x6b, 0x55, 0xa6, 0x6f, 0xaa, 0x4c, 0x62, 0xf2, 0x7e, 0x91, 0x6a, 0x08, 0x1b, + 0x57, 0x5a, 0x7b, 0xf8, 0x73, 0xcc, 0xbc, 0xd4, 0xe2, 0x97, 0xa5, 0x9a, 0x74, 0xb8, 0x1b, 0x0e, 0xeb, 0x80, 0x75, + 0x2b, 0x0f, 0xc6, 0xc8, 0x83, 0x9d, 0x3e, 0xda, 0xbc, 0x5f, 0xf3, 0xa8, 0x0e, 0xd0, 0xc7, 0x47, 0xbb, 0x88, 0x9f, + 0xf5, 0x26, 0xf5, 0x28, 0xc8, 0x92, 0x7c, 0xe4, 0x46, 0xa9, 0x27, 0x52, 0xa9, 0x01, 0x5f, 0x3e, 0x68, 0x34, 0xbf, + 0x90, 0x22, 0x3f, 0x9c, 0xbe, 0xb9, 0xf8, 0x56, 0xe1, 0xeb, 0x9f, 0xac, 0x05, 0x50, 0x90, 0xa1, 0x34, 0x2e, 0x43, + 0x4a, 0xe3, 0xa2, 0xf0, 0x24, 0x56, 0x90, 0x0c, 0x25, 0x3b, 0x20, 0x0c, 0xa2, 0x02, 0x9a, 0x6c, 0x28, 0x96, 0xeb, + 0x20, 0xf5, 0x57, 0x5e, 0x9c, 0x1e, 0x40, 0x53, 0x13, 0x88, 0x9c, 0xda, 0x16, 0x0f, 0x82, 0xcc, 0x30, 0x44, 0x0c, + 0xd0, 0x34, 0x14, 0x76, 0x18, 0x33, 0x3f, 0xc8, 0xcd, 0x30, 0xc4, 0x07, 0xbc, 0xc9, 0x84, 0xad, 0xd2, 0xa1, 0xea, + 0xad, 0x20, 0x95, 0x12, 0xc6, 0xda, 0x3f, 0x88, 0x26, 0x29, 0x4b, 0xcd, 0x24, 0x8d, 0x99, 0xb7, 0x54, 0xf3, 0x58, + 0xd3, 0xf5, 0xfe, 0x92, 0xf5, 0x78, 0xe9, 0xa7, 0x79, 0xb0, 0x56, 0x02, 0x10, 0x0c, 0x22, 0x60, 0x88, 0x10, 0x1c, + 0x86, 0x50, 0x78, 0x1e, 0xcd, 0x2b, 0x2b, 0xaa, 0xe0, 0x5c, 0xce, 0x30, 0x14, 0x38, 0x49, 0x32, 0xa0, 0x2d, 0x9e, + 0x44, 0xc1, 0x35, 0x8f, 0x61, 0x91, 0xc7, 0x94, 0x55, 0x4f, 0x4f, 0xb8, 0x78, 0xab, 0x60, 0xd8, 0x15, 0xb5, 0x6b, + 0x43, 0xb0, 0xf3, 0xb6, 0xe8, 0x16, 0x07, 0xbc, 0x32, 0x1c, 0x4d, 0xd4, 0x33, 0x66, 0xa0, 0xa0, 0xb1, 0x5c, 0x00, + 0x23, 0x54, 0x32, 0x98, 0x59, 0x38, 0xa7, 0xb9, 0x3b, 0x25, 0x8e, 0x0a, 0x79, 0xa5, 0x8f, 0x1f, 0x9f, 0x8f, 0x7e, + 0xfb, 0x17, 0xa4, 0xc9, 0x58, 0x38, 0x22, 0xa6, 0xc4, 0xa5, 0x5c, 0x8b, 0x73, 0x9f, 0xc6, 0x08, 0x8d, 0xa5, 0xd8, + 0x54, 0x04, 0xe6, 0x11, 0x4b, 0x2b, 0x1b, 0x5d, 0x89, 0x68, 0x7f, 0x90, 0x41, 0x47, 0x17, 0x91, 0x2f, 0x46, 0x30, + 0xbd, 0x23, 0x11, 0x70, 0x45, 0xf9, 0xe5, 0xee, 0xbb, 0x63, 0xa5, 0x08, 0xc1, 0xd3, 0x64, 0xd1, 0x43, 0x6b, 0xe8, + 0xf4, 0xc4, 0x53, 0x90, 0x69, 0x41, 0xf6, 0x23, 0xe9, 0x1f, 0x00, 0x98, 0x8b, 0x68, 0xc9, 0x2c, 0x3f, 0x3a, 0xb8, + 0x65, 0x63, 0xd3, 0x5b, 0xf9, 0x64, 0x97, 0x83, 0x7a, 0x37, 0x85, 0x38, 0xbf, 0xdc, 0xdc, 0x85, 0xf8, 0xeb, 0xac, + 0x40, 0x65, 0x54, 0x0e, 0xef, 0xd8, 0x75, 0x8b, 0x7b, 0x40, 0x88, 0x5f, 0x20, 0xe1, 0x31, 0x3a, 0x3d, 0x39, 0xf0, + 0x4e, 0xcb, 0xf1, 0x65, 0x2d, 0x91, 0xda, 0xa4, 0x7c, 0x08, 0x9c, 0x51, 0x98, 0x58, 0x11, 0x11, 0xb6, 0x78, 0x30, + 0xa3, 0xd9, 0x4c, 0x8e, 0x09, 0x6b, 0x95, 0x87, 0x97, 0x23, 0xad, 0x58, 0xd2, 0xd1, 0x8a, 0xbe, 0x54, 0xff, 0x44, + 0xfe, 0x53, 0xed, 0x63, 0x30, 0x68, 0x80, 0x19, 0xb6, 0x7b, 0x2d, 0xb6, 0x6c, 0x8e, 0xb1, 0x87, 0x54, 0x89, 0xd3, + 0x91, 0x6a, 0x26, 0x83, 0x16, 0xce, 0xe5, 0xc1, 0x70, 0x48, 0x64, 0xae, 0x4a, 0xed, 0x00, 0x89, 0x0d, 0x69, 0x5e, + 0x00, 0xd8, 0x14, 0x1a, 0x9a, 0xe4, 0x2e, 0x8b, 0x8d, 0xaa, 0xe0, 0xd4, 0xc7, 0x78, 0xe0, 0x89, 0xe5, 0x57, 0x5a, + 0xa0, 0xb0, 0xf0, 0xf8, 0xbc, 0x03, 0x7d, 0x17, 0xfd, 0x54, 0xc8, 0xbc, 0xf2, 0x0d, 0x51, 0x74, 0x33, 0xf0, 0xee, + 0x23, 0xc9, 0x8c, 0x89, 0x47, 0x34, 0x39, 0xc7, 0xd2, 0x0b, 0xe1, 0x49, 0x5c, 0xdb, 0x68, 0x79, 0xb6, 0x8c, 0xfa, + 0x66, 0x93, 0x33, 0x5c, 0xec, 0xda, 0x6b, 0x72, 0xdd, 0x32, 0x30, 0x48, 0x3c, 0xb3, 0x62, 0x1f, 0x96, 0x5e, 0x22, + 0x59, 0xc8, 0x4e, 0x0e, 0x00, 0x3e, 0x88, 0xc2, 0x52, 0x62, 0x9c, 0x7c, 0x1d, 0x42, 0xbd, 0x78, 0x09, 0x99, 0x62, + 0xbd, 0x9e, 0x0a, 0x9e, 0x0f, 0x05, 0xcb, 0x3c, 0x78, 0x75, 0xa9, 0x4a, 0x9d, 0x97, 0xb1, 0x9b, 0x99, 0xc0, 0xdd, + 0xa9, 0x65, 0x7e, 0x5d, 0x63, 0x5e, 0x99, 0x6c, 0x90, 0x32, 0x11, 0xe4, 0xe0, 0x3c, 0x6d, 0x89, 0x83, 0xd0, 0x56, + 0x85, 0xf8, 0xd9, 0x2d, 0x15, 0x8a, 0x75, 0xbc, 0xad, 0x56, 0xc1, 0x39, 0xe5, 0xd5, 0x56, 0x9e, 0xa6, 0x3e, 0xc4, + 0x15, 0x5f, 0xab, 0x8d, 0xa5, 0x50, 0xef, 0x3c, 0x1d, 0x42, 0x55, 0xa1, 0x8b, 0xf7, 0x56, 0x2b, 0xaa, 0xac, 0x0f, + 0x4e, 0x0e, 0x48, 0x2c, 0x3d, 0xa5, 0x15, 0x76, 0x7a, 0x02, 0xa6, 0xdc, 0x34, 0xe9, 0xde, 0x6a, 0xc5, 0xa7, 0x94, + 0x7e, 0xd1, 0x9b, 0x83, 0x45, 0xba, 0x0c, 0x4e, 0xff, 0x1f, 0xca, 0xa4, 0xb6, 0xee, 0x1c, 0x64, 0x03, 0x00}; } // namespace web_server } // namespace esphome diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 1bb7c6c249..0467023039 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -105,6 +105,14 @@ void WebServer::setup() { // Configure reconnect timeout and send config client->send(this->get_config_json().c_str(), "ping", millis(), 30000); + for (auto &group : this->sorting_groups_) { + client->send(json::build_json([group](JsonObject root) { + root["name"] = group.second.name; + root["sorting_weight"] = group.second.weight; + }).c_str(), + "sorting_group"); + } + this->entities_iterator_.begin(this->include_internal_); }); @@ -219,9 +227,16 @@ void WebServer::handle_sensor_request(AsyncWebServerRequest *request, const UrlM for (sensor::Sensor *obj : App.get_sensors()) { if (obj->get_object_id() != match.id) continue; - std::string data = this->sensor_json(obj, obj->state, DETAIL_STATE); - request->send(200, "application/json", data.c_str()); - return; + if (request->method() == HTTP_GET && match.method.empty()) { + auto detail = DETAIL_STATE; + auto *param = request->getParam("detail"); + if (param && param->value() == "all") { + detail = DETAIL_ALL; + } + std::string data = this->sensor_json(obj, obj->state, detail); + request->send(200, "application/json", data.c_str()); + return; + } } request->send(404); } @@ -239,6 +254,9 @@ std::string WebServer::sensor_json(sensor::Sensor *obj, float value, JsonDetail if (start_config == DETAIL_ALL) { if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { root["sorting_weight"] = this->sorting_entitys_[obj].weight; + if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } if (!obj->get_unit_of_measurement().empty()) root["uom"] = obj->get_unit_of_measurement(); @@ -257,9 +275,16 @@ void WebServer::handle_text_sensor_request(AsyncWebServerRequest *request, const for (text_sensor::TextSensor *obj : App.get_text_sensors()) { if (obj->get_object_id() != match.id) continue; - std::string data = this->text_sensor_json(obj, obj->state, DETAIL_STATE); - request->send(200, "application/json", data.c_str()); - return; + if (request->method() == HTTP_GET && match.method.empty()) { + auto detail = DETAIL_STATE; + auto *param = request->getParam("detail"); + if (param && param->value() == "all") { + detail = DETAIL_ALL; + } + std::string data = this->text_sensor_json(obj, obj->state, detail); + request->send(200, "application/json", data.c_str()); + return; + } } request->send(404); } @@ -270,6 +295,9 @@ std::string WebServer::text_sensor_json(text_sensor::TextSensor *obj, const std: if (start_config == DETAIL_ALL) { if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { root["sorting_weight"] = this->sorting_entitys_[obj].weight; + if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } } }); @@ -288,7 +316,12 @@ void WebServer::handle_switch_request(AsyncWebServerRequest *request, const UrlM continue; if (request->method() == HTTP_GET && match.method.empty()) { - std::string data = this->switch_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->switch_json(obj, obj->state, detail); request->send(200, "application/json", data.c_str()); } else if (match.method == "toggle") { this->schedule_([obj]() { obj->toggle(); }); @@ -313,6 +346,9 @@ std::string WebServer::switch_json(switch_::Switch *obj, bool value, JsonDetail root["assumed_state"] = obj->assumed_state(); if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { root["sorting_weight"] = this->sorting_entitys_[obj].weight; + if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } } }); @@ -324,7 +360,15 @@ 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 (match.method == "press") { + if (request->method() == HTTP_GET && match.method.empty()) { + auto detail = DETAIL_STATE; + auto *param = request->getParam("detail"); + if (param && param->value() == "all") { + detail = DETAIL_ALL; + } + std::string data = this->button_json(obj, detail); + request->send(200, "application/json", data.c_str()); + } else if (match.method == "press") { this->schedule_([obj]() { obj->press(); }); request->send(200); return; @@ -341,6 +385,9 @@ std::string WebServer::button_json(button::Button *obj, JsonDetail 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 (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } } }); @@ -357,9 +404,16 @@ void WebServer::handle_binary_sensor_request(AsyncWebServerRequest *request, con for (binary_sensor::BinarySensor *obj : App.get_binary_sensors()) { if (obj->get_object_id() != match.id) continue; - std::string data = this->binary_sensor_json(obj, obj->state, DETAIL_STATE); - request->send(200, "application/json", data.c_str()); - return; + if (request->method() == HTTP_GET && match.method.empty()) { + auto detail = DETAIL_STATE; + auto *param = request->getParam("detail"); + if (param && param->value() == "all") { + detail = DETAIL_ALL; + } + std::string data = this->binary_sensor_json(obj, obj->state, detail); + request->send(200, "application/json", data.c_str()); + return; + } } request->send(404); } @@ -370,6 +424,9 @@ std::string WebServer::binary_sensor_json(binary_sensor::BinarySensor *obj, bool if (start_config == DETAIL_ALL) { if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { root["sorting_weight"] = this->sorting_entitys_[obj].weight; + if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } } }); @@ -388,7 +445,12 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc continue; if (request->method() == HTTP_GET && match.method.empty()) { - std::string data = this->fan_json(obj, DETAIL_STATE); + auto detail = DETAIL_STATE; + auto *param = request->getParam("detail"); + if (param && param->value() == "all") { + detail = DETAIL_ALL; + } + std::string data = this->fan_json(obj, detail); request->send(200, "application/json", data.c_str()); } else if (match.method == "toggle") { this->schedule_([obj]() { obj->toggle().perform(); }); @@ -448,6 +510,9 @@ std::string WebServer::fan_json(fan::Fan *obj, JsonDetail 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 (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } } }); @@ -466,7 +531,12 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa continue; if (request->method() == HTTP_GET && match.method.empty()) { - std::string data = this->light_json(obj, DETAIL_STATE); + auto detail = DETAIL_STATE; + auto *param = request->getParam("detail"); + if (param && param->value() == "all") { + detail = DETAIL_ALL; + } + std::string data = this->light_json(obj, detail); request->send(200, "application/json", data.c_str()); } else if (match.method == "toggle") { this->schedule_([obj]() { obj->toggle().perform(); }); @@ -559,6 +629,9 @@ std::string WebServer::light_json(light::LightState *obj, JsonDetail start_confi } if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { root["sorting_weight"] = this->sorting_entitys_[obj].weight; + if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } } }); @@ -577,9 +650,14 @@ void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMa continue; if (request->method() == HTTP_GET && match.method.empty()) { - std::string data = this->cover_json(obj, DETAIL_STATE); + auto detail = DETAIL_STATE; + auto *param = request->getParam("detail"); + if (param && param->value() == "all") { + detail = DETAIL_ALL; + } + std::string data = this->cover_json(obj, detail); request->send(200, "application/json", data.c_str()); - continue; + return; } auto call = obj->make_call(); @@ -635,6 +713,9 @@ std::string WebServer::cover_json(cover::Cover *obj, JsonDetail 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 (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } } }); @@ -653,7 +734,12 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM continue; if (request->method() == HTTP_GET && match.method.empty()) { - std::string data = this->number_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->number_json(obj, obj->state, detail); request->send(200, "application/json", data.c_str()); return; } @@ -691,6 +777,9 @@ std::string WebServer::number_json(number::Number *obj, float value, JsonDetail 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 (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } } if (std::isnan(value)) { @@ -717,8 +806,13 @@ void WebServer::handle_date_request(AsyncWebServerRequest *request, const UrlMat for (auto *obj : App.get_dates()) { if (obj->get_object_id() != match.id) continue; - if (request->method() == HTTP_GET) { - std::string data = this->date_json(obj, DETAIL_STATE); + if (request->method() == HTTP_GET && match.method.empty()) { + auto detail = DETAIL_STATE; + auto *param = request->getParam("detail"); + if (param && param->value() == "all") { + detail = DETAIL_ALL; + } + std::string data = this->date_json(obj, detail); request->send(200, "application/json", data.c_str()); return; } @@ -755,6 +849,9 @@ std::string WebServer::date_json(datetime::DateEntity *obj, JsonDetail start_con if (start_config == DETAIL_ALL) { if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { root["sorting_weight"] = this->sorting_entitys_[obj].weight; + if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } } }); @@ -772,7 +869,12 @@ void WebServer::handle_time_request(AsyncWebServerRequest *request, const UrlMat 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); + auto detail = DETAIL_STATE; + auto *param = request->getParam("detail"); + if (param && param->value() == "all") { + detail = DETAIL_ALL; + } + std::string data = this->time_json(obj, detail); request->send(200, "application/json", data.c_str()); return; } @@ -808,6 +910,9 @@ std::string WebServer::time_json(datetime::TimeEntity *obj, JsonDetail start_con if (start_config == DETAIL_ALL) { if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { root["sorting_weight"] = this->sorting_entitys_[obj].weight; + if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } } }); @@ -825,7 +930,12 @@ void WebServer::handle_datetime_request(AsyncWebServerRequest *request, const Ur 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); + auto detail = DETAIL_STATE; + auto *param = request->getParam("detail"); + if (param && param->value() == "all") { + detail = DETAIL_ALL; + } + std::string data = this->datetime_json(obj, detail); request->send(200, "application/json", data.c_str()); return; } @@ -862,6 +972,9 @@ std::string WebServer::datetime_json(datetime::DateTimeEntity *obj, JsonDetail s if (start_config == DETAIL_ALL) { if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { root["sorting_weight"] = this->sorting_entitys_[obj].weight; + if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } } }); @@ -880,8 +993,13 @@ void WebServer::handle_text_request(AsyncWebServerRequest *request, const UrlMat continue; 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()); + auto detail = DETAIL_STATE; + auto *param = request->getParam("detail"); + if (param && param->value() == "all") { + detail = DETAIL_ALL; + } + std::string data = this->text_json(obj, obj->state, detail); + request->send(200, "application/json", data.c_str()); return; } if (match.method != "set") { @@ -918,6 +1036,9 @@ std::string WebServer::text_json(text::Text *obj, const std::string &value, Json 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; + if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } } }); @@ -974,6 +1095,9 @@ std::string WebServer::select_json(select::Select *obj, const std::string &value } if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { root["sorting_weight"] = this->sorting_entitys_[obj].weight; + if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } } }); @@ -995,11 +1119,15 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url continue; if (request->method() == HTTP_GET && match.method.empty()) { - std::string data = this->climate_json(obj, DETAIL_STATE); + auto detail = DETAIL_STATE; + auto *param = request->getParam("detail"); + if (param && param->value() == "all") { + detail = DETAIL_ALL; + } + std::string data = this->climate_json(obj, detail); request->send(200, "application/json", data.c_str()); return; } - if (match.method != "set") { request->send(404); return; @@ -1012,6 +1140,16 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url call.set_mode(mode.c_str()); } + if (request->hasParam("fan_mode")) { + auto mode = request->getParam("fan_mode")->value(); + call.set_fan_mode(mode.c_str()); + } + + if (request->hasParam("swing_mode")) { + auto mode = request->getParam("swing_mode")->value(); + call.set_swing_mode(mode.c_str()); + } + if (request->hasParam("target_temperature_high")) { auto target_temperature_high = parse_number(request->getParam("target_temperature_high")->value().c_str()); if (target_temperature_high.has_value()) @@ -1076,6 +1214,9 @@ std::string WebServer::climate_json(climate::Climate *obj, JsonDetail start_conf } if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { root["sorting_weight"] = this->sorting_entitys_[obj].weight; + if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } } @@ -1139,7 +1280,12 @@ void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMat continue; if (request->method() == HTTP_GET && match.method.empty()) { - std::string data = this->lock_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->lock_json(obj, obj->state, detail); request->send(200, "application/json", data.c_str()); } else if (match.method == "lock") { this->schedule_([obj]() { obj->lock(); }); @@ -1164,6 +1310,9 @@ std::string WebServer::lock_json(lock::Lock *obj, lock::LockState value, JsonDet if (start_config == DETAIL_ALL) { if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { root["sorting_weight"] = this->sorting_entitys_[obj].weight; + if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } } }); @@ -1182,9 +1331,14 @@ void WebServer::handle_valve_request(AsyncWebServerRequest *request, const UrlMa continue; if (request->method() == HTTP_GET && match.method.empty()) { - std::string data = this->valve_json(obj, DETAIL_STATE); + auto detail = DETAIL_STATE; + auto *param = request->getParam("detail"); + if (param && param->value() == "all") { + detail = DETAIL_ALL; + } + std::string data = this->valve_json(obj, detail); request->send(200, "application/json", data.c_str()); - continue; + return; } auto call = obj->make_call(); @@ -1228,8 +1382,13 @@ std::string WebServer::valve_json(valve::Valve *obj, JsonDetail start_config) { 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; + if (start_config == DETAIL_ALL) { + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } + } } }); } @@ -1247,7 +1406,12 @@ void WebServer::handle_alarm_control_panel_request(AsyncWebServerRequest *reques continue; if (request->method() == HTTP_GET && match.method.empty()) { - std::string data = this->alarm_control_panel_json(obj, obj->get_state(), DETAIL_STATE); + auto detail = DETAIL_STATE; + auto *param = request->getParam("detail"); + if (param && param->value() == "all") { + detail = DETAIL_ALL; + } + std::string data = this->alarm_control_panel_json(obj, obj->get_state(), detail); request->send(200, "application/json", data.c_str()); return; } @@ -1264,6 +1428,9 @@ std::string WebServer::alarm_control_panel_json(alarm_control_panel::AlarmContro if (start_config == DETAIL_ALL) { if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { root["sorting_weight"] = this->sorting_entitys_[obj].weight; + if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } } }); @@ -1274,9 +1441,26 @@ std::string WebServer::alarm_control_panel_json(alarm_control_panel::AlarmContro 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"); } +void WebServer::handle_event_request(AsyncWebServerRequest *request, const UrlMatch &match) { + for (event::Event *obj : App.get_events()) { + if (obj->get_object_id() != match.id) + continue; + if (request->method() == HTTP_GET && match.method.empty()) { + auto detail = DETAIL_STATE; + auto *param = request->getParam("detail"); + if (param && param->value() == "all") { + detail = DETAIL_ALL; + } + std::string data = this->event_json(obj, "", detail); + request->send(200, "application/json", data.c_str()); + return; + } + } + request->send(404); +} 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) { + return json::build_json([this, 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; @@ -1287,6 +1471,12 @@ std::string WebServer::event_json(event::Event *obj, const std::string &event_ty event_types.add(event_type); } root["device_class"] = obj->get_device_class(); + if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) { + root["sorting_weight"] = this->sorting_entitys_[obj].weight; + if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } + } } }); } @@ -1304,7 +1494,12 @@ void WebServer::handle_update_request(AsyncWebServerRequest *request, const UrlM continue; if (request->method() == HTTP_GET && match.method.empty()) { - std::string data = this->update_json(obj, DETAIL_STATE); + auto detail = DETAIL_STATE; + auto *param = request->getParam("detail"); + if (param && param->value() == "all") { + detail = DETAIL_ALL; + } + std::string data = this->update_json(obj, detail); request->send(200, "application/json", data.c_str()); return; } @@ -1345,6 +1540,9 @@ std::string WebServer::update_json(update::UpdateEntity *obj, JsonDetail start_c 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; + if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) { + root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name; + } } } }); @@ -1470,6 +1668,11 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) { return true; #endif +#ifdef USE_EVENT + if (request->method() == HTTP_GET && match.domain == "event") + return true; +#endif + #ifdef USE_UPDATE if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain == "update") return true; @@ -1643,8 +1846,12 @@ 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::add_entity_config(EntityBase *entity, float weight, uint64_t group) { + this->sorting_entitys_[entity] = SortingComponents{weight, group}; +} + +void WebServer::add_sorting_group(uint64_t group_id, const std::string &group_name, float weight) { + this->sorting_groups_[group_id] = SortingGroup{group_name, weight}; } void WebServer::schedule_(std::function &&f) { diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 3195fa7109..8edb678169 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -44,6 +44,12 @@ struct UrlMatch { struct SortingComponents { float weight; + uint64_t group_id; +}; + +struct SortingGroup { + std::string name; + float weight; }; enum JsonDetail { DETAIL_ALL, DETAIL_STATE }; @@ -316,6 +322,9 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { #ifdef USE_EVENT void on_event(event::Event *obj, const std::string &event_type) override; + /// Handle a event request under '/event'. + void handle_event_request(AsyncWebServerRequest *request, const UrlMatch &match); + /// 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 @@ -337,7 +346,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// This web handle is not trivial. bool isRequestHandlerTrivial() override; // NOLINT(readability-identifier-naming) - void add_entity_to_sorting_list(EntityBase *entity, float weight); + void add_entity_config(EntityBase *entity, float weight, uint64_t group); + void add_sorting_group(uint64_t group_id, const std::string &group_name, float weight); protected: void schedule_(std::function &&f); @@ -346,6 +356,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { AsyncEventSource events_{"/events"}; ListEntitiesIterator entities_iterator_; std::map sorting_entitys_; + std::map sorting_groups_; + #if USE_WEBSERVER_VERSION == 1 const char *css_url_{nullptr}; const char *js_url_{nullptr}; diff --git a/esphome/components/weikai/weikai.h b/esphome/components/weikai/weikai.h index 042c729162..175a067b27 100644 --- a/esphome/components/weikai/weikai.h +++ b/esphome/components/weikai/weikai.h @@ -209,7 +209,7 @@ class WeikaiComponent : public Component { /// @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); } + void set_name(std::string &&name) { this->name_ = std::move(name); } /// @brief Get the name of the component /// @return the name @@ -308,7 +308,7 @@ class WeikaiChannel : public uart::UARTComponent { /// @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); } + void set_channel_name(std::string &&name) { this->name_ = std::move(name); } /// @brief Get the channel name /// @return the name diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 583a27466a..8788711d5a 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -297,8 +297,8 @@ void WiFiComponent::set_sta(const WiFiAP &ap) { void WiFiComponent::clear_sta() { this->sta_.clear(); } void WiFiComponent::save_wifi_sta(const std::string &ssid, const std::string &password) { SavedWifiSettings save{}; - strncpy(save.ssid, ssid.c_str(), sizeof(save.ssid)); - strncpy(save.password, password.c_str(), sizeof(save.password)); + snprintf(save.ssid, sizeof(save.ssid), "%s", ssid.c_str()); + snprintf(save.password, sizeof(save.password), "%s", password.c_str()); this->pref_.save(&save); // ensure it's written immediately global_preferences->sync(); diff --git a/esphome/components/wifi/wifi_component_esp32_arduino.cpp b/esphome/components/wifi/wifi_component_esp32_arduino.cpp index b8724838c8..88648093c6 100644 --- a/esphome/components/wifi/wifi_component_esp32_arduino.cpp +++ b/esphome/components/wifi/wifi_component_esp32_arduino.cpp @@ -34,6 +34,11 @@ static esp_netif_t *s_ap_netif = nullptr; // NOLINT(cppcoreguidelines-avoid-non static bool s_sta_connecting = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) void WiFiComponent::wifi_pre_setup_() { + uint8_t mac[6]; + if (has_custom_mac_address()) { + get_mac_address_raw(mac); + set_mac_address(mac); + } auto f = std::bind(&WiFiComponent::wifi_event_callback_, this, std::placeholders::_1, std::placeholders::_2); WiFi.onEvent(f); WiFi.persistent(false); @@ -132,8 +137,8 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html#_CPPv417wifi_sta_config_t wifi_config_t conf; memset(&conf, 0, sizeof(conf)); - strncpy(reinterpret_cast(conf.sta.ssid), ap.get_ssid().c_str(), sizeof(conf.sta.ssid)); - strncpy(reinterpret_cast(conf.sta.password), ap.get_password().c_str(), sizeof(conf.sta.password)); + snprintf(reinterpret_cast(conf.sta.ssid), sizeof(conf.sta.ssid), "%s", ap.get_ssid().c_str()); + snprintf(reinterpret_cast(conf.sta.password), sizeof(conf.sta.password), "%s", ap.get_password().c_str()); // The weakest authmode to accept in the fast scan mode if (ap.get_password().empty()) { @@ -741,7 +746,7 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { wifi_config_t conf; memset(&conf, 0, sizeof(conf)); - strncpy(reinterpret_cast(conf.ap.ssid), ap.get_ssid().c_str(), sizeof(conf.ap.ssid)); + snprintf(reinterpret_cast(conf.ap.ssid), sizeof(conf.ap.ssid), "%s", ap.get_ssid().c_str()); conf.ap.channel = ap.get_channel().value_or(1); conf.ap.ssid_hidden = ap.get_ssid().size(); conf.ap.max_connection = 5; @@ -752,7 +757,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.password)); + snprintf(reinterpret_cast(conf.ap.password), sizeof(conf.ap.password), "%s", ap.get_password().c_str()); } // pairwise cipher of SoftAP, group cipher will be derived using this. diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 92f80c1e52..4568895950 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -236,8 +236,8 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { struct station_config conf {}; memset(&conf, 0, sizeof(conf)); - strncpy(reinterpret_cast(conf.ssid), ap.get_ssid().c_str(), sizeof(conf.ssid)); - strncpy(reinterpret_cast(conf.password), ap.get_password().c_str(), sizeof(conf.password)); + snprintf(reinterpret_cast(conf.ssid), sizeof(conf.ssid), "%s", ap.get_ssid().c_str()); + snprintf(reinterpret_cast(conf.password), sizeof(conf.password), "%s", ap.get_password().c_str()); if (ap.get_bssid().has_value()) { conf.bssid_set = 1; @@ -775,7 +775,7 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { return false; struct softap_config conf {}; - strncpy(reinterpret_cast(conf.ssid), ap.get_ssid().c_str(), sizeof(conf.ssid)); + snprintf(reinterpret_cast(conf.ssid), sizeof(conf.ssid), "%s", ap.get_ssid().c_str()); conf.ssid_len = static_cast(ap.get_ssid().size()); conf.channel = ap.get_channel().value_or(1); conf.ssid_hidden = ap.get_hidden(); @@ -787,7 +787,7 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { *conf.password = 0; } else { conf.authmode = AUTH_WPA2_PSK; - strncpy(reinterpret_cast(conf.password), ap.get_password().c_str(), sizeof(conf.password)); + snprintf(reinterpret_cast(conf.password), sizeof(conf.password), "%s", ap.get_password().c_str()); } ETS_UART_INTR_DISABLE(); diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 6008acb95d..13870136d4 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -130,12 +130,11 @@ void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, voi } void WiFiComponent::wifi_pre_setup_() { -#ifdef USE_ESP32_IGNORE_EFUSE_MAC_CRC uint8_t mac[6]; - get_mac_address_raw(mac); - set_mac_address(mac); - ESP_LOGV(TAG, "Use EFuse MAC without checking CRC: %s", get_mac_address_pretty().c_str()); -#endif + if (has_custom_mac_address()) { + get_mac_address_raw(mac); + set_mac_address(mac); + } esp_err_t err = esp_netif_init(); if (err != ERR_OK) { ESP_LOGE(TAG, "esp_netif_init failed: %s", esp_err_to_name(err)); @@ -290,8 +289,8 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html#_CPPv417wifi_sta_config_t wifi_config_t conf; memset(&conf, 0, sizeof(conf)); - strncpy(reinterpret_cast(conf.sta.ssid), ap.get_ssid().c_str(), sizeof(conf.sta.ssid)); - strncpy(reinterpret_cast(conf.sta.password), ap.get_password().c_str(), sizeof(conf.sta.password)); + snprintf(reinterpret_cast(conf.sta.ssid), sizeof(conf.sta.ssid), "%s", ap.get_ssid().c_str()); + snprintf(reinterpret_cast(conf.sta.password), sizeof(conf.sta.password), "%s", ap.get_password().c_str()); // The weakest authmode to accept in the fast scan mode if (ap.get_password().empty()) { 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/esphome/config.py b/esphome/config.py index a2d0d15477..7d48569d2d 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -782,7 +782,7 @@ def validate_config( from esphome.components import substitutions result[CONF_SUBSTITUTIONS] = { - **config.get(CONF_SUBSTITUTIONS, {}), + **(config.get(CONF_SUBSTITUTIONS) or {}), **command_line_substitutions, } result.add_output_path([CONF_SUBSTITUTIONS], CONF_SUBSTITUTIONS) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 719cc43b31..98b81ec328 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -40,6 +40,7 @@ from esphome.const import ( CONF_SECOND, CONF_SETUP_PRIORITY, CONF_STATE_TOPIC, + CONF_SUBSCRIBE_QOS, CONF_TOPIC, CONF_TYPE, CONF_TYPE_ID, @@ -750,6 +751,7 @@ def time_period_str_unit(value): "ns": "nanoseconds", "nanoseconds": "nanoseconds", "us": "microseconds", + "µs": "microseconds", "microseconds": "microseconds", "ms": "milliseconds", "milliseconds": "milliseconds", @@ -1892,9 +1894,10 @@ MQTT_COMPONENT_AVAILABILITY_SCHEMA = Schema( MQTT_COMPONENT_SCHEMA = Schema( { - Optional(CONF_QOS): All(requires_component("mqtt"), int_range(min=0, max=2)), + Optional(CONF_QOS): All(requires_component("mqtt"), mqtt_qos), Optional(CONF_RETAIN): All(requires_component("mqtt"), boolean), Optional(CONF_DISCOVERY): All(requires_component("mqtt"), boolean), + Optional(CONF_SUBSCRIBE_QOS): All(requires_component("mqtt"), mqtt_qos), Optional(CONF_STATE_TOPIC): All(requires_component("mqtt"), publish_topic), Optional(CONF_AVAILABILITY): All( requires_component("mqtt"), Any(None, MQTT_COMPONENT_AVAILABILITY_SCHEMA) @@ -2045,6 +2048,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 +2063,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" diff --git a/esphome/const.py b/esphome/const.py index 95773630d0..c39061631b 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.9.0-dev" +__version__ = "2024.11.0-dev" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( @@ -44,17 +44,21 @@ 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" CONF_AFTER = "after" +CONF_ALL = "all" CONF_ALLOW_OTHER_USES = "allow_other_uses" CONF_ALPHA = "alpha" CONF_ALTITUDE = "altitude" CONF_AMBIENT_LIGHT = "ambient_light" +CONF_AMMONIA = "ammonia" CONF_ANALOG = "analog" CONF_AND = "and" CONF_ANGLE = "angle" +CONF_ANY = "any" CONF_AP = "ap" CONF_APPARENT_POWER = "apparent_power" CONF_ARDUINO_VERSION = "arduino_version" @@ -109,6 +113,7 @@ CONF_CALIBRATE_LINEAR = "calibrate_linear" CONF_CALIBRATION = "calibration" CONF_CAPACITANCE = "capacitance" CONF_CAPACITY = "capacity" +CONF_CARBON_MONOXIDE = "carbon_monoxide" CONF_CARRIER_DUTY_PERCENT = "carrier_duty_percent" CONF_CARRIER_FREQUENCY = "carrier_frequency" CONF_CERTIFICATE = "certificate" @@ -119,6 +124,7 @@ CONF_CHANNELS = "channels" CONF_CHARACTERISTIC_UUID = "characteristic_uuid" CONF_CHECK = "check" CONF_CHIPSET = "chipset" +CONF_CLEAN_SESSION = "clean_session" CONF_CLEAR_IMPEDANCE = "clear_impedance" CONF_CLIENT_CERTIFICATE = "client_certificate" CONF_CLIENT_CERTIFICATE_KEY = "client_certificate_key" @@ -261,6 +267,7 @@ CONF_ENUM_DATAPOINT = "enum_datapoint" CONF_EQUATION = "equation" CONF_ESP8266_DISABLE_SSL_SUPPORT = "esp8266_disable_ssl_support" CONF_ESPHOME = "esphome" +CONF_ETHANOL = "ethanol" CONF_ETHERNET = "ethernet" CONF_EVENT = "event" CONF_EVENT_TYPE = "event_type" @@ -323,6 +330,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" @@ -358,6 +366,7 @@ CONF_HOURS = "hours" CONF_HSYNC_PIN = "hsync_pin" CONF_HUMIDITY = "humidity" CONF_HUMIDITY_SENSOR = "humidity_sensor" +CONF_HYDROGEN = "hydrogen" CONF_HYSTERESIS = "hysteresis" CONF_I2C = "i2c" CONF_I2C_ID = "i2c_id" @@ -373,6 +382,7 @@ CONF_IDLE_ACTION = "idle_action" CONF_IDLE_LEVEL = "idle_level" CONF_IDLE_TIME = "idle_time" CONF_IF = "if" +CONF_IGNORE_EFUSE_CUSTOM_MAC = "ignore_efuse_custom_mac" 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" @@ -388,8 +398,10 @@ CONF_INCLUDES = "includes" CONF_INDEX = "index" CONF_INDOOR = "indoor" CONF_INFRARED = "infrared" +CONF_INIT_SEQUENCE = "init_sequence" CONF_INITIAL_MODE = "initial_mode" CONF_INITIAL_OPTION = "initial_option" +CONF_INITIAL_STATE = "initial_state" CONF_INITIAL_VALUE = "initial_value" CONF_INPUT = "input" CONF_INTEGRATION_TIME = "integration_time" @@ -473,6 +485,7 @@ CONF_MEDIA_PLAYER = "media_player" CONF_MEDIUM = "medium" CONF_MEMORY_BLOCKS = "memory_blocks" CONF_MESSAGE = "message" +CONF_METHANE = "methane" CONF_METHOD = "method" CONF_MICROPHONE = "microphone" CONF_MIN_BRIGHTNESS = "min_brightness" @@ -519,6 +532,7 @@ CONF_NBITS = "nbits" CONF_NEC = "nec" CONF_NETWORKS = "networks" CONF_NEW_PASSWORD = "new_password" +CONF_NITROGEN_DIOXIDE = "nitrogen_dioxide" CONF_NOISE_LEVEL = "noise_level" CONF_NUM_ATTEMPTS = "num_attempts" CONF_NUM_CHANNELS = "num_channels" @@ -652,6 +666,7 @@ CONF_PMC_1_0 = "pmc_1_0" CONF_PMC_10_0 = "pmc_10_0" CONF_PMC_2_5 = "pmc_2_5" CONF_PMC_4_0 = "pmc_4_0" +CONF_POLLING_INTERVAL = "polling_interval" CONF_PORT = "port" CONF_POSITION = "position" CONF_POSITION_ACTION = "position_action" @@ -805,6 +820,7 @@ CONF_STOP = "stop" CONF_STOP_ACTION = "stop_action" CONF_STORE_BASELINE = "store_baseline" CONF_SUBNET = "subnet" +CONF_SUBSCRIBE_QOS = "subscribe_qos" CONF_SUBSTITUTIONS = "substitutions" CONF_SUM = "sum" CONF_SUPPLEMENTAL_COOLING_ACTION = "supplemental_cooling_action" @@ -850,6 +866,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" @@ -923,7 +940,6 @@ 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" @@ -951,6 +967,7 @@ ICON_ACCELERATION_Y = "mdi:axis-y-arrow" ICON_ACCELERATION_Z = "mdi:axis-z-arrow" ICON_ACCOUNT = "mdi:account" ICON_ACCOUNT_CHECK = "mdi:account-check" +ICON_AIR_FILTER = "mdi:air-filter" ICON_ARROW_EXPAND_VERTICAL = "mdi:arrow-expand-vertical" ICON_BATTERY = "mdi:battery" ICON_BLUETOOTH = "mdi:bluetooth" @@ -972,6 +989,7 @@ ICON_FINGERPRINT = "mdi:fingerprint" ICON_FLASH = "mdi:flash" ICON_FLASK = "mdi:flask" ICON_FLASK_OUTLINE = "mdi:flask-outline" +ICON_FLASK_ROUND_BOTTOM = "mdi:flask-round-bottom" ICON_FLOWER = "mdi:flower" ICON_GAS_CYLINDER = "mdi:gas-cylinder" ICON_GAUGE = "mdi:gauge" @@ -984,6 +1002,7 @@ ICON_KEY_PLUS = "mdi:key-plus" ICON_LIGHTBULB = "mdi:lightbulb" ICON_MAGNET = "mdi:magnet" ICON_MEMORY = "mdi:memory" +ICON_MOLECULE_CO = "mdi:molecule-co" ICON_MOLECULE_CO2 = "mdi:molecule-co2" ICON_MOTION_SENSOR = "mdi:motion-sensor" ICON_NEW_BOX = "mdi:new-box" diff --git a/esphome/core/bytebuffer.cpp b/esphome/core/bytebuffer.cpp deleted file mode 100644 index 9dd32bf87a..0000000000 --- a/esphome/core/bytebuffer.cpp +++ /dev/null @@ -1,167 +0,0 @@ -#include "bytebuffer.h" -#include -#include "esphome/core/helpers.h" - -#include -#include - -namespace esphome { - -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); - ByteBuffer buffer = {data}; - buffer.endianness_ = endianness; - return buffer; -} - -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()); - 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; -} -void ByteBuffer::flip() { - this->limit_ = this->position_; - this->position_ = 0; -} - -/// Getters -uint8_t ByteBuffer::get_uint8() { - assert(this->get_remaining() >= 1); - return this->data_[this->position_++]; -} -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)); - return bit_cast(this->get_uint32()); -} -double ByteBuffer::get_double() { - assert(this->get_remaining() >= sizeof(double)); - 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_; - 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_uint(uint64_t value, size_t length) { - assert(this->get_remaining() >= length); - if (this->endianness_ == LITTLE) { - while (length-- != 0) { - this->data_[this->position_++] = static_cast(value); - value >>= 8; - } - } else { - this->position_ += length; - auto index = this->position_; - while (length-- != 0) { - this->data_[--index] = static_cast(value); - value >>= 8; - } - } -} -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)); - 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)); - this->put_uint64(bit_cast(value)); -} -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 deleted file mode 100644 index d44d01f275..0000000000 --- a/esphome/core/bytebuffer.h +++ /dev/null @@ -1,144 +0,0 @@ -#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: - * - * 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 - */ - ByteBuffer(size_t capacity, Endian endianness = LITTLE) - : data_(std::vector(capacity)), endianness_(endianness), limit_(capacity){}; - /** - * Wrap an existing vector in a ByteBufffer - */ - static ByteBuffer wrap(std::vector const &data, Endian endianness = LITTLE); - /** - * Wrap an existing array in a ByteBuffer. Note that this will create a copy of the data. - */ - 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() { return static_cast(this->get_uint(sizeof(uint16_t))); }; - // Get a 24 bit unsigned value, increment by 3 - uint32_t get_uint24() { return static_cast(this->get_uint(3)); }; - // Get a 32 bit unsigned value, increment by 4 - 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 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 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) { 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_; } - 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. - std::vector get_data() { return this->data_; }; - void rewind() { this->position_ = 0; } - void reset() { this->position_ = this->mark_; } - - protected: - ByteBuffer(std::vector const &data) : data_(data), limit_(data.size()) {} - std::vector data_; - Endian endianness_{LITTLE}; - size_t position_{0}; - size_t mark_{0}; - size_t limit_{0}; -}; - -} // namespace esphome diff --git a/esphome/core/config.py b/esphome/core/config.py index 739a8a1aea..8c130eb6db 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 @@ -321,6 +318,8 @@ async def add_includes(includes): async def _add_platformio_options(pio_options): # Add includes at the very end, so that they override everything for key, val in pio_options.items(): + if key == "build_flags" and not isinstance(val, list): + val = [val] cg.add_platformio_option(key, val) diff --git a/esphome/core/defines.h b/esphome/core/defines.h index ffd5cc6f1b..b5511b57eb 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -29,6 +29,7 @@ #define USE_DATETIME_TIME #define USE_DEEP_SLEEP #define USE_DISPLAY +#define USE_ESP32_IMPROV_STATE_CALLBACK #define USE_EVENT #define USE_FAN #define USE_GRAPH @@ -43,12 +44,15 @@ #define USE_LVGL_ANIMIMG #define USE_LVGL_BINARY_SENSOR #define USE_LVGL_BUTTONMATRIX +#define USE_LVGL_DROPDOWN #define USE_LVGL_FONT #define USE_LVGL_IMAGE -#define USE_LVGL_KEYBOARD #define USE_LVGL_KEY_LISTENER -#define USE_LVGL_TOUCHSCREEN +#define USE_LVGL_KEYBOARD +#define USE_LVGL_ROLLER #define USE_LVGL_ROTARY_ENCODER +#define USE_LVGL_TOUCHSCREEN +#define USE_MD5 #define USE_MDNS #define USE_MEDIA_PLAYER #define USE_MQTT diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index e75b06ccd3..8f94f624f1 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef USE_HOST #ifndef _WIN32 @@ -44,9 +45,7 @@ #endif #ifdef USE_ESP32 #include "esp32/rom/crc.h" -#endif -#if defined(CONFIG_SOC_IEEE802154_SUPPORTED) || defined(USE_ESP32_IGNORE_EFUSE_MAC_CRC) #include "esp_efuse.h" #include "esp_efuse_table.h" #endif @@ -190,37 +189,39 @@ uint32_t fnv1_hash(const std::string &str) { return hash; } -uint32_t random_uint32() { #ifdef USE_ESP32 - return esp_random(); +uint32_t random_uint32() { return esp_random(); } #elif defined(USE_ESP8266) - return os_random(); +uint32_t random_uint32() { return os_random(); } #elif defined(USE_RP2040) +uint32_t random_uint32() { uint32_t result = 0; for (uint8_t i = 0; i < 32; i++) { result <<= 1; result |= rosc_hw->randombit; } return result; +} #elif defined(USE_LIBRETINY) - return rand(); +uint32_t random_uint32() { return rand(); } #elif defined(USE_HOST) +uint32_t random_uint32() { std::random_device dev; std::mt19937 rng(dev()); std::uniform_int_distribution dist(0, std::numeric_limits::max()); return dist(rng); -#else -#error "No random source available for this configuration." -#endif } +#endif float random_float() { return static_cast(random_uint32()) / static_cast(UINT32_MAX); } -bool random_bytes(uint8_t *data, size_t len) { #ifdef USE_ESP32 +bool random_bytes(uint8_t *data, size_t len) { esp_fill_random(data, len); return true; +} #elif defined(USE_ESP8266) - return os_get_random(data, len) == 0; +bool random_bytes(uint8_t *data, size_t len) { return os_get_random(data, len) == 0; } #elif defined(USE_RP2040) +bool random_bytes(uint8_t *data, size_t len) { while (len-- != 0) { uint8_t result = 0; for (uint8_t i = 0; i < 8; i++) { @@ -230,10 +231,14 @@ bool random_bytes(uint8_t *data, size_t len) { *data++ = result; } return true; +} #elif defined(USE_LIBRETINY) +bool random_bytes(uint8_t *data, size_t len) { lt_rand_bytes(data, len); return true; +} #elif defined(USE_HOST) +bool random_bytes(uint8_t *data, size_t len) { FILE *fp = fopen("/dev/urandom", "r"); if (fp == nullptr) { ESP_LOGW(TAG, "Could not open /dev/urandom, errno=%d", errno); @@ -246,10 +251,8 @@ bool random_bytes(uint8_t *data, size_t len) { } fclose(fp); return true; -#else -#error "No random source available for this configuration." -#endif } +#endif // Strings @@ -621,11 +624,13 @@ void hsv_to_rgb(int hue, float saturation, float value, float &red, float &green #if defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_HOST) // ESP8266 doesn't have mutexes, but that shouldn't be an issue as it's single-core and non-preemptive OS. Mutex::Mutex() {} +Mutex::~Mutex() {} void Mutex::lock() {} bool Mutex::try_lock() { return true; } void Mutex::unlock() {} #elif defined(USE_ESP32) || defined(USE_LIBRETINY) Mutex::Mutex() { handle_ = xSemaphoreCreateMutex(); } +Mutex::~Mutex() {} void Mutex::lock() { xSemaphoreTake(this->handle_, portMAX_DELAY); } bool Mutex::try_lock() { return xSemaphoreTake(this->handle_, 0) == pdTRUE; } void Mutex::unlock() { xSemaphoreGive(this->handle_); } @@ -659,46 +664,90 @@ void HighFrequencyLoopRequester::stop() { } bool HighFrequencyLoopRequester::is_high_frequency() { return num_requests > 0; } -void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter) #if defined(USE_HOST) +void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter) static const uint8_t esphome_host_mac_address[6] = USE_ESPHOME_HOST_MAC_ADDRESS; memcpy(mac, esphome_host_mac_address, sizeof(esphome_host_mac_address)); +} #elif defined(USE_ESP32) -#if defined(CONFIG_SOC_IEEE802154_SUPPORTED) || defined(USE_ESP32_IGNORE_EFUSE_MAC_CRC) +void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter) +#if defined(CONFIG_SOC_IEEE802154_SUPPORTED) // When CONFIG_SOC_IEEE802154_SUPPORTED is defined, esp_efuse_mac_get_default - // returns the 802.15.4 EUI-64 address. Read directly from eFuse instead. - // On some devices, the MAC address that is burnt into EFuse does not - // match the CRC that goes along with it. For those devices, this - // work-around reads and uses the MAC address as-is from EFuse, - // without doing the CRC check. - esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, mac, 48); + // returns the 802.15.4 EUI-64 address, so we read directly from eFuse instead. + if (has_custom_mac_address()) { + esp_efuse_read_field_blob(ESP_EFUSE_MAC_CUSTOM, mac, 48); + } else { + esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, mac, 48); + } #else - esp_efuse_mac_get_default(mac); -#endif -#elif defined(USE_ESP8266) - wifi_get_macaddr(STATION_IF, mac); -#elif defined(USE_RP2040) && defined(USE_WIFI) - WiFi.macAddress(mac); -#elif defined(USE_LIBRETINY) - WiFi.macAddress(mac); -#else -// this should be an error, but that messes with CI checks. #error No mac address method defined + if (has_custom_mac_address()) { + esp_efuse_mac_get_custom(mac); + } else { + esp_efuse_mac_get_default(mac); + } #endif } +#elif defined(USE_ESP8266) +void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter) + wifi_get_macaddr(STATION_IF, mac); +} +#elif defined(USE_RP2040) && defined(USE_WIFI) +void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter) + WiFi.macAddress(mac); +} +#elif defined(USE_LIBRETINY) +void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter) + WiFi.macAddress(mac); +} +#endif + std::string get_mac_address() { uint8_t mac[6]; get_mac_address_raw(mac); return str_snprintf("%02x%02x%02x%02x%02x%02x", 12, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } + std::string get_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]); } + #ifdef USE_ESP32 void set_mac_address(uint8_t *mac) { esp_base_mac_addr_set(mac); } #endif +bool has_custom_mac_address() { +#if defined(USE_ESP32) && !defined(USE_ESP32_IGNORE_EFUSE_CUSTOM_MAC) + uint8_t mac[6]; + // do not use 'esp_efuse_mac_get_custom(mac)' because it drops an error in the logs whenever it fails +#ifndef USE_ESP32_VARIANT_ESP32 + return (esp_efuse_read_field_blob(ESP_EFUSE_USER_DATA_MAC_CUSTOM, mac, 48) == ESP_OK) && mac_address_is_valid(mac); +#else + return (esp_efuse_read_field_blob(ESP_EFUSE_MAC_CUSTOM, mac, 48) == ESP_OK) && mac_address_is_valid(mac); +#endif +#else + return false; +#endif +} + +bool mac_address_is_valid(const uint8_t *mac) { + bool is_all_zeros = true; + bool is_all_ones = true; + + for (uint8_t i = 0; i < 6; i++) { + if (mac[i] != 0) { + is_all_zeros = false; + } + } + for (uint8_t i = 0; i < 6; i++) { + if (mac[i] != 0xFF) { + is_all_ones = false; + } + } + return !(is_all_zeros || is_all_ones); +} + void delay_microseconds_safe(uint32_t us) { // avoids CPU locks that could trigger WDT or affect WiFi/BT stability uint32_t start = micros(); diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 3e6fe9433e..43001bafdd 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "esphome/core/optional.h" @@ -545,6 +546,7 @@ class Mutex { public: Mutex(); Mutex(const Mutex &) = delete; + ~Mutex(); void lock(); bool try_lock(); void unlock(); @@ -554,6 +556,8 @@ class Mutex { private: #if defined(USE_ESP32) || defined(USE_LIBRETINY) SemaphoreHandle_t handle_; +#else + void *handle_; // d-pointer to store private data on new platforms #endif }; @@ -635,6 +639,14 @@ std::string get_mac_address_pretty(); void set_mac_address(uint8_t *mac); #endif +/// Check if a custom MAC address is set (ESP32 & variants) +/// @return True if a custom MAC address is set (ESP32 & variants), else false +bool has_custom_mac_address(); + +/// Check if the MAC address is not all zeros or all ones +/// @return True if MAC is valid, else false +bool mac_address_is_valid(const uint8_t *mac); + /// Delay for the given amount of microseconds, possibly yielding to other processes during the wait. void delay_microseconds_safe(uint32_t us); @@ -643,35 +655,45 @@ void delay_microseconds_safe(uint32_t us); /// @name Memory management ///@{ -/** An STL allocator that uses SPI RAM. +/** An STL allocator that uses SPI or internal RAM. + * Returns `nullptr` in case no memory is available. * - * By setting flags, it can be configured to don't try main memory if SPI RAM is full or unavailable, and to return - * `nulllptr` instead of aborting when no memory is available. + * By setting flags, it can be configured to: + * - perform external allocation falling back to main memory if SPI RAM is full or unavailable + * - perform external allocation only + * - perform internal allocation only */ -template class ExternalRAMAllocator { +template class RAMAllocator { public: using value_type = T; enum Flags { - NONE = 0, - REFUSE_INTERNAL = 1 << 0, ///< Refuse falling back to internal memory when external RAM is full or unavailable. - ALLOW_FAILURE = 1 << 1, ///< Don't abort when memory allocation fails. + NONE = 0, // Perform external allocation and fall back to internal memory + ALLOC_EXTERNAL = 1 << 0, // Perform external allocation only. + ALLOC_INTERNAL = 1 << 1, // Perform internal allocation only. + ALLOW_FAILURE = 1 << 2, // Does nothing. Kept for compatibility. }; - ExternalRAMAllocator() = default; - ExternalRAMAllocator(Flags flags) : flags_{flags} {} - template constexpr ExternalRAMAllocator(const ExternalRAMAllocator &other) : flags_{other.flags_} {} + RAMAllocator() = default; + RAMAllocator(uint8_t flags) : flags_{flags} {} + template constexpr RAMAllocator(const RAMAllocator &other) : flags_{other.flags_} {} T *allocate(size_t n) { size_t size = n * sizeof(T); T *ptr = nullptr; #ifdef USE_ESP32 - ptr = static_cast(heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT)); -#endif - if (ptr == nullptr && (this->flags_ & Flags::REFUSE_INTERNAL) == 0) + // External allocation by default or if explicitely requested + if ((this->flags_ & Flags::ALLOC_EXTERNAL) || ((this->flags_ & Flags::ALLOC_INTERNAL) == 0)) { + ptr = static_cast(heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT)); + } + // Fallback to internal allocation if explicitely requested or no flag is specified + if (ptr == nullptr && ((this->flags_ & Flags::ALLOC_INTERNAL) || (this->flags_ & Flags::ALLOC_EXTERNAL) == 0)) { ptr = static_cast(malloc(size)); // NOLINT(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc) - if (ptr == nullptr && (this->flags_ & Flags::ALLOW_FAILURE) == 0) - abort(); + } +#else + // Ignore ALLOC_EXTERNAL/ALLOC_INTERNAL flags if external allocation is not supported + ptr = static_cast(malloc(size)); // NOLINT(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc) +#endif return ptr; } @@ -680,9 +702,11 @@ template class ExternalRAMAllocator { } private: - Flags flags_{Flags::ALLOW_FAILURE}; + uint8_t flags_{Flags::ALLOW_FAILURE}; }; +template using ExternalRAMAllocator = RAMAllocator; + /// @} /// @name Internal functions diff --git a/esphome/core/ring_buffer.cpp b/esphome/core/ring_buffer.cpp index d8ca831de0..f97c686684 100644 --- a/esphome/core/ring_buffer.cpp +++ b/esphome/core/ring_buffer.cpp @@ -11,16 +11,26 @@ namespace esphome { static const char *const TAG = "ring_buffer"; +RingBuffer::~RingBuffer() { + if (this->handle_ != nullptr) { + vStreamBufferDelete(this->handle_); + ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); + allocator.deallocate(this->storage_, this->size_); + } +} + std::unique_ptr RingBuffer::create(size_t len) { std::unique_ptr rb = make_unique(); + rb->size_ = len + 1; + ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); - rb->storage_ = allocator.allocate(len + 1); + rb->storage_ = allocator.allocate(rb->size_); if (rb->storage_ == nullptr) { return nullptr; } - rb->handle_ = xStreamBufferCreateStatic(len + 1, 1, rb->storage_, &rb->structure_); + rb->handle_ = xStreamBufferCreateStatic(rb->size_, 1, rb->storage_, &rb->structure_); ESP_LOGD(TAG, "Created ring buffer with size %u", len); return rb; } diff --git a/esphome/core/ring_buffer.h b/esphome/core/ring_buffer.h index 97ffefcefa..c0511fb52e 100644 --- a/esphome/core/ring_buffer.h +++ b/esphome/core/ring_buffer.h @@ -12,6 +12,8 @@ namespace esphome { class RingBuffer { public: + ~RingBuffer(); + /** * @brief Reads from the ring buffer, waiting up to a specified number of ticks if necessary. * @@ -83,6 +85,7 @@ class RingBuffer { StreamBufferHandle_t handle_; StaticStreamBuffer_t structure_; uint8_t *storage_; + size_t size_{0}; }; } // namespace esphome diff --git a/esphome/dashboard/core.py b/esphome/dashboard/core.py index eec0777da6..563ca1506d 100644 --- a/esphome/dashboard/core.py +++ b/esphome/dashboard/core.py @@ -5,10 +5,14 @@ from collections.abc import Coroutine import contextlib from dataclasses import dataclass from functools import partial +import json import logging +from pathlib import Path import threading from typing import TYPE_CHECKING, Any, Callable +from esphome.storage_json import ignored_devices_storage_path + from ..zeroconf import DiscoveredImport from .dns import DNSCache from .entries import DashboardEntries @@ -20,6 +24,8 @@ if TYPE_CHECKING: _LOGGER = logging.getLogger(__name__) +IGNORED_DEVICES_STORAGE_PATH = "ignored-devices.json" + @dataclass class Event: @@ -74,6 +80,7 @@ class ESPHomeDashboard: "settings", "dns_cache", "_background_tasks", + "ignored_devices", ) def __init__(self) -> None: @@ -89,12 +96,30 @@ class ESPHomeDashboard: self.settings = DashboardSettings() self.dns_cache = DNSCache() self._background_tasks: set[asyncio.Task] = set() + self.ignored_devices: set[str] = set() async def async_setup(self) -> None: """Setup the dashboard.""" self.loop = asyncio.get_running_loop() self.ping_request = asyncio.Event() self.entries = DashboardEntries(self) + self.load_ignored_devices() + + def load_ignored_devices(self) -> None: + storage_path = Path(ignored_devices_storage_path()) + try: + with storage_path.open("r", encoding="utf-8") as f_handle: + data = json.load(f_handle) + self.ignored_devices = set(data.get("ignored_devices", set())) + except FileNotFoundError: + pass + + def save_ignored_devices(self) -> None: + storage_path = Path(ignored_devices_storage_path()) + with storage_path.open("w", encoding="utf-8") as f_handle: + json.dump( + {"ignored_devices": sorted(self.ignored_devices)}, indent=2, fp=f_handle + ) async def async_run(self) -> None: """Run the dashboard.""" diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index e4b7b8d342..9aeece9aab 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -7,6 +7,7 @@ import datetime import functools import gzip import hashlib +import importlib import json import logging import os @@ -541,6 +542,46 @@ class ImportRequestHandler(BaseHandler): self.finish() +class IgnoreDeviceRequestHandler(BaseHandler): + @authenticated + def post(self) -> None: + dashboard = DASHBOARD + try: + args = json.loads(self.request.body.decode()) + device_name = args["name"] + ignore = args["ignore"] + except (json.JSONDecodeError, KeyError): + self.set_status(400) + self.set_header("content-type", "application/json") + self.write(json.dumps({"error": "Invalid payload"})) + return + + ignored_device = next( + ( + res + for res in dashboard.import_result.values() + if res.device_name == device_name + ), + None, + ) + + if ignored_device is None: + self.set_status(404) + self.set_header("content-type", "application/json") + self.write(json.dumps({"error": "Device not found"})) + return + + if ignore: + dashboard.ignored_devices.add(ignored_device.device_name) + else: + dashboard.ignored_devices.discard(ignored_device.device_name) + + dashboard.save_ignored_devices() + + self.set_status(204) + self.finish() + + class DownloadListRequestHandler(BaseHandler): @authenticated @bind_config @@ -555,26 +596,18 @@ class DownloadListRequestHandler(BaseHandler): downloads = [] platform: str = storage_json.target_platform.lower() - if platform == const.PLATFORM_RP2040: - from esphome.components.rp2040 import get_download_types as rp2040_types - downloads = rp2040_types(storage_json) - elif platform == const.PLATFORM_ESP8266: - from esphome.components.esp8266 import get_download_types as esp8266_types - - downloads = esp8266_types(storage_json) - elif platform.upper() in ESP32_VARIANTS: - from esphome.components.esp32 import get_download_types as esp32_types - - downloads = esp32_types(storage_json) + if platform.upper() in ESP32_VARIANTS: + platform = "esp32" elif platform in (const.PLATFORM_RTL87XX, const.PLATFORM_BK72XX): - from esphome.components.libretiny import ( - get_download_types as libretiny_types, - ) + platform = "libretiny" - downloads = libretiny_types(storage_json) - else: - raise ValueError(f"Unknown platform {platform}") + try: + module = importlib.import_module(f"esphome.components.{platform}") + get_download_types = getattr(module, "get_download_types") + except AttributeError as exc: + raise ValueError(f"Unknown platform {platform}") from exc + downloads = get_download_types(storage_json) self.set_status(200) self.set_header("content-type", "application/json") @@ -688,6 +721,7 @@ class ListDevicesHandler(BaseHandler): "project_name": res.project_name, "project_version": res.project_version, "network": res.network, + "ignored": res.device_name in dashboard.ignored_devices, } for res in dashboard.import_result.values() if res.device_name not in configured @@ -1156,6 +1190,7 @@ def make_app(debug=get_bool_env(ENV_DEV)) -> tornado.web.Application: (f"{rel}prometheus-sd", PrometheusServiceDiscoveryHandler), (f"{rel}boards/([a-z0-9]+)", BoardsRequestHandler), (f"{rel}version", EsphomeVersionHandler), + (f"{rel}ignore-device", IgnoreDeviceRequestHandler), ], **app_settings, ) diff --git a/esphome/mqtt.py b/esphome/mqtt.py index c1c45799cc..d55fb0202d 100644 --- a/esphome/mqtt.py +++ b/esphome/mqtt.py @@ -209,6 +209,12 @@ def show_logs(config, topic=None, username=None, password=None, client_id=None): elif CONF_MQTT in config: conf = config[CONF_MQTT] if CONF_LOG_TOPIC in conf: + if config[CONF_MQTT][CONF_LOG_TOPIC] is None: + _LOGGER.error("MQTT log topic set to null, can't start MQTT logs") + return 1 + if CONF_TOPIC not in config[CONF_MQTT][CONF_LOG_TOPIC]: + _LOGGER.error("MQTT log topic not available, can't start MQTT logs") + return 1 topic = config[CONF_MQTT][CONF_LOG_TOPIC][CONF_TOPIC] elif CONF_TOPIC_PREFIX in config[CONF_MQTT]: topic = f"{config[CONF_MQTT][CONF_TOPIC_PREFIX]}/debug" diff --git a/esphome/storage_json.py b/esphome/storage_json.py index 2d12ee01a0..97cf9ceadd 100644 --- a/esphome/storage_json.py +++ b/esphome/storage_json.py @@ -28,6 +28,10 @@ def esphome_storage_path() -> str: return os.path.join(CORE.data_dir, "esphome.json") +def ignored_devices_storage_path() -> str: + return os.path.join(CORE.data_dir, "ignored-devices.json") + + def trash_storage_path() -> str: return CORE.relative_config_path("trash") diff --git a/esphome/voluptuous_schema.py b/esphome/voluptuous_schema.py index 7f1573b443..15f9206f21 100644 --- a/esphome/voluptuous_schema.py +++ b/esphome/voluptuous_schema.py @@ -226,4 +226,6 @@ class _Schema(vol.Schema): if isinstance(schema, vol.Schema): schema = schema.schema ret = super().extend(schema, extra=extra) - return _Schema(ret.schema, extra=ret.extra, extra_schemas=self._extra_schemas) + return _Schema( + ret.schema, extra=ret.extra, extra_schemas=self._extra_schemas.copy() + ) diff --git a/esphome/wizard.py b/esphome/wizard.py index 319fb31938..eecbbdb172 100644 --- a/esphome/wizard.py +++ b/esphome/wizard.py @@ -90,9 +90,6 @@ esp32: RP2040_CONFIG = """ rp2040: board: {board} - framework: - # Required until https://github.com/platformio/platform-raspberrypi/pull/36 is merged - platform_version: https://github.com/maxgerhardt/platform-raspberrypi.git """ BK72XX_CONFIG = """ diff --git a/esphome/writer.py b/esphome/writer.py index 79ee72996c..90446ae4b1 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -1,3 +1,4 @@ +import importlib import logging import os from pathlib import Path @@ -299,25 +300,13 @@ def copy_src_tree(): CORE.relative_src_path("esphome", "core", "version.h"), generate_version_h() ) - if CORE.is_esp32: - from esphome.components.esp32 import copy_files - + platform = "esphome.components." + CORE.target_platform + try: + module = importlib.import_module(platform) + copy_files = getattr(module, "copy_files") copy_files() - - elif CORE.is_esp8266: - from esphome.components.esp8266 import copy_files - - copy_files() - - elif CORE.is_rp2040: - from esphome.components.rp2040 import copy_files - - (pio) = copy_files() - if pio: - write_file_if_changed( - CORE.relative_src_path("esphome.h"), - ESPHOME_H_FORMAT.format(include_s + '\n#include "pio_includes.h"'), - ) + except AttributeError: + pass def generate_defines_h(): diff --git a/platformio.ini b/platformio.ini index ee18068a29..04afc059af 100644 --- a/platformio.ini +++ b/platformio.ini @@ -38,7 +38,7 @@ lib_deps = 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 + functionpointer/arduino-MLX90393@1.0.2 ; 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 @@ -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) @@ -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 = @@ -165,7 +165,7 @@ platform_packages = extends = common:arduino board_build.filesystem_size = 0.5m -platform = https://github.com/maxgerhardt/platform-raspberrypi.git +platform = https://github.com/maxgerhardt/platform-raspberrypi.git#v1.2.0-gcc12 platform_packages = ; earlephilhower/framework-arduinopico@~1.20602.0 ; Cannot use the platformio package until old releases stop getting deleted earlephilhower/framework-arduinopico@https://github.com/earlephilhower/arduino-pico/releases/download/3.9.4/rp2040-3.9.4.zip diff --git a/requirements.txt b/requirements.txt index 3e658de8ad..8cc26e4da0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ async_timeout==4.0.3; python_version <= "3.10" cryptography==43.0.0 voluptuous==0.14.2 -PyYAML==6.0.1 +PyYAML==6.0.2 paho-mqtt==1.6.1 colorama==0.4.6 icmplib==3.0.4 @@ -9,13 +9,13 @@ tornado==6.4 tzlocal==5.2 # from time tzdata>=2021.1 # from time pyserial==3.5 -platformio==6.1.15 # When updating platformio, also update Dockerfile +platformio==6.1.16 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 -esphome-dashboard==20240620.0 +esphome-dashboard==20241025.0 aioesphomeapi==24.6.2 zeroconf==0.132.2 -python-magic==0.4.27 +puremagic==1.27 ruamel.yaml==0.18.6 # dashboard_import # esp-idf requires this, but doesn't bundle it by default diff --git a/requirements_optional.txt b/requirements_optional.txt index c984d41332..2d57c5fd96 100644 --- a/requirements_optional.txt +++ b/requirements_optional.txt @@ -1,2 +1,2 @@ -pillow==10.2.0 +pillow==10.4.0 cairosvg==2.7.1 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 diff --git a/script/clang-tidy b/script/clang-tidy index 5bb93846b2..61199edce3 100755 --- a/script/clang-tidy +++ b/script/clang-tidy @@ -98,7 +98,7 @@ def clang_options(idedata): cmd.extend(["-isystem", directory]) # add library include directories using -isystem to suppress their errors - for directory in sorted(set(idedata["includes"]["build"])): + for directory in list(idedata["includes"]["build"]): # skip our own directories, we add those later if ( not directory.startswith(f"{root_path}/") diff --git a/script/test_build_components b/script/test_build_components index e885294b99..62fe0f1b55 100755 --- a/script/test_build_components +++ b/script/test_build_components @@ -2,6 +2,15 @@ set -e +help() { + echo "Usage: $0 [-e ] [-c ] [-t ]" 1>&2 + echo 1>&2 + echo " - e - Parameter for esphome command. Default compile. Common alternative is config." 1>&2 + echo " - c - Component folder name to test. Default *. E.g. '-c logger'." 1>&2 + echo " - t - Target name to test. Put '-t list' to display all possibilities. E.g. '-t esp32-s2-idf-51'." 1>&2 + exit 1 +} + # Parse parameter: # - `e` - Parameter for `esphome` command. Default `compile`. Common alternative is `config`. # - `c` - Component folder name to test. Default `*`. @@ -13,7 +22,7 @@ do e) esphome_command=${OPTARG};; c) target_component=${OPTARG};; t) requested_target_platform=${OPTARG};; - \?) echo "Usage: $0 [-e ] [-c ] [-t ]" 1>&2; exit 1;; + \?) help;; esac done @@ -24,8 +33,8 @@ 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" + if [ -n "$requested_target_platform" ] && [ "$requested_target_platform" != "$target_platform_with_version" ]; then + echo "Skipping $target_platform_with_version" return fi # create dynamic yaml file in `build` folder. diff --git a/tests/components/aic3204/common.yaml b/tests/components/aic3204/common.yaml new file mode 100644 index 0000000000..6e939bd260 --- /dev/null +++ b/tests/components/aic3204/common.yaml @@ -0,0 +1,15 @@ +esphome: + on_boot: + then: + - audio_dac.mute_off: + - audio_dac.mute_on: + - audio_dac.set_volume: + volume: 50% + +i2c: + - id: i2c_aic3204 + scl: ${scl_pin} + sda: ${sda_pin} + +audio_dac: + - platform: aic3204 diff --git a/tests/components/aic3204/test.esp32-ard.yaml b/tests/components/aic3204/test.esp32-ard.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/aic3204/test.esp32-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/aic3204/test.esp32-c3-ard.yaml b/tests/components/aic3204/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/aic3204/test.esp32-c3-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/aic3204/test.esp32-c3-idf.yaml b/tests/components/aic3204/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/aic3204/test.esp32-c3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/aic3204/test.esp32-idf.yaml b/tests/components/aic3204/test.esp32-idf.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/aic3204/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/aic3204/test.esp8266-ard.yaml b/tests/components/aic3204/test.esp8266-ard.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/aic3204/test.esp8266-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/axs15231/common.yaml b/tests/components/axs15231/common.yaml new file mode 100644 index 0000000000..1c0c79975f --- /dev/null +++ b/tests/components/axs15231/common.yaml @@ -0,0 +1,20 @@ +i2c: + - id: i2c_axs15231 + scl: 3 + sda: 21 + +display: + - platform: ssd1306_i2c + id: ssd1306_display + model: SSD1306_128X64 + reset_pin: 19 + pages: + - id: page1 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + +touchscreen: + - platform: axs15231 + display: ssd1306_display + interrupt_pin: 20 + reset_pin: 18 diff --git a/tests/components/qspi_amoled/test.esp32-s3-idf.yaml b/tests/components/axs15231/test.esp32-ard.yaml similarity index 100% rename from tests/components/qspi_amoled/test.esp32-s3-idf.yaml rename to tests/components/axs15231/test.esp32-ard.yaml diff --git a/tests/components/axs15231/test.esp32-c3-ard.yaml b/tests/components/axs15231/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/axs15231/test.esp32-c3-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/axs15231/test.esp32-c3-idf.yaml b/tests/components/axs15231/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/axs15231/test.esp32-c3-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/axs15231/test.esp32-idf.yaml b/tests/components/axs15231/test.esp32-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/axs15231/test.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/axs15231/test.esp8266-ard.yaml b/tests/components/axs15231/test.esp8266-ard.yaml new file mode 100644 index 0000000000..c09d139574 --- /dev/null +++ b/tests/components/axs15231/test.esp8266-ard.yaml @@ -0,0 +1,19 @@ +i2c: + - id: i2c_axs15231 + 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: axs15231 + display: ssd1306_display + interrupt_pin: 12 diff --git a/tests/components/axs15231/test.rp2040-ard.yaml b/tests/components/axs15231/test.rp2040-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/axs15231/test.rp2040-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/bl0906/common.yaml b/tests/components/bl0906/common.yaml index 944791369c..29321a9471 100644 --- a/tests/components/bl0906/common.yaml +++ b/tests/components/bl0906/common.yaml @@ -8,6 +8,7 @@ uart: sensor: - platform: bl0906 + id: bl frequency: name: 'Frequency' temperature: @@ -60,3 +61,9 @@ sensor: name: 'Total_Energy' total_power: name: 'Total_Power' + +button: + - platform: template + id: reset + on_press: + - bl0906.reset_energy: bl 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: diff --git a/tests/components/bytebuffer/common.yaml b/tests/components/bytebuffer/common.yaml new file mode 100644 index 0000000000..177f487e1e --- /dev/null +++ b/tests/components/bytebuffer/common.yaml @@ -0,0 +1,161 @@ +bytebuffer: + +esphome: + on_boot: + - lambda: |- + using namespace bytebuffer; + auto buf = ByteBuffer(16); + assert(buf.get_endianness() == LITTLE); + assert(buf.get_remaining() == 16); + buf.set_limit(10); + assert(buf.get_capacity() == 16); + buf.put_uint8(1); + assert(buf.get_remaining() == 9); + buf.put_uint16(0xABCD); + auto da = buf.get_data(); + assert(buf.get_uint8(0) == 1); + auto x = buf.get_uint16(1); + assert(buf.get_uint16(1) == 0xABCD); + assert(buf.get_remaining() == 7); + buf.put_uint32(0x12345678UL); + assert(buf.get_uint32(3) == 0x12345678UL); + assert(buf.get_remaining() == 3); + assert(buf.get_data()[1] == 0xCD); + assert(buf.get_data()[2] == 0xAB); + assert(buf.get_data()[3] == 0x78); + assert(buf.get_data()[4] == 0x56); + assert(buf.get_data()[5] == 0x34); + assert(buf.get_data()[6] == 0x12); + buf.flip(); + assert(buf.get_capacity() == 16); + assert(buf.get_uint32(3) == 0x12345678UL); + assert(buf.get_uint8(0) == 1); + assert(buf.get_uint16(1) == 0xABCD); + buf.put_uint16(0x1234, 1); + assert(buf.get_uint16(1) == 0x1234); + assert(buf.get_remaining() == 7); + assert(buf.get_uint8() == 1); + assert(buf.get_uint16() == 0x1234); + assert(buf.get_uint32() == 0x12345678ul); + assert(buf.get_remaining() == 0); + assert(buf.get_remaining() == 0); + buf.rewind(); + buf.big_endian(); + assert(buf.get_remaining() == 7); + assert(buf.get_uint8() == 1); + assert(buf.get_uint16() == 0x3412); + buf.mark(); + assert(buf.get_uint32() == 0x78563412ul); + assert(buf.get_remaining() == 0); + buf.reset(); + assert(buf.get_remaining() == 4); + assert(buf.get_uint32() == 0x78563412ul); + auto buf1 = ByteBuffer::wrap(buf.get_data().data(), buf.get_limit()); + buf.clear(); + assert(buf.get_position() == 0); + assert(buf.get_capacity() == 16); + assert(buf.get_limit() == 16); + assert(buf1.get_remaining() == 7); + assert(buf1.get_capacity() == 7); + buf1.set_position(3); + assert(buf1.get_uint32() == 0x12345678ul); + buf1.clear(); + assert(buf1.get_limit() == 7); + assert(buf1.get_capacity() == 7); + assert(buf1.get_position() == 0); + float f = 1.2345; + buf1.put_float(f); + buf1.flip(); + assert(buf1.get_remaining() == 4); + assert(buf1.get_float() == f); + buf1.clear(); + buf1.put_uint16(-32760); + buf1.put_uint24(-302760); + buf1.flip(); + assert(buf1.get_int16() == -32760); + assert(buf1.get_int24() == -302760); + uint8_t arr[4] = {0x10, 0x20, 0x30, 0x40}; + buf1 = ByteBuffer::wrap(arr, 4); + assert(buf1.get_capacity() == 4); + assert(buf1.get_limit() == 4); + assert(buf1.get_position() == 0); + assert(buf1.get_uint32() == 0x40302010UL); + assert(buf1.get_position() == 4); + assert(buf1.get_remaining() == 0); + std::vector vec{}; + vec.push_back(0x10); + vec.push_back(0x20); + vec.push_back(0x30); + vec.push_back(0x40); + buf1 = ByteBuffer::wrap(vec); + assert(buf1.get_capacity() == 4); + assert(buf1.get_limit() == 4); + assert(buf1.get_position() == 0); + buf1.mark(); + buf1.reset(); + assert(buf1.get_uint32() == 0x40302010UL); + buf = ByteBuffer::wrap(true); + assert(buf.get_bool() == true); + buf = ByteBuffer::wrap((uint8_t)0xFE); + assert(buf.get_uint8() == 0xFE); + buf = ByteBuffer::wrap((uint16_t)0xA5A6, BIG); + assert(buf.get_remaining() == 2); + assert(buf.get_position() == 0); + assert(buf.get_capacity() == 2); + assert(buf.get_endianness() == BIG); + assert(buf.get_data()[0] == 0xA5); + assert(buf.get_uint16() == 0xA5A6); + buf.flip(); + buf.little_endian(); + assert(buf.get_uint16() == 0xA6A5); + buf = ByteBuffer::wrap(f, BIG); + assert(buf.get_float() == f); + double d = 1.2345678E7; + buf = ByteBuffer::wrap(d, BIG); + assert(buf.get_double() == d); + buf = ByteBuffer::wrap({1, 2, 3, 4}, BIG); + assert(buf.get_endianness() == BIG); + assert(buf.get_remaining() == 4); + assert(buf.get_data()[2] == 3); + buf.little_endian(); + assert(buf.get_data()[2] == 3); + assert(buf.get_uint16() == 0x0201); + buf.big_endian(); + assert(buf.get_uint16() == 0x0304); + buf.rewind(); + vec = buf.get_vector(3); + assert(buf.get_remaining() == 1); + assert(vec[0] == 1); + assert(vec.size() == 3); + buf = ByteBuffer(10); + buf.put_vector(vec); + assert(buf.get_remaining() == 7); + buf.flip(); + assert(buf.get_remaining() == 3); + assert(buf.get_uint24() == 0x030201); + buf = ByteBuffer(64); + buf.put_uint8(1, 1); + buf.put_uint16(16, 2); + buf.put_uint32(1232, 4); + buf.put_uint64(123432ul, 8); + buf.put_float(1.2f, 16); + buf.put_int24(0x678, 20); + + assert(buf.get_uint8(1) == 1); + assert(buf.get(1) == 1); + assert(buf.get_uint16(2) == 16); + assert(buf.get(2) == 16); + assert(buf.get_uint32(4) == 1232); + assert(buf.get(4) == 1232); + assert(buf.get_uint64(8) == 123432ul); + assert(buf.get(8) == 123432ul); + assert(buf.get_float(16) == 1.2f); + assert(buf.get(16) == 1.2f); + assert(buf.get_int24(20) == 0x678); + buf.clear(); + buf.put(1.234, 10); + double dx = buf.get(10); + assert(dx == 1.234); + buf.put((uint16_t)1, 10); + assert(buf.get_uint16(10) == 1); + ESP_LOGD("bytebuffer", "******************** All tests succeeded"); diff --git a/tests/components/bytebuffer/test.esp32-ard.yaml b/tests/components/bytebuffer/test.esp32-ard.yaml new file mode 100644 index 0000000000..380ca87628 --- /dev/null +++ b/tests/components/bytebuffer/test.esp32-ard.yaml @@ -0,0 +1 @@ +!include common.yaml diff --git a/tests/components/bytebuffer/test.esp32-c3-ard.yaml b/tests/components/bytebuffer/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..380ca87628 --- /dev/null +++ b/tests/components/bytebuffer/test.esp32-c3-ard.yaml @@ -0,0 +1 @@ +!include common.yaml diff --git a/tests/components/bytebuffer/test.esp32-c3-idf.yaml b/tests/components/bytebuffer/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..380ca87628 --- /dev/null +++ b/tests/components/bytebuffer/test.esp32-c3-idf.yaml @@ -0,0 +1 @@ +!include common.yaml diff --git a/tests/components/bytebuffer/test.esp32-idf.yaml b/tests/components/bytebuffer/test.esp32-idf.yaml new file mode 100644 index 0000000000..380ca87628 --- /dev/null +++ b/tests/components/bytebuffer/test.esp32-idf.yaml @@ -0,0 +1 @@ +!include common.yaml diff --git a/tests/components/bytebuffer/test.esp8266-ard.yaml b/tests/components/bytebuffer/test.esp8266-ard.yaml new file mode 100644 index 0000000000..380ca87628 --- /dev/null +++ b/tests/components/bytebuffer/test.esp8266-ard.yaml @@ -0,0 +1 @@ +!include common.yaml diff --git a/tests/components/bytebuffer/test.host.yaml b/tests/components/bytebuffer/test.host.yaml new file mode 100644 index 0000000000..380ca87628 --- /dev/null +++ b/tests/components/bytebuffer/test.host.yaml @@ -0,0 +1 @@ +!include common.yaml diff --git a/tests/components/bytebuffer/test.rp2040-ard.yaml b/tests/components/bytebuffer/test.rp2040-ard.yaml new file mode 100644 index 0000000000..380ca87628 --- /dev/null +++ b/tests/components/bytebuffer/test.rp2040-ard.yaml @@ -0,0 +1 @@ +!include common.yaml diff --git a/tests/components/ch422g/common.yaml b/tests/components/ch422g/common.yaml index 02061bda59..d65956ecac 100644 --- a/tests/components/ch422g/common.yaml +++ b/tests/components/ch422g/common.yaml @@ -1,6 +1,5 @@ ch422g: - id: ch422g_hub - address: 0x24 binary_sensor: - platform: gpio @@ -11,10 +10,18 @@ binary_sensor: number: 1 mode: INPUT inverted: true +output: - platform: gpio - id: ch422g_output + id: ch422_out_0 pin: ch422g: ch422g_hub number: 0 mode: OUTPUT inverted: false + - platform: gpio + id: ch422_out_11 + pin: + ch422g: ch422g_hub + number: 11 + mode: OUTPUT_OPEN_DRAIN + inverted: true diff --git a/tests/components/cse7766/test.esp32-ard.yaml b/tests/components/cse7766/test.esp32-ard.yaml index f94cd0f7d8..5542b52824 100644 --- a/tests/components/cse7766/test.esp32-ard.yaml +++ b/tests/components/cse7766/test.esp32-ard.yaml @@ -5,6 +5,7 @@ uart: rx_pin: number: 16 baud_rate: 4800 + parity: EVEN sensor: - platform: cse7766 diff --git a/tests/components/cse7766/test.esp32-c3-ard.yaml b/tests/components/cse7766/test.esp32-c3-ard.yaml index 432cc0a80e..d27c9d4463 100644 --- a/tests/components/cse7766/test.esp32-c3-ard.yaml +++ b/tests/components/cse7766/test.esp32-c3-ard.yaml @@ -5,6 +5,7 @@ uart: rx_pin: number: 5 baud_rate: 4800 + parity: EVEN sensor: - platform: cse7766 diff --git a/tests/components/cse7766/test.esp32-c3-idf.yaml b/tests/components/cse7766/test.esp32-c3-idf.yaml index 432cc0a80e..d27c9d4463 100644 --- a/tests/components/cse7766/test.esp32-c3-idf.yaml +++ b/tests/components/cse7766/test.esp32-c3-idf.yaml @@ -5,6 +5,7 @@ uart: rx_pin: number: 5 baud_rate: 4800 + parity: EVEN sensor: - platform: cse7766 diff --git a/tests/components/cse7766/test.esp32-idf.yaml b/tests/components/cse7766/test.esp32-idf.yaml index f94cd0f7d8..5542b52824 100644 --- a/tests/components/cse7766/test.esp32-idf.yaml +++ b/tests/components/cse7766/test.esp32-idf.yaml @@ -5,6 +5,7 @@ uart: rx_pin: number: 16 baud_rate: 4800 + parity: EVEN sensor: - platform: cse7766 diff --git a/tests/components/cse7766/test.esp8266-ard.yaml b/tests/components/cse7766/test.esp8266-ard.yaml index 432cc0a80e..d27c9d4463 100644 --- a/tests/components/cse7766/test.esp8266-ard.yaml +++ b/tests/components/cse7766/test.esp8266-ard.yaml @@ -5,6 +5,7 @@ uart: rx_pin: number: 5 baud_rate: 4800 + parity: EVEN sensor: - platform: cse7766 diff --git a/tests/components/cse7766/test.rp2040-ard.yaml b/tests/components/cse7766/test.rp2040-ard.yaml index 432cc0a80e..d27c9d4463 100644 --- a/tests/components/cse7766/test.rp2040-ard.yaml +++ b/tests/components/cse7766/test.rp2040-ard.yaml @@ -5,6 +5,7 @@ uart: rx_pin: number: 5 baud_rate: 4800 + parity: EVEN sensor: - platform: cse7766 diff --git a/tests/components/cst816/common.yaml b/tests/components/cst816/common.yaml index 91abbfd4f6..765a353d1d 100644 --- a/tests/components/cst816/common.yaml +++ b/tests/components/cst816/common.yaml @@ -4,6 +4,7 @@ touchscreen: interrupt_pin: number: 21 reset_pin: GPIO16 + skip_probe: false transform: mirror_x: false mirror_y: false @@ -11,14 +12,14 @@ touchscreen: i2c: sda: 3 - scl: 2 + scl: 4 display: - id: my_display platform: ili9xxx dimensions: 480x320 model: ST7796 - cs_pin: 15 + cs_pin: 18 dc_pin: 20 reset_pin: 22 transform: diff --git a/tests/components/display/common.yaml b/tests/components/display/common.yaml index 1df2665067..4fc4fafa25 100644 --- a/tests/components/display/common.yaml +++ b/tests/components/display/common.yaml @@ -34,3 +34,7 @@ display: it.line_at_angle(centerX, centerY, minuteAngle, radius - 5, radius); } + + // Nice ring around and some gauge + it.filled_ring(centerX, centerY, radius+5, radius+8); + it.filled_gauge(centerX, centerY, radius/2, radius/2-5, 66); 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 index b226d1de06..8d04d3370b 100644 --- a/tests/components/esp32_rmt_led_strip/test.esp32-c3-idf.yaml +++ b/tests/components/esp32_rmt_led_strip/test.esp32-c3-idf.yaml @@ -12,7 +12,7 @@ light: num_leds: 60 rmt_channel: 1 rgb_order: RGB - bit0_high: 100us - bit0_low: 100us - bit1_high: 100us - bit1_low: 100us + bit0_high: 100µs + bit0_low: 100µs + bit1_high: 100µs + bit1_low: 100µs diff --git a/tests/components/esp32_rmt_led_strip/test.esp32-idf.yaml b/tests/components/esp32_rmt_led_strip/test.esp32-idf.yaml index d51a66451f..6e1763b339 100644 --- a/tests/components/esp32_rmt_led_strip/test.esp32-idf.yaml +++ b/tests/components/esp32_rmt_led_strip/test.esp32-idf.yaml @@ -12,7 +12,7 @@ light: num_leds: 60 rmt_channel: 2 rgb_order: RGB - bit0_high: 100us - bit0_low: 100us - bit1_high: 100us - bit1_low: 100us + bit0_high: 100µs + bit0_low: 100µs + bit1_high: 100µs + bit1_low: 100µs diff --git a/tests/components/ethernet/common-openeth.yaml b/tests/components/ethernet/common-openeth.yaml new file mode 100644 index 0000000000..fbb7579598 --- /dev/null +++ b/tests/components/ethernet/common-openeth.yaml @@ -0,0 +1,2 @@ +ethernet: + type: OPENETH diff --git a/tests/components/ethernet/test-openeth.esp32-idf.yaml b/tests/components/ethernet/test-openeth.esp32-idf.yaml new file mode 100644 index 0000000000..220316f3ee --- /dev/null +++ b/tests/components/ethernet/test-openeth.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common-openeth.yaml diff --git a/tests/components/gp2y1010au0f/test.esp32-idf.yaml b/tests/components/gp2y1010au0f/test.esp32-idf.yaml new file mode 100644 index 0000000000..eb5ad0ea67 --- /dev/null +++ b/tests/components/gp2y1010au0f/test.esp32-idf.yaml @@ -0,0 +1,16 @@ +sensor: + - platform: adc + pin: GPIO36 + id: adc_sensor + + - platform: gp2y1010au0f + sensor: adc_sensor + name: Dust Sensor + adc_voltage_offset: 0.2 + adc_voltage_multiplier: 3.3 + output: dust_sensor_led + +output: + - platform: gpio + id: dust_sensor_led + pin: GPIO32 diff --git a/tests/components/grove_gas_mc_v2/common.yaml b/tests/components/grove_gas_mc_v2/common.yaml new file mode 100644 index 0000000000..0729e6b9c7 --- /dev/null +++ b/tests/components/grove_gas_mc_v2/common.yaml @@ -0,0 +1,13 @@ +sensor: + - platform: grove_gas_mc_v2 + i2c_id: i2c_bus + nitrogen_dioxide: + name: "Nitrogen Dioxide" + ethanol: + name: "Ethanol" + carbon_monoxide: + name: "Carbon Monoxide" + tvoc: + name: "Volatile Organic Compounds" + update_interval: 30s + address: 0xAD diff --git a/tests/components/grove_gas_mc_v2/test.esp32-ard.yaml b/tests/components/grove_gas_mc_v2/test.esp32-ard.yaml new file mode 100644 index 0000000000..00c7856c36 --- /dev/null +++ b/tests/components/grove_gas_mc_v2/test.esp32-ard.yaml @@ -0,0 +1,6 @@ +i2c: + sda: 21 + scl: 22 + id: i2c_bus + +<<: !include common.yaml diff --git a/tests/components/grove_gas_mc_v2/test.esp32-idf.yaml b/tests/components/grove_gas_mc_v2/test.esp32-idf.yaml new file mode 100644 index 0000000000..00c7856c36 --- /dev/null +++ b/tests/components/grove_gas_mc_v2/test.esp32-idf.yaml @@ -0,0 +1,6 @@ +i2c: + sda: 21 + scl: 22 + id: i2c_bus + +<<: !include common.yaml diff --git a/tests/components/grove_gas_mc_v2/test.esp8266-ard.yaml b/tests/components/grove_gas_mc_v2/test.esp8266-ard.yaml new file mode 100644 index 0000000000..2de18bdf39 --- /dev/null +++ b/tests/components/grove_gas_mc_v2/test.esp8266-ard.yaml @@ -0,0 +1,6 @@ +i2c: + sda: 4 + scl: 5 + id: i2c_bus + +<<: !include common.yaml diff --git a/tests/components/grove_gas_mc_v2/test.rp2040-ard.yaml b/tests/components/grove_gas_mc_v2/test.rp2040-ard.yaml new file mode 100644 index 0000000000..00c7856c36 --- /dev/null +++ b/tests/components/grove_gas_mc_v2/test.rp2040-ard.yaml @@ -0,0 +1,6 @@ +i2c: + sda: 21 + scl: 22 + id: i2c_bus + +<<: !include common.yaml diff --git a/tests/components/haier/common.yaml b/tests/components/haier/common.yaml index b8a23bac5a..368b88b69c 100644 --- a/tests/components/haier/common.yaml +++ b/tests/components/haier/common.yaml @@ -16,7 +16,6 @@ climate: name: Haier AC wifi_signal: true answer_timeout: 200ms - beeper: true visual: min_temperature: 16 °C max_temperature: 30 °C @@ -38,7 +37,6 @@ climate: supported_presets: - AWAY - BOOST - - ECO - SLEEP on_alarm_start: then: @@ -112,3 +110,15 @@ text_sensor: name: Haier cleaning status protocol_version: name: Haier protocol version + +switch: + - platform: haier + haier_id: haier_ac + beeper: + name: Haier beeper + display: + name: Haier display + health_mode: + name: Haier health mode + quiet_mode: + name: Haier quiet mode diff --git a/tests/components/i2c_device/test.esp32-ard.yaml b/tests/components/i2c_device/test.esp32-ard.yaml new file mode 100644 index 0000000000..6169d113f8 --- /dev/null +++ b/tests/components/i2c_device/test.esp32-ard.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_i2c + scl: 16 + sda: 17 + +i2c_device: + id: i2cdev + address: 0x2C diff --git a/tests/components/i2c_device/test.esp32-c3-ard.yaml b/tests/components/i2c_device/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..5d53d12208 --- /dev/null +++ b/tests/components/i2c_device/test.esp32-c3-ard.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_i2c + scl: 5 + sda: 4 + +i2c_device: + id: i2cdev + address: 0x2C diff --git a/tests/components/i2c_device/test.esp32-c3-idf.yaml b/tests/components/i2c_device/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..5d53d12208 --- /dev/null +++ b/tests/components/i2c_device/test.esp32-c3-idf.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_i2c + scl: 5 + sda: 4 + +i2c_device: + id: i2cdev + address: 0x2C diff --git a/tests/components/i2c_device/test.esp32-idf.yaml b/tests/components/i2c_device/test.esp32-idf.yaml new file mode 100644 index 0000000000..6169d113f8 --- /dev/null +++ b/tests/components/i2c_device/test.esp32-idf.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_i2c + scl: 16 + sda: 17 + +i2c_device: + id: i2cdev + address: 0x2C diff --git a/tests/components/i2c_device/test.esp8266-ard.yaml b/tests/components/i2c_device/test.esp8266-ard.yaml new file mode 100644 index 0000000000..5d53d12208 --- /dev/null +++ b/tests/components/i2c_device/test.esp8266-ard.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_i2c + scl: 5 + sda: 4 + +i2c_device: + id: i2cdev + address: 0x2C diff --git a/tests/components/i2c_device/test.rp2040-ard.yaml b/tests/components/i2c_device/test.rp2040-ard.yaml new file mode 100644 index 0000000000..5d53d12208 --- /dev/null +++ b/tests/components/i2c_device/test.rp2040-ard.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_i2c + scl: 5 + sda: 4 + +i2c_device: + id: i2cdev + address: 0x2C diff --git a/tests/components/image/common.yaml b/tests/components/image/common.yaml new file mode 100644 index 0000000000..313da6bc0b --- /dev/null +++ b/tests/components/image/common.yaml @@ -0,0 +1,38 @@ +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-ard.yaml b/tests/components/image/test.esp32-ard.yaml index 34c7914976..818e720221 100644 --- a/tests/components/image/test.esp32-ard.yaml +++ b/tests/components/image/test.esp32-ard.yaml @@ -2,52 +2,16 @@ spi: - id: spi_main_lcd clk_pin: 16 mosi_pin: 17 - miso_pin: 15 + miso_pin: 32 display: - platform: ili9xxx id: main_lcd model: ili9342 - cs_pin: 12 + cs_pin: 14 dc_pin: 13 reset_pin: 21 invert_colors: true -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 +<<: !include common.yaml + diff --git a/tests/components/image/test.esp32-c3-ard.yaml b/tests/components/image/test.esp32-c3-ard.yaml index 91ff0a0579..4dae9cd5ec 100644 --- a/tests/components/image/test.esp32-c3-ard.yaml +++ b/tests/components/image/test.esp32-c3-ard.yaml @@ -8,46 +8,9 @@ display: - platform: ili9xxx id: main_lcd model: ili9342 - cs_pin: 8 - dc_pin: 9 + cs_pin: 3 + dc_pin: 11 reset_pin: 10 invert_colors: true -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 +<<: !include common.yaml diff --git a/tests/components/image/test.esp32-c3-idf.yaml b/tests/components/image/test.esp32-c3-idf.yaml index 91ff0a0579..4dae9cd5ec 100644 --- a/tests/components/image/test.esp32-c3-idf.yaml +++ b/tests/components/image/test.esp32-c3-idf.yaml @@ -8,46 +8,9 @@ display: - platform: ili9xxx id: main_lcd model: ili9342 - cs_pin: 8 - dc_pin: 9 + cs_pin: 3 + dc_pin: 11 reset_pin: 10 invert_colors: true -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 +<<: !include common.yaml diff --git a/tests/components/image/test.esp32-idf.yaml b/tests/components/image/test.esp32-idf.yaml index 34c7914976..814f16c36c 100644 --- a/tests/components/image/test.esp32-idf.yaml +++ b/tests/components/image/test.esp32-idf.yaml @@ -2,52 +2,15 @@ spi: - id: spi_main_lcd clk_pin: 16 mosi_pin: 17 - miso_pin: 15 + miso_pin: 18 display: - platform: ili9xxx id: main_lcd model: ili9342 - cs_pin: 12 + cs_pin: 19 dc_pin: 13 reset_pin: 21 invert_colors: true -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 +<<: !include common.yaml diff --git a/tests/components/image/test.esp8266-ard.yaml b/tests/components/image/test.esp8266-ard.yaml index 5a96ed9497..f963022ff4 100644 --- a/tests/components/image/test.esp8266-ard.yaml +++ b/tests/components/image/test.esp8266-ard.yaml @@ -13,41 +13,4 @@ display: reset_pin: 16 invert_colors: true -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 +<<: !include common.yaml diff --git a/tests/components/image/test.host.yaml b/tests/components/image/test.host.yaml new file mode 100644 index 0000000000..29509db66c --- /dev/null +++ b/tests/components/image/test.host.yaml @@ -0,0 +1,8 @@ +display: + - platform: sdl + auto_clear_enabled: false + dimensions: + width: 480 + height: 480 + +<<: !include common.yaml diff --git a/tests/components/image/test.rp2040-ard.yaml b/tests/components/image/test.rp2040-ard.yaml index 4c40ca464f..5167c99a7d 100644 --- a/tests/components/image/test.rp2040-ard.yaml +++ b/tests/components/image/test.rp2040-ard.yaml @@ -13,41 +13,4 @@ display: reset_pin: 22 invert_colors: true -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 +<<: !include common.yaml diff --git a/tests/components/light/common.yaml b/tests/components/light/common.yaml new file mode 100644 index 0000000000..a224dbe8bc --- /dev/null +++ b/tests/components/light/common.yaml @@ -0,0 +1,125 @@ +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% + brightness_limits: + max_brightness: 90% + +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 + - platform: rgb + id: test_rgb_light_initial_state + name: RGB Light + red: test_ledc_1 + green: test_ledc_2 + blue: test_ledc_3 + initial_state: + color_mode: rgb + red: 100% + green: 50% + blue: 50% diff --git a/tests/components/light/test.esp32-ard.yaml b/tests/components/light/test.esp32-ard.yaml index 1d0b4cd8f0..925197182c 100644 --- a/tests/components/light/test.esp32-ard.yaml +++ b/tests/components/light/test.esp32-ard.yaml @@ -1,23 +1,3 @@ -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% - brightness_limits: - max_brightness: 90% - output: - platform: gpio id: test_binary @@ -38,97 +18,4 @@ output: 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 +<<: !include common.yaml diff --git a/tests/components/light/test.esp32-c3-ard.yaml b/tests/components/light/test.esp32-c3-ard.yaml index 79171805a6..317d5748a3 100644 --- a/tests/components/light/test.esp32-c3-ard.yaml +++ b/tests/components/light/test.esp32-c3-ard.yaml @@ -1,23 +1,3 @@ -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% - brightness_limits: - max_brightness: 90% - output: - platform: gpio id: test_binary @@ -38,97 +18,4 @@ output: 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 +<<: !include common.yaml diff --git a/tests/components/light/test.esp32-c3-idf.yaml b/tests/components/light/test.esp32-c3-idf.yaml index 79171805a6..317d5748a3 100644 --- a/tests/components/light/test.esp32-c3-idf.yaml +++ b/tests/components/light/test.esp32-c3-idf.yaml @@ -1,23 +1,3 @@ -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% - brightness_limits: - max_brightness: 90% - output: - platform: gpio id: test_binary @@ -38,97 +18,4 @@ output: 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 +<<: !include common.yaml diff --git a/tests/components/light/test.esp32-idf.yaml b/tests/components/light/test.esp32-idf.yaml index 1d0b4cd8f0..925197182c 100644 --- a/tests/components/light/test.esp32-idf.yaml +++ b/tests/components/light/test.esp32-idf.yaml @@ -1,23 +1,3 @@ -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% - brightness_limits: - max_brightness: 90% - output: - platform: gpio id: test_binary @@ -38,97 +18,4 @@ output: 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 +<<: !include common.yaml diff --git a/tests/components/light/test.esp8266-ard.yaml b/tests/components/light/test.esp8266-ard.yaml index 555e1a1b67..518011e925 100644 --- a/tests/components/light/test.esp8266-ard.yaml +++ b/tests/components/light/test.esp8266-ard.yaml @@ -1,23 +1,3 @@ -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% - brightness_limits: - max_brightness: 90% - output: - platform: gpio id: test_binary @@ -38,97 +18,4 @@ output: 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 +<<: !include common.yaml diff --git a/tests/components/light/test.rp2040-ard.yaml b/tests/components/light/test.rp2040-ard.yaml index a509bc85c9..a5a37fd559 100644 --- a/tests/components/light/test.rp2040-ard.yaml +++ b/tests/components/light/test.rp2040-ard.yaml @@ -1,23 +1,3 @@ -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% - brightness_limits: - max_brightness: 90% - output: - platform: gpio id: test_binary @@ -38,97 +18,4 @@ output: 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 +<<: !include common.yaml 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 diff --git a/tests/components/lvgl/common.yaml b/tests/components/lvgl/common.yaml index 7ef7772ac9..cebc3caaa7 100644 --- a/tests/components/lvgl/common.yaml +++ b/tests/components/lvgl/common.yaml @@ -93,7 +93,7 @@ light: - platform: lvgl name: LVGL LED id: lv_light - led: lv_led + widget: lv_led binary_sensor: - platform: lvgl @@ -127,6 +127,11 @@ binary_sensor: - platform: lvgl name: LVGL checkbox widget: checkbox_id + on_state: + then: + - lvgl.image.update: + id: lv_image + src: !lambda if (x) return id(cat_image); else return id(dog_image); wifi: ssid: SSID @@ -135,3 +140,9 @@ wifi: time: platform: sntp id: time_id + +text: + - id: lvgl_text + platform: lvgl + widget: hello_label + mode: text diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 0feb6d6ce6..9bfbb5fc95 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -1,12 +1,50 @@ +substitutions: + light_recessed: "\U000F179B" + wall_sconce_round: "\U000F0748" + gas_burner: "\U000F1A1B" + home_icon: "\U000F02DC" + menu_left: "\U000F0A02" + menu_right: "\U000F035F" + close: "\U000F0156" + delete: "\U000F01B4" + backspace: "\U000F006E" + check: "\U000F012C" + arrow_down: "\U000F004B" + lvgl: - log_level: TRACE + log_level: debug + resume_on_input: true + on_pause: + logger.log: LVGL is Paused + on_resume: + logger.log: LVGL has resumed 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 @@ -18,8 +56,8 @@ lvgl: border_width: 0 radius: 0 pad_all: 0 - border_color: 0x0077b3 - text_color: 0xFFFFFF + border_color: tomato + text_color: springgreen width: 100% height: 30 border_side: [left, top] @@ -31,7 +69,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 @@ -47,11 +85,37 @@ lvgl: border_width: 2 pad_all: 4 align: center + - id: image_recolor + image_recolor: 0x10ca1e + image_recolor_opa: cover touchscreens: - 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: @@ -61,6 +125,8 @@ lvgl: on_unload: - logger.log: page unloaded - lvgl.widget.focus: mark + - lvgl.widget.redraw: hello_label + - lvgl.widget.redraw: on_all_events: logger.log: format: "Event %s" @@ -74,6 +140,19 @@ lvgl: flex_align_cross: start flex_align_track: end widgets: + - roller: + id: lv_roller + visible_row_count: 2 + anim_time: 500ms + options: + - Nov + - Dec + selected_index: 1 + on_value: + then: + - logger.log: + format: "Roller changed = %d: %s" + args: [x, text.c_str()] - animimg: height: 60 id: anim_img @@ -92,12 +171,17 @@ lvgl: align: center text_font: montserrat_40 border_post: true + on_press: + lvgl.label.update: + id: hello_label + text: Goodbye on_click: then: - lvgl.animimg.stop: anim_img - lvgl.update: disp_bg_color: 0xffff00 disp_bg_image: cat_image + - lvgl.widget.show: message_box - label: text: "Hello shiny day" text_color: 0xFFFFFF @@ -176,9 +260,13 @@ lvgl: y: 120 - buttonmatrix: on_press: - logger.log: - format: "matrix button pressed: %d" - args: ["x"] + then: + - logger.log: + format: "matrix button pressed: %d" + args: ["x"] + - lvgl.widget.show: b_matrix + - lvgl.widget.redraw: + on_long_press: lvgl.matrix.button.update: id: [button_a, button_e, button_c] @@ -235,6 +323,13 @@ lvgl: id: button_button width: 20% height: 10% + transform_angle: !lambda return 180*100; + arc_width: !lambda return 4; + border_width: !lambda return 6; + shadow_ofs_x: !lambda return 6; + shadow_ofs_y: !lambda return 6; + shadow_spread: !lambda return 6; + shadow_width: !lambda return 6; pressed: bg_color: light_blue checkable: true @@ -331,9 +426,10 @@ lvgl: spin_time: 2s align: left_mid - image: + id: lv_image src: cat_image align: top_left - y: 50 + y: "50" - tileview: id: tileview_id scrollbar_mode: active @@ -362,6 +458,34 @@ lvgl: - id: page2 widgets: + - qrcode: + id: lv_qr + align: left_mid + size: 100 + light_color: whitesmoke + dark_color: steelblue + text: esphome.io + on_click: + lvgl.qrcode.update: + id: lv_qr + text: homeassistant.io + + - 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 @@ -536,15 +660,107 @@ lvgl: - name: Cat id: tabview_tab_2 widgets: + - dropdown: + indicator: + text_font: helvetica20 + id: lv_dropdown + options: + - First + - Second + - Third + - 6th + - 7th + - 8th + - 9th + selected_index: 2 + dir: top + symbol: ${arrow_down} + dropdown_list: + max_height: 100px + bg_color: 0x000080 + text_color: 0xFF00 + selected: + bg_color: 0xFFFF00 + checked: + bg_color: 0x00 + text_color: 0xFF0000 + scrollbar: + bg_color: 0xFF + on_value: + logger.log: + format: "Dropdown changed = %d: %s" + args: [x, text.c_str()] + on_cancel: + logger.log: + format: "Dropdown closed = %d" + args: [x] - image: src: cat_image on_click: then: + - lvgl.dropdown.update: + id: lv_dropdown + options: + ["First", "Second", "Third", "4th", "5th", "6th", "7th", "8th", "9th", "10th", "11th"] + selected_index: 3 - logger.log: Cat image clicked - lvgl.tabview.select: id: tabview_id index: 0 animated: true + - meter: + height: 200px + width: 200px + indicator: + bg_color: 0xFF + radius: 0 + bg_opa: TRANSP + text_color: 0xFFFFFF + scales: + - ticks: + width: 1 + count: 61 + length: 20 + color: 0xFFFFFF + range_from: 0 + range_to: 60 + angle_range: 360 + rotation: 270 + indicators: + - line: + opa: 50% + id: minute_hand + color: 0xFF0000 + r_mod: -1 + width: 3 + - + angle_range: 330 + rotation: 300 + range_from: 1 + range_to: 12 + ticks: + width: 1 + count: 12 + length: 1 + major: + stride: 1 + width: 4 + length: 8 + color: 0xC0C0C0 + label_gap: 6 + - angle_range: 360 + rotation: 270 + range_from: 0 + range_to: 720 + indicators: + - line: + id: hour_hand + value: 180 + width: 4 + color: 0xA0A0A0 + r_mod: -20 + opa: 0% + font: - file: "gfonts://Roboto" id: space16 @@ -562,3 +778,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 diff --git a/tests/components/lvgl/test.esp32-ard.yaml b/tests/components/lvgl/test.esp32-ard.yaml index 51593e7967..80d5ce503f 100644 --- a/tests/components/lvgl/test.esp32-ard.yaml +++ b/tests/components/lvgl/test.esp32-ard.yaml @@ -44,6 +44,7 @@ binary_sensor: number: GPIO39 inverted: true lvgl: + draw_rounding: 8 encoders: group: switches initial_focus: button_button diff --git a/tests/components/lvgl/test.esp32-idf.yaml b/tests/components/lvgl/test.esp32-idf.yaml index 927d72d15c..05a1f243ed 100644 --- a/tests/components/lvgl/test.esp32-idf.yaml +++ b/tests/components/lvgl/test.esp32-idf.yaml @@ -10,7 +10,7 @@ sensor: - platform: rotary_encoder name: "Rotary Encoder" id: encoder - pin_a: 2 + pin_a: 3 pin_b: 1 internal: true diff --git a/tests/components/lvgl/test.host.yaml b/tests/components/lvgl/test.host.yaml new file mode 100644 index 0000000000..3a490bbe15 --- /dev/null +++ b/tests/components/lvgl/test.host.yaml @@ -0,0 +1,11 @@ +display: + - platform: sdl + auto_clear_enabled: false + dimensions: + width: 480 + height: 480 + +touchscreen: + - platform: sdl + +lvgl: diff --git a/tests/components/max17043/common.yaml b/tests/components/max17043/common.yaml new file mode 100644 index 0000000000..c2f324212e --- /dev/null +++ b/tests/components/max17043/common.yaml @@ -0,0 +1,19 @@ +esphome: + on_boot: + then: + - max17043.sleep_mode: max17043_id + +i2c: + - id: i2c_id + scl: ${scl_pin} + sda: ${sda_pin} + +sensor: + - platform: max17043 + id: max17043_id + i2c_id: i2c_id + battery_voltage: + name: "Battery Voltage" + battery_level: + name: Battery + update_interval: 10s diff --git a/tests/components/max17043/test.esp32-ard.yaml b/tests/components/max17043/test.esp32-ard.yaml new file mode 100644 index 0000000000..c84e0a5c2e --- /dev/null +++ b/tests/components/max17043/test.esp32-ard.yaml @@ -0,0 +1,6 @@ +substitutions: + sda_pin: GPIO21 + scl_pin: GPIO22 + +<<: !include common.yaml + diff --git a/tests/components/max17043/test.esp32-c3-ard.yaml b/tests/components/max17043/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..9a1477d4b9 --- /dev/null +++ b/tests/components/max17043/test.esp32-c3-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + sda_pin: GPIO8 + scl_pin: GPIO10 + +<<: !include common.yaml diff --git a/tests/components/max17043/test.esp32-c3-idf.yaml b/tests/components/max17043/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..9a1477d4b9 --- /dev/null +++ b/tests/components/max17043/test.esp32-c3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + sda_pin: GPIO8 + scl_pin: GPIO10 + +<<: !include common.yaml diff --git a/tests/components/max17043/test.esp32-idf.yaml b/tests/components/max17043/test.esp32-idf.yaml new file mode 100644 index 0000000000..c6615f51cd --- /dev/null +++ b/tests/components/max17043/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + sda_pin: GPIO21 + scl_pin: GPIO22 + +<<: !include common.yaml diff --git a/tests/components/max17043/test.esp8266-ard.yaml b/tests/components/max17043/test.esp8266-ard.yaml new file mode 100644 index 0000000000..a87353b78b --- /dev/null +++ b/tests/components/max17043/test.esp8266-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + sda_pin: GPIO4 + scl_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/max17043/test.rp2040-ard.yaml b/tests/components/max17043/test.rp2040-ard.yaml new file mode 100644 index 0000000000..c6615f51cd --- /dev/null +++ b/tests/components/max17043/test.rp2040-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + sda_pin: GPIO21 + scl_pin: GPIO22 + +<<: !include common.yaml 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 + diff --git a/tests/components/media_player/common.yaml b/tests/components/media_player/common.yaml index 24b85cd474..af0d5c7765 100644 --- a/tests/components/media_player/common.yaml +++ b/tests/components/media_player/common.yaml @@ -27,6 +27,10 @@ media_player: media_player.is_idle: - wait_until: media_player.is_playing: + - wait_until: + media_player.is_announcing: + - wait_until: + media_player.is_paused: - media_player.volume_up: - media_player.volume_down: - media_player.volume_set: 50% 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 diff --git a/tests/components/mopeka_pro_check/common.yaml b/tests/components/mopeka_pro_check/common.yaml index 147cbcb9de..3533ecf631 100644 --- a/tests/components/mopeka_pro_check/common.yaml +++ b/tests/components/mopeka_pro_check/common.yaml @@ -14,3 +14,20 @@ sensor: name: Propane test distance battery_level: name: Propane test battery level + + - platform: mopeka_pro_check + mac_address: AA:BB:CC:DD:EE:FF + tank_type: 20LB_V + temperature: + name: "Propane test2 temp" + level: + name: "Propane test2 level" + distance: + name: "Propane test2 distance" + battery_level: + name: "Propane test2 battery level" + signal_quality: + name: "propane test2 read quality" + ignored_reads: + name: "propane test2 ignored reads" + minimum_signal_quality: "LOW" diff --git a/tests/components/mqtt/common.yaml b/tests/components/mqtt/common.yaml index b7d1655ec9..5ed6335d65 100644 --- a/tests/components/mqtt/common.yaml +++ b/tests/components/mqtt/common.yaml @@ -10,6 +10,7 @@ mqtt: port: 1883 username: debug password: debug + clean_session: True client_id: someclient use_abbreviations: false discovery: true @@ -226,6 +227,7 @@ datetime: type: date state_topic: some/topic/date qos: 2 + subscribe_qos: 2 set_action: - logger.log: "set_value" on_value: diff --git a/tests/components/nau7802/common.yaml b/tests/components/nau7802/common.yaml new file mode 100644 index 0000000000..2501911a3f --- /dev/null +++ b/tests/components/nau7802/common.yaml @@ -0,0 +1,13 @@ +sensor: + - platform: nau7802 + id: test_id + name: weight + i2c_id: i2c_nau7802 + gain: 32 + ldo_voltage: "3.0v" + samples_per_second: 10 + on_value: + then: + - nau7802.calibrate_external_offset: test_id + - nau7802.calibrate_internal_offset: test_id + - nau7802.calibrate_gain: test_id diff --git a/tests/components/nau7802/test.esp32-ard.yaml b/tests/components/nau7802/test.esp32-ard.yaml new file mode 100644 index 0000000000..73a4aa4251 --- /dev/null +++ b/tests/components/nau7802/test.esp32-ard.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_nau7802 + scl: 16 + sda: 17 + +<<: !include common.yaml diff --git a/tests/components/nau7802/test.esp32-c3-ard.yaml b/tests/components/nau7802/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..769468f9ec --- /dev/null +++ b/tests/components/nau7802/test.esp32-c3-ard.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_nau7802 + scl: 5 + sda: 4 + +<<: !include common.yaml diff --git a/tests/components/nau7802/test.esp32-c3-idf.yaml b/tests/components/nau7802/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..769468f9ec --- /dev/null +++ b/tests/components/nau7802/test.esp32-c3-idf.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_nau7802 + scl: 5 + sda: 4 + +<<: !include common.yaml diff --git a/tests/components/nau7802/test.esp32-idf.yaml b/tests/components/nau7802/test.esp32-idf.yaml new file mode 100644 index 0000000000..73a4aa4251 --- /dev/null +++ b/tests/components/nau7802/test.esp32-idf.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_nau7802 + scl: 16 + sda: 17 + +<<: !include common.yaml diff --git a/tests/components/nau7802/test.esp8266-ard.yaml b/tests/components/nau7802/test.esp8266-ard.yaml new file mode 100644 index 0000000000..769468f9ec --- /dev/null +++ b/tests/components/nau7802/test.esp8266-ard.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_nau7802 + scl: 5 + sda: 4 + +<<: !include common.yaml diff --git a/tests/components/nau7802/test.rp2040-ard.yaml b/tests/components/nau7802/test.rp2040-ard.yaml new file mode 100644 index 0000000000..769468f9ec --- /dev/null +++ b/tests/components/nau7802/test.rp2040-ard.yaml @@ -0,0 +1,6 @@ +i2c: + - id: i2c_nau7802 + scl: 5 + sda: 4 + +<<: !include common.yaml 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 diff --git a/tests/components/npi19/common.yaml b/tests/components/npi19/common.yaml new file mode 100644 index 0000000000..012e05695e --- /dev/null +++ b/tests/components/npi19/common.yaml @@ -0,0 +1,16 @@ +i2c: + id: i2c_bus + scl: ${scl_pin} + sda: ${sda_pin} + frequency: 200kHz + +sensor: + - platform: npi19 + update_interval: 1s + i2c_id: i2c_bus + + temperature: + name: water temperature + + raw_pressure: + name: water pressure diff --git a/tests/components/npi19/test.esp32-ard.yaml b/tests/components/npi19/test.esp32-ard.yaml new file mode 100644 index 0000000000..3b761d3fc1 --- /dev/null +++ b/tests/components/npi19/test.esp32-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO22 + sda_pin: GPIO21 + +<<: !include common.yaml diff --git a/tests/components/npi19/test.esp32-idf.yaml b/tests/components/npi19/test.esp32-idf.yaml new file mode 100644 index 0000000000..3b761d3fc1 --- /dev/null +++ b/tests/components/npi19/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO22 + sda_pin: GPIO21 + +<<: !include common.yaml diff --git a/tests/components/npi19/test.esp32-s3-ard.yaml b/tests/components/npi19/test.esp32-s3-ard.yaml new file mode 100644 index 0000000000..4942e3c2b3 --- /dev/null +++ b/tests/components/npi19/test.esp32-s3-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO40 + sda_pin: GPIO41 + +<<: !include common.yaml diff --git a/tests/components/npi19/test.esp32-s3-idf.yaml b/tests/components/npi19/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..4942e3c2b3 --- /dev/null +++ b/tests/components/npi19/test.esp32-s3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO40 + sda_pin: GPIO41 + +<<: !include common.yaml diff --git a/tests/components/npi19/test.esp8266-ard.yaml b/tests/components/npi19/test.esp8266-ard.yaml new file mode 100644 index 0000000000..3be5e53dcb --- /dev/null +++ b/tests/components/npi19/test.esp8266-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO05 + sda_pin: GPIO04 + +<<: !include common.yaml diff --git a/tests/components/online_image/common-esp32.yaml b/tests/components/online_image/common-esp32.yaml index d3a304cdc0..787a1ad368 100644 --- a/tests/components/online_image/common-esp32.yaml +++ b/tests/components/online_image/common-esp32.yaml @@ -4,13 +4,13 @@ spi: - id: spi_main_lcd clk_pin: 16 mosi_pin: 17 - miso_pin: 15 + miso_pin: 18 display: - platform: ili9xxx id: main_lcd model: ili9342 - cs_pin: 12 + cs_pin: 20 dc_pin: 13 reset_pin: 21 invert_colors: true diff --git a/tests/components/online_image/common.yaml b/tests/components/online_image/common.yaml index 8f7ea6238b..5c6feb4c81 100644 --- a/tests/components/online_image/common.yaml +++ b/tests/components/online_image/common.yaml @@ -34,4 +34,12 @@ time: - online_image.set_url: id: online_rgba_image url: http://www.example.org/example.png + - online_image.set_url: + id: online_rgba_image + url: !lambda |- + return "http://www.example.org/example.png"; + - online_image.set_url: + id: online_rgba_image + url: !lambda |- + return str_sprintf("http://homeassistant.local:8123"); diff --git a/tests/components/opentherm/common.yaml b/tests/components/opentherm/common.yaml new file mode 100644 index 0000000000..27cbae280a --- /dev/null +++ b/tests/components/opentherm/common.yaml @@ -0,0 +1,76 @@ +api: +wifi: + ap: + ssid: "Thermostat" + password: "MySecretThemostat" + +opentherm: + in_pin: 4 + out_pin: 5 + ch_enable: true + dhw_enable: false + cooling_enable: false + otc_active: false + ch2_active: true + summer_mode_active: true + dhw_block: true + sync_mode: true + +sensor: + - platform: opentherm + rel_mod_level: + name: "Boiler Relative modulation level" + ch_pressure: + name: "Boiler Water pressure in CH circuit" + dhw_flow_rate: + name: "Boiler Water flow rate in DHW circuit" + t_boiler: + name: "Boiler water temperature" + t_dhw: + name: "Boiler DHW temperature" + t_outside: + name: "Boiler Outside temperature" + t_ret: + name: "Boiler Return water temperature" + t_storage: + name: "Boiler Solar storage temperature" + t_collector: + name: "Boiler Solar collector temperature" + t_flow_ch2: + name: "Boiler Flow water temperature CH2 circuit" + t_dhw2: + name: "Boiler Domestic hot water temperature 2" + t_exhaust: + name: "Boiler Exhaust temperature" + burner_starts: + name: "Boiler Number of starts burner" + ch_pump_starts: + name: "Boiler Number of starts CH pump" + dhw_pump_valve_starts: + name: "Boiler Number of starts DHW pump/valve" + dhw_burner_starts: + name: "Boiler Number of starts burner during DHW mode" + burner_operation_hours: + name: "Boiler Number of hours that burner is in operation (i.e. flame on)" + ch_pump_operation_hours: + name: "Boiler Number of hours that CH pump has been running" + dhw_pump_valve_operation_hours: + name: "Boiler Number of hours that DHW pump has been running or DHW valve has been opened" + dhw_burner_operation_hours: + name: "Boiler Number of hours that burner is in operation during DHW mode" + t_dhw_set_ub: + name: "Boiler Upper bound for adjustement of DHW setpoint" + t_dhw_set_lb: + name: "Boiler Lower bound for adjustement of DHW setpoint" + max_t_set_ub: + name: "Boiler Upper bound for adjustement of max CH setpoint" + max_t_set_lb: + name: "Boiler Lower bound for adjustement of max CH setpoint" + t_dhw_set: + name: "Boiler Domestic hot water temperature setpoint" + max_t_set: + name: "Boiler Maximum allowable CH water setpoint" + otc_hc_ratio_ub: + name: "OTC heat curve ratio upper bound" + otc_hc_ratio_lb: + name: "OTC heat curve ratio lower bound" 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 diff --git a/tests/components/prometheus/common.yaml b/tests/components/prometheus/common.yaml index c8ce17da88..7aa509f8b2 100644 --- a/tests/components/prometheus/common.yaml +++ b/tests/components/prometheus/common.yaml @@ -13,9 +13,23 @@ sensor: } update_interval: 60s +text_sensor: + - platform: template + id: template_text_sensor1 + lambda: |- + if (millis() > 10000) { + return {"Hello World"}; + } else { + return {"Goodbye (cruel) World"}; + } + update_interval: 60s + prometheus: include_internal: true relabel: template_sensor1: id: hellow_world name: Hello World + template_text_sensor1: + id: hello_text + name: Text Substitution diff --git a/tests/components/qspi_amoled/common.yaml b/tests/components/qspi_dbi/common.yaml similarity index 73% rename from tests/components/qspi_amoled/common.yaml rename to tests/components/qspi_dbi/common.yaml index 01d1a63bcb..655af304af 100644 --- a/tests/components/qspi_amoled/common.yaml +++ b/tests/components/qspi_dbi/common.yaml @@ -5,7 +5,7 @@ spi: data_pins: [14, 10, 16, 12] display: - - platform: qspi_amoled + - platform: qspi_dbi model: RM690B0 data_rate: 80MHz spi_mode: mode0 @@ -20,9 +20,10 @@ display: reset_pin: 13 enable_pin: 9 - - platform: qspi_amoled - model: RM67162 + - platform: qspi_dbi + model: CUSTOM id: main_lcd + draw_from_origin: true dimensions: height: 240 width: 536 @@ -34,3 +35,10 @@ display: cs_pin: 6 reset_pin: 17 enable_pin: 38 + init_sequence: + - [0x3A, 0x66] + - [0x11] + - delay 120ms + - [0x29] + - delay 20ms + diff --git a/tests/components/qspi_dbi/test.esp32-s3-idf.yaml b/tests/components/qspi_dbi/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/qspi_dbi/test.esp32-s3-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/speaker/test.esp32-ard.yaml b/tests/components/speaker/test.esp32-ard.yaml index e10c3e88c1..396b4d95ea 100644 --- a/tests/components/speaker/test.esp32-ard.yaml +++ b/tests/components/speaker/test.esp32-ard.yaml @@ -1,10 +1,13 @@ esphome: on_boot: then: + - speaker.mute_on: + - speaker.mute_off: - if: condition: speaker.is_stopped then: - speaker.play: [0, 1, 2, 3] + - speaker.volume_set: 0.9 - if: condition: speaker.is_playing then: @@ -21,4 +24,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..636aeba766 100644 --- a/tests/components/speaker/test.esp32-c3-ard.yaml +++ b/tests/components/speaker/test.esp32-c3-ard.yaml @@ -1,10 +1,13 @@ esphome: on_boot: then: + - speaker.mute_on: + - speaker.mute_off: - if: condition: speaker.is_stopped then: - speaker.play: [0, 1, 2, 3] + - speaker.volume_set: 0.9 - if: condition: speaker.is_playing then: @@ -21,4 +24,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..636aeba766 100644 --- a/tests/components/speaker/test.esp32-c3-idf.yaml +++ b/tests/components/speaker/test.esp32-c3-idf.yaml @@ -1,10 +1,13 @@ esphome: on_boot: then: + - speaker.mute_on: + - speaker.mute_off: - if: condition: speaker.is_stopped then: - speaker.play: [0, 1, 2, 3] + - speaker.volume_set: 0.9 - if: condition: speaker.is_playing then: @@ -21,4 +24,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..b69440b133 100644 --- a/tests/components/speaker/test.esp32-idf.yaml +++ b/tests/components/speaker/test.esp32-idf.yaml @@ -1,10 +1,13 @@ esphome: on_boot: then: + - speaker.mute_on: + - speaker.mute_off: - if: condition: speaker.is_stopped then: - speaker.play: [0, 1, 2, 3] + - speaker.volume_set: 0.9 - if: condition: speaker.is_playing then: @@ -16,9 +19,17 @@ i2s_audio: i2s_bclk_pin: 17 i2s_mclk_pin: 15 +i2c: + scl: 12 + sda: 10 + +audio_dac: + - platform: aic3204 + id: internal_dac + speaker: - platform: i2s_audio - id: speaker_id + id: speaker_with_audio_dac_id + audio_dac: internal_dac dac_type: external - i2s_dout_pin: 13 - mode: mono + i2s_dout_pin: 14 diff --git a/tests/components/tc74/test.esp32-ard.yaml b/tests/components/tc74/test.esp32-ard.yaml new file mode 100644 index 0000000000..ef9b40e184 --- /dev/null +++ b/tests/components/tc74/test.esp32-ard.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_tc74 + scl: 16 + sda: 17 + +sensor: + - platform: tc74 + name: TC74 Temperature diff --git a/tests/components/tc74/test.esp32-c3-ard.yaml b/tests/components/tc74/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..e1a373fbf4 --- /dev/null +++ b/tests/components/tc74/test.esp32-c3-ard.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_tc74 + scl: 5 + sda: 4 + +sensor: + - platform: tc74 + name: TC74 Temperature diff --git a/tests/components/tc74/test.esp32-c3-idf.yaml b/tests/components/tc74/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..e1a373fbf4 --- /dev/null +++ b/tests/components/tc74/test.esp32-c3-idf.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_tc74 + scl: 5 + sda: 4 + +sensor: + - platform: tc74 + name: TC74 Temperature diff --git a/tests/components/tc74/test.esp32-idf.yaml b/tests/components/tc74/test.esp32-idf.yaml new file mode 100644 index 0000000000..ef9b40e184 --- /dev/null +++ b/tests/components/tc74/test.esp32-idf.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_tc74 + scl: 16 + sda: 17 + +sensor: + - platform: tc74 + name: TC74 Temperature diff --git a/tests/components/tc74/test.esp8266-ard.yaml b/tests/components/tc74/test.esp8266-ard.yaml new file mode 100644 index 0000000000..e1a373fbf4 --- /dev/null +++ b/tests/components/tc74/test.esp8266-ard.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_tc74 + scl: 5 + sda: 4 + +sensor: + - platform: tc74 + name: TC74 Temperature diff --git a/tests/components/tc74/test.rp2040-ard.yaml b/tests/components/tc74/test.rp2040-ard.yaml new file mode 100644 index 0000000000..e1a373fbf4 --- /dev/null +++ b/tests/components/tc74/test.rp2040-ard.yaml @@ -0,0 +1,8 @@ +i2c: + - id: i2c_tc74 + scl: 5 + sda: 4 + +sensor: + - platform: tc74 + name: TC74 Temperature diff --git a/tests/components/tca9555/test.esp32-ard.yaml b/tests/components/tca9555/test.esp32-ard.yaml new file mode 100644 index 0000000000..e0c046b443 --- /dev/null +++ b/tests/components/tca9555/test.esp32-ard.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_tca9555 + scl: 16 + sda: 17 + +tca9555: + - id: tca9555_hub + address: 0x21 + +binary_sensor: + - platform: gpio + id: tca9555_binary_sensor + name: TCA9555 Binary Sensor + pin: + tca9555: tca9555_hub + number: 1 + mode: INPUT + inverted: true + +output: + - platform: gpio + id: tca9555_output + pin: + tca9555: tca9555_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/tca9555/test.esp32-c3-ard.yaml b/tests/components/tca9555/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..5c49b27640 --- /dev/null +++ b/tests/components/tca9555/test.esp32-c3-ard.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_tca9555 + scl: 5 + sda: 4 + +tca9555: + - id: tca9555_hub + address: 0x21 + +binary_sensor: + - platform: gpio + id: tca9555_binary_sensor + name: TCA9555 Binary Sensor + pin: + tca9555: tca9555_hub + number: 1 + mode: INPUT + inverted: true + +output: + - platform: gpio + id: tca9555_output + pin: + tca9555: tca9555_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/tca9555/test.esp32-c3-idf.yaml b/tests/components/tca9555/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..5c49b27640 --- /dev/null +++ b/tests/components/tca9555/test.esp32-c3-idf.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_tca9555 + scl: 5 + sda: 4 + +tca9555: + - id: tca9555_hub + address: 0x21 + +binary_sensor: + - platform: gpio + id: tca9555_binary_sensor + name: TCA9555 Binary Sensor + pin: + tca9555: tca9555_hub + number: 1 + mode: INPUT + inverted: true + +output: + - platform: gpio + id: tca9555_output + pin: + tca9555: tca9555_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/tca9555/test.esp32-idf.yaml b/tests/components/tca9555/test.esp32-idf.yaml new file mode 100644 index 0000000000..e0c046b443 --- /dev/null +++ b/tests/components/tca9555/test.esp32-idf.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_tca9555 + scl: 16 + sda: 17 + +tca9555: + - id: tca9555_hub + address: 0x21 + +binary_sensor: + - platform: gpio + id: tca9555_binary_sensor + name: TCA9555 Binary Sensor + pin: + tca9555: tca9555_hub + number: 1 + mode: INPUT + inverted: true + +output: + - platform: gpio + id: tca9555_output + pin: + tca9555: tca9555_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/tca9555/test.esp8266-ard.yaml b/tests/components/tca9555/test.esp8266-ard.yaml new file mode 100644 index 0000000000..5c49b27640 --- /dev/null +++ b/tests/components/tca9555/test.esp8266-ard.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_tca9555 + scl: 5 + sda: 4 + +tca9555: + - id: tca9555_hub + address: 0x21 + +binary_sensor: + - platform: gpio + id: tca9555_binary_sensor + name: TCA9555 Binary Sensor + pin: + tca9555: tca9555_hub + number: 1 + mode: INPUT + inverted: true + +output: + - platform: gpio + id: tca9555_output + pin: + tca9555: tca9555_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/tca9555/test.rp2040-ard.yaml b/tests/components/tca9555/test.rp2040-ard.yaml new file mode 100644 index 0000000000..5c49b27640 --- /dev/null +++ b/tests/components/tca9555/test.rp2040-ard.yaml @@ -0,0 +1,27 @@ +i2c: + - id: i2c_tca9555 + scl: 5 + sda: 4 + +tca9555: + - id: tca9555_hub + address: 0x21 + +binary_sensor: + - platform: gpio + id: tca9555_binary_sensor + name: TCA9555 Binary Sensor + pin: + tca9555: tca9555_hub + number: 1 + mode: INPUT + inverted: true + +output: + - platform: gpio + id: tca9555_output + pin: + tca9555: tca9555_hub + number: 0 + mode: OUTPUT + inverted: false diff --git a/tests/components/tem3200/common.yaml b/tests/components/tem3200/common.yaml new file mode 100644 index 0000000000..392c853bf4 --- /dev/null +++ b/tests/components/tem3200/common.yaml @@ -0,0 +1,16 @@ +i2c: + id: i2c_bus + scl: ${scl_pin} + sda: ${sda_pin} + frequency: 200kHz + +sensor: + - platform: tem3200 + update_interval: 1s + i2c_id: i2c_bus + + temperature: + name: water temperature + + raw_pressure: + name: water pressure diff --git a/tests/components/tem3200/test.esp32-ard.yaml b/tests/components/tem3200/test.esp32-ard.yaml new file mode 100644 index 0000000000..3b761d3fc1 --- /dev/null +++ b/tests/components/tem3200/test.esp32-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO22 + sda_pin: GPIO21 + +<<: !include common.yaml diff --git a/tests/components/tem3200/test.esp32-idf.yaml b/tests/components/tem3200/test.esp32-idf.yaml new file mode 100644 index 0000000000..3b761d3fc1 --- /dev/null +++ b/tests/components/tem3200/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO22 + sda_pin: GPIO21 + +<<: !include common.yaml diff --git a/tests/components/tem3200/test.esp32-s3-ard.yaml b/tests/components/tem3200/test.esp32-s3-ard.yaml new file mode 100644 index 0000000000..4942e3c2b3 --- /dev/null +++ b/tests/components/tem3200/test.esp32-s3-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO40 + sda_pin: GPIO41 + +<<: !include common.yaml diff --git a/tests/components/tem3200/test.esp32-s3-idf.yaml b/tests/components/tem3200/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..4942e3c2b3 --- /dev/null +++ b/tests/components/tem3200/test.esp32-s3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO40 + sda_pin: GPIO41 + +<<: !include common.yaml diff --git a/tests/components/tem3200/test.esp8266-ard.yaml b/tests/components/tem3200/test.esp8266-ard.yaml new file mode 100644 index 0000000000..3be5e53dcb --- /dev/null +++ b/tests/components/tem3200/test.esp8266-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO05 + sda_pin: GPIO04 + +<<: !include common.yaml diff --git a/tests/components/template/common.yaml b/tests/components/template/common.yaml index 9e89424d8a..3565926933 100644 --- a/tests/components/template/common.yaml +++ b/tests/components/template/common.yaml @@ -46,6 +46,13 @@ binary_sensor: // Garage Door is closed. return false; } + - platform: template + id: other_binary_sensor + name: "Garage Door Closed" + condition: + sensor.in_range: + id: template_sens + below: 30.0 output: - platform: template 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 diff --git a/tests/components/web_server/common_v3.yaml b/tests/components/web_server/common_v3.yaml new file mode 100644 index 0000000000..69f4b67f15 --- /dev/null +++ b/tests/components/web_server/common_v3.yaml @@ -0,0 +1,37 @@ +packages: + device_base: !include common.yaml + +web_server: + port: 8080 + version: 3 + sorting_groups: + - id: sorting_group_1 + name: "Group 1 Diplayed Last" + sorting_weight: 40 + - id: sorting_group_2 + name: "Group 2 Displayed Third" + sorting_weight: 30 + - id: sorting_group_3 + name: "Group 3 Displayed Second" + sorting_weight: 20 + - id: sorting_group_4 + name: "Group 4 Displayed First" + sorting_weight: 10 + +number: + - platform: template + name: "Template number" + optimistic: true + min_value: 0 + max_value: 100 + step: 1 + web_server: + sorting_group_id: sorting_group_1 + sorting_weight: -1 +switch: + - platform: template + name: "Template Switch" + optimistic: true + web_server: + sorting_group_id: sorting_group_2 + sorting_weight: -10 diff --git a/tests/components/web_server/test_v3.esp32-ard.yaml b/tests/components/web_server/test_v3.esp32-ard.yaml new file mode 100644 index 0000000000..00d05521e4 --- /dev/null +++ b/tests/components/web_server/test_v3.esp32-ard.yaml @@ -0,0 +1 @@ +<<: !include common_v3.yaml diff --git a/tests/test_build_components/build_components_base.rp2040-ard.yaml b/tests/test_build_components/build_components_base.rp2040-ard.yaml index 6c6a27e0a7..4fb8d51333 100644 --- a/tests/test_build_components/build_components_base.rp2040-ard.yaml +++ b/tests/test_build_components/build_components_base.rp2040-ard.yaml @@ -4,9 +4,6 @@ esphome: rp2040: board: rpipicow - framework: - # Waiting for https://github.com/platformio/platform-raspberrypi/pull/36 - platform_version: https://github.com/maxgerhardt/platform-raspberrypi.git logger: level: VERY_VERBOSE