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 d277ec06c7..5c686605c3 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -46,7 +46,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@v6.7.0 + uses: docker/build-push-action@v6.9.0 env: DOCKER_BUILD_SUMMARY: false DOCKER_BUILD_RECORD_UPLOAD: false @@ -72,7 +72,7 @@ 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 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/release.yml b/.github/workflows/release.yml index 522de63360..096b00f0f1 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.12.2 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 1418867240..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.2 + 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 0b1b88fbc8..8fbbacef59 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 @@ -126,6 +131,7 @@ esphome/components/ens160_base/* @latonita @vincentscode esphome/components/ens160_i2c/* @latonita esphome/components/ens160_spi/* @latonita esphome/components/ens210/* @itn3rd77 +esphome/components/es8311/* @kahrendt @kroimon esphome/components/esp32/* @esphome/core esphome/components/esp32_ble/* @Rapsssito @jesserockz esphome/components/esp32_ble_client/* @jesserockz @@ -152,6 +158,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 +166,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 +174,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 +200,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 @@ -232,6 +242,7 @@ 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 @@ -278,6 +289,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 @@ -286,9 +298,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 @@ -316,7 +330,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 @@ -365,7 +379,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 @@ -395,10 +409,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 e255f4e2fc..ed6ce083a8 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -32,33 +32,14 @@ RUN \ python3-setuptools=66.1.1-1 \ python3-venv=3.11.2-1+b1 \ python3-wheel=0.38.4-2 \ - iputils-ping=3:20221126-1 \ - git=1:2.39.2-1.1 \ - curl=7.88.1-10+deb12u7 \ + iputils-ping=3:20221126-1+deb12u1 \ + git=1:2.39.5-0+deb12u1 \ + curl=7.88.1-10+deb12u8 \ openssh-client=1:9.2p1-2+deb12u3 \ python3-cffi=1.15.1-5 \ libcairo2=1.16.0-7 \ libmagic1=1:5.44-3 \ patch=2.7.6-7 \ - && ( \ - ( \ - [ "$TARGETARCH$TARGETVARIANT" = "armv7" ] && \ - apt-get install -y --no-install-recommends \ - build-essential=12.9 \ - python3-dev=3.11.2-1+b1 \ - zlib1g-dev=1:1.2.13.dfsg-1 \ - libjpeg-dev=1:2.1.5-2 \ - libfreetype-dev=2.12.1+dfsg-5+deb12u3 \ - libssl-dev=3.0.14-1~deb12u2 \ - libffi-dev=3.4.4-1 \ - libopenjp2-7=2.5.0-2 \ - libtiff6=4.5.0-6+deb12u1 \ - cargo=0.66.0+ds1-1 \ - pkg-config=1.8.1-1 \ - gcc-arm-linux-gnueabihf=4:12.2.0-3 \ - ) \ - || [ "$TARGETARCH$TARGETVARIANT" != "armv7" ] \ - ) \ && rm -rf \ /tmp/* \ /var/{cache,log}/* \ @@ -86,7 +67,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 \ @@ -97,15 +78,48 @@ RUN \ # tmpfs is for https://github.com/rust-lang/cargo/issues/8719 COPY requirements.txt requirements_optional.txt / -RUN --mount=type=tmpfs,target=/root/.cargo if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \ - 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 +RUN --mount=type=tmpfs,target=/root/.cargo <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 eb3d09ac96..5a308855de 100644 --- a/esphome/components/animation/__init__.py +++ b/esphome/components/animation/__init__.py @@ -271,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) @@ -288,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 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 1c40e8014e..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; @@ -1570,6 +1573,36 @@ message VoiceAssistantAnnounceFinished { 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 6b7051a704..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); } @@ -1223,6 +1225,42 @@ void APIConnection::on_voice_assistant_announce_request(const VoiceAssistantAnno } } +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 @@ -1531,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 e8d66a5e07..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 @@ -152,6 +153,9 @@ class APIConnection : public APIServerConnection { 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 @@ -265,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 2a1552d6fc..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 @@ -7114,6 +7124,140 @@ void VoiceAssistantAnnounceFinished::dump_to(std::string &out) const { 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 6fab1f57e0..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; @@ -1848,6 +1849,53 @@ class VoiceAssistantAnnounceFinished : public ProtoMessage { 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 faa977389a..6e11d7169d 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -496,6 +496,19 @@ bool APIServerConnectionBase::send_voice_assistant_announce_finished(const Voice return this->send_message_(msg, 120); } #endif +#ifdef USE_VOICE_ASSISTANT +#endif +#ifdef USE_VOICE_ASSISTANT +bool APIServerConnectionBase::send_voice_assistant_configuration_response( + const VoiceAssistantConfigurationResponse &msg) { +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "send_voice_assistant_configuration_response: %s", msg.dump().c_str()); +#endif + return this->send_message_(msg, 122); +} +#endif +#ifdef USE_VOICE_ASSISTANT +#endif #ifdef USE_ALARM_CONTROL_PANEL bool APIServerConnectionBase::send_list_entities_alarm_control_panel_response( const ListEntitiesAlarmControlPanelResponse &msg) { @@ -1156,6 +1169,28 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ESP_LOGVV(TAG, "on_voice_assistant_announce_request: %s", msg.dump().c_str()); #endif this->on_voice_assistant_announce_request(msg); +#endif + break; + } + case 121: { +#ifdef USE_VOICE_ASSISTANT + VoiceAssistantConfigurationRequest msg; + msg.decode(msg_data, msg_size); +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "on_voice_assistant_configuration_request: %s", msg.dump().c_str()); +#endif + this->on_voice_assistant_configuration_request(msg); +#endif + break; + } + case 123: { +#ifdef USE_VOICE_ASSISTANT + VoiceAssistantSetConfiguration msg; + msg.decode(msg_data, msg_size); +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "on_voice_assistant_set_configuration: %s", msg.dump().c_str()); +#endif + this->on_voice_assistant_set_configuration(msg); #endif break; } @@ -1646,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 f3803ad628..51b94bf530 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -253,6 +253,15 @@ class APIServerConnectionBase : public ProtoService { #ifdef USE_VOICE_ASSISTANT bool send_voice_assistant_announce_finished(const VoiceAssistantAnnounceFinished &msg); #endif +#ifdef USE_VOICE_ASSISTANT + virtual void on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &value){}; +#endif +#ifdef USE_VOICE_ASSISTANT + bool send_voice_assistant_configuration_response(const VoiceAssistantConfigurationResponse &msg); +#endif +#ifdef USE_VOICE_ASSISTANT + virtual void on_voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &value){}; +#endif #ifdef USE_ALARM_CONTROL_PANEL bool send_list_entities_alarm_control_panel_response(const ListEntitiesAlarmControlPanelResponse &msg); #endif @@ -425,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 @@ -526,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/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..ec68940726 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 @@ -119,10 +119,21 @@ visual_temperature = cv.float_with_unit( ) -def single_visual_temperature(value): - if isinstance(value, dict): - return value +VISUAL_TEMPERATURE_STEP_SCHEMA = cv.Schema( + { + cv.Required(CONF_TARGET_TEMPERATURE): visual_temperature, + cv.Required(CONF_CURRENT_TEMPERATURE): visual_temperature, + } +) + +def visual_temperature_step(value): + + # Allow defining target/current temperature steps separately + if isinstance(value, dict): + return VISUAL_TEMPERATURE_STEP_SCHEMA(value) + + # Otherwise, use the single value for both properties value = visual_temperature(value) return VISUAL_TEMPERATURE_STEP_SCHEMA( { @@ -141,16 +152,6 @@ ControlTrigger = climate_ns.class_( "ControlTrigger", automation.Trigger.template(ClimateCall.operator("ref")) ) -VISUAL_TEMPERATURE_STEP_SCHEMA = cv.Any( - single_visual_temperature, - cv.Schema( - { - cv.Required(CONF_TARGET_TEMPERATURE): visual_temperature, - cv.Required(CONF_CURRENT_TEMPERATURE): visual_temperature, - } - ), -) - CLIMATE_SCHEMA = ( cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) @@ -162,7 +163,7 @@ CLIMATE_SCHEMA = ( { cv.Optional(CONF_MIN_TEMPERATURE): cv.temperature, cv.Optional(CONF_MAX_TEMPERATURE): cv.temperature, - cv.Optional(CONF_TEMPERATURE_STEP): VISUAL_TEMPERATURE_STEP_SCHEMA, + cv.Optional(CONF_TEMPERATURE_STEP): visual_temperature_step, cv.Optional(CONF_MIN_HUMIDITY): cv.percentage_int, cv.Optional(CONF_MAX_HUMIDITY): cv.percentage_int, } @@ -408,9 +409,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..630bf6962c 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( + 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), } ) -) + .extend(web_server.WEBSERVER_SORTING_SCHEMA) + .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) +).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/es8311/__init__.py b/esphome/components/es8311/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/es8311/audio_dac.py b/esphome/components/es8311/audio_dac.py new file mode 100644 index 0000000000..1b450c3c11 --- /dev/null +++ b/esphome/components/es8311/audio_dac.py @@ -0,0 +1,70 @@ +import esphome.codegen as cg +from esphome.components import i2c +from esphome.components.audio_dac import AudioDac +import esphome.config_validation as cv +from esphome.const import CONF_BITS_PER_SAMPLE, CONF_ID, CONF_SAMPLE_RATE + +CODEOWNERS = ["@kroimon", "@kahrendt"] +DEPENDENCIES = ["i2c"] + +es8311_ns = cg.esphome_ns.namespace("es8311") +ES8311 = es8311_ns.class_("ES8311", AudioDac, cg.Component, i2c.I2CDevice) + +CONF_MIC_GAIN = "mic_gain" +CONF_USE_MCLK = "use_mclk" +CONF_USE_MICROPHONE = "use_microphone" + +es8311_resolution = es8311_ns.enum("ES8311Resolution") +ES8311_BITS_PER_SAMPLE_ENUM = { + 16: es8311_resolution.ES8311_RESOLUTION_16, + 24: es8311_resolution.ES8311_RESOLUTION_24, + 32: es8311_resolution.ES8311_RESOLUTION_32, +} + +es8311_mic_gain = es8311_ns.enum("ES8311MicGain") +ES8311_MIC_GAIN_ENUM = { + "MIN": es8311_mic_gain.ES8311_MIC_GAIN_MIN, + "0DB": es8311_mic_gain.ES8311_MIC_GAIN_0DB, + "6DB": es8311_mic_gain.ES8311_MIC_GAIN_6DB, + "12DB": es8311_mic_gain.ES8311_MIC_GAIN_12DB, + "18DB": es8311_mic_gain.ES8311_MIC_GAIN_18DB, + "24DB": es8311_mic_gain.ES8311_MIC_GAIN_24DB, + "30DB": es8311_mic_gain.ES8311_MIC_GAIN_30DB, + "36DB": es8311_mic_gain.ES8311_MIC_GAIN_36DB, + "42DB": es8311_mic_gain.ES8311_MIC_GAIN_42DB, + "MAX": es8311_mic_gain.ES8311_MIC_GAIN_MAX, +} + + +_validate_bits = cv.float_with_unit("bits", "bit") + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(ES8311), + cv.Optional(CONF_BITS_PER_SAMPLE, default="16bit"): cv.All( + _validate_bits, cv.enum(ES8311_BITS_PER_SAMPLE_ENUM) + ), + cv.Optional(CONF_MIC_GAIN, default="42DB"): cv.enum( + ES8311_MIC_GAIN_ENUM, upper=True + ), + cv.Optional(CONF_SAMPLE_RATE, default=16000): cv.int_range(min=1), + cv.Optional(CONF_USE_MCLK, default=True): cv.boolean, + cv.Optional(CONF_USE_MICROPHONE, default=False): cv.boolean, + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x18)) +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + await i2c.register_i2c_device(var, config) + + cg.add(var.set_bits_per_sample(config[CONF_BITS_PER_SAMPLE])) + cg.add(var.set_mic_gain(config[CONF_MIC_GAIN])) + cg.add(var.set_sample_frequency(config[CONF_SAMPLE_RATE])) + cg.add(var.set_use_mclk(config[CONF_USE_MCLK])) + cg.add(var.set_use_mic(config[CONF_USE_MICROPHONE])) diff --git a/esphome/components/es8311/es8311.cpp b/esphome/components/es8311/es8311.cpp new file mode 100644 index 0000000000..1cb1fbbe08 --- /dev/null +++ b/esphome/components/es8311/es8311.cpp @@ -0,0 +1,227 @@ +#include "es8311.h" +#include "es8311_const.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" +#include + +namespace esphome { +namespace es8311 { + +static const char *const TAG = "es8311"; + +// Mark the component as failed; use only in setup +#define ES8311_ERROR_FAILED(func) \ + if (!(func)) { \ + this->mark_failed(); \ + return; \ + } +// Return false; use outside of setup +#define ES8311_ERROR_CHECK(func) \ + if (!(func)) { \ + return false; \ + } + +void ES8311::setup() { + ESP_LOGCONFIG(TAG, "Setting up ES8311..."); + + // Reset + ES8311_ERROR_FAILED(this->write_byte(ES8311_REG00_RESET, 0x1F)); + ES8311_ERROR_FAILED(this->write_byte(ES8311_REG00_RESET, 0x00)); + + ES8311_ERROR_FAILED(this->configure_clock_()); + ES8311_ERROR_FAILED(this->configure_format_()); + ES8311_ERROR_FAILED(this->configure_mic_()); + + // Set initial volume + this->set_volume(0.75); // 0.75 = 0xBF = 0dB + + // Power up analog circuitry + ES8311_ERROR_FAILED(this->write_byte(ES8311_REG0D_SYSTEM, 0x01)); + // Enable analog PGA, enable ADC modulator + ES8311_ERROR_FAILED(this->write_byte(ES8311_REG0E_SYSTEM, 0x02)); + // Power up DAC + ES8311_ERROR_FAILED(this->write_byte(ES8311_REG12_SYSTEM, 0x00)); + // Enable output to HP drive + ES8311_ERROR_FAILED(this->write_byte(ES8311_REG13_SYSTEM, 0x10)); + // ADC Equalizer bypass, cancel DC offset in digital domain + ES8311_ERROR_FAILED(this->write_byte(ES8311_REG1C_ADC, 0x6A)); + // Bypass DAC equalizer + ES8311_ERROR_FAILED(this->write_byte(ES8311_REG37_DAC, 0x08)); + // Power On + ES8311_ERROR_FAILED(this->write_byte(ES8311_REG00_RESET, 0x80)); +} + +void ES8311::dump_config() { + ESP_LOGCONFIG(TAG, "ES8311 Audio Codec:"); + ESP_LOGCONFIG(TAG, " Use MCLK: %s", YESNO(this->use_mclk_)); + ESP_LOGCONFIG(TAG, " Use Microphone: %s", YESNO(this->use_mic_)); + ESP_LOGCONFIG(TAG, " DAC Bits per Sample: %" PRIu8, this->resolution_out_); + ESP_LOGCONFIG(TAG, " Sample Rate: %" PRIu32, this->sample_frequency_); + + if (this->is_failed()) { + ESP_LOGCONFIG(TAG, " Failed to initialize!"); + return; + } +} + +bool ES8311::set_volume(float volume) { + volume = clamp(volume, 0.0f, 1.0f); + uint8_t reg32 = remap(volume, 0.0f, 1.0f, 0, 255); + return this->write_byte(ES8311_REG32_DAC, reg32); +} + +float ES8311::volume() { + uint8_t reg32; + this->read_byte(ES8311_REG32_DAC, ®32); + return remap(reg32, 0, 255, 0.0f, 1.0f); +} + +uint8_t ES8311::calculate_resolution_value(ES8311Resolution resolution) { + switch (resolution) { + case ES8311_RESOLUTION_16: + return (3 << 2); + case ES8311_RESOLUTION_18: + return (2 << 2); + case ES8311_RESOLUTION_20: + return (1 << 2); + case ES8311_RESOLUTION_24: + return (0 << 2); + case ES8311_RESOLUTION_32: + return (4 << 2); + default: + return 0; + } +} + +const ES8311Coefficient *ES8311::get_coefficient(uint32_t mclk, uint32_t rate) { + for (const auto &coefficient : ES8311_COEFFICIENTS) { + if (coefficient.mclk == mclk && coefficient.rate == rate) + return &coefficient; + } + return nullptr; +} + +bool ES8311::configure_clock_() { + // Register 0x01: select clock source for internal MCLK and determine its frequency + uint8_t reg01 = 0x3F; // Enable all clocks + + uint32_t mclk_frequency = this->sample_frequency_ * this->mclk_multiple_; + if (!this->use_mclk_) { + reg01 |= BIT(7); // Use SCLK + mclk_frequency = this->sample_frequency_ * (int) this->resolution_out_ * 2; + } + if (this->mclk_inverted_) { + reg01 |= BIT(6); // Invert MCLK pin + } + ES8311_ERROR_CHECK(this->write_byte(ES8311_REG01_CLK_MANAGER, reg01)); + + // Get clock coefficients from coefficient table + auto *coefficient = get_coefficient(mclk_frequency, this->sample_frequency_); + if (coefficient == nullptr) { + ESP_LOGE(TAG, "Unable to configure sample rate %" PRIu32 "Hz with %" PRIu32 "Hz MCLK", this->sample_frequency_, + mclk_frequency); + return false; + } + + // Register 0x02 + uint8_t reg02; + ES8311_ERROR_CHECK(this->read_byte(ES8311_REG02_CLK_MANAGER, ®02)); + reg02 &= 0x07; + reg02 |= (coefficient->pre_div - 1) << 5; + reg02 |= coefficient->pre_mult << 3; + ES8311_ERROR_CHECK(this->write_byte(ES8311_REG02_CLK_MANAGER, reg02)); + + // Register 0x03 + const uint8_t reg03 = (coefficient->fs_mode << 6) | coefficient->adc_osr; + ES8311_ERROR_CHECK(this->write_byte(ES8311_REG03_CLK_MANAGER, reg03)); + + // Register 0x04 + ES8311_ERROR_CHECK(this->write_byte(ES8311_REG04_CLK_MANAGER, coefficient->dac_osr)); + + // Register 0x05 + const uint8_t reg05 = ((coefficient->adc_div - 1) << 4) | (coefficient->dac_div - 1); + ES8311_ERROR_CHECK(this->write_byte(ES8311_REG05_CLK_MANAGER, reg05)); + + // Register 0x06 + uint8_t reg06; + ES8311_ERROR_CHECK(this->read_byte(ES8311_REG06_CLK_MANAGER, ®06)); + if (this->sclk_inverted_) { + reg06 |= BIT(5); + } else { + reg06 &= ~BIT(5); + } + reg06 &= 0xE0; + if (coefficient->bclk_div < 19) { + reg06 |= (coefficient->bclk_div - 1) << 0; + } else { + reg06 |= (coefficient->bclk_div) << 0; + } + ES8311_ERROR_CHECK(this->write_byte(ES8311_REG06_CLK_MANAGER, reg06)); + + // Register 0x07 + uint8_t reg07; + ES8311_ERROR_CHECK(this->read_byte(ES8311_REG07_CLK_MANAGER, ®07)); + reg07 &= 0xC0; + reg07 |= coefficient->lrck_h << 0; + ES8311_ERROR_CHECK(this->write_byte(ES8311_REG07_CLK_MANAGER, reg07)); + + // Register 0x08 + ES8311_ERROR_CHECK(this->write_byte(ES8311_REG08_CLK_MANAGER, coefficient->lrck_l)); + + // Successfully configured the clock + return true; +} + +bool ES8311::configure_format_() { + // Configure I2S mode and format + uint8_t reg00; + ES8311_ERROR_CHECK(this->read_byte(ES8311_REG00_RESET, ®00)); + reg00 &= 0xBF; + ES8311_ERROR_CHECK(this->write_byte(ES8311_REG00_RESET, reg00)); + + // Configure SDP in resolution + uint8_t reg09 = calculate_resolution_value(this->resolution_in_); + ES8311_ERROR_CHECK(this->write_byte(ES8311_REG09_SDPIN, reg09)); + + // Configure SDP out resolution + uint8_t reg0a = calculate_resolution_value(this->resolution_out_); + ES8311_ERROR_CHECK(this->write_byte(ES8311_REG0A_SDPOUT, reg0a)); + + // Successfully configured the format + return true; +} + +bool ES8311::configure_mic_() { + uint8_t reg14 = 0x1A; // Enable analog MIC and max PGA gain + if (this->use_mic_) { + reg14 |= BIT(6); // Enable PDM digital microphone + } + ES8311_ERROR_CHECK(this->write_byte(ES8311_REG14_SYSTEM, reg14)); + + ES8311_ERROR_CHECK(this->write_byte(ES8311_REG16_ADC, this->mic_gain_)); // ADC gain scale up + ES8311_ERROR_CHECK(this->write_byte(ES8311_REG17_ADC, 0xC8)); // Set ADC gain + + // Successfully configured the microphones + return true; +} + +bool ES8311::set_mute_state_(bool mute_state) { + uint8_t reg31; + + this->is_muted_ = mute_state; + + if (!this->read_byte(ES8311_REG31_DAC, ®31)) { + return false; + } + + if (mute_state) { + reg31 |= BIT(6) | BIT(5); + } else { + reg31 &= ~(BIT(6) | BIT(5)); + } + + return this->write_byte(ES8311_REG31_DAC, reg31); +} + +} // namespace es8311 +} // namespace esphome diff --git a/esphome/components/es8311/es8311.h b/esphome/components/es8311/es8311.h new file mode 100644 index 0000000000..840a07204c --- /dev/null +++ b/esphome/components/es8311/es8311.h @@ -0,0 +1,135 @@ +#pragma once + +#include "esphome/components/audio_dac/audio_dac.h" +#include "esphome/components/i2c/i2c.h" +#include "esphome/core/component.h" + +namespace esphome { +namespace es8311 { + +enum ES8311MicGain { + ES8311_MIC_GAIN_MIN = -1, + ES8311_MIC_GAIN_0DB, + ES8311_MIC_GAIN_6DB, + ES8311_MIC_GAIN_12DB, + ES8311_MIC_GAIN_18DB, + ES8311_MIC_GAIN_24DB, + ES8311_MIC_GAIN_30DB, + ES8311_MIC_GAIN_36DB, + ES8311_MIC_GAIN_42DB, + ES8311_MIC_GAIN_MAX +}; + +enum ES8311Resolution : uint8_t { + ES8311_RESOLUTION_16 = 16, + ES8311_RESOLUTION_18 = 18, + ES8311_RESOLUTION_20 = 20, + ES8311_RESOLUTION_24 = 24, + ES8311_RESOLUTION_32 = 32 +}; + +struct ES8311Coefficient { + uint32_t mclk; // mclk frequency + uint32_t rate; // sample rate + uint8_t pre_div; // the pre divider with range from 1 to 8 + uint8_t pre_mult; // the pre multiplier with x1, x2, x4 and x8 selection + uint8_t adc_div; // adcclk divider + uint8_t dac_div; // dacclk divider + uint8_t fs_mode; // single speed (0) or double speed (1) + uint8_t lrck_h; // adc lrck divider and dac lrck divider + uint8_t lrck_l; // + uint8_t bclk_div; // sclk divider + uint8_t adc_osr; // adc osr + uint8_t dac_osr; // dac osr +}; + +class ES8311 : public audio_dac::AudioDac, public Component, public i2c::I2CDevice { + public: + ///////////////////////// + // Component overrides // + ///////////////////////// + + void setup() override; + float get_setup_priority() const override { return setup_priority::DATA; } + void dump_config() override; + + //////////////////////// + // AudioDac overrides // + //////////////////////// + + /// @brief Writes the volume out to the DAC + /// @param volume floating point between 0.0 and 1.0 + /// @return True if successful and false otherwise + bool set_volume(float volume) override; + + /// @brief Gets the current volume out from the DAC + /// @return floating point between 0.0 and 1.0 + float volume() override; + + /// @brief Disables mute for audio out + /// @return True if successful and false otherwise + bool set_mute_off() override { return this->set_mute_state_(false); } + + /// @brief Enables mute for audio out + /// @return True if successful and false otherwise + bool set_mute_on() override { return this->set_mute_state_(true); } + + bool is_muted() override { return this->is_muted_; } + + ////////////////////////////////// + // ES8311 configuration setters // + ////////////////////////////////// + + void set_use_mclk(bool use_mclk) { this->use_mclk_ = use_mclk; } + void set_bits_per_sample(ES8311Resolution resolution) { + this->resolution_in_ = resolution; + this->resolution_out_ = resolution; + } + void set_sample_frequency(uint32_t sample_frequency) { this->sample_frequency_ = sample_frequency; } + void set_use_mic(bool use_mic) { this->use_mic_ = use_mic; } + void set_mic_gain(ES8311MicGain mic_gain) { this->mic_gain_ = mic_gain; } + + protected: + /// @brief Computes the register value for the configured resolution (bits per sample) + /// @param resolution bits per sample enum for both audio in and audio out + /// @return register value + static uint8_t calculate_resolution_value(ES8311Resolution resolution); + + /// @brief Retrieves the appropriate registers values for the configured mclk and rate + /// @param mclk mlck frequency in Hz + /// @param rate sample rate frequency in Hz + /// @return ES8311Coeffecient containing appropriate register values to configure the ES8311 or nullptr if impossible + static const ES8311Coefficient *get_coefficient(uint32_t mclk, uint32_t rate); + + /// @brief Configures the ES8311 registers for the chosen sample rate + /// @return True if successful and false otherwise + bool configure_clock_(); + + /// @brief Configures the ES8311 registers for the chosen bits per sample + /// @return True if successful and false otherwise + bool configure_format_(); + + /// @brief Configures the ES8311 microphone registers + /// @return True if successful and false otherwise + bool configure_mic_(); + + /// @brief Mutes or unmute the DAC audio out + /// @param mute_state True to mute, false to unmute + /// @return + bool set_mute_state_(bool mute_state); + + bool use_mic_; + ES8311MicGain mic_gain_; + + bool use_mclk_; // true = use dedicated MCLK pin, false = use SCLK + bool sclk_inverted_{false}; // SCLK is inverted + bool mclk_inverted_{false}; // MCLK is inverted (ignored if use_mclk_ == false) + uint32_t mclk_multiple_{256}; // MCLK frequency is sample rate * mclk_multiple_ (ignored if use_mclk_ == false) + + uint32_t sample_frequency_; // in Hz + ES8311Resolution resolution_in_; + ES8311Resolution resolution_out_; +}; + +} // namespace es8311 +} // namespace esphome diff --git a/esphome/components/es8311/es8311_const.h b/esphome/components/es8311/es8311_const.h new file mode 100644 index 0000000000..7463a92ef1 --- /dev/null +++ b/esphome/components/es8311/es8311_const.h @@ -0,0 +1,195 @@ +#pragma once + +#include "es8311.h" + +namespace esphome { +namespace es8311 { + +// ES8311 register addresses +static const uint8_t ES8311_REG00_RESET = 0x00; // Reset +static const uint8_t ES8311_REG01_CLK_MANAGER = 0x01; // Clock Manager: select clk src for mclk, enable clock for codec +static const uint8_t ES8311_REG02_CLK_MANAGER = 0x02; // Clock Manager: clk divider and clk multiplier +static const uint8_t ES8311_REG03_CLK_MANAGER = 0x03; // Clock Manager: adc fsmode and osr +static const uint8_t ES8311_REG04_CLK_MANAGER = 0x04; // Clock Manager: dac osr +static const uint8_t ES8311_REG05_CLK_MANAGER = 0x05; // Clock Manager: clk divider for adc and dac +static const uint8_t ES8311_REG06_CLK_MANAGER = 0x06; // Clock Manager: bclk inverter BIT(5) and divider +static const uint8_t ES8311_REG07_CLK_MANAGER = 0x07; // Clock Manager: tri-state, lrck divider +static const uint8_t ES8311_REG08_CLK_MANAGER = 0x08; // Clock Manager: lrck divider +static const uint8_t ES8311_REG09_SDPIN = 0x09; // Serial Digital Port: DAC +static const uint8_t ES8311_REG0A_SDPOUT = 0x0A; // Serial Digital Port: ADC +static const uint8_t ES8311_REG0B_SYSTEM = 0x0B; // System +static const uint8_t ES8311_REG0C_SYSTEM = 0x0C; // System +static const uint8_t ES8311_REG0D_SYSTEM = 0x0D; // System: power up/down +static const uint8_t ES8311_REG0E_SYSTEM = 0x0E; // System: power up/down +static const uint8_t ES8311_REG0F_SYSTEM = 0x0F; // System: low power +static const uint8_t ES8311_REG10_SYSTEM = 0x10; // System +static const uint8_t ES8311_REG11_SYSTEM = 0x11; // System +static const uint8_t ES8311_REG12_SYSTEM = 0x12; // System: Enable DAC +static const uint8_t ES8311_REG13_SYSTEM = 0x13; // System +static const uint8_t ES8311_REG14_SYSTEM = 0x14; // System: select DMIC, select analog pga gain +static const uint8_t ES8311_REG15_ADC = 0x15; // ADC: adc ramp rate, dmic sense +static const uint8_t ES8311_REG16_ADC = 0x16; // ADC +static const uint8_t ES8311_REG17_ADC = 0x17; // ADC: volume +static const uint8_t ES8311_REG18_ADC = 0x18; // ADC: alc enable and winsize +static const uint8_t ES8311_REG19_ADC = 0x19; // ADC: alc maxlevel +static const uint8_t ES8311_REG1A_ADC = 0x1A; // ADC: alc automute +static const uint8_t ES8311_REG1B_ADC = 0x1B; // ADC: alc automute, adc hpf s1 +static const uint8_t ES8311_REG1C_ADC = 0x1C; // ADC: equalizer, hpf s2 +static const uint8_t ES8311_REG1D_ADCEQ = 0x1D; // ADCEQ: equalizer B0 +static const uint8_t ES8311_REG1E_ADCEQ = 0x1E; // ADCEQ: equalizer B0 +static const uint8_t ES8311_REG1F_ADCEQ = 0x1F; // ADCEQ: equalizer B0 +static const uint8_t ES8311_REG20_ADCEQ = 0x20; // ADCEQ: equalizer B0 +static const uint8_t ES8311_REG21_ADCEQ = 0x21; // ADCEQ: equalizer A1 +static const uint8_t ES8311_REG22_ADCEQ = 0x22; // ADCEQ: equalizer A1 +static const uint8_t ES8311_REG23_ADCEQ = 0x23; // ADCEQ: equalizer A1 +static const uint8_t ES8311_REG24_ADCEQ = 0x24; // ADCEQ: equalizer A1 +static const uint8_t ES8311_REG25_ADCEQ = 0x25; // ADCEQ: equalizer A2 +static const uint8_t ES8311_REG26_ADCEQ = 0x26; // ADCEQ: equalizer A2 +static const uint8_t ES8311_REG27_ADCEQ = 0x27; // ADCEQ: equalizer A2 +static const uint8_t ES8311_REG28_ADCEQ = 0x28; // ADCEQ: equalizer A2 +static const uint8_t ES8311_REG29_ADCEQ = 0x29; // ADCEQ: equalizer B1 +static const uint8_t ES8311_REG2A_ADCEQ = 0x2A; // ADCEQ: equalizer B1 +static const uint8_t ES8311_REG2B_ADCEQ = 0x2B; // ADCEQ: equalizer B1 +static const uint8_t ES8311_REG2C_ADCEQ = 0x2C; // ADCEQ: equalizer B1 +static const uint8_t ES8311_REG2D_ADCEQ = 0x2D; // ADCEQ: equalizer B2 +static const uint8_t ES8311_REG2E_ADCEQ = 0x2E; // ADCEQ: equalizer B2 +static const uint8_t ES8311_REG2F_ADCEQ = 0x2F; // ADCEQ: equalizer B2 +static const uint8_t ES8311_REG30_ADCEQ = 0x30; // ADCEQ: equalizer B2 +static const uint8_t ES8311_REG31_DAC = 0x31; // DAC: mute +static const uint8_t ES8311_REG32_DAC = 0x32; // DAC: volume +static const uint8_t ES8311_REG33_DAC = 0x33; // DAC: offset +static const uint8_t ES8311_REG34_DAC = 0x34; // DAC: drc enable, drc winsize +static const uint8_t ES8311_REG35_DAC = 0x35; // DAC: drc maxlevel, minilevel +static const uint8_t ES8311_REG36_DAC = 0x36; // DAC +static const uint8_t ES8311_REG37_DAC = 0x37; // DAC: ramprate +static const uint8_t ES8311_REG38_DACEQ = 0x38; // DACEQ: equalizer B0 +static const uint8_t ES8311_REG39_DACEQ = 0x39; // DACEQ: equalizer B0 +static const uint8_t ES8311_REG3A_DACEQ = 0x3A; // DACEQ: equalizer B0 +static const uint8_t ES8311_REG3B_DACEQ = 0x3B; // DACEQ: equalizer B0 +static const uint8_t ES8311_REG3C_DACEQ = 0x3C; // DACEQ: equalizer B1 +static const uint8_t ES8311_REG3D_DACEQ = 0x3D; // DACEQ: equalizer B1 +static const uint8_t ES8311_REG3E_DACEQ = 0x3E; // DACEQ: equalizer B1 +static const uint8_t ES8311_REG3F_DACEQ = 0x3F; // DACEQ: equalizer B1 +static const uint8_t ES8311_REG40_DACEQ = 0x40; // DACEQ: equalizer A1 +static const uint8_t ES8311_REG41_DACEQ = 0x41; // DACEQ: equalizer A1 +static const uint8_t ES8311_REG42_DACEQ = 0x42; // DACEQ: equalizer A1 +static const uint8_t ES8311_REG43_DACEQ = 0x43; // DACEQ: equalizer A1 +static const uint8_t ES8311_REG44_GPIO = 0x44; // GPIO: dac2adc for test +static const uint8_t ES8311_REG45_GP = 0x45; // GPIO: GP control +static const uint8_t ES8311_REGFA_I2C = 0xFA; // I2C: reset registers +static const uint8_t ES8311_REGFC_FLAG = 0xFC; // Flag +static const uint8_t ES8311_REGFD_CHD1 = 0xFD; // Chip: ID1 +static const uint8_t ES8311_REGFE_CHD2 = 0xFE; // Chip: ID2 +static const uint8_t ES8311_REGFF_CHVER = 0xFF; // Chip: Version + +// ES8311 clock divider coefficients +static const ES8311Coefficient ES8311_COEFFICIENTS[] = { + // clang-format off + + // mclk, rate, pre_ pre_ adc_ dac_ fs_ lrck lrck bclk_ adc_ dac_ + // div, mult, div, div, mode, _h, _l, div, osr, osr + + // 8k + {12288000, 8000, 0x06, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + {18432000, 8000, 0x03, 0x02, 0x03, 0x03, 0x00, 0x05, 0xff, 0x18, 0x10, 0x20}, + {16384000, 8000, 0x08, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 8192000, 8000, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 6144000, 8000, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 4096000, 8000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 3072000, 8000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 2048000, 8000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 1536000, 8000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 1024000, 8000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + + // 11.025k + {11289600, 11025, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 5644800, 11025, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 2822400, 11025, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 1411200, 11025, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + + // 12k + {12288000, 12000, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 6144000, 12000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 3072000, 12000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 1536000, 12000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + + // 16k + {12288000, 16000, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + {18432000, 16000, 0x03, 0x02, 0x03, 0x03, 0x00, 0x02, 0xff, 0x0c, 0x10, 0x20}, + {16384000, 16000, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 8192000, 16000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 6144000, 16000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 4096000, 16000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 3072000, 16000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 2048000, 16000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 1536000, 16000, 0x03, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + { 1024000, 16000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20}, + + // 22.05k + {11289600, 22050, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 5644800, 22050, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 2822400, 22050, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 1411200, 22050, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + + // 24k + {12288000, 24000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {18432000, 24000, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 6144000, 24000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 3072000, 24000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 1536000, 24000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + + // 32k + {12288000, 32000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {18432000, 32000, 0x03, 0x04, 0x03, 0x03, 0x00, 0x02, 0xff, 0x0c, 0x10, 0x10}, + {16384000, 32000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 8192000, 32000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 6144000, 32000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 4096000, 32000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 3072000, 32000, 0x03, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 2048000, 32000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 1536000, 32000, 0x03, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10}, + { 1024000, 32000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + + // 44.1k + {11289600, 44100, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 5644800, 44100, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 2822400, 44100, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 1411200, 44100, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + + // 48k + {12288000, 48000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {18432000, 48000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 6144000, 48000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 3072000, 48000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 1536000, 48000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + + // 64k + {12288000, 64000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {18432000, 64000, 0x03, 0x04, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10}, + {16384000, 64000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 8192000, 64000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 6144000, 64000, 0x01, 0x04, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10}, + { 4096000, 64000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 3072000, 64000, 0x01, 0x08, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10}, + { 2048000, 64000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 1536000, 64000, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0xbf, 0x03, 0x18, 0x18}, + { 1024000, 64000, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10}, + + // 88.2k + {11289600, 88200, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 5644800, 88200, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 2822400, 88200, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 1411200, 88200, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10}, + + // 96k + {12288000, 96000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {18432000, 96000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 6144000, 96000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 3072000, 96000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + { 1536000, 96000, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10}, + + // clang-format on +}; + +} // namespace es8311 +} // namespace esphome diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 9cb9ac257a..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, ) @@ -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/gpio.py b/esphome/components/esp32/gpio.py index 558ff51af8..df01769a66 100644 --- a/esphome/components/esp32/gpio.py +++ b/esphome/components/esp32/gpio.py @@ -67,8 +67,10 @@ def _translate_pin(value): "This variable only supports pin numbers, not full pin schemas " "(with inverted and mode)." ) - if isinstance(value, int): + if isinstance(value, int) and not isinstance(value, bool): return value + if not isinstance(value, str): + raise cv.Invalid(f"Invalid pin number: {value}") try: return int(value) except ValueError: 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_client/ble_client_base.h b/esphome/components/esp32_ble_client/ble_client_base.h index fd586e59d6..fca66c0b3c 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.h +++ b/esphome/components/esp32_ble_client/ble_client_base.h @@ -35,7 +35,7 @@ class BLEClientBase : public espbt::ESPBTClient, public Component { void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override; void connect() override; esp_err_t pair(); - void disconnect(); + void disconnect() override; void release_services(); bool connected() { return this->state_ == espbt::ClientState::ESTABLISHED; } diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index d2bb6a6e6d..2fc5da829d 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -11,9 +11,9 @@ #ifdef USE_ESP32 +#include #include #include -#include #include #include @@ -172,6 +172,7 @@ class ESPBTClient : public ESPBTDeviceListener { esp_ble_gattc_cb_param_t *param) = 0; virtual void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) = 0; virtual void connect() = 0; + virtual void disconnect() = 0; virtual void set_state(ClientState st) { this->state_ = st; } ClientState state() const { return state_; } int app_id; 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/esp8266/gpio.py b/esphome/components/esp8266/gpio.py index c42bc9204f..53016d2130 100644 --- a/esphome/components/esp8266/gpio.py +++ b/esphome/components/esp8266/gpio.py @@ -1,6 +1,9 @@ -import logging from dataclasses import dataclass +import logging +from esphome import pins +import esphome.codegen as cg +import esphome.config_validation as cv from esphome.const import ( CONF_ANALOG, CONF_ID, @@ -14,10 +17,7 @@ from esphome.const import ( CONF_PULLUP, PLATFORM_ESP8266, ) -from esphome import pins from esphome.core import CORE, coroutine_with_priority -import esphome.config_validation as cv -import esphome.codegen as cg from . import boards from .const import KEY_BOARD, KEY_ESP8266, KEY_PIN_INITIAL_STATES, esp8266_ns @@ -48,8 +48,10 @@ def _translate_pin(value): "This variable only supports pin numbers, not full pin schemas " "(with inverted and mode)." ) - if isinstance(value, int): + if isinstance(value, int) and not isinstance(value, bool): return value + if not isinstance(value, str): + raise cv.Invalid(f"Invalid pin number: {value}") try: return int(value) except ValueError: 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..6fd2d7c310 100644 --- a/esphome/components/font/__init__.py +++ b/esphome/components/font/__init__.py @@ -1,3 +1,4 @@ +from collections.abc import Iterable import functools import hashlib import logging @@ -5,6 +6,8 @@ import os from pathlib import Path import re +import freetype +import glyphsets from packaging import version import requests @@ -43,6 +46,18 @@ GlyphData = font_ns.struct("GlyphData") CONF_BPP = "bpp" CONF_EXTRAS = "extras" CONF_FONTS = "fonts" +CONF_GLYPHSETS = "glyphsets" +CONF_IGNORE_MISSING_GLYPHS = "ignore_missing_glyphs" + + +# Cache loaded freetype fonts +class FontCache(dict): + def __missing__(self, key): + res = self[key] = freetype.Face(key) + return res + + +FONT_CACHE = FontCache() def glyph_comparator(x, y): @@ -59,36 +74,106 @@ def glyph_comparator(x, y): return -1 if len(x_) > len(y_): return 1 - raise cv.Invalid(f"Found duplicate glyph {x}") + return 0 -def validate_glyphs(value): - if isinstance(value, list): - value = cv.Schema([cv.string])(value) - value = cv.Schema([cv.string])(list(value)) +def flatten(lists) -> list: + """ + Given a list of lists, flatten it to a single list of all elements of all lists. + This wraps itertools.chain.from_iterable to make it more readable, and return a list + rather than a single use iterable. + """ + from itertools import chain - value.sort(key=functools.cmp_to_key(glyph_comparator)) - return value + return list(chain.from_iterable(lists)) -font_map = {} +def check_missing_glyphs(file, codepoints: Iterable, warning: bool = False): + """ + Check that the given font file actually contains the requested glyphs + :param file: A Truetype font file + :param codepoints: A list of codepoints to check + :param warning: If true, log a warning instead of raising an exception + """ - -def merge_glyphs(config): - glyphs = [] - glyphs.extend(config[CONF_GLYPHS]) - font_list = [(EFont(config[CONF_FILE], config[CONF_SIZE], config[CONF_GLYPHS]))] - if extras := config.get(CONF_EXTRAS): - extra_fonts = list( - map( - lambda x: EFont(x[CONF_FILE], config[CONF_SIZE], x[CONF_GLYPHS]), extras - ) + font = FONT_CACHE[file] + missing = [chr(x) for x in codepoints if font.get_char_index(x) == 0] + if missing: + # Only list up to 10 missing glyphs + missing.sort(key=functools.cmp_to_key(glyph_comparator)) + count = len(missing) + missing = missing[:10] + missing_str = "\n ".join( + f"{x} ({x.encode('unicode_escape')})" for x in missing ) - font_list.extend(extra_fonts) - for extra in extras: - glyphs.extend(extra[CONF_GLYPHS]) - validate_glyphs(glyphs) - font_map[config[CONF_ID]] = font_list + if count > 10: + missing_str += f"\n and {count - 10} more." + message = f"Font {Path(file).name} is missing {count} glyph{'s' if count != 1 else ''}:\n {missing_str}" + if warning: + _LOGGER.warning(message) + else: + raise cv.Invalid(message) + + +def validate_glyphs(config): + """ + Check for duplicate codepoints, then check that all requested codepoints actually + have glyphs defined in the appropriate font file. + """ + + # Collect all glyph codepoints and flatten to a list of chars + glyphspoints = flatten( + [x[CONF_GLYPHS] for x in config[CONF_EXTRAS]] + config[CONF_GLYPHS] + ) + # Convert a list of strings to a list of chars (one char strings) + glyphspoints = flatten([list(x) for x in glyphspoints]) + if len(set(glyphspoints)) != len(glyphspoints): + duplicates = {x for x in glyphspoints if glyphspoints.count(x) > 1} + dup_str = ", ".join(f"{x} ({x.encode('unicode_escape')})" for x in duplicates) + raise cv.Invalid( + f"Found duplicate glyph{'s' if len(duplicates) != 1 else ''}: {dup_str}" + ) + # convert to codepoints + glyphspoints = {ord(x) for x in glyphspoints} + fileconf = config[CONF_FILE] + setpoints = set( + flatten([glyphsets.unicodes_per_glyphset(x) for x in config[CONF_GLYPHSETS]]) + ) + # Make setpoints and glyphspoints disjoint + setpoints.difference_update(glyphspoints) + if fileconf[CONF_TYPE] == TYPE_LOCAL_BITMAP: + # Pillow only allows 256 glyphs per bitmap font. Not sure if that is a Pillow limitation + # or a file format limitation + if any(x >= 256 for x in setpoints.copy().union(glyphspoints)): + raise cv.Invalid("Codepoints in bitmap fonts must be in the range 0-255") + else: + # for TT fonts, check that glyphs are actually present + # Check extras against their own font, exclude from parent font codepoints + for extra in config[CONF_EXTRAS]: + points = {ord(x) for x in flatten(extra[CONF_GLYPHS])} + glyphspoints.difference_update(points) + setpoints.difference_update(points) + check_missing_glyphs(extra[CONF_FILE][CONF_PATH], points) + + # A named glyph that can't be provided is an error + check_missing_glyphs(fileconf[CONF_PATH], glyphspoints) + # A missing glyph from a set is a warning. + if not config[CONF_IGNORE_MISSING_GLYPHS]: + check_missing_glyphs(fileconf[CONF_PATH], setpoints, warning=True) + + # Populate the default after the above checks so that use of the default doesn't trigger errors + if not config[CONF_GLYPHS] and not config[CONF_GLYPHSETS]: + if fileconf[CONF_TYPE] == TYPE_LOCAL_BITMAP: + config[CONF_GLYPHS] = [DEFAULT_GLYPHS] + else: + # set a default glyphset, intersected with what the font actually offers + font = FONT_CACHE[fileconf[CONF_PATH]] + config[CONF_GLYPHS] = [ + chr(x) + for x in glyphsets.unicodes_per_glyphset(DEFAULT_GLYPHSET) + if font.get_char_index(x) != 0 + ] + return config @@ -98,13 +183,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 @@ -120,7 +205,7 @@ def validate_truetype_file(value): ) if not any(map(value.lower().endswith, FONT_EXTENSIONS)): raise cv.Invalid(f"Only {FONT_EXTENSIONS} files are supported.") - return cv.file_(value) + return CORE.relative_config_path(cv.file_(value)) TYPE_LOCAL = "local" @@ -139,6 +224,10 @@ LOCAL_BITMAP_SCHEMA = cv.Schema( } ) +FULLPATH_SCHEMA = cv.maybe_simple_value( + {cv.Required(CONF_PATH): cv.string}, key=CONF_PATH +) + CONF_ITALIC = "italic" FONT_WEIGHTS = { "thin": 100, @@ -167,13 +256,13 @@ def _compute_local_font_path(value: dict) -> Path: return base_dir / key -def get_font_path(value, type) -> Path: - if type == TYPE_GFONTS: +def get_font_path(value, font_type) -> Path: + if font_type == TYPE_GFONTS: name = f"{value[CONF_FAMILY]}@{value[CONF_WEIGHT]}@{value[CONF_ITALIC]}@v1" return external_files.compute_local_file_dir(DOMAIN) / f"{name}.ttf" - if type == TYPE_WEB: + if font_type == TYPE_WEB: return _compute_local_font_path(value) / "font.ttf" - return None + assert False def download_gfont(value): @@ -203,7 +292,7 @@ def download_gfont(value): _LOGGER.debug("download_gfont: ttf_url=%s", ttf_url) external_files.download_content(ttf_url, path) - return value + return FULLPATH_SCHEMA(path) def download_web_font(value): @@ -212,7 +301,7 @@ def download_web_font(value): external_files.download_content(url, path) _LOGGER.debug("download_web_font: path=%s", path) - return value + return FULLPATH_SCHEMA(path) EXTERNAL_FONT_SCHEMA = cv.Schema( @@ -225,7 +314,6 @@ EXTERNAL_FONT_SCHEMA = cv.Schema( } ) - GFONTS_SCHEMA = cv.All( EXTERNAL_FONT_SCHEMA.extend( { @@ -259,10 +347,10 @@ def validate_file_shorthand(value): } if weight is not None: data[CONF_WEIGHT] = weight[1:] - return FILE_SCHEMA(data) + return font_file_schema(data) if value.startswith("http://") or value.startswith("https://"): - return FILE_SCHEMA( + return font_file_schema( { CONF_TYPE: TYPE_WEB, CONF_URL: value, @@ -270,14 +358,15 @@ def validate_file_shorthand(value): ) if value.endswith(".pcf") or value.endswith(".bdf"): - return FILE_SCHEMA( - { - CONF_TYPE: TYPE_LOCAL_BITMAP, - CONF_PATH: value, - } + value = convert_bitmap_to_pillow_font( + CORE.relative_config_path(cv.file_(value)) ) + return { + CONF_TYPE: TYPE_LOCAL_BITMAP, + CONF_PATH: value, + } - return FILE_SCHEMA( + return font_file_schema( { CONF_TYPE: TYPE_LOCAL, CONF_PATH: value, @@ -295,31 +384,35 @@ TYPED_FILE_SCHEMA = cv.typed_schema( ) -def _file_schema(value): +def font_file_schema(value): if isinstance(value, str): return validate_file_shorthand(value) return TYPED_FILE_SCHEMA(value) -FILE_SCHEMA = cv.All(_file_schema) +# Default if no glyphs or glyphsets are provided +DEFAULT_GLYPHSET = "GF_Latin_Kernel" +# default for bitmap fonts +DEFAULT_GLYPHS = ' !"%()+=,-.:/?0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz' -DEFAULT_GLYPHS = ( - ' !"%()+=,-.:/?0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz°' -) CONF_RAW_GLYPH_ID = "raw_glyph_id" FONT_SCHEMA = cv.Schema( { cv.Required(CONF_ID): cv.declare_id(Font), - cv.Required(CONF_FILE): FILE_SCHEMA, - cv.Optional(CONF_GLYPHS, default=DEFAULT_GLYPHS): validate_glyphs, + cv.Required(CONF_FILE): font_file_schema, + cv.Optional(CONF_GLYPHS, default=[]): cv.ensure_list(cv.string_strict), + cv.Optional(CONF_GLYPHSETS, default=[]): cv.ensure_list( + cv.one_of(*glyphsets.defined_glyphsets()) + ), + cv.Optional(CONF_IGNORE_MISSING_GLYPHS, default=False): cv.boolean, cv.Optional(CONF_SIZE, default=20): cv.int_range(min=1), cv.Optional(CONF_BPP, default=1): cv.one_of(1, 2, 4, 8), - cv.Optional(CONF_EXTRAS): cv.ensure_list( + cv.Optional(CONF_EXTRAS, default=[]): cv.ensure_list( cv.Schema( { - cv.Required(CONF_FILE): FILE_SCHEMA, - cv.Required(CONF_GLYPHS): validate_glyphs, + cv.Required(CONF_FILE): font_file_schema, + cv.Required(CONF_GLYPHS): cv.ensure_list(cv.string_strict), } ) ), @@ -328,7 +421,7 @@ FONT_SCHEMA = cv.Schema( }, ) -CONFIG_SCHEMA = cv.All(validate_pillow_installed, FONT_SCHEMA, merge_glyphs) +CONFIG_SCHEMA = cv.All(validate_pillow_installed, FONT_SCHEMA, validate_glyphs) # PIL doesn't provide a consistent interface for both TrueType and bitmap @@ -344,7 +437,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 +452,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 @@ -367,28 +460,20 @@ class BitmapFontWrapper: mask = self.getmask(glyph, mode="1") _, height = mask.size max_height = max(max_height, height) - return (max_height, 0) + return max_height, 0 class EFont: - def __init__(self, file, size, glyphs): - self.glyphs = glyphs + def __init__(self, file, size, codepoints): + self.codepoints = codepoints + path = file[CONF_PATH] + self.name = Path(path).name ftype = file[CONF_TYPE] if ftype == TYPE_LOCAL_BITMAP: - font = load_bitmap_font(CORE.relative_config_path(file[CONF_PATH])) - elif ftype == TYPE_LOCAL: - path = CORE.relative_config_path(file[CONF_PATH]) - font = load_ttf_font(path, size) - elif ftype in (TYPE_GFONTS, TYPE_WEB): - path = get_font_path(file, ftype) - font = load_ttf_font(path, size) + self.font = load_bitmap_font(path) else: - raise cv.Invalid(f"Could not load font: unknown type: {ftype}") - self.font = font - self.ascent, self.descent = font.getmetrics(glyphs) - - def has_glyph(self, glyph): - return glyph in self.glyphs + self.font = load_ttf_font(path, size) + self.ascent, self.descent = self.font.getmetrics(codepoints) def convert_bitmap_to_pillow_font(filepath): @@ -400,6 +485,7 @@ def convert_bitmap_to_pillow_font(filepath): copy_file_if_changed(filepath, local_bitmap_font_file) + local_pil_font_file = local_bitmap_font_file.with_suffix(".pil") with open(local_bitmap_font_file, "rb") as fp: try: try: @@ -409,28 +495,22 @@ def convert_bitmap_to_pillow_font(filepath): p = BdfFontFile.BdfFontFile(fp) # Convert to pillow-formatted fonts, which have a .pil and .pbm extension. - p.save(local_bitmap_font_file) + p.save(local_pil_font_file) except (SyntaxError, OSError) as err: raise core.EsphomeError( f"Failed to parse as bitmap font: '{filepath}': {err}" ) - local_pil_font_file = os.path.splitext(local_bitmap_font_file)[0] + ".pil" - return cv.file_(local_pil_font_file) + return str(local_pil_font_file) def load_bitmap_font(filepath): from PIL import ImageFont - # Convert bpf and pcf files to pillow fonts, first. - pil_font_path = convert_bitmap_to_pillow_font(filepath) - try: - font = ImageFont.load(str(pil_font_path)) + font = ImageFont.load(str(filepath)) except Exception as e: - raise core.EsphomeError( - f"Failed to load bitmap font file: {pil_font_path} : {e}" - ) + raise core.EsphomeError(f"Failed to load bitmap font file: {filepath}: {e}") return BitmapFontWrapper(font) @@ -441,7 +521,7 @@ def load_ttf_font(path, size): try: font = ImageFont.truetype(str(path), size) except Exception as e: - raise core.EsphomeError(f"Could not load truetype file {path}: {e}") + raise core.EsphomeError(f"Could not load TrueType file {path}: {e}") return TrueTypeFontWrapper(font) @@ -456,14 +536,35 @@ class GlyphInfo: async def to_code(config): - glyph_to_font_map = {} - font_list = font_map[config[CONF_ID]] - glyphs = [] - for font in font_list: - glyphs.extend(font.glyphs) - for glyph in font.glyphs: - glyph_to_font_map[glyph] = font - glyphs.sort(key=functools.cmp_to_key(glyph_comparator)) + """ + Collect all glyph codepoints, construct a map from a codepoint to a font file. + Codepoints are either explicit (glyphs key in top level or extras) or part of a glyphset. + Codepoints listed in extras use the extra font and override codepoints from glyphsets. + Achieve this by processing the base codepoints first, then the extras + """ + + # get the codepoints from glyphsets and flatten to a set of chrs. + point_set: set[str] = { + chr(x) + for x in flatten( + [glyphsets.unicodes_per_glyphset(x) for x in config[CONF_GLYPHSETS]] + ) + } + # get the codepoints from the glyphs key, flatten to a list of chrs and combine with the points from glyphsets + point_set.update(flatten(config[CONF_GLYPHS])) + size = config[CONF_SIZE] + # Create the codepoint to font file map + base_font = EFont(config[CONF_FILE], size, point_set) + point_font_map: dict[str, EFont] = {c: base_font for c in point_set} + # process extras, updating the map and extending the codepoint list + for extra in config[CONF_EXTRAS]: + extra_points = flatten(extra[CONF_GLYPHS]) + point_set.update(extra_points) + extra_font = EFont(extra[CONF_FILE], size, extra_points) + point_font_map.update({c: extra_font for c in extra_points}) + + codepoints = list(point_set) + codepoints.sort(key=functools.cmp_to_key(glyph_comparator)) glyph_args = {} data = [] bpp = config[CONF_BPP] @@ -473,10 +574,11 @@ async def to_code(config): else: mode = "L" scale = 256 // (1 << bpp) - for glyph in glyphs: - font = glyph_to_font_map[glyph].font - mask = font.getmask(glyph, mode=mode) - offset_x, offset_y = font.getoffset(glyph) + # create the data array for all glyphs + for codepoint in codepoints: + font = point_font_map[codepoint] + mask = font.font.getmask(codepoint, mode=mode) + offset_x, offset_y = font.font.getoffset(codepoint) width, height = mask.size glyph_data = [0] * ((height * width * bpp + 7) // 8) pos = 0 @@ -487,31 +589,34 @@ async def to_code(config): if pixel & (1 << (bpp - bit_num - 1)): glyph_data[pos // 8] |= 0x80 >> (pos % 8) pos += 1 - glyph_args[glyph] = GlyphInfo(len(data), offset_x, offset_y, width, height) + glyph_args[codepoint] = GlyphInfo(len(data), offset_x, offset_y, width, height) data += glyph_data rhs = [HexInt(x) for x in data] prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) + # Create the glyph table that points to data in the above array. glyph_initializer = [] - for glyph in glyphs: + for codepoint in codepoints: glyph_initializer.append( cg.StructInitializer( GlyphData, ( "a_char", - cg.RawExpression(f"(const uint8_t *){cpp_string_escape(glyph)}"), + cg.RawExpression( + f"(const uint8_t *){cpp_string_escape(codepoint)}" + ), ), ( "data", cg.RawExpression( - f"{str(prog_arr)} + {str(glyph_args[glyph].data_len)}" + f"{str(prog_arr)} + {str(glyph_args[codepoint].data_len)}" ), ), - ("offset_x", glyph_args[glyph].offset_x), - ("offset_y", glyph_args[glyph].offset_y), - ("width", glyph_args[glyph].width), - ("height", glyph_args[glyph].height), + ("offset_x", glyph_args[codepoint].offset_x), + ("offset_y", glyph_args[codepoint].offset_y), + ("width", glyph_args[codepoint].width), + ("height", glyph_args[codepoint].height), ) ) @@ -521,7 +626,7 @@ async def to_code(config): config[CONF_ID], glyphs, len(glyph_initializer), - font_list[0].ascent, - font_list[0].ascent + font_list[0].descent, + base_font.ascent, + base_font.ascent + base_font.descent, bpp, ) 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/host/gpio.py b/esphome/components/host/gpio.py index 180919de4f..0f22a790bd 100644 --- a/esphome/components/host/gpio.py +++ b/esphome/components/host/gpio.py @@ -1,5 +1,8 @@ import logging +from esphome import pins +import esphome.codegen as cg +import esphome.config_validation as cv from esphome.const import ( CONF_ID, CONF_INPUT, @@ -11,9 +14,6 @@ from esphome.const import ( CONF_PULLDOWN, CONF_PULLUP, ) -from esphome import pins -import esphome.config_validation as cv -import esphome.codegen as cg from .const import host_ns @@ -28,8 +28,10 @@ def _translate_pin(value): "This variable only supports pin numbers, not full pin schemas " "(with inverted and mode)." ) - if isinstance(value, int): + if isinstance(value, int) and not isinstance(value, bool): return value + if not isinstance(value, str): + raise cv.Invalid(f"Invalid pin number: {value}") try: return int(value) except ValueError: diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index 0407bbd326..78064fb4b4 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -6,6 +6,7 @@ from esphome.const import ( CONF_ESP8266_DISABLE_SSL_SUPPORT, CONF_ID, CONF_METHOD, + CONF_ON_ERROR, CONF_TIMEOUT, CONF_TRIGGER_ID, CONF_URL, @@ -185,6 +186,13 @@ HTTP_REQUEST_ACTION_SCHEMA = cv.Schema( cv.Optional(CONF_ON_RESPONSE): automation.validate_automation( {cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(HttpRequestResponseTrigger)} ), + cv.Optional(CONF_ON_ERROR): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + automation.Trigger.template() + ) + } + ), cv.Optional(CONF_MAX_RESPONSE_BUFFER_SIZE, default="1kB"): cv.validate_bytes, } ) @@ -272,5 +280,9 @@ async def http_request_action_to_code(config, action_id, template_arg, args): ], conf, ) + for conf in config.get(CONF_ON_ERROR, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID]) + cg.add(var.register_error_trigger(trigger)) + await automation.build_automation(trigger, [], conf) return var diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index c01baf8644..4ed2c834f8 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 { @@ -78,8 +135,8 @@ class HttpRequestComponent : public Component { protected: const char *useragent_{nullptr}; - bool follow_redirects_; - uint16_t redirect_limit_; + bool follow_redirects_{}; + uint16_t redirect_limit_{}; uint16_t timeout_{4500}; uint32_t watchdog_timeout_{0}; }; @@ -100,6 +157,8 @@ template class HttpRequestSendAction : public Action { void register_response_trigger(HttpRequestResponseTrigger *trigger) { this->response_triggers_.push_back(trigger); } + void register_error_trigger(Trigger<> *trigger) { this->error_triggers_.push_back(trigger); } + void set_max_response_buffer_size(size_t max_response_buffer_size) { this->max_response_buffer_size_ = max_response_buffer_size; } @@ -129,6 +188,8 @@ template class HttpRequestSendAction : public Action { auto container = this->parent_->start(this->url_.value(x...), this->method_.value(x...), body, headers); if (container == nullptr) { + for (auto *trigger : this->error_triggers_) + trigger->trigger(x...); return; } @@ -180,7 +241,8 @@ template class HttpRequestSendAction : public Action { std::map> headers_{}; std::map> json_{}; std::function json_func_{nullptr}; - std::vector response_triggers_; + std::vector response_triggers_{}; + std::vector *> error_triggers_{}; size_t max_response_buffer_size_{SIZE_MAX}; }; 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 d376907925..fa515a585f 100644 --- a/esphome/components/i2s_audio/__init__.py +++ b/esphome/components/i2s_audio/__init__.py @@ -8,7 +8,7 @@ from esphome.components.esp32.const import ( VARIANT_ESP32S3, ) import esphome.config_validation as cv -from esphome.const import CONF_CHANNEL, CONF_ID, CONF_SAMPLE_RATE +from esphome.const import CONF_BITS_PER_SAMPLE, CONF_CHANNEL, CONF_ID, CONF_SAMPLE_RATE from esphome.cpp_generator import MockObjClass import esphome.final_validate as fv @@ -25,13 +25,11 @@ 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" diff --git a/esphome/components/i2s_audio/speaker/__init__.py b/esphome/components/i2s_audio/speaker/__init__.py index 22a5af259d..dd43d6cb39 100644 --- a/esphome/components/i2s_audio/speaker/__init__.py +++ b/esphome/components/i2s_audio/speaker/__init__.py @@ -16,7 +16,8 @@ from .. import ( register_i2s_audio_component, ) -CODEOWNERS = ["@jesserockz"] +AUTO_LOAD = ["audio"] +CODEOWNERS = ["@jesserockz", "@kahrendt"] DEPENDENCIES = ["i2s_audio"] I2SAudioSpeaker = i2s_audio_ns.class_( @@ -25,6 +26,7 @@ I2SAudioSpeaker = i2s_audio_ns.class_( 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 = { @@ -33,6 +35,20 @@ INTERNAL_DAC_OPTIONS = { CONF_STEREO: i2s_dac_mode_t.I2S_DAC_CHANNEL_BOTH_EN, } +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] @@ -57,7 +73,7 @@ BASE_SCHEMA = ( .extend( { cv.Optional( - CONF_TIMEOUT, default="100ms" + CONF_TIMEOUT, default="500ms" ): cv.positive_time_period_milliseconds, } ) @@ -77,6 +93,9 @@ CONFIG_SCHEMA = cv.All( cv.Required( CONF_I2S_DOUT_PIN ): pins.internal_gpio_output_pin_number, + cv.Optional(CONF_I2S_COMM_FMT, default="stand_i2s"): cv.enum( + I2C_COMM_FMT_OPTIONS, lower=True + ), } ), }, @@ -96,4 +115,5 @@ async def to_code(config): cg.add(var.set_internal_dac_mode(config[CONF_CHANNEL])) else: cg.add(var.set_dout_pin(config[CONF_I2S_DOUT_PIN])) + cg.add(var.set_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 4b427898a2..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,186 +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; -} - -template const uint8_t *convert_data_format(const a *from, b *to, size_t &bytes, bool repeat) { - if (sizeof(a) == sizeof(b) && !repeat) { - return reinterpret_cast(from); - } - const b *result = to; - for (size_t i = 0; i < bytes; i += sizeof(a)) { - b value = static_cast(*from++) << (sizeof(b) - sizeof(a)) * 8; - *to++ = value; - if (repeat) - *to++ = value; - } - bytes *= (sizeof(b) / sizeof(a)) * (repeat ? 2 : 1); // NOLINT - return reinterpret_cast(result); -} - -void I2SAudioSpeaker::player_task(void *params) { - I2SAudioSpeaker *this_speaker = (I2SAudioSpeaker *) params; - - TaskEvent event; - event.type = TaskEventType::STARTING; - xQueueSend(this_speaker->event_queue_, &event, portMAX_DELAY); - - i2s_driver_config_t config = { - .mode = (i2s_mode_t) (this_speaker->i2s_mode_ | I2S_MODE_TX), - .sample_rate = this_speaker->sample_rate_, - .bits_per_sample = this_speaker->bits_per_sample_, - .channel_format = this_speaker->channel_, - .communication_format = I2S_COMM_FORMAT_STAND_I2S, - .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, - .dma_buf_count = 8, - .dma_buf_len = 256, - .use_apll = this_speaker->use_apll_, - .tx_desc_auto_clear = true, - .fixed_mclk = 0, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - .bits_per_chan = this_speaker->bits_per_channel_, - }; -#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); - - int32_t buffer[BUFFER_SIZE]; - - while (true) { - if (xQueueReceive(this_speaker->buffer_queue_, &data_event, this_speaker->timeout_ / portTICK_PERIOD_MS) != - pdTRUE) { - break; // End of audio from main thread - } - if (data_event.stop) { - // Stop signal from main thread - xQueueReset(this_speaker->buffer_queue_); // Flush queue - break; - } - - const uint8_t *data = data_event.data; - size_t remaining = data_event.len; - switch (this_speaker->bits_per_sample_) { - case I2S_BITS_PER_SAMPLE_8BIT: - case I2S_BITS_PER_SAMPLE_16BIT: { - data = convert_data_format(reinterpret_cast(data), reinterpret_cast(buffer), - remaining, this_speaker->channel_ == I2S_CHANNEL_FMT_ALL_LEFT); - break; - } - case I2S_BITS_PER_SAMPLE_24BIT: - case I2S_BITS_PER_SAMPLE_32BIT: { - data = convert_data_format(reinterpret_cast(data), reinterpret_cast(buffer), - remaining, this_speaker->channel_ == I2S_CHANNEL_FMT_ALL_LEFT); - break; - } - } - - while (remaining != 0) { - size_t bytes_written; - esp_err_t err = - i2s_write(this_speaker->parent_->get_port(), data, remaining, &bytes_written, (32 / portTICK_PERIOD_MS)); - if (err != ESP_OK) { - event = {.type = TaskEventType::WARNING, .err = err}; - if (xQueueSend(this_speaker->event_queue_, &event, 10 / portTICK_PERIOD_MS) != pdTRUE) { - ESP_LOGW(TAG, "Failed to send WARNING event"); - } - continue; - } - data += bytes_written; - remaining -= bytes_written; - } - } - - 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); } } @@ -203,92 +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; - this->status_clear_warning(); - break; - case TaskEventType::STOPPING: - ESP_LOGD(TAG, "Stopping I2S Audio Speaker"); - 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 7adc4e8a24..3c512d4d4d 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h @@ -5,38 +5,21 @@ #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, - 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 I2SAudioOut, public speaker::Speaker, public Component { public: float get_setup_priority() const override { return esphome::setup_priority::LATE; } @@ -49,33 +32,105 @@ class I2SAudioSpeaker : public I2SAudioOut, public speaker::Speaker, public Comp #if SOC_I2S_SUPPORTS_DAC void set_internal_dac_mode(i2s_dac_mode_t mode) { this->internal_dac_mode_ = mode; } #endif + 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_; - uint32_t timeout_{0}; - 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 + 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..739ad07843 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): @@ -196,6 +196,10 @@ CONFIG_SCHEMA = cv.All( _validate, ) +FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( + "ili9xxx", require_miso=False, require_mosi=True +) + async def to_code(config): rhs = MODELS[config[CONF_MODEL]].new() 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 e80ba4498f..8742540067 100644 --- a/esphome/components/image/__init__.py +++ b/esphome/components/image/__init__.py @@ -6,7 +6,7 @@ import logging from pathlib import Path import re -from magic import Magic +import puremagic from esphome import core, external_files import esphome.codegen as cg @@ -237,8 +237,8 @@ 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 - # 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 @@ -281,8 +281,7 @@ async def to_code(config): 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: @@ -362,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..afa5583e59 100644 --- a/esphome/components/internal_temperature/internal_temperature.cpp +++ b/esphome/components/internal_temperature/internal_temperature.cpp @@ -7,8 +7,14 @@ 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) || defined(USE_ESP32_VARIANT_ESP32H2) || \ + defined(USE_ESP32_VARIANT_ESP32C2) +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) #include "driver/temp_sensor.h" +#else +#include "driver/temperature_sensor.h" +#endif // ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) #endif // USE_ESP32_VARIANT #endif // USE_ESP32 #ifdef USE_RP2040 @@ -24,6 +30,13 @@ namespace esphome { namespace internal_temperature { static const char *const TAG = "internal_temperature"; +#ifdef USE_ESP32 +#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)) && \ + (defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S2) || \ + defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32H2) || defined(USE_ESP32_VARIANT_ESP32C2)) +static temperature_sensor_handle_t tsensNew = NULL; +#endif // ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) && USE_ESP32_VARIANT +#endif // USE_ESP32 void InternalTemperatureSensor::update() { float temperature = NAN; @@ -34,7 +47,10 @@ 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) || defined(USE_ESP32_VARIANT_ESP32H2) || \ + defined(USE_ESP32_VARIANT_ESP32C2) +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) temp_sensor_config_t tsens = TSENS_CONFIG_DEFAULT(); temp_sensor_set_config(tsens); temp_sensor_start(); @@ -45,6 +61,13 @@ void InternalTemperatureSensor::update() { esp_err_t result = temp_sensor_read_celsius(&temperature); temp_sensor_stop(); success = (result == ESP_OK); +#else + esp_err_t result = temperature_sensor_get_celsius(tsensNew, &temperature); + success = (result == ESP_OK); + if (!success) { + ESP_LOGE(TAG, "Failed to get temperature: %d", result); + } +#endif // ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) #endif // USE_ESP32_VARIANT #endif // USE_ESP32 #ifdef USE_RP2040 @@ -73,6 +96,32 @@ void InternalTemperatureSensor::update() { } } +void InternalTemperatureSensor::setup() { +#ifdef USE_ESP32 +#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)) && \ + (defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S2) || \ + defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32H2) || defined(USE_ESP32_VARIANT_ESP32C2)) + ESP_LOGCONFIG(TAG, "Setting up temperature sensor..."); + + temperature_sensor_config_t tsens_config = TEMPERATURE_SENSOR_CONFIG_DEFAULT(-10, 80); + + esp_err_t result = temperature_sensor_install(&tsens_config, &tsensNew); + if (result != ESP_OK) { + ESP_LOGE(TAG, "Failed to install temperature sensor: %d", result); + this->mark_failed(); + return; + } + + result = temperature_sensor_enable(tsensNew); + if (result != ESP_OK) { + ESP_LOGE(TAG, "Failed to enable temperature sensor: %d", result); + this->mark_failed(); + return; + } +#endif // ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) && USE_ESP32_VARIANT +#endif // USE_ESP32 +} + void InternalTemperatureSensor::dump_config() { LOG_SENSOR("", "Internal Temperature Sensor", this); } } // namespace internal_temperature diff --git a/esphome/components/internal_temperature/internal_temperature.h b/esphome/components/internal_temperature/internal_temperature.h index 0e46a69769..78e3bcef7d 100644 --- a/esphome/components/internal_temperature/internal_temperature.h +++ b/esphome/components/internal_temperature/internal_temperature.h @@ -8,6 +8,7 @@ namespace internal_temperature { class InternalTemperatureSensor : public sensor::Sensor, public PollingComponent { public: + void setup() override; void dump_config() override; void update() override; diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index cc7fae7e70..b29d2e309c 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -46,7 +46,7 @@ from .const import ( _LOGGER = logging.getLogger(__name__) CODEOWNERS = ["@kuba2k2"] -AUTO_LOAD = [] +AUTO_LOAD = ["preferences"] def _detect_variant(value): diff --git a/esphome/components/libretiny/gpio.py b/esphome/components/libretiny/gpio.py index 1d7b37cc9b..07eb0ce133 100644 --- a/esphome/components/libretiny/gpio.py +++ b/esphome/components/libretiny/gpio.py @@ -1,8 +1,8 @@ import logging +from esphome import pins import esphome.codegen as cg import esphome.config_validation as cv -from esphome import pins from esphome.const import ( CONF_ANALOG, CONF_ID, @@ -103,8 +103,10 @@ def _translate_pin(value): "This variable only supports pin numbers, not full pin schemas " "(with inverted and mode)." ) - if isinstance(value, int): + if isinstance(value, int) and not isinstance(value, bool): return value + if not isinstance(value, str): + raise cv.Invalid(f"Invalid pin number: {value}") try: return int(value) except ValueError: 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/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index 64f254cde8..d03adc9624 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -7,6 +7,7 @@ import esphome.config_validation as cv from esphome.const import ( CONF_AUTO_CLEAR_ENABLED, CONF_BUFFER_SIZE, + CONF_GROUP, CONF_ID, CONF_LAMBDA, CONF_ON_IDLE, @@ -23,10 +24,17 @@ 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 add_define -from .encoders import ENCODERS_CONFIG, encoders_to_code, initial_focus_to_code +from .encoders import ( + ENCODERS_CONFIG, + encoders_to_code, + get_default_group, + initial_focus_to_code, +) from .gradient import GRADIENT_SCHEMA, gradients_to_code +from .hello_world import get_hello_world +from .keypads import KEYPADS_CONFIG, keypads_to_code from .lv_validation import lv_bool, lv_images_used -from .lvcode import LvContext, LvglComponent +from .lvcode import LvContext, LvglComponent, lvgl_static from .schemas import ( DISP_BG_SCHEMA, FLEX_OBJ_SCHEMA, @@ -47,12 +55,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 @@ -69,6 +78,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 @@ -107,6 +117,7 @@ for w_type in ( spinbox_spec, keyboard_spec, tileview_spec, + qr_code_spec, ): WIDGET_TYPES[w_type.name] = w_type @@ -148,43 +159,80 @@ def generate_lv_conf_h(): return LV_CONF_H_FORMAT.format("\n".join(definitions)) -def final_validation(config): - if pages := config.get(CONF_PAGES): - if all(p[df.CONF_SKIP] for p in pages): - raise cv.Invalid("At least one page must not be skipped") +def multi_conf_validate(configs: list[dict]): + displays = [config[df.CONF_DISPLAYS] for config in configs] + # flatten the display list + display_list = [disp for disps in displays for disp in disps] + if len(display_list) != len(set(display_list)): + raise cv.Invalid("A display ID may be used in only one LVGL instance") + for config in configs: + for item in (df.CONF_ENCODERS, df.CONF_KEYPADS): + for enc in config.get(item, ()): + if CONF_GROUP not in enc: + raise cv.Invalid( + f"'{item}' must have an explicit group set when using multiple LVGL instances" + ) + base_config = configs[0] + for config in configs[1:]: + for item in ( + df.CONF_LOG_LEVEL, + df.CONF_COLOR_DEPTH, + df.CONF_BYTE_ORDER, + df.CONF_TRANSPARENCY_KEY, + ): + if base_config[item] != config[item]: + raise cv.Invalid( + f"Config item '{item}' must be the same for all LVGL instances" + ) + + +def final_validation(configs): + if len(configs) != 1: + multi_conf_validate(configs) global_config = full_config.get() - for display_id in config[df.CONF_DISPLAYS]: - path = global_config.get_path_for_id(display_id)[:-1] - display = global_config.get_config_for_path(path) - if CONF_LAMBDA in display: - raise cv.Invalid("Using lambda: in display config not compatible with LVGL") - if display[CONF_AUTO_CLEAR_ENABLED]: - raise cv.Invalid( - "Using auto_clear_enabled: true in display config not compatible with LVGL" - ) - buffer_frac = config[CONF_BUFFER_SIZE] - if CORE.is_esp32 and buffer_frac > 0.5 and "psram" not in global_config: - LOGGER.warning("buffer_size: may need to be reduced without PSRAM") - for image_id in lv_images_used: - path = global_config.get_path_for_id(image_id)[:-1] - image_conf = global_config.get_config_for_path(path) - if image_conf[CONF_TYPE] in ("RGBA", "RGB24"): - raise cv.Invalid( - "Using RGBA or RGB24 in image config not compatible with LVGL", path - ) - for w in focused_widgets: - path = global_config.get_path_for_id(w) - widget_conf = global_config.get_config_for_path(path[:-1]) - 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, - ) + for config in configs: + if pages := config.get(CONF_PAGES): + if all(p[df.CONF_SKIP] for p in pages): + raise cv.Invalid("At least one page must not be skipped") + for display_id in config[df.CONF_DISPLAYS]: + path = global_config.get_path_for_id(display_id)[:-1] + display = global_config.get_config_for_path(path) + if CONF_LAMBDA in display: + raise cv.Invalid( + "Using lambda: in display config not compatible with LVGL" + ) + if display[CONF_AUTO_CLEAR_ENABLED]: + raise cv.Invalid( + "Using auto_clear_enabled: true in display config not compatible with LVGL" + ) + buffer_frac = config[CONF_BUFFER_SIZE] + if CORE.is_esp32 and buffer_frac > 0.5 and "psram" not in global_config: + LOGGER.warning("buffer_size: may need to be reduced without PSRAM") + for image_id in lv_images_used: + path = global_config.get_path_for_id(image_id)[:-1] + image_conf = global_config.get_config_for_path(path) + if image_conf[CONF_TYPE] in ("RGBA", "RGB24"): + raise cv.Invalid( + "Using RGBA or RGB24 in image config not compatible with LVGL", path + ) + for w in focused_widgets: + path = global_config.get_path_for_id(w) + widget_conf = global_config.get_config_for_path(path[:-1]) + 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, + ) -async def to_code(config): +async def to_code(configs): + config_0 = configs[0] + # Global configuration 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. @@ -198,45 +246,34 @@ 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_COLOR_DEPTH", config[df.CONF_COLOR_DEPTH]) + add_define( + "LV_LOG_LEVEL", + f"LV_LOG_LEVEL_{df.LV_LOG_LEVELS[config_0[df.CONF_LOG_LEVEL]]}", + ) + cg.add_define( + "LVGL_LOG_LEVEL", + cg.RawExpression(f"ESPHOME_LOG_LEVEL_{config_0[df.CONF_LOG_LEVEL]}"), + ) + add_define("LV_COLOR_DEPTH", config_0[df.CONF_COLOR_DEPTH]) for font in helpers.lv_fonts_used: add_define(f"LV_FONT_{font.upper()}") - if config[df.CONF_COLOR_DEPTH] == 16: + if config_0[df.CONF_COLOR_DEPTH] == 16: add_define( "LV_COLOR_16_SWAP", - "1" if config[df.CONF_BYTE_ORDER] == "big_endian" else "0", + "1" if config_0[df.CONF_BYTE_ORDER] == "big_endian" else "0", ) add_define( "LV_COLOR_CHROMA_KEY", - await lvalid.lv_color.process(config[df.CONF_TRANSPARENCY_KEY]), + await lvalid.lv_color.process(config_0[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 - elif frac >= 0.375: - frac = 2 - elif frac > 0.19: - frac = 4 - else: - frac = 8 - cg.add(lv_component.set_buffer_frac(int(frac))) - cg.add(lv_component.set_full_refresh(config[df.CONF_FULL_REFRESH])) - for font in helpers.esphome_fonts_used: await cg.get_variable(font) cg.new_Pvariable(ID(f"{font}_engine", True, type=FontEngine), MockObj(font)) - default_font = config[df.CONF_DEFAULT_FONT] + default_font = config_0[df.CONF_DEFAULT_FONT] if not lvalid.is_lv_font(default_font): add_define( "LV_FONT_CUSTOM_DECLARE", f"LV_FONT_DECLARE(*{df.DEFAULT_ESPHOME_FONT})" @@ -252,49 +289,103 @@ async def to_code(config): add_define("LV_FONT_DEFAULT", df.DEFAULT_ESPHOME_FONT) else: add_define("LV_FONT_DEFAULT", await lvalid.lv_font.process(default_font)) + cg.add(lvgl_static.esphome_lvgl_init()) + default_group = get_default_group(config_0) - 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() - async with LvContext(lv_component): - await generate_triggers(lv_component) - await generate_page_triggers(lv_component, config) - for conf in config.get(CONF_ON_IDLE, ()): - templ = await cg.templatable(conf[CONF_TIMEOUT], [], cg.uint32) - idle_trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], lv_component, templ) - await build_automation(idle_trigger, [], conf) - await initial_focus_to_code(config) + for config in configs: + frac = config[CONF_BUFFER_SIZE] + if frac >= 0.75: + frac = 1 + elif frac >= 0.375: + frac = 2 + elif frac > 0.19: + frac = 4 + else: + frac = 8 + 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) + lv_scr_act = get_scr_act(lv_component) + async with LvContext(): + await touchscreens_to_code(lv_component, config) + await encoders_to_code(lv_component, config, default_group) + await keypads_to_code(lv_component, config, default_group) + 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(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(): + await generate_triggers() + for config in configs: + lv_component = await cg.get_variable(config[CONF_ID]) + await generate_page_triggers(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) + 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) + + # This must be done after all widgets are created 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): value = cv.ensure_list(cv.use_id(Display))(config) - return value or [cv.use_id(Display)(config)] + value = value or [cv.use_id(Display)(config)] + if len(set(value)) != len(value): + raise cv.Invalid("Display IDs must be unique") + return value + + +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 = ( +LVGL_SCHEMA = ( cv.polling_component_schema("1s") .extend(obj_schema(obj_spec)) .extend( @@ -304,9 +395,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" @@ -331,6 +423,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) @@ -345,8 +447,24 @@ CONFIG_SCHEMA = ( 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.Optional(df.CONF_KEYPADS, default=None): KEYPADS_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) +) + + +def lvgl_config_schema(config): + """ + Can't use cv.ensure_list here because it converts an empty config to an empty list, + rather than a default config. + """ + if not config or isinstance(config, dict): + return [LVGL_SCHEMA(config)] + return cv.Schema([LVGL_SCHEMA])(config) + + +CONFIG_SCHEMA = lvgl_config_schema diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py index cdc7553e81..c26ae54892 100644 --- a/esphome/components/lvgl/automation.py +++ b/esphome/components/lvgl/automation.py @@ -1,11 +1,10 @@ -from collections.abc import Awaitable -from typing import Callable +from typing import Any, Callable 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,8 +22,6 @@ from .lvcode import ( UPDATE_EVENT, LambdaContext, LocalVariable, - LvConditional, - LvglComponent, ReturnStatement, add_line_marks, lv, @@ -47,8 +44,8 @@ from .types import ( ) from .widgets import ( Widget, + get_scr_act, get_widgets, - lv_scr_act, set_obj_properties, wait_for_widgets, ) @@ -59,15 +56,13 @@ focused_widgets = set() async def action_to_code( widgets: list[Widget], - action: Callable[[Widget], Awaitable[None]], + action: Callable[[Widget], Any], action_id, template_arg, args, ): await wait_for_widgets() async with LambdaContext(parameters=args, where=action_id) as context: - with LvConditional(lv_expr.is_pre_initialise()): - context.add(RawExpression("return")) for widget in widgets: await action(widget) var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) @@ -126,7 +121,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 +131,22 @@ 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), + }, + key=CONF_ID, + ), + LVGL_SCHEMA, ), ) async def obj_invalidate_to_code(config, action_id, template_arg, args): - widgets = await get_widgets(config) or [lv_scr_act] + if CONF_LVGL_ID in config: + lv_comp = await cg.get_variable(config[CONF_LVGL_ID]) + widgets = [get_scr_act(lv_comp)] + else: + widgets = await get_widgets(config) async def do_invalidate(widget: Widget): lv_obj.invalidate(widget.obj) @@ -155,16 +157,14 @@ async def obj_invalidate_to_code(config, action_id, template_arg, args): @automation.register_action( "lvgl.update", LvglAction, - DISP_BG_SCHEMA.extend( - { - cv.GenerateID(): cv.use_id(LvglComponent), - } - ).add_extra(cv.has_at_least_one_key(CONF_DISP_BG_COLOR, CONF_DISP_BG_IMAGE)), + DISP_BG_SCHEMA.extend(LVGL_SCHEMA).add_extra( + cv.has_at_least_one_key(CONF_DISP_BG_COLOR, CONF_DISP_BG_IMAGE) + ), ) async def lvgl_update_to_code(config, action_id, template_arg, args): - widgets = await get_widgets(config) + widgets = await get_widgets(config, CONF_LVGL_ID) 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()) @@ -175,32 +175,33 @@ async def lvgl_update_to_code(config, action_id, template_arg, args): @automation.register_action( "lvgl.pause", LvglAction, - { - cv.GenerateID(): cv.use_id(LvglComponent), - cv.Optional(CONF_SHOW_SNOW, default=False): lv_bool, - }, + LVGL_SCHEMA.extend( + { + cv.Optional(CONF_SHOW_SNOW, default=False): lv_bool, + } + ), ) async def pause_action_to_code(config, action_id, template_arg, args): + lv_comp = await cg.get_variable(config[CONF_LVGL_ID]) async with LambdaContext(LVGL_COMP_ARG) as context: add_line_marks(where=action_id) lv_add(lvgl_comp.set_paused(True, config[CONF_SHOW_SNOW])) var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) - await cg.register_parented(var, config[CONF_ID]) + await cg.register_parented(var, lv_comp) return var @automation.register_action( "lvgl.resume", LvglAction, - { - cv.GenerateID(): cv.use_id(LvglComponent), - }, + LVGL_SCHEMA, ) async def resume_action_to_code(config, action_id, template_arg, args): + lv_comp = await cg.get_variable(config[CONF_LVGL_ID]) async with LambdaContext(LVGL_COMP_ARG, where=action_id) as context: lv_add(lvgl_comp.set_paused(False, False)) var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) - await cg.register_parented(var, config[CONF_ID]) + await cg.register_parented(var, lv_comp) return var @@ -259,14 +260,15 @@ def focused_id(value): ObjUpdateAction, cv.Any( cv.maybe_simple_value( - { - cv.Optional(CONF_GROUP): cv.use_id(lv_group_t), - cv.Required(CONF_ACTION): cv.one_of( - "MARK", "RESTORE", "NEXT", "PREVIOUS", upper=True - ), - cv.GenerateID(CONF_LVGL_ID): cv.use_id(LvglComponent), - cv.Optional(CONF_FREEZE, default=False): cv.boolean, - }, + LVGL_SCHEMA.extend( + { + cv.Optional(CONF_GROUP): cv.use_id(lv_group_t), + cv.Required(CONF_ACTION): cv.one_of( + "MARK", "RESTORE", "NEXT", "PREVIOUS", upper=True + ), + cv.Optional(CONF_FREEZE, default=False): cv.boolean, + } + ), key=CONF_ACTION, ), cv.maybe_simple_value( diff --git a/esphome/components/lvgl/binary_sensor/__init__.py b/esphome/components/lvgl/binary_sensor/__init__.py index 56984405aa..ffbdc977b2 100644 --- a/esphome/components/lvgl/binary_sensor/__init__.py +++ b/esphome/components/lvgl/binary_sensor/__init__.py @@ -1,4 +1,3 @@ -import esphome.codegen as cg from esphome.components.binary_sensor import ( BinarySensor, binary_sensor_schema, @@ -6,36 +5,30 @@ from esphome.components.binary_sensor import ( ) import esphome.config_validation as cv -from ..defines import CONF_LVGL_ID, CONF_WIDGET -from ..lvcode import EVENT_ARG, LambdaContext, LvContext -from ..schemas import LVGL_SCHEMA +from ..defines import CONF_WIDGET +from ..lvcode import EVENT_ARG, LambdaContext, LvContext, lvgl_static from ..types import LV_EVENT, lv_pseudo_button_t from ..widgets import Widget, get_widgets, wait_for_widgets -CONFIG_SCHEMA = ( - binary_sensor_schema(BinarySensor) - .extend(LVGL_SCHEMA) - .extend( - { - cv.Required(CONF_WIDGET): cv.use_id(lv_pseudo_button_t), - } - ) +CONFIG_SCHEMA = binary_sensor_schema(BinarySensor).extend( + { + cv.Required(CONF_WIDGET): cv.use_id(lv_pseudo_button_t), + } ) async def to_code(config): sensor = await new_binary_sensor(config) - paren = await cg.get_variable(config[CONF_LVGL_ID]) widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] assert isinstance(widget, Widget) await wait_for_widgets() async with LambdaContext(EVENT_ARG) as pressed_ctx: pressed_ctx.add(sensor.publish_state(widget.is_pressed())) - async with LvContext(paren) as ctx: + async with LvContext() as ctx: ctx.add(sensor.publish_initial_state(widget.is_pressed())) ctx.add( - paren.add_event_cb( + lvgl_static.add_event_cb( widget.obj, await pressed_ctx.get_lambda(), LV_EVENT.PRESSING, diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index 3db49d26a4..ea345fa55c 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -189,14 +189,14 @@ LV_ANIM = LvConstant( LV_GRAD_DIR = LvConstant("LV_GRAD_DIR_", "NONE", "HOR", "VER") LV_DITHER = LvConstant("LV_DITHER_", "NONE", "ORDERED", "ERR_DIFF") -LOG_LEVELS = ( - "TRACE", - "INFO", - "WARN", - "ERROR", - "USER", - "NONE", -) +LV_LOG_LEVELS = { + "VERBOSE": "TRACE", + "DEBUG": "TRACE", + "INFO": "INFO", + "WARN": "WARN", + "ERROR": "ERROR", + "NONE": "NONE", +} LV_LONG_MODES = LvConstant( "LV_LABEL_LONG_", @@ -408,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" @@ -437,6 +438,7 @@ CONF_HEADER_MODE = "header_mode" CONF_HOME = "home" CONF_INITIAL_FOCUS = "initial_focus" CONF_KEY_CODE = "key_code" +CONF_KEYPADS = "keypads" CONF_LAYOUT = "layout" CONF_LEFT_BUTTON = "left_button" CONF_LINE_WIDTH = "line_width" @@ -451,7 +453,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" @@ -465,6 +470,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" @@ -472,6 +478,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/encoders.py b/esphome/components/lvgl/encoders.py index 81bcda95b4..952572df43 100644 --- a/esphome/components/lvgl/encoders.py +++ b/esphome/components/lvgl/encoders.py @@ -17,7 +17,7 @@ from .defines import ( from .helpers import lvgl_components_required, requires_component from .lvcode import lv, lv_add, lv_assign, lv_expr, lv_Pvariable from .schemas import ENCODER_SCHEMA -from .types import lv_group_t, lv_indev_type_t +from .types import lv_group_t, lv_indev_type_t, lv_key_t ENCODERS_CONFIG = cv.ensure_list( ENCODER_SCHEMA.extend( @@ -39,10 +39,13 @@ ENCODERS_CONFIG = cv.ensure_list( ) -async def encoders_to_code(var, config): - default_group = lv_Pvariable(lv_group_t, config[CONF_DEFAULT_GROUP]) - lv_assign(default_group, lv_expr.group_create()) - lv.group_set_default(default_group) +def get_default_group(config): + default_group = cg.Pvariable(config[CONF_DEFAULT_GROUP], lv_expr.group_create()) + cg.add(lv.group_set_default(default_group)) + return default_group + + +async def encoders_to_code(var, config, default_group): for enc_conf in config[CONF_ENCODERS]: lvgl_components_required.add("KEY_LISTENER") lpt = enc_conf[CONF_LONG_PRESS_TIME].total_milliseconds @@ -54,14 +57,14 @@ async def encoders_to_code(var, config): if sensor_config := enc_conf.get(CONF_SENSOR): if isinstance(sensor_config, dict): b_sensor = await cg.get_variable(sensor_config[CONF_LEFT_BUTTON]) - cg.add(listener.set_left_button(b_sensor)) + cg.add(listener.add_button(b_sensor, lv_key_t.LV_KEY_LEFT)) b_sensor = await cg.get_variable(sensor_config[CONF_RIGHT_BUTTON]) - cg.add(listener.set_right_button(b_sensor)) + cg.add(listener.add_button(b_sensor, lv_key_t.LV_KEY_RIGHT)) else: sensor_config = await cg.get_variable(sensor_config) lv_add(listener.set_sensor(sensor_config)) b_sensor = await cg.get_variable(enc_conf[CONF_ENTER_BUTTON]) - cg.add(listener.set_enter_button(b_sensor)) + cg.add(listener.add_button(b_sensor, lv_key_t.LV_KEY_ENTER)) if group := enc_conf.get(CONF_GROUP): group = lv_Pvariable(lv_group_t, group) lv_assign(group, lv_expr.group_create()) 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/keypads.py b/esphome/components/lvgl/keypads.py new file mode 100644 index 0000000000..5e2953d57f --- /dev/null +++ b/esphome/components/lvgl/keypads.py @@ -0,0 +1,77 @@ +import esphome.codegen as cg +from esphome.components.binary_sensor import BinarySensor +import esphome.config_validation as cv +from esphome.const import CONF_GROUP, CONF_ID + +from .defines import ( + CONF_ENCODERS, + CONF_INITIAL_FOCUS, + CONF_KEYPADS, + CONF_LONG_PRESS_REPEAT_TIME, + CONF_LONG_PRESS_TIME, + literal, +) +from .helpers import lvgl_components_required +from .lvcode import lv, lv_assign, lv_expr, lv_Pvariable +from .schemas import ENCODER_SCHEMA +from .types import lv_group_t, lv_indev_type_t + +KEYPAD_KEYS = ( + "up", + "down", + "right", + "left", + "esc", + "del", + "backspace", + "enter", + "next", + "prev", + "home", + "end", + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "#", + "*", +) + +KEYPADS_CONFIG = cv.ensure_list( + ENCODER_SCHEMA.extend( + {cv.Optional(key): cv.use_id(BinarySensor) for key in KEYPAD_KEYS} + ) +) + + +async def keypads_to_code(var, config, default_group): + for enc_conf in config[CONF_KEYPADS]: + lvgl_components_required.add("KEY_LISTENER") + lpt = enc_conf[CONF_LONG_PRESS_TIME].total_milliseconds + lprt = enc_conf[CONF_LONG_PRESS_REPEAT_TIME].total_milliseconds + listener = cg.new_Pvariable( + enc_conf[CONF_ID], lv_indev_type_t.LV_INDEV_TYPE_KEYPAD, lpt, lprt + ) + await cg.register_parented(listener, var) + for key in [x for x in enc_conf if x in KEYPAD_KEYS]: + b_sensor = await cg.get_variable(enc_conf[key]) + cg.add(listener.add_button(b_sensor, literal(f"LV_KEY_{key.upper()}"))) + if group := enc_conf.get(CONF_GROUP): + group = lv_Pvariable(lv_group_t, group) + lv_assign(group, lv_expr.group_create()) + else: + group = default_group + lv.indev_set_group(lv_expr.indev_drv_register(listener.get_drv()), group) + + +async def initial_focus_to_code(config): + for enc_conf in config[CONF_ENCODERS]: + if default_focus := enc_conf.get(CONF_INITIAL_FOCUS): + obj = await cg.get_variable(default_focus) + lv.group_focus_obj(obj) diff --git a/esphome/components/lvgl/light/__init__.py b/esphome/components/lvgl/light/__init__.py index a0eeded349..dcdf67a520 100644 --- a/esphome/components/lvgl/light/__init__.py +++ b/esphome/components/lvgl/light/__init__.py @@ -2,11 +2,10 @@ 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_WIDGET from ..lvcode import LvContext -from ..schemas import LVGL_SCHEMA from ..types import LvType, lvgl_ns from ..widgets import get_widgets, wait_for_widgets @@ -15,19 +14,18 @@ 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) +) async def to_code(config): var = cg.new_Pvariable(config[CONF_OUTPUT_ID]) await light.register_light(var, config) - paren = await cg.get_variable(config[CONF_LVGL_ID]) - widget = await get_widgets(config, CONF_LED) + widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] await wait_for_widgets() - async with LvContext(paren) as ctx: + async with LvContext() as ctx: ctx.add(var.set_obj(widget.obj)) diff --git a/esphome/components/lvgl/lv_validation.py b/esphome/components/lvgl/lv_validation.py index 8593deb869..b91b0905df 100644 --- a/esphome/components/lvgl/lv_validation.py +++ b/esphome/components/lvgl/lv_validation.py @@ -31,7 +31,6 @@ from .defines import ( literal, ) from .helpers import esphome_fonts_used, lv_fonts_used, requires_component -from .lvcode import lv_expr from .types import lv_font_t, lv_gradient_t, lv_img_t opacity_consts = LvConstant("LV_OPA_", "TRANSP", "COVER") @@ -49,17 +48,172 @@ 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): return literal( f"lv_color_make({(value >> 16) & 0xFF}, {(value >> 8) & 0xFF}, {value & 0xFF})" @@ -88,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 @@ -111,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""" @@ -118,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) @@ -175,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) @@ -247,6 +404,7 @@ 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)) diff --git a/esphome/components/lvgl/lvcode.py b/esphome/components/lvgl/lvcode.py index 3a080d63e9..6b98cc4251 100644 --- a/esphome/components/lvgl/lvcode.py +++ b/esphome/components/lvgl/lvcode.py @@ -178,22 +178,15 @@ class LvContext(LambdaContext): added_lambda_count = 0 - def __init__(self, lv_component, args=None): + def __init__(self, args=None): self.args = args or LVGL_COMP_ARG super().__init__(parameters=self.args) - self.lv_component = lv_component - - async def add_init_lambda(self): - if self.code_list: - cg.add(self.lv_component.add_init_lambda(await self.get_lambda())) - LvContext.added_lambda_count += 1 async def __aexit__(self, exc_type, exc_val, exc_tb): await super().__aexit__(exc_type, exc_val, exc_tb) - 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): @@ -304,6 +297,7 @@ lv_expr = LvExpr("lv_") lv_obj = MockLv("lv_obj_") # Operations on the LVGL component lvgl_comp = MockObj(LVGL_COMP, "->") +lvgl_static = MockObj("LvglComponent", "::") # equivalent to cg.add() for the current code context diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index 89c9828740..41346bc732 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,43 +65,57 @@ 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::esphome_lvgl_init() { + lv_init(); + lv_update_event = static_cast(lv_event_register_id()); + lv_api_event = static_cast(lv_event_register_id()); } 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); + lv_obj_add_event_cb(obj, callback, event, nullptr); } void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1, lv_event_code_t event2) { - this->add_event_cb(obj, callback, event1); - this->add_event_cb(obj, callback, event2); + add_event_cb(obj, callback, event1); + add_event_cb(obj, callback, event2); } void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1, lv_event_code_t event2, lv_event_code_t event3) { - this->add_event_cb(obj, callback, event1); - this->add_event_cb(obj, callback, event2); - this->add_event_cb(obj, callback, event3); + add_event_cb(obj, callback, event1); + add_event_cb(obj, callback, event2); + add_event_cb(obj, callback, event3); } void LvglComponent::add_page(LvPageType *page) { this->pages_.push_back(page); @@ -133,19 +143,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,9 +215,18 @@ 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) { +LVTouchListener::LVTouchListener(uint16_t long_press_time, uint16_t long_press_repeat_time, LvglComponent *parent) { + this->set_parent(parent); lv_indev_drv_init(&this->drv_); + this->drv_.disp = parent->get_disp(); this->drv_.long_press_repeat_time = long_press_repeat_time; this->drv_.long_press_time = long_press_time; this->drv_.type = LV_INDEV_TYPE_POINTER; @@ -178,6 +242,7 @@ LVTouchListener::LVTouchListener(uint16_t long_press_time, uint16_t long_press_r } }; } + void LVTouchListener::update(const touchscreen::TouchPoints_t &tpoints) { this->touch_pressed_ = !this->parent_->is_paused() && !tpoints.empty(); if (this->touch_pressed_) @@ -203,6 +268,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 +359,72 @@ 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 - lv_init(); - lv_update_event = static_cast(lv_event_register_id()); - lv_api_event = static_cast(lv_event_register_id()); +/** + * @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) { 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 +432,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 +476,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 d5cff51de2..208cb1cbd5 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,7 +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(); #if LV_COLOR_DEPTH == 16 static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_565; #elif LV_COLOR_DEPTH == 32 @@ -50,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: @@ -102,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 @@ -114,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; } @@ -123,19 +129,31 @@ 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); - 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_; } + // 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); + } + } + + /** + * Initialize the LVGL library and register custom events. + */ + static void esphome_lvgl_init(); + static void add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event); + static void add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1, lv_event_code_t event2); + static void add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1, lv_event_code_t event2, + lv_event_code_t event3); void add_page(LvPageType *page); void show_page(size_t index, lv_scr_load_anim_t anim, uint32_t time); void show_next_page(lv_scr_load_anim_t anim, uint32_t time); @@ -148,12 +166,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_{}; @@ -161,14 +188,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<> { @@ -180,6 +205,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)) {} @@ -202,9 +235,12 @@ template class LvglCondition : public Condition, public P #ifdef USE_LVGL_TOUCHSCREEN class LVTouchListener : public touchscreen::TouchListener, public Parented { public: - LVTouchListener(uint16_t long_press_time, uint16_t long_press_repeat_time); + LVTouchListener(uint16_t long_press_time, uint16_t long_press_repeat_time, LvglComponent *parent); void update(const touchscreen::TouchPoints_t &tpoints) override; - void release() override { touch_pressed_ = false; } + void release() override { + touch_pressed_ = false; + this->parent_->maybe_wakeup(); + } lv_indev_drv_t *get_drv() { return &this->drv_; } protected: @@ -219,16 +255,11 @@ class LVEncoderListener : public Parented { public: LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_t lprt); - void set_left_button(binary_sensor::BinarySensor *left_button) { - left_button->add_on_state_callback([this](bool state) { this->event(LV_KEY_LEFT, state); }); - } - void set_right_button(binary_sensor::BinarySensor *right_button) { - right_button->add_on_state_callback([this](bool state) { this->event(LV_KEY_RIGHT, state); }); - } - - void set_enter_button(binary_sensor::BinarySensor *enter_button) { - enter_button->add_on_state_callback([this](bool state) { this->event(LV_KEY_ENTER, state); }); +#ifdef USE_BINARY_SENSOR + void add_button(binary_sensor::BinarySensor *button, lv_key_t key) { + button->add_on_state_callback([this, key](bool state) { this->event(key, state); }); } +#endif #ifdef USE_LVGL_ROTARY_ENCODER void set_sensor(rotary_encoder::RotaryEncoderSensor *sensor) { @@ -240,12 +271,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_; } @@ -259,6 +296,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/number/__init__.py b/esphome/components/lvgl/number/__init__.py index 07f92635b5..b41a36bc0f 100644 --- a/esphome/components/lvgl/number/__init__.py +++ b/esphome/components/lvgl/number/__init__.py @@ -3,7 +3,7 @@ from esphome.components import number import esphome.config_validation as cv from esphome.cpp_generator import MockObj -from ..defines import CONF_ANIMATED, CONF_LVGL_ID, CONF_UPDATE_ON_RELEASE, CONF_WIDGET +from ..defines import CONF_ANIMATED, CONF_UPDATE_ON_RELEASE, CONF_WIDGET from ..lv_validation import animated from ..lvcode import ( API_EVENT, @@ -13,28 +13,23 @@ from ..lvcode import ( LvContext, lv, lv_add, + lvgl_static, ) -from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvNumber, lvgl_ns from ..widgets import get_widgets, wait_for_widgets LVGLNumber = lvgl_ns.class_("LVGLNumber", number.Number) -CONFIG_SCHEMA = ( - number.number_schema(LVGLNumber) - .extend(LVGL_SCHEMA) - .extend( - { - cv.Required(CONF_WIDGET): cv.use_id(LvNumber), - cv.Optional(CONF_ANIMATED, default=True): animated, - cv.Optional(CONF_UPDATE_ON_RELEASE, default=False): cv.boolean, - } - ) +CONFIG_SCHEMA = number.number_schema(LVGLNumber).extend( + { + cv.Required(CONF_WIDGET): cv.use_id(LvNumber), + cv.Optional(CONF_ANIMATED, default=True): animated, + cv.Optional(CONF_UPDATE_ON_RELEASE, default=False): cv.boolean, + } ) async def to_code(config): - paren = await cg.get_variable(config[CONF_LVGL_ID]) widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] var = await number.new_number( @@ -58,10 +53,10 @@ async def to_code(config): if not config[CONF_UPDATE_ON_RELEASE] else LV_EVENT.RELEASED ) - async with LvContext(paren): + async with LvContext(): lv_add(var.set_control_lambda(await control.get_lambda())) lv_add( - paren.add_event_cb( + lvgl_static.add_event_cb( widget.obj, await event.get_lambda(), UPDATE_EVENT, event_code ) ) diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index 780057623a..516627708e 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -91,7 +91,7 @@ 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, @@ -111,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, @@ -134,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, @@ -150,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, @@ -216,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( @@ -391,7 +391,9 @@ def container_validator(schema, widget_type: WidgetType): add_lv_use(ltype) if value == SCHEMA_EXTRACT: return result - result = result.extend(LAYOUT_SCHEMAS[ltype.lower()]) + result = result.extend( + LAYOUT_SCHEMAS.get(ltype.lower(), LAYOUT_SCHEMAS[df.TYPE_NONE]) + ) return result(value) return validator diff --git a/esphome/components/lvgl/select/__init__.py b/esphome/components/lvgl/select/__init__.py index 73ac50aa55..bd5ef8f237 100644 --- a/esphome/components/lvgl/select/__init__.py +++ b/esphome/components/lvgl/select/__init__.py @@ -1,33 +1,19 @@ -import esphome.codegen as cg from esphome.components import select import esphome.config_validation as cv from esphome.const import CONF_OPTIONS -from ..defines import CONF_ANIMATED, CONF_LVGL_ID, CONF_WIDGET -from ..lvcode import ( - API_EVENT, - EVENT_ARG, - UPDATE_EVENT, - LambdaContext, - LvContext, - lv, - lv_add, -) -from ..schemas import LVGL_SCHEMA -from ..types import LV_EVENT, LvSelect, lvgl_ns +from ..defines import CONF_ANIMATED, CONF_WIDGET, literal +from ..lvcode import LvContext +from ..types import LvSelect, lvgl_ns from ..widgets import get_widgets, wait_for_widgets LVGLSelect = lvgl_ns.class_("LVGLSelect", select.Select) -CONFIG_SCHEMA = ( - select.select_schema(LVGLSelect) - .extend(LVGL_SCHEMA) - .extend( - { - cv.Required(CONF_WIDGET): cv.use_id(LvSelect), - cv.Optional(CONF_ANIMATED, default=False): cv.boolean, - } - ) +CONFIG_SCHEMA = select.select_schema(LVGLSelect).extend( + { + cv.Required(CONF_WIDGET): cv.use_id(LvSelect), + cv.Optional(CONF_ANIMATED, default=False): cv.boolean, + } ) @@ -36,22 +22,11 @@ async def to_code(config): widget = widget[0] options = widget.config.get(CONF_OPTIONS, []) selector = await select.new_select(config, options=options) - paren = await cg.get_variable(config[CONF_LVGL_ID]) 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())) + async with LvContext() as ctx: 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/sensor/__init__.py b/esphome/components/lvgl/sensor/__init__.py index a2a2298c27..03b2638ed0 100644 --- a/esphome/components/lvgl/sensor/__init__.py +++ b/esphome/components/lvgl/sensor/__init__.py @@ -1,8 +1,7 @@ -import esphome.codegen as cg from esphome.components.sensor import Sensor, new_sensor, sensor_schema import esphome.config_validation as cv -from ..defines import CONF_LVGL_ID, CONF_WIDGET +from ..defines import CONF_WIDGET from ..lvcode import ( API_EVENT, EVENT_ARG, @@ -11,34 +10,29 @@ from ..lvcode import ( LambdaContext, LvContext, lv_add, + lvgl_static, ) -from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvNumber from ..widgets import Widget, get_widgets, wait_for_widgets -CONFIG_SCHEMA = ( - sensor_schema(Sensor) - .extend(LVGL_SCHEMA) - .extend( - { - cv.Required(CONF_WIDGET): cv.use_id(LvNumber), - } - ) +CONFIG_SCHEMA = sensor_schema(Sensor).extend( + { + cv.Required(CONF_WIDGET): cv.use_id(LvNumber), + } ) async def to_code(config): sensor = await new_sensor(config) - paren = await cg.get_variable(config[CONF_LVGL_ID]) widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] assert isinstance(widget, Widget) await wait_for_widgets() async with LambdaContext(EVENT_ARG) as lamb: lv_add(sensor.publish_state(widget.get_value())) - async with LvContext(paren, LVGL_COMP_ARG): + async with LvContext(LVGL_COMP_ARG): lv_add( - paren.add_event_cb( + lvgl_static.add_event_cb( widget.obj, await lamb.get_lambda(), LV_EVENT.VALUE_CHANGED, diff --git a/esphome/components/lvgl/styles.py b/esphome/components/lvgl/styles.py index 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/switch/__init__.py b/esphome/components/lvgl/switch/__init__.py index 8c090543f9..4e1e7f72e0 100644 --- a/esphome/components/lvgl/switch/__init__.py +++ b/esphome/components/lvgl/switch/__init__.py @@ -3,7 +3,7 @@ from esphome.components.switch import Switch, new_switch, switch_schema import esphome.config_validation as cv from esphome.cpp_generator import MockObj -from ..defines import CONF_LVGL_ID, CONF_WIDGET, literal +from ..defines import CONF_WIDGET, literal from ..lvcode import ( API_EVENT, EVENT_ARG, @@ -13,26 +13,21 @@ from ..lvcode import ( LvContext, lv, lv_add, + lvgl_static, ) -from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LV_STATE, lv_pseudo_button_t, lvgl_ns from ..widgets import get_widgets, wait_for_widgets LVGLSwitch = lvgl_ns.class_("LVGLSwitch", Switch) -CONFIG_SCHEMA = ( - switch_schema(LVGLSwitch) - .extend(LVGL_SCHEMA) - .extend( - { - cv.Required(CONF_WIDGET): cv.use_id(lv_pseudo_button_t), - } - ) +CONFIG_SCHEMA = switch_schema(LVGLSwitch).extend( + { + cv.Required(CONF_WIDGET): cv.use_id(lv_pseudo_button_t), + } ) async def to_code(config): switch = await new_switch(config) - paren = await cg.get_variable(config[CONF_LVGL_ID]) widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] await wait_for_widgets() @@ -45,10 +40,10 @@ async def to_code(config): widget.clear_state(LV_STATE.CHECKED) lv.event_send(widget.obj, API_EVENT, cg.nullptr) control.add(switch.publish_state(literal("v"))) - async with LvContext(paren) as ctx: + async with LvContext() as ctx: lv_add(switch.set_control_lambda(await control.get_lambda())) ctx.add( - paren.add_event_cb( + lvgl_static.add_event_cb( widget.obj, await checked_ctx.get_lambda(), LV_EVENT.VALUE_CHANGED, diff --git a/esphome/components/lvgl/text/__init__.py b/esphome/components/lvgl/text/__init__.py index 540591d24b..89db139a6a 100644 --- a/esphome/components/lvgl/text/__init__.py +++ b/esphome/components/lvgl/text/__init__.py @@ -3,7 +3,7 @@ from esphome.components import text from esphome.components.text import new_text import esphome.config_validation as cv -from ..defines import CONF_LVGL_ID, CONF_WIDGET +from ..defines import CONF_WIDGET from ..lvcode import ( API_EVENT, EVENT_ARG, @@ -12,14 +12,14 @@ from ..lvcode import ( LvContext, lv, lv_add, + lvgl_static, ) -from ..schemas import LVGL_SCHEMA from ..types import LV_EVENT, LvText, lvgl_ns from ..widgets import get_widgets, wait_for_widgets LVGLText = lvgl_ns.class_("LVGLText", text.Text) -CONFIG_SCHEMA = text.TEXT_SCHEMA.extend(LVGL_SCHEMA).extend( +CONFIG_SCHEMA = text.TEXT_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(LVGLText), cv.Required(CONF_WIDGET): cv.use_id(LvText), @@ -29,20 +29,19 @@ CONFIG_SCHEMA = text.TEXT_SCHEMA.extend(LVGL_SCHEMA).extend( async def to_code(config): textvar = await new_text(config) - paren = await cg.get_variable(config[CONF_LVGL_ID]) widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] 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()) + async with LvContext(): + lv_add(textvar.set_control_lambda(await control.get_lambda())) lv_add( - paren.add_event_cb( + lvgl_static.add_event_cb( widget.obj, await lamb.get_lambda(), LV_EVENT.VALUE_CHANGED, diff --git a/esphome/components/lvgl/text_sensor/__init__.py b/esphome/components/lvgl/text_sensor/__init__.py index ae39eec291..4728fd137a 100644 --- a/esphome/components/lvgl/text_sensor/__init__.py +++ b/esphome/components/lvgl/text_sensor/__init__.py @@ -1,4 +1,3 @@ -import esphome.codegen as cg from esphome.components.text_sensor import ( TextSensor, new_text_sensor, @@ -6,34 +5,35 @@ from esphome.components.text_sensor import ( ) import esphome.config_validation as cv -from ..defines import CONF_LVGL_ID, CONF_WIDGET -from ..lvcode import API_EVENT, EVENT_ARG, UPDATE_EVENT, LambdaContext, LvContext -from ..schemas import LVGL_SCHEMA +from ..defines import CONF_WIDGET +from ..lvcode import ( + API_EVENT, + EVENT_ARG, + UPDATE_EVENT, + LambdaContext, + LvContext, + lvgl_static, +) from ..types import LV_EVENT, LvText from ..widgets import get_widgets, wait_for_widgets -CONFIG_SCHEMA = ( - text_sensor_schema(TextSensor) - .extend(LVGL_SCHEMA) - .extend( - { - cv.Required(CONF_WIDGET): cv.use_id(LvText), - } - ) +CONFIG_SCHEMA = text_sensor_schema(TextSensor).extend( + { + cv.Required(CONF_WIDGET): cv.use_id(LvText), + } ) async def to_code(config): sensor = await new_text_sensor(config) - paren = await cg.get_variable(config[CONF_LVGL_ID]) widget = await get_widgets(config, CONF_WIDGET) widget = widget[0] await wait_for_widgets() async with LambdaContext(EVENT_ARG) as pressed_ctx: pressed_ctx.add(sensor.publish_state(widget.get_value())) - async with LvContext(paren) as ctx: + async with LvContext() as ctx: ctx.add( - paren.add_event_cb( + lvgl_static.add_event_cb( widget.obj, await pressed_ctx.get_lambda(), LV_EVENT.VALUE_CHANGED, diff --git a/esphome/components/lvgl/touchscreens.py b/esphome/components/lvgl/touchscreens.py index 4d430a428e..f2dd013f6d 100644 --- a/esphome/components/lvgl/touchscreens.py +++ b/esphome/components/lvgl/touchscreens.py @@ -33,13 +33,12 @@ def touchscreen_schema(config): return [TOUCHSCREENS_CONFIG(config)] -async def touchscreens_to_code(var, config): +async def touchscreens_to_code(lv_component, config): for tconf in config[CONF_TOUCHSCREENS]: lvgl_components_required.add(CONF_TOUCHSCREEN) touchscreen = await cg.get_variable(tconf[CONF_TOUCHSCREEN_ID]) lpt = tconf[CONF_LONG_PRESS_TIME].total_milliseconds lprt = tconf[CONF_LONG_PRESS_REPEAT_TIME].total_milliseconds - listener = cg.new_Pvariable(tconf[CONF_ID], lpt, lprt) - await cg.register_parented(listener, var) + listener = cg.new_Pvariable(tconf[CONF_ID], lpt, lprt, lv_component) lv.indev_drv_register(listener.get_drv()) cg.add(touchscreen.register_listener(listener)) diff --git a/esphome/components/lvgl/trigger.py b/esphome/components/lvgl/trigger.py index 5288745fab..fb856df04e 100644 --- a/esphome/components/lvgl/trigger.py +++ b/esphome/components/lvgl/trigger.py @@ -20,17 +20,16 @@ from .lvcode import ( lv, lv_add, lv_event_t_ptr, + lvgl_static, ) from .types import LV_EVENT from .widgets import widget_map -async def generate_triggers(lv_component): +async def generate_triggers(): """ Generate LVGL triggers for all defined widgets Must be done after all widgets completed - :param lv_component: The parent component - :return: """ for w in widget_map.values(): @@ -43,11 +42,10 @@ async def generate_triggers(lv_component): conf = conf[0] w.add_flag("LV_OBJ_FLAG_CLICKABLE") event = literal("LV_EVENT_" + LV_EVENT_MAP[event[3:].upper()]) - await add_trigger(conf, lv_component, w, event) + await add_trigger(conf, w, event) for conf in w.config.get(CONF_ON_VALUE, ()): await add_trigger( conf, - lv_component, w, LV_EVENT.VALUE_CHANGED, API_EVENT, @@ -63,13 +61,13 @@ async def generate_triggers(lv_component): lv.obj_align_to(w.obj, target, align, x, y) -async def add_trigger(conf, lv_component, w, *events): +async def add_trigger(conf, 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(lv_component.add_event_cb(w.obj, await context.get_lambda(), *events)) + lv_add(trigger.trigger(*value, literal("event"))) + lv_add(lvgl_static.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 b452ab5fb3..40e69119f0 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): @@ -38,8 +40,10 @@ void_ptr = cg.void.operator("ptr") lv_coord_t = cg.global_ns.namespace("lv_coord_t") lv_event_code_t = cg.global_ns.enum("lv_event_code_t") lv_indev_type_t = cg.global_ns.enum("lv_indev_type_t") +lv_key_t = cg.global_ns.enum("lv_key_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) @@ -91,11 +95,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 e093cebd16..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 @@ -158,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): @@ -177,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: @@ -211,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. @@ -441,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..8adea72ad3 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 @@ -61,9 +60,10 @@ class AnimimgType(WidgetType): lvgl_components_required.add(CONF_IMAGE) lvgl_components_required.add(CONF_ANIMIMG) if CONF_SRC in config: - for x in config[CONF_SRC]: - await cg.get_variable(x) - srcs = [lv_expr.img_from(MockObj(x)) for x in config[CONF_SRC]] + srcs = [ + await lv_image.process(await cg.get_variable(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 +73,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/img.py b/esphome/components/lvgl/widgets/img.py index 59b2c97c63..931d0c0b5b 100644 --- a/esphome/components/lvgl/widgets/img.py +++ b/esphome/components/lvgl/widgets/img.py @@ -1,3 +1,4 @@ +import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_ANGLE, CONF_MODE @@ -64,6 +65,7 @@ class ImgType(WidgetType): async def to_code(self, w: Widget, config): if src := config.get(CONF_SRC): + src = await cg.get_variable(src) lv.img_set_src(w.obj, await lv_image.process(src)) if (cf_angle := config.get(CONF_ANGLE)) is not None: pivot_x = config[CONF_PIVOT_X] diff --git a/esphome/components/lvgl/widgets/meter.py b/esphome/components/lvgl/widgets/meter.py index 36f6643022..cd61d1c775 100644 --- a/esphome/components/lvgl/widgets/meter.py +++ b/esphome/components/lvgl/widgets/meter.py @@ -20,6 +20,7 @@ from ..defines import ( CONF_END_VALUE, CONF_INDICATOR, CONF_MAIN, + CONF_OPA, CONF_PIVOT_X, CONF_PIVOT_Y, CONF_SRC, @@ -35,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 @@ -76,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( @@ -84,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( @@ -94,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( @@ -218,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 @@ -268,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() @@ -285,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) @@ -307,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 1af4ed6e05..be0f2100d7 100644 --- a/esphome/components/lvgl/widgets/msgbox.py +++ b/esphome/components/lvgl/widgets/msgbox.py @@ -20,6 +20,7 @@ from ..lvcode import ( EVENT_ARG, LambdaContext, LocalVariable, + lv, lv_add, lv_assign, lv_expr, @@ -27,7 +28,6 @@ from ..lvcode import ( lv_Pvariable, ) from ..schemas import STYLE_SCHEMA, STYLED_TEXT_SCHEMA, container_schema, part_schema -from ..styles import TOP_LAYER from ..types import LV_EVENT, char_ptr, lv_obj_t from . import Widget, set_obj_properties from .button import button_spec @@ -59,7 +59,7 @@ MSGBOX_SCHEMA = container_schema( ) -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 @@ -101,7 +101,7 @@ async def msgbox_to_code(conf): 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) @@ -141,6 +141,7 @@ async def msgbox_to_code(conf): 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/page.py b/esphome/components/lvgl/widgets/page.py index 0e84ab6791..a754a9cb9a 100644 --- a/esphome/components/lvgl/widgets/page.py +++ b/esphome/components/lvgl/widgets/page.py @@ -20,6 +20,7 @@ from ..lvcode import ( add_line_marks, lv_add, lvgl_comp, + lvgl_static, ) from ..schemas import LVGL_SCHEMA from ..types import LvglAction, lv_page_t @@ -139,7 +140,7 @@ async def add_pages(lv_component, config): await add_widgets(page, pconf) -async def generate_page_triggers(lv_component, config): +async def generate_page_triggers(config): for pconf in config.get(CONF_PAGES, ()): page = (await get_widgets(pconf))[0] for ev in (CONF_ON_LOAD, CONF_ON_UNLOAD): @@ -149,7 +150,7 @@ async def generate_page_triggers(lv_component, config): async with LambdaContext(EVENT_ARG, where=id) as context: lv_add(trigger.trigger()) lv_add( - lv_component.add_event_cb( + lvgl_static.add_event_cb( page.obj, await context.get_lambda(), literal(f"LV_EVENT_SCREEN_{ev[3:].upper()}_START"), 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/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/midea/air_conditioner.cpp b/esphome/components/midea/air_conditioner.cpp index b5bf43b64f..a823680d03 100644 --- a/esphome/components/midea/air_conditioner.cpp +++ b/esphome/components/midea/air_conditioner.cpp @@ -3,6 +3,8 @@ #include "esphome/core/log.h" #include "air_conditioner.h" #include "ac_adapter.h" +#include +#include namespace esphome { namespace midea { @@ -121,7 +123,21 @@ void AirConditioner::dump_config() { void AirConditioner::do_follow_me(float temperature, bool beeper) { #ifdef USE_REMOTE_TRANSMITTER - IrFollowMeData data(static_cast(lroundf(temperature)), beeper); + // Check if temperature is finite (not NaN or infinite) + if (!std::isfinite(temperature)) { + ESP_LOGW(Constants::TAG, "Follow me action requires a finite temperature, got: %f", temperature); + return; + } + + // Round and convert temperature to long, then clamp and convert it to uint8_t + uint8_t temp_uint8 = + static_cast(std::max(0L, std::min(static_cast(UINT8_MAX), std::lroundf(temperature)))); + + ESP_LOGD(Constants::TAG, "Follow me action called with temperature: %f °C, rounded to: %u °C", temperature, + temp_uint8); + + // Create and transmit the data + IrFollowMeData data(temp_uint8, beeper); this->transmitter_.transmit(data); #else ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component"); 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 6917807b07..488baa245a 100644 --- a/esphome/components/modbus_controller/__init__.py +++ b/esphome/components/modbus_controller/__init__.py @@ -1,27 +1,29 @@ import binascii -import esphome.codegen as cg -import esphome.config_validation as cv + from esphome import automation +import esphome.codegen as cg from esphome.components import modbus +import esphome.config_validation as cv from esphome.const import ( CONF_ADDRESS, CONF_ID, - CONF_NAME, CONF_LAMBDA, + CONF_NAME, CONF_OFFSET, CONF_TRIGGER_ID, ) from esphome.cpp_helpers import logging + from .const import ( CONF_ALLOW_DUPLICATE_COMMANDS, CONF_BITMASK, CONF_BYTE_OFFSET, CONF_COMMAND_THROTTLE, - CONF_OFFLINE_SKIP_UPDATES, CONF_CUSTOM_COMMAND, CONF_FORCE_NEW_RANGE, - CONF_MODBUS_CONTROLLER_ID, CONF_MAX_CMD_RETRIES, + CONF_MODBUS_CONTROLLER_ID, + CONF_OFFLINE_SKIP_UPDATES, CONF_ON_COMMAND_SENT, CONF_REGISTER_COUNT, CONF_REGISTER_TYPE, diff --git a/esphome/components/modbus_controller/binary_sensor/__init__.py b/esphome/components/modbus_controller/binary_sensor/__init__.py index 5315167479..2ae008f630 100644 --- a/esphome/components/modbus_controller/binary_sensor/__init__.py +++ b/esphome/components/modbus_controller/binary_sensor/__init__.py @@ -1,16 +1,16 @@ +import esphome.codegen as cg from esphome.components import binary_sensor import esphome.config_validation as cv -import esphome.codegen as cg - from esphome.const import CONF_ADDRESS, CONF_ID + from .. import ( - add_modbus_base_properties, - modbus_controller_ns, - modbus_calc_properties, - validate_modbus_register, + MODBUS_REGISTER_TYPE, ModbusItemBaseSchema, SensorItem, - MODBUS_REGISTER_TYPE, + add_modbus_base_properties, + modbus_calc_properties, + modbus_controller_ns, + validate_modbus_register, ) from ..const import ( CONF_BITMASK, diff --git a/esphome/components/modbus_controller/number/__init__.py b/esphome/components/modbus_controller/number/__init__.py index fe99b28a00..b5efd7abf0 100644 --- a/esphome/components/modbus_controller/number/__init__.py +++ b/esphome/components/modbus_controller/number/__init__.py @@ -1,6 +1,6 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import number +import esphome.config_validation as cv from esphome.const import ( CONF_ADDRESS, CONF_ID, @@ -12,14 +12,13 @@ from esphome.const import ( from .. import ( MODBUS_WRITE_REGISTER_TYPE, - add_modbus_base_properties, - modbus_controller_ns, - modbus_calc_properties, + SENSOR_VALUE_TYPE, ModbusItemBaseSchema, SensorItem, - SENSOR_VALUE_TYPE, + add_modbus_base_properties, + modbus_calc_properties, + modbus_controller_ns, ) - from ..const import ( CONF_BITMASK, CONF_CUSTOM_COMMAND, diff --git a/esphome/components/modbus_controller/output/__init__.py b/esphome/components/modbus_controller/output/__init__.py index 1bf989ce8b..1800a90d57 100644 --- a/esphome/components/modbus_controller/output/__init__.py +++ b/esphome/components/modbus_controller/output/__init__.py @@ -1,20 +1,15 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import output -from esphome.const import ( - CONF_ADDRESS, - CONF_ID, - CONF_MULTIPLY, -) +import esphome.config_validation as cv +from esphome.const import CONF_ADDRESS, CONF_ID, CONF_MULTIPLY from .. import ( - modbus_controller_ns, - modbus_calc_properties, + SENSOR_VALUE_TYPE, ModbusItemBaseSchema, SensorItem, - SENSOR_VALUE_TYPE, + modbus_calc_properties, + modbus_controller_ns, ) - from ..const import ( CONF_MODBUS_CONTROLLER_ID, CONF_REGISTER_TYPE, @@ -65,6 +60,7 @@ CONFIG_SCHEMA = cv.typed_schema( async def to_code(config): byte_offset, reg_count = modbus_calc_properties(config) # Binary Output + write_template = None if config[CONF_REGISTER_TYPE] == "coil": var = cg.new_Pvariable( config[CONF_ID], @@ -72,7 +68,7 @@ async def to_code(config): byte_offset, ) if CONF_WRITE_LAMBDA in config: - template_ = await cg.process_lambda( + write_template = await cg.process_lambda( config[CONF_WRITE_LAMBDA], [ (ModbusBinaryOutput.operator("ptr"), "item"), @@ -92,7 +88,7 @@ async def to_code(config): ) cg.add(var.set_write_multiply(config[CONF_MULTIPLY])) if CONF_WRITE_LAMBDA in config: - template_ = await cg.process_lambda( + write_template = await cg.process_lambda( config[CONF_WRITE_LAMBDA], [ (ModbusFloatOutput.operator("ptr"), "item"), @@ -105,5 +101,5 @@ async def to_code(config): parent = await cg.get_variable(config[CONF_MODBUS_CONTROLLER_ID]) cg.add(var.set_use_write_mutiple(config[CONF_USE_WRITE_MULTIPLE])) cg.add(var.set_parent(parent)) - if CONF_WRITE_LAMBDA in config: - cg.add(var.set_write_template(template_)) + if write_template: + cg.add(var.set_write_template(write_template)) diff --git a/esphome/components/modbus_controller/select/__init__.py b/esphome/components/modbus_controller/select/__init__.py index 5692fea3e3..c94532da51 100644 --- a/esphome/components/modbus_controller/select/__init__.py +++ b/esphome/components/modbus_controller/select/__init__.py @@ -1,6 +1,6 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import select +import esphome.config_validation as cv from esphome.const import CONF_ADDRESS, CONF_ID, CONF_LAMBDA, CONF_OPTIMISTIC from .. import ( diff --git a/esphome/components/modbus_controller/sensor/__init__.py b/esphome/components/modbus_controller/sensor/__init__.py index 0e4588cfef..d8fce54ece 100644 --- a/esphome/components/modbus_controller/sensor/__init__.py +++ b/esphome/components/modbus_controller/sensor/__init__.py @@ -1,17 +1,17 @@ +import esphome.codegen as cg from esphome.components import sensor import esphome.config_validation as cv -import esphome.codegen as cg +from esphome.const import CONF_ADDRESS, CONF_ID -from esphome.const import CONF_ID, CONF_ADDRESS from .. import ( - add_modbus_base_properties, - modbus_controller_ns, - modbus_calc_properties, - validate_modbus_register, - ModbusItemBaseSchema, - SensorItem, MODBUS_REGISTER_TYPE, SENSOR_VALUE_TYPE, + ModbusItemBaseSchema, + SensorItem, + add_modbus_base_properties, + modbus_calc_properties, + modbus_controller_ns, + validate_modbus_register, ) from ..const import ( CONF_BITMASK, diff --git a/esphome/components/modbus_controller/switch/__init__.py b/esphome/components/modbus_controller/switch/__init__.py index 9490325968..258d87fd25 100644 --- a/esphome/components/modbus_controller/switch/__init__.py +++ b/esphome/components/modbus_controller/switch/__init__.py @@ -1,17 +1,16 @@ +import esphome.codegen as cg from esphome.components import switch import esphome.config_validation as cv -import esphome.codegen as cg +from esphome.const import CONF_ADDRESS, CONF_ID - -from esphome.const import CONF_ID, CONF_ADDRESS from .. import ( - add_modbus_base_properties, - modbus_controller_ns, - modbus_calc_properties, - validate_modbus_register, + MODBUS_REGISTER_TYPE, ModbusItemBaseSchema, SensorItem, - MODBUS_REGISTER_TYPE, + add_modbus_base_properties, + modbus_calc_properties, + modbus_controller_ns, + validate_modbus_register, ) from ..const import ( CONF_BITMASK, diff --git a/esphome/components/modbus_controller/text_sensor/__init__.py b/esphome/components/modbus_controller/text_sensor/__init__.py index 81d6453c6f..35cae645e1 100644 --- a/esphome/components/modbus_controller/text_sensor/__init__.py +++ b/esphome/components/modbus_controller/text_sensor/__init__.py @@ -1,26 +1,25 @@ +import esphome.codegen as cg from esphome.components import text_sensor import esphome.config_validation as cv -import esphome.codegen as cg - - from esphome.const import CONF_ADDRESS, CONF_ID + from .. import ( - add_modbus_base_properties, - modbus_controller_ns, - modbus_calc_properties, - validate_modbus_register, + MODBUS_REGISTER_TYPE, ModbusItemBaseSchema, SensorItem, - MODBUS_REGISTER_TYPE, + add_modbus_base_properties, + modbus_calc_properties, + modbus_controller_ns, + validate_modbus_register, ) from ..const import ( CONF_FORCE_NEW_RANGE, CONF_MODBUS_CONTROLLER_ID, + CONF_RAW_ENCODE, CONF_REGISTER_COUNT, + CONF_REGISTER_TYPE, CONF_RESPONSE_SIZE, CONF_SKIP_UPDATES, - CONF_RAW_ENCODE, - CONF_REGISTER_TYPE, ) DEPENDENCIES = ["modbus_controller"] 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..86d163e61d 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, @@ -21,6 +22,7 @@ from esphome.const import ( CONF_DISCOVERY_PREFIX, CONF_DISCOVERY_RETAIN, CONF_DISCOVERY_UNIQUE_ID_GENERATOR, + CONF_ENABLE_ON_BOOT, CONF_ID, CONF_KEEPALIVE, CONF_LEVEL, @@ -40,6 +42,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, @@ -97,6 +100,8 @@ MQTTMessage = mqtt_ns.struct("MQTTMessage") MQTTClientComponent = mqtt_ns.class_("MQTTClientComponent", cg.Component) MQTTPublishAction = mqtt_ns.class_("MQTTPublishAction", automation.Action) MQTTPublishJsonAction = mqtt_ns.class_("MQTTPublishJsonAction", automation.Action) +MQTTEnableAction = mqtt_ns.class_("MQTTEnableAction", automation.Action) +MQTTDisableAction = mqtt_ns.class_("MQTTDisableAction", automation.Action) MQTTMessageTrigger = mqtt_ns.class_( "MQTTMessageTrigger", automation.Trigger.template(cg.std_string), cg.Component ) @@ -206,9 +211,11 @@ CONFIG_SCHEMA = cv.All( { cv.GenerateID(): cv.declare_id(MQTTClientComponent), cv.Required(CONF_BROKER): cv.string_strict, + cv.Optional(CONF_ENABLE_ON_BOOT, default=True): cv.boolean, 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 @@ -322,9 +329,11 @@ async def to_code(config): cg.add_global(mqtt_ns.using) cg.add(var.set_broker_address(config[CONF_BROKER])) + cg.add(var.set_enable_on_boot(config[CONF_ENABLE_ON_BOOT])) 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 +524,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: @@ -549,3 +560,31 @@ async def register_mqtt_component(var, config): async def mqtt_connected_to_code(config, condition_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(condition_id, template_arg, paren) + + +@automation.register_action( + "mqtt.enable", + MQTTEnableAction, + cv.Schema( + { + cv.GenerateID(): cv.use_id(MQTTClientComponent), + } + ), +) +async def mqtt_enable_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( + "mqtt.disable", + MQTTDisableAction, + cv.Schema( + { + cv.GenerateID(): cv.use_id(MQTTClientComponent), + } + ), +) +async def mqtt_disable_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/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index c19b24c0cf..106192c0e3 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -50,6 +50,8 @@ void MQTTClientComponent::setup() { } }); this->mqtt_backend_.set_on_disconnect([this](MQTTClientDisconnectReason reason) { + if (this->state_ == MQTT_CLIENT_DISABLED) + return; this->state_ = MQTT_CLIENT_DISCONNECTED; this->disconnect_reason_ = reason; }); @@ -77,8 +79,9 @@ void MQTTClientComponent::setup() { topic, [this](const std::string &topic, const std::string &payload) { this->send_device_info_(); }, 2); } - this->last_connected_ = millis(); - this->start_dnslookup_(); + if (this->enable_on_boot_) { + this->enable(); + } } void MQTTClientComponent::send_device_info_() { @@ -147,6 +150,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"); } @@ -162,7 +166,9 @@ void MQTTClientComponent::dump_config() { ESP_LOGCONFIG(TAG, " Availability: '%s'", this->availability_.topic.c_str()); } } -bool MQTTClientComponent::can_proceed() { return network::is_disabled() || this->is_connected(); } +bool MQTTClientComponent::can_proceed() { + return network::is_disabled() || this->state_ == MQTT_CLIENT_DISABLED || this->is_connected(); +} void MQTTClientComponent::start_dnslookup_() { for (auto &subscription : this->subscriptions_) { @@ -246,6 +252,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(); @@ -337,6 +344,8 @@ void MQTTClientComponent::loop() { const uint32_t now = millis(); switch (this->state_) { + case MQTT_CLIENT_DISABLED: + return; // Return to avoid a reboot when disabled case MQTT_CLIENT_DISCONNECTED: if (now - this->connect_begin_ > 5000) { this->start_dnslookup_(); @@ -499,6 +508,23 @@ bool MQTTClientComponent::publish_json(const std::string &topic, const json::jso return this->publish(topic, message, qos, retain); } +void MQTTClientComponent::enable() { + if (this->state_ != MQTT_CLIENT_DISABLED) + return; + ESP_LOGD(TAG, "Enabling MQTT..."); + this->state_ = MQTT_CLIENT_DISCONNECTED; + this->last_connected_ = millis(); + this->start_dnslookup_(); +} + +void MQTTClientComponent::disable() { + if (this->state_ == MQTT_CLIENT_DISABLED) + return; + ESP_LOGD(TAG, "Disabling MQTT..."); + this->state_ = MQTT_CLIENT_DISABLED; + this->on_shutdown(); +} + /** Check if the message topic matches the given subscription topic * * INFO: MQTT spec mandates that topics must not be empty and must be valid NULL-terminated UTF-8 strings. diff --git a/esphome/components/mqtt/mqtt_client.h b/esphome/components/mqtt/mqtt_client.h index b0d3bbe66d..7ae3a6c5e8 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. @@ -86,7 +87,8 @@ struct MQTTDiscoveryInfo { }; enum MQTTClientState { - MQTT_CLIENT_DISCONNECTED = 0, + MQTT_CLIENT_DISABLED = 0, + MQTT_CLIENT_DISCONNECTED, MQTT_CLIENT_RESOLVING_ADDRESS, MQTT_CLIENT_CONNECTING, MQTT_CLIENT_CONNECTED, @@ -246,6 +248,9 @@ class MQTTClientComponent : public Component { void register_mqtt_component(MQTTComponent *component); bool is_connected(); + void set_enable_on_boot(bool enable_on_boot) { this->enable_on_boot_ = enable_on_boot; } + void enable(); + void disable(); void on_shutdown() override; @@ -254,6 +259,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); @@ -312,10 +318,11 @@ class MQTTClientComponent : public Component { MQTTBackendLibreTiny mqtt_backend_; #endif - MQTTClientState state_{MQTT_CLIENT_DISCONNECTED}; + MQTTClientState state_{MQTT_CLIENT_DISABLED}; network::IPAddress ip_; bool dns_resolved_{false}; bool dns_resolve_error_{false}; + bool enable_on_boot_{true}; std::vector children_; uint32_t reboot_timeout_{300000}; uint32_t connect_begin_; @@ -412,6 +419,26 @@ template class MQTTConnectedCondition : public Condition MQTTClientComponent *parent_; }; +template class MQTTEnableAction : public Action { + public: + MQTTEnableAction(MQTTClientComponent *parent) : parent_(parent) {} + + void play(Ts... x) override { this->parent_->enable(); } + + protected: + MQTTClientComponent *parent_; +}; + +template class MQTTDisableAction : public Action { + public: + MQTTDisableAction(MQTTClientComponent *parent) : parent_(parent) {} + + void play(Ts... x) override { this->parent_->disable(); } + + protected: + MQTTClientComponent *parent_; +}; + } // namespace mqtt } // namespace esphome diff --git a/esphome/components/mqtt/mqtt_climate.cpp b/esphome/components/mqtt/mqtt_climate.cpp index 49a8f06734..773d863835 100644 --- a/esphome/components/mqtt/mqtt_climate.cpp +++ b/esphome/components/mqtt/mqtt_climate.cpp @@ -71,8 +71,10 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo root[MQTT_MIN_TEMP] = traits.get_visual_min_temperature(); // max_temp root[MQTT_MAX_TEMP] = traits.get_visual_max_temperature(); - // temp_step - root["temp_step"] = traits.get_visual_target_temperature_step(); + // target_temp_step + root[MQTT_TARGET_TEMPERATURE_STEP] = traits.get_visual_target_temperature_step(); + // current_temp_step + root[MQTT_CURRENT_TEMPERATURE_STEP] = traits.get_visual_current_temperature_step(); // temperature units are always coerced to Celsius internally root[MQTT_TEMPERATURE_UNIT] = "C"; 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..445457a27f 100644 --- a/esphome/components/mqtt/mqtt_const.h +++ b/esphome/components/mqtt/mqtt_const.h @@ -51,6 +51,7 @@ constexpr const char *const MQTT_COMMAND_TOPIC = "cmd_t"; constexpr const char *const MQTT_CONFIGURATION_URL = "cu"; constexpr const char *const MQTT_CURRENT_HUMIDITY_TEMPLATE = "curr_hum_tpl"; constexpr const char *const MQTT_CURRENT_HUMIDITY_TOPIC = "curr_hum_t"; +constexpr const char *const MQTT_CURRENT_TEMPERATURE_STEP = "precision"; constexpr const char *const MQTT_CURRENT_TEMPERATURE_TEMPLATE = "curr_temp_tpl"; constexpr const char *const MQTT_CURRENT_TEMPERATURE_TOPIC = "curr_temp_t"; constexpr const char *const MQTT_DEVICE = "dev"; @@ -180,6 +181,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"; @@ -231,6 +233,7 @@ constexpr const char *const MQTT_TARGET_HUMIDITY_COMMAND_TEMPLATE = "hum_cmd_tpl constexpr const char *const MQTT_TARGET_HUMIDITY_COMMAND_TOPIC = "hum_cmd_t"; constexpr const char *const MQTT_TARGET_HUMIDITY_STATE_TEMPLATE = "hum_state_tpl"; constexpr const char *const MQTT_TARGET_HUMIDITY_STATE_TOPIC = "hum_stat_t"; +constexpr const char *const MQTT_TARGET_TEMPERATURE_STEP = "temp_step"; constexpr const char *const MQTT_TEMPERATURE_COMMAND_TEMPLATE = "temp_cmd_tpl"; constexpr const char *const MQTT_TEMPERATURE_COMMAND_TOPIC = "temp_cmd_t"; constexpr const char *const MQTT_TEMPERATURE_HIGH_COMMAND_TEMPLATE = "temp_hi_cmd_tpl"; @@ -312,6 +315,7 @@ constexpr const char *const MQTT_COMMAND_TOPIC = "command_topic"; constexpr const char *const MQTT_CONFIGURATION_URL = "configuration_url"; constexpr const char *const MQTT_CURRENT_HUMIDITY_TEMPLATE = "current_humidity_template"; constexpr const char *const MQTT_CURRENT_HUMIDITY_TOPIC = "current_humidity_topic"; +constexpr const char *const MQTT_CURRENT_TEMPERATURE_STEP = "precision"; constexpr const char *const MQTT_CURRENT_TEMPERATURE_TEMPLATE = "current_temperature_template"; constexpr const char *const MQTT_CURRENT_TEMPERATURE_TOPIC = "current_temperature_topic"; constexpr const char *const MQTT_DEVICE = "device"; @@ -441,6 +445,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"; @@ -492,6 +497,7 @@ constexpr const char *const MQTT_TARGET_HUMIDITY_COMMAND_TEMPLATE = "target_humi constexpr const char *const MQTT_TARGET_HUMIDITY_COMMAND_TOPIC = "target_humidity_command_topic"; constexpr const char *const MQTT_TARGET_HUMIDITY_STATE_TEMPLATE = "target_humidity_state_template"; constexpr const char *const MQTT_TARGET_HUMIDITY_STATE_TOPIC = "target_humidity_state_topic"; +constexpr const char *const MQTT_TARGET_TEMPERATURE_STEP = "temp_step"; constexpr const char *const MQTT_TEMPERATURE_COMMAND_TEMPLATE = "temperature_command_template"; constexpr const char *const MQTT_TEMPERATURE_COMMAND_TOPIC = "temperature_command_topic"; constexpr const char *const MQTT_TEMPERATURE_HIGH_COMMAND_TEMPLATE = "temperature_high_command_template"; 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/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/pcd8544/display.py b/esphome/components/pcd8544/display.py index d7e72d1c81..2c24b133da 100644 --- a/esphome/components/pcd8544/display.py +++ b/esphome/components/pcd8544/display.py @@ -1,15 +1,15 @@ -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, spi +import esphome.config_validation as cv from esphome.const import ( + CONF_CONTRAST, + CONF_CS_PIN, CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES, CONF_RESET_PIN, - CONF_CS_PIN, - CONF_CONTRAST, ) DEPENDENCIES = ["spi"] @@ -35,6 +35,10 @@ CONFIG_SCHEMA = cv.All( cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), ) +FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( + "pcd8544", require_miso=False, require_mosi=True +) + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) diff --git a/esphome/components/prometheus/prometheus_handler.cpp b/esphome/components/prometheus/prometheus_handler.cpp index 3e9cf81e6e..5d1861202a 100644 --- a/esphome/components/prometheus/prometheus_handler.cpp +++ b/esphome/components/prometheus/prometheus_handler.cpp @@ -7,47 +7,56 @@ namespace prometheus { void PrometheusHandler::handleRequest(AsyncWebServerRequest *req) { AsyncResponseStream *stream = req->beginResponseStream("text/plain; version=0.0.4; charset=utf-8"); + std::string area = App.get_area(); + std::string node = App.get_name(); + std::string friendly_name = App.get_friendly_name(); #ifdef USE_SENSOR this->sensor_type_(stream); for (auto *obj : App.get_sensors()) - this->sensor_row_(stream, obj); + this->sensor_row_(stream, obj, area, node, friendly_name); #endif #ifdef USE_BINARY_SENSOR this->binary_sensor_type_(stream); for (auto *obj : App.get_binary_sensors()) - this->binary_sensor_row_(stream, obj); + this->binary_sensor_row_(stream, obj, area, node, friendly_name); #endif #ifdef USE_FAN this->fan_type_(stream); for (auto *obj : App.get_fans()) - this->fan_row_(stream, obj); + this->fan_row_(stream, obj, area, node, friendly_name); #endif #ifdef USE_LIGHT this->light_type_(stream); for (auto *obj : App.get_lights()) - this->light_row_(stream, obj); + this->light_row_(stream, obj, area, node, friendly_name); #endif #ifdef USE_COVER this->cover_type_(stream); for (auto *obj : App.get_covers()) - this->cover_row_(stream, obj); + this->cover_row_(stream, obj, area, node, friendly_name); #endif #ifdef USE_SWITCH this->switch_type_(stream); for (auto *obj : App.get_switches()) - this->switch_row_(stream, obj); + this->switch_row_(stream, obj, area, node, friendly_name); #endif #ifdef USE_LOCK this->lock_type_(stream); for (auto *obj : App.get_locks()) - this->lock_row_(stream, obj); + this->lock_row_(stream, obj, area, node, friendly_name); +#endif + +#ifdef USE_TEXT_SENSOR + this->text_sensor_type_(stream); + for (auto *obj : App.get_text_sensors()) + this->text_sensor_row_(stream, obj, area, node, friendly_name); #endif req->send(stream); @@ -63,25 +72,53 @@ std::string PrometheusHandler::relabel_name_(EntityBase *obj) { return item == relabel_map_name_.end() ? obj->get_name() : item->second; } +void PrometheusHandler::add_area_label_(AsyncResponseStream *stream, std::string &area) { + if (!area.empty()) { + stream->print(F("\",area=\"")); + stream->print(area.c_str()); + } +} + +void PrometheusHandler::add_node_label_(AsyncResponseStream *stream, std::string &node) { + if (!node.empty()) { + stream->print(F("\",node=\"")); + stream->print(node.c_str()); + } +} + +void PrometheusHandler::add_friendly_name_label_(AsyncResponseStream *stream, std::string &friendly_name) { + if (!friendly_name.empty()) { + stream->print(F("\",friendly_name=\"")); + stream->print(friendly_name.c_str()); + } +} + // Type-specific implementation #ifdef USE_SENSOR void PrometheusHandler::sensor_type_(AsyncResponseStream *stream) { stream->print(F("#TYPE esphome_sensor_value gauge\n")); stream->print(F("#TYPE esphome_sensor_failed gauge\n")); } -void PrometheusHandler::sensor_row_(AsyncResponseStream *stream, sensor::Sensor *obj) { +void PrometheusHandler::sensor_row_(AsyncResponseStream *stream, sensor::Sensor *obj, std::string &area, + std::string &node, std::string &friendly_name) { if (obj->is_internal() && !this->include_internal_) return; if (!std::isnan(obj->state)) { // We have a valid value, output this value stream->print(F("esphome_sensor_failed{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} 0\n")); // Data itself stream->print(F("esphome_sensor_value{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\",unit=\"")); @@ -93,6 +130,9 @@ void PrometheusHandler::sensor_row_(AsyncResponseStream *stream, sensor::Sensor // Invalid state stream->print(F("esphome_sensor_failed{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} 1\n")); @@ -106,19 +146,26 @@ void PrometheusHandler::binary_sensor_type_(AsyncResponseStream *stream) { stream->print(F("#TYPE esphome_binary_sensor_value gauge\n")); stream->print(F("#TYPE esphome_binary_sensor_failed gauge\n")); } -void PrometheusHandler::binary_sensor_row_(AsyncResponseStream *stream, binary_sensor::BinarySensor *obj) { +void PrometheusHandler::binary_sensor_row_(AsyncResponseStream *stream, binary_sensor::BinarySensor *obj, + std::string &area, std::string &node, std::string &friendly_name) { if (obj->is_internal() && !this->include_internal_) return; if (obj->has_state()) { // We have a valid value, output this value stream->print(F("esphome_binary_sensor_failed{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} 0\n")); // Data itself stream->print(F("esphome_binary_sensor_value{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); @@ -128,6 +175,9 @@ void PrometheusHandler::binary_sensor_row_(AsyncResponseStream *stream, binary_s // Invalid state stream->print(F("esphome_binary_sensor_failed{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} 1\n")); @@ -142,17 +192,24 @@ void PrometheusHandler::fan_type_(AsyncResponseStream *stream) { stream->print(F("#TYPE esphome_fan_speed gauge\n")); stream->print(F("#TYPE esphome_fan_oscillation gauge\n")); } -void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj) { +void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj, std::string &area, std::string &node, + std::string &friendly_name) { if (obj->is_internal() && !this->include_internal_) return; stream->print(F("esphome_fan_failed{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} 0\n")); // Data itself stream->print(F("esphome_fan_value{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); @@ -162,6 +219,9 @@ void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj) { if (obj->get_traits().supports_speed()) { stream->print(F("esphome_fan_speed{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); @@ -172,6 +232,9 @@ void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj) { if (obj->get_traits().supports_oscillation()) { stream->print(F("esphome_fan_oscillation{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); @@ -187,12 +250,16 @@ void PrometheusHandler::light_type_(AsyncResponseStream *stream) { stream->print(F("#TYPE esphome_light_color gauge\n")); stream->print(F("#TYPE esphome_light_effect_active gauge\n")); } -void PrometheusHandler::light_row_(AsyncResponseStream *stream, light::LightState *obj) { +void PrometheusHandler::light_row_(AsyncResponseStream *stream, light::LightState *obj, std::string &area, + std::string &node, std::string &friendly_name) { if (obj->is_internal() && !this->include_internal_) return; // State stream->print(F("esphome_light_state{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); @@ -205,6 +272,9 @@ void PrometheusHandler::light_row_(AsyncResponseStream *stream, light::LightStat color.as_rgbw(&r, &g, &b, &w); stream->print(F("esphome_light_color{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\",channel=\"brightness\"} ")); @@ -212,6 +282,9 @@ void PrometheusHandler::light_row_(AsyncResponseStream *stream, light::LightStat stream->print(F("\n")); stream->print(F("esphome_light_color{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\",channel=\"r\"} ")); @@ -219,6 +292,9 @@ void PrometheusHandler::light_row_(AsyncResponseStream *stream, light::LightStat stream->print(F("\n")); stream->print(F("esphome_light_color{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\",channel=\"g\"} ")); @@ -226,6 +302,9 @@ void PrometheusHandler::light_row_(AsyncResponseStream *stream, light::LightStat stream->print(F("\n")); stream->print(F("esphome_light_color{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\",channel=\"b\"} ")); @@ -233,6 +312,9 @@ void PrometheusHandler::light_row_(AsyncResponseStream *stream, light::LightStat stream->print(F("\n")); stream->print(F("esphome_light_color{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\",channel=\"w\"} ")); @@ -243,12 +325,18 @@ void PrometheusHandler::light_row_(AsyncResponseStream *stream, light::LightStat if (effect == "None") { stream->print(F("esphome_light_effect_active{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\",effect=\"None\"} 0\n")); } else { stream->print(F("esphome_light_effect_active{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\",effect=\"")); @@ -263,19 +351,26 @@ void PrometheusHandler::cover_type_(AsyncResponseStream *stream) { stream->print(F("#TYPE esphome_cover_value gauge\n")); stream->print(F("#TYPE esphome_cover_failed gauge\n")); } -void PrometheusHandler::cover_row_(AsyncResponseStream *stream, cover::Cover *obj) { +void PrometheusHandler::cover_row_(AsyncResponseStream *stream, cover::Cover *obj, std::string &area, std::string &node, + std::string &friendly_name) { if (obj->is_internal() && !this->include_internal_) return; if (!std::isnan(obj->position)) { // We have a valid value, output this value stream->print(F("esphome_cover_failed{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} 0\n")); // Data itself stream->print(F("esphome_cover_value{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); @@ -284,6 +379,9 @@ void PrometheusHandler::cover_row_(AsyncResponseStream *stream, cover::Cover *ob if (obj->get_traits().get_supports_tilt()) { stream->print(F("esphome_cover_tilt{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); @@ -294,6 +392,9 @@ void PrometheusHandler::cover_row_(AsyncResponseStream *stream, cover::Cover *ob // Invalid state stream->print(F("esphome_cover_failed{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} 1\n")); @@ -306,17 +407,24 @@ void PrometheusHandler::switch_type_(AsyncResponseStream *stream) { stream->print(F("#TYPE esphome_switch_value gauge\n")); stream->print(F("#TYPE esphome_switch_failed gauge\n")); } -void PrometheusHandler::switch_row_(AsyncResponseStream *stream, switch_::Switch *obj) { +void PrometheusHandler::switch_row_(AsyncResponseStream *stream, switch_::Switch *obj, std::string &area, + std::string &node, std::string &friendly_name) { if (obj->is_internal() && !this->include_internal_) return; stream->print(F("esphome_switch_failed{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} 0\n")); // Data itself stream->print(F("esphome_switch_value{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); @@ -330,17 +438,24 @@ void PrometheusHandler::lock_type_(AsyncResponseStream *stream) { stream->print(F("#TYPE esphome_lock_value gauge\n")); stream->print(F("#TYPE esphome_lock_failed gauge\n")); } -void PrometheusHandler::lock_row_(AsyncResponseStream *stream, lock::Lock *obj) { +void PrometheusHandler::lock_row_(AsyncResponseStream *stream, lock::Lock *obj, std::string &area, std::string &node, + std::string &friendly_name) { if (obj->is_internal() && !this->include_internal_) return; stream->print(F("esphome_lock_failed{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} 0\n")); // Data itself stream->print(F("esphome_lock_value{id=\"")); stream->print(relabel_id_(obj).c_str()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); stream->print(F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(F("\"} ")); @@ -349,6 +464,53 @@ 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, std::string &area, + std::string &node, std::string &friendly_name) { + 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()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); + 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()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); + 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()); + add_area_label_(stream, area); + add_node_label_(stream, node); + add_friendly_name_label_(stream, friendly_name); + 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..5d08aca63a 100644 --- a/esphome/components/prometheus/prometheus_handler.h +++ b/esphome/components/prometheus/prometheus_handler.h @@ -60,54 +60,72 @@ class PrometheusHandler : public AsyncWebHandler, public Component { protected: std::string relabel_id_(EntityBase *obj); std::string relabel_name_(EntityBase *obj); + void add_area_label_(AsyncResponseStream *stream, std::string &area); + void add_node_label_(AsyncResponseStream *stream, std::string &node); + void add_friendly_name_label_(AsyncResponseStream *stream, std::string &friendly_name); #ifdef USE_SENSOR /// Return the type for prometheus void sensor_type_(AsyncResponseStream *stream); /// Return the sensor state as prometheus data point - void sensor_row_(AsyncResponseStream *stream, sensor::Sensor *obj); + void sensor_row_(AsyncResponseStream *stream, sensor::Sensor *obj, std::string &area, std::string &node, + std::string &friendly_name); #endif #ifdef USE_BINARY_SENSOR /// Return the type for prometheus void binary_sensor_type_(AsyncResponseStream *stream); /// Return the sensor state as prometheus data point - void binary_sensor_row_(AsyncResponseStream *stream, binary_sensor::BinarySensor *obj); + void binary_sensor_row_(AsyncResponseStream *stream, binary_sensor::BinarySensor *obj, std::string &area, + std::string &node, std::string &friendly_name); #endif #ifdef USE_FAN /// Return the type for prometheus void fan_type_(AsyncResponseStream *stream); /// Return the sensor state as prometheus data point - void fan_row_(AsyncResponseStream *stream, fan::Fan *obj); + void fan_row_(AsyncResponseStream *stream, fan::Fan *obj, std::string &area, std::string &node, + std::string &friendly_name); #endif #ifdef USE_LIGHT /// Return the type for prometheus void light_type_(AsyncResponseStream *stream); /// Return the Light Values state as prometheus data point - void light_row_(AsyncResponseStream *stream, light::LightState *obj); + void light_row_(AsyncResponseStream *stream, light::LightState *obj, std::string &area, std::string &node, + std::string &friendly_name); #endif #ifdef USE_COVER /// Return the type for prometheus void cover_type_(AsyncResponseStream *stream); /// Return the switch Values state as prometheus data point - void cover_row_(AsyncResponseStream *stream, cover::Cover *obj); + void cover_row_(AsyncResponseStream *stream, cover::Cover *obj, std::string &area, std::string &node, + std::string &friendly_name); #endif #ifdef USE_SWITCH /// Return the type for prometheus void switch_type_(AsyncResponseStream *stream); /// Return the switch Values state as prometheus data point - void switch_row_(AsyncResponseStream *stream, switch_::Switch *obj); + void switch_row_(AsyncResponseStream *stream, switch_::Switch *obj, std::string &area, std::string &node, + std::string &friendly_name); #endif #ifdef USE_LOCK /// Return the type for prometheus void lock_type_(AsyncResponseStream *stream); /// Return the lock Values state as prometheus data point - void lock_row_(AsyncResponseStream *stream, lock::Lock *obj); + void lock_row_(AsyncResponseStream *stream, lock::Lock *obj, std::string &area, std::string &node, + std::string &friendly_name); +#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, std::string &area, std::string &node, + std::string &friendly_name); #endif web_server_base::WebServerBase *base_; 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/rp2040/gpio.py b/esphome/components/rp2040/gpio.py index 6ba0975a2c..58514f7db5 100644 --- a/esphome/components/rp2040/gpio.py +++ b/esphome/components/rp2040/gpio.py @@ -1,6 +1,8 @@ +from esphome import pins import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import ( + CONF_ANALOG, CONF_ID, CONF_INPUT, CONF_INVERTED, @@ -10,10 +12,8 @@ from esphome.const import ( CONF_OUTPUT, CONF_PULLDOWN, CONF_PULLUP, - CONF_ANALOG, ) from esphome.core import CORE -from esphome import pins from . import boards from .const import KEY_BOARD, KEY_RP2040, rp2040_ns @@ -41,8 +41,10 @@ def _translate_pin(value): "This variable only supports pin numbers, not full pin schemas " "(with inverted and mode)." ) - if isinstance(value, int): + if isinstance(value, int) and not isinstance(value, bool): return value + if not isinstance(value, str): + raise cv.Invalid(f"Invalid pin number: {value}") try: return int(value) except ValueError: diff --git a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp index 655b469b91..ba09171649 100644 --- a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +++ b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp @@ -84,6 +84,26 @@ void RpiDpiRgb::draw_pixels_at(int x_start, int y_start, int w, int h, const uin 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) { if (!this->get_clipping().inside(x, y)) return; // NOLINT diff --git a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h index 10f77a2624..7525040cd1 100644 --- a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h +++ b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h @@ -24,6 +24,7 @@ class RpiDpiRgb : public display::Display { 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; @@ -44,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/sdl/sdl_esphome.cpp b/esphome/components/sdl/sdl_esphome.cpp index 5e17ca5650..8f0821a2fa 100644 --- a/esphome/components/sdl/sdl_esphome.cpp +++ b/esphome/components/sdl/sdl_esphome.cpp @@ -9,8 +9,9 @@ void Sdl::setup() { ESP_LOGD(TAG, "Starting setup"); SDL_Init(SDL_INIT_VIDEO); this->window_ = SDL_CreateWindow(App.get_name().c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - this->width_, this->height_, 0); + this->width_, this->height_, SDL_WINDOW_RESIZABLE); this->renderer_ = SDL_CreateRenderer(this->window_, -1, SDL_RENDERER_SOFTWARE); + SDL_RenderSetLogicalSize(this->renderer_, this->width_, this->height_); this->texture_ = SDL_CreateTexture(this->renderer_, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STATIC, this->width_, this->height_); SDL_SetTextureBlendMode(this->texture_, SDL_BLENDMODE_BLEND); @@ -25,6 +26,10 @@ void Sdl::update() { this->y_low_ = this->height_; this->x_high_ = 0; this->y_high_ = 0; + this->redraw_(rect); +} + +void Sdl::redraw_(SDL_Rect &rect) { SDL_RenderCopy(this->renderer_, this->texture_, &rect, &rect); SDL_RenderPresent(this->renderer_); } @@ -33,15 +38,13 @@ void Sdl::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t * display::ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) { SDL_Rect rect{x_start, y_start, w, h}; if (this->rotation_ != display::DISPLAY_ROTATION_0_DEGREES || bitness != display::COLOR_BITNESS_565 || big_endian) { - display::Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, - x_pad); + Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, x_pad); } else { auto stride = x_offset + w + x_pad; auto data = ptr + (stride * y_offset + x_offset) * 2; SDL_UpdateTexture(this->texture_, &rect, data, stride * 2); } - SDL_RenderCopy(this->renderer_, this->texture_, &rect, &rect); - SDL_RenderPresent(this->renderer_); + this->redraw_(rect); } void Sdl::draw_pixel_at(int x, int y, Color color) { @@ -84,6 +87,20 @@ void Sdl::loop() { } break; + case SDL_WINDOWEVENT: + switch (e.window.event) { + case SDL_WINDOWEVENT_SIZE_CHANGED: + case SDL_WINDOWEVENT_EXPOSED: + case SDL_WINDOWEVENT_RESIZED: { + SDL_Rect rect{0, 0, this->width_, this->height_}; + this->redraw_(rect); + break; + } + default: + break; + } + break; + default: ESP_LOGV(TAG, "Event %d", e.type); break; diff --git a/esphome/components/sdl/sdl_esphome.h b/esphome/components/sdl/sdl_esphome.h index e4b2d9dd9f..4b0e59c9fe 100644 --- a/esphome/components/sdl/sdl_esphome.h +++ b/esphome/components/sdl/sdl_esphome.h @@ -38,6 +38,7 @@ class Sdl : public display::Display { protected: int get_width_internal() override { return this->width_; } int get_height_internal() override { return this->height_; } + void redraw_(SDL_Rect &rect); int width_{}; int height_{}; SDL_Renderer *renderer_{}; 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..9dbad27102 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, @@ -335,19 +335,28 @@ def sensor_schema( return SENSOR_SCHEMA.extend(schema) -@FILTER_REGISTRY.register("offset", OffsetFilter, cv.float_) +@FILTER_REGISTRY.register("offset", OffsetFilter, cv.templatable(cv.float_)) async def offset_filter_to_code(config, filter_id): - return cg.new_Pvariable(filter_id, config) + template_ = await cg.templatable(config, [], float) + return cg.new_Pvariable(filter_id, template_) -@FILTER_REGISTRY.register("multiply", MultiplyFilter, cv.float_) +@FILTER_REGISTRY.register("multiply", MultiplyFilter, cv.templatable(cv.float_)) async def multiply_filter_to_code(config, filter_id): - return cg.new_Pvariable(filter_id, config) + template_ = await cg.templatable(config, [], float) + return cg.new_Pvariable(filter_id, template_) -@FILTER_REGISTRY.register("filter_out", FilterOutValueFilter, cv.float_) +@FILTER_REGISTRY.register( + "filter_out", + FilterOutValueFilter, + cv.Any(cv.templatable(cv.float_), [cv.templatable(cv.float_)]), +) async def filter_out_filter_to_code(config, filter_id): - return cg.new_Pvariable(filter_id, config) + if not isinstance(config, list): + config = [config] + template_ = [await cg.templatable(x, [], float) for x in config] + return cg.new_Pvariable(filter_id, template_) QUANTILE_SCHEMA = cv.All( @@ -573,7 +582,7 @@ async def heartbeat_filter_to_code(config, filter_id): TIMEOUT_SCHEMA = cv.maybe_simple_value( { cv.Required(CONF_TIMEOUT): cv.positive_time_period_milliseconds, - cv.Optional(CONF_VALUE, default="nan"): cv.float_, + cv.Optional(CONF_VALUE, default="nan"): cv.templatable(cv.float_), }, key=CONF_TIMEOUT, ) @@ -581,7 +590,8 @@ TIMEOUT_SCHEMA = cv.maybe_simple_value( @FILTER_REGISTRY.register("timeout", TimeoutFilter, TIMEOUT_SCHEMA) async def timeout_filter_to_code(config, filter_id): - var = cg.new_Pvariable(filter_id, config[CONF_TIMEOUT], config[CONF_VALUE]) + template_ = await cg.templatable(config[CONF_VALUE], [], float) + var = cg.new_Pvariable(filter_id, config[CONF_TIMEOUT], template_) await cg.register_component(var, {}) return var @@ -800,9 +810,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/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index bcf1fc8269..0a8740dd5b 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -288,36 +288,36 @@ optional LambdaFilter::new_value(float value) { } // OffsetFilter -OffsetFilter::OffsetFilter(float offset) : offset_(offset) {} +OffsetFilter::OffsetFilter(TemplatableValue offset) : offset_(std::move(offset)) {} -optional OffsetFilter::new_value(float value) { return value + this->offset_; } +optional OffsetFilter::new_value(float value) { return value + this->offset_.value(); } // MultiplyFilter -MultiplyFilter::MultiplyFilter(float multiplier) : multiplier_(multiplier) {} +MultiplyFilter::MultiplyFilter(TemplatableValue multiplier) : multiplier_(std::move(multiplier)) {} -optional MultiplyFilter::new_value(float value) { return value * this->multiplier_; } +optional MultiplyFilter::new_value(float value) { return value * this->multiplier_.value(); } // FilterOutValueFilter -FilterOutValueFilter::FilterOutValueFilter(float value_to_filter_out) : value_to_filter_out_(value_to_filter_out) {} +FilterOutValueFilter::FilterOutValueFilter(std::vector> values_to_filter_out) + : values_to_filter_out_(std::move(values_to_filter_out)) {} optional FilterOutValueFilter::new_value(float value) { - if (std::isnan(this->value_to_filter_out_)) { - if (std::isnan(value)) { - return {}; - } else { - return value; + int8_t accuracy = this->parent_->get_accuracy_decimals(); + float accuracy_mult = powf(10.0f, accuracy); + for (auto filter_value : this->values_to_filter_out_) { + if (std::isnan(filter_value.value())) { + if (std::isnan(value)) { + return {}; + } + continue; } - } else { - int8_t accuracy = this->parent_->get_accuracy_decimals(); - float accuracy_mult = powf(10.0f, accuracy); - float rounded_filter_out = roundf(accuracy_mult * this->value_to_filter_out_); + float rounded_filter_out = roundf(accuracy_mult * filter_value.value()); float rounded_value = roundf(accuracy_mult * value); if (rounded_filter_out == rounded_value) { return {}; - } else { - return value; } } + return value; } // ThrottleFilter @@ -383,11 +383,12 @@ void OrFilter::initialize(Sensor *parent, Filter *next) { // TimeoutFilter optional TimeoutFilter::new_value(float value) { - this->set_timeout("timeout", this->time_period_, [this]() { this->output(this->value_); }); + this->set_timeout("timeout", this->time_period_, [this]() { this->output(this->value_.value()); }); return value; } -TimeoutFilter::TimeoutFilter(uint32_t time_period, float new_value) : time_period_(time_period), value_(new_value) {} +TimeoutFilter::TimeoutFilter(uint32_t time_period, TemplatableValue new_value) + : time_period_(time_period), value_(std::move(new_value)) {} float TimeoutFilter::get_setup_priority() const { return setup_priority::HARDWARE; } // DebounceFilter diff --git a/esphome/components/sensor/filter.h b/esphome/components/sensor/filter.h index 92b1d8d240..86586b458d 100644 --- a/esphome/components/sensor/filter.h +++ b/esphome/components/sensor/filter.h @@ -5,6 +5,7 @@ #include #include "esphome/core/component.h" #include "esphome/core/helpers.h" +#include "esphome/core/automation.h" namespace esphome { namespace sensor { @@ -273,34 +274,33 @@ class LambdaFilter : public Filter { /// A simple filter that adds `offset` to each value it receives. class OffsetFilter : public Filter { public: - explicit OffsetFilter(float offset); + explicit OffsetFilter(TemplatableValue offset); optional new_value(float value) override; protected: - float offset_; + TemplatableValue offset_; }; /// A simple filter that multiplies to each value it receives by `multiplier`. class MultiplyFilter : public Filter { public: - explicit MultiplyFilter(float multiplier); - + explicit MultiplyFilter(TemplatableValue multiplier); optional new_value(float value) override; protected: - float multiplier_; + TemplatableValue multiplier_; }; /// A simple filter that only forwards the filter chain if it doesn't receive `value_to_filter_out`. class FilterOutValueFilter : public Filter { public: - explicit FilterOutValueFilter(float value_to_filter_out); + explicit FilterOutValueFilter(std::vector> values_to_filter_out); optional new_value(float value) override; protected: - float value_to_filter_out_; + std::vector> values_to_filter_out_; }; class ThrottleFilter : public Filter { @@ -316,8 +316,7 @@ class ThrottleFilter : public Filter { class TimeoutFilter : public Filter, public Component { public: - explicit TimeoutFilter(uint32_t time_period, float new_value); - void set_value(float new_value) { this->value_ = new_value; } + explicit TimeoutFilter(uint32_t time_period, TemplatableValue new_value); optional new_value(float value) override; @@ -325,7 +324,7 @@ class TimeoutFilter : public Filter, public Component { protected: uint32_t time_period_; - float value_; + TemplatableValue value_; }; class DebounceFilter : public Filter, public Component { 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/spi/__init__.py b/esphome/components/spi/__init__.py index fdf19bb56e..52afbf365e 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -1,40 +1,37 @@ import re +from esphome import pins import esphome.codegen as cg -import esphome.config_validation as cv -import esphome.final_validate as fv from esphome.components.esp32.const import ( KEY_ESP32, - VARIANT_ESP32S2, - VARIANT_ESP32S3, VARIANT_ESP32C2, VARIANT_ESP32C3, VARIANT_ESP32C6, VARIANT_ESP32H2, + VARIANT_ESP32S2, + VARIANT_ESP32S3, ) -from esphome import pins +import esphome.config_validation as cv from esphome.const import ( CONF_CLK_PIN, + CONF_CS_PIN, + CONF_DATA_PINS, + CONF_DATA_RATE, CONF_ID, + CONF_INVERTED, CONF_MISO_PIN, CONF_MOSI_PIN, - CONF_SPI_ID, - CONF_CS_PIN, CONF_NUMBER, - CONF_INVERTED, + CONF_SPI_ID, KEY_CORE, KEY_TARGET_PLATFORM, KEY_VARIANT, - CONF_DATA_RATE, PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040, - CONF_DATA_PINS, -) -from esphome.core import ( - coroutine_with_priority, - CORE, ) +from esphome.core import CORE, coroutine_with_priority +import esphome.final_validate as fv CODEOWNERS = ["@esphome/core", "@clydebarrow"] spi_ns = cg.esphome_ns.namespace("spi") @@ -69,6 +66,10 @@ SPI_MODE_OPTIONS = { 1: SPIMode.MODE1, 2: SPIMode.MODE2, 3: SPIMode.MODE3, + "0": SPIMode.MODE0, + "1": SPIMode.MODE1, + "2": SPIMode.MODE2, + "3": SPIMode.MODE3, } CONF_SPI_MODE = "spi_mode" diff --git a/esphome/components/spi_device/__init__.py b/esphome/components/spi_device/__init__.py index 65e7ee6fc6..2f23d8a011 100644 --- a/esphome/components/spi_device/__init__.py +++ b/esphome/components/spi_device/__init__.py @@ -1,6 +1,6 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import spi +import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_MODE DEPENDENCIES = ["spi"] @@ -11,18 +11,6 @@ spi_device_ns = cg.esphome_ns.namespace("spi_device") spi_device = spi_device_ns.class_("SPIDeviceComponent", cg.Component, spi.SPIDevice) -Mode = spi.spi_ns.enum("SPIMode") -MODES = { - "0": Mode.MODE0, - "1": Mode.MODE1, - "2": Mode.MODE2, - "3": Mode.MODE3, - "MODE0": Mode.MODE0, - "MODE1": Mode.MODE1, - "MODE2": Mode.MODE2, - "MODE3": Mode.MODE3, -} - BitOrder = spi.spi_ns.enum("SPIBitOrder") ORDERS = { "msb_first": BitOrder.BIT_ORDER_MSB_FIRST, @@ -34,7 +22,9 @@ CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(CONF_ID): cv.declare_id(spi_device), cv.Optional(CONF_BIT_ORDER, default="msb_first"): cv.enum(ORDERS, lower=True), - cv.Optional(CONF_MODE, default="0"): cv.enum(MODES, upper=True), + cv.Optional(CONF_MODE): cv.invalid( + "The 'mode' option has been renamed to 'spi_mode'." + ), } ).extend(spi.spi_device_schema(False, "1MHz")) @@ -42,6 +32,5 @@ CONFIG_SCHEMA = cv.Schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) - cg.add(var.set_mode(config[CONF_MODE])) cg.add(var.set_bit_order(config[CONF_BIT_ORDER])) await spi.register_spi_device(var, config) diff --git a/esphome/components/ssd1306_spi/display.py b/esphome/components/ssd1306_spi/display.py index 0af1168bde..4af41073d4 100644 --- a/esphome/components/ssd1306_spi/display.py +++ b/esphome/components/ssd1306_spi/display.py @@ -1,8 +1,8 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import pins +import esphome.codegen as cg from esphome.components import spi, ssd1306_base from esphome.components.ssd1306_base import _validate +import esphome.config_validation as cv from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES AUTO_LOAD = ["ssd1306_base"] @@ -24,6 +24,10 @@ CONFIG_SCHEMA = cv.All( _validate, ) +FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( + "ssd1306_spi", require_miso=False, require_mosi=True +) + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) diff --git a/esphome/components/ssd1322_spi/display.py b/esphome/components/ssd1322_spi/display.py index 88b3a53355..849e71abee 100644 --- a/esphome/components/ssd1322_spi/display.py +++ b/esphome/components/ssd1322_spi/display.py @@ -1,7 +1,7 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import pins +import esphome.codegen as cg from esphome.components import spi, ssd1322_base +import esphome.config_validation as cv from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES CODEOWNERS = ["@kbx81"] @@ -24,6 +24,10 @@ CONFIG_SCHEMA = cv.All( cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), ) +FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( + "ssd1322_spi", require_miso=False, require_mosi=True +) + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) diff --git a/esphome/components/ssd1325_spi/display.py b/esphome/components/ssd1325_spi/display.py index a86dc751d5..e18db33c68 100644 --- a/esphome/components/ssd1325_spi/display.py +++ b/esphome/components/ssd1325_spi/display.py @@ -1,7 +1,7 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import pins +import esphome.codegen as cg from esphome.components import spi, ssd1325_base +import esphome.config_validation as cv from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES CODEOWNERS = ["@kbx81"] @@ -24,6 +24,10 @@ CONFIG_SCHEMA = cv.All( cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), ) +FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( + "ssd1325_spi", require_miso=False, require_mosi=True +) + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) diff --git a/esphome/components/ssd1327_spi/display.py b/esphome/components/ssd1327_spi/display.py index 138e85eecd..b622c098ec 100644 --- a/esphome/components/ssd1327_spi/display.py +++ b/esphome/components/ssd1327_spi/display.py @@ -1,7 +1,7 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import pins +import esphome.codegen as cg from esphome.components import spi, ssd1327_base +import esphome.config_validation as cv from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES CODEOWNERS = ["@kbx81"] @@ -24,6 +24,10 @@ CONFIG_SCHEMA = cv.All( cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), ) +FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( + "ssd1327_spi", require_miso=False, require_mosi=True +) + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) diff --git a/esphome/components/ssd1331_spi/display.py b/esphome/components/ssd1331_spi/display.py index c32ac60578..50895b3175 100644 --- a/esphome/components/ssd1331_spi/display.py +++ b/esphome/components/ssd1331_spi/display.py @@ -1,7 +1,7 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import pins +import esphome.codegen as cg from esphome.components import spi, ssd1331_base +import esphome.config_validation as cv from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES CODEOWNERS = ["@kbx81"] @@ -24,6 +24,10 @@ CONFIG_SCHEMA = cv.All( cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), ) +FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( + "ssd1331_spi", require_miso=False, require_mosi=True +) + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) diff --git a/esphome/components/ssd1351_spi/display.py b/esphome/components/ssd1351_spi/display.py index 3f3409226c..bd7033c3d4 100644 --- a/esphome/components/ssd1351_spi/display.py +++ b/esphome/components/ssd1351_spi/display.py @@ -1,7 +1,7 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import pins +import esphome.codegen as cg from esphome.components import spi, ssd1351_base +import esphome.config_validation as cv from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES CODEOWNERS = ["@kbx81"] @@ -24,6 +24,10 @@ CONFIG_SCHEMA = cv.All( cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), ) +FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( + "ssd1351_spi", require_miso=False, require_mosi=True +) + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) diff --git a/esphome/components/st7567_spi/display.py b/esphome/components/st7567_spi/display.py index aabe02a2d8..305aa35024 100644 --- a/esphome/components/st7567_spi/display.py +++ b/esphome/components/st7567_spi/display.py @@ -1,7 +1,7 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import pins +import esphome.codegen as cg from esphome.components import spi, st7567_base +import esphome.config_validation as cv from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES CODEOWNERS = ["@latonita"] @@ -24,6 +24,10 @@ CONFIG_SCHEMA = cv.All( cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), ) +FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( + "st7567_spi", require_miso=False, require_mosi=True +) + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) diff --git a/esphome/components/st7701s/display.py b/esphome/components/st7701s/display.py index 9310e9d760..c6ad43c14c 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" @@ -167,6 +167,10 @@ CONFIG_SCHEMA = cv.All( cv.only_with_esp_idf, ) +FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( + "st7701s", require_miso=False, require_mosi=True +) + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) 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/st7735/display.py b/esphome/components/st7735/display.py index d5bb2fa3d6..2761214315 100644 --- a/esphome/components/st7735/display.py +++ b/esphome/components/st7735/display.py @@ -1,17 +1,17 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import pins -from esphome.components import spi -from esphome.components import display +import esphome.codegen as cg +from esphome.components import display, spi +import esphome.config_validation as cv from esphome.const import ( CONF_DC_PIN, CONF_ID, + CONF_INVERT_COLORS, CONF_LAMBDA, CONF_MODEL, - CONF_RESET_PIN, CONF_PAGES, - CONF_INVERT_COLORS, + CONF_RESET_PIN, ) + from . import st7735_ns CODEOWNERS = ["@SenexCrenshaw"] @@ -68,6 +68,11 @@ CONFIG_SCHEMA = cv.All( ) +FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( + "st7735", require_miso=False, require_mosi=True +) + + async def setup_st7735(var, config): await display.register_display(var, config) diff --git a/esphome/components/st7789v/display.py b/esphome/components/st7789v/display.py index 04dce2cf6c..8259eacf2d 100644 --- a/esphome/components/st7789v/display.py +++ b/esphome/components/st7789v/display.py @@ -1,22 +1,23 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import pins -from esphome.components import display, spi, power_supply +import esphome.codegen as cg +from esphome.components import display, power_supply, spi +import esphome.config_validation as cv from esphome.const import ( CONF_BACKLIGHT_PIN, + CONF_CS_PIN, CONF_DC_PIN, CONF_HEIGHT, CONF_ID, CONF_LAMBDA, CONF_MODEL, - CONF_RESET_PIN, - CONF_WIDTH, - CONF_POWER_SUPPLY, - CONF_ROTATION, - CONF_CS_PIN, CONF_OFFSET_HEIGHT, CONF_OFFSET_WIDTH, + CONF_POWER_SUPPLY, + CONF_RESET_PIN, + CONF_ROTATION, + CONF_WIDTH, ) + from . import st7789v_ns CONF_EIGHTBITCOLOR = "eightbitcolor" @@ -168,6 +169,10 @@ CONFIG_SCHEMA = cv.All( validate_st7789v, ) +FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( + "st7789v", require_miso=False, require_mosi=True +) + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) 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/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/touchscreen/__init__.py b/esphome/components/touchscreen/__init__.py index b2d3f60d2b..01a271a34e 100644 --- a/esphome/components/touchscreen/__init__.py +++ b/esphome/components/touchscreen/__init__.py @@ -1,21 +1,18 @@ -import esphome.config_validation as cv -import esphome.codegen as cg - -from esphome.components import display from esphome import automation - +import esphome.codegen as cg +from esphome.components import display +import esphome.config_validation as cv from esphome.const import ( + CONF_CALIBRATION, CONF_DISPLAY, - CONF_ON_TOUCH, - CONF_ON_RELEASE, - CONF_ON_UPDATE, - CONF_SWAP_XY, CONF_MIRROR_X, CONF_MIRROR_Y, + CONF_ON_RELEASE, + CONF_ON_TOUCH, + CONF_ON_UPDATE, + CONF_SWAP_XY, CONF_TRANSFORM, - CONF_CALIBRATION, ) - from esphome.core import coroutine_with_priority CODEOWNERS = ["@jesserockz", "@nielsnl68"] @@ -43,51 +40,45 @@ CONF_Y_MIN = "y_min" CONF_Y_MAX = "y_max" -def validate_calibration(config): - if CONF_CALIBRATION in config: - calibration_config = config[CONF_CALIBRATION] - if ( - cv.int_([CONF_X_MIN]) != 0 - and cv.int_(calibration_config[CONF_X_MAX]) != 0 - and abs( - cv.int_(calibration_config[CONF_X_MIN]) - - cv.int_(calibration_config[CONF_X_MAX]) - ) - < 10 - ): - raise cv.Invalid("Calibration X values difference must be more than 10") - - if ( - cv.int_(calibration_config[CONF_Y_MIN]) != 0 - and cv.int_(calibration_config[CONF_Y_MAX]) != 0 - and abs( - cv.int_(calibration_config[CONF_Y_MIN]) - - cv.int_(calibration_config[CONF_Y_MAX]) - ) - < 10 - ): - raise cv.Invalid("Calibration Y values difference must be more than 10") - - return config +def validate_calibration(calibration_config): + x_min = calibration_config[CONF_X_MIN] + x_max = calibration_config[CONF_X_MAX] + y_min = calibration_config[CONF_Y_MIN] + y_max = calibration_config[CONF_Y_MAX] + if x_max < x_min: + raise cv.Invalid( + "x_min must be smaller than x_max. To mirror the direction use the 'transform' options" + ) + if y_max < y_min: + raise cv.Invalid( + "y_min must be smaller than y_max. To mirror the direction use the 'transform' options" + ) + x_delta = x_max - x_min + y_delta = y_max - y_min + if x_delta < 10 or y_delta < 10: + raise cv.Invalid("Calibration value range must be greater than 10") + return calibration_config -def calibration_schema(default_max_values): - return cv.Schema( +CALIBRATION_SCHEMA = cv.All( + cv.Schema( { - cv.Optional(CONF_X_MIN, default=0): cv.int_range(min=0, max=4095), - cv.Optional(CONF_X_MAX, default=default_max_values): cv.int_range( - min=0, max=4095 - ), - cv.Optional(CONF_Y_MIN, default=0): cv.int_range(min=0, max=4095), - cv.Optional(CONF_Y_MAX, default=default_max_values): cv.int_range( - min=0, max=4095 - ), - }, - validate_calibration, + cv.Required(CONF_X_MIN): cv.int_range(min=0, max=4095), + cv.Required(CONF_X_MAX): cv.int_range(min=0, max=4095), + cv.Required(CONF_Y_MIN): cv.int_range(min=0, max=4095), + cv.Required(CONF_Y_MAX): cv.int_range(min=0, max=4095), + } + ), + validate_calibration, +) + + +def touchscreen_schema(default_touch_timeout=cv.UNDEFINED, calibration_required=False): + calibration = ( + cv.Required(CONF_CALIBRATION) + if calibration_required + else cv.Optional(CONF_CALIBRATION) ) - - -def touchscreen_schema(default_touch_timeout): return cv.Schema( { cv.GenerateID(CONF_DISPLAY): cv.use_id(display.Display), @@ -102,7 +93,7 @@ def touchscreen_schema(default_touch_timeout): cv.positive_time_period_milliseconds, cv.Range(max=cv.TimePeriod(milliseconds=65535)), ), - cv.Optional(CONF_CALIBRATION): calibration_schema(0), + calibration: CALIBRATION_SCHEMA, cv.Optional(CONF_ON_TOUCH): automation.validate_automation(single=True), cv.Optional(CONF_ON_UPDATE): automation.validate_automation(single=True), cv.Optional(CONF_ON_RELEASE): automation.validate_automation(single=True), 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/touchscreen/touchscreen.h b/esphome/components/touchscreen/touchscreen.h index 21111f87b3..8016323d49 100644 --- a/esphome/components/touchscreen/touchscreen.h +++ b/esphome/components/touchscreen/touchscreen.h @@ -53,14 +53,10 @@ class Touchscreen : public PollingComponent { void set_swap_xy(bool swap) { this->swap_x_y_ = swap; } void set_calibration(int16_t x_min, int16_t x_max, int16_t y_min, int16_t y_max) { - this->x_raw_min_ = std::min(x_min, x_max); - this->x_raw_max_ = std::max(x_min, x_max); - this->y_raw_min_ = std::min(y_min, y_max); - this->y_raw_max_ = std::max(y_min, y_max); - if (x_min > x_max) - this->invert_x_ = true; - if (y_min > y_max) - this->invert_y_ = true; + this->x_raw_min_ = x_min; + this->x_raw_max_ = x_max; + this->y_raw_min_ = y_min; + this->y_raw_max_ = y_max; } Trigger *get_touch_trigger() { return &this->touch_trigger_; } 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/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/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index a2210f188d..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 @@ -437,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"); + } } } } @@ -776,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; } @@ -806,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 } diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index b0a172332f..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(); @@ -133,6 +146,8 @@ class VoiceAssistant : public Component { 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; } @@ -235,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}; @@ -267,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_; @@ -279,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/waveshare_epaper/display.py b/esphome/components/waveshare_epaper/display.py index 4d3965449f..8287788de5 100644 --- a/esphome/components/waveshare_epaper/display.py +++ b/esphome/components/waveshare_epaper/display.py @@ -1,7 +1,7 @@ -import esphome.codegen as cg -import esphome.config_validation as cv from esphome import core, pins +import esphome.codegen as cg from esphome.components import display, spi +import esphome.config_validation as cv from esphome.const import ( CONF_BUSY_PIN, CONF_DC_PIN, @@ -187,6 +187,10 @@ CONFIG_SCHEMA = cv.All( cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), ) +FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( + "waveshare_epaper", require_miso=False, require_mosi=True +) + async def to_code(config): model_type, model = MODELS[config[CONF_MODEL]] 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/xpt2046/touchscreen/__init__.py b/esphome/components/xpt2046/touchscreen/__init__.py index d45f309a3b..d91ae44789 100644 --- a/esphome/components/xpt2046/touchscreen/__init__.py +++ b/esphome/components/xpt2046/touchscreen/__init__.py @@ -1,9 +1,8 @@ -import esphome.codegen as cg -import esphome.config_validation as cv - from esphome import pins +import esphome.codegen as cg from esphome.components import spi, touchscreen -from esphome.const import CONF_ID, CONF_THRESHOLD, CONF_INTERRUPT_PIN +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_INTERRUPT_PIN, CONF_THRESHOLD CODEOWNERS = ["@numo68", "@nielsnl68"] DEPENDENCIES = ["spi"] @@ -15,13 +14,9 @@ XPT2046Component = XPT2046_ns.class_( spi.SPIDevice, ) -CONF_CALIBRATION_X_MIN = "calibration_x_min" -CONF_CALIBRATION_X_MAX = "calibration_x_max" -CONF_CALIBRATION_Y_MIN = "calibration_y_min" -CONF_CALIBRATION_Y_MAX = "calibration_y_max" - CONFIG_SCHEMA = cv.All( - touchscreen.TOUCHSCREEN_SCHEMA.extend( + touchscreen.touchscreen_schema(calibration_required=True) + .extend( cv.Schema( { cv.GenerateID(): cv.declare_id(XPT2046Component), @@ -29,30 +24,10 @@ CONFIG_SCHEMA = cv.All( pins.internal_gpio_input_pin_schema ), cv.Optional(CONF_THRESHOLD, default=400): cv.int_range(min=0, max=4095), - cv.Optional( - touchscreen.CONF_CALIBRATION - ): touchscreen.calibration_schema(4095), - cv.Optional(CONF_CALIBRATION_X_MIN): cv.invalid( - "Deprecated: use the new 'calibration' configuration variable" - ), - cv.Optional(CONF_CALIBRATION_X_MAX): cv.invalid( - "Deprecated: use the new 'calibration' configuration variable" - ), - cv.Optional(CONF_CALIBRATION_Y_MIN): cv.invalid( - "Deprecated: use the new 'calibration' configuration variable" - ), - cv.Optional(CONF_CALIBRATION_Y_MAX): cv.invalid( - "Deprecated: use the new 'calibration' configuration variable" - ), - cv.Optional(CONF_CALIBRATION_Y_MAX): cv.invalid( - "Deprecated: use the new 'calibration' configuration variable" - ), - cv.Optional("report_interval"): cv.invalid( - "Deprecated: use the 'update_interval' configuration variable" - ), }, ) - ).extend(spi.spi_device_schema()), + ) + .extend(spi.spi_device_schema()), ) 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 e55879e37e..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) diff --git a/esphome/const.py b/esphome/const.py index 6e7bbdec98..5645c9eaab 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.10.0-dev" +__version__ = "2024.11.0-dev" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( @@ -49,13 +49,16 @@ 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" @@ -89,6 +92,7 @@ CONF_BINARY_SENSORS = "binary_sensors" CONF_BINDKEY = "bindkey" CONF_BIRTH_MESSAGE = "birth_message" CONF_BIT_DEPTH = "bit_depth" +CONF_BITS_PER_SAMPLE = "bits_per_sample" CONF_BLOCK = "block" CONF_BLUE = "blue" CONF_BOARD = "board" @@ -110,6 +114,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" @@ -120,6 +125,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" @@ -262,6 +268,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" @@ -360,6 +367,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" @@ -375,6 +383,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" @@ -390,8 +399,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" @@ -475,6 +486,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" @@ -521,6 +533,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" @@ -654,6 +667,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" @@ -807,6 +821,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" @@ -926,7 +941,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" @@ -954,6 +968,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" @@ -975,6 +990,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" @@ -987,6 +1003,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..3798ddba6a 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 @@ -82,8 +86,6 @@ #ifdef USE_ARDUINO #define USE_CAPTIVE_PORTAL #define USE_PROMETHEUS -#define USE_WEBSERVER -#define USE_WEBSERVER_PORT 80 // NOLINT #define USE_WIFI_WPA2_EAP #endif @@ -107,6 +109,8 @@ #define USE_SPEAKER #define USE_SPI #define USE_VOICE_ASSISTANT +#define USE_WEBSERVER +#define USE_WEBSERVER_PORT 80 // NOLINT #define USE_WIFI_11KV_SUPPORT #ifdef USE_ARDUINO @@ -143,6 +147,8 @@ #define USE_SHD_FIRMWARE_DATA \ {} +#define USE_WEBSERVER +#define USE_WEBSERVER_PORT 80 // NOLINT #endif #ifdef USE_RP2040 @@ -154,6 +160,8 @@ #ifdef USE_LIBRETINY #define USE_SOCKET_IMPL_LWIP_SOCKETS +#define USE_WEBSERVER +#define USE_WEBSERVER_PORT 80 // NOLINT #endif #ifdef USE_HOST diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index e75b06ccd3..dae60a4e1d 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,92 @@ 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) +void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter) +#ifdef USE_WIFI + WiFi.macAddress(mac); +#endif +} +#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/status/mdns.py b/esphome/dashboard/status/mdns.py index bd212bc563..9f6399ca8b 100644 --- a/esphome/dashboard/status/mdns.py +++ b/esphome/dashboard/status/mdns.py @@ -26,7 +26,7 @@ class MDNSStatus: self.host_mdns_state: dict[str, bool | None] = {} self._loop = asyncio.get_running_loop() - async def async_resolve_host(self, host_name: str) -> str | None: + async def async_resolve_host(self, host_name: str) -> list[str] | None: """Resolve a host name to an address in a thread-safe manner.""" if aiozc := self.aiozc: return await aiozc.async_resolve_host(host_name) @@ -50,13 +50,12 @@ class MDNSStatus: poll_names.setdefault(entry.name, set()).add(entry) elif (online := host_mdns_state.get(entry.name, SENTINEL)) != SENTINEL: entries.async_set_state(entry, bool_to_entry_state(online)) - if poll_names and self.aiozc: results = await asyncio.gather( *(self.aiozc.async_resolve_host(name) for name in poll_names) ) - for name, address in zip(poll_names, results): - result = bool(address) + for name, address_list in zip(poll_names, results): + result = bool(address_list) host_mdns_state[name] = result for entry in poll_names[name]: entries.async_set_state(entry, bool_to_entry_state(result)) diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index e4b7b8d342..07f7f019f8 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 @@ -319,12 +320,12 @@ class EsphomePortCommandWebSocket(EsphomeCommandWebSocket): and "api" in entry.loaded_integrations ): if (mdns := dashboard.mdns_status) and ( - address := await mdns.async_resolve_host(entry.name) + address_list := await mdns.async_resolve_host(entry.name) ): # Use the IP address if available but only # if the API is loaded and the device is online # since MQTT logging will not work otherwise - port = address + port = address_list[0] elif ( entry.address and ( @@ -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/espota2.py b/esphome/espota2.py index 580536153a..94b845b246 100644 --- a/esphome/espota2.py +++ b/esphome/espota2.py @@ -10,7 +10,7 @@ import sys import time from esphome.core import EsphomeError -from esphome.helpers import is_ip_address, resolve_ip_address +from esphome.helpers import resolve_ip_address RESPONSE_OK = 0x00 RESPONSE_REQUEST_AUTH = 0x01 @@ -311,44 +311,45 @@ def perform_ota( def run_ota_impl_(remote_host, remote_port, password, filename): - if is_ip_address(remote_host): - _LOGGER.info("Connecting to %s", remote_host) - ip = remote_host - else: - _LOGGER.info("Resolving IP address of %s", remote_host) - try: - ip = resolve_ip_address(remote_host) - except EsphomeError as err: - _LOGGER.error( - "Error resolving IP address of %s. Is it connected to WiFi?", - remote_host, - ) - _LOGGER.error( - "(If this error persists, please set a static IP address: " - "https://esphome.io/components/wifi.html#manual-ips)" - ) - raise OTAError(err) from err - _LOGGER.info(" -> %s", ip) - - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.settimeout(10.0) try: - sock.connect((ip, remote_port)) - except OSError as err: - sock.close() - _LOGGER.error("Connecting to %s:%s failed: %s", remote_host, remote_port, err) - return 1 + res = resolve_ip_address(remote_host, remote_port) + except EsphomeError as err: + _LOGGER.error( + "Error resolving IP address of %s. Is it connected to WiFi?", + remote_host, + ) + _LOGGER.error( + "(If this error persists, please set a static IP address: " + "https://esphome.io/components/wifi.html#manual-ips)" + ) + raise OTAError(err) from err - with open(filename, "rb") as file_handle: + for r in res: + af, socktype, _, _, sa = r + _LOGGER.info("Connecting to %s port %s...", sa[0], sa[1]) + sock = socket.socket(af, socktype) + sock.settimeout(10.0) try: - perform_ota(sock, password, file_handle, filename) - except OTAError as err: - _LOGGER.error(str(err)) - return 1 - finally: + sock.connect(sa) + except OSError as err: sock.close() + _LOGGER.error("Connecting to %s port %s failed: %s", sa[0], sa[1], err) + continue - return 0 + _LOGGER.info("Connected to %s", sa[0]) + with open(filename, "rb") as file_handle: + try: + perform_ota(sock, password, file_handle, filename) + except OTAError as err: + _LOGGER.error(str(err)) + return 1 + finally: + sock.close() + + return 0 + + _LOGGER.error("Connection failed.") + return 1 def run_ota(remote_host, remote_port, password, filename): diff --git a/esphome/helpers.py b/esphome/helpers.py index 2a7e5cd9b6..8aae43c2bb 100644 --- a/esphome/helpers.py +++ b/esphome/helpers.py @@ -1,5 +1,6 @@ import codecs from contextlib import suppress +import ipaddress import logging import os from pathlib import Path @@ -91,12 +92,8 @@ def mkdir_p(path): def is_ip_address(host): - parts = host.split(".") - if len(parts) != 4: - return False try: - for p in parts: - int(p) + ipaddress.ip_address(host) return True except ValueError: return False @@ -127,25 +124,80 @@ def _resolve_with_zeroconf(host): return info -def resolve_ip_address(host): +def addr_preference_(res): + # Trivial alternative to RFC6724 sorting. Put sane IPv6 first, then + # Legacy IP, then IPv6 link-local addresses without an actual link. + sa = res[4] + ip = ipaddress.ip_address(sa[0]) + if ip.version == 4: + return 2 + if ip.is_link_local and sa[3] == 0: + return 3 + return 1 + + +def resolve_ip_address(host, port): import socket from esphome.core import EsphomeError + # There are five cases here. The host argument could be one of: + # • a *list* of IP addresses discovered by MQTT, + # • a single IP address specified by the user, + # • a .local hostname to be resolved by mDNS, + # • a normal hostname to be resolved in DNS, or + # • A URL from which we should extract the hostname. + # + # In each of the first three cases, we end up with IP addresses in + # string form which need to be converted to a 5-tuple to be used + # for the socket connection attempt. The easiest way to construct + # those is to pass the IP address string to getaddrinfo(). Which, + # coincidentally, is how we do hostname lookups in the other cases + # too. So first build a list which contains either IP addresses or + # a single hostname, then call getaddrinfo() on each element of + # that list. + errs = [] + if isinstance(host, list): + addr_list = host + elif is_ip_address(host): + addr_list = [host] + else: + url = urlparse(host) + if url.scheme != "": + host = url.hostname - if host.endswith(".local"): + addr_list = [] + if host.endswith(".local"): + try: + _LOGGER.info("Resolving IP address of %s in mDNS", host) + addr_list = _resolve_with_zeroconf(host) + except EsphomeError as err: + errs.append(str(err)) + + # If not mDNS, or if mDNS failed, use normal DNS + if not addr_list: + addr_list = [host] + + # Now we have a list containing either IP addresses or a hostname + res = [] + for addr in addr_list: + if not is_ip_address(addr): + _LOGGER.info("Resolving IP address of %s", host) try: - return _resolve_with_zeroconf(host) - except EsphomeError as err: + r = socket.getaddrinfo(addr, port, proto=socket.IPPROTO_TCP) + except OSError as err: errs.append(str(err)) + raise EsphomeError( + f"Error resolving IP address: {', '.join(errs)}" + ) from err - try: - host_url = host if (urlparse(host).scheme != "") else "http://" + host - return socket.gethostbyname(urlparse(host_url).hostname) - except OSError as err: - errs.append(str(err)) - raise EsphomeError(f"Error resolving IP address: {', '.join(errs)}") from err + res = res + r + + # Zeroconf tends to give us link-local IPv6 addresses without specifying + # the link. Put those last in the list to be attempted. + res.sort(key=addr_preference_) + return res def get_bool_env(var, default=False): diff --git a/esphome/mqtt.py b/esphome/mqtt.py index c1c45799cc..2f90c49025 100644 --- a/esphome/mqtt.py +++ b/esphome/mqtt.py @@ -175,8 +175,15 @@ def get_esphome_device_ip( _LOGGER.Warn("Wrong device answer") return - if "ip" in data: - dev_ip = data["ip"] + dev_ip = [] + key = "ip" + n = 0 + while key in data: + dev_ip.append(data[key]) + n = n + 1 + key = "ip" + str(n) + + if dev_ip: client.disconnect() def on_connect(client, userdata, flags, return_code): @@ -209,6 +216,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/esphome/zeroconf.py b/esphome/zeroconf.py index b3ee64e259..5a92a4ed7c 100644 --- a/esphome/zeroconf.py +++ b/esphome/zeroconf.py @@ -176,24 +176,26 @@ def _make_host_resolver(host: str) -> HostResolver: class EsphomeZeroconf(Zeroconf): - def resolve_host(self, host: str, timeout: float = 3.0) -> str | None: + def resolve_host(self, host: str, timeout: float = 3.0) -> list[str] | None: """Resolve a host name to an IP address.""" info = _make_host_resolver(host) if ( info.load_from_cache(self) or (timeout and info.request(self, timeout * 1000)) - ) and (addresses := info.ip_addresses_by_version(IPVersion.V4Only)): - return str(addresses[0]) + ) and (addresses := info.parsed_scoped_addresses(IPVersion.All)): + return addresses return None class AsyncEsphomeZeroconf(AsyncZeroconf): - async def async_resolve_host(self, host: str, timeout: float = 3.0) -> str | None: + async def async_resolve_host( + self, host: str, timeout: float = 3.0 + ) -> list[str] | None: """Resolve a host name to an IP address.""" info = _make_host_resolver(host) if ( info.load_from_cache(self.zeroconf) or (timeout and await info.async_request(self.zeroconf, timeout * 1000)) - ) and (addresses := info.ip_addresses_by_version(IPVersion.V4Only)): - return str(addresses[0]) + ) and (addresses := info.parsed_scoped_addresses(IPVersion.All)): + return addresses return None diff --git a/platformio.ini b/platformio.ini index e3593bf43f..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 @@ -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..e11e629743 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,14 +9,17 @@ 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 +glyphsets==1.0.0 +pillow==10.4.0 +freetype-py==2.5.1 # esp-idf requires this, but doesn't bundle it by default # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 diff --git a/requirements_optional.txt b/requirements_optional.txt index c984d41332..7416753d55 100644 --- a/requirements_optional.txt +++ b/requirements_optional.txt @@ -1,2 +1 @@ -pillow==10.2.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/ci-custom.py b/script/ci-custom.py index 9a97d3e4a8..81e3da311a 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -58,7 +58,7 @@ file_types = ( ) cpp_include = ("*.h", "*.c", "*.cpp", "*.tcc") py_include = ("*.py",) -ignore_types = (".ico", ".png", ".woff", ".woff2", "", ".ttf", ".otf") +ignore_types = (".ico", ".png", ".woff", ".woff2", "", ".ttf", ".otf", ".pcf") LINT_FILE_CHECKS = [] LINT_CONTENT_CHECKS = [] 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/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/es8311/common.yaml b/tests/components/es8311/common.yaml new file mode 100644 index 0000000000..d833d1c043 --- /dev/null +++ b/tests/components/es8311/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: es8311 diff --git a/tests/components/es8311/test.esp32-ard.yaml b/tests/components/es8311/test.esp32-ard.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/es8311/test.esp32-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/es8311/test.esp32-c3-ard.yaml b/tests/components/es8311/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/es8311/test.esp32-c3-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/es8311/test.esp32-c3-idf.yaml b/tests/components/es8311/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/es8311/test.esp32-c3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/es8311/test.esp32-idf.yaml b/tests/components/es8311/test.esp32-idf.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/es8311/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/es8311/test.esp8266-ard.yaml b/tests/components/es8311/test.esp8266-ard.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/es8311/test.esp8266-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml 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/font/.gitattributes b/tests/components/font/.gitattributes new file mode 100644 index 0000000000..18d9a389e8 --- /dev/null +++ b/tests/components/font/.gitattributes @@ -0,0 +1,2 @@ +*.pcf -text + diff --git a/tests/components/font/MatrixChunky8X.bdf b/tests/components/font/MatrixChunky8X.bdf new file mode 100644 index 0000000000..89b3683180 --- /dev/null +++ b/tests/components/font/MatrixChunky8X.bdf @@ -0,0 +1,7461 @@ +STARTFONT 2.1 +FONT -Trip5-MatrixChunky8X-Medium-R-Normal--8-80-75-75-P-40-ISO10646-1 +SIZE 8 75 75 +FONTBOUNDINGBOX 8 8 -1 0 +COMMENT "Generated by fontforge, http://fontforge.sourceforge.net" +COMMENT "Trip5" +COMMENT "Conventional Chaos" +COMMENT "CC-BY" +STARTPROPERTIES 25 +FOUNDRY "Conventional Chaos" +FAMILY_NAME "MatrixChunky8X" +FONT_NAME "MatrixChunky8X" +FACE_NAME "MatrixChunky8X" +COPYRIGHT "https://github.com/trip5/Matrix-Fonts" +FONT_VERSION "001.000" +WEIGHT_NAME "Medium" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 8 +POINT_SIZE 80 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "P" +AVERAGE_WIDTH 40 +CHARSET_REGISTRY "ISO10646" +CHARSET_ENCODING "1" +CHARSET_COLLECTIONS "ISO8859-2 ISO8859-9 ISO8859-4 ISO10646-1" +FONT_ASCENT 8 +FONT_DESCENT 0 +UNDERLINE_POSITION 0 +UNDERLINE_THICKNESS 1 +X_HEIGHT 6 +CAP_HEIGHT 8 +ENDPROPERTIES +CHARS 535 +STARTCHAR uni0000 +ENCODING 0 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 2 +BITMAP +A0 +00 +40 +00 +A0 +ENDCHAR +STARTCHAR space +ENCODING 32 +SWIDTH 250 0 +DWIDTH 2 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 250 0 +DWIDTH 2 0 +BBX 1 8 0 0 +BITMAP +80 +80 +80 +80 +80 +80 +00 +80 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 2 0 6 +BITMAP +A0 +A0 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +50 +50 +F8 +50 +50 +F8 +50 +50 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +E0 +80 +E0 +20 +20 +E0 +40 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +20 +40 +40 +80 +A0 +A0 +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +E0 +A0 +A0 +40 +B0 +A0 +B0 +D0 +ENDCHAR +STARTCHAR quotesingle +ENCODING 39 +SWIDTH 250 0 +DWIDTH 2 0 +BBX 1 3 0 5 +BITMAP +80 +80 +80 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 1000 0 +DWIDTH 3 0 +BBX 2 8 0 0 +BITMAP +40 +40 +80 +80 +80 +80 +40 +40 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 1000 0 +DWIDTH 3 0 +BBX 2 8 0 0 +BITMAP +80 +80 +40 +40 +40 +40 +80 +80 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 4 0 4 +BITMAP +90 +60 +60 +90 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 3 0 3 +BITMAP +40 +E0 +40 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 1000 0 +DWIDTH 2 0 +BBX 1 2 0 0 +BITMAP +80 +80 +ENDCHAR +STARTCHAR hyphen +ENCODING 45 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 1 0 4 +BITMAP +E0 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 1000 0 +DWIDTH 2 0 +BBX 1 1 0 0 +BITMAP +80 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +20 +40 +40 +40 +80 +80 +80 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +A0 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +C0 +40 +40 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +20 +20 +E0 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +20 +20 +E0 +20 +20 +20 +E0 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +A0 +E0 +20 +20 +20 +20 +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +80 +80 +E0 +20 +20 +20 +E0 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +80 +80 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +20 +20 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +A0 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +A0 +E0 +20 +20 +20 +E0 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 1000 0 +DWIDTH 2 0 +BBX 1 3 0 3 +BITMAP +80 +00 +80 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 1000 0 +DWIDTH 2 0 +BBX 1 4 0 2 +BITMAP +80 +00 +80 +80 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 2 +BITMAP +20 +40 +80 +40 +20 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 3 0 3 +BITMAP +E0 +00 +E0 +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 2 +BITMAP +80 +40 +20 +40 +80 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +20 +60 +40 +40 +00 +40 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +F0 +90 +90 +B0 +B0 +80 +80 +F0 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +A0 +E0 +A0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +A0 +C0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +80 +80 +80 +80 +A0 +E0 +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +C0 +A0 +A0 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +80 +80 +E0 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +80 +80 +E0 +80 +80 +80 +80 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +E0 +80 +80 +B0 +90 +90 +90 +F0 +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +90 +90 +90 +F0 +90 +90 +90 +90 +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +40 +40 +40 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +20 +20 +20 +20 +A0 +A0 +E0 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +A0 +C0 +A0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +80 +80 +80 +80 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +88 +D8 +A8 +A8 +88 +88 +88 +88 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +90 +90 +D0 +B0 +90 +90 +90 +90 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +F0 +90 +90 +90 +90 +90 +90 +F0 +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +A0 +E0 +80 +80 +80 +80 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +F0 +90 +90 +90 +B0 +B0 +A0 +D0 +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +A0 +C0 +A0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +80 +E0 +20 +20 +A0 +E0 +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +A0 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +A0 +A0 +A0 +A0 +E0 +40 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +A8 +A8 +A8 +A8 +A8 +A8 +F8 +50 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +A0 +40 +A0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +A0 +E0 +40 +40 +40 +40 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +20 +20 +40 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +80 +80 +80 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +80 +80 +40 +40 +40 +20 +20 +20 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +20 +20 +20 +20 +20 +20 +E0 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 3 0 5 +BITMAP +40 +E0 +A0 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 1 0 0 +BITMAP +E0 +ENDCHAR +STARTCHAR grave +ENCODING 96 +SWIDTH 1000 0 +DWIDTH 3 0 +BBX 2 2 0 6 +BITMAP +80 +40 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +20 +E0 +A0 +E0 +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +80 +80 +80 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +20 +20 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +A0 +E0 +80 +E0 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +60 +40 +40 +E0 +40 +40 +40 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +A0 +E0 +20 +60 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +80 +80 +80 +E0 +A0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +40 +00 +C0 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +20 +00 +20 +20 +20 +A0 +E0 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +80 +80 +A0 +A0 +C0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +C0 +40 +40 +40 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 5 0 0 +BITMAP +F8 +A8 +A8 +A8 +A8 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +A0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +A0 +E0 +80 +80 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +A0 +E0 +20 +20 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +80 +80 +80 +80 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +80 +E0 +20 +E0 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +40 +40 +E0 +40 +40 +40 +60 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +A0 +A0 +A0 +E0 +40 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 5 0 0 +BITMAP +A8 +A8 +A8 +F8 +50 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +A0 +A0 +40 +A0 +A0 +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +A0 +A0 +E0 +20 +60 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +20 +40 +80 +E0 +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +60 +40 +40 +C0 +40 +40 +40 +60 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 1000 0 +DWIDTH 2 0 +BBX 1 8 0 0 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +C0 +40 +40 +60 +40 +40 +40 +C0 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 2 0 3 +BITMAP +60 +C0 +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 250 0 +DWIDTH 2 0 +BBX 1 8 0 0 +BITMAP +80 +80 +00 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +40 +E0 +80 +80 +80 +E0 +40 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +70 +50 +40 +E0 +40 +40 +40 +F0 +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 6 0 1 +BITMAP +F0 +60 +90 +90 +60 +F0 +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +E0 +40 +E0 +40 +40 +40 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 1000 0 +DWIDTH 2 0 +BBX 1 8 0 0 +BITMAP +80 +80 +80 +00 +80 +80 +80 +80 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +60 +80 +E0 +A0 +A0 +E0 +20 +C0 +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +E0 +A0 +C0 +A0 +A0 +E0 +40 +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 1000 0 +DWIDTH 7 0 +BBX 6 7 0 1 +BITMAP +78 +CC +B4 +A4 +B4 +CC +78 +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 3 +BITMAP +60 +A0 +E0 +00 +E0 +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 3 0 3 +BITMAP +50 +F0 +50 +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +B8 +A8 +20 +20 +20 +28 +28 +38 +ENDCHAR +STARTCHAR uni00AD +ENCODING 173 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 1 0 4 +BITMAP +E0 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 1000 0 +DWIDTH 7 0 +BBX 6 7 0 1 +BITMAP +78 +CC +B4 +A4 +A4 +CC +78 +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +B8 +A0 +20 +38 +20 +20 +20 +20 +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 3 0 5 +BITMAP +E0 +A0 +E0 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 2 +BITMAP +40 +E0 +40 +00 +E0 +ENDCHAR +STARTCHAR uni00B2 +ENCODING 178 +SWIDTH 1000 0 +DWIDTH 3 0 +BBX 2 5 0 3 +BITMAP +C0 +40 +C0 +80 +C0 +ENDCHAR +STARTCHAR uni00B3 +ENCODING 179 +SWIDTH 1000 0 +DWIDTH 3 0 +BBX 2 5 0 3 +BITMAP +C0 +40 +C0 +40 +C0 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 1000 0 +DWIDTH 3 0 +BBX 2 2 0 6 +BITMAP +40 +C0 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 6 0 0 +BITMAP +A0 +A0 +A0 +A0 +E0 +80 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +F0 +D0 +F0 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 1000 0 +DWIDTH 2 0 +BBX 1 1 0 4 +BITMAP +80 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +00 +00 +E0 +00 +00 +00 +E0 +ENDCHAR +STARTCHAR uni00B9 +ENCODING 185 +SWIDTH 1000 0 +DWIDTH 2 0 +BBX 1 5 0 3 +BITMAP +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 5 0 3 +BITMAP +E0 +A0 +E0 +00 +E0 +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 3 0 3 +BITMAP +A0 +F0 +A0 +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +30 +60 +40 +F0 +40 +40 +60 +30 +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +54 +54 +FE +54 +54 +54 +7C +28 +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +50 +10 +F8 +40 +40 +50 +70 +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +00 +40 +40 +C0 +80 +A0 +E0 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +80 +40 +00 +E0 +A0 +E0 +A0 +A0 +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +E0 +A0 +E0 +A0 +A0 +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +A0 +00 +E0 +A0 +E0 +A0 +A0 +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +00 +E0 +A0 +E0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +00 +E0 +A0 +E0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +00 +E0 +A0 +E0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +A0 +A0 +F8 +A0 +A0 +A0 +B8 +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +80 +80 +80 +80 +80 +E0 +40 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +80 +40 +00 +E0 +80 +E0 +80 +E0 +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +E0 +80 +E0 +80 +E0 +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +A0 +00 +E0 +80 +E0 +80 +E0 +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +00 +E0 +80 +E0 +80 +80 +E0 +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +80 +40 +00 +E0 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +E0 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +A0 +00 +E0 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +00 +E0 +40 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +60 +50 +50 +F0 +50 +50 +50 +60 +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +60 +00 +90 +D0 +B0 +90 +90 +90 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +20 +00 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +80 +00 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +A0 +00 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +00 +E0 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +00 +E0 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 3 0 3 +BITMAP +A0 +40 +A0 +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +F0 +90 +90 +B0 +D0 +90 +90 +F0 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +80 +40 +00 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +A0 +00 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +00 +A0 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +A0 +A0 +E0 +40 +40 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +80 +80 +E0 +A0 +A0 +E0 +80 +80 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +C0 +A0 +A0 +E0 +80 +80 +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +20 +00 +E0 +20 +E0 +A0 +E0 +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +80 +00 +E0 +20 +E0 +A0 +E0 +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +A0 +00 +E0 +20 +E0 +A0 +E0 +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +E0 +00 +E0 +20 +E0 +A0 +E0 +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +A0 +00 +E0 +20 +E0 +A0 +E0 +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +40 +00 +E0 +20 +E0 +A0 +E0 +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 5 0 0 +BITMAP +F8 +28 +F8 +A0 +F8 +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +80 +80 +E0 +40 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +20 +00 +E0 +A0 +E0 +80 +E0 +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +80 +00 +E0 +A0 +E0 +80 +E0 +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +A0 +00 +E0 +A0 +E0 +80 +E0 +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +A0 +00 +E0 +A0 +E0 +80 +E0 +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 375 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +80 +40 +00 +C0 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +C0 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +A0 +00 +C0 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +A0 +00 +C0 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +A0 +20 +E0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +E0 +00 +E0 +A0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +80 +40 +00 +E0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +20 +40 +00 +E0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +40 +A0 +00 +E0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 6 0 0 +BITMAP +E0 +00 +E0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 6 0 0 +BITMAP +A0 +00 +E0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 2 +BITMAP +40 +00 +E0 +00 +40 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 5 0 0 +BITMAP +F0 +B0 +D0 +90 +F0 +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +80 +40 +00 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +20 +40 +00 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +40 +A0 +00 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 6 0 0 +BITMAP +A0 +00 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +A0 +A0 +E0 +20 +60 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +80 +80 +80 +E0 +A0 +A0 +E0 +80 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +00 +A0 +A0 +A0 +E0 +20 +60 +ENDCHAR +STARTCHAR Amacron +ENCODING 256 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +00 +E0 +A0 +E0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR amacron +ENCODING 257 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +E0 +00 +E0 +20 +E0 +A0 +E0 +ENDCHAR +STARTCHAR Abreve +ENCODING 258 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +E0 +A0 +E0 +A0 +A0 +ENDCHAR +STARTCHAR abreve +ENCODING 259 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +E0 +20 +E0 +A0 +E0 +ENDCHAR +STARTCHAR Aogonek +ENCODING 260 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 4 8 0 0 +BITMAP +E0 +A0 +A0 +E0 +A0 +A0 +A0 +30 +ENDCHAR +STARTCHAR aogonek +ENCODING 261 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 4 6 0 0 +BITMAP +E0 +20 +E0 +A0 +E0 +30 +ENDCHAR +STARTCHAR Cacute +ENCODING 262 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +80 +00 +E0 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR cacute +ENCODING 263 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +40 +80 +00 +E0 +80 +80 +E0 +ENDCHAR +STARTCHAR Ccircumflex +ENCODING 264 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +A0 +00 +E0 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR ccircumflex +ENCODING 265 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +40 +A0 +00 +E0 +80 +80 +E0 +ENDCHAR +STARTCHAR Cdotaccent +ENCODING 266 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +00 +E0 +80 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR cdotaccent +ENCODING 267 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +40 +00 +E0 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR Ccaron +ENCODING 268 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +E0 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR ccaron +ENCODING 269 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +A0 +40 +00 +E0 +80 +80 +E0 +ENDCHAR +STARTCHAR Dcaron +ENCODING 270 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +C0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR dcaron +ENCODING 271 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +30 +30 +20 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Dcroat +ENCODING 272 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +60 +50 +50 +F0 +50 +50 +50 +70 +ENDCHAR +STARTCHAR dcroat +ENCODING 273 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +20 +70 +20 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Emacron +ENCODING 274 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +00 +E0 +80 +E0 +80 +80 +E0 +ENDCHAR +STARTCHAR emacron +ENCODING 275 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +E0 +00 +E0 +A0 +E0 +80 +E0 +ENDCHAR +STARTCHAR Ebreve +ENCODING 276 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +E0 +80 +E0 +80 +E0 +ENDCHAR +STARTCHAR ebreve +ENCODING 277 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +E0 +A0 +E0 +80 +E0 +ENDCHAR +STARTCHAR Edotaccent +ENCODING 278 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +00 +E0 +80 +E0 +80 +80 +E0 +ENDCHAR +STARTCHAR edotaccent +ENCODING 279 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +40 +00 +E0 +A0 +E0 +80 +E0 +ENDCHAR +STARTCHAR Eogonek +ENCODING 280 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 4 8 0 0 +BITMAP +E0 +80 +80 +E0 +80 +80 +E0 +30 +ENDCHAR +STARTCHAR eogonek +ENCODING 281 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 6 0 0 +BITMAP +E0 +A0 +E0 +80 +E0 +40 +ENDCHAR +STARTCHAR Ecaron +ENCODING 282 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +E0 +80 +E0 +80 +E0 +ENDCHAR +STARTCHAR ecaron +ENCODING 283 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +E0 +A0 +E0 +80 +E0 +ENDCHAR +STARTCHAR Gcircumflex +ENCODING 284 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +40 +A0 +00 +E0 +80 +B0 +90 +F0 +ENDCHAR +STARTCHAR gcircumflex +ENCODING 285 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +A0 +00 +E0 +A0 +E0 +20 +60 +ENDCHAR +STARTCHAR Gbreve +ENCODING 286 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +A0 +40 +00 +E0 +80 +B0 +90 +F0 +ENDCHAR +STARTCHAR gbreve +ENCODING 287 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +E0 +A0 +E0 +20 +60 +ENDCHAR +STARTCHAR Gdotaccent +ENCODING 288 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +40 +00 +E0 +80 +80 +B0 +90 +F0 +ENDCHAR +STARTCHAR gdotaccent +ENCODING 289 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +40 +00 +E0 +A0 +E0 +20 +60 +ENDCHAR +STARTCHAR uni0122 +ENCODING 290 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +E0 +80 +80 +B0 +90 +90 +F0 +40 +ENDCHAR +STARTCHAR uni0123 +ENCODING 291 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +40 +00 +E0 +A0 +E0 +20 +60 +ENDCHAR +STARTCHAR Hcircumflex +ENCODING 292 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +A0 +00 +A0 +A0 +E0 +A0 +A0 +ENDCHAR +STARTCHAR hcircumflex +ENCODING 293 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +A0 +00 +80 +80 +E0 +A0 +A0 +ENDCHAR +STARTCHAR Hbar +ENCODING 294 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +50 +F8 +50 +70 +50 +50 +50 +50 +ENDCHAR +STARTCHAR hbar +ENCODING 295 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +40 +E0 +40 +40 +70 +50 +50 +50 +ENDCHAR +STARTCHAR Itilde +ENCODING 296 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +00 +E0 +40 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR itilde +ENCODING 297 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +E0 +00 +C0 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR Imacron +ENCODING 298 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +00 +E0 +40 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR imacron +ENCODING 299 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +E0 +00 +C0 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR Ibreve +ENCODING 300 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +E0 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR ibreve +ENCODING 301 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +C0 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR Iogonek +ENCODING 302 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +40 +40 +40 +40 +40 +E0 +40 +ENDCHAR +STARTCHAR iogonek +ENCODING 303 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +40 +00 +C0 +40 +40 +E0 +20 +ENDCHAR +STARTCHAR Idotaccent +ENCODING 304 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +00 +E0 +40 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR dotlessi +ENCODING 305 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +C0 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR IJ +ENCODING 306 +SWIDTH 875 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +E4 +44 +44 +44 +44 +54 +54 +FC +ENDCHAR +STARTCHAR ij +ENCODING 307 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 5 7 -1 0 +BITMAP +48 +00 +C8 +48 +48 +68 +F8 +ENDCHAR +STARTCHAR Jcircumflex +ENCODING 308 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +20 +50 +00 +20 +20 +A0 +A0 +E0 +ENDCHAR +STARTCHAR jcircumflex +ENCODING 309 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 7 0 0 +BITMAP +20 +50 +00 +20 +20 +A0 +E0 +ENDCHAR +STARTCHAR uni0136 +ENCODING 310 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +A0 +C0 +A0 +A0 +A0 +40 +ENDCHAR +STARTCHAR uni0137 +ENCODING 311 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +80 +80 +A0 +A0 +C0 +A0 +A0 +40 +ENDCHAR +STARTCHAR kgreenlandic +ENCODING 312 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 6 0 0 +BITMAP +A0 +A0 +C0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR Lacute +ENCODING 313 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +80 +00 +80 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR lacute +ENCODING 314 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +80 +00 +C0 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR uni013B +ENCODING 315 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +80 +80 +80 +80 +80 +80 +E0 +40 +ENDCHAR +STARTCHAR uni013C +ENCODING 316 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +C0 +40 +40 +40 +40 +40 +E0 +40 +ENDCHAR +STARTCHAR Lcaron +ENCODING 317 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +80 +80 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR lcaron +ENCODING 318 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +D0 +50 +40 +40 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR Ldot +ENCODING 319 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +80 +80 +A0 +80 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR ldot +ENCODING 320 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +C0 +40 +60 +40 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR Lslash +ENCODING 321 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +40 +40 +60 +C0 +40 +40 +40 +70 +ENDCHAR +STARTCHAR lslash +ENCODING 322 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +C0 +40 +60 +C0 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR Nacute +ENCODING 323 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +20 +40 +00 +90 +D0 +B0 +90 +90 +ENDCHAR +STARTCHAR nacute +ENCODING 324 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +E0 +A0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR uni0145 +ENCODING 325 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +90 +90 +D0 +B0 +90 +90 +90 +40 +ENDCHAR +STARTCHAR uni0146 +ENCODING 326 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +A0 +A0 +A0 +40 +ENDCHAR +STARTCHAR Ncaron +ENCODING 327 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +A0 +40 +00 +90 +D0 +B0 +90 +90 +ENDCHAR +STARTCHAR ncaron +ENCODING 328 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +E0 +A0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR napostrophe +ENCODING 329 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +80 +80 +00 +70 +50 +50 +50 +50 +ENDCHAR +STARTCHAR Eng +ENCODING 330 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +F0 +90 +90 +90 +90 +90 +90 +20 +ENDCHAR +STARTCHAR eng +ENCODING 331 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 6 0 0 +BITMAP +E0 +A0 +A0 +A0 +A0 +20 +ENDCHAR +STARTCHAR Omacron +ENCODING 332 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +00 +E0 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR omacron +ENCODING 333 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +E0 +00 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Obreve +ENCODING 334 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR obreve +ENCODING 335 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +A0 +40 +00 +E0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Ohungarumlaut +ENCODING 336 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +00 +E0 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR ohungarumlaut +ENCODING 337 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +A0 +00 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR OE +ENCODING 338 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +A0 +A0 +B8 +A0 +A0 +A0 +F8 +ENDCHAR +STARTCHAR oe +ENCODING 339 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 5 0 0 +BITMAP +F8 +A8 +B8 +A0 +F8 +ENDCHAR +STARTCHAR Racute +ENCODING 340 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +E0 +A0 +C0 +A0 +A0 +ENDCHAR +STARTCHAR racute +ENCODING 341 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +E0 +80 +80 +80 +80 +ENDCHAR +STARTCHAR uni0156 +ENCODING 342 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +A0 +C0 +A0 +A0 +A0 +40 +ENDCHAR +STARTCHAR uni0157 +ENCODING 343 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 6 0 0 +BITMAP +E0 +80 +80 +80 +80 +40 +ENDCHAR +STARTCHAR Rcaron +ENCODING 344 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +E0 +A0 +C0 +A0 +A0 +ENDCHAR +STARTCHAR rcaron +ENCODING 345 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +E0 +80 +80 +80 +80 +ENDCHAR +STARTCHAR Sacute +ENCODING 346 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +80 +00 +E0 +80 +E0 +20 +E0 +ENDCHAR +STARTCHAR sacute +ENCODING 347 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +E0 +80 +E0 +20 +E0 +ENDCHAR +STARTCHAR Scircumflex +ENCODING 348 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +A0 +00 +E0 +80 +E0 +20 +E0 +ENDCHAR +STARTCHAR scircumflex +ENCODING 349 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +A0 +00 +E0 +80 +E0 +20 +E0 +ENDCHAR +STARTCHAR Scedilla +ENCODING 350 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +80 +80 +E0 +20 +20 +E0 +40 +ENDCHAR +STARTCHAR scedilla +ENCODING 351 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 6 0 0 +BITMAP +E0 +80 +E0 +20 +E0 +40 +ENDCHAR +STARTCHAR Scaron +ENCODING 352 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +E0 +80 +E0 +20 +E0 +ENDCHAR +STARTCHAR scaron +ENCODING 353 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +E0 +80 +E0 +20 +E0 +ENDCHAR +STARTCHAR uni0162 +ENCODING 354 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +40 +40 +40 +40 +40 +60 +20 +ENDCHAR +STARTCHAR uni0163 +ENCODING 355 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +40 +E0 +40 +40 +40 +60 +20 +ENDCHAR +STARTCHAR Tcaron +ENCODING 356 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +00 +E0 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR tcaron +ENCODING 357 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +50 +50 +40 +E0 +40 +40 +40 +60 +ENDCHAR +STARTCHAR Tbar +ENCODING 358 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +40 +40 +E0 +40 +40 +40 +40 +ENDCHAR +STARTCHAR tbar +ENCODING 359 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +40 +E0 +40 +E0 +40 +40 +60 +ENDCHAR +STARTCHAR Utilde +ENCODING 360 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +00 +A0 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR utilde +ENCODING 361 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +E0 +00 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Umacron +ENCODING 362 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +00 +A0 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR umacron +ENCODING 363 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +E0 +00 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Ubreve +ENCODING 364 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR ubreve +ENCODING 365 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +A0 +40 +00 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Uring +ENCODING 366 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +00 +A0 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR uring +ENCODING 367 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +40 +00 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Uhungarumlaut +ENCODING 368 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +00 +A0 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR uhungarumlaut +ENCODING 369 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +A0 +00 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Uogonek +ENCODING 370 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +A0 +A0 +A0 +A0 +E0 +20 +ENDCHAR +STARTCHAR uogonek +ENCODING 371 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +A0 +A0 +A0 +E0 +20 +ENDCHAR +STARTCHAR Wcircumflex +ENCODING 372 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +20 +50 +00 +A8 +A8 +A8 +F8 +50 +ENDCHAR +STARTCHAR wcircumflex +ENCODING 373 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 7 0 0 +BITMAP +20 +50 +00 +A8 +A8 +F8 +50 +ENDCHAR +STARTCHAR Ycircumflex +ENCODING 374 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +A0 +00 +A0 +A0 +E0 +40 +40 +ENDCHAR +STARTCHAR ycircumflex +ENCODING 375 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +A0 +00 +A0 +A0 +E0 +20 +60 +ENDCHAR +STARTCHAR Ydieresis +ENCODING 376 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +00 +A0 +A0 +E0 +40 +40 +40 +ENDCHAR +STARTCHAR Zacute +ENCODING 377 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +E0 +20 +40 +80 +E0 +ENDCHAR +STARTCHAR zacute +ENCODING 378 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +E0 +20 +40 +80 +E0 +ENDCHAR +STARTCHAR Zdotaccent +ENCODING 379 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +00 +E0 +20 +40 +80 +80 +E0 +ENDCHAR +STARTCHAR zdotaccent +ENCODING 380 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +40 +00 +E0 +20 +40 +80 +E0 +ENDCHAR +STARTCHAR Zcaron +ENCODING 381 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +E0 +20 +40 +80 +E0 +ENDCHAR +STARTCHAR zcaron +ENCODING 382 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +40 +00 +E0 +20 +40 +80 +E0 +ENDCHAR +STARTCHAR longs +ENCODING 383 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR Alphatonos +ENCODING 902 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +B8 +A8 +28 +38 +28 +28 +28 +28 +ENDCHAR +STARTCHAR Epsilontonos +ENCODING 904 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +B8 +A0 +20 +38 +20 +20 +20 +38 +ENDCHAR +STARTCHAR Etatonos +ENCODING 905 +SWIDTH 875 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +A4 +A4 +24 +3C +24 +24 +24 +24 +ENDCHAR +STARTCHAR Iotatonos +ENCODING 906 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +B8 +90 +10 +10 +10 +10 +10 +38 +ENDCHAR +STARTCHAR Omicrontonos +ENCODING 908 +SWIDTH 875 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +BC +A4 +24 +24 +24 +24 +24 +3C +ENDCHAR +STARTCHAR Upsilontonos +ENCODING 910 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +A8 +A8 +28 +38 +10 +10 +10 +10 +ENDCHAR +STARTCHAR Omegatonos +ENCODING 911 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +BE +A2 +22 +22 +22 +36 +14 +36 +ENDCHAR +STARTCHAR Alpha +ENCODING 913 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +A0 +E0 +A0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR Beta +ENCODING 914 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +A0 +C0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR Gamma +ENCODING 915 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR uni0394 +ENCODING 916 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +20 +20 +50 +50 +88 +88 +88 +F8 +ENDCHAR +STARTCHAR Epsilon +ENCODING 917 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +80 +80 +E0 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR Zeta +ENCODING 918 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +20 +20 +40 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR Eta +ENCODING 919 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +90 +90 +90 +F0 +90 +90 +90 +90 +ENDCHAR +STARTCHAR Theta +ENCODING 920 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +F0 +90 +90 +F0 +90 +90 +90 +F0 +ENDCHAR +STARTCHAR Iota +ENCODING 921 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +40 +40 +40 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR Kappa +ENCODING 922 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +A0 +C0 +A0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR Lambda +ENCODING 923 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +20 +20 +50 +50 +50 +88 +88 +88 +ENDCHAR +STARTCHAR Mu +ENCODING 924 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +88 +D8 +A8 +A8 +88 +88 +88 +88 +ENDCHAR +STARTCHAR Nu +ENCODING 925 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +90 +90 +D0 +B0 +90 +90 +90 +90 +ENDCHAR +STARTCHAR Xi +ENCODING 926 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +00 +00 +E0 +00 +00 +00 +E0 +ENDCHAR +STARTCHAR Omicron +ENCODING 927 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +F0 +90 +90 +90 +90 +90 +90 +F0 +ENDCHAR +STARTCHAR Pi +ENCODING 928 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +F0 +90 +90 +90 +90 +90 +90 +90 +ENDCHAR +STARTCHAR Rho +ENCODING 929 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +A0 +E0 +80 +80 +80 +80 +ENDCHAR +STARTCHAR Sigma +ENCODING 931 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +80 +40 +20 +40 +80 +80 +E0 +ENDCHAR +STARTCHAR Tau +ENCODING 932 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR Upsilon +ENCODING 933 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +A0 +E0 +40 +40 +40 +40 +ENDCHAR +STARTCHAR Phi +ENCODING 934 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +20 +F8 +A8 +A8 +A8 +A8 +F8 +20 +ENDCHAR +STARTCHAR Chi +ENCODING 935 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +A0 +40 +A0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR Psi +ENCODING 936 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +A8 +A8 +A8 +F8 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni03A9 +ENCODING 937 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +88 +88 +88 +88 +D8 +50 +D8 +ENDCHAR +STARTCHAR Iotadieresis +ENCODING 938 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +00 +E0 +40 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR Upsilondieresis +ENCODING 939 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +00 +A0 +A0 +E0 +40 +40 +40 +ENDCHAR +STARTCHAR alphatonos +ENCODING 940 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +20 +40 +00 +D0 +A0 +A0 +A0 +D0 +ENDCHAR +STARTCHAR epsilontonos +ENCODING 941 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +E0 +80 +40 +80 +E0 +ENDCHAR +STARTCHAR etatonos +ENCODING 942 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +E0 +A0 +A0 +A0 +20 +ENDCHAR +STARTCHAR iotatonos +ENCODING 943 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +C0 +40 +40 +40 +60 +ENDCHAR +STARTCHAR alpha +ENCODING 945 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 5 0 0 +BITMAP +D0 +A0 +A0 +A0 +D0 +ENDCHAR +STARTCHAR beta +ENCODING 946 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +60 +A0 +A0 +C0 +A0 +A0 +E0 +80 +ENDCHAR +STARTCHAR gamma +ENCODING 947 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 5 0 0 +BITMAP +D0 +50 +70 +20 +20 +ENDCHAR +STARTCHAR delta +ENCODING 948 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +80 +40 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR epsilon +ENCODING 949 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +80 +40 +80 +E0 +ENDCHAR +STARTCHAR zeta +ENCODING 950 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +20 +C0 +80 +80 +80 +E0 +20 +ENDCHAR +STARTCHAR eta +ENCODING 951 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +A0 +A0 +A0 +20 +ENDCHAR +STARTCHAR theta +ENCODING 952 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +A0 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR iota +ENCODING 953 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +C0 +40 +40 +40 +60 +ENDCHAR +STARTCHAR kappa +ENCODING 954 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +A0 +A0 +C0 +A0 +A0 +ENDCHAR +STARTCHAR lambda +ENCODING 955 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +60 +20 +20 +50 +50 +88 +88 +88 +ENDCHAR +STARTCHAR uni03BC +ENCODING 956 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +A0 +A0 +A0 +E0 +80 +ENDCHAR +STARTCHAR nu +ENCODING 957 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +A0 +A0 +A0 +E0 +40 +ENDCHAR +STARTCHAR xi +ENCODING 958 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +80 +E0 +80 +60 +80 +80 +E0 +20 +ENDCHAR +STARTCHAR omicron +ENCODING 959 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR pi +ENCODING 960 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 5 5 0 0 +BITMAP +F8 +50 +50 +50 +58 +ENDCHAR +STARTCHAR rho +ENCODING 961 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +A0 +A0 +E0 +80 +ENDCHAR +STARTCHAR sigma1 +ENCODING 962 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +80 +80 +E0 +20 +ENDCHAR +STARTCHAR sigma +ENCODING 963 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 5 0 0 +BITMAP +F0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR tau +ENCODING 964 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +40 +40 +40 +60 +ENDCHAR +STARTCHAR upsilon +ENCODING 965 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR phi +ENCODING 966 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 5 0 0 +BITMAP +B8 +A8 +A8 +F8 +20 +ENDCHAR +STARTCHAR chi +ENCODING 967 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +A0 +A0 +40 +A0 +A0 +ENDCHAR +STARTCHAR psi +ENCODING 968 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 5 0 0 +BITMAP +A8 +A8 +A8 +F8 +20 +ENDCHAR +STARTCHAR omega +ENCODING 969 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 5 0 0 +BITMAP +88 +A8 +A8 +F8 +50 +ENDCHAR +STARTCHAR iotadieresis +ENCODING 970 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +A0 +00 +C0 +40 +40 +40 +60 +ENDCHAR +STARTCHAR upsilondieresis +ENCODING 971 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +A0 +00 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR omicrontonos +ENCODING 972 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR upsilontonos +ENCODING 973 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +20 +40 +00 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR omegatonos +ENCODING 974 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +10 +20 +00 +88 +A8 +A8 +F8 +50 +ENDCHAR +STARTCHAR uni0401 +ENCODING 1025 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +00 +E0 +80 +E0 +80 +80 +E0 +ENDCHAR +STARTCHAR uni0404 +ENCODING 1028 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +70 +80 +80 +E0 +80 +80 +80 +70 +ENDCHAR +STARTCHAR uni0406 +ENCODING 1030 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +40 +40 +40 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR uni0407 +ENCODING 1031 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +00 +E0 +40 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR uni040E +ENCODING 1038 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +00 +A0 +A0 +E0 +20 +20 +60 +ENDCHAR +STARTCHAR uni0410 +ENCODING 1040 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +A0 +E0 +A0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR uni0411 +ENCODING 1041 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +80 +80 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR uni0412 +ENCODING 1042 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +A0 +C0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR uni0413 +ENCODING 1043 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR uni0414 +ENCODING 1044 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +30 +50 +50 +50 +50 +50 +F8 +88 +ENDCHAR +STARTCHAR uni0415 +ENCODING 1045 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +80 +80 +E0 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR uni0416 +ENCODING 1046 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +A8 +A8 +A8 +F8 +A8 +A8 +A8 +A8 +ENDCHAR +STARTCHAR uni0417 +ENCODING 1047 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +20 +40 +20 +20 +A0 +E0 +ENDCHAR +STARTCHAR uni0418 +ENCODING 1048 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +88 +88 +98 +A8 +C8 +88 +88 +88 +ENDCHAR +STARTCHAR uni0419 +ENCODING 1049 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +A8 +88 +98 +A8 +C8 +88 +88 +88 +ENDCHAR +STARTCHAR uni041A +ENCODING 1050 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +A0 +C0 +A0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR uni041B +ENCODING 1051 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +30 +50 +50 +50 +50 +50 +50 +D0 +ENDCHAR +STARTCHAR uni041C +ENCODING 1052 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +88 +D8 +A8 +A8 +88 +88 +88 +88 +ENDCHAR +STARTCHAR uni041D +ENCODING 1053 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +90 +90 +90 +F0 +90 +90 +90 +90 +ENDCHAR +STARTCHAR uni041E +ENCODING 1054 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +F0 +90 +90 +90 +90 +90 +90 +F0 +ENDCHAR +STARTCHAR uni041F +ENCODING 1055 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +F0 +90 +90 +90 +90 +90 +90 +90 +ENDCHAR +STARTCHAR uni0420 +ENCODING 1056 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +A0 +E0 +80 +80 +80 +80 +ENDCHAR +STARTCHAR uni0421 +ENCODING 1057 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +80 +80 +80 +80 +A0 +E0 +ENDCHAR +STARTCHAR uni0422 +ENCODING 1058 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR uni0423 +ENCODING 1059 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +90 +90 +90 +F0 +10 +10 +10 +70 +ENDCHAR +STARTCHAR uni0424 +ENCODING 1060 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +20 +F8 +A8 +A8 +A8 +A8 +F8 +20 +ENDCHAR +STARTCHAR uni0425 +ENCODING 1061 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +A0 +40 +A0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR uni0426 +ENCODING 1062 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +A0 +A0 +A0 +A0 +A0 +A0 +A0 +F0 +ENDCHAR +STARTCHAR uni0427 +ENCODING 1063 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +A0 +E0 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni0428 +ENCODING 1064 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +A8 +A8 +A8 +A8 +A8 +A8 +A8 +F8 +ENDCHAR +STARTCHAR uni0429 +ENCODING 1065 +SWIDTH 1000 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +A8 +A8 +A8 +A8 +A8 +A8 +A8 +FC +ENDCHAR +STARTCHAR uni042A +ENCODING 1066 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +C0 +40 +40 +70 +50 +50 +50 +70 +ENDCHAR +STARTCHAR uni042B +ENCODING 1067 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +88 +88 +88 +E8 +A8 +A8 +A8 +E8 +ENDCHAR +STARTCHAR uni042C +ENCODING 1068 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +80 +80 +80 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR uni042D +ENCODING 1069 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +E0 +10 +10 +70 +10 +10 +10 +E0 +ENDCHAR +STARTCHAR uni042E +ENCODING 1070 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +B8 +A8 +A8 +E8 +A8 +A8 +A8 +B8 +ENDCHAR +STARTCHAR uni042F +ENCODING 1071 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +A0 +A0 +60 +A0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR uni0430 +ENCODING 1072 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +20 +E0 +A0 +E0 +ENDCHAR +STARTCHAR uni0431 +ENCODING 1073 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +60 +80 +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR uni0432 +ENCODING 1074 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +A0 +C0 +A0 +E0 +ENDCHAR +STARTCHAR uni0433 +ENCODING 1075 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +80 +80 +80 +80 +ENDCHAR +STARTCHAR uni0434 +ENCODING 1076 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 5 5 0 0 +BITMAP +30 +50 +50 +F8 +88 +ENDCHAR +STARTCHAR uni0435 +ENCODING 1077 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +A0 +E0 +80 +E0 +ENDCHAR +STARTCHAR uni0436 +ENCODING 1078 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 5 0 0 +BITMAP +A8 +A8 +F8 +A8 +A8 +ENDCHAR +STARTCHAR uni0437 +ENCODING 1079 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +20 +40 +20 +E0 +ENDCHAR +STARTCHAR uni0438 +ENCODING 1080 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 5 0 0 +BITMAP +90 +B0 +D0 +90 +90 +ENDCHAR +STARTCHAR uni0439 +ENCODING 1081 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 7 0 0 +BITMAP +60 +00 +90 +B0 +D0 +90 +90 +ENDCHAR +STARTCHAR uni043A +ENCODING 1082 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +A0 +A0 +C0 +A0 +A0 +ENDCHAR +STARTCHAR uni043B +ENCODING 1083 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 5 0 0 +BITMAP +30 +50 +50 +50 +D0 +ENDCHAR +STARTCHAR uni043C +ENCODING 1084 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 5 0 0 +BITMAP +88 +D8 +A8 +88 +88 +ENDCHAR +STARTCHAR uni043D +ENCODING 1085 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +A0 +A0 +E0 +A0 +A0 +ENDCHAR +STARTCHAR uni043E +ENCODING 1086 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR uni043F +ENCODING 1087 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +A0 +A0 +A0 +A0 +ENDCHAR +STARTCHAR uni0440 +ENCODING 1088 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +A0 +E0 +80 +80 +ENDCHAR +STARTCHAR uni0441 +ENCODING 1089 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +80 +80 +80 +E0 +ENDCHAR +STARTCHAR uni0442 +ENCODING 1090 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +40 +40 +40 +40 +ENDCHAR +STARTCHAR uni0443 +ENCODING 1091 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +A0 +A0 +E0 +20 +60 +ENDCHAR +STARTCHAR uni0444 +ENCODING 1092 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +20 +20 +20 +F8 +A8 +A8 +F8 +20 +ENDCHAR +STARTCHAR uni0445 +ENCODING 1093 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +A0 +A0 +40 +A0 +A0 +ENDCHAR +STARTCHAR uni0446 +ENCODING 1094 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 5 0 0 +BITMAP +A0 +A0 +A0 +A0 +F0 +ENDCHAR +STARTCHAR uni0447 +ENCODING 1095 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +A0 +A0 +E0 +20 +20 +ENDCHAR +STARTCHAR uni0448 +ENCODING 1096 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 5 0 0 +BITMAP +A8 +A8 +A8 +A8 +F8 +ENDCHAR +STARTCHAR uni0449 +ENCODING 1097 +SWIDTH 1000 0 +DWIDTH 7 0 +BBX 6 5 0 0 +BITMAP +A8 +A8 +A8 +A8 +FC +ENDCHAR +STARTCHAR uni044A +ENCODING 1098 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 5 0 0 +BITMAP +C0 +40 +70 +50 +70 +ENDCHAR +STARTCHAR uni044B +ENCODING 1099 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 5 0 0 +BITMAP +88 +88 +E8 +A8 +E8 +ENDCHAR +STARTCHAR uni044C +ENCODING 1100 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +80 +80 +E0 +A0 +E0 +ENDCHAR +STARTCHAR uni044D +ENCODING 1101 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +C0 +20 +E0 +20 +C0 +ENDCHAR +STARTCHAR uni044E +ENCODING 1102 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 5 0 0 +BITMAP +B8 +A8 +E8 +A8 +B8 +ENDCHAR +STARTCHAR uni044F +ENCODING 1103 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +E0 +A0 +60 +A0 +A0 +ENDCHAR +STARTCHAR uni0451 +ENCODING 1105 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +A0 +00 +E0 +A0 +E0 +80 +E0 +ENDCHAR +STARTCHAR uni0454 +ENCODING 1108 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 5 0 0 +BITMAP +60 +80 +E0 +80 +60 +ENDCHAR +STARTCHAR uni0456 +ENCODING 1110 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +40 +00 +C0 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR uni0457 +ENCODING 1111 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +A0 +00 +C0 +40 +40 +40 +E0 +ENDCHAR +STARTCHAR uni045E +ENCODING 1118 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +40 +00 +A0 +A0 +E0 +20 +60 +ENDCHAR +STARTCHAR uni0490 +ENCODING 1168 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +10 +E0 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR uni0491 +ENCODING 1169 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 6 0 0 +BITMAP +20 +C0 +80 +80 +80 +80 +ENDCHAR +STARTCHAR uni2002 +ENCODING 8194 +SWIDTH 375 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2003 +ENCODING 8195 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2009 +ENCODING 8201 +SWIDTH 1000 0 +DWIDTH 1 0 +BBX 1 1 6 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2010 +ENCODING 8208 +SWIDTH 1000 0 +DWIDTH 1 0 +BBX 1 1 0 4 +BITMAP +80 +ENDCHAR +STARTCHAR endash +ENCODING 8211 +SWIDTH 1000 0 +DWIDTH 3 0 +BBX 2 1 0 4 +BITMAP +C0 +ENDCHAR +STARTCHAR emdash +ENCODING 8212 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 1 0 4 +BITMAP +F0 +ENDCHAR +STARTCHAR uni2015 +ENCODING 8213 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 4 1 0 4 +BITMAP +F0 +ENDCHAR +STARTCHAR bullet +ENCODING 8226 +SWIDTH 1000 0 +DWIDTH 2 0 +BBX 1 1 0 4 +BITMAP +80 +ENDCHAR +STARTCHAR colonmonetary +ENCODING 8353 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +10 +F0 +A0 +A0 +A0 +A0 +F0 +40 +ENDCHAR +STARTCHAR uni20A2 +ENCODING 8354 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +F0 +80 +80 +B0 +A0 +A0 +A0 +F0 +ENDCHAR +STARTCHAR uni20A6 +ENCODING 8358 +SWIDTH 875 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +48 +48 +EC +58 +CC +48 +48 +48 +ENDCHAR +STARTCHAR uni20A9 +ENCODING 8361 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +54 +54 +FE +54 +54 +54 +7C +28 +ENDCHAR +STARTCHAR uni20AA +ENCODING 8362 +SWIDTH 875 0 +DWIDTH 7 0 +BBX 6 6 0 0 +BITMAP +F4 +94 +B4 +B4 +A4 +BC +ENDCHAR +STARTCHAR dong +ENCODING 8363 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +20 +70 +20 +E0 +A0 +E0 +00 +E0 +ENDCHAR +STARTCHAR Euro +ENCODING 8364 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +30 +60 +40 +F0 +40 +40 +60 +30 +ENDCHAR +STARTCHAR uni20AD +ENCODING 8365 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +50 +50 +60 +F0 +60 +50 +50 +50 +ENDCHAR +STARTCHAR uni20AE +ENCODING 8366 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +40 +60 +40 +C0 +40 +40 +40 +ENDCHAR +STARTCHAR uni20B1 +ENCODING 8369 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +50 +70 +40 +40 +40 +40 +ENDCHAR +STARTCHAR uni20B2 +ENCODING 8370 +SWIDTH 1000 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +40 +E0 +80 +B0 +90 +90 +F0 +40 +ENDCHAR +STARTCHAR uni20B4 +ENCODING 8372 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +50 +10 +F8 +40 +50 +50 +70 +ENDCHAR +STARTCHAR uni20B5 +ENCODING 8373 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 7 0 0 +BITMAP +40 +E0 +80 +80 +80 +E0 +40 +ENDCHAR +STARTCHAR uni20B8 +ENCODING 8376 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +E0 +00 +E0 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR uni20B9 +ENCODING 8377 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +F0 +20 +F0 +80 +40 +20 +10 +10 +ENDCHAR +STARTCHAR uni20BA +ENCODING 8378 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +E0 +40 +E0 +40 +40 +50 +50 +70 +ENDCHAR +STARTCHAR uni20BC +ENCODING 8380 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 7 0 0 +BITMAP +20 +20 +F8 +A8 +A8 +A8 +A8 +ENDCHAR +STARTCHAR uni20BD +ENCODING 8381 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +70 +50 +70 +40 +E0 +40 +40 +40 +ENDCHAR +STARTCHAR uni20BE +ENCODING 8382 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +20 +F8 +A8 +A8 +A0 +80 +40 +F8 +ENDCHAR +STARTCHAR uni20BF +ENCODING 8383 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +40 +E0 +A0 +C0 +A0 +A0 +E0 +40 +ENDCHAR +STARTCHAR uni20C0 +ENCODING 8384 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 3 6 0 0 +BITMAP +E0 +80 +80 +E0 +00 +E0 +ENDCHAR +STARTCHAR uni2103 +ENCODING 8451 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +B8 +A8 +20 +20 +20 +20 +28 +38 +ENDCHAR +STARTCHAR uni2109 +ENCODING 8457 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +B8 +A0 +20 +38 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2460 +ENCODING 9312 +SWIDTH 125 0 +DWIDTH 1 0 +BBX 1 1 4 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2461 +ENCODING 9313 +SWIDTH 250 0 +DWIDTH 2 0 +BBX 1 1 1 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2462 +ENCODING 9314 +SWIDTH 375 0 +DWIDTH 3 0 +BBX 1 1 3 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2463 +ENCODING 9315 +SWIDTH 500 0 +DWIDTH 4 0 +BBX 1 1 4 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2464 +ENCODING 9316 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 1 1 4 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2465 +ENCODING 9317 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 1 1 1 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2466 +ENCODING 9318 +SWIDTH 875 0 +DWIDTH 7 0 +BBX 1 1 3 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2467 +ENCODING 9319 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 1 1 4 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2468 +ENCODING 9320 +SWIDTH 1125 0 +DWIDTH 9 0 +BBX 1 1 4 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2469 +ENCODING 9321 +SWIDTH 1250 0 +DWIDTH 10 0 +BBX 1 1 4 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni24EA +ENCODING 9450 +SWIDTH 0 0 +DWIDTH 0 0 +BBX 1 1 3 0 +BITMAP +00 +ENDCHAR +STARTCHAR H22073 +ENCODING 9633 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 6 0 1 +BITMAP +E0 +A0 +A0 +A0 +A0 +E0 +ENDCHAR +STARTCHAR uni4E00 +ENCODING 19968 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 2 0 3 +BITMAP +04 +FE +ENDCHAR +STARTCHAR uni4E03 +ENCODING 19971 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +20 +20 +2E +F0 +20 +20 +22 +1E +ENDCHAR +STARTCHAR uni4E09 +ENCODING 19977 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +7C +00 +00 +38 +00 +00 +04 +FE +ENDCHAR +STARTCHAR uni4E0A +ENCODING 19978 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +40 +40 +70 +40 +40 +40 +40 +F0 +ENDCHAR +STARTCHAR uni4E0B +ENCODING 19979 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 4 8 0 0 +BITMAP +F0 +40 +60 +50 +40 +40 +40 +40 +ENDCHAR +STARTCHAR uni4E5D +ENCODING 20061 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +20 +F8 +28 +28 +48 +48 +4A +8E +ENDCHAR +STARTCHAR uni4E8C +ENCODING 20108 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 6 0 1 +BITMAP +7C +00 +00 +00 +04 +FE +ENDCHAR +STARTCHAR uni4E94 +ENCODING 20116 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +7C +10 +10 +7C +24 +24 +24 +FE +ENDCHAR +STARTCHAR uni516B +ENCODING 20843 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +28 +28 +28 +28 +44 +44 +44 +82 +ENDCHAR +STARTCHAR uni516D +ENCODING 20845 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +10 +FE +00 +28 +28 +44 +44 +82 +ENDCHAR +STARTCHAR uni5341 +ENCODING 21313 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +10 +10 +FE +10 +10 +10 +10 +10 +ENDCHAR +STARTCHAR uni5348 +ENCODING 21320 +SWIDTH 625 0 +DWIDTH 5 0 +BBX 5 8 0 0 +BITMAP +40 +70 +A0 +20 +F8 +20 +20 +20 +ENDCHAR +STARTCHAR uni56DB +ENCODING 22235 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +FE +AA +AA +AE +C2 +82 +FE +82 +ENDCHAR +STARTCHAR uni5929 +ENCODING 22825 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +7C +10 +10 +FE +10 +10 +28 +C6 +ENDCHAR +STARTCHAR uni661F +ENCODING 26143 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +FC +84 +FC +5E +90 +7C +10 +FE +ENDCHAR +STARTCHAR uni6708 +ENCODING 26376 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +3E +22 +3E +22 +3E +22 +42 +86 +ENDCHAR +STARTCHAR uni671F +ENCODING 26399 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +5E +FA +5E +7A +5E +EA +12 +A6 +ENDCHAR +STARTCHAR uniAE08 +ENCODING 44552 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +08 +00 +F8 +00 +F8 +88 +F8 +ENDCHAR +STARTCHAR uniBAA9 +ENCODING 47785 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +88 +F8 +20 +F8 +00 +F8 +08 +ENDCHAR +STARTCHAR uniC218 +ENCODING 49688 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +20 +20 +50 +88 +00 +F8 +20 +20 +ENDCHAR +STARTCHAR uniC624 +ENCODING 50724 +SWIDTH 750 0 +DWIDTH 6 0 +BBX 5 7 0 1 +BITMAP +70 +88 +88 +70 +20 +20 +F8 +ENDCHAR +STARTCHAR uniC694 +ENCODING 50836 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 7 0 1 +BITMAP +70 +88 +88 +70 +50 +50 +F8 +ENDCHAR +STARTCHAR uniC6D4 +ENCODING 50900 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +48 +A8 +48 +E8 +58 +38 +C0 +F8 +ENDCHAR +STARTCHAR uniC77C +ENCODING 51068 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +48 +A8 +48 +00 +F8 +38 +C0 +F8 +ENDCHAR +STARTCHAR uniC804 +ENCODING 51204 +SWIDTH 875 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F4 +24 +4C +A4 +94 +44 +40 +7C +ENDCHAR +STARTCHAR uniD1A0 +ENCODING 53664 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 7 0 1 +BITMAP +F8 +80 +F0 +80 +F8 +20 +F8 +ENDCHAR +STARTCHAR uniD654 +ENCODING 54868 +SWIDTH 1000 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +24 +FC +54 +56 +24 +24 +FC +04 +ENDCHAR +STARTCHAR uniD6C4 +ENCODING 54980 +SWIDTH 1000 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +20 +F8 +50 +20 +00 +F8 +20 +20 +ENDCHAR +STARTCHAR uniFFE5 +ENCODING 65509 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +A0 +A0 +E0 +40 +E0 +40 +40 +40 +ENDCHAR +STARTCHAR uniFFFD +ENCODING 65533 +SWIDTH 1000 0 +DWIDTH 4 0 +BBX 3 6 0 1 +BITMAP +A0 +A0 +40 +A0 +A0 +A0 +ENDCHAR +ENDFONT diff --git a/tests/components/font/common.yaml b/tests/components/font/common.yaml index a81457a05d..5be9faf5be 100644 --- a/tests/components/font/common.yaml +++ b/tests/components/font/common.yaml @@ -1,4 +1,12 @@ font: + - file: + type: gfonts + family: "Roboto" + weight: bold + italic: true + size: 32 + id: roboto32 + - file: "gfonts://Roboto" id: roboto size: 20 @@ -9,6 +17,10 @@ font: - file: "gfonts://Roboto" id: roboto_web size: 20 + - file: "gfonts://Roboto" + id: roboto_greek + size: 20 + glyphs: ["\u0300", "\u00C5", "\U000000C7"] - file: "https://github.com/IdreesInc/Monocraft/releases/download/v3.0/Monocraft.ttf" id: monocraft size: 20 @@ -20,6 +32,17 @@ font: - file: $component_dir/Monocraft.ttf id: monocraft3 size: 28 + - file: $component_dir/MatrixChunky8X.bdf + id: special_font + glyphs: + - '"' + - "'" + - '#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz°' + + - file: $component_dir/MatrixChunky8X.bdf + id: default_font + - file: $component_dir/x11.pcf + id: pcf_font i2c: scl: ${i2c_scl} @@ -36,3 +59,4 @@ display: it.print(0, 40, id(monocraft), "Hello, World!"); it.print(0, 60, id(monocraft2), "Hello, World!"); it.print(0, 80, id(monocraft3), "Hello, World!"); + it.print(0, 100, id(roboto_greek), "Hello κόσμε!"); diff --git a/tests/components/font/test.host.yaml b/tests/components/font/test.host.yaml index 017328ec83..c5399f2826 100644 --- a/tests/components/font/test.host.yaml +++ b/tests/components/font/test.host.yaml @@ -1,4 +1,12 @@ font: + - file: + type: gfonts + family: "Roboto" + weight: bold + italic: true + size: 32 + id: roboto32 + - file: "gfonts://Roboto" id: roboto size: 20 @@ -9,6 +17,10 @@ font: - file: "gfonts://Roboto" id: roboto_web size: 20 + - file: "gfonts://Roboto" + id: roboto_greek + size: 20 + glyphs: ["\u0300", "\u00C5", "\U000000C7"] - file: "https://github.com/IdreesInc/Monocraft/releases/download/v3.0/Monocraft.ttf" id: monocraft size: 20 @@ -20,4 +32,26 @@ font: - file: $component_dir/Monocraft.ttf id: monocraft3 size: 28 + - file: $component_dir/MatrixChunky8X.bdf + id: special_font + glyphs: + - '"' + - "'" + - '#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz°' + - file: $component_dir/MatrixChunky8X.bdf + id: default_font + +display: + - platform: sdl + id: sdl_display + dimensions: + width: 800 + height: 600 + lambda: |- + it.print(0, 0, id(roboto), "Hello, World!"); + it.print(0, 20, id(roboto_web), "Hello, World!"); + it.print(0, 40, id(roboto_greek), "Hello κόσμε!"); + it.print(0, 60, id(monocraft), "Hello, World!"); + it.print(0, 80, id(monocraft2), "Hello, World!"); + it.print(0, 100, id(monocraft3), "Hello, World!"); diff --git a/tests/components/font/x11.pcf b/tests/components/font/x11.pcf new file mode 100644 index 0000000000..19a38d4e39 Binary files /dev/null and b/tests/components/font/x11.pcf differ 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/http_request/common.yaml b/tests/components/http_request/common.yaml index 589b7fb4b4..593b85e435 100644 --- a/tests/components/http_request/common.yaml +++ b/tests/components/http_request/common.yaml @@ -12,6 +12,8 @@ esphome: url: https://esphome.io headers: Content-Type: application/json + on_error: + logger.log: "Request failed" on_response: then: - logger.log: 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/lvgl/common.yaml b/tests/components/lvgl/common.yaml index 7ef7772ac9..c7d635db1c 100644 --- a/tests/components/lvgl/common.yaml +++ b/tests/components/lvgl/common.yaml @@ -4,56 +4,18 @@ touchscreen: display: tft_display update_interval: 50ms threshold: 1 - calibration: - x_max: 240 - y_max: 320 font: - file: "$component_dir/roboto.ttf" id: roboto20 size: 20 - extras: - - file: '$component_dir/materialdesignicons-webfont.ttf' - glyphs: [ - "\U000F004B", - "\U0000f0ed", - "\U000F006E", - "\U000F012C", - "\U000F179B", - "\U000F0748", - "\U000F1A1B", - "\U000F02DC", - "\U000F0A02", - "\U000F035F", - "\U000F0156", - "\U000F0C5F", - "\U000f0084", - "\U000f0091", - ] + - file: "$component_dir/helvetica.ttf" id: helvetica20 - file: "$component_dir/roboto.ttf" id: roboto10 size: 10 bpp: 4 - extras: - - file: '$component_dir/materialdesignicons-webfont.ttf' - glyphs: [ - "\U000F004B", - "\U0000f0ed", - "\U000F006E", - "\U000F012C", - "\U000F179B", - "\U000F0748", - "\U000F1A1B", - "\U000F02DC", - "\U000F0A02", - "\U000F035F", - "\U000F0156", - "\U000F0C5F", - "\U000f0084", - "\U000f0091", - ] sensor: - platform: lvgl @@ -93,7 +55,7 @@ light: - platform: lvgl name: LVGL LED id: lv_light - led: lv_led + widget: lv_led binary_sensor: - platform: lvgl @@ -127,6 +89,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 +102,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 9d157ea5b0..db0443b3bb 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -1,5 +1,29 @@ +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" + +binary_sensor: + - id: enter_sensor + platform: template + - id: left_sensor + platform: template + 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: color_id disp_bg_image: cat_image @@ -38,8 +62,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] @@ -67,11 +91,18 @@ 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 + keypads: + - initial_focus: button_button + enter: enter_sensor + next: left_sensor msgboxes: - id: message_box @@ -104,6 +135,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" @@ -117,6 +150,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 @@ -135,6 +181,10 @@ 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 @@ -220,9 +270,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] @@ -279,6 +333,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 @@ -375,9 +436,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 @@ -406,6 +468,18 @@ 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 @@ -416,7 +490,7 @@ lvgl: bg_opa: transp knob: radius: 1 - width: 4 + width: "4" height: 10% bg_color: 0x000000 width: 100% @@ -596,15 +670,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 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..34918cb113 --- /dev/null +++ b/tests/components/lvgl/test.host.yaml @@ -0,0 +1,43 @@ +display: + - platform: sdl + id: sdl0 + auto_clear_enabled: false + dimensions: + width: 480 + height: 320 + - platform: sdl + id: sdl1 + auto_clear_enabled: false + dimensions: + width: 480 + height: 480 + +touchscreen: + - platform: sdl + display: sdl0 + sdl_id: sdl0 + +lvgl: + - id: lvgl_0 + displays: sdl0 + - id: lvgl_1 + displays: sdl1 + on_idle: + timeout: 8s + then: + if: + condition: + lvgl.is_idle: + lvgl_id: lvgl_1 + timeout: 5s + then: + logger.log: Lvgl2 is idle + widgets: + - button: + align: center + widgets: + - label: + text: Click ME + on_click: + logger.log: Clicked + 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/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/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..d22fe9579f 100644 --- a/tests/components/mqtt/common.yaml +++ b/tests/components/mqtt/common.yaml @@ -10,6 +10,8 @@ mqtt: port: 1883 username: debug password: debug + enable_on_boot: false + clean_session: True client_id: someclient use_abbreviations: false discovery: true @@ -86,6 +88,8 @@ button: state_topic: some/topic/button qos: 2 on_press: + - mqtt.disable + - mqtt.enable - mqtt.publish: topic: some/topic/button payload: Hello @@ -199,6 +203,10 @@ climate: fan_only_cooling: true fan_with_cooling: true fan_with_heating: true + visual: + temperature_step: + target_temperature: 0.1 + current_temperature: 0.1 cover: - platform: template @@ -225,7 +233,9 @@ datetime: id: test_date type: date state_topic: some/topic/date + command_topic: test_date/custom_command_topic 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/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..68ef2a2f58 100644 --- a/tests/components/prometheus/common.yaml +++ b/tests/components/prometheus/common.yaml @@ -1,3 +1,8 @@ +esphome: + name: livingroomdevice + friendly_name: Living Room Device + area: Living Room + wifi: ssid: MySSID password: password1 @@ -13,9 +18,72 @@ sensor: } update_interval: 60s +text_sensor: + - platform: version + name: "ESPHome Version" + hide_timestamp: true + - platform: template + id: template_text_sensor1 + lambda: |- + if (millis() > 10000) { + return {"Hello World"}; + } else { + return {"Goodbye (cruel) World"}; + } + update_interval: 60s + +binary_sensor: + - platform: template + id: template_binary_sensor1 + lambda: |- + if (millis() > 10000) { + return true; + } else { + return false; + } + +switch: + - platform: template + id: template_switch1 + lambda: |- + if (millis() > 10000) { + return true; + } else { + return false; + } + optimistic: true + +fan: + - platform: template + id: template_fan1 + +cover: + - platform: template + id: template_cover1 + lambda: |- + if (millis() > 10000) { + return COVER_OPEN; + } else { + return COVER_CLOSED; + } + +lock: + - platform: template + id: template_lock1 + lambda: |- + if (millis() > 10000) { + return LOCK_STATE_LOCKED; + } else { + return LOCK_STATE_UNLOCKED; + } + optimistic: true + 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 ab20f36eb6..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: diff --git a/tests/components/speaker/test.esp32-c3-ard.yaml b/tests/components/speaker/test.esp32-c3-ard.yaml index c966f9daa7..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: diff --git a/tests/components/speaker/test.esp32-c3-idf.yaml b/tests/components/speaker/test.esp32-c3-idf.yaml index c966f9daa7..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: diff --git a/tests/components/speaker/test.esp32-idf.yaml b/tests/components/speaker/test.esp32-idf.yaml index ab20f36eb6..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,8 +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 + i2s_dout_pin: 14 diff --git a/tests/components/spi_device/test.esp32-ard.yaml b/tests/components/spi_device/test.esp32-ard.yaml index cad8ca49f8..b539cb3ec4 100644 --- a/tests/components/spi_device/test.esp32-ard.yaml +++ b/tests/components/spi_device/test.esp32-ard.yaml @@ -7,5 +7,5 @@ spi: spi_device: id: spi_device_test data_rate: 2MHz - mode: 3 + spi_mode: 3 bit_order: lsb_first diff --git a/tests/components/spi_device/test.esp32-c3-ard.yaml b/tests/components/spi_device/test.esp32-c3-ard.yaml index 49e2733676..99c0ac1ebb 100644 --- a/tests/components/spi_device/test.esp32-c3-ard.yaml +++ b/tests/components/spi_device/test.esp32-c3-ard.yaml @@ -7,5 +7,5 @@ spi: spi_device: id: spi_device_test data_rate: 2MHz - mode: 3 + spi_mode: 3 bit_order: lsb_first diff --git a/tests/components/spi_device/test.esp32-c3-idf.yaml b/tests/components/spi_device/test.esp32-c3-idf.yaml index 49e2733676..99c0ac1ebb 100644 --- a/tests/components/spi_device/test.esp32-c3-idf.yaml +++ b/tests/components/spi_device/test.esp32-c3-idf.yaml @@ -7,5 +7,5 @@ spi: spi_device: id: spi_device_test data_rate: 2MHz - mode: 3 + spi_mode: 3 bit_order: lsb_first diff --git a/tests/components/spi_device/test.esp32-idf.yaml b/tests/components/spi_device/test.esp32-idf.yaml index cad8ca49f8..b539cb3ec4 100644 --- a/tests/components/spi_device/test.esp32-idf.yaml +++ b/tests/components/spi_device/test.esp32-idf.yaml @@ -7,5 +7,5 @@ spi: spi_device: id: spi_device_test data_rate: 2MHz - mode: 3 + spi_mode: 3 bit_order: lsb_first diff --git a/tests/components/spi_device/test.esp8266-ard.yaml b/tests/components/spi_device/test.esp8266-ard.yaml index 1b191bdb6a..988825ce2d 100644 --- a/tests/components/spi_device/test.esp8266-ard.yaml +++ b/tests/components/spi_device/test.esp8266-ard.yaml @@ -7,5 +7,5 @@ spi: spi_device: id: spi_device_test data_rate: 2MHz - mode: 3 + spi_mode: 3 bit_order: lsb_first diff --git a/tests/components/spi_device/test.rp2040-ard.yaml b/tests/components/spi_device/test.rp2040-ard.yaml index c70493c70d..6020643f21 100644 --- a/tests/components/spi_device/test.rp2040-ard.yaml +++ b/tests/components/spi_device/test.rp2040-ard.yaml @@ -7,5 +7,5 @@ spi: spi_device: id: spi_device_test data_rate: 2MHz - mode: 3 + spi_mode: 3 bit_order: lsb_first 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..79201fbe07 100644 --- a/tests/components/template/common.yaml +++ b/tests/components/template/common.yaml @@ -9,6 +9,25 @@ sensor: return 0.0; } update_interval: 60s + filters: + - offset: 10 + - multiply: 1 + - offset: !lambda return 10; + - multiply: !lambda return 2; + - filter_out: + - 10 + - 20 + - !lambda return 10; + - filter_out: 10 + - filter_out: !lambda return NAN; + - timeout: + timeout: 10s + value: !lambda return 10; + - timeout: + timeout: 1h + value: 20.0 + - timeout: + timeout: 1d esphome: on_boot: @@ -46,6 +65,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/web_server/common_v3.yaml b/tests/components/web_server/common_v3.yaml new file mode 100644 index 0000000000..bdacaaddbe --- /dev/null +++ b/tests/components/web_server/common_v3.yaml @@ -0,0 +1,45 @@ +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 +datetime: + - platform: template + name: Pick a Date + type: datetime + optimistic: yes + web_server: + sorting_group_id: sorting_group_3 + sorting_weight: -5 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/components/xpt2046/test.esp32-ard.yaml b/tests/components/xpt2046/test.esp32-ard.yaml index f15d1f9b41..9e305791e0 100644 --- a/tests/components/xpt2046/test.esp32-ard.yaml +++ b/tests/components/xpt2046/test.esp32-ard.yaml @@ -25,8 +25,8 @@ touchscreen: update_interval: 50ms threshold: 400 calibration: - x_min: 3860 - x_max: 280 + x_min: 280 + x_max: 3860 y_min: 340 y_max: 3860 on_touch: diff --git a/tests/components/xpt2046/test.esp32-c3-ard.yaml b/tests/components/xpt2046/test.esp32-c3-ard.yaml index ef4daa800d..c03fd6b345 100644 --- a/tests/components/xpt2046/test.esp32-c3-ard.yaml +++ b/tests/components/xpt2046/test.esp32-c3-ard.yaml @@ -25,7 +25,7 @@ touchscreen: update_interval: 50ms threshold: 400 calibration: - x_min: 3860 + x_min: 28 x_max: 280 y_min: 340 y_max: 3860 diff --git a/tests/components/xpt2046/test.esp32-c3-idf.yaml b/tests/components/xpt2046/test.esp32-c3-idf.yaml index ef4daa800d..787ca9b1ed 100644 --- a/tests/components/xpt2046/test.esp32-c3-idf.yaml +++ b/tests/components/xpt2046/test.esp32-c3-idf.yaml @@ -25,7 +25,7 @@ touchscreen: update_interval: 50ms threshold: 400 calibration: - x_min: 3860 + x_min: 50 x_max: 280 y_min: 340 y_max: 3860 diff --git a/tests/components/xpt2046/test.esp32-idf.yaml b/tests/components/xpt2046/test.esp32-idf.yaml index f15d1f9b41..e79997146b 100644 --- a/tests/components/xpt2046/test.esp32-idf.yaml +++ b/tests/components/xpt2046/test.esp32-idf.yaml @@ -25,7 +25,7 @@ touchscreen: update_interval: 50ms threshold: 400 calibration: - x_min: 3860 + x_min: 50 x_max: 280 y_min: 340 y_max: 3860 diff --git a/tests/components/xpt2046/test.esp8266-ard.yaml b/tests/components/xpt2046/test.esp8266-ard.yaml index 0daa25ad60..ab71f7b8bc 100644 --- a/tests/components/xpt2046/test.esp8266-ard.yaml +++ b/tests/components/xpt2046/test.esp8266-ard.yaml @@ -25,7 +25,7 @@ touchscreen: update_interval: 50ms threshold: 400 calibration: - x_min: 3860 + x_min: 50 x_max: 280 y_min: 340 y_max: 3860 diff --git a/tests/components/xpt2046/test.rp2040-ard.yaml b/tests/components/xpt2046/test.rp2040-ard.yaml index 8afc45d04d..622e69ac98 100644 --- a/tests/components/xpt2046/test.rp2040-ard.yaml +++ b/tests/components/xpt2046/test.rp2040-ard.yaml @@ -25,8 +25,8 @@ touchscreen: update_interval: 50ms threshold: 400 calibration: - x_min: 3860 - x_max: 280 + x_min: 280 + x_max: 3860 y_min: 340 y_max: 3860 on_touch: 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