diff --git a/.github/workflows/Tasmota_build_devel.yml b/.github/workflows/Tasmota_build_devel.yml index 3f9fe9e06..a1f6204b4 100644 --- a/.github/workflows/Tasmota_build_devel.yml +++ b/.github/workflows/Tasmota_build_devel.yml @@ -32,13 +32,18 @@ jobs: - tasmota-zbbridge - tasmota-zigbee - tasmota32 + - tasmota32-zbbrdgpro - tasmota32-webcam - tasmota32-bluetooth + - tasmota32-nspanel - tasmota32-display - tasmota32-ir - tasmota32-lvgl - tasmota32c3 - tasmota32c3usb + - tasmota32s2 + - tasmota32s3 + - tasmota32s3usb - tasmota32solo1 - tasmota32solo1-safeboot - tasmota32-safeboot @@ -46,6 +51,7 @@ jobs: - tasmota32c3usb-safeboot - tasmota32s2-safeboot - tasmota32s3-safeboot + - tasmota32s3usb-safeboot steps: - uses: actions/checkout@v3 with: @@ -121,9 +127,13 @@ jobs: [ ! -f ./mv_firmware/firmware/tasmota32-lvgl.* ] || mv ./mv_firmware/firmware/tasmota32-lvgl.* ./firmware/tasmota32/ [ ! -f ./mv_firmware/firmware/tasmota32-web*.* ] || mv ./mv_firmware/firmware/tasmota32-web*.* ./firmware/tasmota32/ [ ! -f ./mv_firmware/firmware/tasmota32-odroidgo.* ] || mv ./mv_firmware/firmware/tasmota32-odroidgo.* ./firmware/tasmota32/ + [ ! -f ./mv_firmware/firmware/tasmota32-zbbrdgpro.* ] || mv ./mv_firmware/firmware/tasmota32-zbbrdgpro.* ./firmware/tasmota32/ + [ ! -f ./mv_firmware/firmware/tasmota32-nspanel.* ] || mv ./mv_firmware/firmware/tasmota32-nspanel.* ./firmware/tasmota32/ [ ! -f ./mv_firmware/firmware/tasmota32-core2.* ] || mv ./mv_firmware/firmware/tasmota32-core2.* ./firmware/tasmota32/ [ ! -f ./mv_firmware/firmware/tasmota32-bluetooth.* ] || mv ./mv_firmware/firmware/tasmota32-bluetooth.* ./firmware/tasmota32/ [ ! -f ./mv_firmware/firmware/tasmota32c3*.* ] || mv ./mv_firmware/firmware/tasmota32c3*.* ./firmware/tasmota32/ + [ ! -f ./mv_firmware/firmware/tasmota32s2*.* ] || mv ./mv_firmware/firmware/tasmota32s2*.* ./firmware/tasmota32/ + [ ! -f ./mv_firmware/firmware/tasmota32s3*.* ] || mv ./mv_firmware/firmware/tasmota32s3*.* ./firmware/tasmota32/ [ ! -f ./mv_firmware/firmware/tasmota32-safeboot* ] || mv ./mv_firmware/firmware/tasmota32-safeboot* ./firmware/tasmota32/ [ ! -f ./mv_firmware/firmware/tasmota32-* ] || mv ./mv_firmware/firmware/tasmota32-* ./firmware/tasmota32/languages/ [ ! -f ./mv_firmware/firmware/tasmota32* ] || mv ./mv_firmware/firmware/tasmota32* ./firmware/tasmota32/ diff --git a/.github/workflows/Tasmota_build_master.yml b/.github/workflows/Tasmota_build_master.yml index d39246639..8cc057300 100644 --- a/.github/workflows/Tasmota_build_master.yml +++ b/.github/workflows/Tasmota_build_master.yml @@ -31,20 +31,26 @@ jobs: - tasmota-zbbridge - tasmota-zigbee - tasmota32 + - tasmota32-zbbrdgpro - tasmota32-webcam - tasmota32-bluetooth + - tasmota32-nspanel - tasmota32-display - tasmota32-ir - tasmota32-lvgl - tasmota32c3 - tasmota32c3usb + - tasmota32s2 + - tasmota32s3 + - tasmota32s3usb - tasmota32solo1 - tasmota32solo1-safeboot - tasmota32-safeboot - tasmota32c3-safeboot + - tasmota32c3usb-safeboot - tasmota32s2-safeboot - tasmota32s3-safeboot - - tasmota32c3usb-safeboot + - tasmota32s3usb-safeboot steps: - uses: actions/checkout@v3 with: @@ -128,10 +134,14 @@ jobs: [ ! -f ./mv_firmware/firmware/tasmota32-display.* ] || mv ./mv_firmware/firmware/tasmota32-display.* ./release-firmware/tasmota32/ [ ! -f ./mv_firmware/firmware/tasmota32-lvgl.* ] || mv ./mv_firmware/firmware/tasmota32-lvgl.* ./release-firmware/tasmota32/ [ ! -f ./mv_firmware/firmware/tasmota32-web*.* ] || mv ./mv_firmware/firmware/tasmota32-web*.* ./release-firmware/tasmota32/ + [ ! -f ./mv_firmware/firmware/tasmota32-zbbrdgpro.* ] || mv ./mv_firmware/firmware/tasmota32-zbbrdgpro.* ./release-firmware/tasmota32/ + [ ! -f ./mv_firmware/firmware/tasmota32-nspanel.* ] || mv ./mv_firmware/firmware/tasmota32-nspanel.* ./release-firmware/tasmota32/ [ ! -f ./mv_firmware/firmware/tasmota32-odroidgo.* ] || mv ./mv_firmware/firmware/tasmota32-odroidgo.* ./release-firmware/tasmota32/ [ ! -f ./mv_firmware/firmware/tasmota32-core2.* ] || mv ./mv_firmware/firmware/tasmota32-core2.* ./release-firmware/tasmota32/ [ ! -f ./mv_firmware/firmware/tasmota32-bluetooth.* ] || mv ./mv_firmware/firmware/tasmota32-bluetooth.* ./release-firmware/tasmota32/ [ ! -f ./mv_firmware/firmware/tasmota32c3*.* ] || mv ./mv_firmware/firmware/tasmota32c3*.* ./release-firmware/tasmota32/ + [ ! -f ./mv_firmware/firmware/tasmota32s2*.* ] || mv ./mv_firmware/firmware/tasmota32s2*.* ./release-firmware/tasmota32/ + [ ! -f ./mv_firmware/firmware/tasmota32s3*.* ] || mv ./mv_firmware/firmware/tasmota32s3*.* ./release-firmware/tasmota32/ [ ! -f ./mv_firmware/firmware/tasmota32-safeboot* ] || mv ./mv_firmware/firmware/tasmota32-safeboot* ./release-firmware/tasmota32/ [ ! -f ./mv_firmware/firmware/tasmota32-* ] || mv ./mv_firmware/firmware/tasmota32-* ./release-firmware/tasmota32/languages/ [ ! -f ./mv_firmware/firmware/tasmota32* ] || mv ./mv_firmware/firmware/tasmota32* ./release-firmware/tasmota32/languages/ diff --git a/.github/workflows/build_all_the_things.yml b/.github/workflows/build_all_the_things.yml index 3303759f4..c5ba5ae12 100644 --- a/.github/workflows/build_all_the_things.yml +++ b/.github/workflows/build_all_the_things.yml @@ -32,17 +32,21 @@ jobs: - tasmota-minimal - tasmota-sensors - tasmota-zbbridge + - tasmota32-zbbrdgpro - tasmota-zigbee - tasmota32 - tasmota32-webcam - tasmota32-bluetooth - tasmota32-core2 + - tasmota32-nspanel - tasmota32-display - tasmota32-ir - tasmota32-lvgl - - tasmota32s2 - tasmota32c3 - tasmota32c3usb + - tasmota32s2 + - tasmota32s3 + - tasmota32s3usb - tasmota32solo1 - tasmota32solo1-safeboot - tasmota32-safeboot @@ -50,6 +54,7 @@ jobs: - tasmota32c3usb-safeboot - tasmota32s2-safeboot - tasmota32s3-safeboot + - tasmota32s3usb-safeboot steps: - uses: actions/checkout@v2 - name: Set up Python diff --git a/.travis.yml.off b/.travis.yml.off deleted file mode 100644 index 02f97e5b5..000000000 --- a/.travis.yml.off +++ /dev/null @@ -1,47 +0,0 @@ -language: python -python: - - '3.7' -sudo: false -install: - - pip install -U platformio - - platformio upgrade --dev - - platformio update - -cache: false - -env: - - ENV=tasmota - - ENV=tasmota-minimal - - ENV=tasmota-lite - - ENV=tasmota-knx - - ENV=tasmota-sensors - - ENV=tasmota-display - - ENV=tasmota-ir - - ENV=tasmota-BG - - ENV=tasmota-BR - - ENV=tasmota-CN - - ENV=tasmota-CZ - - ENV=tasmota-DE - - ENV=tasmota-ES - - ENV=tasmota-FR - - ENV=tasmota-GR - - ENV=tasmota-HE - - ENV=tasmota-HU - - ENV=tasmota-IT - - ENV=tasmota-KO - - ENV=tasmota-NL - - ENV=tasmota-PL - - ENV=tasmota-PT - - ENV=tasmota-RO - - ENV=tasmota-RU - - ENV=tasmota-SE - - ENV=tasmota-SK - - ENV=tasmota-TR - - ENV=tasmota-TW - - ENV=tasmota-UK - - ENV=tasmota-VN - -script: - - platformio run -e $ENV -before_deploy: - - for file in .pioenvs/*/firmware.bin; do cp $file ${file%/*}.bin; done diff --git a/BUILDS.md b/BUILDS.md index c3d70ad51..89f522bce 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -65,6 +65,7 @@ Note: `minimal` variant is not listed as it shouldn't be used outside of the [up | USE_MY92X1 | - | x / - | x | x | - | x | | USE_SM16716 | - | x / - | x | x | - | x | | USE_SM2135 | - | x / - | x | x | - | x | +| USE_BP5758D | - | x / - | x | x | - | x | | USE_SONOFF_L1 | - | x / - | x | x | - | x | | USE_ELECTRIQ_MOODL | - | x / - | x | x | - | x | | | | | | | | | @@ -170,6 +171,7 @@ Note: `minimal` variant is not listed as it shouldn't be used outside of the [up | USE_HDC2010 | - | - / - | - | - | - | - | | USE_PCF85363 | - | - / - | - | - | - | - | | USE_DS3502 | - | - / - | - | - | - | - | +| USE_HYT | - | - / - | - | - | - | - | | | | | | | | | | Feature or Sensor | l | t | k | s | i | d | Remarks | USE_SPI | - | - / - | - | - | - | x | @@ -241,6 +243,7 @@ Note: `minimal` variant is not listed as it shouldn't be used outside of the [up | USE_MI_ESP32 | | / x | | | | | See SetOption115 | USE_IBEACON_ESP32 | | / - | | | | | | USE_WEBCAM | | / - | | | | | -| USE_ETHERNET | | / - | | | | | +| USE_ETHERNET | | / x | | | | | | USE_I2S_AUDIO | | / - | | | | | | USE_TTGO_WATCH | | / - | | | | | +| USE_SONOFF_SPM | | / x | | | | | diff --git a/CHANGELOG.md b/CHANGELOG.md index aac70f934..d12c0dcf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,19 +3,30 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - Development -## [11.1.0.3] +## [11.1.0.4] ### Added -- Support for Sonoff SPM v1.2.0 +- Support for HYTxxx temperature and humidity sensor (#15715) +- Support for Sensirion SHT4X using define USE_SHT3X (#15349) ### Changed - +- Restructured tasmota source directories taking benefit from PlatformIO Core v6.0.2 ### Fixed - ### Removed +## [11.1.0.3] 20220602 +### Added +- Support for Sonoff SPM v1.2.0 +- Support for Sonoff Zigbee Bridge Pro by Stephan Hadinger (#15701) +- Command ``SspmDisplay 2`` to display Sonoff SPM energy data in GUI for user tab-selected relay modules (#13447) +- Command ``SetOption141 1`` to disable display of module name in GUI header +- Support for 5-channel light dimmer driver BP5758D used in Tuya bulbs (#15713) + +### Fixed +- Possible pin output toggle after power on (#15630) + ## [11.1.0.2] 20220514 ### Added - ESP32 Command ``Restart 3`` to switch between SafeBoot and Production diff --git a/I2CDEVICES.md b/I2CDEVICES.md index cb3d0ab83..59bc03065 100644 --- a/I2CDEVICES.md +++ b/I2CDEVICES.md @@ -31,7 +31,8 @@ Index | Define | Driver | Device | Address(es) | Description 13 | USE_ADS1115 | xsns_12 | ADS1115 | 0x48 - 0x4B | 4-channel 16-bit A/D converter 14 | USE_INA219 | xsns_13 | INA219 | 0x40 - 0x41, 0x44 - 0x45 | Low voltage current sensor 15 | USE_SHT3X | xsns_14 | SHT3X | 0x44 - 0x45 | Temperature and Humidity sensor - 15 | USE_SHT3X | xsns_14 | SHTC3 | 0x70 | Temperature and Humidity sensor + 15 | USE_SHT3X | xsns_14 | SHT4X | 0x44 - 0x45 | Temperature and Humidity sensor + 15 | USE_SHT3X | xsns_14 | SHTCX | 0x70 | Temperature and Humidity sensor 16 | USE_TSL2561 | xsns_16 | TSL2561 | 0x29, 0x39, 0x49 | Light intensity sensor 17 | USE_MGS | xsns_19 | Grove | 0x04 | Multichannel gas sensor 18 | USE_SGP30 | xsns_21 | SGP30 | 0x58 | Gas (TVOC) and air quality sensor @@ -101,3 +102,4 @@ Index | Define | Driver | Device | Address(es) | Description 65 | USE_ADE7880 | xnrg_23 | ADE7880 | 0x38 | Energy monitor 66 | USE_PCF85363 | xsns_99 | PCF85363 | 0x51 | Real time clock 67 | USE_DS3502 | xdrv_61 | DS3502 | 0x28 - 0x2B | Digital potentiometer + 68 | USE_HYT | xsns_97 | HYTxxx | 0x28 | Temperature and Humidity sensor diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 24af1c458..cbc4b42af 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -104,22 +104,29 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo [Complete list](BUILDS.md) of available feature and sensors. -## Changelog v11.1.0.3 +## Changelog v11.1.0.4 ### Added - Command ``SetOption139 0/1`` to switch between pressure unit "mmHg" (0) or "inHg" (1) when ``SO24 1`` [#15350](https://github.com/arendst/Tasmota/issues/15350) - Command ``SetOption140 0/1`` to switch between MQTT Clean Session (0) or Persistent Session (1) [#15530](https://github.com/arendst/Tasmota/issues/15530) +- Command ``SetOption141 1`` to disable display of module name in GUI header - Command ``EnergyExportActive`` to (p)reset energy export active for supported devices. Currently ADE7880 only [#13515](https://github.com/arendst/Tasmota/issues/13515) - Command ``IfxRp ""|`` adds optional InfluxDb Retention Policy [#15513](https://github.com/arendst/Tasmota/issues/15513) +- Command ``SspmDisplay 2`` to display Sonoff SPM energy data in GUI for user tab-selected relay modules [#13447](https://github.com/arendst/Tasmota/issues/13447) - Support for Sonoff MS01 soil moisture sensor [#15335](https://github.com/arendst/Tasmota/issues/15335) - Support for daisy chaining MAX7219 displays [#15345](https://github.com/arendst/Tasmota/issues/15345) +- Support for Sensirion SHT4X using define USE_SHT3X [#15349](https://github.com/arendst/Tasmota/issues/15349) - Sonoff SPM delayed SetPowerOnState [#13447](https://github.com/arendst/Tasmota/issues/13447) - Support for Sonoff SPM v1.2.0 +- Support for Sonoff Zigbee Bridge Pro by Stephan Hadinger [#15701](https://github.com/arendst/Tasmota/issues/15701) - Support for flowrate meters like YF-DN50 and similary [#15474](https://github.com/arendst/Tasmota/issues/15474) +- Support for 5-channel light dimmer driver BP5758D used in Tuya bulbs [#15713](https://github.com/arendst/Tasmota/issues/15713) +- Support for HYTxxx temperature and humidity sensor [#15715](https://github.com/arendst/Tasmota/issues/15715) - ESP32 Command ``Restart 3`` to switch between SafeBoot and Production ### Breaking Changed ### Changed +- Restructured tasmota source directories taking benefit from PlatformIO Core v6.0.2 - Prepare to remove dedicated Home Assistant discovery in favour of Tasmota Discovery and hatasmota - ESP32 Tasmota SafeBoot with changed partition scheme allowing larger binaries @@ -127,6 +134,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - Improv initial or erase device installation failing to provide Configure WiFi option - SCD40 start low power command [#15361](https://github.com/arendst/Tasmota/issues/15361) - BL09xx negative power presentation [#15374](https://github.com/arendst/Tasmota/issues/15374) +- Possible pin output toggle after power on [#15630](https://github.com/arendst/Tasmota/issues/15630) ### Removed - Arduino IDE support diff --git a/boards/esp32s3usb.json b/boards/esp32s3usb.json new file mode 100644 index 000000000..f495bc5d8 --- /dev/null +++ b/boards/esp32s3usb.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qspi_qspi" + }, + "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DUSE_USB_SERIAL_CONSOLE -DESP32_4M -DESP32S3", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32s3", + "variant": "esp32s3", + "partitions": "partitions/esp32_partition_app2880k_fs320k.csv" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "espidf", + "arduino" + ], + "name": "Espressif Generic ESP32-S3 4M Flash, Tasmota 2880k Code/OTA, 320k FS", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x10000", + "variants/tasmota/tasmota32s3usb-safeboot.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/", + "vendor": "Espressif" +} diff --git a/include/tasmota_options.h b/include/tasmota_options.h index 840daf379..ebfc69019 100644 --- a/include/tasmota_options.h +++ b/include/tasmota_options.h @@ -21,6 +21,6 @@ #define __TASMOTA_INCLUDE__ #include "../tasmota/my_user_config.h" -#include "../tasmota/tasmota_configurations.h" +#include "../tasmota/include/tasmota_configurations.h" #endif // __TASMOTA_INCLUDE__ \ No newline at end of file diff --git a/lib/default/Ext-printf/src/SBuffer.hpp b/lib/default/Ext-printf/src/SBuffer.hpp index 67bbbcd48..9c545add0 100644 --- a/lib/default/Ext-printf/src/SBuffer.hpp +++ b/lib/default/Ext-printf/src/SBuffer.hpp @@ -48,7 +48,7 @@ public: inline uint8_t *buf(size_t i = 0) const { return &_buf->buf[i]; } inline char *charptr(size_t i = 0) const { return (char*) &_buf->buf[i]; } - virtual ~SBuffer(void) { + ~SBuffer(void) { delete[] _buf; } @@ -258,6 +258,12 @@ public: return buf2; } + static SBuffer SBufferFromBytes(const uint8_t *bytes, size_t len2) { + SBuffer buf2(len2); + buf2.addBuffer(bytes, len2); + return buf2; + } + // nullptr accepted static bool equalsSBuffer(const class SBuffer * buf1, const class SBuffer * buf2) { if (buf1 == buf2) { return true; } @@ -290,18 +296,3 @@ protected: SBuffer_impl * _buf; } SBuffer; - -typedef class PreAllocatedSBuffer : public SBuffer { - -public: - PreAllocatedSBuffer(const size_t size, void * buffer) { - _buf = (SBuffer_impl*) buffer; - _buf->size = size - 4; - _buf->len = 0; - } - - ~PreAllocatedSBuffer(void) { - // don't deallocate - _buf = nullptr; - } -} PreAllocatedSBuffer; diff --git a/lib/default/Unishox-1.0-shadinger/src/unishox.cpp b/lib/default/Unishox-1.0-shadinger/src/unishox.cpp index 1c0fd7142..64b18f3c2 100644 --- a/lib/default/Unishox-1.0-shadinger/src/unishox.cpp +++ b/lib/default/Unishox-1.0-shadinger/src/unishox.cpp @@ -252,7 +252,6 @@ int32_t Unishox::unishox_compress(const char *p_in, size_t p_len, char *p_out, s out = p_out; len_out = p_len_out; - char *ptr; byte bits; int ll; diff --git a/lib/default/jsmn-shadinger-1.0/src/jsmn.cpp b/lib/default/jsmn-shadinger-1.0/src/jsmn.cpp index bfd0e11bb..80da28f07 100644 --- a/lib/default/jsmn-shadinger-1.0/src/jsmn.cpp +++ b/lib/default/jsmn-shadinger-1.0/src/jsmn.cpp @@ -391,7 +391,7 @@ static uint32_t json_encode_utf8(char* str, uint32_t val) { void json_unescape(char* string) { size_t outlength = 0; - uint32_t hexval, numbytes; + uint32_t numbytes; char c; for (uint32_t i = 0; (c = string[i]) != 0; i++) { diff --git a/lib/libesp32/berry/default/be_modtab.c b/lib/libesp32/berry/default/be_modtab.c index 5ed4a99e6..8f7addd94 100644 --- a/lib/libesp32/berry/default/be_modtab.c +++ b/lib/libesp32/berry/default/be_modtab.c @@ -48,13 +48,16 @@ be_extern_native_module(uuid); be_extern_native_module(animate); be_extern_native_module(partition_core); be_extern_native_module(crc); +#ifdef USE_ZIGBEE +be_extern_native_module(zigbee); +#endif // USE_ZIGBEE #ifdef USE_LVGL be_extern_native_module(lv); be_extern_native_module(lv_extra); be_extern_native_module(lv_tasmota); -#ifdef USE_LVGL_OPENHASP -be_extern_native_module(openhasp); -#endif // USE_LVGL_OPENHASP +#ifdef USE_LVGL_HASPMOTA +be_extern_native_module(haspmota); +#endif // USE_LVGL_HASPMOTA #endif // USE_LVGL /* user-defined modules declare start */ @@ -137,9 +140,9 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = { &be_native_module(lv), &be_native_module(lv_extra), &be_native_module(lv_tasmota), -#ifdef USE_LVGL_OPENHASP - &be_native_module(openhasp), -#endif // USE_LVGL_OPENHASP +#ifdef USE_LVGL_HASPMOTA + &be_native_module(haspmota), +#endif // USE_LVGL_HASPMOTA #endif // USE_LVGL #ifdef USE_ENERGY_SENSOR &be_native_module(energy), @@ -147,6 +150,9 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = { #ifdef USE_WEBSERVER &be_native_module(webserver), #endif // USE_WEBSERVER +#ifdef USE_ZIGBEE + &be_native_module(zigbee), +#endif // USE_ZIGBEE &be_native_module(flash), &be_native_module(partition_core), &be_native_module(crc), diff --git a/lib/libesp32/berry/default/berry_conf.h b/lib/libesp32/berry/default/berry_conf.h index 84255936b..c70af7945 100644 --- a/lib/libesp32/berry/default/berry_conf.h +++ b/lib/libesp32/berry/default/berry_conf.h @@ -12,7 +12,7 @@ #ifdef COMPILE_BERRY_LIB #include "my_user_config.h" - #include "tasmota_configurations.h" + #include "include/tasmota_configurations.h" #endif /* Macro: BE_DEBUG diff --git a/lib/libesp32/berry/gen.sh b/lib/libesp32/berry/gen.sh index 7156e8719..ee97feeef 100755 --- a/lib/libesp32/berry/gen.sh +++ b/lib/libesp32/berry/gen.sh @@ -1,2 +1,8 @@ #!/bin/bash +# +# generate all precompiled Berry structures from multiple modules +# +# Should be eventually included in the build process +# +rm generate/be_*.h python3 tools/pycoc/main.py -o generate src default ../berry_tasmota/src ../berry_mapping/src ../berry_int64/src ../../libesp32_lvgl/lv_binding_berry/src ../../libesp32_lvgl/lv_binding_berry/generate -c default/berry_conf.h diff --git a/lib/libesp32/berry/generate/be_const_strtab.h b/lib/libesp32/berry/generate/be_const_strtab.h index d9cdc2394..7ef8af957 100644 --- a/lib/libesp32/berry/generate/be_const_strtab.h +++ b/lib/libesp32/berry/generate/be_const_strtab.h @@ -1,5 +1,6 @@ extern const bcstring be_const_str_; extern const bcstring be_const_str_00; +extern const bcstring be_const_str_0x_X2502X; extern const bcstring be_const_str_AA50; extern const bcstring be_const_str_AES_GCM; extern const bcstring be_const_str_ALIGN_BOTTOM_MID; @@ -245,6 +246,7 @@ extern const bcstring be_const_str__energy; extern const bcstring be_const_str__error; extern const bcstring be_const_str__filename; extern const bcstring be_const_str__fl; +extern const bcstring be_const_str__get_bytes; extern const bcstring be_const_str__global_addr; extern const bcstring be_const_str__global_def; extern const bcstring be_const_str__lvgl; @@ -255,6 +257,7 @@ extern const bcstring be_const_str__read; extern const bcstring be_const_str__request_from; extern const bcstring be_const_str__rmt; extern const bcstring be_const_str__rules; +extern const bcstring be_const_str__set_bytes; extern const bcstring be_const_str__settings_def; extern const bcstring be_const_str__settings_ptr; extern const bcstring be_const_str__splash; @@ -264,6 +267,7 @@ extern const bcstring be_const_str__timers; extern const bcstring be_const_str__validate; extern const bcstring be_const_str__write; extern const bcstring be_const_str_a; +extern const bcstring be_const_str_abort; extern const bcstring be_const_str_abs; extern const bcstring be_const_str_acos; extern const bcstring be_const_str_active_otadata; @@ -486,6 +490,7 @@ extern const bcstring be_const_str_format; extern const bcstring be_const_str_from_to; extern const bcstring be_const_str_fromb64; extern const bcstring be_const_str_frombytes; +extern const bcstring be_const_str_fromhex; extern const bcstring be_const_str_fromptr; extern const bcstring be_const_str_fromstring; extern const bcstring be_const_str_full_state; @@ -567,6 +572,7 @@ extern const bcstring be_const_str_imax; extern const bcstring be_const_str_img; extern const bcstring be_const_str_imin; extern const bcstring be_const_str_import; +extern const bcstring be_const_str_info; extern const bcstring be_const_str_init; extern const bcstring be_const_str_init_draw_arc_dsc; extern const bcstring be_const_str_init_draw_line_dsc; @@ -917,6 +923,7 @@ extern const bcstring be_const_str_subscribe; extern const bcstring be_const_str_subtype; extern const bcstring be_const_str_subtype_to_string; extern const bcstring be_const_str_success; +extern const bcstring be_const_str_sum; extern const bcstring be_const_str_super; extern const bcstring be_const_str_switch_factory; extern const bcstring be_const_str_sys; @@ -940,6 +947,7 @@ extern const bcstring be_const_str_timer_cb; extern const bcstring be_const_str_to_gamma; extern const bcstring be_const_str_tob64; extern const bcstring be_const_str_tobytes; +extern const bcstring be_const_str_tohex; extern const bcstring be_const_str_toint; extern const bcstring be_const_str_tolower; extern const bcstring be_const_str_tomap; @@ -1029,5 +1037,9 @@ extern const bcstring be_const_str_y; extern const bcstring be_const_str_y1; extern const bcstring be_const_str_year; extern const bcstring be_const_str_yield; +extern const bcstring be_const_str_zb_coord_ntv; +extern const bcstring be_const_str_zb_device; +extern const bcstring be_const_str_zcl_frame; +extern const bcstring be_const_str_zcl_frame_ntv; extern const bcstring be_const_str_zero; extern const bcstring be_const_str_zip; diff --git a/lib/libesp32/berry/generate/be_const_strtab_def.h b/lib/libesp32/berry/generate/be_const_strtab_def.h index a2d290c79..7448f971b 100644 --- a/lib/libesp32/berry/generate/be_const_strtab_def.h +++ b/lib/libesp32/berry/generate/be_const_strtab_def.h @@ -1,967 +1,975 @@ -be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str__X3Clegend_X3E_X3Cb_X20title_X3D_X27New_X20autoconf_X27_X3E_X26nbsp_X3BSelect_X20new_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E); -be_define_const_str(_X0A, "\n", 252472541u, 0, 1, &be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dzip_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20); -be_define_const_str(_X0A_X29_X3E, "\n)>", 804061574u, 0, 3, &be_const_str_CFG_X3A_X20running_X20); -be_define_const_str(_X20, " ", 621580159u, 0, 1, &be_const_str_Auto_X2Dconfiguration); -be_define_const_str(_X20_X20, " ", 2982523533u, 0, 2, NULL); -be_define_const_str(_X20_X28, " (", 2848302581u, 0, 2, &be_const_str_show); -be_define_const_str(_X21_X3D, "!=", 2428715011u, 0, 2, NULL); -be_define_const_str(_X21_X3D_X3D, "!==", 559817114u, 0, 3, NULL); +be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_zb_device); +be_define_const_str(_X0A, "\n", 252472541u, 0, 1, NULL); +be_define_const_str(_X0A_X29_X3E, "\n)>", 804061574u, 0, 3, &be_const_str_SERIAL_8O2); +be_define_const_str(_X20, " ", 621580159u, 0, 1, &be_const_str_time_str); +be_define_const_str(_X20_X20, " ", 2982523533u, 0, 2, &be_const_str_onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E); +be_define_const_str(_X20_X28, " (", 2848302581u, 0, 2, &be_const_str_find_key_i); +be_define_const_str(_X21_X3D, "!=", 2428715011u, 0, 2, &be_const_str_exec_tele); +be_define_const_str(_X21_X3D_X3D, "!==", 559817114u, 0, 3, &be_const_str_add_anim); be_define_const_str(_X22, "\"", 655135397u, 0, 1, NULL); -be_define_const_str(_X22_X3A, "\":", 399167565u, 0, 2, &be_const_str_gamma8); -be_define_const_str(_X23, "#", 638357778u, 0, 1, &be_const_str_finish); -be_define_const_str(_X23autoexec_X2Ebat, "#autoexec.bat", 3382890497u, 0, 13, &be_const_str_set_alternate); -be_define_const_str(_X23autoexec_X2Ebe, "#autoexec.be", 1181757091u, 0, 12, &be_const_str_pc); -be_define_const_str(_X23display_X2Eini, "#display.ini", 182218220u, 0, 12, NULL); -be_define_const_str(_X23init_X2Ebat, "#init.bat", 3297595077u, 0, 9, NULL); -be_define_const_str(_X23preinit_X2Ebe, "#preinit.be", 687035716u, 0, 11, &be_const_str_clock_icon); -be_define_const_str(_X25, "%", 537692064u, 0, 1, NULL); -be_define_const_str(_X2502d_X25s_X2502d, "%02d%s%02d", 1587999717u, 0, 10, &be_const_str_get_free_heap); -be_define_const_str(_X2504d_X2D_X2502d_X2D_X2502dT_X2502d_X3A_X2502d_X3A_X2502d, "%04d-%02d-%02dT%02d:%02d:%02d", 3425528601u, 0, 29, &be_const_str_before_del); -be_define_const_str(_X2508x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2508x, "%08x-%04x-%04x-%04x-%04x%08x", 1670063141u, 0, 28, &be_const_str_BLE); -be_define_const_str(_X25s_X2Eautoconf, "%s.autoconf", 3560383524u, 0, 11, &be_const_str_EVENT_DRAW_PART_BEGIN); -be_define_const_str(_X26lt_X3BError_X3A_X20apply_X20new_X20or_X20remove_X26gt_X3B, "<Error: apply new or remove>", 2855507949u, 0, 34, &be_const_str_exec_cmd); -be_define_const_str(_X26lt_X3BNone_X26gt_X3B, "<None>", 2602165498u, 0, 12, &be_const_str__X3F); -be_define_const_str(_X27_X20_X2D_X20, "' - ", 3420378487u, 0, 4, &be_const_str_set_light); -be_define_const_str(_X28_X29, "()", 685372826u, 0, 2, &be_const_str__X2Elen); +be_define_const_str(_X22_X3A, "\":", 399167565u, 0, 2, &be_const_str__X3Cp_X3E_X3Csmall_X3E_X26nbsp_X3B_X28This_X20feature_X20requires_X20an_X20internet_X20connection_X29_X3C_X2Fsmall_X3E_X3C_X2Fp_X3E); +be_define_const_str(_X23, "#", 638357778u, 0, 1, &be_const_str_gamma8); +be_define_const_str(_X23autoexec_X2Ebat, "#autoexec.bat", 3382890497u, 0, 13, &be_const_str__X25); +be_define_const_str(_X23autoexec_X2Ebe, "#autoexec.be", 1181757091u, 0, 12, &be_const_str_load_templates); +be_define_const_str(_X23display_X2Eini, "#display.ini", 182218220u, 0, 12, &be_const_str_argument_X20must_X20be_X20a_X20list); +be_define_const_str(_X23init_X2Ebat, "#init.bat", 3297595077u, 0, 9, &be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3EAuto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E); +be_define_const_str(_X23preinit_X2Ebe, "#preinit.be", 687035716u, 0, 11, &be_const_str_find); +be_define_const_str(_X25, "%", 537692064u, 0, 1, &be_const_str__X2C_X22AXP192_X22_X3A_X7B_X22VBusVoltage_X22_X3A_X25_X2E3f_X2C_X22VBusCurrent_X22_X3A_X25_X2E1f_X2C_X22BattVoltage_X22_X3A_X25_X2E3f_X2C_X22BattCurrent_X22_X3A_X25_X2E1f_X2C_X22Temperature_X22_X3A_X25_X2E1f_X7D); +be_define_const_str(_X2502d_X25s_X2502d, "%02d%s%02d", 1587999717u, 0, 10, &be_const_str_web_sensor); +be_define_const_str(_X2504d_X2D_X2502d_X2D_X2502dT_X2502d_X3A_X2502d_X3A_X2502d, "%04d-%02d-%02dT%02d:%02d:%02d", 3425528601u, 0, 29, &be_const_str___iterator__); +be_define_const_str(_X2508x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2508x, "%08x-%04x-%04x-%04x-%04x%08x", 1670063141u, 0, 28, &be_const_str_base_class); +be_define_const_str(_X25s_X2Eautoconf, "%s.autoconf", 3560383524u, 0, 11, &be_const_str_ALIGN_BOTTOM_MID); +be_define_const_str(_X26lt_X3BError_X3A_X20apply_X20new_X20or_X20remove_X26gt_X3B, "<Error: apply new or remove>", 2855507949u, 0, 34, &be_const_str_get_warning_level); +be_define_const_str(_X26lt_X3BNone_X26gt_X3B, "<None>", 2602165498u, 0, 12, &be_const_str_atan2); +be_define_const_str(_X27_X20_X2D_X20, "' - ", 3420378487u, 0, 4, &be_const_str_I2C_X3A); +be_define_const_str(_X28_X29, "()", 685372826u, 0, 2, &be_const_str_clock); be_define_const_str(_X29, ")", 739023492u, 0, 1, NULL); -be_define_const_str(_X2A, "*", 789356349u, 0, 1, &be_const_str_widget_event_cb); -be_define_const_str(_X2B, "+", 772578730u, 0, 1, &be_const_str_add); -be_define_const_str(_X2C, ",", 688690635u, 0, 1, &be_const_str_CFG_X3A_X20removing_X20autoconf_X20files); -be_define_const_str(_X2C_X22AXP192_X22_X3A_X7B_X22VBusVoltage_X22_X3A_X25_X2E3f_X2C_X22VBusCurrent_X22_X3A_X25_X2E1f_X2C_X22BattVoltage_X22_X3A_X25_X2E3f_X2C_X22BattCurrent_X22_X3A_X25_X2E1f_X2C_X22Temperature_X22_X3A_X25_X2E1f_X7D, ",\"AXP192\":{\"VBusVoltage\":%.3f,\"VBusCurrent\":%.1f,\"BattVoltage\":%.3f,\"BattCurrent\":%.1f,\"Temperature\":%.1f}", 2598755376u, 0, 106, NULL); -be_define_const_str(_X2D, "-", 671913016u, 0, 1, NULL); -be_define_const_str(_X2D_X2A, "-*", 499980374u, 0, 2, &be_const_str_MI32); -be_define_const_str(_X2D_X2D_X3A_X2D_X2D, "--:--", 1370615441u, 0, 5, &be_const_str_get_coords); -be_define_const_str(_X2E, ".", 722245873u, 0, 1, NULL); +be_define_const_str(_X2A, "*", 789356349u, 0, 1, &be_const_str_while); +be_define_const_str(_X2B, "+", 772578730u, 0, 1, &be_const_str_BRY_X3A_X20failed_X20to_X20load_X20compiled_X20_X27_X25s_X27_X20_X28_X25s_X29); +be_define_const_str(_X2C, ",", 688690635u, 0, 1, NULL); +be_define_const_str(_X2C_X22AXP192_X22_X3A_X7B_X22VBusVoltage_X22_X3A_X25_X2E3f_X2C_X22VBusCurrent_X22_X3A_X25_X2E1f_X2C_X22BattVoltage_X22_X3A_X25_X2E3f_X2C_X22BattCurrent_X22_X3A_X25_X2E1f_X2C_X22Temperature_X22_X3A_X25_X2E1f_X7D, ",\"AXP192\":{\"VBusVoltage\":%.3f,\"VBusCurrent\":%.1f,\"BattVoltage\":%.3f,\"BattCurrent\":%.1f,\"Temperature\":%.1f}", 2598755376u, 0, 106, &be_const_str_lv_wifi_arcs); +be_define_const_str(_X2D, "-", 671913016u, 0, 1, &be_const_str__global_addr); +be_define_const_str(_X2D_X2A, "-*", 499980374u, 0, 2, NULL); +be_define_const_str(_X2D_X2D_X3A_X2D_X2D, "--:--", 1370615441u, 0, 5, &be_const_str_listdir); +be_define_const_str(_X2E, ".", 722245873u, 0, 1, &be_const_str_obj); be_define_const_str(_X2E_X2E, "..", 2748622605u, 0, 2, NULL); -be_define_const_str(_X2Eautoconf, ".autoconf", 2524679088u, 0, 9, &be_const_str_check_privileged_access); -be_define_const_str(_X2Ebe, ".be", 1325797348u, 0, 3, &be_const_str_addr); -be_define_const_str(_X2Ebec, ".bec", 3985273221u, 0, 4, NULL); -be_define_const_str(_X2Elen, ".len", 850842136u, 0, 4, NULL); -be_define_const_str(_X2Ep, ".p", 1171526419u, 0, 2, NULL); -be_define_const_str(_X2Ep1, ".p1", 249175686u, 0, 3, &be_const_str_CT); -be_define_const_str(_X2Ep2, ".p2", 232398067u, 0, 3, &be_const_str_setfloat); -be_define_const_str(_X2Esize, ".size", 1965188224u, 0, 5, &be_const_str_set_huesat); -be_define_const_str(_X2Etapp, ".tapp", 1363391594u, 0, 5, &be_const_str__X2Ew); -be_define_const_str(_X2Ew, ".w", 1255414514u, 0, 2, &be_const_str__X3C_X2Fform_X3E_X3C_X2Fp_X3E); -be_define_const_str(_X2F, "/", 705468254u, 0, 1, &be_const_str_get_string); -be_define_const_str(_X2F_X2Eautoconf, "/.autoconf", 2212074393u, 0, 10, &be_const_str_add_anim); -be_define_const_str(_X2F_X3Frst_X3D, "/?rst=", 580074707u, 0, 6, &be_const_str_AudioOpusDecoder); -be_define_const_str(_X2Fac, "/ac", 3904651978u, 0, 3, &be_const_str_pow); -be_define_const_str(_X2Flights_X2F, "/lights/", 2370247908u, 0, 8, &be_const_str_AudioGeneratorMP3); -be_define_const_str(_X2Fstate_X2F, "/state/", 4226179876u, 0, 7, &be_const_str_keys); -be_define_const_str(00, "00", 569209421u, 0, 2, &be_const_str_find_op); -be_define_const_str(_X3A, ":", 1057798253u, 0, 1, &be_const_str_compile); -be_define_const_str(_X3C, "<", 957132539u, 0, 1, &be_const_str_instance_X20required); -be_define_const_str(_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "

", 3546571739u, 0, 11, NULL); -be_define_const_str(_X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "

", 1863865923u, 0, 16, &be_const_str_get_bat_power); -be_define_const_str(_X3C_X3D, "<=", 2499223986u, 0, 2, &be_const_str__X3Cp_X3ECurrent_X20configuration_X3A_X20_X3C_X2Fp_X3E_X3Cp_X3E_X3Cb_X3E_X25s_X3C_X2Fb_X3E_X3C_X2Fp_X3E); -be_define_const_str(_X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, "", 3147934216u, 0, 82, &be_const_str_draw_line_dsc_init); -be_define_const_str(_X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, "", 1205771629u, 0, 72, &be_const_str_tag); -be_define_const_str(_X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, "
", 842307168u, 0, 77, &be_const_str_PART_MAIN); -be_define_const_str(_X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29, "", 2342198361u, 0, 61, &be_const_str__ptr); -be_define_const_str(_X3Cinstance_X3A_X20Partition_otadata_X28ota_active_X3A_X25s_X2C_X20ota_seq_X3D_X5B_X25d_X2C_X25d_X5D_X2C_X20ota_max_X3D_X25d_X29_X3E, "", 179503047u, 0, 73, &be_const_str_flush); -be_define_const_str(_X3Clabel_X3EChoose_X20a_X20device_X20configuration_X3A_X3C_X2Flabel_X3E_X3Cbr_X3E, "
", 1336654704u, 0, 49, NULL); -be_define_const_str(_X3Clambda_X3E, "", 607256038u, 0, 8, &be_const_str_HTTP_GET); +be_define_const_str(_X2Eautoconf, ".autoconf", 2524679088u, 0, 9, &be_const_str_CFG_X3A_X20_X27init_X2Ebat_X27_X20done_X2C_X20restarting); +be_define_const_str(_X2Ebe, ".be", 1325797348u, 0, 3, &be_const_str_set_dc_voltage); +be_define_const_str(_X2Ebec, ".bec", 3985273221u, 0, 4, &be_const_str_abort); +be_define_const_str(_X2Elen, ".len", 850842136u, 0, 4, &be_const_str_enabled); +be_define_const_str(_X2Ep, ".p", 1171526419u, 0, 2, &be_const_str_lower); +be_define_const_str(_X2Ep1, ".p1", 249175686u, 0, 3, &be_const_str_autorun); +be_define_const_str(_X2Ep2, ".p2", 232398067u, 0, 3, &be_const_str_STATE_DEFAULT); +be_define_const_str(_X2Esize, ".size", 1965188224u, 0, 5, NULL); +be_define_const_str(_X2Etapp, ".tapp", 1363391594u, 0, 5, &be_const_str__ptr); +be_define_const_str(_X2Ew, ".w", 1255414514u, 0, 2, &be_const_str_obj_class_create_obj); +be_define_const_str(_X2F, "/", 705468254u, 0, 1, &be_const_str__X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E); +be_define_const_str(_X2F_X2Eautoconf, "/.autoconf", 2212074393u, 0, 10, &be_const_str_event_cb); +be_define_const_str(_X2F_X3Frst_X3D, "/?rst=", 580074707u, 0, 6, &be_const_str_r); +be_define_const_str(_X2Fac, "/ac", 3904651978u, 0, 3, &be_const_str_set_dcdc_enable); +be_define_const_str(_X2Flights_X2F, "/lights/", 2370247908u, 0, 8, &be_const_str_concat); +be_define_const_str(_X2Fstate_X2F, "/state/", 4226179876u, 0, 7, &be_const_str_serial); +be_define_const_str(00, "00", 569209421u, 0, 2, &be_const_str_get_light); +be_define_const_str(0x_X2502X, "0x%02X", 2626549866u, 0, 6, &be_const_str_tostring); +be_define_const_str(_X3A, ":", 1057798253u, 0, 1, &be_const_str_show); +be_define_const_str(_X3C, "<", 957132539u, 0, 1, NULL); +be_define_const_str(_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "

", 3546571739u, 0, 11, &be_const_str_BRY_X3A_X20corrupt_X20bytecode_X20_X27_X25s_X27); +be_define_const_str(_X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "

", 1863865923u, 0, 16, &be_const_str_chars_in_string); +be_define_const_str(_X3C_X3D, "<=", 2499223986u, 0, 2, &be_const_str_False); +be_define_const_str(_X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, "", 3147934216u, 0, 82, NULL); +be_define_const_str(_X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, "", 1205771629u, 0, 72, &be_const_str__rmt); +be_define_const_str(_X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, "
", 842307168u, 0, 77, &be_const_str_INTERNAL_DAC); +be_define_const_str(_X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29, "", 2342198361u, 0, 61, &be_const_str__get_bytes); +be_define_const_str(_X3Cinstance_X3A_X20Partition_otadata_X28ota_active_X3A_X25s_X2C_X20ota_seq_X3D_X5B_X25d_X2C_X25d_X5D_X2C_X20ota_max_X3D_X25d_X29_X3E, "", 179503047u, 0, 73, &be_const_str_wire2); +be_define_const_str(_X3Clabel_X3EChoose_X20a_X20device_X20configuration_X3A_X3C_X2Flabel_X3E_X3Cbr_X3E, "
", 1336654704u, 0, 49, &be_const_str_BRY_X3A_X20Exception_X3E_X20_X27); +be_define_const_str(_X3Clambda_X3E, "", 607256038u, 0, 8, &be_const_str_Auto_X2Dconfiguration); be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27Autoconfiguration_X27_X3E_X26nbsp_X3BCurrent_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, " Current auto-configuration", 4212500780u, 0, 82, NULL); -be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27New_X20autoconf_X27_X3E_X26nbsp_X3BSelect_X20new_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, " Select new auto-configuration", 1926223891u, 0, 80, &be_const_str_coredump); -be_define_const_str(_X3Coption_X20value_X3D_X27_X25s_X27_X3E_X25s_X3C_X2Foption_X3E, "", 510303524u, 0, 30, &be_const_str_set_style_text_color); -be_define_const_str(_X3Coption_X20value_X3D_X27reset_X27_X3E_X26lt_X3BRemove_X20autoconf_X26gt_X3B_X3C_X2Foption_X3E, "", 3994619755u, 0, 54, &be_const_str_Leds); -be_define_const_str(_X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E, "

Exception:
'%s'
%s

", 4252565082u, 0, 59, &be_const_str_AudioGenerator); -be_define_const_str(_X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "

", 2052843416u, 0, 25, &be_const_str__X7Bs_X7DTemp_X20AXP_X7Bm_X7D_X25_X2E1f_X20_X26deg_X3BC_X7Be_X7D); -be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3EAuto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "

", 2058443583u, 0, 110, &be_const_str_CFG_X3A_X20loading_X20); -be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, "

 (This feature requires an internet connection)

", 2719266486u, 0, 74, NULL); -be_define_const_str(_X3Cp_X3ECurrent_X20configuration_X3A_X20_X3C_X2Fp_X3E_X3Cp_X3E_X3Cb_X3E_X25s_X3C_X2Fb_X3E_X3C_X2Fp_X3E, "

Current configuration:

%s

", 4115655761u, 0, 46, &be_const_str_light_X20must_X20be_X20of_X20class_X20_X27light_state_X27); -be_define_const_str(_X3Cselect_X20name_X3D_X27zip_X27_X3E, "", 4247924536u, 0, 19, &be_const_str_Animate_X20pc_X20is_X20out_X20of_X20range); +be_define_const_str(_X3D, "=", 940354920u, 0, 1, NULL); +be_define_const_str(_X3D_X3C_X3E_X21, "=<>!", 2664470277u, 0, 4, &be_const_str_AudioGeneratorMP3); +be_define_const_str(_X3D_X3D, "==", 2431966415u, 0, 2, NULL); +be_define_const_str(_X3E, ">", 990687777u, 0, 1, &be_const_str_EVENT_DRAW_PART_BEGIN); +be_define_const_str(_X3E_X3D, ">=", 284975636u, 0, 2, &be_const_str_web_add_main_button); +be_define_const_str(_X3F, "?", 973910158u, 0, 1, NULL); +be_define_const_str(AA50, "AA50", 2265997666u, 0, 4, &be_const_str_display_X2Eini); +be_define_const_str(AES_GCM, "AES_GCM", 3832208678u, 0, 7, NULL); +be_define_const_str(ALIGN_BOTTOM_MID, "ALIGN_BOTTOM_MID", 3933267889u, 0, 16, &be_const_str_introspect); +be_define_const_str(ALIGN_LEFT_MID, "ALIGN_LEFT_MID", 1043035067u, 0, 14, &be_const_str_get_bat_power); +be_define_const_str(AXP192, "AXP192", 757230128u, 0, 6, &be_const_str_event); +be_define_const_str(Animate_X20pc_X20is_X20out_X20of_X20range, "Animate pc is out of range", 1854929421u, 0, 26, &be_const_str_partition_core); be_define_const_str(AudioFileSource, "AudioFileSource", 2959980058u, 0, 15, NULL); be_define_const_str(AudioFileSourceFS, "AudioFileSourceFS", 1839147653u, 0, 17, NULL); -be_define_const_str(AudioGenerator, "AudioGenerator", 1839297342u, 0, 14, NULL); -be_define_const_str(AudioGeneratorMP3, "AudioGeneratorMP3", 2199818488u, 0, 17, &be_const_str_color); -be_define_const_str(AudioGeneratorWAV, "AudioGeneratorWAV", 2746509368u, 0, 17, &be_const_str_offset); -be_define_const_str(AudioOpusDecoder, "AudioOpusDecoder", 1187272062u, 0, 16, &be_const_str_BRY_X3A_X20method_X20not_X20allowed_X2C_X20use_X20a_X20closure_X20like_X20_X27_X2F_X20args_X20_X2D_X3E_X20obj_X2Efunc_X28args_X29_X27); -be_define_const_str(AudioOutput, "AudioOutput", 3257792048u, 0, 11, &be_const_str_cb); -be_define_const_str(AudioOutputI2S, "AudioOutputI2S", 638031784u, 0, 14, &be_const_str_available); -be_define_const_str(Auto_X2Dconfiguration, "Auto-configuration", 1665006109u, 0, 18, &be_const_str_CFG_X3A_X20skipping_X20_X27display_X2Eini_X27_X20because_X20already_X20present_X20in_X20file_X2Dsystem); -be_define_const_str(BECDFE, "BECDFE", 608341218u, 0, 6, &be_const_str_millis); +be_define_const_str(AudioGenerator, "AudioGenerator", 1839297342u, 0, 14, &be_const_str_AudioGeneratorWAV); +be_define_const_str(AudioGeneratorMP3, "AudioGeneratorMP3", 2199818488u, 0, 17, &be_const_str_constructor_cb); +be_define_const_str(AudioGeneratorWAV, "AudioGeneratorWAV", 2746509368u, 0, 17, &be_const_str_add_rule); +be_define_const_str(AudioOpusDecoder, "AudioOpusDecoder", 1187272062u, 0, 16, &be_const_str__available); +be_define_const_str(AudioOutput, "AudioOutput", 3257792048u, 0, 11, &be_const_str_subtype_to_string); +be_define_const_str(AudioOutputI2S, "AudioOutputI2S", 638031784u, 0, 14, &be_const_str_decode); +be_define_const_str(Auto_X2Dconfiguration, "Auto-configuration", 1665006109u, 0, 18, &be_const_str_now); +be_define_const_str(BECDFE, "BECDFE", 608341218u, 0, 6, &be_const_str_add_header); be_define_const_str(BLE, "BLE", 3933843306u, 0, 3, NULL); -be_define_const_str(BRY_X3A_X20ERROR_X2C_X20bad_X20json_X3A_X20, "BRY: ERROR, bad json: ", 2715135809u, 0, 22, &be_const_str_set_height); -be_define_const_str(BRY_X3A_X20Exception_X3E_X20_X27, "BRY: Exception> '", 3883673906u, 0, 17, &be_const_str_get_object_from_ptr); -be_define_const_str(BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s, "BRY: Exception> '%s' - %s", 2246990964u, 0, 25, &be_const_str_content_send); -be_define_const_str(BRY_X3A_X20argument_X20must_X20be_X20a_X20function, "BRY: argument must be a function", 3917068408u, 0, 32, &be_const_str_invalidate_spiffs); -be_define_const_str(BRY_X3A_X20bytecode_X20has_X20wrong_X20version_X20_X27_X25s_X27_X20_X28_X25i_X29, "BRY: bytecode has wrong version '%s' (%i)", 2140321415u, 0, 41, &be_const_str_ins_ramp); -be_define_const_str(BRY_X3A_X20corrupt_X20bytecode_X20_X27_X25s_X27, "BRY: corrupt bytecode '%s'", 4009923544u, 0, 26, NULL); -be_define_const_str(BRY_X3A_X20could_X20not_X20save_X20compiled_X20file_X20_X25s_X20_X28_X25s_X29, "BRY: could not save compiled file %s (%s)", 736659787u, 0, 41, &be_const_str_event_send); -be_define_const_str(BRY_X3A_X20failed_X20to_X20load_X20_X27_X25s_X27_X20_X28_X25s_X20_X2D_X20_X25s_X29, "BRY: failed to load '%s' (%s - %s)", 1047433014u, 0, 34, NULL); -be_define_const_str(BRY_X3A_X20failed_X20to_X20load_X20_persist_X2Ejson, "BRY: failed to load _persist.json", 2991913445u, 0, 33, &be_const_str_remove_timer); -be_define_const_str(BRY_X3A_X20failed_X20to_X20load_X20compiled_X20_X27_X25s_X27_X20_X28_X25s_X29, "BRY: failed to load compiled '%s' (%s)", 3488122666u, 0, 38, &be_const_str_files); -be_define_const_str(BRY_X3A_X20failed_X20to_X20run_X20compiled_X20code_X20_X27_X25s_X27_X20_X2D_X20_X25s, "BRY: failed to run compiled code '%s' - %s", 380265962u, 0, 42, &be_const_str_autorun); -be_define_const_str(BRY_X3A_X20invalid_X20hue_X20payload_X3A_X20, "BRY: invalid hue payload: ", 203709367u, 0, 26, NULL); -be_define_const_str(BRY_X3A_X20method_X20not_X20allowed_X2C_X20use_X20a_X20closure_X20like_X20_X27_X2F_X20args_X20_X2D_X3E_X20obj_X2Efunc_X28args_X29_X27, "BRY: method not allowed, use a closure like '/ args -> obj.func(args)'", 177121572u, 0, 70, &be_const_str_connected); -be_define_const_str(BUTTON_CONFIGURATION, "BUTTON_CONFIGURATION", 70820856u, 0, 20, &be_const_str_get_warning_level); -be_define_const_str(CFG_X3A_X20_X27init_X2Ebat_X27_X20done_X2C_X20restarting, "CFG: 'init.bat' done, restarting", 1569670677u, 0, 32, &be_const_str_get_power); -be_define_const_str(CFG_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s, "CFG: Exception> '%s' - %s", 1228874553u, 0, 25, &be_const_str_exists); -be_define_const_str(CFG_X3A_X20No_X20_X27_X2A_X2Eautoconf_X27_X20file_X20found, "CFG: No '*.autoconf' file found", 755798501u, 0, 31, &be_const_str_eth); -be_define_const_str(CFG_X3A_X20could_X20not_X20run_X20_X25s_X20_X28_X25s_X20_X2D_X20_X25s_X29, "CFG: could not run %s (%s - %s)", 1428829580u, 0, 31, &be_const_str_tostring); -be_define_const_str(CFG_X3A_X20downloading_X20_X27_X25s_X27, "CFG: downloading '%s'", 589480701u, 0, 21, &be_const_str__begin_transmission); -be_define_const_str(CFG_X3A_X20exception_X20_X27_X25s_X27_X20_X2D_X20_X27_X25s_X27, "CFG: exception '%s' - '%s'", 4095407913u, 0, 26, &be_const_str_EVENT_DELETE); +be_define_const_str(BRY_X3A_X20ERROR_X2C_X20bad_X20json_X3A_X20, "BRY: ERROR, bad json: ", 2715135809u, 0, 22, &be_const_str_get_style_line_color); +be_define_const_str(BRY_X3A_X20Exception_X3E_X20_X27, "BRY: Exception> '", 3883673906u, 0, 17, NULL); +be_define_const_str(BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s, "BRY: Exception> '%s' - %s", 2246990964u, 0, 25, &be_const_str_copy); +be_define_const_str(BRY_X3A_X20argument_X20must_X20be_X20a_X20function, "BRY: argument must be a function", 3917068408u, 0, 32, &be_const_str_scr_act); +be_define_const_str(BRY_X3A_X20bytecode_X20has_X20wrong_X20version_X20_X27_X25s_X27_X20_X28_X25i_X29, "BRY: bytecode has wrong version '%s' (%i)", 2140321415u, 0, 41, &be_const_str_pop); +be_define_const_str(BRY_X3A_X20corrupt_X20bytecode_X20_X27_X25s_X27, "BRY: corrupt bytecode '%s'", 4009923544u, 0, 26, &be_const_str_SERIAL_8N1); +be_define_const_str(BRY_X3A_X20could_X20not_X20save_X20compiled_X20file_X20_X25s_X20_X28_X25s_X29, "BRY: could not save compiled file %s (%s)", 736659787u, 0, 41, &be_const_str__subscribe); +be_define_const_str(BRY_X3A_X20failed_X20to_X20load_X20_X27_X25s_X27_X20_X28_X25s_X20_X2D_X20_X25s_X29, "BRY: failed to load '%s' (%s - %s)", 1047433014u, 0, 34, &be_const_str_set_first_time); +be_define_const_str(BRY_X3A_X20failed_X20to_X20load_X20_persist_X2Ejson, "BRY: failed to load _persist.json", 2991913445u, 0, 33, &be_const_str_try_rule); +be_define_const_str(BRY_X3A_X20failed_X20to_X20load_X20compiled_X20_X27_X25s_X27_X20_X28_X25s_X29, "BRY: failed to load compiled '%s' (%s)", 3488122666u, 0, 38, &be_const_str_Unknown); +be_define_const_str(BRY_X3A_X20failed_X20to_X20run_X20compiled_X20code_X20_X27_X25s_X27_X20_X2D_X20_X25s, "BRY: failed to run compiled code '%s' - %s", 380265962u, 0, 42, &be_const_str_LVG_X3A_X20call_X20to_X20unsupported_X20callback); +be_define_const_str(BRY_X3A_X20invalid_X20hue_X20payload_X3A_X20, "BRY: invalid hue payload: ", 203709367u, 0, 26, &be_const_str_webserver); +be_define_const_str(BRY_X3A_X20method_X20not_X20allowed_X2C_X20use_X20a_X20closure_X20like_X20_X27_X2F_X20args_X20_X2D_X3E_X20obj_X2Efunc_X28args_X29_X27, "BRY: method not allowed, use a closure like '/ args -> obj.func(args)'", 177121572u, 0, 70, &be_const_str_SERIAL_5E2); +be_define_const_str(BUTTON_CONFIGURATION, "BUTTON_CONFIGURATION", 70820856u, 0, 20, &be_const_str_register_obj); +be_define_const_str(CFG_X3A_X20_X27init_X2Ebat_X27_X20done_X2C_X20restarting, "CFG: 'init.bat' done, restarting", 1569670677u, 0, 32, &be_const_str_set_MAC); +be_define_const_str(CFG_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s, "CFG: Exception> '%s' - %s", 1228874553u, 0, 25, &be_const_str_exp); +be_define_const_str(CFG_X3A_X20No_X20_X27_X2A_X2Eautoconf_X27_X20file_X20found, "CFG: No '*.autoconf' file found", 755798501u, 0, 31, &be_const_str_lv_style_prop_arr); +be_define_const_str(CFG_X3A_X20could_X20not_X20run_X20_X25s_X20_X28_X25s_X20_X2D_X20_X25s_X29, "CFG: could not run %s (%s - %s)", 1428829580u, 0, 31, NULL); +be_define_const_str(CFG_X3A_X20downloading_X20_X27_X25s_X27, "CFG: downloading '%s'", 589480701u, 0, 21, NULL); +be_define_const_str(CFG_X3A_X20exception_X20_X27_X25s_X27_X20_X2D_X20_X27_X25s_X27, "CFG: exception '%s' - '%s'", 4095407913u, 0, 26, &be_const_str__fl); be_define_const_str(CFG_X3A_X20loaded_X20_X20, "CFG: loaded ", 3710273538u, 0, 13, NULL); -be_define_const_str(CFG_X3A_X20loaded_X20_X27_X25s_X27, "CFG: loaded '%s'", 1699028828u, 0, 16, &be_const_str_create_custom_widget); -be_define_const_str(CFG_X3A_X20loading_X20, "CFG: loading ", 4010361503u, 0, 13, NULL); -be_define_const_str(CFG_X3A_X20loading_X20_X27_X25s_X27, "CFG: loading '%s'", 2285306097u, 0, 17, &be_const_str_calldepth); -be_define_const_str(CFG_X3A_X20multiple_X20autoconf_X20files_X20found_X2C_X20aborting_X20_X28_X27_X25s_X27_X20_X2B_X20_X27_X25s_X27_X29, "CFG: multiple autoconf files found, aborting ('%s' + '%s')", 197663371u, 0, 58, &be_const_str_floor); -be_define_const_str(CFG_X3A_X20ran_X20_X20, "CFG: ran ", 3579570472u, 0, 10, &be_const_str_tanh); -be_define_const_str(CFG_X3A_X20removed_X20file_X20_X27_X25s_X27, "CFG: removed file '%s'", 2048602473u, 0, 22, NULL); -be_define_const_str(CFG_X3A_X20removing_X20autoconf_X20files, "CFG: removing autoconf files", 4014704970u, 0, 28, &be_const_str_clear_to); -be_define_const_str(CFG_X3A_X20removing_X20first_X20time_X20marker, "CFG: removing first time marker", 2125556683u, 0, 31, &be_const_str_ctypes_bytes); -be_define_const_str(CFG_X3A_X20return_code_X3D_X25i, "CFG: return_code=%i", 2059897320u, 0, 19, &be_const_str___lower__); -be_define_const_str(CFG_X3A_X20running_X20, "CFG: running ", 2478334534u, 0, 13, &be_const_str_round_start); -be_define_const_str(CFG_X3A_X20skipping_X20_X27display_X2Eini_X27_X20because_X20already_X20present_X20in_X20file_X2Dsystem, "CFG: skipping 'display.ini' because already present in file-system", 3965549264u, 0, 66, &be_const_str_matrix); -be_define_const_str(COLOR_BLACK, "COLOR_BLACK", 264427940u, 0, 11, &be_const_str_ceil); -be_define_const_str(COLOR_WHITE, "COLOR_WHITE", 2536871270u, 0, 11, NULL); -be_define_const_str(CT, "CT", 1792671826u, 0, 2, &be_const_str_zip); -be_define_const_str(DIMMER, "DIMMER", 4049308363u, 0, 6, &be_const_str_driver_name); -be_define_const_str(EBEBFFFFFFFFFFFFFFFFFFFFFFFFFFFF, "EBEBFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 3217293201u, 0, 32, &be_const_str_POST); -be_define_const_str(EC_C25519, "EC_C25519", 95492591u, 0, 9, &be_const_str_ip); -be_define_const_str(EVENT_DELETE, "EVENT_DELETE", 282828603u, 0, 12, &be_const_str_Parameter_X20error); -be_define_const_str(EVENT_DRAW_MAIN, "EVENT_DRAW_MAIN", 1955620614u, 0, 15, &be_const_str_o); +be_define_const_str(CFG_X3A_X20loaded_X20_X27_X25s_X27, "CFG: loaded '%s'", 1699028828u, 0, 16, &be_const_str_SERIAL_5E1); +be_define_const_str(CFG_X3A_X20loading_X20, "CFG: loading ", 4010361503u, 0, 13, &be_const_str_persist_X2E_p_X20is_X20not_X20a_X20map); +be_define_const_str(CFG_X3A_X20loading_X20_X27_X25s_X27, "CFG: loading '%s'", 2285306097u, 0, 17, &be_const_str_cos); +be_define_const_str(CFG_X3A_X20multiple_X20autoconf_X20files_X20found_X2C_X20aborting_X20_X28_X27_X25s_X27_X20_X2B_X20_X27_X25s_X27_X29, "CFG: multiple autoconf files found, aborting ('%s' + '%s')", 197663371u, 0, 58, &be_const_str_json_fdump_any); +be_define_const_str(CFG_X3A_X20ran_X20_X20, "CFG: ran ", 3579570472u, 0, 10, &be_const_str_clear_first_time); +be_define_const_str(CFG_X3A_X20removed_X20file_X20_X27_X25s_X27, "CFG: removed file '%s'", 2048602473u, 0, 22, &be_const_str_MI32); +be_define_const_str(CFG_X3A_X20removing_X20autoconf_X20files, "CFG: removing autoconf files", 4014704970u, 0, 28, &be_const_str_isrunning); +be_define_const_str(CFG_X3A_X20removing_X20first_X20time_X20marker, "CFG: removing first time marker", 2125556683u, 0, 31, &be_const_str_json_append); +be_define_const_str(CFG_X3A_X20return_code_X3D_X25i, "CFG: return_code=%i", 2059897320u, 0, 19, &be_const_str_set_xy); +be_define_const_str(CFG_X3A_X20running_X20, "CFG: running ", 2478334534u, 0, 13, &be_const_str_add_event_cb); +be_define_const_str(CFG_X3A_X20skipping_X20_X27display_X2Eini_X27_X20because_X20already_X20present_X20in_X20file_X2Dsystem, "CFG: skipping 'display.ini' because already present in file-system", 3965549264u, 0, 66, &be_const_str_sat); +be_define_const_str(COLOR_BLACK, "COLOR_BLACK", 264427940u, 0, 11, &be_const_str_set_y); +be_define_const_str(COLOR_WHITE, "COLOR_WHITE", 2536871270u, 0, 11, &be_const_str_None); +be_define_const_str(CT, "CT", 1792671826u, 0, 2, &be_const_str_code); +be_define_const_str(DIMMER, "DIMMER", 4049308363u, 0, 6, &be_const_str_argument_X20must_X20be_X20a_X20function); +be_define_const_str(EBEBFFFFFFFFFFFFFFFFFFFFFFFFFFFF, "EBEBFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 3217293201u, 0, 32, &be_const_str_invalidate_spiffs); +be_define_const_str(EC_C25519, "EC_C25519", 95492591u, 0, 9, &be_const_str_elif); +be_define_const_str(EVENT_DELETE, "EVENT_DELETE", 282828603u, 0, 12, &be_const_str_SERIAL_6O2); +be_define_const_str(EVENT_DRAW_MAIN, "EVENT_DRAW_MAIN", 1955620614u, 0, 15, &be_const_str_destructor_cb); be_define_const_str(EVENT_DRAW_PART_BEGIN, "EVENT_DRAW_PART_BEGIN", 3391865024u, 0, 21, NULL); -be_define_const_str(EVENT_DRAW_PART_END, "EVENT_DRAW_PART_END", 3301625292u, 0, 19, &be_const_str_get_cb_list); -be_define_const_str(EXTERNAL_I2S, "EXTERNAL_I2S", 4067456169u, 0, 12, &be_const_str__crons); -be_define_const_str(FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 2684107141u, 0, 48, &be_const_str_lv_event_cb); -be_define_const_str(False, "False", 2541049336u, 0, 5, NULL); -be_define_const_str(GET, "GET", 2531704439u, 0, 3, NULL); -be_define_const_str(HTTP_GET, "HTTP_GET", 1722467738u, 0, 8, &be_const_str_rad); -be_define_const_str(HTTP_POST, "HTTP_POST", 1999554144u, 0, 9, &be_const_str_remove); -be_define_const_str(I2C_X3A, "I2C:", 813483371u, 0, 4, &be_const_str_log); -be_define_const_str(I2C_Driver, "I2C_Driver", 1714501658u, 0, 10, NULL); -be_define_const_str(INTERNAL_DAC, "INTERNAL_DAC", 1097623719u, 0, 12, NULL); -be_define_const_str(INTERNAL_PDM, "INTERNAL_PDM", 3043685628u, 0, 12, &be_const_str_day); -be_define_const_str(Invalid_X20ota_X20partition_X20number, "Invalid ota partition number", 1611602265u, 0, 28, NULL); -be_define_const_str(LVG_X3A_X20call_X20to_X20unsupported_X20callback, "LVG: call to unsupported callback", 504176819u, 0, 33, NULL); -be_define_const_str(Leds, "Leds", 2709245275u, 0, 4, NULL); -be_define_const_str(MAX_RMT, "MAX_RMT", 1615574873u, 0, 7, &be_const_str_int64); -be_define_const_str(MD5, "MD5", 1935726387u, 0, 3, &be_const_str_web_add_handler); -be_define_const_str(MI32, "MI32", 4074273414u, 0, 4, &be_const_str_loop); -be_define_const_str(No_X20SPIFFS_X20partition_X20found, "No SPIFFS partition found", 4165718279u, 0, 25, &be_const_str_write); -be_define_const_str(None, "None", 810547195u, 0, 4, &be_const_str_destructor_cb); -be_define_const_str(OPTION_A, "OPTION_A", 1133299440u, 0, 8, &be_const_str_imax); -be_define_const_str(OneWire, "OneWire", 2298990722u, 0, 7, NULL); -be_define_const_str(PART_MAIN, "PART_MAIN", 2473491508u, 0, 9, &be_const_str_init_draw_arc_dsc); -be_define_const_str(POST, "POST", 1929554311u, 0, 4, &be_const_str_reverse); -be_define_const_str(Parameter_X20error, "Parameter error", 3840042038u, 0, 15, &be_const_str_draw_ctx); -be_define_const_str(Partition, "Partition", 3077057705u, 0, 9, &be_const_str_arc_dsc); -be_define_const_str(Partition_info, "Partition_info", 3970922042u, 0, 14, &be_const_str_remove_cmd); -be_define_const_str(Partition_otadata, "Partition_otadata", 2666256496u, 0, 17, &be_const_str_list_handlers); -be_define_const_str(RELAY, "RELAY", 2163786658u, 0, 5, &be_const_str_Tele); -be_define_const_str(RES_OK, "RES_OK", 1233817284u, 0, 6, &be_const_str_persist); -be_define_const_str(RGB, "RGB", 3386082140u, 0, 3, NULL); -be_define_const_str(RGBCT, "RGBCT", 8076251u, 0, 5, &be_const_str_True); -be_define_const_str(RGBW, "RGBW", 3270986321u, 0, 4, &be_const_str_autoexec); -be_define_const_str(Restart_X201, "Restart 1", 3504455855u, 0, 9, &be_const_str_module); -be_define_const_str(SERIAL_5E1, "SERIAL_5E1", 1163775235u, 0, 10, &be_const_str_full_state); -be_define_const_str(SERIAL_5E2, "SERIAL_5E2", 1180552854u, 0, 10, &be_const_str_is_first_time); -be_define_const_str(SERIAL_5N1, "SERIAL_5N1", 3313031680u, 0, 10, &be_const_str_valuer_error); -be_define_const_str(SERIAL_5N2, "SERIAL_5N2", 3363364537u, 0, 10, &be_const_str_readline); -be_define_const_str(SERIAL_5O1, "SERIAL_5O1", 3782657917u, 0, 10, &be_const_str_has_factory); -be_define_const_str(SERIAL_5O2, "SERIAL_5O2", 3732325060u, 0, 10, &be_const_str_SERIAL_8N1); -be_define_const_str(SERIAL_6E1, "SERIAL_6E1", 334249486u, 0, 10, &be_const_str_gen_cb); -be_define_const_str(SERIAL_6E2, "SERIAL_6E2", 317471867u, 0, 10, &be_const_str_next); -be_define_const_str(SERIAL_6N1, "SERIAL_6N1", 198895701u, 0, 10, &be_const_str_arg); -be_define_const_str(SERIAL_6N2, "SERIAL_6N2", 148562844u, 0, 10, &be_const_str_local); -be_define_const_str(SERIAL_6O1, "SERIAL_6O1", 266153272u, 0, 10, &be_const_str_reapply); -be_define_const_str(SERIAL_6O2, "SERIAL_6O2", 316486129u, 0, 10, &be_const_str_web_add_main_button); -be_define_const_str(SERIAL_7E1, "SERIAL_7E1", 147718061u, 0, 10, &be_const_str_area); -be_define_const_str(SERIAL_7E2, "SERIAL_7E2", 97385204u, 0, 10, &be_const_str_adv_block); -be_define_const_str(SERIAL_7N1, "SERIAL_7N1", 1891060246u, 0, 10, &be_const_str_assign_rmt); -be_define_const_str(SERIAL_7N2, "SERIAL_7N2", 1874282627u, 0, 10, &be_const_str_crc8); -be_define_const_str(SERIAL_7O1, "SERIAL_7O1", 1823802675u, 0, 10, &be_const_str_resolvecmnd); -be_define_const_str(SERIAL_7O2, "SERIAL_7O2", 1840580294u, 0, 10, &be_const_str_counters); -be_define_const_str(SERIAL_8E1, "SERIAL_8E1", 2371121616u, 0, 10, &be_const_str_super); -be_define_const_str(SERIAL_8E2, "SERIAL_8E2", 2421454473u, 0, 10, &be_const_str_instance); -be_define_const_str(SERIAL_8N1, "SERIAL_8N1", 2369297235u, 0, 10, &be_const_str_abs); -be_define_const_str(SERIAL_8N2, "SERIAL_8N2", 2386074854u, 0, 10, &be_const_str_copy); -be_define_const_str(SERIAL_8O1, "SERIAL_8O1", 289122742u, 0, 10, &be_const_str_alternate); -be_define_const_str(SERIAL_8O2, "SERIAL_8O2", 272345123u, 0, 10, &be_const_str_consume_stereo); -be_define_const_str(SK6812_GRBW, "SK6812_GRBW", 81157857u, 0, 11, NULL); -be_define_const_str(STATE_DEFAULT, "STATE_DEFAULT", 712406428u, 0, 13, &be_const_str__ccmd); -be_define_const_str(TAP_X3A_X20Loaded_X20Tasmota_X20App_X20_X27_X25s_X27, "TAP: Loaded Tasmota App '%s'", 926477145u, 0, 28, &be_const_str__X5D_X2C_X0A_X20_X20); +be_define_const_str(EVENT_DRAW_PART_END, "EVENT_DRAW_PART_END", 3301625292u, 0, 19, &be_const_str__t); +be_define_const_str(EXTERNAL_I2S, "EXTERNAL_I2S", 4067456169u, 0, 12, &be_const_str_HTTP_POST); +be_define_const_str(FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 2684107141u, 0, 48, &be_const_str_Leds); +be_define_const_str(False, "False", 2541049336u, 0, 5, &be_const_str_format); +be_define_const_str(GET, "GET", 2531704439u, 0, 3, &be_const_str_fast_loop); +be_define_const_str(HTTP_GET, "HTTP_GET", 1722467738u, 0, 8, NULL); +be_define_const_str(HTTP_POST, "HTTP_POST", 1999554144u, 0, 9, NULL); +be_define_const_str(I2C_X3A, "I2C:", 813483371u, 0, 4, &be_const_str_from_to); +be_define_const_str(I2C_Driver, "I2C_Driver", 1714501658u, 0, 10, &be_const_str_frombytes); +be_define_const_str(INTERNAL_DAC, "INTERNAL_DAC", 1097623719u, 0, 12, &be_const_str_Partition_info); +be_define_const_str(INTERNAL_PDM, "INTERNAL_PDM", 3043685628u, 0, 12, &be_const_str_load_otadata); +be_define_const_str(Invalid_X20ota_X20partition_X20number, "Invalid ota partition number", 1611602265u, 0, 28, &be_const_str_pin); +be_define_const_str(LVG_X3A_X20call_X20to_X20unsupported_X20callback, "LVG: call to unsupported callback", 504176819u, 0, 33, &be_const_str__ccmd); +be_define_const_str(Leds, "Leds", 2709245275u, 0, 4, &be_const_str__energy); +be_define_const_str(MAX_RMT, "MAX_RMT", 1615574873u, 0, 7, &be_const_str_leds); +be_define_const_str(MD5, "MD5", 1935726387u, 0, 3, &be_const_str_refr_size); +be_define_const_str(MI32, "MI32", 4074273414u, 0, 4, &be_const_str_RGBCT); +be_define_const_str(No_X20SPIFFS_X20partition_X20found, "No SPIFFS partition found", 4165718279u, 0, 25, &be_const_str_get_size); +be_define_const_str(None, "None", 810547195u, 0, 4, NULL); +be_define_const_str(OPTION_A, "OPTION_A", 1133299440u, 0, 8, &be_const_str__dirty); +be_define_const_str(OneWire, "OneWire", 2298990722u, 0, 7, &be_const_str_Parameter_X20error); +be_define_const_str(PART_MAIN, "PART_MAIN", 2473491508u, 0, 9, &be_const_str_a); +be_define_const_str(POST, "POST", 1929554311u, 0, 4, &be_const_str_read_bytes); +be_define_const_str(Parameter_X20error, "Parameter error", 3840042038u, 0, 15, NULL); +be_define_const_str(Partition, "Partition", 3077057705u, 0, 9, &be_const_str_push_path); +be_define_const_str(Partition_info, "Partition_info", 3970922042u, 0, 14, &be_const_str_ceil); +be_define_const_str(Partition_otadata, "Partition_otadata", 2666256496u, 0, 17, &be_const_str_break); +be_define_const_str(RELAY, "RELAY", 2163786658u, 0, 5, &be_const_str_clear); +be_define_const_str(RES_OK, "RES_OK", 1233817284u, 0, 6, &be_const_str_page_autoconf_mgr); +be_define_const_str(RGB, "RGB", 3386082140u, 0, 3, &be_const_str__change_buffer); +be_define_const_str(RGBCT, "RGBCT", 8076251u, 0, 5, &be_const_str_maxota); +be_define_const_str(RGBW, "RGBW", 3270986321u, 0, 4, &be_const_str_every_250ms); +be_define_const_str(Restart_X201, "Restart 1", 3504455855u, 0, 9, &be_const_str_instance); +be_define_const_str(SERIAL_5E1, "SERIAL_5E1", 1163775235u, 0, 10, &be_const_str_get_event_cb); +be_define_const_str(SERIAL_5E2, "SERIAL_5E2", 1180552854u, 0, 10, &be_const_str_open); +be_define_const_str(SERIAL_5N1, "SERIAL_5N1", 3313031680u, 0, 10, &be_const_str_set_svc); +be_define_const_str(SERIAL_5N2, "SERIAL_5N2", 3363364537u, 0, 10, &be_const_str_addr); +be_define_const_str(SERIAL_5O1, "SERIAL_5O1", 3782657917u, 0, 10, &be_const_str_setfloat); +be_define_const_str(SERIAL_5O2, "SERIAL_5O2", 3732325060u, 0, 10, &be_const_str_exists); +be_define_const_str(SERIAL_6E1, "SERIAL_6E1", 334249486u, 0, 10, &be_const_str_set_style_img_recolor_opa); +be_define_const_str(SERIAL_6E2, "SERIAL_6E2", 317471867u, 0, 10, &be_const_str_consume_silence); +be_define_const_str(SERIAL_6N1, "SERIAL_6N1", 198895701u, 0, 10, &be_const_str_month); +be_define_const_str(SERIAL_6N2, "SERIAL_6N2", 148562844u, 0, 10, &be_const_str_rad); +be_define_const_str(SERIAL_6O1, "SERIAL_6O1", 266153272u, 0, 10, NULL); +be_define_const_str(SERIAL_6O2, "SERIAL_6O2", 316486129u, 0, 10, &be_const_str_groups); +be_define_const_str(SERIAL_7E1, "SERIAL_7E1", 147718061u, 0, 10, &be_const_str_battery_present); +be_define_const_str(SERIAL_7E2, "SERIAL_7E2", 97385204u, 0, 10, &be_const_str_ct); +be_define_const_str(SERIAL_7N1, "SERIAL_7N1", 1891060246u, 0, 10, &be_const_str_flash); +be_define_const_str(SERIAL_7N2, "SERIAL_7N2", 1874282627u, 0, 10, NULL); +be_define_const_str(SERIAL_7O1, "SERIAL_7O1", 1823802675u, 0, 10, &be_const_str_color); +be_define_const_str(SERIAL_7O2, "SERIAL_7O2", 1840580294u, 0, 10, NULL); +be_define_const_str(SERIAL_8E1, "SERIAL_8E1", 2371121616u, 0, 10, &be_const_str_event_send); +be_define_const_str(SERIAL_8E2, "SERIAL_8E2", 2421454473u, 0, 10, &be_const_str_crc8); +be_define_const_str(SERIAL_8N1, "SERIAL_8N1", 2369297235u, 0, 10, &be_const_str_back_forth); +be_define_const_str(SERIAL_8N2, "SERIAL_8N2", 2386074854u, 0, 10, &be_const_str_alternate); +be_define_const_str(SERIAL_8O1, "SERIAL_8O1", 289122742u, 0, 10, &be_const_str_b); +be_define_const_str(SERIAL_8O2, "SERIAL_8O2", 272345123u, 0, 10, &be_const_str_c); +be_define_const_str(SK6812_GRBW, "SK6812_GRBW", 81157857u, 0, 11, &be_const_str_char); +be_define_const_str(STATE_DEFAULT, "STATE_DEFAULT", 712406428u, 0, 13, &be_const_str__crons); +be_define_const_str(TAP_X3A_X20Loaded_X20Tasmota_X20App_X20_X27_X25s_X27, "TAP: Loaded Tasmota App '%s'", 926477145u, 0, 28, NULL); be_define_const_str(TASMOTA, "TASMOTA", 2487641028u, 0, 7, NULL); be_define_const_str(Tasmota, "Tasmota", 4047617668u, 0, 7, NULL); -be_define_const_str(Tele, "Tele", 1329980653u, 0, 4, &be_const_str_save_before_restart); -be_define_const_str(Too_X20many_X20partiition_X20slots, "Too many partiition slots", 3190277896u, 0, 25, &be_const_str__X5B); -be_define_const_str(Trigger, "Trigger", 2783579555u, 0, 7, &be_const_str_list); +be_define_const_str(Tele, "Tele", 1329980653u, 0, 4, NULL); +be_define_const_str(Too_X20many_X20partiition_X20slots, "Too many partiition slots", 3190277896u, 0, 25, NULL); +be_define_const_str(Trigger, "Trigger", 2783579555u, 0, 7, &be_const_str_invalid_X20magic_X20number_X20_X2502X); be_define_const_str(True, "True", 3453902341u, 0, 4, NULL); -be_define_const_str(Unknown, "Unknown", 3424652889u, 0, 7, &be_const_str_widget_constructor); -be_define_const_str(Unknown_X20command, "Unknown command", 1830905432u, 0, 15, &be_const_str_efuse_em); +be_define_const_str(Unknown, "Unknown", 3424652889u, 0, 7, &be_const_str_classof); +be_define_const_str(Unknown_X20command, "Unknown command", 1830905432u, 0, 15, NULL); be_define_const_str(WS2812, "WS2812", 3539741218u, 0, 6, NULL); -be_define_const_str(WS2812_GRB, "WS2812_GRB", 1736405692u, 0, 10, &be_const_str_set_ota_max); -be_define_const_str(Wire, "Wire", 1938276536u, 0, 4, NULL); -be_define_const_str(_X5B, "[", 3725336506u, 0, 1, &be_const_str_fast_loop_enabled); -be_define_const_str(_X5D, "]", 3624670792u, 0, 1, NULL); -be_define_const_str(_X5D_X2C_X0A_X20_X20, "],\n ", 2456223650u, 0, 5, &be_const_str_get_aps_voltage); -be_define_const_str(_, "_", 3658226030u, 0, 1, &be_const_str_call_native); -be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_time_reached); -be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, NULL); -be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_now); -be_define_const_str(_anonymous_, "_anonymous_", 1957281476u, 0, 11, NULL); -be_define_const_str(_archive, "_archive", 4004559404u, 0, 8, NULL); -be_define_const_str(_available, "_available", 1306196581u, 0, 10, &be_const_str_insert); -be_define_const_str(_begin_transmission, "_begin_transmission", 2779461176u, 0, 19, &be_const_str_crc16); +be_define_const_str(WS2812_GRB, "WS2812_GRB", 1736405692u, 0, 10, &be_const_str_get_pixel_color); +be_define_const_str(Wire, "Wire", 1938276536u, 0, 4, &be_const_str_add_fast_loop); +be_define_const_str(_X5B, "[", 3725336506u, 0, 1, &be_const_str_is_ota); +be_define_const_str(_X5D, "]", 3624670792u, 0, 1, &be_const_str_arc_dsc); +be_define_const_str(_X5D_X2C_X0A_X20_X20, "],\n ", 2456223650u, 0, 5, &be_const_str__p); +be_define_const_str(_, "_", 3658226030u, 0, 1, &be_const_str_draw_ctx); +be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_arg_X20must_X20be_X20a_X20subclass_X20of_X20lv_obj); +be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str__splash); +be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, NULL); +be_define_const_str(_anonymous_, "_anonymous_", 1957281476u, 0, 11, &be_const_str_create_matrix); +be_define_const_str(_archive, "_archive", 4004559404u, 0, 8, &be_const_str_nil); +be_define_const_str(_available, "_available", 1306196581u, 0, 10, NULL); +be_define_const_str(_begin_transmission, "_begin_transmission", 2779461176u, 0, 19, &be_const_str_digital_write); be_define_const_str(_buffer, "_buffer", 2044888568u, 0, 7, NULL); -be_define_const_str(_ccmd, "_ccmd", 2163421413u, 0, 5, &be_const_str_add_event_cb); -be_define_const_str(_change_buffer, "_change_buffer", 2101848693u, 0, 14, &be_const_str_allocated); -be_define_const_str(_class, "_class", 2732146350u, 0, 6, &be_const_str_round_end); -be_define_const_str(_cmd, "_cmd", 3419822142u, 0, 4, &be_const_str_display); -be_define_const_str(_crons, "_crons", 1000733579u, 0, 6, NULL); -be_define_const_str(_debug_present, "_debug_present", 4063411725u, 0, 14, &be_const_str_adv_watch); -be_define_const_str(_def, "_def", 1985022181u, 0, 4, &be_const_str_response_append); -be_define_const_str(_dirty, "_dirty", 283846766u, 0, 6, &be_const_str__global_addr); -be_define_const_str(_drivers, "_drivers", 3260328985u, 0, 8, NULL); -be_define_const_str(_end_transmission, "_end_transmission", 3237480400u, 0, 17, &be_const_str_json_fdump_any); -be_define_const_str(_energy, "_energy", 535372070u, 0, 7, &be_const_str_ismethod); -be_define_const_str(_error, "_error", 1132109656u, 0, 6, &be_const_str_exec_tele); -be_define_const_str(_filename, "_filename", 1430813195u, 0, 9, NULL); -be_define_const_str(_fl, "_fl", 4042564892u, 0, 3, &be_const_str_name); -be_define_const_str(_global_addr, "_global_addr", 533766721u, 0, 12, &be_const_str_ota_); -be_define_const_str(_global_def, "_global_def", 646007001u, 0, 11, &be_const_str_codedump); -be_define_const_str(_lvgl, "_lvgl", 2689219483u, 0, 5, &be_const_str_file); -be_define_const_str(_p, "_p", 1594591802u, 0, 2, &be_const_str_hue_ntv); -be_define_const_str(_persist_X2Ejson, "_persist.json", 2008425138u, 0, 13, &be_const_str_get_bat_voltage); +be_define_const_str(_ccmd, "_ccmd", 2163421413u, 0, 5, &be_const_str_decompress); +be_define_const_str(_change_buffer, "_change_buffer", 2101848693u, 0, 14, &be_const_str_area); +be_define_const_str(_class, "_class", 2732146350u, 0, 6, &be_const_str_json_fdump_map); +be_define_const_str(_cmd, "_cmd", 3419822142u, 0, 4, NULL); +be_define_const_str(_crons, "_crons", 1000733579u, 0, 6, &be_const_str_duration); +be_define_const_str(_debug_present, "_debug_present", 4063411725u, 0, 14, &be_const_str_every_50ms); +be_define_const_str(_def, "_def", 1985022181u, 0, 4, &be_const_str_public_key); +be_define_const_str(_dirty, "_dirty", 283846766u, 0, 6, &be_const_str_get_current_module_name); +be_define_const_str(_drivers, "_drivers", 3260328985u, 0, 8, &be_const_str_devices); +be_define_const_str(_end_transmission, "_end_transmission", 3237480400u, 0, 17, &be_const_str_add_cron); +be_define_const_str(_energy, "_energy", 535372070u, 0, 7, &be_const_str_global); +be_define_const_str(_error, "_error", 1132109656u, 0, 6, &be_const_str_setrange); +be_define_const_str(_filename, "_filename", 1430813195u, 0, 9, &be_const_str_create_segment); +be_define_const_str(_fl, "_fl", 4042564892u, 0, 3, &be_const_str_geti); +be_define_const_str(_get_bytes, "_get_bytes", 91696618u, 0, 10, &be_const_str__lvgl); +be_define_const_str(_global_addr, "_global_addr", 533766721u, 0, 12, &be_const_str_sin); +be_define_const_str(_global_def, "_global_def", 646007001u, 0, 11, NULL); +be_define_const_str(_lvgl, "_lvgl", 2689219483u, 0, 5, &be_const_str_remove_trailing_zeroes); +be_define_const_str(_p, "_p", 1594591802u, 0, 2, &be_const_str_asstring); +be_define_const_str(_persist_X2Ejson, "_persist.json", 2008425138u, 0, 13, &be_const_str_lv_wifi_arcs_icon); be_define_const_str(_ptr, "_ptr", 306235816u, 0, 4, NULL); -be_define_const_str(_read, "_read", 346717030u, 0, 5, &be_const_str__subscribe); -be_define_const_str(_request_from, "_request_from", 3965148604u, 0, 13, &be_const_str_size); -be_define_const_str(_rmt, "_rmt", 1094422685u, 0, 4, NULL); -be_define_const_str(_rules, "_rules", 4266217105u, 0, 6, &be_const_str_widget_dtor_impl); -be_define_const_str(_settings_def, "_settings_def", 3775560307u, 0, 13, &be_const_str_b); -be_define_const_str(_settings_ptr, "_settings_ptr", 1825772182u, 0, 13, &be_const_str_deinit); -be_define_const_str(_splash, "_splash", 3660617917u, 0, 7, &be_const_str_contains); -be_define_const_str(_subscribe, "_subscribe", 2888456770u, 0, 10, &be_const_str_cb_event_closure); -be_define_const_str(_t, "_t", 1527481326u, 0, 2, &be_const_str_data); -be_define_const_str(_timers, "_timers", 2600100916u, 0, 7, &be_const_str_char); -be_define_const_str(_validate, "_validate", 1742604448u, 0, 9, &be_const_str_lv_extra); -be_define_const_str(_write, "_write", 2215462825u, 0, 6, &be_const_str_listdir); -be_define_const_str(a, "a", 3826002220u, 0, 1, NULL); -be_define_const_str(abs, "abs", 709362235u, 0, 3, &be_const_str_bytes); -be_define_const_str(acos, "acos", 1006755615u, 0, 4, &be_const_str_resp_cmnd_done); -be_define_const_str(active_otadata, "active_otadata", 3055353486u, 0, 14, &be_const_str_get_style_bg_color); -be_define_const_str(add, "add", 993596020u, 0, 3, &be_const_str_quality); -be_define_const_str(add_anim, "add_anim", 3980662668u, 0, 8, &be_const_str_get_current_module_path); -be_define_const_str(add_cb_event_closure, "add_cb_event_closure", 1775958321u, 0, 20, NULL); -be_define_const_str(add_cmd, "add_cmd", 3361630879u, 0, 7, NULL); -be_define_const_str(add_cron, "add_cron", 2475327477u, 0, 8, &be_const_str_content_send_style); +be_define_const_str(_read, "_read", 346717030u, 0, 5, NULL); +be_define_const_str(_request_from, "_request_from", 3965148604u, 0, 13, NULL); +be_define_const_str(_rmt, "_rmt", 1094422685u, 0, 4, &be_const_str_srand); +be_define_const_str(_rules, "_rules", 4266217105u, 0, 6, &be_const_str_id); +be_define_const_str(_set_bytes, "_set_bytes", 3793929630u, 0, 10, &be_const_str_setbits); +be_define_const_str(_settings_def, "_settings_def", 3775560307u, 0, 13, &be_const_str_getfloat); +be_define_const_str(_settings_ptr, "_settings_ptr", 1825772182u, 0, 13, &be_const_str_tobytes); +be_define_const_str(_splash, "_splash", 3660617917u, 0, 7, &be_const_str_asin); +be_define_const_str(_subscribe, "_subscribe", 2888456770u, 0, 10, &be_const_str_delay); +be_define_const_str(_t, "_t", 1527481326u, 0, 2, &be_const_str_call); +be_define_const_str(_timers, "_timers", 2600100916u, 0, 7, &be_const_str_read24); +be_define_const_str(_validate, "_validate", 1742604448u, 0, 9, &be_const_str_consume_stereo); +be_define_const_str(_write, "_write", 2215462825u, 0, 6, &be_const_str_save); +be_define_const_str(a, "a", 3826002220u, 0, 1, &be_const_str_deinit); +be_define_const_str(abort, "abort", 2771110649u, 0, 5, &be_const_str_y); +be_define_const_str(abs, "abs", 709362235u, 0, 3, &be_const_str_ccronexpr); +be_define_const_str(acos, "acos", 1006755615u, 0, 4, &be_const_str_flags); +be_define_const_str(active_otadata, "active_otadata", 3055353486u, 0, 14, NULL); +be_define_const_str(add, "add", 993596020u, 0, 3, &be_const_str_select); +be_define_const_str(add_anim, "add_anim", 3980662668u, 0, 8, NULL); +be_define_const_str(add_cb_event_closure, "add_cb_event_closure", 1775958321u, 0, 20, &be_const_str_depower); +be_define_const_str(add_cmd, "add_cmd", 3361630879u, 0, 7, &be_const_str_before_del); +be_define_const_str(add_cron, "add_cron", 2475327477u, 0, 8, &be_const_str_run); be_define_const_str(add_driver, "add_driver", 1654458371u, 0, 10, NULL); -be_define_const_str(add_event_cb, "add_event_cb", 633097693u, 0, 12, &be_const_str_add_rule); -be_define_const_str(add_fast_loop, "add_fast_loop", 3025842946u, 0, 13, &be_const_str_y); -be_define_const_str(add_handler, "add_handler", 2055124119u, 0, 11, &be_const_str_pct); -be_define_const_str(add_header, "add_header", 927130612u, 0, 10, &be_const_str_draw_arc_dsc); -be_define_const_str(add_light, "add_light", 3169328603u, 0, 9, &be_const_str_bool); -be_define_const_str(add_rule, "add_rule", 596540743u, 0, 8, &be_const_str_refr_size); -be_define_const_str(addr, "addr", 1087856498u, 0, 4, &be_const_str_ct); -be_define_const_str(adv_block, "adv_block", 4243837184u, 0, 9, &be_const_str_cosh); -be_define_const_str(adv_cb, "adv_cb", 1957890034u, 0, 6, &be_const_str_get_alternate); -be_define_const_str(adv_watch, "adv_watch", 3871786950u, 0, 9, &be_const_str_init); +be_define_const_str(add_event_cb, "add_event_cb", 633097693u, 0, 12, &be_const_str_widget_event_cb); +be_define_const_str(add_fast_loop, "add_fast_loop", 3025842946u, 0, 13, &be_const_str_is_spiffs); +be_define_const_str(add_handler, "add_handler", 2055124119u, 0, 11, NULL); +be_define_const_str(add_header, "add_header", 927130612u, 0, 10, &be_const_str_log10); +be_define_const_str(add_light, "add_light", 3169328603u, 0, 9, &be_const_str_iter); +be_define_const_str(add_rule, "add_rule", 596540743u, 0, 8, &be_const_str_atleast1); +be_define_const_str(addr, "addr", 1087856498u, 0, 4, &be_const_str_get_hor_res); +be_define_const_str(adv_block, "adv_block", 4243837184u, 0, 9, &be_const_str_nvskeys); +be_define_const_str(adv_cb, "adv_cb", 1957890034u, 0, 6, &be_const_str_bus); +be_define_const_str(adv_watch, "adv_watch", 3871786950u, 0, 9, &be_const_str_fat); be_define_const_str(allocated, "allocated", 429986098u, 0, 9, NULL); -be_define_const_str(alternate, "alternate", 1140253277u, 0, 9, &be_const_str_remove_cron); -be_define_const_str(animate, "animate", 3885786800u, 0, 7, &be_const_str_collect); -be_define_const_str(animators, "animators", 279858213u, 0, 9, &be_const_str_load_templates); -be_define_const_str(app, "app", 527074092u, 0, 3, &be_const_str_content_button); -be_define_const_str(arc_dsc, "arc_dsc", 2768816310u, 0, 7, NULL); -be_define_const_str(arch, "arch", 2952804297u, 0, 4, &be_const_str_out_X20of_X20range); -be_define_const_str(area, "area", 2601460036u, 0, 4, &be_const_str_f); +be_define_const_str(alternate, "alternate", 1140253277u, 0, 9, &be_const_str_coredump); +be_define_const_str(animate, "animate", 3885786800u, 0, 7, NULL); +be_define_const_str(animators, "animators", 279858213u, 0, 9, &be_const_str_ip); +be_define_const_str(app, "app", 527074092u, 0, 3, &be_const_str_arg_size); +be_define_const_str(arc_dsc, "arc_dsc", 2768816310u, 0, 7, &be_const_str_rounded); +be_define_const_str(arch, "arch", 2952804297u, 0, 4, &be_const_str_elements_X20must_X20be_X20a_X20lv_point); +be_define_const_str(area, "area", 2601460036u, 0, 4, &be_const_str_get_height); be_define_const_str(arg, "arg", 1047474471u, 0, 3, NULL); -be_define_const_str(arg_X20must_X20be_X20a_X20subclass_X20of_X20lv_obj, "arg must be a subclass of lv_obj", 1641882079u, 0, 32, &be_const_str_content_start); -be_define_const_str(arg_name, "arg_name", 1345046155u, 0, 8, &be_const_str_reset_search); -be_define_const_str(arg_size, "arg_size", 3310243257u, 0, 8, &be_const_str_mqtt_listener); -be_define_const_str(argument_X20must_X20be_X20a_X20function, "argument must be a function", 527172389u, 0, 27, &be_const_str_clear_first_time); -be_define_const_str(argument_X20must_X20be_X20a_X20list, "argument must be a list", 3056915661u, 0, 23, &be_const_str_close); -be_define_const_str(argument_X20must_X20be_X20a_X20list_X20or_X20a_X20pointer_X2Bsize, "argument must be a list or a pointer+size", 241605448u, 0, 41, &be_const_str_lvgl_timer_dispatch); +be_define_const_str(arg_X20must_X20be_X20a_X20subclass_X20of_X20lv_obj, "arg must be a subclass of lv_obj", 1641882079u, 0, 32, NULL); +be_define_const_str(arg_name, "arg_name", 1345046155u, 0, 8, &be_const_str_top); +be_define_const_str(arg_size, "arg_size", 3310243257u, 0, 8, NULL); +be_define_const_str(argument_X20must_X20be_X20a_X20function, "argument must be a function", 527172389u, 0, 27, NULL); +be_define_const_str(argument_X20must_X20be_X20a_X20list, "argument must be a list", 3056915661u, 0, 23, &be_const_str_ctypes_bytes_dyn); +be_define_const_str(argument_X20must_X20be_X20a_X20list_X20or_X20a_X20pointer_X2Bsize, "argument must be a list or a pointer+size", 241605448u, 0, 41, &be_const_str_https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_manifest_X2Ejson); be_define_const_str(as, "as", 1579491469u, 67, 2, NULL); -be_define_const_str(asin, "asin", 4272848550u, 0, 4, &be_const_str_set_first_time); -be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_draw_line); -be_define_const_str(assign_rmt, "assign_rmt", 1047642576u, 0, 10, &be_const_str_lv_clock); -be_define_const_str(asstring, "asstring", 1298225088u, 0, 8, &be_const_str_battery_present); -be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_dimmer); -be_define_const_str(atan2, "atan2", 3173440503u, 0, 5, &be_const_str_refr_pos); -be_define_const_str(atleast1, "atleast1", 1956331672u, 0, 8, &be_const_str_crc32); -be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_set_bri); -be_define_const_str(autoexec, "autoexec", 3676861891u, 0, 8, &be_const_str_is_factory); -be_define_const_str(autorun, "autorun", 1447527407u, 0, 7, &be_const_str_get_style_line_color); -be_define_const_str(available, "available", 1727918744u, 0, 9, &be_const_str_load); -be_define_const_str(b, "b", 3876335077u, 0, 1, &be_const_str_check_not_method); -be_define_const_str(back_forth, "back_forth", 2665042062u, 0, 10, &be_const_str_style_prop_arr); +be_define_const_str(asin, "asin", 4272848550u, 0, 4, &be_const_str_dim); +be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_ptr); +be_define_const_str(assign_rmt, "assign_rmt", 1047642576u, 0, 10, &be_const_str_save_before_restart); +be_define_const_str(asstring, "asstring", 1298225088u, 0, 8, &be_const_str_set_exten); +be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_json); +be_define_const_str(atan2, "atan2", 3173440503u, 0, 5, &be_const_str_delete_all_configs); +be_define_const_str(atleast1, "atleast1", 1956331672u, 0, 8, &be_const_str_create_custom_widget); +be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_get_bat_voltage); +be_define_const_str(autoexec, "autoexec", 3676861891u, 0, 8, NULL); +be_define_const_str(autorun, "autorun", 1447527407u, 0, 7, &be_const_str_label); +be_define_const_str(available, "available", 1727918744u, 0, 9, &be_const_str_ins_goto); +be_define_const_str(b, "b", 3876335077u, 0, 1, &be_const_str_draw_arc); +be_define_const_str(back_forth, "back_forth", 2665042062u, 0, 10, &be_const_str_line_dsc); be_define_const_str(base_class, "base_class", 1107737279u, 0, 10, NULL); -be_define_const_str(battery_present, "battery_present", 3588397058u, 0, 15, &be_const_str_byte); -be_define_const_str(before_del, "before_del", 815924436u, 0, 10, &be_const_str_closure); -be_define_const_str(begin, "begin", 1748273790u, 0, 5, &be_const_str_light); +be_define_const_str(battery_present, "battery_present", 3588397058u, 0, 15, &be_const_str_fromstring); +be_define_const_str(before_del, "before_del", 815924436u, 0, 10, &be_const_str_set_text); +be_define_const_str(begin, "begin", 1748273790u, 0, 5, &be_const_str_switch_factory); be_define_const_str(begin_multicast, "begin_multicast", 57647915u, 0, 15, NULL); -be_define_const_str(bool, "bool", 3365180733u, 0, 4, &be_const_str_getfloat); +be_define_const_str(bool, "bool", 3365180733u, 0, 4, NULL); be_define_const_str(break, "break", 3378807160u, 58, 5, NULL); -be_define_const_str(bri, "bri", 2112284244u, 0, 3, &be_const_str_editable); -be_define_const_str(bus, "bus", 1607822841u, 0, 3, &be_const_str_dim); +be_define_const_str(bri, "bri", 2112284244u, 0, 3, NULL); +be_define_const_str(bus, "bus", 1607822841u, 0, 3, NULL); be_define_const_str(button_pressed, "button_pressed", 1694209616u, 0, 14, NULL); -be_define_const_str(byte, "byte", 1683620383u, 0, 4, &be_const_str_ptr); -be_define_const_str(bytes, "bytes", 1706151940u, 0, 5, &be_const_str_factory); -be_define_const_str(c, "c", 3859557458u, 0, 1, &be_const_str_crc); -be_define_const_str(call, "call", 3018949801u, 0, 4, &be_const_str_deg); -be_define_const_str(call_native, "call_native", 1389147405u, 0, 11, &be_const_str_every_250ms); -be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, &be_const_str_get_image_size); -be_define_const_str(can_show, "can_show", 960091187u, 0, 8, NULL); -be_define_const_str(cb, "cb", 1428787088u, 0, 2, NULL); -be_define_const_str(cb_do_nothing, "cb_do_nothing", 1488730702u, 0, 13, &be_const_str_decode); -be_define_const_str(cb_event_closure, "cb_event_closure", 3828267325u, 0, 16, &be_const_str_light_state); -be_define_const_str(cb_obj, "cb_obj", 1195696482u, 0, 6, NULL); -be_define_const_str(ccronexpr, "ccronexpr", 258146169u, 0, 9, &be_const_str_the_X20second_X20argument_X20is_X20not_X20a_X20function); -be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, &be_const_str_has); -be_define_const_str(char, "char", 2823553821u, 0, 4, &be_const_str_i2c_enabled); -be_define_const_str(chars_in_string, "chars_in_string", 3148785132u, 0, 15, &be_const_str_couldn_X27t_X20not_X20initialize_X20noepixelbus); -be_define_const_str(check_not_method, "check_not_method", 2597324607u, 0, 16, NULL); -be_define_const_str(check_privileged_access, "check_privileged_access", 3692933968u, 0, 23, NULL); +be_define_const_str(byte, "byte", 1683620383u, 0, 4, &be_const_str_efuse_em); +be_define_const_str(bytes, "bytes", 1706151940u, 0, 5, NULL); +be_define_const_str(c, "c", 3859557458u, 0, 1, &be_const_str_real); +be_define_const_str(call, "call", 3018949801u, 0, 4, &be_const_str_ismethod); +be_define_const_str(call_native, "call_native", 1389147405u, 0, 11, &be_const_str_name); +be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, NULL); +be_define_const_str(can_show, "can_show", 960091187u, 0, 8, &be_const_str_member); +be_define_const_str(cb, "cb", 1428787088u, 0, 2, &be_const_str_cb_obj); +be_define_const_str(cb_do_nothing, "cb_do_nothing", 1488730702u, 0, 13, &be_const_str_get_temp); +be_define_const_str(cb_event_closure, "cb_event_closure", 3828267325u, 0, 16, &be_const_str_resp_cmnd_error); +be_define_const_str(cb_obj, "cb_obj", 1195696482u, 0, 6, &be_const_str_widget_ctor_impl); +be_define_const_str(ccronexpr, "ccronexpr", 258146169u, 0, 9, &be_const_str_h); +be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, &be_const_str_file); +be_define_const_str(char, "char", 2823553821u, 0, 4, &be_const_str_set_ldo_voltage); +be_define_const_str(chars_in_string, "chars_in_string", 3148785132u, 0, 15, NULL); +be_define_const_str(check_not_method, "check_not_method", 2597324607u, 0, 16, &be_const_str_crc); +be_define_const_str(check_privileged_access, "check_privileged_access", 3692933968u, 0, 23, &be_const_str_var); be_define_const_str(class, "class", 2872970239u, 57, 5, NULL); -be_define_const_str(class_init_obj, "class_init_obj", 178410604u, 0, 14, &be_const_str_img); -be_define_const_str(classname, "classname", 1998589948u, 0, 9, &be_const_str_invalidate); -be_define_const_str(classof, "classof", 1796577762u, 0, 7, NULL); -be_define_const_str(clear, "clear", 1550717474u, 0, 5, &be_const_str_every_100ms); -be_define_const_str(clear_first_time, "clear_first_time", 632769909u, 0, 16, NULL); -be_define_const_str(clear_to, "clear_to", 3528002130u, 0, 8, &be_const_str_web_add_config_button); -be_define_const_str(clock, "clock", 363073373u, 0, 5, NULL); -be_define_const_str(clock_icon, "clock_icon", 544669651u, 0, 10, &be_const_str_send); -be_define_const_str(close, "close", 667630371u, 0, 5, &be_const_str_lv_wifi_bars); -be_define_const_str(closure, "closure", 1548407746u, 0, 7, NULL); -be_define_const_str(cmd, "cmd", 4136785899u, 0, 3, &be_const_str_json); +be_define_const_str(class_init_obj, "class_init_obj", 178410604u, 0, 14, &be_const_str_light_state); +be_define_const_str(classname, "classname", 1998589948u, 0, 9, &be_const_str_content_flush); +be_define_const_str(classof, "classof", 1796577762u, 0, 7, &be_const_str_light); +be_define_const_str(clear, "clear", 1550717474u, 0, 5, &be_const_str_trig); +be_define_const_str(clear_first_time, "clear_first_time", 632769909u, 0, 16, &be_const_str_deg); +be_define_const_str(clear_to, "clear_to", 3528002130u, 0, 8, &be_const_str_tan); +be_define_const_str(clock, "clock", 363073373u, 0, 5, &be_const_str_set_bat); +be_define_const_str(clock_icon, "clock_icon", 544669651u, 0, 10, &be_const_str_cosh); +be_define_const_str(close, "close", 667630371u, 0, 5, &be_const_str_gamma); +be_define_const_str(closure, "closure", 1548407746u, 0, 7, &be_const_str_get_aps_voltage); +be_define_const_str(cmd, "cmd", 4136785899u, 0, 3, &be_const_str_get_current_module_path); be_define_const_str(cmd_res, "cmd_res", 921166762u, 0, 7, NULL); -be_define_const_str(code, "code", 4180765940u, 0, 4, &be_const_str_set_temp); +be_define_const_str(code, "code", 4180765940u, 0, 4, &be_const_str_get_switch); be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, NULL); be_define_const_str(collect, "collect", 2399039025u, 0, 7, NULL); -be_define_const_str(color, "color", 1031692888u, 0, 5, &be_const_str_get_height); -be_define_const_str(compile, "compile", 1000265118u, 0, 7, &be_const_str_get_option); -be_define_const_str(compress, "compress", 2818084237u, 0, 8, &be_const_str_open); -be_define_const_str(concat, "concat", 4124019837u, 0, 6, &be_const_str_pin_used); -be_define_const_str(conn_cb, "conn_cb", 1381122945u, 0, 7, NULL); -be_define_const_str(connect, "connect", 2866859257u, 0, 7, &be_const_str_lvgl_event_dispatch); -be_define_const_str(connected, "connected", 1424938192u, 0, 9, &be_const_str_from_to); -be_define_const_str(connection_error, "connection_error", 1358926260u, 0, 16, &be_const_str_lv_clock_icon); +be_define_const_str(color, "color", 1031692888u, 0, 5, NULL); +be_define_const_str(compile, "compile", 1000265118u, 0, 7, NULL); +be_define_const_str(compress, "compress", 2818084237u, 0, 8, &be_const_str_remove_rule); +be_define_const_str(concat, "concat", 4124019837u, 0, 6, &be_const_str_log); +be_define_const_str(conn_cb, "conn_cb", 1381122945u, 0, 7, &be_const_str_lv_signal_bars); +be_define_const_str(connect, "connect", 2866859257u, 0, 7, NULL); +be_define_const_str(connected, "connected", 1424938192u, 0, 9, &be_const_str_read13); +be_define_const_str(connection_error, "connection_error", 1358926260u, 0, 16, NULL); be_define_const_str(constructor_cb, "constructor_cb", 2489105297u, 0, 14, NULL); -be_define_const_str(consume_mono, "consume_mono", 3577563453u, 0, 12, NULL); -be_define_const_str(consume_silence, "consume_silence", 1445390925u, 0, 15, &be_const_str_set_gain); -be_define_const_str(consume_stereo, "consume_stereo", 1834661098u, 0, 14, &be_const_str_get_switch); -be_define_const_str(contains, "contains", 1825239352u, 0, 8, &be_const_str_power_off); -be_define_const_str(content_button, "content_button", 1956476087u, 0, 14, &be_const_str_fast_loop); -be_define_const_str(content_flush, "content_flush", 214922475u, 0, 13, &be_const_str_min); -be_define_const_str(content_response, "content_response", 3881475860u, 0, 16, &be_const_str_detect); -be_define_const_str(content_send, "content_send", 1673733649u, 0, 12, &be_const_str_members); -be_define_const_str(content_send_style, "content_send_style", 1087907647u, 0, 18, NULL); -be_define_const_str(content_start, "content_start", 2937509069u, 0, 13, &be_const_str_json_append); +be_define_const_str(consume_mono, "consume_mono", 3577563453u, 0, 12, &be_const_str_editable); +be_define_const_str(consume_silence, "consume_silence", 1445390925u, 0, 15, &be_const_str_count); +be_define_const_str(consume_stereo, "consume_stereo", 1834661098u, 0, 14, &be_const_str_draw_arc_dsc); +be_define_const_str(contains, "contains", 1825239352u, 0, 8, NULL); +be_define_const_str(content_button, "content_button", 1956476087u, 0, 14, NULL); +be_define_const_str(content_flush, "content_flush", 214922475u, 0, 13, &be_const_str_get_image_size); +be_define_const_str(content_response, "content_response", 3881475860u, 0, 16, NULL); +be_define_const_str(content_send, "content_send", 1673733649u, 0, 12, &be_const_str_driver_name); +be_define_const_str(content_send_style, "content_send_style", 1087907647u, 0, 18, &be_const_str_toupper); +be_define_const_str(content_start, "content_start", 2937509069u, 0, 13, &be_const_str_counters); be_define_const_str(content_stop, "content_stop", 658554751u, 0, 12, NULL); be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL); be_define_const_str(coord_arr, "coord_arr", 4189963658u, 0, 9, NULL); -be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_groups); -be_define_const_str(coredump, "coredump", 2141225116u, 0, 8, NULL); -be_define_const_str(cos, "cos", 4220379804u, 0, 3, &be_const_str_issubclass); -be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, &be_const_str_publish); -be_define_const_str(couldn_X27t_X20not_X20initialize_X20noepixelbus, "couldn't not initialize noepixelbus", 2536490812u, 0, 35, &be_const_str_except); -be_define_const_str(count, "count", 967958004u, 0, 5, &be_const_str_seti); -be_define_const_str(counters, "counters", 4095866864u, 0, 8, NULL); -be_define_const_str(crc, "crc", 3812935353u, 0, 3, &be_const_str_ctor); -be_define_const_str(crc16, "crc16", 3504496746u, 0, 5, &be_const_str_display_X2Eini); -be_define_const_str(crc32, "crc32", 3571901412u, 0, 5, &be_const_str_tasmota_log_reader); -be_define_const_str(crc32_ota_seq, "crc32_ota_seq", 172417u, 0, 13, &be_const_str_minute); -be_define_const_str(crc8, "crc8", 1178893587u, 0, 4, &be_const_str_set_x); -be_define_const_str(create_custom_widget, "create_custom_widget", 1140594778u, 0, 20, &be_const_str_is_ota); -be_define_const_str(create_matrix, "create_matrix", 3528185923u, 0, 13, &be_const_str_dirty); -be_define_const_str(create_segment, "create_segment", 3863522719u, 0, 14, NULL); -be_define_const_str(ct, "ct", 1261010898u, 0, 2, NULL); -be_define_const_str(ctor, "ctor", 375399343u, 0, 4, &be_const_str_obj_event_base); -be_define_const_str(ctypes_bytes, "ctypes_bytes", 3879019703u, 0, 12, &be_const_str_lv_event); -be_define_const_str(ctypes_bytes_dyn, "ctypes_bytes_dyn", 915205307u, 0, 16, &be_const_str_int); -be_define_const_str(dac_voltage, "dac_voltage", 1552257222u, 0, 11, &be_const_str_set_pwm); -be_define_const_str(data, "data", 3631407781u, 0, 4, &be_const_str_widget_editable); -be_define_const_str(day, "day", 3830391293u, 0, 3, &be_const_str_devices); -be_define_const_str(debug, "debug", 1483009432u, 0, 5, &be_const_str_set_zoom); -be_define_const_str(decode, "decode", 3007678287u, 0, 6, NULL); -be_define_const_str(decompress, "decompress", 2887031650u, 0, 10, NULL); -be_define_const_str(decrypt, "decrypt", 2886974618u, 0, 7, NULL); +be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_register_button_encoder); +be_define_const_str(coredump, "coredump", 2141225116u, 0, 8, &be_const_str_esphttpd); +be_define_const_str(cos, "cos", 4220379804u, 0, 3, NULL); +be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, NULL); +be_define_const_str(couldn_X27t_X20not_X20initialize_X20noepixelbus, "couldn't not initialize noepixelbus", 2536490812u, 0, 35, NULL); +be_define_const_str(count, "count", 967958004u, 0, 5, NULL); +be_define_const_str(counters, "counters", 4095866864u, 0, 8, &be_const_str_get_switches); +be_define_const_str(crc, "crc", 3812935353u, 0, 3, &be_const_str_lv_clock_icon); +be_define_const_str(crc16, "crc16", 3504496746u, 0, 5, NULL); +be_define_const_str(crc32, "crc32", 3571901412u, 0, 5, &be_const_str_int); +be_define_const_str(crc32_ota_seq, "crc32_ota_seq", 172417u, 0, 13, &be_const_str_set_timer); +be_define_const_str(crc8, "crc8", 1178893587u, 0, 4, &be_const_str_point_arr); +be_define_const_str(create_custom_widget, "create_custom_widget", 1140594778u, 0, 20, &be_const_str_list); +be_define_const_str(create_matrix, "create_matrix", 3528185923u, 0, 13, &be_const_str_internal_error); +be_define_const_str(create_segment, "create_segment", 3863522719u, 0, 14, &be_const_str_imin); +be_define_const_str(ct, "ct", 1261010898u, 0, 2, &be_const_str_hex); +be_define_const_str(ctor, "ctor", 375399343u, 0, 4, &be_const_str_imax); +be_define_const_str(ctypes_bytes, "ctypes_bytes", 3879019703u, 0, 12, &be_const_str_function); +be_define_const_str(ctypes_bytes_dyn, "ctypes_bytes_dyn", 915205307u, 0, 16, &be_const_str_is_running); +be_define_const_str(dac_voltage, "dac_voltage", 1552257222u, 0, 11, &be_const_str_splash); +be_define_const_str(data, "data", 3631407781u, 0, 4, NULL); +be_define_const_str(day, "day", 3830391293u, 0, 3, &be_const_str_set_hum); +be_define_const_str(debug, "debug", 1483009432u, 0, 5, NULL); +be_define_const_str(decode, "decode", 3007678287u, 0, 6, &be_const_str_font_seg7); +be_define_const_str(decompress, "decompress", 2887031650u, 0, 10, &be_const_str_pin_mode); +be_define_const_str(decrypt, "decrypt", 2886974618u, 0, 7, &be_const_str_lv); be_define_const_str(def, "def", 3310976652u, 55, 3, NULL); -be_define_const_str(deg, "deg", 3327754271u, 0, 3, &be_const_str_set_style_border_width); -be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_get_active); -be_define_const_str(del, "del", 3478752842u, 0, 3, &be_const_str_flash); -be_define_const_str(delay, "delay", 1322381784u, 0, 5, &be_const_str_traceback); -be_define_const_str(delete_all_configs, "delete_all_configs", 2382067578u, 0, 18, &be_const_str_json_fdump_map); -be_define_const_str(depower, "depower", 3563819571u, 0, 7, &be_const_str_function); -be_define_const_str(deregister_obj, "deregister_obj", 3909966993u, 0, 14, &be_const_str_height_def); -be_define_const_str(destructor_cb, "destructor_cb", 1930283190u, 0, 13, NULL); -be_define_const_str(detect, "detect", 8884370u, 0, 6, &be_const_str_detected_X20on_X20bus); -be_define_const_str(detected_X20on_X20bus, "detected on bus", 1432002650u, 0, 15, NULL); -be_define_const_str(devices, "devices", 2701822848u, 0, 7, NULL); -be_define_const_str(digital_read, "digital_read", 3585496928u, 0, 12, &be_const_str_touch_update); -be_define_const_str(digital_write, "digital_write", 3435877979u, 0, 13, &be_const_str_lv_obj); -be_define_const_str(dim, "dim", 3496118841u, 0, 3, &be_const_str_io_error); +be_define_const_str(deg, "deg", 3327754271u, 0, 3, NULL); +be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_set_size); +be_define_const_str(del, "del", 3478752842u, 0, 3, &be_const_str_tasmota); +be_define_const_str(delay, "delay", 1322381784u, 0, 5, NULL); +be_define_const_str(delete_all_configs, "delete_all_configs", 2382067578u, 0, 18, &be_const_str_engine); +be_define_const_str(depower, "depower", 3563819571u, 0, 7, &be_const_str_minute); +be_define_const_str(deregister_obj, "deregister_obj", 3909966993u, 0, 14, NULL); +be_define_const_str(destructor_cb, "destructor_cb", 1930283190u, 0, 13, &be_const_str_lv_signal_arcs); +be_define_const_str(detect, "detect", 8884370u, 0, 6, &be_const_str_discover); +be_define_const_str(detected_X20on_X20bus, "detected on bus", 1432002650u, 0, 15, &be_const_str_lv_event_cb); +be_define_const_str(devices, "devices", 2701822848u, 0, 7, &be_const_str_get_name); +be_define_const_str(digital_read, "digital_read", 3585496928u, 0, 12, &be_const_str_get_vbus_voltage); +be_define_const_str(digital_write, "digital_write", 3435877979u, 0, 13, NULL); +be_define_const_str(dim, "dim", 3496118841u, 0, 3, &be_const_str_light_X20must_X20be_X20of_X20class_X20_X27light_state_X27); be_define_const_str(dimmer, "dimmer", 794270539u, 0, 6, NULL); -be_define_const_str(dirty, "dirty", 2667581083u, 0, 5, NULL); -be_define_const_str(discover, "discover", 1383599054u, 0, 8, NULL); -be_define_const_str(display, "display", 1164572437u, 0, 7, &be_const_str_static); -be_define_const_str(display_X2Eini, "display.ini", 2646174001u, 0, 11, &be_const_str_timer_cb); +be_define_const_str(dirty, "dirty", 2667581083u, 0, 5, &be_const_str_splash_remove); +be_define_const_str(discover, "discover", 1383599054u, 0, 8, &be_const_str_set_matrix_pixel_color); +be_define_const_str(display, "display", 1164572437u, 0, 7, NULL); +be_define_const_str(display_X2Eini, "display.ini", 2646174001u, 0, 11, &be_const_str_widget_instance_size); be_define_const_str(do, "do", 1646057492u, 65, 2, NULL); -be_define_const_str(draw_arc, "draw_arc", 1828251676u, 0, 8, &be_const_str_pc_rel); +be_define_const_str(draw_arc, "draw_arc", 1828251676u, 0, 8, &be_const_str_erase); be_define_const_str(draw_arc_dsc, "draw_arc_dsc", 2411410957u, 0, 12, NULL); be_define_const_str(draw_arc_dsc_init, "draw_arc_dsc_init", 402724044u, 0, 17, NULL); -be_define_const_str(draw_ctx, "draw_ctx", 953366593u, 0, 8, NULL); -be_define_const_str(draw_line, "draw_line", 1634465686u, 0, 9, &be_const_str_webclient); -be_define_const_str(draw_line_dsc, "draw_line_dsc", 4220676203u, 0, 13, &be_const_str_get_bat_current); -be_define_const_str(draw_line_dsc_init, "draw_line_dsc_init", 3866693646u, 0, 18, &be_const_str_raw); -be_define_const_str(driver_name, "driver_name", 862681603u, 0, 11, &be_const_str_widget_height_def); -be_define_const_str(dump, "dump", 3663001223u, 0, 4, NULL); -be_define_const_str(duration, "duration", 799079693u, 0, 8, &be_const_str_isinstance); -be_define_const_str(editable, "editable", 60532369u, 0, 8, &be_const_str_mqtt_data); -be_define_const_str(efuse_em, "efuse_em", 1643301972u, 0, 8, &be_const_str_range); -be_define_const_str(elements_X20must_X20be_X20a_X20lv_point, "elements must be a lv_point", 1415796524u, 0, 27, &be_const_str_hs2rgb); +be_define_const_str(draw_ctx, "draw_ctx", 953366593u, 0, 8, &be_const_str_lvgl_timer_dispatch); +be_define_const_str(draw_line, "draw_line", 1634465686u, 0, 9, &be_const_str_persist); +be_define_const_str(draw_line_dsc, "draw_line_dsc", 4220676203u, 0, 13, &be_const_str_set_style_text_font); +be_define_const_str(draw_line_dsc_init, "draw_line_dsc_init", 3866693646u, 0, 18, NULL); +be_define_const_str(driver_name, "driver_name", 862681603u, 0, 11, &be_const_str_exec_rules); +be_define_const_str(dump, "dump", 3663001223u, 0, 4, &be_const_str_set_user_data); +be_define_const_str(duration, "duration", 799079693u, 0, 8, NULL); +be_define_const_str(editable, "editable", 60532369u, 0, 8, NULL); +be_define_const_str(efuse_em, "efuse_em", 1643301972u, 0, 8, &be_const_str_keys); +be_define_const_str(elements_X20must_X20be_X20a_X20lv_point, "elements must be a lv_point", 1415796524u, 0, 27, &be_const_str_factory); be_define_const_str(elif, "elif", 3232090307u, 51, 4, NULL); be_define_const_str(else, "else", 3183434736u, 52, 4, NULL); -be_define_const_str(enabled, "enabled", 49525662u, 0, 7, &be_const_str_event_cb); +be_define_const_str(enabled, "enabled", 49525662u, 0, 7, NULL); be_define_const_str(encrypt, "encrypt", 2194327650u, 0, 7, NULL); be_define_const_str(end, "end", 1787721130u, 56, 3, NULL); -be_define_const_str(energy_struct, "energy_struct", 1655792843u, 0, 13, &be_const_str_get_size); +be_define_const_str(energy_struct, "energy_struct", 1655792843u, 0, 13, NULL); be_define_const_str(engine, "engine", 3993360443u, 0, 6, NULL); -be_define_const_str(erase, "erase", 1010949589u, 0, 5, &be_const_str_widget_ctor_impl); +be_define_const_str(erase, "erase", 1010949589u, 0, 5, &be_const_str_matrix); be_define_const_str(escape, "escape", 2652972038u, 0, 6, NULL); -be_define_const_str(esphttpd, "esphttpd", 2255925709u, 0, 8, &be_const_str_imin); -be_define_const_str(eth, "eth", 2191266556u, 0, 3, NULL); -be_define_const_str(event, "event", 4264611999u, 0, 5, &be_const_str_toptr); -be_define_const_str(event_cb, "event_cb", 3128698017u, 0, 8, &be_const_str_stop); -be_define_const_str(event_send, "event_send", 598925582u, 0, 10, &be_const_str_next_cron); -be_define_const_str(every_100ms, "every_100ms", 1546407804u, 0, 11, &be_const_str_set_svc); -be_define_const_str(every_250ms, "every_250ms", 2579240000u, 0, 11, &be_const_str_set_user_data); -be_define_const_str(every_50ms, "every_50ms", 2383884008u, 0, 10, &be_const_str_read13); -be_define_const_str(every_second, "every_second", 2075451465u, 0, 12, &be_const_str_register_obj); +be_define_const_str(esphttpd, "esphttpd", 2255925709u, 0, 8, NULL); +be_define_const_str(eth, "eth", 2191266556u, 0, 3, &be_const_str_set_reachable); +be_define_const_str(event, "event", 4264611999u, 0, 5, &be_const_str_get_power); +be_define_const_str(event_cb, "event_cb", 3128698017u, 0, 8, NULL); +be_define_const_str(event_send, "event_send", 598925582u, 0, 10, &be_const_str_flush); +be_define_const_str(every_100ms, "every_100ms", 1546407804u, 0, 11, &be_const_str_def); +be_define_const_str(every_250ms, "every_250ms", 2579240000u, 0, 11, &be_const_str_touch_update); +be_define_const_str(every_50ms, "every_50ms", 2383884008u, 0, 10, &be_const_str_power_off); +be_define_const_str(every_second, "every_second", 2075451465u, 0, 12, &be_const_str_web_add_config_button); be_define_const_str(except, "except", 950914032u, 69, 6, NULL); -be_define_const_str(exec_cmd, "exec_cmd", 493567399u, 0, 8, NULL); -be_define_const_str(exec_rules, "exec_rules", 1445221092u, 0, 10, &be_const_str_widget_struct_by_class); -be_define_const_str(exec_tele, "exec_tele", 1020751601u, 0, 9, NULL); -be_define_const_str(exists, "exists", 1002329533u, 0, 6, &be_const_str_ins_goto); -be_define_const_str(exp, "exp", 1923516200u, 0, 3, NULL); -be_define_const_str(f, "f", 3809224601u, 0, 1, &be_const_str_scan); -be_define_const_str(factory, "factory", 2510088205u, 0, 7, &be_const_str_p2); +be_define_const_str(exec_cmd, "exec_cmd", 493567399u, 0, 8, &be_const_str_to_gamma); +be_define_const_str(exec_rules, "exec_rules", 1445221092u, 0, 10, &be_const_str_set_zoom); +be_define_const_str(exec_tele, "exec_tele", 1020751601u, 0, 9, &be_const_str__X7B); +be_define_const_str(exists, "exists", 1002329533u, 0, 6, &be_const_str_make_cb); +be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_web_add_handler); +be_define_const_str(f, "f", 3809224601u, 0, 1, NULL); +be_define_const_str(factory, "factory", 2510088205u, 0, 7, &be_const_str_lv_); be_define_const_str(false, "false", 184981848u, 62, 5, NULL); -be_define_const_str(fast_loop, "fast_loop", 3414422702u, 0, 9, &be_const_str_lv_); -be_define_const_str(fast_loop_enabled, "fast_loop_enabled", 2567964376u, 0, 17, &be_const_str_get_light); -be_define_const_str(fat, "fat", 3203931412u, 0, 3, &be_const_str_reverse_gamma10); -be_define_const_str(file, "file", 2867484483u, 0, 4, NULL); -be_define_const_str(file_X20extension_X20is_X20not_X20_X27_X2Ebe_X27_X20or_X20_X27_X2Ebec_X27, "file extension is not '.be' or '.bec'", 3095719639u, 0, 37, &be_const_str_offseta); -be_define_const_str(files, "files", 1055342736u, 0, 5, &be_const_str_switch_factory); -be_define_const_str(find, "find", 3186656602u, 0, 4, &be_const_str_load_otadata); -be_define_const_str(find_key_i, "find_key_i", 850136726u, 0, 10, &be_const_str_seq0); -be_define_const_str(find_op, "find_op", 3766713376u, 0, 7, NULL); -be_define_const_str(finish, "finish", 1494643858u, 0, 6, NULL); -be_define_const_str(flags, "flags", 2624027180u, 0, 5, &be_const_str_continue); -be_define_const_str(flash, "flash", 2944773417u, 0, 5, NULL); -be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_get_ota_slot); -be_define_const_str(flush, "flush", 3002334877u, 0, 5, &be_const_str_read8); -be_define_const_str(font_embedded, "font_embedded", 1623675143u, 0, 13, NULL); -be_define_const_str(font_montserrat, "font_montserrat", 3790091262u, 0, 15, &be_const_str_get_input_power_status); -be_define_const_str(font_seg7, "font_seg7", 1551771835u, 0, 9, &be_const_str_lv_solidified); +be_define_const_str(fast_loop, "fast_loop", 3414422702u, 0, 9, &be_const_str_get_cb_list); +be_define_const_str(fast_loop_enabled, "fast_loop_enabled", 2567964376u, 0, 17, &be_const_str_read_sensors); +be_define_const_str(fat, "fat", 3203931412u, 0, 3, &be_const_str_has); +be_define_const_str(file, "file", 2867484483u, 0, 4, &be_const_str_out_X20of_X20range); +be_define_const_str(file_X20extension_X20is_X20not_X20_X27_X2Ebe_X27_X20or_X20_X27_X2Ebec_X27, "file extension is not '.be' or '.bec'", 3095719639u, 0, 37, &be_const_str_get_alternate); +be_define_const_str(files, "files", 1055342736u, 0, 5, &be_const_str_memory); +be_define_const_str(find, "find", 3186656602u, 0, 4, &be_const_str_get_MAC); +be_define_const_str(find_key_i, "find_key_i", 850136726u, 0, 10, &be_const_str_resp_cmnd_done); +be_define_const_str(find_op, "find_op", 3766713376u, 0, 7, &be_const_str_response_append); +be_define_const_str(finish, "finish", 1494643858u, 0, 6, &be_const_str_next_cron); +be_define_const_str(flags, "flags", 2624027180u, 0, 5, NULL); +be_define_const_str(flash, "flash", 2944773417u, 0, 5, &be_const_str_id_X20must_X20be_X20of_X20type_X20_X27int_X27); +be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_set_rate); +be_define_const_str(flush, "flush", 3002334877u, 0, 5, &be_const_str_lv_extra); +be_define_const_str(font_embedded, "font_embedded", 1623675143u, 0, 13, &be_const_str_write_flash); +be_define_const_str(font_montserrat, "font_montserrat", 3790091262u, 0, 15, &be_const_str_lv_point); +be_define_const_str(font_seg7, "font_seg7", 1551771835u, 0, 9, &be_const_str_widget_struct_by_class); be_define_const_str(for, "for", 2901640080u, 54, 3, NULL); -be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_pixels_buffer); -be_define_const_str(from_to, "from_to", 21625507u, 0, 7, &be_const_str_obj_class_create_obj); -be_define_const_str(fromb64, "fromb64", 2717019639u, 0, 7, &be_const_str_global); -be_define_const_str(frombytes, "frombytes", 3771700788u, 0, 9, &be_const_str_unsubscribe); -be_define_const_str(fromptr, "fromptr", 666189689u, 0, 7, &be_const_str_lv_signal_bars); -be_define_const_str(fromstring, "fromstring", 610302344u, 0, 10, &be_const_str_remove_light); -be_define_const_str(full_state, "full_state", 255687770u, 0, 10, &be_const_str_get_width); -be_define_const_str(full_status, "full_status", 648242459u, 0, 11, NULL); -be_define_const_str(function, "function", 2664841801u, 0, 8, NULL); -be_define_const_str(gamma, "gamma", 3492353034u, 0, 5, NULL); -be_define_const_str(gamma10, "gamma10", 3472052483u, 0, 7, &be_const_str_lv_point_arr); -be_define_const_str(gamma8, "gamma8", 3802843830u, 0, 6, &be_const_str_set_mode_ct); -be_define_const_str(gc, "gc", 1042313471u, 0, 2, &be_const_str_read24); -be_define_const_str(gen_cb, "gen_cb", 3245227551u, 0, 6, &be_const_str_r); -be_define_const_str(get, "get", 1410115415u, 0, 3, &be_const_str_set_channels); -be_define_const_str(get_MAC, "get_MAC", 2091521771u, 0, 7, &be_const_str_resp_cmnd); -be_define_const_str(get_active, "get_active", 3504842642u, 0, 10, &be_const_str_parse); +be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_instance_size); +be_define_const_str(from_to, "from_to", 21625507u, 0, 7, &be_const_str_get_percentage); +be_define_const_str(fromb64, "fromb64", 2717019639u, 0, 7, &be_const_str_last_modified); +be_define_const_str(frombytes, "frombytes", 3771700788u, 0, 9, NULL); +be_define_const_str(fromhex, "fromhex", 1847150394u, 0, 7, NULL); +be_define_const_str(fromptr, "fromptr", 666189689u, 0, 7, NULL); +be_define_const_str(fromstring, "fromstring", 610302344u, 0, 10, &be_const_str_mqtt_data); +be_define_const_str(full_state, "full_state", 255687770u, 0, 10, &be_const_str_lv_event); +be_define_const_str(full_status, "full_status", 648242459u, 0, 11, &be_const_str_set_huesat); +be_define_const_str(function, "function", 2664841801u, 0, 8, &be_const_str_hs2rgb); +be_define_const_str(gamma, "gamma", 3492353034u, 0, 5, &be_const_str_get); +be_define_const_str(gamma10, "gamma10", 3472052483u, 0, 7, NULL); +be_define_const_str(gamma8, "gamma8", 3802843830u, 0, 6, &be_const_str_reset_search); +be_define_const_str(gc, "gc", 1042313471u, 0, 2, NULL); +be_define_const_str(gen_cb, "gen_cb", 3245227551u, 0, 6, &be_const_str_signal_arcs); +be_define_const_str(get, "get", 1410115415u, 0, 3, &be_const_str_tag); +be_define_const_str(get_MAC, "get_MAC", 2091521771u, 0, 7, &be_const_str_tasmota_X2Eget_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eget_X28_X29); +be_define_const_str(get_active, "get_active", 3504842642u, 0, 10, NULL); be_define_const_str(get_alternate, "get_alternate", 1450148894u, 0, 13, NULL); -be_define_const_str(get_aps_voltage, "get_aps_voltage", 2293036435u, 0, 15, &be_const_str_get_current_module_name); -be_define_const_str(get_bat_charge_current, "get_bat_charge_current", 1385293050u, 0, 22, &be_const_str_manuf); -be_define_const_str(get_bat_current, "get_bat_current", 1912106073u, 0, 15, NULL); -be_define_const_str(get_bat_power, "get_bat_power", 3067374853u, 0, 13, &be_const_str_get_switches); -be_define_const_str(get_bat_voltage, "get_bat_voltage", 706676538u, 0, 15, NULL); -be_define_const_str(get_battery_chargin_status, "get_battery_chargin_status", 2233241571u, 0, 26, &be_const_str_is_running); -be_define_const_str(get_bri, "get_bri", 2041809895u, 0, 7, NULL); -be_define_const_str(get_cb_list, "get_cb_list", 1605319182u, 0, 11, &be_const_str_persist_X2E_p_X20is_X20not_X20a_X20map); -be_define_const_str(get_coords, "get_coords", 1044089006u, 0, 10, &be_const_str_real); -be_define_const_str(get_current_module_name, "get_current_module_name", 2379270740u, 0, 23, &be_const_str_wire_scan); -be_define_const_str(get_current_module_path, "get_current_module_path", 3206673408u, 0, 23, NULL); -be_define_const_str(get_event_cb, "get_event_cb", 375876088u, 0, 12, &be_const_str_top); -be_define_const_str(get_factory_slot, "get_factory_slot", 3086140407u, 0, 16, NULL); +be_define_const_str(get_aps_voltage, "get_aps_voltage", 2293036435u, 0, 15, NULL); +be_define_const_str(get_bat_charge_current, "get_bat_charge_current", 1385293050u, 0, 22, &be_const_str_seti); +be_define_const_str(get_bat_current, "get_bat_current", 1912106073u, 0, 15, &be_const_str_null_cb); +be_define_const_str(get_bat_power, "get_bat_power", 3067374853u, 0, 13, NULL); +be_define_const_str(get_bat_voltage, "get_bat_voltage", 706676538u, 0, 15, &be_const_str_set_channels); +be_define_const_str(get_battery_chargin_status, "get_battery_chargin_status", 2233241571u, 0, 26, &be_const_str_pct); +be_define_const_str(get_bri, "get_bri", 2041809895u, 0, 7, &be_const_str_set); +be_define_const_str(get_cb_list, "get_cb_list", 1605319182u, 0, 11, NULL); +be_define_const_str(get_coords, "get_coords", 1044089006u, 0, 10, &be_const_str_invalid_X20GPIO_X20number); +be_define_const_str(get_current_module_name, "get_current_module_name", 2379270740u, 0, 23, NULL); +be_define_const_str(get_current_module_path, "get_current_module_path", 3206673408u, 0, 23, &be_const_str_param); +be_define_const_str(get_event_cb, "get_event_cb", 375876088u, 0, 12, &be_const_str_reverse_gamma10); +be_define_const_str(get_factory_slot, "get_factory_slot", 3086140407u, 0, 16, &be_const_str_widget_event); be_define_const_str(get_free_heap, "get_free_heap", 625069757u, 0, 13, NULL); -be_define_const_str(get_height, "get_height", 3571755523u, 0, 10, &be_const_str_group_def); -be_define_const_str(get_hor_res, "get_hor_res", 37131144u, 0, 11, &be_const_str_input); -be_define_const_str(get_image_size, "get_image_size", 4009859887u, 0, 14, &be_const_str_get_vbus_current); +be_define_const_str(get_height, "get_height", 3571755523u, 0, 10, &be_const_str_write8); +be_define_const_str(get_hor_res, "get_hor_res", 37131144u, 0, 11, NULL); +be_define_const_str(get_image_size, "get_image_size", 4009859887u, 0, 14, NULL); be_define_const_str(get_input_power_status, "get_input_power_status", 4102829177u, 0, 22, NULL); -be_define_const_str(get_light, "get_light", 381930476u, 0, 9, &be_const_str_tele); -be_define_const_str(get_log, "get_log", 3524441898u, 0, 7, &be_const_str_pixel_count); -be_define_const_str(get_name, "get_name", 1616902907u, 0, 8, &be_const_str_xy); -be_define_const_str(get_object_from_ptr, "get_object_from_ptr", 2345019201u, 0, 19, NULL); -be_define_const_str(get_option, "get_option", 2123730033u, 0, 10, &be_const_str_lv_timer_cb); -be_define_const_str(get_ota_slot, "get_ota_slot", 2686180151u, 0, 12, NULL); -be_define_const_str(get_percentage, "get_percentage", 2880483992u, 0, 14, NULL); -be_define_const_str(get_pixel_color, "get_pixel_color", 337490048u, 0, 15, &be_const_str_publish_rule); -be_define_const_str(get_power, "get_power", 3009799377u, 0, 9, &be_const_str_time_dump); -be_define_const_str(get_size, "get_size", 2803644713u, 0, 8, &be_const_str_label); -be_define_const_str(get_string, "get_string", 4195847969u, 0, 10, &be_const_str_onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20change_X20the_X20current_X20configuration_X20and_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E); -be_define_const_str(get_style_bg_color, "get_style_bg_color", 964794381u, 0, 18, &be_const_str_rtc); -be_define_const_str(get_style_line_color, "get_style_line_color", 805371932u, 0, 20, NULL); +be_define_const_str(get_light, "get_light", 381930476u, 0, 9, NULL); +be_define_const_str(get_log, "get_log", 3524441898u, 0, 7, &be_const_str_parse); +be_define_const_str(get_name, "get_name", 1616902907u, 0, 8, &be_const_str_web_add_button); +be_define_const_str(get_object_from_ptr, "get_object_from_ptr", 2345019201u, 0, 19, &be_const_str_o); +be_define_const_str(get_option, "get_option", 2123730033u, 0, 10, NULL); +be_define_const_str(get_ota_slot, "get_ota_slot", 2686180151u, 0, 12, &be_const_str_has_factory); +be_define_const_str(get_percentage, "get_percentage", 2880483992u, 0, 14, &be_const_str_i2c_enabled); +be_define_const_str(get_pixel_color, "get_pixel_color", 337490048u, 0, 15, &be_const_str_subtype); +be_define_const_str(get_power, "get_power", 3009799377u, 0, 9, &be_const_str_phy); +be_define_const_str(get_size, "get_size", 2803644713u, 0, 8, NULL); +be_define_const_str(get_string, "get_string", 4195847969u, 0, 10, &be_const_str_mqtt); +be_define_const_str(get_style_bg_color, "get_style_bg_color", 964794381u, 0, 18, NULL); +be_define_const_str(get_style_line_color, "get_style_line_color", 805371932u, 0, 20, &be_const_str_init_draw_line_dsc); be_define_const_str(get_style_pad_right, "get_style_pad_right", 3150287466u, 0, 19, NULL); -be_define_const_str(get_switch, "get_switch", 164821028u, 0, 10, NULL); +be_define_const_str(get_switch, "get_switch", 164821028u, 0, 10, &be_const_str_mqtt_listener); be_define_const_str(get_switches, "get_switches", 4116216928u, 0, 12, NULL); -be_define_const_str(get_temp, "get_temp", 3370919486u, 0, 8, &be_const_str_h); -be_define_const_str(get_vbus_current, "get_vbus_current", 1205347942u, 0, 16, NULL); -be_define_const_str(get_vbus_voltage, "get_vbus_voltage", 2398210401u, 0, 16, NULL); +be_define_const_str(get_temp, "get_temp", 3370919486u, 0, 8, NULL); +be_define_const_str(get_vbus_current, "get_vbus_current", 1205347942u, 0, 16, &be_const_str_sqrt); +be_define_const_str(get_vbus_voltage, "get_vbus_voltage", 2398210401u, 0, 16, &be_const_str_ota_); be_define_const_str(get_warning_level, "get_warning_level", 1737834441u, 0, 17, NULL); -be_define_const_str(get_width, "get_width", 3293417300u, 0, 9, &be_const_str_hex); -be_define_const_str(getbits, "getbits", 3094168979u, 0, 7, &be_const_str_isnan); -be_define_const_str(getfloat, "getfloat", 2820979603u, 0, 8, &be_const_str_id_X20must_X20be_X20of_X20type_X20_X27int_X27); -be_define_const_str(geti, "geti", 2381006490u, 0, 4, NULL); -be_define_const_str(global, "global", 503252654u, 0, 6, &be_const_str_target); -be_define_const_str(gpio, "gpio", 2638155258u, 0, 4, &be_const_str_no_X20GPIO_X20specified_X20for_X20neopixelbus); +be_define_const_str(get_width, "get_width", 3293417300u, 0, 9, NULL); +be_define_const_str(getbits, "getbits", 3094168979u, 0, 7, &be_const_str_module); +be_define_const_str(getfloat, "getfloat", 2820979603u, 0, 8, &be_const_str_md5); +be_define_const_str(geti, "geti", 2381006490u, 0, 4, &be_const_str_push); +be_define_const_str(global, "global", 503252654u, 0, 6, &be_const_str_insert); +be_define_const_str(gpio, "gpio", 2638155258u, 0, 4, &be_const_str_splash_init); be_define_const_str(group_def, "group_def", 1524213328u, 0, 9, NULL); -be_define_const_str(groups, "groups", 2943077229u, 0, 6, &be_const_str_p1); -be_define_const_str(h, "h", 3977000791u, 0, 1, &be_const_str_var); -be_define_const_str(has, "has", 3988721635u, 0, 3, &be_const_str_percentage); -be_define_const_str(has_arg, "has_arg", 424878688u, 0, 7, &be_const_str_rounded); -be_define_const_str(has_factory, "has_factory", 2702829042u, 0, 11, &be_const_str_slots); -be_define_const_str(height_def, "height_def", 2348238838u, 0, 10, NULL); -be_define_const_str(hex, "hex", 4273249610u, 0, 3, &be_const_str_introspect); -be_define_const_str(hour, "hour", 3053661199u, 0, 4, &be_const_str_on); -be_define_const_str(hs2rgb, "hs2rgb", 1040816349u, 0, 6, &be_const_str_set_style_bg_color); -be_define_const_str(https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_X2F_X25s_X2Eautoconf, "https://raw.githubusercontent.com/tasmota/autoconf/main/%s/%s.autoconf", 2743526309u, 0, 70, &be_const_str_type_to_string); -be_define_const_str(https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_manifest_X2Ejson, "https://raw.githubusercontent.com/tasmota/autoconf/main/%s_manifest.json", 3657552045u, 0, 72, &be_const_str_is_dirty); -be_define_const_str(hue, "hue", 3817694041u, 0, 3, &be_const_str_page_autoconf_ctl); -be_define_const_str(hue_ntv, "hue_ntv", 705068642u, 0, 7, NULL); -be_define_const_str(hue_status, "hue_status", 437978812u, 0, 10, &be_const_str_y1); -be_define_const_str(i2c_enabled, "i2c_enabled", 218388101u, 0, 11, &be_const_str_param); -be_define_const_str(id, "id", 926444256u, 0, 2, &be_const_str_run_deferred); -be_define_const_str(id_X20must_X20be_X20of_X20type_X20_X27int_X27, "id must be of type 'int'", 2097653458u, 0, 24, &be_const_str_instance_size); +be_define_const_str(groups, "groups", 2943077229u, 0, 6, &be_const_str_readbytes); +be_define_const_str(h, "h", 3977000791u, 0, 1, &be_const_str_super); +be_define_const_str(has, "has", 3988721635u, 0, 3, NULL); +be_define_const_str(has_arg, "has_arg", 424878688u, 0, 7, NULL); +be_define_const_str(has_factory, "has_factory", 2702829042u, 0, 11, NULL); +be_define_const_str(height_def, "height_def", 2348238838u, 0, 10, &be_const_str_pc_rel); +be_define_const_str(hex, "hex", 4273249610u, 0, 3, &be_const_str_tomap); +be_define_const_str(hour, "hour", 3053661199u, 0, 4, &be_const_str_remove_driver); +be_define_const_str(hs2rgb, "hs2rgb", 1040816349u, 0, 6, &be_const_str_json_fdump_list); +be_define_const_str(https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_X2F_X25s_X2Eautoconf, "https://raw.githubusercontent.com/tasmota/autoconf/main/%s/%s.autoconf", 2743526309u, 0, 70, &be_const_str_p1); +be_define_const_str(https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_manifest_X2Ejson, "https://raw.githubusercontent.com/tasmota/autoconf/main/%s_manifest.json", 3657552045u, 0, 72, &be_const_str_round_start); +be_define_const_str(hue, "hue", 3817694041u, 0, 3, NULL); +be_define_const_str(hue_ntv, "hue_ntv", 705068642u, 0, 7, &be_const_str_ins_time); +be_define_const_str(hue_status, "hue_status", 437978812u, 0, 10, &be_const_str_set_ldo_enable); +be_define_const_str(i2c_enabled, "i2c_enabled", 218388101u, 0, 11, &be_const_str_seq1); +be_define_const_str(id, "id", 926444256u, 0, 2, &be_const_str_width_def); +be_define_const_str(id_X20must_X20be_X20of_X20type_X20_X27int_X27, "id must be of type 'int'", 2097653458u, 0, 24, &be_const_str_w); be_define_const_str(if, "if", 959999494u, 50, 2, NULL); -be_define_const_str(imax, "imax", 3084515410u, 0, 4, &be_const_str_pixel_size); -be_define_const_str(img, "img", 2229740804u, 0, 3, &be_const_str_tobytes); +be_define_const_str(imax, "imax", 3084515410u, 0, 4, &be_const_str_percentage); +be_define_const_str(img, "img", 2229740804u, 0, 3, &be_const_str_resolvecmnd); be_define_const_str(imin, "imin", 2714127864u, 0, 4, NULL); be_define_const_str(import, "import", 288002260u, 66, 6, NULL); -be_define_const_str(init, "init", 380752755u, 0, 4, &be_const_str_send_multicast); +be_define_const_str(info, "info", 263456517u, 0, 4, NULL); +be_define_const_str(init, "init", 380752755u, 0, 4, &be_const_str_set_style_text_color); be_define_const_str(init_draw_arc_dsc, "init_draw_arc_dsc", 1655274348u, 0, 17, NULL); -be_define_const_str(init_draw_line_dsc, "init_draw_line_dsc", 2507936040u, 0, 18, NULL); -be_define_const_str(input, "input", 4191711099u, 0, 5, &be_const_str_internal_error); -be_define_const_str(ins_goto, "ins_goto", 1342843963u, 0, 8, NULL); -be_define_const_str(ins_ramp, "ins_ramp", 1068049360u, 0, 8, &be_const_str_md5); -be_define_const_str(ins_time, "ins_time", 2980245553u, 0, 8, NULL); -be_define_const_str(insert, "insert", 3332609576u, 0, 6, &be_const_str_readbytes); -be_define_const_str(instance, "instance", 193386898u, 0, 8, NULL); -be_define_const_str(instance_X20required, "instance required", 381192159u, 0, 17, &be_const_str_lv_style_prop_arr); -be_define_const_str(instance_size, "instance_size", 4280269518u, 0, 13, &be_const_str_sec); +be_define_const_str(init_draw_line_dsc, "init_draw_line_dsc", 2507936040u, 0, 18, &be_const_str_pow); +be_define_const_str(input, "input", 4191711099u, 0, 5, &be_const_str_resp_cmnd_failed); +be_define_const_str(ins_goto, "ins_goto", 1342843963u, 0, 8, &be_const_str_lv_coord_arr); +be_define_const_str(ins_ramp, "ins_ramp", 1068049360u, 0, 8, &be_const_str_settings); +be_define_const_str(ins_time, "ins_time", 2980245553u, 0, 8, &be_const_str_set_time); +be_define_const_str(insert, "insert", 3332609576u, 0, 6, &be_const_str_return_X20code_X3D_X25i); +be_define_const_str(instance, "instance", 193386898u, 0, 8, &be_const_str_item); +be_define_const_str(instance_X20required, "instance required", 381192159u, 0, 17, &be_const_str_missing_X20name); +be_define_const_str(instance_size, "instance_size", 4280269518u, 0, 13, &be_const_str_reverse); be_define_const_str(int, "int", 2515107422u, 0, 3, NULL); be_define_const_str(int64, "int64", 64103268u, 0, 5, NULL); -be_define_const_str(internal_error, "internal_error", 2519158169u, 0, 14, NULL); -be_define_const_str(introspect, "introspect", 164638290u, 0, 10, &be_const_str_try_compile); -be_define_const_str(invalid_X20GPIO_X20number, "invalid GPIO number", 4135793328u, 0, 19, NULL); -be_define_const_str(invalid_X20magic_X20number_X20_X2502X, "invalid magic number %02X", 2836756259u, 0, 25, NULL); -be_define_const_str(invalidate, "invalidate", 2649734928u, 0, 10, &be_const_str_length_X20in_X20bits_X20must_X20be_X20between_X200_X20and_X2032); -be_define_const_str(invalidate_spiffs, "invalidate_spiffs", 1470453498u, 0, 17, &be_const_str_set_align); -be_define_const_str(io_error, "io_error", 1970281036u, 0, 8, &be_const_str_scr_act); +be_define_const_str(internal_error, "internal_error", 2519158169u, 0, 14, &be_const_str_lv_point_arr); +be_define_const_str(introspect, "introspect", 164638290u, 0, 10, NULL); +be_define_const_str(invalid_X20GPIO_X20number, "invalid GPIO number", 4135793328u, 0, 19, &be_const_str_set_gain); +be_define_const_str(invalid_X20magic_X20number_X20_X2502X, "invalid magic number %02X", 2836756259u, 0, 25, &be_const_str_p2); +be_define_const_str(invalidate, "invalidate", 2649734928u, 0, 10, NULL); +be_define_const_str(invalidate_spiffs, "invalidate_spiffs", 1470453498u, 0, 17, &be_const_str_montserrat_font); +be_define_const_str(io_error, "io_error", 1970281036u, 0, 8, &be_const_str_strip); be_define_const_str(ip, "ip", 1261996636u, 0, 2, NULL); -be_define_const_str(is_dirty, "is_dirty", 418034110u, 0, 8, &be_const_str_json_fdump); +be_define_const_str(is_dirty, "is_dirty", 418034110u, 0, 8, &be_const_str_widget_constructor); be_define_const_str(is_factory, "is_factory", 1312753376u, 0, 10, NULL); be_define_const_str(is_first_time, "is_first_time", 275242384u, 0, 13, NULL); -be_define_const_str(is_ota, "is_ota", 2892315548u, 0, 6, &be_const_str_type); -be_define_const_str(is_running, "is_running", 2226847261u, 0, 10, &be_const_str_set_dcdc_enable); +be_define_const_str(is_ota, "is_ota", 2892315548u, 0, 6, &be_const_str_offset); +be_define_const_str(is_running, "is_running", 2226847261u, 0, 10, &be_const_str_isinstance); be_define_const_str(is_spiffs, "is_spiffs", 3196570601u, 0, 9, NULL); -be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, NULL); -be_define_const_str(ismethod, "ismethod", 3513438880u, 0, 8, &be_const_str_refr_now); -be_define_const_str(isnan, "isnan", 2981347434u, 0, 5, NULL); -be_define_const_str(isrunning, "isrunning", 1688182268u, 0, 9, &be_const_str_onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E); -be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, NULL); +be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, &be_const_str_signal_bars); +be_define_const_str(ismethod, "ismethod", 3513438880u, 0, 8, NULL); +be_define_const_str(isnan, "isnan", 2981347434u, 0, 5, &be_const_str_write_gpio); +be_define_const_str(isrunning, "isrunning", 1688182268u, 0, 9, &be_const_str_lv_obj); +be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, &be_const_str_do); be_define_const_str(item, "item", 2671260646u, 0, 4, NULL); -be_define_const_str(iter, "iter", 3124256359u, 0, 4, NULL); +be_define_const_str(iter, "iter", 3124256359u, 0, 4, &be_const_str_nvs); be_define_const_str(json, "json", 916562499u, 0, 4, NULL); -be_define_const_str(json_append, "json_append", 3002019284u, 0, 11, &be_const_str_montserrat_font); -be_define_const_str(json_fdump, "json_fdump", 1694216580u, 0, 10, &be_const_str_lv_module_init); -be_define_const_str(json_fdump_any, "json_fdump_any", 3348629385u, 0, 14, &be_const_str_null_cb); -be_define_const_str(json_fdump_list, "json_fdump_list", 3903879853u, 0, 15, NULL); +be_define_const_str(json_append, "json_append", 3002019284u, 0, 11, NULL); +be_define_const_str(json_fdump, "json_fdump", 1694216580u, 0, 10, &be_const_str_set_pwm); +be_define_const_str(json_fdump_any, "json_fdump_any", 3348629385u, 0, 14, &be_const_str_zb_coord_ntv); +be_define_const_str(json_fdump_list, "json_fdump_list", 3903879853u, 0, 15, &be_const_str_light_to_id); be_define_const_str(json_fdump_map, "json_fdump_map", 4091954653u, 0, 14, NULL); -be_define_const_str(keys, "keys", 4182378701u, 0, 4, NULL); -be_define_const_str(label, "label", 4137097213u, 0, 5, NULL); -be_define_const_str(last_modified, "last_modified", 772177145u, 0, 13, &be_const_str_lights); +be_define_const_str(keys, "keys", 4182378701u, 0, 4, &be_const_str_rtc); +be_define_const_str(label, "label", 4137097213u, 0, 5, &be_const_str_set_auth); +be_define_const_str(last_modified, "last_modified", 772177145u, 0, 13, &be_const_str_resp_cmnd); be_define_const_str(leds, "leds", 558858555u, 0, 4, NULL); -be_define_const_str(length_X20in_X20bits_X20must_X20be_X20between_X200_X20and_X2032, "length in bits must be between 0 and 32", 2584509128u, 0, 39, &be_const_str_set_rate); -be_define_const_str(light, "light", 3801947695u, 0, 5, &be_const_str_set_ldo_voltage); -be_define_const_str(light_X20must_X20be_X20of_X20class_X20_X27light_state_X27, "light must be of class 'light_state'", 3669350396u, 0, 36, &be_const_str_read_sensors); -be_define_const_str(light_state, "light_state", 905783845u, 0, 11, &be_const_str_lv_wifi_bars_icon); -be_define_const_str(light_to_id, "light_to_id", 1117015647u, 0, 11, NULL); -be_define_const_str(lights, "lights", 425118420u, 0, 6, &be_const_str_set_size); -be_define_const_str(line_dsc, "line_dsc", 4094490978u, 0, 8, &be_const_str_try_run_compiled); -be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_set_MAC); -be_define_const_str(list_handlers, "list_handlers", 593774371u, 0, 13, NULL); -be_define_const_str(listdir, "listdir", 2005220720u, 0, 7, &be_const_str_math); -be_define_const_str(load, "load", 3859241449u, 0, 4, &be_const_str_wifi); -be_define_const_str(load_freetype_font, "load_freetype_font", 2368447592u, 0, 18, NULL); +be_define_const_str(length_X20in_X20bits_X20must_X20be_X20between_X200_X20and_X2032, "length in bits must be between 0 and 32", 2584509128u, 0, 39, &be_const_str_math); +be_define_const_str(light, "light", 3801947695u, 0, 5, &be_const_str_wire_scan); +be_define_const_str(light_X20must_X20be_X20of_X20class_X20_X27light_state_X27, "light must be of class 'light_state'", 3669350396u, 0, 36, &be_const_str_set_style_bg_color); +be_define_const_str(light_state, "light_state", 905783845u, 0, 11, NULL); +be_define_const_str(light_to_id, "light_to_id", 1117015647u, 0, 11, &be_const_str_members); +be_define_const_str(lights, "lights", 425118420u, 0, 6, &be_const_str_the_X20second_X20argument_X20is_X20not_X20a_X20function); +be_define_const_str(line_dsc, "line_dsc", 4094490978u, 0, 8, NULL); +be_define_const_str(list, "list", 217798785u, 0, 4, NULL); +be_define_const_str(list_handlers, "list_handlers", 593774371u, 0, 13, &be_const_str_preinit); +be_define_const_str(listdir, "listdir", 2005220720u, 0, 7, &be_const_str_lvgl_event_dispatch); +be_define_const_str(load, "load", 3859241449u, 0, 4, &be_const_str_pi); +be_define_const_str(load_freetype_font, "load_freetype_font", 2368447592u, 0, 18, &be_const_str_quality); be_define_const_str(load_otadata, "load_otadata", 1955073712u, 0, 12, NULL); -be_define_const_str(load_templates, "load_templates", 3513870133u, 0, 14, NULL); -be_define_const_str(local, "local", 2621662984u, 0, 5, NULL); -be_define_const_str(log, "log", 1062293841u, 0, 3, &be_const_str__X7Bs_X7DBatt_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D); +be_define_const_str(load_templates, "load_templates", 3513870133u, 0, 14, &be_const_str_run_deferred); +be_define_const_str(local, "local", 2621662984u, 0, 5, &be_const_str_set_useragent); +be_define_const_str(log, "log", 1062293841u, 0, 3, &be_const_str_value_error); be_define_const_str(log10, "log10", 2346846000u, 0, 5, NULL); be_define_const_str(loop, "loop", 3723446379u, 0, 4, NULL); -be_define_const_str(lower, "lower", 3038577850u, 0, 5, &be_const_str_widget_dtor_cb); -be_define_const_str(lv, "lv", 1529997255u, 0, 2, &be_const_str_ota_max); +be_define_const_str(lower, "lower", 3038577850u, 0, 5, NULL); +be_define_const_str(lv, "lv", 1529997255u, 0, 2, NULL); be_define_const_str(lv_, "lv_", 663721032u, 0, 3, NULL); -be_define_const_str(lv_clock, "lv_clock", 2859904766u, 0, 8, &be_const_str_set_y); -be_define_const_str(lv_clock_icon, "lv_clock_icon", 3257216210u, 0, 13, &be_const_str_pc_abs); -be_define_const_str(lv_coord_arr, "lv_coord_arr", 1197238601u, 0, 12, NULL); -be_define_const_str(lv_event, "lv_event", 2434089968u, 0, 8, &be_const_str_web_send); -be_define_const_str(lv_event_cb, "lv_event_cb", 2480731016u, 0, 11, &be_const_str_nvs); -be_define_const_str(lv_extra, "lv_extra", 399561998u, 0, 8, NULL); -be_define_const_str(lv_module_init, "lv_module_init", 1133027755u, 0, 14, &be_const_str__X7Bs_X7DVBus_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D); -be_define_const_str(lv_obj, "lv_obj", 4257833149u, 0, 6, &be_const_str_lv_wifi_arcs_icon); -be_define_const_str(lv_obj_class, "lv_obj_class", 4039656294u, 0, 12, &be_const_str_wifi_arcs_icon); -be_define_const_str(lv_point, "lv_point", 4120221790u, 0, 8, NULL); -be_define_const_str(lv_point_arr, "lv_point_arr", 3959768858u, 0, 12, &be_const_str_number); +be_define_const_str(lv_clock, "lv_clock", 2859904766u, 0, 8, &be_const_str_except); +be_define_const_str(lv_clock_icon, "lv_clock_icon", 3257216210u, 0, 13, &be_const_str_publish_result); +be_define_const_str(lv_coord_arr, "lv_coord_arr", 1197238601u, 0, 12, &be_const_str_widget_destructor); +be_define_const_str(lv_event, "lv_event", 2434089968u, 0, 8, &be_const_str_no_X20GPIO_X20specified_X20for_X20neopixelbus); +be_define_const_str(lv_event_cb, "lv_event_cb", 2480731016u, 0, 11, &be_const_str_pop_path); +be_define_const_str(lv_extra, "lv_extra", 399561998u, 0, 8, &be_const_str_widget_width_def); +be_define_const_str(lv_module_init, "lv_module_init", 1133027755u, 0, 14, NULL); +be_define_const_str(lv_obj, "lv_obj", 4257833149u, 0, 6, NULL); +be_define_const_str(lv_obj_class, "lv_obj_class", 4039656294u, 0, 12, NULL); +be_define_const_str(lv_point, "lv_point", 4120221790u, 0, 8, &be_const_str_write_bytes); +be_define_const_str(lv_point_arr, "lv_point_arr", 3959768858u, 0, 12, NULL); be_define_const_str(lv_signal_arcs, "lv_signal_arcs", 2839156988u, 0, 14, NULL); -be_define_const_str(lv_signal_bars, "lv_signal_bars", 3513972559u, 0, 14, &be_const_str_trig); -be_define_const_str(lv_solidified, "lv_solidified", 2274121310u, 0, 13, &be_const_str_test); -be_define_const_str(lv_style_prop_arr, "lv_style_prop_arr", 2504347499u, 0, 17, &be_const_str_write_gpio); -be_define_const_str(lv_timer_cb, "lv_timer_cb", 1383473763u, 0, 11, &be_const_str_pop_path); +be_define_const_str(lv_signal_bars, "lv_signal_bars", 3513972559u, 0, 14, NULL); +be_define_const_str(lv_solidified, "lv_solidified", 2274121310u, 0, 13, NULL); +be_define_const_str(lv_style_prop_arr, "lv_style_prop_arr", 2504347499u, 0, 17, &be_const_str_min); +be_define_const_str(lv_timer_cb, "lv_timer_cb", 1383473763u, 0, 11, &be_const_str_strptime); be_define_const_str(lv_wifi_arcs, "lv_wifi_arcs", 2082091963u, 0, 12, NULL); be_define_const_str(lv_wifi_arcs_icon, "lv_wifi_arcs_icon", 1507982909u, 0, 17, NULL); -be_define_const_str(lv_wifi_bars, "lv_wifi_bars", 2109539196u, 0, 12, &be_const_str_missing_X20name); -be_define_const_str(lv_wifi_bars_icon, "lv_wifi_bars_icon", 2805815540u, 0, 17, &be_const_str_resp_cmnd_str); -be_define_const_str(lvgl_event_dispatch, "lvgl_event_dispatch", 2104396622u, 0, 19, &be_const_str_str); -be_define_const_str(lvgl_timer_dispatch, "lvgl_timer_dispatch", 975257833u, 0, 19, &be_const_str_set_timer); -be_define_const_str(make_cb, "make_cb", 71252785u, 0, 7, &be_const_str_memory); -be_define_const_str(manuf, "manuf", 4120929560u, 0, 5, NULL); -be_define_const_str(map, "map", 3751997361u, 0, 3, NULL); -be_define_const_str(math, "math", 4001929615u, 0, 4, NULL); +be_define_const_str(lv_wifi_bars, "lv_wifi_bars", 2109539196u, 0, 12, NULL); +be_define_const_str(lv_wifi_bars_icon, "lv_wifi_bars_icon", 2805815540u, 0, 17, NULL); +be_define_const_str(lvgl_event_dispatch, "lvgl_event_dispatch", 2104396622u, 0, 19, &be_const_str_widget_struct_default); +be_define_const_str(lvgl_timer_dispatch, "lvgl_timer_dispatch", 975257833u, 0, 19, NULL); +be_define_const_str(make_cb, "make_cb", 71252785u, 0, 7, NULL); +be_define_const_str(manuf, "manuf", 4120929560u, 0, 5, &be_const_str_number); +be_define_const_str(map, "map", 3751997361u, 0, 3, &be_const_str_nan); +be_define_const_str(math, "math", 4001929615u, 0, 4, &be_const_str_set_active); be_define_const_str(matrix, "matrix", 365099244u, 0, 6, NULL); -be_define_const_str(maxota, "maxota", 2594898265u, 0, 6, NULL); -be_define_const_str(md5, "md5", 2393554675u, 0, 3, NULL); -be_define_const_str(member, "member", 719708611u, 0, 6, &be_const_str_set_ldo_enable); +be_define_const_str(maxota, "maxota", 2594898265u, 0, 6, &be_const_str_wifi_arcs); +be_define_const_str(md5, "md5", 2393554675u, 0, 3, &be_const_str_path); +be_define_const_str(member, "member", 719708611u, 0, 6, NULL); be_define_const_str(members, "members", 937576464u, 0, 7, NULL); -be_define_const_str(memory, "memory", 2229924270u, 0, 6, &be_const_str_width); -be_define_const_str(millis, "millis", 1214679063u, 0, 6, &be_const_str_remote_ip); -be_define_const_str(min, "min", 3381609815u, 0, 3, &be_const_str_pop); -be_define_const_str(minute, "minute", 954666857u, 0, 6, NULL); -be_define_const_str(missing_X20name, "missing name", 3635024006u, 0, 12, NULL); -be_define_const_str(model, "model", 2961925722u, 0, 5, &be_const_str_return); -be_define_const_str(module, "module", 3617558685u, 0, 6, NULL); -be_define_const_str(month, "month", 3598321157u, 0, 5, &be_const_str_point_arr); -be_define_const_str(montserrat_font, "montserrat_font", 1819065874u, 0, 15, &be_const_str_set_hue16sat); -be_define_const_str(mqtt, "mqtt", 353147387u, 0, 4, &be_const_str_wifi_bars_icon); -be_define_const_str(mqtt_data, "mqtt_data", 2538213364u, 0, 9, NULL); -be_define_const_str(mqtt_listener, "mqtt_listener", 2764719532u, 0, 13, NULL); -be_define_const_str(name, "name", 2369371622u, 0, 4, &be_const_str_push_path); -be_define_const_str(nan, "nan", 797905850u, 0, 3, &be_const_str_subscribe); -be_define_const_str(next, "next", 1555467752u, 0, 4, &be_const_str_publish_result); +be_define_const_str(memory, "memory", 2229924270u, 0, 6, NULL); +be_define_const_str(millis, "millis", 1214679063u, 0, 6, &be_const_str_wire); +be_define_const_str(min, "min", 3381609815u, 0, 3, NULL); +be_define_const_str(minute, "minute", 954666857u, 0, 6, &be_const_str_read32); +be_define_const_str(missing_X20name, "missing name", 3635024006u, 0, 12, &be_const_str_set_chg_current); +be_define_const_str(model, "model", 2961925722u, 0, 5, &be_const_str_tanh); +be_define_const_str(module, "module", 3617558685u, 0, 6, &be_const_str_next); +be_define_const_str(month, "month", 3598321157u, 0, 5, NULL); +be_define_const_str(montserrat_font, "montserrat_font", 1819065874u, 0, 15, &be_const_str_type); +be_define_const_str(mqtt, "mqtt", 353147387u, 0, 4, NULL); +be_define_const_str(mqtt_data, "mqtt_data", 2538213364u, 0, 9, &be_const_str_widget_height_def); +be_define_const_str(mqtt_listener, "mqtt_listener", 2764719532u, 0, 13, &be_const_str_no_X20more_X20RMT_X20channel_X20available); +be_define_const_str(name, "name", 2369371622u, 0, 4, &be_const_str__X7B_X7D); +be_define_const_str(nan, "nan", 797905850u, 0, 3, &be_const_str_refr_pos); +be_define_const_str(next, "next", 1555467752u, 0, 4, NULL); be_define_const_str(next_cron, "next_cron", 3260705337u, 0, 9, NULL); be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL); -be_define_const_str(no_X20GPIO_X20specified_X20for_X20neopixelbus, "no GPIO specified for neopixelbus", 42078528u, 0, 33, NULL); -be_define_const_str(no_X20more_X20RMT_X20channel_X20available, "no more RMT channel available", 305838632u, 0, 29, &be_const_str_web_add_console_button); -be_define_const_str(now, "now", 682728183u, 0, 3, &be_const_str_value); -be_define_const_str(null_cb, "null_cb", 2333536460u, 0, 7, NULL); -be_define_const_str(number, "number", 467038368u, 0, 6, NULL); -be_define_const_str(nvs, "nvs", 477704066u, 0, 3, &be_const_str_set_tasmota_logo); -be_define_const_str(nvskeys, "nvskeys", 1760042990u, 0, 7, NULL); +be_define_const_str(no_X20GPIO_X20specified_X20for_X20neopixelbus, "no GPIO specified for neopixelbus", 42078528u, 0, 33, &be_const_str_signal_change); +be_define_const_str(no_X20more_X20RMT_X20channel_X20available, "no more RMT channel available", 305838632u, 0, 29, NULL); +be_define_const_str(now, "now", 682728183u, 0, 3, &be_const_str_otadata); +be_define_const_str(null_cb, "null_cb", 2333536460u, 0, 7, &be_const_str_try_compile); +be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_slots); +be_define_const_str(nvs, "nvs", 477704066u, 0, 3, NULL); +be_define_const_str(nvskeys, "nvskeys", 1760042990u, 0, 7, &be_const_str_wifi); be_define_const_str(o, "o", 3926667934u, 0, 1, NULL); -be_define_const_str(obj, "obj", 3343205242u, 0, 3, &be_const_str_splash_remove); -be_define_const_str(obj_class_create_obj, "obj_class_create_obj", 3304390632u, 0, 20, &be_const_str_write_bytes); -be_define_const_str(obj_event_base, "obj_event_base", 1624064363u, 0, 14, &be_const_str_sat); -be_define_const_str(offset, "offset", 348705738u, 0, 6, NULL); -be_define_const_str(offseta, "offseta", 1663383089u, 0, 7, NULL); -be_define_const_str(on, "on", 1630810064u, 0, 2, &be_const_str_udp); -be_define_const_str(onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E, "onsubmit='return confirm(\"This will cause a restart.\");'>", 232646018u, 0, 57, &be_const_str_tcpclient); -be_define_const_str(onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20change_X20the_X20current_X20configuration_X20and_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E, "onsubmit='return confirm(\"This will change the current configuration and cause a restart.\");'>", 3792412559u, 0, 94, NULL); -be_define_const_str(open, "open", 3546203337u, 0, 4, &be_const_str_rotate); -be_define_const_str(ota_, "ota_", 773595766u, 0, 4, &be_const_str_try); +be_define_const_str(obj, "obj", 3343205242u, 0, 3, &be_const_str_publish); +be_define_const_str(obj_class_create_obj, "obj_class_create_obj", 3304390632u, 0, 20, &be_const_str_xy); +be_define_const_str(obj_event_base, "obj_event_base", 1624064363u, 0, 14, NULL); +be_define_const_str(offset, "offset", 348705738u, 0, 6, &be_const_str_read); +be_define_const_str(offseta, "offseta", 1663383089u, 0, 7, &be_const_str_sinh); +be_define_const_str(on, "on", 1630810064u, 0, 2, &be_const_str_ota_max); +be_define_const_str(onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E, "onsubmit='return confirm(\"This will cause a restart.\");'>", 232646018u, 0, 57, NULL); +be_define_const_str(onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20change_X20the_X20current_X20configuration_X20and_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E, "onsubmit='return confirm(\"This will change the current configuration and cause a restart.\");'>", 3792412559u, 0, 94, &be_const_str_round_end); +be_define_const_str(open, "open", 3546203337u, 0, 4, NULL); +be_define_const_str(ota_, "ota_", 773595766u, 0, 4, NULL); be_define_const_str(ota_max, "ota_max", 2940511240u, 0, 7, NULL); -be_define_const_str(otadata, "otadata", 1962391757u, 0, 7, &be_const_str_save); -be_define_const_str(out_X20of_X20range, "out of range", 2236631477u, 0, 12, NULL); -be_define_const_str(p1, "p1", 2689521274u, 0, 2, NULL); -be_define_const_str(p2, "p2", 2672743655u, 0, 2, &be_const_str_widget_cb); -be_define_const_str(page_autoconf_ctl, "page_autoconf_ctl", 2453381496u, 0, 17, &be_const_str_web_add_management_button); -be_define_const_str(page_autoconf_mgr, "page_autoconf_mgr", 3643937031u, 0, 17, NULL); +be_define_const_str(otadata, "otadata", 1962391757u, 0, 7, &be_const_str_point); +be_define_const_str(out_X20of_X20range, "out of range", 2236631477u, 0, 12, &be_const_str_publish_rule); +be_define_const_str(p1, "p1", 2689521274u, 0, 2, &be_const_str_widget_group_def); +be_define_const_str(p2, "p2", 2672743655u, 0, 2, NULL); +be_define_const_str(page_autoconf_ctl, "page_autoconf_ctl", 2453381496u, 0, 17, &be_const_str_class); +be_define_const_str(page_autoconf_mgr, "page_autoconf_mgr", 3643937031u, 0, 17, &be_const_str_resize); be_define_const_str(param, "param", 1309554226u, 0, 5, NULL); be_define_const_str(parse, "parse", 1111180012u, 0, 5, NULL); be_define_const_str(partition_core, "partition_core", 2913046901u, 0, 14, NULL); -be_define_const_str(path, "path", 2223459638u, 0, 4, &be_const_str_rule); -be_define_const_str(pc, "pc", 1313756516u, 0, 2, &be_const_str_true); -be_define_const_str(pc_abs, "pc_abs", 920256495u, 0, 6, NULL); -be_define_const_str(pc_rel, "pc_rel", 991921176u, 0, 6, &be_const_str_try_remove_file); -be_define_const_str(pct, "pct", 1431300144u, 0, 3, &be_const_str_sys); -be_define_const_str(percentage, "percentage", 2538831285u, 0, 10, &be_const_str_uuid4); -be_define_const_str(persist, "persist", 3917083779u, 0, 7, NULL); -be_define_const_str(persist_X2E_p_X20is_X20not_X20a_X20map, "persist._p is not a map", 1176528732u, 0, 23, NULL); -be_define_const_str(phy, "phy", 1648673716u, 0, 3, &be_const_str_print); -be_define_const_str(pi, "pi", 1213090802u, 0, 2, &be_const_str_set_style_radius); -be_define_const_str(pin, "pin", 1866532500u, 0, 3, &be_const_str_set_timeouts); -be_define_const_str(pin_mode, "pin_mode", 3258314030u, 0, 8, NULL); +be_define_const_str(path, "path", 2223459638u, 0, 4, NULL); +be_define_const_str(pc, "pc", 1313756516u, 0, 2, NULL); +be_define_const_str(pc_abs, "pc_abs", 920256495u, 0, 6, &be_const_str_pin_used); +be_define_const_str(pc_rel, "pc_rel", 991921176u, 0, 6, NULL); +be_define_const_str(pct, "pct", 1431300144u, 0, 3, &be_const_str_raw); +be_define_const_str(percentage, "percentage", 2538831285u, 0, 10, &be_const_str_set_hue16sat); +be_define_const_str(persist, "persist", 3917083779u, 0, 7, &be_const_str_pixel_count); +be_define_const_str(persist_X2E_p_X20is_X20not_X20a_X20map, "persist._p is not a map", 1176528732u, 0, 23, &be_const_str_upper); +be_define_const_str(phy, "phy", 1648673716u, 0, 3, &be_const_str_read8); +be_define_const_str(pi, "pi", 1213090802u, 0, 2, &be_const_str_reapply); +be_define_const_str(pin, "pin", 1866532500u, 0, 3, NULL); +be_define_const_str(pin_mode, "pin_mode", 3258314030u, 0, 8, &be_const_str_wd); be_define_const_str(pin_used, "pin_used", 4033854612u, 0, 8, NULL); -be_define_const_str(pixel_count, "pixel_count", 2439130743u, 0, 11, NULL); -be_define_const_str(pixel_size, "pixel_size", 2209135785u, 0, 10, &be_const_str_set_mode_rgb); -be_define_const_str(pixels_buffer, "pixels_buffer", 1229555807u, 0, 13, &be_const_str_setrange); -be_define_const_str(point, "point", 414084241u, 0, 5, NULL); +be_define_const_str(pixel_count, "pixel_count", 2439130743u, 0, 11, &be_const_str_split); +be_define_const_str(pixel_size, "pixel_size", 2209135785u, 0, 10, &be_const_str_try); +be_define_const_str(pixels_buffer, "pixels_buffer", 1229555807u, 0, 13, NULL); +be_define_const_str(point, "point", 414084241u, 0, 5, &be_const_str_continue); be_define_const_str(point_arr, "point_arr", 1140859857u, 0, 9, NULL); be_define_const_str(pop, "pop", 1362321360u, 0, 3, NULL); -be_define_const_str(pop_path, "pop_path", 2403243998u, 0, 8, &be_const_str_resp_cmnd_error); +be_define_const_str(pop_path, "pop_path", 2403243998u, 0, 8, NULL); be_define_const_str(pow, "pow", 1479764693u, 0, 3, NULL); be_define_const_str(power_off, "power_off", 3568741752u, 0, 9, NULL); -be_define_const_str(preinit, "preinit", 2722007100u, 0, 7, &be_const_str_seq1); -be_define_const_str(print, "print", 372738696u, 0, 5, &be_const_str_write_flash); +be_define_const_str(preinit, "preinit", 2722007100u, 0, 7, &be_const_str_str); +be_define_const_str(print, "print", 372738696u, 0, 5, &be_const_str_string); be_define_const_str(ptr, "ptr", 1433816073u, 0, 3, NULL); -be_define_const_str(public_key, "public_key", 4169142980u, 0, 10, &be_const_str_running); -be_define_const_str(publish, "publish", 264247304u, 0, 7, NULL); -be_define_const_str(publish_result, "publish_result", 2013351252u, 0, 14, NULL); -be_define_const_str(publish_rule, "publish_rule", 1829459523u, 0, 12, NULL); -be_define_const_str(push, "push", 2272264157u, 0, 4, NULL); -be_define_const_str(push_path, "push_path", 1155254157u, 0, 9, &be_const_str_set_matrix_pixel_color); +be_define_const_str(public_key, "public_key", 4169142980u, 0, 10, &be_const_str_set_alternate); +be_define_const_str(publish, "publish", 264247304u, 0, 7, &be_const_str_strftime); +be_define_const_str(publish_result, "publish_result", 2013351252u, 0, 14, &be_const_str_time_reached); +be_define_const_str(publish_rule, "publish_rule", 1829459523u, 0, 12, &be_const_str_style_prop_arr); +be_define_const_str(push, "push", 2272264157u, 0, 4, &be_const_str_running); +be_define_const_str(push_path, "push_path", 1155254157u, 0, 9, NULL); be_define_const_str(quality, "quality", 2597670950u, 0, 7, NULL); -be_define_const_str(r, "r", 4144776981u, 0, 1, NULL); +be_define_const_str(r, "r", 4144776981u, 0, 1, &be_const_str_rotate); be_define_const_str(rad, "rad", 1358899048u, 0, 3, NULL); be_define_const_str(raise, "raise", 1593437475u, 70, 5, NULL); be_define_const_str(rand, "rand", 2711325910u, 0, 4, NULL); -be_define_const_str(range, "range", 4208725202u, 0, 5, &be_const_str_set); -be_define_const_str(raw, "raw", 1140790001u, 0, 3, &be_const_str_strftime); -be_define_const_str(read, "read", 3470762949u, 0, 4, &be_const_str_set_style_text_font); -be_define_const_str(read12, "read12", 4291076970u, 0, 6, &be_const_str_widget_group_def); -be_define_const_str(read13, "read13", 12887293u, 0, 6, NULL); +be_define_const_str(range, "range", 4208725202u, 0, 5, NULL); +be_define_const_str(raw, "raw", 1140790001u, 0, 3, NULL); +be_define_const_str(read, "read", 3470762949u, 0, 4, &be_const_str_stop); +be_define_const_str(read12, "read12", 4291076970u, 0, 6, NULL); +be_define_const_str(read13, "read13", 12887293u, 0, 6, &be_const_str_remove_cron); be_define_const_str(read24, "read24", 1808533811u, 0, 6, NULL); -be_define_const_str(read32, "read32", 1741276240u, 0, 6, &be_const_str_register_button_encoder); +be_define_const_str(read32, "read32", 1741276240u, 0, 6, NULL); be_define_const_str(read8, "read8", 2802788167u, 0, 5, NULL); -be_define_const_str(read_bytes, "read_bytes", 3576733173u, 0, 10, NULL); -be_define_const_str(read_sensors, "read_sensors", 892689201u, 0, 12, &be_const_str_setitem); -be_define_const_str(readbytes, "readbytes", 2716426756u, 0, 9, &be_const_str_widget_event_impl); +be_define_const_str(read_bytes, "read_bytes", 3576733173u, 0, 10, &be_const_str_resp_cmnd_str); +be_define_const_str(read_sensors, "read_sensors", 892689201u, 0, 12, NULL); +be_define_const_str(readbytes, "readbytes", 2716426756u, 0, 9, NULL); be_define_const_str(readline, "readline", 1212709927u, 0, 8, NULL); -be_define_const_str(real, "real", 3604983901u, 0, 4, &be_const_str_subtype); -be_define_const_str(reapply, "reapply", 3778939332u, 0, 7, &be_const_str_setbits); +be_define_const_str(real, "real", 3604983901u, 0, 4, &be_const_str_remove); +be_define_const_str(reapply, "reapply", 3778939332u, 0, 7, &be_const_str_sum); be_define_const_str(redirect, "redirect", 389758641u, 0, 8, NULL); -be_define_const_str(refr_now, "refr_now", 3191284735u, 0, 8, &be_const_str_signal_change); -be_define_const_str(refr_pos, "refr_pos", 1020780033u, 0, 8, &be_const_str_wire2); -be_define_const_str(refr_size, "refr_size", 1958144468u, 0, 9, NULL); +be_define_const_str(refr_now, "refr_now", 3191284735u, 0, 8, NULL); +be_define_const_str(refr_pos, "refr_pos", 1020780033u, 0, 8, NULL); +be_define_const_str(refr_size, "refr_size", 1958144468u, 0, 9, &be_const_str_tr); be_define_const_str(register_button_encoder, "register_button_encoder", 2811301550u, 0, 23, NULL); -be_define_const_str(register_obj, "register_obj", 3982614770u, 0, 12, NULL); -be_define_const_str(remote_ip, "remote_ip", 2953154693u, 0, 9, &be_const_str_splash); -be_define_const_str(remote_port, "remote_port", 2163585967u, 0, 11, &be_const_str_tan); -be_define_const_str(remove, "remove", 3683784189u, 0, 6, NULL); -be_define_const_str(remove_cmd, "remove_cmd", 3832315702u, 0, 10, &be_const_str_solidified); -be_define_const_str(remove_cron, "remove_cron", 2914538962u, 0, 11, &be_const_str_web_sensor); +be_define_const_str(register_obj, "register_obj", 3982614770u, 0, 12, &be_const_str_unknown_X20instruction); +be_define_const_str(remote_ip, "remote_ip", 2953154693u, 0, 9, &be_const_str_remove_light); +be_define_const_str(remote_port, "remote_port", 2163585967u, 0, 11, &be_const_str_topic); +be_define_const_str(remove, "remove", 3683784189u, 0, 6, &be_const_str_web_send_decimal); +be_define_const_str(remove_cmd, "remove_cmd", 3832315702u, 0, 10, &be_const_str_set_chr); +be_define_const_str(remove_cron, "remove_cron", 2914538962u, 0, 11, NULL); be_define_const_str(remove_driver, "remove_driver", 1030243768u, 0, 13, NULL); be_define_const_str(remove_light, "remove_light", 1783624394u, 0, 12, NULL); -be_define_const_str(remove_rule, "remove_rule", 3456211328u, 0, 11, &be_const_str_set_exten); -be_define_const_str(remove_timer, "remove_timer", 4141472215u, 0, 12, &be_const_str_url_encode); -be_define_const_str(remove_trailing_zeroes, "remove_trailing_zeroes", 2688378377u, 0, 22, NULL); +be_define_const_str(remove_rule, "remove_rule", 3456211328u, 0, 11, NULL); +be_define_const_str(remove_timer, "remove_timer", 4141472215u, 0, 12, &be_const_str_zcl_frame); +be_define_const_str(remove_trailing_zeroes, "remove_trailing_zeroes", 2688378377u, 0, 22, &be_const_str_set_power); be_define_const_str(reset, "reset", 1695364032u, 0, 5, NULL); -be_define_const_str(reset_search, "reset_search", 1350414305u, 0, 12, &be_const_str_raise); -be_define_const_str(resize, "resize", 3514612129u, 0, 6, &be_const_str_set_style_pad_right); +be_define_const_str(reset_search, "reset_search", 1350414305u, 0, 12, NULL); +be_define_const_str(resize, "resize", 3514612129u, 0, 6, NULL); be_define_const_str(resolvecmnd, "resolvecmnd", 993361485u, 0, 11, NULL); -be_define_const_str(resp_cmnd, "resp_cmnd", 2869459626u, 0, 9, &be_const_str_set_bat); +be_define_const_str(resp_cmnd, "resp_cmnd", 2869459626u, 0, 9, NULL); be_define_const_str(resp_cmnd_done, "resp_cmnd_done", 2601874875u, 0, 14, NULL); be_define_const_str(resp_cmnd_error, "resp_cmnd_error", 2404088863u, 0, 15, NULL); be_define_const_str(resp_cmnd_failed, "resp_cmnd_failed", 2136281562u, 0, 16, NULL); -be_define_const_str(resp_cmnd_str, "resp_cmnd_str", 737845590u, 0, 13, &be_const_str_set_width); -be_define_const_str(response_append, "response_append", 450346371u, 0, 15, &be_const_str_return_X20code_X3D_X25i); +be_define_const_str(resp_cmnd_str, "resp_cmnd_str", 737845590u, 0, 13, &be_const_str_send_multicast); +be_define_const_str(response_append, "response_append", 450346371u, 0, 15, &be_const_str_solidified); be_define_const_str(return, "return", 2246981567u, 60, 6, NULL); -be_define_const_str(return_X20code_X3D_X25i, "return code=%i", 2127454401u, 0, 14, &be_const_str_write_bit); -be_define_const_str(reverse, "reverse", 558918661u, 0, 7, &be_const_str_sin); +be_define_const_str(return_X20code_X3D_X25i, "return code=%i", 2127454401u, 0, 14, NULL); +be_define_const_str(reverse, "reverse", 558918661u, 0, 7, NULL); be_define_const_str(reverse_gamma10, "reverse_gamma10", 739112262u, 0, 15, NULL); -be_define_const_str(rotate, "rotate", 2784296202u, 0, 6, &be_const_str_set_active); +be_define_const_str(rotate, "rotate", 2784296202u, 0, 6, NULL); be_define_const_str(round_end, "round_end", 985288225u, 0, 9, NULL); -be_define_const_str(round_start, "round_start", 2949484384u, 0, 11, &be_const_str_tolower); +be_define_const_str(round_start, "round_start", 2949484384u, 0, 11, NULL); be_define_const_str(rounded, "rounded", 1920734138u, 0, 7, NULL); -be_define_const_str(rtc, "rtc", 1070575216u, 0, 3, NULL); -be_define_const_str(rule, "rule", 4230889683u, 0, 4, &be_const_str_webserver); +be_define_const_str(rtc, "rtc", 1070575216u, 0, 3, &be_const_str_stop_iteration); +be_define_const_str(rule, "rule", 4230889683u, 0, 4, &be_const_str_spiffs); be_define_const_str(run, "run", 718098122u, 0, 3, NULL); -be_define_const_str(run_bat, "run_bat", 2536903298u, 0, 7, &be_const_str_target_search); -be_define_const_str(run_cron, "run_cron", 1929098555u, 0, 8, NULL); -be_define_const_str(run_deferred, "run_deferred", 371594696u, 0, 12, &be_const_str_set_hum); -be_define_const_str(running, "running", 343848780u, 0, 7, NULL); -be_define_const_str(sat, "sat", 3592196823u, 0, 3, &be_const_str_set_chr); +be_define_const_str(run_bat, "run_bat", 2536903298u, 0, 7, &be_const_str_set_temp); +be_define_const_str(run_cron, "run_cron", 1929098555u, 0, 8, &be_const_str_skip); +be_define_const_str(run_deferred, "run_deferred", 371594696u, 0, 12, NULL); +be_define_const_str(running, "running", 343848780u, 0, 7, &be_const_str__X7Bs_X7DBatt_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D); +be_define_const_str(sat, "sat", 3592196823u, 0, 3, &be_const_str_set_ct); be_define_const_str(save, "save", 3439296072u, 0, 4, NULL); be_define_const_str(save_before_restart, "save_before_restart", 1253239338u, 0, 19, NULL); be_define_const_str(scale_uint, "scale_uint", 3090811094u, 0, 10, NULL); be_define_const_str(scan, "scan", 3974641896u, 0, 4, NULL); -be_define_const_str(scr_act, "scr_act", 2080211456u, 0, 7, NULL); -be_define_const_str(screenshot, "screenshot", 3894592561u, 0, 10, NULL); +be_define_const_str(scr_act, "scr_act", 2080211456u, 0, 7, &be_const_str_set_tasmota_logo); +be_define_const_str(screenshot, "screenshot", 3894592561u, 0, 10, &be_const_str_start); be_define_const_str(search, "search", 2150836393u, 0, 6, NULL); be_define_const_str(sec, "sec", 3139892658u, 0, 3, NULL); -be_define_const_str(seg7_font, "seg7_font", 4099690689u, 0, 9, &be_const_str_shared_key); -be_define_const_str(select, "select", 297952813u, 0, 6, &be_const_str_string); -be_define_const_str(send, "send", 1919010991u, 0, 4, &be_const_str_tasmota_X2Eset_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eset_X28_X29); -be_define_const_str(send_multicast, "send_multicast", 812185870u, 0, 14, &be_const_str_serial); -be_define_const_str(seq0, "seq0", 880225636u, 0, 4, &be_const_str_set_bits_per_sample); -be_define_const_str(seq1, "seq1", 897003255u, 0, 4, &be_const_str_widget_destructor); +be_define_const_str(seg7_font, "seg7_font", 4099690689u, 0, 9, &be_const_str_seq0); +be_define_const_str(select, "select", 297952813u, 0, 6, NULL); +be_define_const_str(send, "send", 1919010991u, 0, 4, NULL); +be_define_const_str(send_multicast, "send_multicast", 812185870u, 0, 14, &be_const_str_state); +be_define_const_str(seq0, "seq0", 880225636u, 0, 4, NULL); +be_define_const_str(seq1, "seq1", 897003255u, 0, 4, NULL); be_define_const_str(serial, "serial", 3687697785u, 0, 6, NULL); -be_define_const_str(set, "set", 3324446467u, 0, 3, NULL); -be_define_const_str(set_MAC, "set_MAC", 1617581015u, 0, 7, NULL); -be_define_const_str(set_active, "set_active", 3683994102u, 0, 10, &be_const_str_write8); +be_define_const_str(set, "set", 3324446467u, 0, 3, &be_const_str_set_bri); +be_define_const_str(set_MAC, "set_MAC", 1617581015u, 0, 7, &be_const_str_set_rgb); +be_define_const_str(set_active, "set_active", 3683994102u, 0, 10, &be_const_str_set_height); be_define_const_str(set_align, "set_align", 2592958913u, 0, 9, NULL); -be_define_const_str(set_alternate, "set_alternate", 1709680562u, 0, 13, &be_const_str_set_style_img_recolor_opa); -be_define_const_str(set_auth, "set_auth", 1057170930u, 0, 8, NULL); -be_define_const_str(set_bat, "set_bat", 2736667351u, 0, 7, &be_const_str_set_pixel_color); -be_define_const_str(set_bits_per_sample, "set_bits_per_sample", 3747657551u, 0, 19, &be_const_str_split); +be_define_const_str(set_alternate, "set_alternate", 1709680562u, 0, 13, &be_const_str_set_style_pad_all); +be_define_const_str(set_auth, "set_auth", 1057170930u, 0, 8, &be_const_str_set_pixel_color); +be_define_const_str(set_bat, "set_bat", 2736667351u, 0, 7, NULL); +be_define_const_str(set_bits_per_sample, "set_bits_per_sample", 3747657551u, 0, 19, NULL); be_define_const_str(set_bri, "set_bri", 2789118779u, 0, 7, NULL); -be_define_const_str(set_channels, "set_channels", 1370190620u, 0, 12, &be_const_str_set_text); -be_define_const_str(set_chg_current, "set_chg_current", 336304386u, 0, 15, NULL); -be_define_const_str(set_chr, "set_chr", 102133743u, 0, 7, NULL); +be_define_const_str(set_channels, "set_channels", 1370190620u, 0, 12, &be_const_str_width); +be_define_const_str(set_chg_current, "set_chg_current", 336304386u, 0, 15, &be_const_str_value); +be_define_const_str(set_chr, "set_chr", 102133743u, 0, 7, &be_const_str_set_width); be_define_const_str(set_ct, "set_ct", 972363187u, 0, 6, NULL); be_define_const_str(set_dc_voltage, "set_dc_voltage", 2181981936u, 0, 14, NULL); -be_define_const_str(set_dcdc_enable, "set_dcdc_enable", 1594690786u, 0, 15, &be_const_str_subtype_to_string); -be_define_const_str(set_exten, "set_exten", 1721782768u, 0, 9, NULL); -be_define_const_str(set_first_time, "set_first_time", 3111247550u, 0, 14, NULL); -be_define_const_str(set_gain, "set_gain", 3847781975u, 0, 8, &be_const_str_break); -be_define_const_str(set_height, "set_height", 1080207399u, 0, 10, &be_const_str_set_percentage); -be_define_const_str(set_hue16sat, "set_hue16sat", 1858983599u, 0, 12, &be_const_str_toint); -be_define_const_str(set_huesat, "set_huesat", 626496854u, 0, 10, &be_const_str_sqrt); +be_define_const_str(set_dcdc_enable, "set_dcdc_enable", 1594690786u, 0, 15, NULL); +be_define_const_str(set_exten, "set_exten", 1721782768u, 0, 9, &be_const_str_set_style_border_width); +be_define_const_str(set_first_time, "set_first_time", 3111247550u, 0, 14, &be_const_str_setmember); +be_define_const_str(set_gain, "set_gain", 3847781975u, 0, 8, &be_const_str_widget_cb); +be_define_const_str(set_height, "set_height", 1080207399u, 0, 10, NULL); +be_define_const_str(set_hue16sat, "set_hue16sat", 1858983599u, 0, 12, NULL); +be_define_const_str(set_huesat, "set_huesat", 626496854u, 0, 10, NULL); be_define_const_str(set_hum, "set_hum", 964296026u, 0, 7, NULL); -be_define_const_str(set_ldo_enable, "set_ldo_enable", 2916502041u, 0, 14, &be_const_str_strptime); +be_define_const_str(set_ldo_enable, "set_ldo_enable", 2916502041u, 0, 14, NULL); be_define_const_str(set_ldo_voltage, "set_ldo_voltage", 4090501160u, 0, 15, NULL); -be_define_const_str(set_light, "set_light", 3176076152u, 0, 9, &be_const_str_set_style_pad_all); +be_define_const_str(set_light, "set_light", 3176076152u, 0, 9, NULL); be_define_const_str(set_matrix_pixel_color, "set_matrix_pixel_color", 1197149462u, 0, 22, NULL); be_define_const_str(set_mode_ct, "set_mode_ct", 665073295u, 0, 11, NULL); -be_define_const_str(set_mode_rgb, "set_mode_rgb", 852310875u, 0, 12, NULL); +be_define_const_str(set_mode_rgb, "set_mode_rgb", 852310875u, 0, 12, &be_const_str_tcpclient); be_define_const_str(set_ota_max, "set_ota_max", 4093779527u, 0, 11, NULL); be_define_const_str(set_percentage, "set_percentage", 2952022724u, 0, 14, NULL); -be_define_const_str(set_pixel_color, "set_pixel_color", 1275248356u, 0, 15, NULL); +be_define_const_str(set_pixel_color, "set_pixel_color", 1275248356u, 0, 15, &be_const_str_tolower); be_define_const_str(set_power, "set_power", 549820893u, 0, 9, NULL); be_define_const_str(set_pwm, "set_pwm", 3781811012u, 0, 7, NULL); -be_define_const_str(set_rate, "set_rate", 1154016838u, 0, 8, &be_const_str_spiffs); -be_define_const_str(set_reachable, "set_reachable", 3280367499u, 0, 13, &be_const_str_skip); +be_define_const_str(set_rate, "set_rate", 1154016838u, 0, 8, &be_const_str_set_timeouts); +be_define_const_str(set_reachable, "set_reachable", 3280367499u, 0, 13, NULL); be_define_const_str(set_rgb, "set_rgb", 3380244855u, 0, 7, NULL); be_define_const_str(set_size, "set_size", 2183165325u, 0, 8, NULL); be_define_const_str(set_style_bg_color, "set_style_bg_color", 1689513089u, 0, 18, NULL); -be_define_const_str(set_style_border_width, "set_style_border_width", 549034191u, 0, 22, &be_const_str_stop_iteration); +be_define_const_str(set_style_border_width, "set_style_border_width", 549034191u, 0, 22, &be_const_str_uuid4); be_define_const_str(set_style_img_recolor, "set_style_img_recolor", 1245681294u, 0, 21, NULL); -be_define_const_str(set_style_img_recolor_opa, "set_style_img_recolor_opa", 2667062087u, 0, 25, NULL); -be_define_const_str(set_style_line_color, "set_style_line_color", 3665238976u, 0, 20, &be_const_str_start); +be_define_const_str(set_style_img_recolor_opa, "set_style_img_recolor_opa", 2667062087u, 0, 25, &be_const_str_target); +be_define_const_str(set_style_line_color, "set_style_line_color", 3665238976u, 0, 20, NULL); be_define_const_str(set_style_pad_all, "set_style_pad_all", 3987000607u, 0, 17, NULL); -be_define_const_str(set_style_pad_right, "set_style_pad_right", 3314069054u, 0, 19, &be_const_str_set_useragent); +be_define_const_str(set_style_pad_right, "set_style_pad_right", 3314069054u, 0, 19, NULL); be_define_const_str(set_style_radius, "set_style_radius", 3868404032u, 0, 16, NULL); be_define_const_str(set_style_text_color, "set_style_text_color", 943105189u, 0, 20, NULL); be_define_const_str(set_style_text_font, "set_style_text_font", 1028590019u, 0, 19, NULL); -be_define_const_str(set_svc, "set_svc", 752734654u, 0, 7, NULL); +be_define_const_str(set_svc, "set_svc", 752734654u, 0, 7, &be_const_str_zip); be_define_const_str(set_tasmota_logo, "set_tasmota_logo", 4090375591u, 0, 16, NULL); -be_define_const_str(set_temp, "set_temp", 1952131250u, 0, 8, &be_const_str_widget_ctor_cb); +be_define_const_str(set_temp, "set_temp", 1952131250u, 0, 8, NULL); be_define_const_str(set_text, "set_text", 1849641155u, 0, 8, NULL); -be_define_const_str(set_time, "set_time", 900236405u, 0, 8, NULL); -be_define_const_str(set_timeouts, "set_timeouts", 3732850900u, 0, 12, &be_const_str_state); +be_define_const_str(set_time, "set_time", 900236405u, 0, 8, &be_const_str_test); +be_define_const_str(set_timeouts, "set_timeouts", 3732850900u, 0, 12, NULL); be_define_const_str(set_timer, "set_timer", 2135414533u, 0, 9, NULL); -be_define_const_str(set_user_data, "set_user_data", 3596043360u, 0, 13, &be_const_str_for); -be_define_const_str(set_useragent, "set_useragent", 612237244u, 0, 13, &be_const_str_class); +be_define_const_str(set_user_data, "set_user_data", 3596043360u, 0, 13, NULL); +be_define_const_str(set_useragent, "set_useragent", 612237244u, 0, 13, &be_const_str_try_run_compiled); be_define_const_str(set_width, "set_width", 484671920u, 0, 9, NULL); be_define_const_str(set_x, "set_x", 1849400772u, 0, 5, NULL); be_define_const_str(set_xy, "set_xy", 1155092615u, 0, 6, NULL); -be_define_const_str(set_y, "set_y", 1866178391u, 0, 5, &be_const_str_value_error); +be_define_const_str(set_y, "set_y", 1866178391u, 0, 5, NULL); be_define_const_str(set_zoom, "set_zoom", 1925134407u, 0, 8, NULL); be_define_const_str(setbits, "setbits", 2762408167u, 0, 7, NULL); -be_define_const_str(setfloat, "setfloat", 2799488807u, 0, 8, &be_const_str_to_gamma); +be_define_const_str(setfloat, "setfloat", 2799488807u, 0, 8, &be_const_str_web_add_console_button); be_define_const_str(seti, "seti", 1500556254u, 0, 4, NULL); -be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, NULL); -be_define_const_str(setmember, "setmember", 1432909441u, 0, 9, NULL); -be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, NULL); -be_define_const_str(settings, "settings", 1745255176u, 0, 8, NULL); +be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, &be_const_str_write); +be_define_const_str(setmember, "setmember", 1432909441u, 0, 9, &be_const_str_wire1); +be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, &be_const_str_success); +be_define_const_str(settings, "settings", 1745255176u, 0, 8, &be_const_str_sys); be_define_const_str(shared_key, "shared_key", 2200833624u, 0, 10, NULL); -be_define_const_str(show, "show", 2840060476u, 0, 4, &be_const_str_w); +be_define_const_str(show, "show", 2840060476u, 0, 4, NULL); be_define_const_str(signal_arcs, "signal_arcs", 1505996127u, 0, 11, NULL); -be_define_const_str(signal_bars, "signal_bars", 3181573600u, 0, 11, &be_const_str_tob64); +be_define_const_str(signal_bars, "signal_bars", 3181573600u, 0, 11, &be_const_str__X7Bs_X7DBatt_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D); be_define_const_str(signal_change, "signal_change", 3262299350u, 0, 13, NULL); -be_define_const_str(sin, "sin", 3761252941u, 0, 3, &be_const_str_widget_event); +be_define_const_str(sin, "sin", 3761252941u, 0, 3, NULL); be_define_const_str(sinh, "sinh", 282220607u, 0, 4, NULL); -be_define_const_str(size, "size", 597743964u, 0, 4, NULL); -be_define_const_str(skip, "skip", 1097563074u, 0, 4, &be_const_str__X7B); -be_define_const_str(slots, "slots", 1023330342u, 0, 5, &be_const_str_while); +be_define_const_str(size, "size", 597743964u, 0, 4, &be_const_str_timer_cb); +be_define_const_str(skip, "skip", 1097563074u, 0, 4, NULL); +be_define_const_str(slots, "slots", 1023330342u, 0, 5, NULL); be_define_const_str(solidified, "solidified", 3257553487u, 0, 10, NULL); be_define_const_str(spiffs, "spiffs", 994943858u, 0, 6, NULL); -be_define_const_str(splash, "splash", 2531464038u, 0, 6, &be_const_str_srand); -be_define_const_str(splash_init, "splash_init", 1522992293u, 0, 11, &be_const_str_wd); +be_define_const_str(splash, "splash", 2531464038u, 0, 6, NULL); +be_define_const_str(splash_init, "splash_init", 1522992293u, 0, 11, NULL); be_define_const_str(splash_remove, "splash_remove", 3132020807u, 0, 13, NULL); -be_define_const_str(split, "split", 2276994531u, 0, 5, &be_const_str_unknown_X20instruction); -be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, &be_const_str_yield); +be_define_const_str(split, "split", 2276994531u, 0, 5, NULL); +be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, &be_const_str_wifi_bars_icon); be_define_const_str(srand, "srand", 465518633u, 0, 5, NULL); -be_define_const_str(start, "start", 1697318111u, 0, 5, NULL); +be_define_const_str(start, "start", 1697318111u, 0, 5, &be_const_str_time_dump); be_define_const_str(started, "started", 2153339806u, 0, 7, NULL); be_define_const_str(state, "state", 2016490230u, 0, 5, NULL); be_define_const_str(static, "static", 3532702267u, 71, 6, NULL); be_define_const_str(stop, "stop", 3411225317u, 0, 4, NULL); be_define_const_str(stop_iteration, "stop_iteration", 4173793901u, 0, 14, NULL); -be_define_const_str(str, "str", 3259748752u, 0, 3, NULL); +be_define_const_str(str, "str", 3259748752u, 0, 3, &be_const_str_x1); be_define_const_str(strftime, "strftime", 187738851u, 0, 8, NULL); be_define_const_str(string, "string", 398550328u, 0, 6, NULL); be_define_const_str(strip, "strip", 4246411473u, 0, 5, NULL); -be_define_const_str(strptime, "strptime", 1277910361u, 0, 8, &be_const_str_toupper); +be_define_const_str(strptime, "strptime", 1277910361u, 0, 8, NULL); be_define_const_str(style_prop_arr, "style_prop_arr", 3019174322u, 0, 14, NULL); -be_define_const_str(subscribe, "subscribe", 2946386435u, 0, 9, &be_const_str_success); +be_define_const_str(subscribe, "subscribe", 2946386435u, 0, 9, &be_const_str_else); be_define_const_str(subtype, "subtype", 2023873341u, 0, 7, NULL); be_define_const_str(subtype_to_string, "subtype_to_string", 2996733901u, 0, 17, NULL); be_define_const_str(success, "success", 979353360u, 0, 7, NULL); +be_define_const_str(sum, "sum", 3712891560u, 0, 3, NULL); be_define_const_str(super, "super", 4152230356u, 0, 5, NULL); -be_define_const_str(switch_factory, "switch_factory", 4206217516u, 0, 14, NULL); +be_define_const_str(switch_factory, "switch_factory", 4206217516u, 0, 14, &be_const_str_web_send); be_define_const_str(sys, "sys", 3277365014u, 0, 3, NULL); -be_define_const_str(tag, "tag", 2516003219u, 0, 3, &be_const_str_wire1); +be_define_const_str(tag, "tag", 2516003219u, 0, 3, NULL); be_define_const_str(tan, "tan", 2633446552u, 0, 3, NULL); -be_define_const_str(tanh, "tanh", 153638352u, 0, 4, NULL); +be_define_const_str(tanh, "tanh", 153638352u, 0, 4, &be_const_str_tasmota_X2Eset_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eset_X28_X29); be_define_const_str(target, "target", 845187144u, 0, 6, NULL); -be_define_const_str(target_search, "target_search", 1947846553u, 0, 13, &be_const_str_tr); +be_define_const_str(target_search, "target_search", 1947846553u, 0, 13, NULL); be_define_const_str(tasmota, "tasmota", 424643812u, 0, 7, NULL); be_define_const_str(tasmota_X2Eget_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eget_X28_X29, "tasmota.get_light() is deprecated, use light.get()", 3525753647u, 0, 50, NULL); be_define_const_str(tasmota_X2Eset_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eset_X28_X29, "tasmota.set_light() is deprecated, use light.set()", 2124937871u, 0, 50, NULL); be_define_const_str(tasmota_log_reader, "tasmota_log_reader", 3555069257u, 0, 18, NULL); -be_define_const_str(tcpclient, "tcpclient", 3828797983u, 0, 9, &be_const_str_web_add_button); +be_define_const_str(tcpclient, "tcpclient", 3828797983u, 0, 9, &be_const_str_as); be_define_const_str(tele, "tele", 3474458061u, 0, 4, NULL); be_define_const_str(test, "test", 2949673445u, 0, 4, NULL); -be_define_const_str(the_X20second_X20argument_X20is_X20not_X20a_X20function, "the second argument is not a function", 3954574469u, 0, 37, NULL); +be_define_const_str(the_X20second_X20argument_X20is_X20not_X20a_X20function, "the second argument is not a function", 3954574469u, 0, 37, &be_const_str_if); be_define_const_str(time_dump, "time_dump", 3330410747u, 0, 9, NULL); -be_define_const_str(time_reached, "time_reached", 2075136773u, 0, 12, NULL); +be_define_const_str(time_reached, "time_reached", 2075136773u, 0, 12, &be_const_str_type_error); be_define_const_str(time_str, "time_str", 2613827612u, 0, 8, NULL); be_define_const_str(timer_cb, "timer_cb", 79918026u, 0, 8, NULL); -be_define_const_str(to_gamma, "to_gamma", 1597139862u, 0, 8, NULL); +be_define_const_str(to_gamma, "to_gamma", 1597139862u, 0, 8, &be_const_str_unsubscribe); be_define_const_str(tob64, "tob64", 373777640u, 0, 5, NULL); be_define_const_str(tobytes, "tobytes", 595962279u, 0, 7, NULL); +be_define_const_str(tohex, "tohex", 1583935793u, 0, 5, NULL); be_define_const_str(toint, "toint", 3613182909u, 0, 5, NULL); be_define_const_str(tolower, "tolower", 1042520049u, 0, 7, NULL); -be_define_const_str(tomap, "tomap", 612167626u, 0, 5, NULL); +be_define_const_str(tomap, "tomap", 612167626u, 0, 5, &be_const_str_widget_dtor_cb); be_define_const_str(top, "top", 2802900028u, 0, 3, NULL); -be_define_const_str(topic, "topic", 3264522692u, 0, 5, &be_const_str_upper); +be_define_const_str(topic, "topic", 3264522692u, 0, 5, NULL); be_define_const_str(toptr, "toptr", 3379847454u, 0, 5, NULL); -be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, &be_const_str_import); -be_define_const_str(touch_update, "touch_update", 1918102068u, 0, 12, &be_const_str_try_get_bec_version); -be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, NULL); -be_define_const_str(tr, "tr", 1195724803u, 0, 2, NULL); -be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, &be_const_str_type_error); +be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, NULL); +be_define_const_str(touch_update, "touch_update", 1918102068u, 0, 12, NULL); +be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, &be_const_str__X7Bs_X7DVBus_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D); +be_define_const_str(tr, "tr", 1195724803u, 0, 2, &be_const_str_udp); +be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, NULL); be_define_const_str(trig, "trig", 2073314619u, 0, 4, NULL); be_define_const_str(true, "true", 1303515621u, 61, 4, NULL); be_define_const_str(try, "try", 2887626766u, 68, 3, NULL); -be_define_const_str(try_compile, "try_compile", 4263879840u, 0, 11, &be_const_str_zero); +be_define_const_str(try_compile, "try_compile", 4263879840u, 0, 11, NULL); be_define_const_str(try_get_bec_version, "try_get_bec_version", 3143116423u, 0, 19, NULL); -be_define_const_str(try_remove_file, "try_remove_file", 3025429926u, 0, 15, NULL); -be_define_const_str(try_rule, "try_rule", 1986449405u, 0, 8, &be_const_str__X7D); -be_define_const_str(try_run_compiled, "try_run_compiled", 2339741218u, 0, 16, NULL); -be_define_const_str(type, "type", 1361572173u, 0, 4, NULL); -be_define_const_str(type_error, "type_error", 3789613824u, 0, 10, &be_const_str__X7Bs_X7DBatt_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D); -be_define_const_str(type_to_string, "type_to_string", 1072804509u, 0, 14, &be_const_str_x1); -be_define_const_str(udp, "udp", 1253872004u, 0, 3, &be_const_str_web_send_decimal); +be_define_const_str(try_remove_file, "try_remove_file", 3025429926u, 0, 15, &be_const_str_url_encode); +be_define_const_str(try_rule, "try_rule", 1986449405u, 0, 8, &be_const_str_widget_editable); +be_define_const_str(try_run_compiled, "try_run_compiled", 2339741218u, 0, 16, &be_const_str_web_add_management_button); +be_define_const_str(type, "type", 1361572173u, 0, 4, &be_const_str_valuer_error); +be_define_const_str(type_error, "type_error", 3789613824u, 0, 10, NULL); +be_define_const_str(type_to_string, "type_to_string", 1072804509u, 0, 14, &be_const_str_zcl_frame_ntv); +be_define_const_str(udp, "udp", 1253872004u, 0, 3, NULL); be_define_const_str(unknown_X20instruction, "unknown instruction", 1093911841u, 0, 19, NULL); -be_define_const_str(unsubscribe, "unsubscribe", 4190043798u, 0, 11, NULL); +be_define_const_str(unsubscribe, "unsubscribe", 4190043798u, 0, 11, &be_const_str_for); be_define_const_str(update, "update", 672109684u, 0, 6, NULL); be_define_const_str(upper, "upper", 176974407u, 0, 5, NULL); -be_define_const_str(url_encode, "url_encode", 528392145u, 0, 10, NULL); -be_define_const_str(uuid4, "uuid4", 1153582450u, 0, 5, NULL); -be_define_const_str(value, "value", 1113510858u, 0, 5, &be_const_str_wifi_bars); +be_define_const_str(url_encode, "url_encode", 528392145u, 0, 10, &be_const_str_widget_ctor_cb); +be_define_const_str(uuid4, "uuid4", 1153582450u, 0, 5, &be_const_str_wifi_bars); +be_define_const_str(value, "value", 1113510858u, 0, 5, NULL); be_define_const_str(value_error, "value_error", 773297791u, 0, 11, NULL); be_define_const_str(valuer_error, "valuer_error", 2567947105u, 0, 12, NULL); be_define_const_str(var, "var", 2317739966u, 64, 3, NULL); @@ -969,10 +977,10 @@ be_define_const_str(w, "w", 4060888886u, 0, 1, NULL); be_define_const_str(wd, "wd", 1531424278u, 0, 2, NULL); be_define_const_str(web_add_button, "web_add_button", 3537875058u, 0, 14, NULL); be_define_const_str(web_add_config_button, "web_add_config_button", 639674325u, 0, 21, NULL); -be_define_const_str(web_add_console_button, "web_add_console_button", 3481436192u, 0, 22, NULL); +be_define_const_str(web_add_console_button, "web_add_console_button", 3481436192u, 0, 22, &be_const_str_yield); be_define_const_str(web_add_handler, "web_add_handler", 3990174962u, 0, 15, NULL); be_define_const_str(web_add_main_button, "web_add_main_button", 3960367664u, 0, 19, NULL); -be_define_const_str(web_add_management_button, "web_add_management_button", 2738877186u, 0, 25, &be_const_str__X7B_X7D); +be_define_const_str(web_add_management_button, "web_add_management_button", 2738877186u, 0, 25, NULL); be_define_const_str(web_send, "web_send", 2989941448u, 0, 8, NULL); be_define_const_str(web_send_decimal, "web_send_decimal", 1407210204u, 0, 16, NULL); be_define_const_str(web_sensor, "web_sensor", 2900096972u, 0, 10, NULL); @@ -983,34 +991,34 @@ be_define_const_str(widget_cb, "widget_cb", 2763583055u, 0, 9, NULL); be_define_const_str(widget_constructor, "widget_constructor", 2543785934u, 0, 18, NULL); be_define_const_str(widget_ctor_cb, "widget_ctor_cb", 876007560u, 0, 14, NULL); be_define_const_str(widget_ctor_impl, "widget_ctor_impl", 194252479u, 0, 16, NULL); -be_define_const_str(widget_destructor, "widget_destructor", 4207388345u, 0, 17, NULL); -be_define_const_str(widget_dtor_cb, "widget_dtor_cb", 3151545845u, 0, 14, &be_const_str_end); -be_define_const_str(widget_dtor_impl, "widget_dtor_impl", 520430610u, 0, 16, NULL); -be_define_const_str(widget_editable, "widget_editable", 3821793286u, 0, 15, NULL); +be_define_const_str(widget_destructor, "widget_destructor", 4207388345u, 0, 17, &be_const_str_write_bit); +be_define_const_str(widget_dtor_cb, "widget_dtor_cb", 3151545845u, 0, 14, &be_const_str__X7Bs_X7DTemp_X20AXP_X7Bm_X7D_X25_X2E1f_X20_X26deg_X3BC_X7Be_X7D); +be_define_const_str(widget_dtor_impl, "widget_dtor_impl", 520430610u, 0, 16, &be_const_str_import); +be_define_const_str(widget_editable, "widget_editable", 3821793286u, 0, 15, &be_const_str_write_file); be_define_const_str(widget_event, "widget_event", 1951408186u, 0, 12, NULL); -be_define_const_str(widget_event_cb, "widget_event_cb", 1508466754u, 0, 15, &be_const_str_width_def); +be_define_const_str(widget_event_cb, "widget_event_cb", 1508466754u, 0, 15, &be_const_str__X7Bs_X7DVBus_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D); be_define_const_str(widget_event_impl, "widget_event_impl", 2178430561u, 0, 17, NULL); -be_define_const_str(widget_group_def, "widget_group_def", 1246968785u, 0, 16, &be_const_str_nil); +be_define_const_str(widget_group_def, "widget_group_def", 1246968785u, 0, 16, NULL); be_define_const_str(widget_height_def, "widget_height_def", 3131667813u, 0, 17, NULL); -be_define_const_str(widget_instance_size, "widget_instance_size", 2055354779u, 0, 20, NULL); +be_define_const_str(widget_instance_size, "widget_instance_size", 2055354779u, 0, 20, &be_const_str_false); be_define_const_str(widget_struct_by_class, "widget_struct_by_class", 3806373842u, 0, 22, NULL); be_define_const_str(widget_struct_default, "widget_struct_default", 781673633u, 0, 21, NULL); be_define_const_str(widget_width_def, "widget_width_def", 3986078862u, 0, 16, NULL); be_define_const_str(width, "width", 2508680735u, 0, 5, NULL); -be_define_const_str(width_def, "width_def", 1143717879u, 0, 9, &be_const_str_as); -be_define_const_str(wifi, "wifi", 120087624u, 0, 4, &be_const_str_wire); +be_define_const_str(width_def, "width_def", 1143717879u, 0, 9, NULL); +be_define_const_str(wifi, "wifi", 120087624u, 0, 4, NULL); be_define_const_str(wifi_arcs, "wifi_arcs", 3838492904u, 0, 9, NULL); be_define_const_str(wifi_arcs_icon, "wifi_arcs_icon", 767180544u, 0, 14, NULL); be_define_const_str(wifi_bars, "wifi_bars", 653141243u, 0, 9, NULL); -be_define_const_str(wifi_bars_icon, "wifi_bars_icon", 3641522557u, 0, 14, NULL); +be_define_const_str(wifi_bars_icon, "wifi_bars_icon", 3641522557u, 0, 14, &be_const_str_year); be_define_const_str(wire, "wire", 4082753944u, 0, 4, NULL); be_define_const_str(wire1, "wire1", 3212721419u, 0, 5, NULL); be_define_const_str(wire2, "wire2", 3229499038u, 0, 5, NULL); be_define_const_str(wire_scan, "wire_scan", 2671275880u, 0, 9, NULL); be_define_const_str(write, "write", 3190202204u, 0, 5, NULL); -be_define_const_str(write8, "write8", 3133991532u, 0, 6, &be_const_str_elif); +be_define_const_str(write8, "write8", 3133991532u, 0, 6, NULL); be_define_const_str(write_bit, "write_bit", 2660990436u, 0, 9, NULL); -be_define_const_str(write_bytes, "write_bytes", 1227543792u, 0, 11, &be_const_str_do); +be_define_const_str(write_bytes, "write_bytes", 1227543792u, 0, 11, NULL); be_define_const_str(write_file, "write_file", 3177658879u, 0, 10, NULL); be_define_const_str(write_flash, "write_flash", 3003629621u, 0, 11, NULL); be_define_const_str(write_gpio, "write_gpio", 2267940334u, 0, 10, NULL); @@ -1020,11 +1028,15 @@ be_define_const_str(xy, "xy", 1482915802u, 0, 2, NULL); be_define_const_str(y, "y", 4228665076u, 0, 1, NULL); be_define_const_str(y1, "y1", 2355101727u, 0, 2, NULL); be_define_const_str(year, "year", 2927578396u, 0, 4, NULL); -be_define_const_str(yield, "yield", 1821831854u, 0, 5, NULL); +be_define_const_str(yield, "yield", 1821831854u, 0, 5, &be_const_str_static); +be_define_const_str(zb_coord_ntv, "zb_coord_ntv", 1266983504u, 0, 12, NULL); +be_define_const_str(zb_device, "zb_device", 2987454808u, 0, 9, NULL); +be_define_const_str(zcl_frame, "zcl_frame", 3755758684u, 0, 9, NULL); +be_define_const_str(zcl_frame_ntv, "zcl_frame_ntv", 4005322111u, 0, 13, NULL); be_define_const_str(zero, "zero", 2339366755u, 0, 4, NULL); -be_define_const_str(zip, "zip", 2877453236u, 0, 3, NULL); +be_define_const_str(zip, "zip", 2877453236u, 0, 3, &be_const_str_raise); be_define_const_str(_X7B, "{", 4262220314u, 0, 1, NULL); -be_define_const_str(_X7Bs_X7DBatt_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D, "{s}Batt Current{m}%.1f mA{e}", 866537156u, 0, 28, &be_const_str_else); +be_define_const_str(_X7Bs_X7DBatt_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D, "{s}Batt Current{m}%.1f mA{e}", 866537156u, 0, 28, NULL); be_define_const_str(_X7Bs_X7DBatt_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D, "{s}Batt Voltage{m}%.3f V{e}", 3184308199u, 0, 27, NULL); be_define_const_str(_X7Bs_X7DTemp_X20AXP_X7Bm_X7D_X25_X2E1f_X20_X26deg_X3BC_X7Be_X7D, "{s}Temp AXP{m}%.1f °C{e}", 2622904081u, 0, 28, NULL); be_define_const_str(_X7Bs_X7DVBus_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D, "{s}VBus Current{m}%.1f mA{e}", 1032721155u, 0, 28, NULL); @@ -1033,515 +1045,521 @@ be_define_const_str(_X7B_X7D, "{}", 1415952421u, 0, 2, NULL); be_define_const_str(_X7D, "}", 4161554600u, 0, 1, NULL); static const bstring* const m_string_table[] = { - (const bstring *)&be_const_str__drivers, - (const bstring *)&be_const_str_get_style_pad_right, - (const bstring *)&be_const_str_pi, - (const bstring *)&be_const_str__X3A, (const bstring *)&be_const_str_scale_uint, NULL, - (const bstring *)&be_const_str_SERIAL_7E1, - (const bstring *)&be_const_str_back_forth, NULL, - (const bstring *)&be_const_str_get_hor_res, - (const bstring *)&be_const_str_a, - (const bstring *)&be_const_str__X2Fstate_X2F, - (const bstring *)&be_const_str_connect, - (const bstring *)&be_const_str_duration, - (const bstring *)&be_const_str__X3Coption_X20value_X3D_X27_X25s_X27_X3E_X25s_X3C_X2Foption_X3E, - (const bstring *)&be_const_str_lv_point, + (const bstring *)&be_const_str_pixel_size, NULL, - (const bstring *)&be_const_str__cmd, - (const bstring *)&be_const_str_AES_GCM, - (const bstring *)&be_const_str_create_segment, - (const bstring *)&be_const_str__X2E_X2E, - (const bstring *)&be_const_str_item, - (const bstring *)&be_const_str__settings_def, - (const bstring *)&be_const_str_lv_signal_arcs, - (const bstring *)&be_const_str_wifi_arcs, - NULL, - (const bstring *)&be_const_str__X23autoexec_X2Ebe, - (const bstring *)&be_const_str_no_X20more_X20RMT_X20channel_X20available, - (const bstring *)&be_const_str_RELAY, - (const bstring *)&be_const_str_BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s, - (const bstring *)&be_const_str_content_flush, - (const bstring *)&be_const_str_find_key_i, - (const bstring *)&be_const_str__X23autoexec_X2Ebat, - (const bstring *)&be_const_str_consume_mono, - (const bstring *)&be_const_str_EVENT_DRAW_MAIN, - (const bstring *)&be_const_str_preinit, - (const bstring *)&be_const_str_gc, - (const bstring *)&be_const_str_app, - (const bstring *)&be_const_str_BECDFE, - (const bstring *)&be_const_str_bri, - (const bstring *)&be_const_str__X3D_X3D, - (const bstring *)&be_const_str_id, - (const bstring *)&be_const_str_chars_in_string, - (const bstring *)&be_const_str_get_event_cb, - (const bstring *)&be_const_str_No_X20SPIFFS_X20partition_X20found, - (const bstring *)&be_const_str_connection_error, - (const bstring *)&be_const_str_AA50, - (const bstring *)&be_const_str_find, - (const bstring *)&be_const_str__lvgl, - (const bstring *)&be_const_str_if, - (const bstring *)&be_const_str__write, - (const bstring *)&be_const_str__X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, - (const bstring *)&be_const_str_atleast1, - (const bstring *)&be_const_str_BRY_X3A_X20argument_X20must_X20be_X20a_X20function, - (const bstring *)&be_const_str_discover, - (const bstring *)&be_const_str_set_xy, - (const bstring *)&be_const_str__X3Cp_X3E_X3Csmall_X3E_X26nbsp_X3B_X28This_X20feature_X20requires_X20an_X20internet_X20connection_X29_X3C_X2Fsmall_X3E_X3C_X2Fp_X3E, - (const bstring *)&be_const_str_WS2812_GRB, - (const bstring *)&be_const_str__X2Fac, - (const bstring *)&be_const_str_GET, - (const bstring *)&be_const_str_read12, - (const bstring *)&be_const_str_tomap, - (const bstring *)&be_const_str_get_factory_slot, - (const bstring *)&be_const_str_get_pixel_color, - (const bstring *)&be_const_str_invalid_X20magic_X20number_X20_X2502X, - (const bstring *)&be_const_str__X3Coption_X20value_X3D_X27reset_X27_X3E_X26lt_X3BRemove_X20autoconf_X26gt_X3B_X3C_X2Foption_X3E, - (const bstring *)&be_const_str__X20_X28, - NULL, - (const bstring *)&be_const_str_CFG_X3A_X20removing_X20first_X20time_X20marker, + (const bstring *)&be_const_str_add_cmd, + (const bstring *)&be_const_str__X2E, + (const bstring *)&be_const_str_set_style_line_color, (const bstring *)&be_const_str__X0A_X29_X3E, - (const bstring *)&be_const_str_run_cron, - (const bstring *)&be_const_str__X2Ebec, - (const bstring *)&be_const_str_arg_size, - NULL, - (const bstring *)&be_const_str__X2D_X2A, - (const bstring *)&be_const_str_RGB, - (const bstring *)&be_const_str_add_cb_event_closure, - NULL, - (const bstring *)&be_const_str_json_fdump_list, - (const bstring *)&be_const_str_HTTP_POST, - (const bstring *)&be_const_str__X23display_X2Eini, - (const bstring *)&be_const_str_I2C_X3A, - (const bstring *)&be_const_str_SERIAL_6E2, - (const bstring *)&be_const_str_MAX_RMT, - (const bstring *)&be_const_str_base_class, - (const bstring *)&be_const_str_set_rgb, - (const bstring *)&be_const_str_SERIAL_6E1, - (const bstring *)&be_const_str_light_to_id, - (const bstring *)&be_const_str_clock, - NULL, - (const bstring *)&be_const_str_try_rule, - (const bstring *)&be_const_str_hue, - (const bstring *)&be_const_str_SERIAL_6O1, - (const bstring *)&be_const_str_isrunning, - (const bstring *)&be_const_str__X26lt_X3BError_X3A_X20apply_X20new_X20or_X20remove_X26gt_X3B, - NULL, - (const bstring *)&be_const_str__X3E_X3D, - (const bstring *)&be_const_str__X2Ep2, - (const bstring *)&be_const_str__X20_X20, - NULL, - (const bstring *)&be_const_str_rand, - (const bstring *)&be_const_str__X2Ep1, - (const bstring *)&be_const_str_add_header, - (const bstring *)&be_const_str__X3Clambda_X3E, - (const bstring *)&be_const_str_SERIAL_6O2, - (const bstring *)&be_const_str_TAP_X3A_X20Loaded_X20Tasmota_X20App_X20_X27_X25s_X27, - (const bstring *)&be_const_str_add_fast_loop, - (const bstring *)&be_const_str_font_montserrat, - (const bstring *)&be_const_str__X2Flights_X2F, - NULL, - (const bstring *)&be_const_str_x, - (const bstring *)&be_const_str_started, - (const bstring *)&be_const_str_arch, - (const bstring *)&be_const_str_add_light, - (const bstring *)&be_const_str_set_reachable, - (const bstring *)&be_const_str_BRY_X3A_X20bytecode_X20has_X20wrong_X20version_X20_X27_X25s_X27_X20_X28_X25i_X29, - NULL, - (const bstring *)&be_const_str_load_freetype_font, - NULL, - (const bstring *)&be_const_str_event, - (const bstring *)&be_const_str_asin, - (const bstring *)&be_const_str_EC_C25519, - (const bstring *)&be_const_str__X23init_X2Ebat, - (const bstring *)&be_const_str_set_power, - (const bstring *)&be_const_str_cmd, - (const bstring *)&be_const_str_consume_silence, - (const bstring *)&be_const_str__X2C_X22AXP192_X22_X3A_X7B_X22VBusVoltage_X22_X3A_X25_X2E3f_X2C_X22VBusCurrent_X22_X3A_X25_X2E1f_X2C_X22BattVoltage_X22_X3A_X25_X2E3f_X2C_X22BattCurrent_X22_X3A_X25_X2E1f_X2C_X22Temperature_X22_X3A_X25_X2E1f_X7D, - (const bstring *)&be_const_str_BRY_X3A_X20could_X20not_X20save_X20compiled_X20file_X20_X25s_X20_X28_X25s_X29, - (const bstring *)&be_const_str_INTERNAL_PDM, - (const bstring *)&be_const_str_iter, - NULL, - NULL, - (const bstring *)&be_const_str_time_str, - NULL, - (const bstring *)&be_const_str_update, - (const bstring *)&be_const_str_encrypt, - (const bstring *)&be_const_str_get_MAC, - (const bstring *)&be_const_str_otadata, - (const bstring *)&be_const_str_SERIAL_8O2, - (const bstring *)&be_const_str_AudioOutputI2S, - (const bstring *)&be_const_str__end_transmission, - (const bstring *)&be_const_str_set_chg_current, - (const bstring *)&be_const_str_SERIAL_8O1, - (const bstring *)&be_const_str__X2Ebe, - (const bstring *)&be_const_str_ALIGN_BOTTOM_MID, - (const bstring *)&be_const_str_begin_multicast, - (const bstring *)&be_const_str_redirect, - (const bstring *)&be_const_str__X3Cinstance_X3A_X20Partition_X28_X5B_X0A, - (const bstring *)&be_const_str__buffer, - (const bstring *)&be_const_str__X2Ep, - (const bstring *)&be_const_str_begin, - (const bstring *)&be_const_str__error, - NULL, - (const bstring *)&be_const_str_font_embedded, - NULL, - (const bstring *)&be_const_str_OPTION_A, - (const bstring *)&be_const_str_set_dc_voltage, - (const bstring *)&be_const_str_Unknown_X20command, - (const bstring *)&be_const_str_CFG_X3A_X20loaded_X20_X20, - (const bstring *)&be_const_str_INTERNAL_DAC, - (const bstring *)&be_const_str_https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_manifest_X2Ejson, - (const bstring *)&be_const_str_BUTTON_CONFIGURATION, - NULL, - (const bstring *)&be_const_str_splash_init, - (const bstring *)&be_const_str_class_init_obj, - (const bstring *)&be_const_str_animate, - (const bstring *)&be_const_str_SERIAL_8E1, - NULL, - (const bstring *)&be_const_str__X2F_X2Eautoconf, - (const bstring *)&be_const_str__X2Etapp, - (const bstring *)&be_const_str_geti, - (const bstring *)&be_const_str_argument_X20must_X20be_X20a_X20list, - (const bstring *)&be_const_str_debug, - (const bstring *)&be_const_str_ins_time, - NULL, - (const bstring *)&be_const_str_set_time, - (const bstring *)&be_const_str_draw_arc, - (const bstring *)&be_const_str__splash, - (const bstring *)&be_const_str_SERIAL_8E2, - (const bstring *)&be_const_str_draw_arc_dsc_init, - (const bstring *)&be_const_str_decompress, - (const bstring *)&be_const_str_Wire, - (const bstring *)&be_const_str_CFG_X3A_X20ran_X20_X20, - (const bstring *)&be_const_str__X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29, - (const bstring *)&be_const_str_https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_X2F_X25s_X2Eautoconf, - NULL, - (const bstring *)&be_const_str_00, - (const bstring *)&be_const_str_topic, - (const bstring *)&be_const_str_path, - (const bstring *)&be_const_str_erase, - (const bstring *)&be_const_str__read, - (const bstring *)&be_const_str_BRY_X3A_X20Exception_X3E_X20_X27, - (const bstring *)&be_const_str_constructor_cb, - (const bstring *)&be_const_str_lv_wifi_arcs, - (const bstring *)&be_const_str_seg7_font, - (const bstring *)&be_const_str__X7Bs_X7DVBus_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D, - (const bstring *)&be_const_str__X3C_X3D, - (const bstring *)&be_const_str_tasmota_X2Eget_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eget_X28_X29, - (const bstring *)&be_const_str_every_50ms, - (const bstring *)&be_const_str_lv_obj_class, - NULL, - NULL, - (const bstring *)&be_const_str_obj, - (const bstring *)&be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, - (const bstring *)&be_const_str__X25s_X2Eautoconf, - (const bstring *)&be_const_str_maxota, - NULL, - (const bstring *)&be_const_str_def, - (const bstring *)&be_const_str_AudioGeneratorWAV, - (const bstring *)&be_const_str__request_from, - (const bstring *)&be_const_str_SERIAL_5E1, - (const bstring *)&be_const_str_call, - (const bstring *)&be_const_str_crc32_ota_seq, - (const bstring *)&be_const_str_decrypt, - (const bstring *)&be_const_str_SERIAL_5E2, - (const bstring *)&be_const_str_flags, - (const bstring *)&be_const_str_phy, - (const bstring *)&be_const_str_month, - (const bstring *)&be_const_str_frombytes, - (const bstring *)&be_const_str_full_status, - (const bstring *)&be_const_str_code, - (const bstring *)&be_const_str_setmember, - NULL, - (const bstring *)&be_const_str_engine, - NULL, - (const bstring *)&be_const_str_SERIAL_7O1, - NULL, - (const bstring *)&be_const_str_model, - (const bstring *)&be_const_str_gamma10, - (const bstring *)&be_const_str_SERIAL_7O2, - (const bstring *)&be_const_str__filename, - (const bstring *)&be_const_str_depower, - (const bstring *)&be_const_str__settings_ptr, - NULL, - (const bstring *)&be_const_str_widget_instance_size, - (const bstring *)&be_const_str_COLOR_WHITE, - (const bstring *)&be_const_str__X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E, - (const bstring *)&be_const_str_widget_width_def, - NULL, - (const bstring *)&be_const_str_elements_X20must_X20be_X20a_X20lv_point, - (const bstring *)&be_const_str_acos, - (const bstring *)&be_const_str_screenshot, - (const bstring *)&be_const_str_run, - (const bstring *)&be_const_str__persist_X2Ejson, - (const bstring *)&be_const_str_attrdump, - NULL, - (const bstring *)&be_const_str_get_vbus_voltage, - (const bstring *)&be_const_str_del, - (const bstring *)&be_const_str_Tasmota, - (const bstring *)&be_const_str_fromstring, - NULL, - (const bstring *)&be_const_str__t, - (const bstring *)&be_const_str_reset, - (const bstring *)&be_const_str_delete_all_configs, + (const bstring *)&be_const_str_get_coords, + (const bstring *)&be_const_str_check_not_method, (const bstring *)&be_const_str_fromptr, - (const bstring *)&be_const_str_CFG_X3A_X20could_X20not_X20run_X20_X25s_X20_X28_X25s_X20_X2D_X20_X25s_X29, - (const bstring *)&be_const_str_lv_coord_arr, + (const bstring *)&be_const_str_init, + (const bstring *)&be_const_str_https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_X2F_X25s_X2Eautoconf, + (const bstring *)&be_const_str_sec, + (const bstring *)&be_const_str__settings_def, + (const bstring *)&be_const_str_set_style_pad_right, + (const bstring *)&be_const_str__X3Coption_X20value_X3D_X27_X25s_X27_X3E_X25s_X3C_X2Foption_X3E, + (const bstring *)&be_const_str_x, + (const bstring *)&be_const_str_content_start, + (const bstring *)&be_const_str_digital_read, + (const bstring *)&be_const_str_toint, + (const bstring *)&be_const_str_CT, + (const bstring *)&be_const_str__debug_present, + (const bstring *)&be_const_str__class, + (const bstring *)&be_const_str__, + (const bstring *)&be_const_str_TASMOTA, + (const bstring *)&be_const_str_find_op, + (const bstring *)&be_const_str_lv_timer_cb, + (const bstring *)&be_const_str_finish, + NULL, + (const bstring *)&be_const_str_seg7_font, + NULL, + (const bstring *)&be_const_str_BRY_X3A_X20failed_X20to_X20load_X20_X27_X25s_X27_X20_X28_X25s_X20_X2D_X20_X25s_X29, + (const bstring *)&be_const_str_redirect, + (const bstring *)&be_const_str_SERIAL_7N2, + (const bstring *)&be_const_str_list_handlers, + (const bstring *)&be_const_str_call_native, + (const bstring *)&be_const_str_allocated, + NULL, + (const bstring *)&be_const_str_hue_ntv, + (const bstring *)&be_const_str_get_bri, + (const bstring *)&be_const_str__end_transmission, + (const bstring *)&be_const_str_Partition_otadata, + (const bstring *)&be_const_str_pc, + (const bstring *)&be_const_str_connect, + NULL, + (const bstring *)&be_const_str_tob64, + NULL, + (const bstring *)&be_const_str_argument_X20must_X20be_X20a_X20list_X20or_X20a_X20pointer_X2Bsize, + (const bstring *)&be_const_str__X2F, + (const bstring *)&be_const_str_debug, + (const bstring *)&be_const_str_escape, + (const bstring *)&be_const_str__X2Elen, + (const bstring *)&be_const_str_energy_struct, + NULL, + (const bstring *)&be_const_str__timers, + (const bstring *)&be_const_str_Trigger, + (const bstring *)&be_const_str_send, + (const bstring *)&be_const_str_shared_key, + (const bstring *)&be_const_str_get_style_pad_right, + (const bstring *)&be_const_str_CFG_X3A_X20removing_X20first_X20time_X20marker, + (const bstring *)&be_const_str__X2Ebec, + (const bstring *)&be_const_str_OPTION_A, + (const bstring *)&be_const_str_class_init_obj, + (const bstring *)&be_const_str_on, + (const bstring *)&be_const_str__X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E, + (const bstring *)&be_const_str_byte, + (const bstring *)&be_const_str_zero, + (const bstring *)&be_const_str_adv_block, + (const bstring *)&be_const_str_model, + (const bstring *)&be_const_str_update, + (const bstring *)&be_const_str_input, + (const bstring *)&be_const_str_has_arg, + (const bstring *)&be_const_str_closure, + (const bstring *)&be_const_str_obj_event_base, + (const bstring *)&be_const_str_app, + (const bstring *)&be_const_str_setitem, + (const bstring *)&be_const_str_data, + (const bstring *)&be_const_str_I2C_Driver, + NULL, + (const bstring *)&be_const_str_draw_line_dsc_init, + (const bstring *)&be_const_str_RELAY, + (const bstring *)&be_const_str__archive, + (const bstring *)&be_const_str_ins_ramp, + (const bstring *)&be_const_str_assign_rmt, + NULL, + (const bstring *)&be_const_str__X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E, + (const bstring *)&be_const_str_webclient, + (const bstring *)&be_const_str__X2D_X2A, + (const bstring *)&be_const_str_search, + (const bstring *)&be_const_str__X26lt_X3BError_X3A_X20apply_X20new_X20or_X20remove_X26gt_X3B, + (const bstring *)&be_const_str_scan, + (const bstring *)&be_const_str___upper__, + (const bstring *)&be_const_str__X2C, + (const bstring *)&be_const_str__X23autoexec_X2Ebe, + (const bstring *)&be_const_str_PART_MAIN, + (const bstring *)&be_const_str_Unknown_X20command, + (const bstring *)&be_const_str_WS2812_GRB, + (const bstring *)&be_const_str_arg, + (const bstring *)&be_const_str_true, + (const bstring *)&be_const_str_bytes, + NULL, + (const bstring *)&be_const_str_return, + (const bstring *)&be_const_str_getbits, + (const bstring *)&be_const_str_widget_dtor_impl, + (const bstring *)&be_const_str__X2E_X2E, + (const bstring *)&be_const_str_, + (const bstring *)&be_const_str_EVENT_DRAW_MAIN, + (const bstring *)&be_const_str_set_light, + (const bstring *)&be_const_str_CFG_X3A_X20return_code_X3D_X25i, NULL, NULL, + (const bstring *)&be_const_str__X5D, + (const bstring *)&be_const_str_started, NULL, - (const bstring *)&be_const_str_font_seg7, - (const bstring *)&be_const_str_CFG_X3A_X20downloading_X20_X27_X25s_X27, - (const bstring *)&be_const_str_resp_cmnd_failed, - (const bstring *)&be_const_str_CFG_X3A_X20loaded_X20_X27_X25s_X27, - (const bstring *)&be_const_str_count, NULL, - (const bstring *)&be_const_str_button_pressed, - (const bstring *)&be_const_str__p, - (const bstring *)&be_const_str__X2Eautoconf, - (const bstring *)&be_const_str_ccronexpr, - (const bstring *)&be_const_str_lv, - (const bstring *)&be_const_str_get_battery_chargin_status, - (const bstring *)&be_const_str_remove_trailing_zeroes, - (const bstring *)&be_const_str_AudioFileSourceFS, + (const bstring *)&be_const_str_set_ota_max, + (const bstring *)&be_const_str_dirty, (const bstring *)&be_const_str_RES_OK, - (const bstring *)&be_const_str_Restart_X201, + (const bstring *)&be_const_str_get_vbus_current, + (const bstring *)&be_const_str__cmd, + NULL, + (const bstring *)&be_const_str_full_status, + (const bstring *)&be_const_str_detect, + (const bstring *)&be_const_str_lv_solidified, + (const bstring *)&be_const_str_EVENT_DRAW_PART_END, + (const bstring *)&be_const_str_invalidate, + (const bstring *)&be_const_str_readline, + NULL, + (const bstring *)&be_const_str_gamma10, + (const bstring *)&be_const_str_arg_name, NULL, - (const bstring *)&be_const_str_signal_arcs, - (const bstring *)&be_const_str_WS2812, - (const bstring *)&be_const_str_BRY_X3A_X20ERROR_X2C_X20bad_X20json_X3A_X20, - (const bstring *)&be_const_str_get_bat_charge_current, - (const bstring *)&be_const_str__X3Cinstance_X3A_X20Partition_info_X28_X25d_X25s_X2C_X25d_X25s_X2C0x_X2508X_X2C0x_X2508X_X2C_X27_X25s_X27_X2C0x_X25X_X29_X3E, (const bstring *)&be_const_str_MD5, - (const bstring *)&be_const_str_CFG_X3A_X20removed_X20file_X20_X27_X25s_X27, - (const bstring *)&be_const_str_gamma, + (const bstring *)&be_const_str__X3E_X3D, + (const bstring *)&be_const_str_traceback, NULL, - (const bstring *)&be_const_str_Animate_X20pc_X20is_X20out_X20of_X20range, - (const bstring *)&be_const_str_add_cron, - (const bstring *)&be_const_str_select, + (const bstring *)&be_const_str_encrypt, + (const bstring *)&be_const_str__X2D, + (const bstring *)&be_const_str_CFG_X3A_X20loaded_X20_X20, + (const bstring *)&be_const_str_f, + (const bstring *)&be_const_str_Too_X20many_X20partiition_X20slots, + (const bstring *)&be_const_str_CFG_X3A_X20ran_X20_X20, + (const bstring *)&be_const_str_BRY_X3A_X20could_X20not_X20save_X20compiled_X20file_X20_X25s_X20_X28_X25s_X29, + (const bstring *)&be_const_str_CFG_X3A_X20loading_X20_X27_X25s_X27, + NULL, + (const bstring *)&be_const_str_lights, + (const bstring *)&be_const_str__X3C_X3D, + (const bstring *)&be_const_str__X3A, + NULL, + (const bstring *)&be_const_str_set_style_radius, + (const bstring *)&be_const_str_assert, + (const bstring *)&be_const_str_set_mode_ct, + (const bstring *)&be_const_str_remove_timer, + (const bstring *)&be_const_str__X2Ep, + (const bstring *)&be_const_str_get_bat_charge_current, + NULL, + (const bstring *)&be_const_str_0x_X2502X, + (const bstring *)&be_const_str__request_from, + (const bstring *)&be_const_str__X2Etapp, + (const bstring *)&be_const_str_add_handler, + (const bstring *)&be_const_str_content_send, + (const bstring *)&be_const_str_BRY_X3A_X20ERROR_X2C_X20bad_X20json_X3A_X20, + (const bstring *)&be_const_str_draw_line_dsc, + (const bstring *)&be_const_str_exec_cmd, + (const bstring *)&be_const_str_cb_do_nothing, + (const bstring *)&be_const_str__X2508x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2508x, + (const bstring *)&be_const_str_content_button, + (const bstring *)&be_const_str__X23init_X2Ebat, + (const bstring *)&be_const_str_height_def, + (const bstring *)&be_const_str_crc32, + (const bstring *)&be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, + (const bstring *)&be_const_str_pc_abs, + (const bstring *)&be_const_str_remove_cmd, + (const bstring *)&be_const_str_font_montserrat, NULL, (const bstring *)&be_const_str_Partition, - (const bstring *)&be_const_str_RGBCT, - (const bstring *)&be_const_str__X3Cinstance_X3A_X20Partition_otadata_X28ota_active_X3A_X25s_X2C_X20ota_seq_X3D_X5B_X25d_X2C_X25d_X5D_X2C_X20ota_max_X3D_X25d_X29_X3E, - (const bstring *)&be_const_str_widget_struct_default, - NULL, - (const bstring *)&be_const_str_nan, - NULL, - (const bstring *)&be_const_str_cb_do_nothing, - (const bstring *)&be_const_str_strip, - (const bstring *)&be_const_str__X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, - (const bstring *)&be_const_str_CFG_X3A_X20return_code_X3D_X25i, - (const bstring *)&be_const_str_BRY_X3A_X20failed_X20to_X20load_X20compiled_X20_X27_X25s_X27_X20_X28_X25s_X29, - (const bstring *)&be_const_str_cmd_res, + (const bstring *)&be_const_str_adv_cb, + (const bstring *)&be_const_str_set_mode_rgb, (const bstring *)&be_const_str_AXP192, - (const bstring *)&be_const_str__archive, - (const bstring *)&be_const_str_leds, - (const bstring *)&be_const_str_bus, - (const bstring *)&be_const_str_CFG_X3A_X20loading_X20_X27_X25s_X27, - (const bstring *)&be_const_str__X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E, - NULL, - (const bstring *)&be_const_str_Invalid_X20ota_X20partition_X20number, - (const bstring *)&be_const_str_CFG_X3A_X20multiple_X20autoconf_X20files_X20found_X2C_X20aborting_X20_X28_X27_X25s_X27_X20_X2B_X20_X27_X25s_X27_X29, - (const bstring *)&be_const_str_enabled, - (const bstring *)&be_const_str__change_buffer, - (const bstring *)&be_const_str_esphttpd, - (const bstring *)&be_const_str_make_cb, - (const bstring *)&be_const_str__X0A, - (const bstring *)&be_const_str_SK6812_GRBW, - (const bstring *)&be_const_str_argument_X20must_X20be_X20a_X20list_X20or_X20a_X20pointer_X2Bsize, - (const bstring *)&be_const_str_set_style_img_recolor, - (const bstring *)&be_const_str__rmt, - (const bstring *)&be_const_str_RGBW, - (const bstring *)&be_const_str_fat, - (const bstring *)&be_const_str_CFG_X3A_X20exception_X20_X27_X25s_X27_X20_X2D_X20_X27_X25s_X27, - (const bstring *)&be_const_str_arg_X20must_X20be_X20a_X20subclass_X20of_X20lv_obj, - (const bstring *)&be_const_str_nvskeys, - (const bstring *)&be_const_str_FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, - (const bstring *)&be_const_str_remote_port, - (const bstring *)&be_const_str_AudioFileSource, - (const bstring *)&be_const_str_EXTERNAL_I2S, - (const bstring *)&be_const_str_last_modified, - (const bstring *)&be_const_str__X21_X3D, - (const bstring *)&be_const_str_set_ct, - (const bstring *)&be_const_str_draw_line_dsc, - (const bstring *)&be_const_str_BRY_X3A_X20corrupt_X20bytecode_X20_X27_X25s_X27, - (const bstring *)&be_const_str__rules, - NULL, - (const bstring *)&be_const_str_can_show, - (const bstring *)&be_const_str_remove_driver, - (const bstring *)&be_const_str_clear, - (const bstring *)&be_const_str_public_key, - NULL, - (const bstring *)&be_const_str_dac_voltage, - (const bstring *)&be_const_str_animators, - NULL, - (const bstring *)&be_const_str_COLOR_BLACK, - (const bstring *)&be_const_str__timers, - (const bstring *)&be_const_str_sinh, - (const bstring *)&be_const_str_false, - NULL, - (const bstring *)&be_const_str_SERIAL_5O2, - (const bstring *)&be_const_str_CFG_X3A_X20No_X20_X27_X2A_X2Eautoconf_X27_X20file_X20found, - (const bstring *)&be_const_str_get_percentage, - NULL, - (const bstring *)&be_const_str_SERIAL_8N2, - (const bstring *)&be_const_str__X3Clegend_X3E_X3Cb_X20title_X3D_X27Autoconfiguration_X27_X3E_X26nbsp_X3BCurrent_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, - (const bstring *)&be_const_str_partition_core, - (const bstring *)&be_const_str__X27_X20_X2D_X20, - (const bstring *)&be_const_str_energy_struct, - (const bstring *)&be_const_str_add_handler, - (const bstring *)&be_const_str__energy, - (const bstring *)&be_const_str_assert, - (const bstring *)&be_const_str_SERIAL_5O1, - NULL, - (const bstring *)&be_const_str_argument_X20must_X20be_X20a_X20function, - (const bstring *)&be_const_str_Trigger, - (const bstring *)&be_const_str__X2508x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2508x, - (const bstring *)&be_const_str_classof, - (const bstring *)&be_const_str___iterator__, - (const bstring *)&be_const_str_cos, - (const bstring *)&be_const_str_arg_name, - (const bstring *)&be_const_str_, - (const bstring *)&be_const_str_ctypes_bytes_dyn, - (const bstring *)&be_const_str_coord_arr, - (const bstring *)&be_const_str__X21_X3D_X3D, - (const bstring *)&be_const_str_signal_bars, - (const bstring *)&be_const_str_map, - (const bstring *)&be_const_str_SERIAL_7N2, - (const bstring *)&be_const_str_asstring, - NULL, - (const bstring *)&be_const_str_get, - (const bstring *)&be_const_str__X3Cselect_X20name_X3D_X27zip_X27_X3E, - (const bstring *)&be_const_str_mqtt, - (const bstring *)&be_const_str_invalid_X20GPIO_X20number, - (const bstring *)&be_const_str__X25, - (const bstring *)&be_const_str_read32, - (const bstring *)&be_const_str__X23preinit_X2Ebe, - (const bstring *)&be_const_str__X3D_X3C_X3E_X21, - (const bstring *)&be_const_str_dump, - (const bstring *)&be_const_str_digital_write, - (const bstring *)&be_const_str_SERIAL_5N1, - (const bstring *)&be_const_str_is_spiffs, - (const bstring *)&be_const_str_hue_status, - (const bstring *)&be_const_str_create_matrix, - (const bstring *)&be_const_str_BRY_X3A_X20failed_X20to_X20load_X20_X27_X25s_X27_X20_X28_X25s_X20_X2D_X20_X25s_X29, - (const bstring *)&be_const_str_set_auth, - (const bstring *)&be_const_str__global_def, - (const bstring *)&be_const_str__X2F_X3Frst_X3D, - (const bstring *)&be_const_str_I2C_Driver, - (const bstring *)&be_const_str_delay, - (const bstring *)&be_const_str__class, - (const bstring *)&be_const_str_point, - (const bstring *)&be_const_str_SERIAL_5N2, - (const bstring *)&be_const_str_STATE_DEFAULT, - (const bstring *)&be_const_str__X20, - (const bstring *)&be_const_str_log10, - (const bstring *)&be_const_str__dirty, - (const bstring *)&be_const_str_cb_obj, - (const bstring *)&be_const_str__X23, - (const bstring *)&be_const_str_add_cmd, - (const bstring *)&be_const_str_content_response, - (const bstring *)&be_const_str_content_stop, + (const bstring *)&be_const_str_HTTP_GET, + (const bstring *)&be_const_str_size, (const bstring *)&be_const_str__X22, + (const bstring *)&be_const_str__X2Ebe, + (const bstring *)&be_const_str_close, + NULL, + (const bstring *)&be_const_str_every_100ms, + (const bstring *)&be_const_str_dac_voltage, + (const bstring *)&be_const_str__X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, + (const bstring *)&be_const_str_OneWire, + (const bstring *)&be_const_str_day, + NULL, + NULL, + (const bstring *)&be_const_str__X3Clegend_X3E_X3Cb_X20title_X3D_X27New_X20autoconf_X27_X3E_X26nbsp_X3BSelect_X20new_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, + (const bstring *)&be_const_str_CFG_X3A_X20skipping_X20_X27display_X2Eini_X27_X20because_X20already_X20present_X20in_X20file_X2Dsystem, + (const bstring *)&be_const_str_atan, + (const bstring *)&be_const_str_SERIAL_7O2, + (const bstring *)&be_const_str_True, + (const bstring *)&be_const_str__X26lt_X3BNone_X26gt_X3B, + (const bstring *)&be_const_str_gc, + NULL, + (const bstring *)&be_const_str_hue_status, + (const bstring *)&be_const_str_BRY_X3A_X20failed_X20to_X20run_X20compiled_X20code_X20_X27_X25s_X27_X20_X2D_X20_X25s, + NULL, + (const bstring *)&be_const_str_RGBW, + (const bstring *)&be_const_str_isnan, + NULL, + NULL, + (const bstring *)&be_const_str__X28_X29, + (const bstring *)&be_const_str_manuf, + (const bstring *)&be_const_str_crc32_ota_seq, + (const bstring *)&be_const_str_abs, + (const bstring *)&be_const_str_SERIAL_8N2, + NULL, + (const bstring *)&be_const_str_remote_port, + NULL, + (const bstring *)&be_const_str__X0A, + NULL, + (const bstring *)&be_const_str_cmd, + (const bstring *)&be_const_str__X23display_X2Eini, + (const bstring *)&be_const_str__anonymous_, + (const bstring *)&be_const_str_begin, + (const bstring *)&be_const_str__X25s_X2Eautoconf, + (const bstring *)&be_const_str__X3Cinstance_X3A_X20Partition_info_X28_X25d_X25s_X2C_X25d_X25s_X2C0x_X2508X_X2C0x_X2508X_X2C_X27_X25s_X27_X2C0x_X25X_X29_X3E, + (const bstring *)&be_const_str_init_draw_arc_dsc, + (const bstring *)&be_const_str_SERIAL_7E1, + (const bstring *)&be_const_str__X23, + (const bstring *)&be_const_str__X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29, (const bstring *)&be_const_str_gpio, - (const bstring *)&be_const_str_write_file, - (const bstring *)&be_const_str__X22_X3A, - (const bstring *)&be_const_str__X2D, - (const bstring *)&be_const_str_compress, - (const bstring *)&be_const_str_remove_rule, + (const bstring *)&be_const_str__X3Clegend_X3E_X3Cb_X20title_X3D_X27Autoconfiguration_X27_X3E_X26nbsp_X3BCurrent_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, + (const bstring *)&be_const_str_lv_module_init, + (const bstring *)&be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dzip_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, + NULL, + (const bstring *)&be_const_str_full_state, + (const bstring *)&be_const_str__rules, + (const bstring *)&be_const_str_SERIAL_8E2, + (const bstring *)&be_const_str_get_option, + (const bstring *)&be_const_str_font_embedded, + (const bstring *)&be_const_str__X7D, + (const bstring *)&be_const_str_BRY_X3A_X20invalid_X20hue_X20payload_X3A_X20, + (const bstring *)&be_const_str_SERIAL_7O1, + NULL, + (const bstring *)&be_const_str_set_style_img_recolor, + (const bstring *)&be_const_str__X2504d_X2D_X2502d_X2D_X2502dT_X2502d_X3A_X2502d_X3A_X2502d, + (const bstring *)&be_const_str_dimmer, + (const bstring *)&be_const_str_Invalid_X20ota_X20partition_X20number, + NULL, + (const bstring *)&be_const_str_info, + (const bstring *)&be_const_str_adv_watch, + (const bstring *)&be_const_str_get_free_heap, + (const bstring *)&be_const_str_AudioOutputI2S, + (const bstring *)&be_const_str_coord_arr, + (const bstring *)&be_const_str_set_percentage, + (const bstring *)&be_const_str_BLE, + (const bstring *)&be_const_str_couldn_X27t_X20not_X20initialize_X20noepixelbus, + (const bstring *)&be_const_str_CFG_X3A_X20removing_X20autoconf_X20files, + (const bstring *)&be_const_str__X3C_X2Fform_X3E_X3C_X2Fp_X3E, + (const bstring *)&be_const_str_del, + (const bstring *)&be_const_str_widget_event_impl, + (const bstring *)&be_const_str_COLOR_BLACK, + (const bstring *)&be_const_str_try_remove_file, + (const bstring *)&be_const_str_DIMMER, + (const bstring *)&be_const_str__X21_X3D_X3D, + (const bstring *)&be_const_str_ALIGN_LEFT_MID, + (const bstring *)&be_const_str_lv_clock, (const bstring *)&be_const_str__X2Esize, - (const bstring *)&be_const_str__X2C, - (const bstring *)&be_const_str_Partition_otadata, - (const bstring *)&be_const_str_tasmota, - (const bstring *)&be_const_str_TASMOTA, - (const bstring *)&be_const_str__X2F, - (const bstring *)&be_const_str_lower, - (const bstring *)&be_const_str_settings, + (const bstring *)&be_const_str_hue, + (const bstring *)&be_const_str_detected_X20on_X20bus, + (const bstring *)&be_const_str__def, + (const bstring *)&be_const_str_BRY_X3A_X20failed_X20to_X20load_X20_persist_X2Ejson, + (const bstring *)&be_const_str__X20, NULL, - (const bstring *)&be_const_str__X2E, + (const bstring *)&be_const_str_WS2812, + NULL, + NULL, + (const bstring *)&be_const_str_issubclass, + (const bstring *)&be_const_str__X2502d_X25s_X2502d, + NULL, + (const bstring *)&be_const_str_acos, + (const bstring *)&be_const_str_rand, + (const bstring *)&be_const_str__X3D_X3C_X3E_X21, + NULL, + (const bstring *)&be_const_str__X2F_X3Frst_X3D, + (const bstring *)&be_const_str_get_bat_current, + (const bstring *)&be_const_str__drivers, + (const bstring *)&be_const_str_BRY_X3A_X20method_X20not_X20allowed_X2C_X20use_X20a_X20closure_X20like_X20_X27_X2F_X20args_X20_X2D_X3E_X20obj_X2Efunc_X28args_X29_X27, + (const bstring *)&be_const_str_rule, + NULL, + (const bstring *)&be_const_str_CFG_X3A_X20loading_X20, + (const bstring *)&be_const_str_No_X20SPIFFS_X20partition_X20found, + (const bstring *)&be_const_str__global_def, + (const bstring *)&be_const_str_CFG_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s, + (const bstring *)&be_const_str_get_log, + (const bstring *)&be_const_str_subscribe, + (const bstring *)&be_const_str_AudioFileSource, + (const bstring *)&be_const_str__X2Eautoconf, + NULL, + NULL, + (const bstring *)&be_const_str_SERIAL_6E1, + (const bstring *)&be_const_str_CFG_X3A_X20downloading_X20_X27_X25s_X27, + (const bstring *)&be_const_str_set_align, + (const bstring *)&be_const_str_map, + (const bstring *)&be_const_str_BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s, + (const bstring *)&be_const_str_set_x, + (const bstring *)&be_const_str__X23preinit_X2Ebe, + (const bstring *)&be_const_str_add_cb_event_closure, + (const bstring *)&be_const_str_fast_loop_enabled, + (const bstring *)&be_const_str_ctypes_bytes, + (const bstring *)&be_const_str_load, + NULL, + (const bstring *)&be_const_str_refr_now, + (const bstring *)&be_const_str__X2Fac, + NULL, + (const bstring *)&be_const_str_collect, + (const bstring *)&be_const_str_add_driver, + (const bstring *)&be_const_str_add_light, + (const bstring *)&be_const_str_hour, + (const bstring *)&be_const_str_BECDFE, + (const bstring *)&be_const_str__X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, + (const bstring *)&be_const_str_get_ota_slot, + (const bstring *)&be_const_str_get_style_bg_color, + (const bstring *)&be_const_str_conn_cb, + (const bstring *)&be_const_str__X3Clabel_X3EChoose_X20a_X20device_X20configuration_X3A_X3C_X2Flabel_X3E_X3Cbr_X3E, + (const bstring *)&be_const_str_EVENT_DELETE, + (const bstring *)&be_const_str__X3E, (const bstring *)&be_const_str_SERIAL_6N2, - (const bstring *)&be_const_str__debug_present, + (const bstring *)&be_const_str_SK6812_GRBW, + (const bstring *)&be_const_str_get_width, + (const bstring *)&be_const_str_y1, + (const bstring *)&be_const_str_CFG_X3A_X20loaded_X20_X27_X25s_X27, + (const bstring *)&be_const_str_attrdump, + (const bstring *)&be_const_str_consume_mono, + (const bstring *)&be_const_str_check_privileged_access, + (const bstring *)&be_const_str__X2Ep1, + (const bstring *)&be_const_str__X20_X28, + (const bstring *)&be_const_str_tohex, + (const bstring *)&be_const_str_bri, NULL, + (const bstring *)&be_const_str__begin_transmission, + (const bstring *)&be_const_str_MAX_RMT, + (const bstring *)&be_const_str_is_dirty, + (const bstring *)&be_const_str__X2A, + (const bstring *)&be_const_str_SERIAL_6E2, + (const bstring *)&be_const_str_get_object_from_ptr, + (const bstring *)&be_const_str_BUTTON_CONFIGURATION, + (const bstring *)&be_const_str_draw_arc_dsc_init, + (const bstring *)&be_const_str_SERIAL_5O1, + (const bstring *)&be_const_str_ctor, + (const bstring *)&be_const_str_cmd_res, + (const bstring *)&be_const_str_available, + NULL, + (const bstring *)&be_const_str_SERIAL_5N2, + (const bstring *)&be_const_str__write, + (const bstring *)&be_const_str__settings_ptr, + (const bstring *)&be_const_str_AudioOpusDecoder, + (const bstring *)&be_const_str_tasmota_log_reader, + (const bstring *)&be_const_str_remote_ip, + (const bstring *)&be_const_str_SERIAL_7E2, + (const bstring *)&be_const_str_button_pressed, + (const bstring *)&be_const_str_AA50, + (const bstring *)&be_const_str__X5B, + (const bstring *)&be_const_str__X2F_X2Eautoconf, + (const bstring *)&be_const_str_int64, + (const bstring *)&be_const_str_run_bat, + (const bstring *)&be_const_str_get_factory_slot, + (const bstring *)&be_const_str_AudioGenerator, + (const bstring *)&be_const_str__X2Fstate_X2F, + (const bstring *)&be_const_str_SERIAL_8E1, + (const bstring *)&be_const_str__X3F, + (const bstring *)&be_const_str_fromhex, + (const bstring *)&be_const_str_can_show, + (const bstring *)&be_const_str_display, + (const bstring *)&be_const_str_clock_icon, + NULL, + (const bstring *)&be_const_str_CFG_X3A_X20No_X20_X27_X2A_X2Eautoconf_X27_X20file_X20found, + (const bstring *)&be_const_str_CFG_X3A_X20running_X20, + (const bstring *)&be_const_str_animators, + (const bstring *)&be_const_str__X2Ep2, + (const bstring *)&be_const_str_type_to_string, + NULL, + (const bstring *)&be_const_str_lv_wifi_bars, + (const bstring *)&be_const_str_millis, + (const bstring *)&be_const_str_pixels_buffer, + NULL, + (const bstring *)&be_const_str_connected, + (const bstring *)&be_const_str__X2B, + (const bstring *)&be_const_str_get_battery_chargin_status, + (const bstring *)&be_const_str_clear_to, + (const bstring *)&be_const_str_lv_wifi_bars_icon, + (const bstring *)&be_const_str_00, + (const bstring *)&be_const_str_file_X20extension_X20is_X20not_X20_X27_X2Ebe_X27_X20or_X20_X27_X2Ebec_X27, + (const bstring *)&be_const_str_try_get_bec_version, + (const bstring *)&be_const_str_Wire, + NULL, + NULL, + (const bstring *)&be_const_str_CFG_X3A_X20multiple_X20autoconf_X20files_X20found_X2C_X20aborting_X20_X28_X27_X25s_X27_X20_X2B_X20_X27_X25s_X27_X29, + (const bstring *)&be_const_str__X3D_X3D, + (const bstring *)&be_const_str_get_string, + (const bstring *)&be_const_str__error, + (const bstring *)&be_const_str_AudioFileSourceFS, + (const bstring *)&be_const_str_content_send_style, + (const bstring *)&be_const_str_target_search, + (const bstring *)&be_const_str_decrypt, + (const bstring *)&be_const_str_wifi_arcs_icon, + NULL, + (const bstring *)&be_const_str_end, + (const bstring *)&be_const_str__X3Coption_X20value_X3D_X27reset_X27_X3E_X26lt_X3BRemove_X20autoconf_X26gt_X3B_X3C_X2Foption_X3E, + (const bstring *)&be_const_str_CFG_X3A_X20removed_X20file_X20_X27_X25s_X27, + NULL, + (const bstring *)&be_const_str_EBEBFFFFFFFFFFFFFFFFFFFFFFFFFFFF, + (const bstring *)&be_const_str_is_first_time, + (const bstring *)&be_const_str_length_X20in_X20bits_X20must_X20be_X20between_X200_X20and_X2032, + (const bstring *)&be_const_str__X3C, + (const bstring *)&be_const_str_EXTERNAL_I2S, + (const bstring *)&be_const_str_set_bits_per_sample, + (const bstring *)&be_const_str_deregister_obj, + NULL, + (const bstring *)&be_const_str_offseta, + (const bstring *)&be_const_str_GET, + (const bstring *)&be_const_str_TAP_X3A_X20Loaded_X20Tasmota_X20App_X20_X27_X25s_X27, + (const bstring *)&be_const_str__filename, + (const bstring *)&be_const_str__set_bytes, + (const bstring *)&be_const_str_loop, + NULL, + (const bstring *)&be_const_str__validate, + (const bstring *)&be_const_str_reset, + (const bstring *)&be_const_str__X22_X3A, + (const bstring *)&be_const_str_RGB, + (const bstring *)&be_const_str__X3Cinstance_X3A_X20Partition_X28_X5B_X0A, + NULL, + (const bstring *)&be_const_str_range, + (const bstring *)&be_const_str_tele, + (const bstring *)&be_const_str___lower__, + (const bstring *)&be_const_str_gen_cb, + (const bstring *)&be_const_str_dump, + (const bstring *)&be_const_str_content_stop, + (const bstring *)&be_const_str_FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, + (const bstring *)&be_const_str_every_second, + NULL, + NULL, + (const bstring *)&be_const_str_screenshot, + (const bstring *)&be_const_str__X3Cp_X3ECurrent_X20configuration_X3A_X20_X3C_X2Fp_X3E_X3Cp_X3E_X3Cb_X3E_X25s_X3C_X2Fb_X3E_X3C_X2Fp_X3E, + (const bstring *)&be_const_str_Tele, + (const bstring *)&be_const_str__X3Cselect_X20name_X3D_X27zip_X27_X3E, + (const bstring *)&be_const_str_eth, + (const bstring *)&be_const_str__X2Ew, + (const bstring *)&be_const_str_fromb64, + (const bstring *)&be_const_str__persist_X2Ejson, + NULL, + (const bstring *)&be_const_str_cb_event_closure, + (const bstring *)&be_const_str__buffer, + (const bstring *)&be_const_str_io_error, + (const bstring *)&be_const_str_toptr, + (const bstring *)&be_const_str_bool, + (const bstring *)&be_const_str_connection_error, + (const bstring *)&be_const_str_SERIAL_6O1, + (const bstring *)&be_const_str__X3D, + (const bstring *)&be_const_str_CFG_X3A_X20exception_X20_X27_X25s_X27_X20_X2D_X20_X27_X25s_X27, + (const bstring *)&be_const_str_codedump, + (const bstring *)&be_const_str_AES_GCM, + (const bstring *)&be_const_str_read12, + (const bstring *)&be_const_str__X5D_X2C_X0A_X20_X20, + (const bstring *)&be_const_str_AudioOutput, + (const bstring *)&be_const_str_BRY_X3A_X20argument_X20must_X20be_X20a_X20function, + (const bstring *)&be_const_str__read, + (const bstring *)&be_const_str_Tasmota, + (const bstring *)&be_const_str_add, + (const bstring *)&be_const_str_instance_X20required, + (const bstring *)&be_const_str_get_input_power_status, + (const bstring *)&be_const_str__X2Flights_X2F, + (const bstring *)&be_const_str_BRY_X3A_X20bytecode_X20has_X20wrong_X20version_X20_X27_X25s_X27_X20_X28_X25i_X29, + (const bstring *)&be_const_str_lv_obj_class, + (const bstring *)&be_const_str_begin_multicast, (const bstring *)&be_const_str__X29, (const bstring *)&be_const_str_classname, - (const bstring *)&be_const_str_hour, - NULL, - (const bstring *)&be_const_str_False, - (const bstring *)&be_const_str_EVENT_DRAW_PART_END, - (const bstring *)&be_const_str_get_log, - (const bstring *)&be_const_str_Unknown, - (const bstring *)&be_const_str__X2B, - (const bstring *)&be_const_str_SERIAL_6N1, - (const bstring *)&be_const_str_OneWire, - (const bstring *)&be_const_str__validate, - (const bstring *)&be_const_str__X2A, - (const bstring *)&be_const_str_every_second, - (const bstring *)&be_const_str__available, - (const bstring *)&be_const_str_BRY_X3A_X20invalid_X20hue_X20payload_X3A_X20, - (const bstring *)&be_const_str_run_bat, + (const bstring *)&be_const_str_SERIAL_8O1, + (const bstring *)&be_const_str__X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, + (const bstring *)&be_const_str_print, + (const bstring *)&be_const_str_SERIAL_5O2, + (const bstring *)&be_const_str_local, + (const bstring *)&be_const_str_img, + (const bstring *)&be_const_str_Restart_X201, + (const bstring *)&be_const_str_run_cron, + (const bstring *)&be_const_str_SERIAL_5N1, + (const bstring *)&be_const_str_group_def, + (const bstring *)&be_const_str__X21_X3D, + (const bstring *)&be_const_str_compress, + (const bstring *)&be_const_str_INTERNAL_PDM, + (const bstring *)&be_const_str_EC_C25519, + (const bstring *)&be_const_str_page_autoconf_ctl, + (const bstring *)&be_const_str__X23autoexec_X2Ebat, + (const bstring *)&be_const_str_calldepth, + (const bstring *)&be_const_str_crc16, + (const bstring *)&be_const_str__X20_X20, NULL, NULL, - (const bstring *)&be_const_str_page_autoconf_mgr, - (const bstring *)&be_const_str__X2502d_X25s_X2502d, - (const bstring *)&be_const_str_deregister_obj, - (const bstring *)&be_const_str_file_X20extension_X20is_X20not_X20_X27_X2Ebe_X27_X20or_X20_X27_X2Ebec_X27, + (const bstring *)&be_const_str_contains, + (const bstring *)&be_const_str_files, + (const bstring *)&be_const_str__X27_X20_X2D_X20, + (const bstring *)&be_const_str_floor, + (const bstring *)&be_const_str__X3Cinstance_X3A_X20Partition_otadata_X28ota_active_X3A_X25s_X2C_X20ota_seq_X3D_X5B_X25d_X2C_X25d_X5D_X2C_X20ota_max_X3D_X25d_X29_X3E, + (const bstring *)&be_const_str__X3Clambda_X3E, + (const bstring *)&be_const_str_SERIAL_7N1, + (const bstring *)&be_const_str_compile, + (const bstring *)&be_const_str_draw_line, NULL, - (const bstring *)&be_const_str__anonymous_, - (const bstring *)&be_const_str_BRY_X3A_X20failed_X20to_X20run_X20compiled_X20code_X20_X27_X25s_X27_X20_X2D_X20_X25s, - (const bstring *)&be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3EAuto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, - (const bstring *)&be_const_str_fromb64, - (const bstring *)&be_const_str_get_bri, - (const bstring *)&be_const_str__X28_X29, - (const bstring *)&be_const_str_concat, - (const bstring *)&be_const_str_digital_read, - (const bstring *)&be_const_str_read, - (const bstring *)&be_const_str_conn_cb, - (const bstring *)&be_const_str_active_otadata, - (const bstring *)&be_const_str__X5D, - (const bstring *)&be_const_str_line_dsc, - NULL, - NULL, - NULL, - (const bstring *)&be_const_str_get_name, - (const bstring *)&be_const_str_has_arg, - (const bstring *)&be_const_str_LVG_X3A_X20call_X20to_X20unsupported_X20callback, - (const bstring *)&be_const_str__, - (const bstring *)&be_const_str_year, - (const bstring *)&be_const_str_exec_rules, - (const bstring *)&be_const_str_read_bytes, - (const bstring *)&be_const_str_atan, - (const bstring *)&be_const_str__X3D, - (const bstring *)&be_const_str__X2504d_X2D_X2502d_X2D_X2502dT_X2502d_X3A_X2502d_X3A_X2502d, - (const bstring *)&be_const_str__X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E, - (const bstring *)&be_const_str_CFG_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s, - (const bstring *)&be_const_str__X3C, - (const bstring *)&be_const_str_pin, - (const bstring *)&be_const_str_set_style_line_color, - (const bstring *)&be_const_str_Partition_info, - (const bstring *)&be_const_str__X26lt_X3BNone_X26gt_X3B, - (const bstring *)&be_const_str_adv_cb, - (const bstring *)&be_const_str_exp, - (const bstring *)&be_const_str_Too_X20many_X20partiition_X20slots, - (const bstring *)&be_const_str__X3E, - (const bstring *)&be_const_str_escape, - (const bstring *)&be_const_str_resize, - (const bstring *)&be_const_str_init_draw_line_dsc, - (const bstring *)&be_const_str__X2D_X2D_X3A_X2D_X2D, - (const bstring *)&be_const_str_push, - (const bstring *)&be_const_str__X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, - (const bstring *)&be_const_str_SERIAL_7E2, - (const bstring *)&be_const_str_pin_mode, - (const bstring *)&be_const_str__def, - (const bstring *)&be_const_str__fl, - (const bstring *)&be_const_str___upper__, - (const bstring *)&be_const_str__X3Clabel_X3EChoose_X20a_X20device_X20configuration_X3A_X3C_X2Flabel_X3E_X3Cbr_X3E + (const bstring *)&be_const_str_arch, + (const bstring *)&be_const_str_CFG_X3A_X20could_X20not_X20run_X20_X25s_X20_X28_X25s_X20_X2D_X20_X25s_X29, + (const bstring *)&be_const_str_is_factory, + (const bstring *)&be_const_str_onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20change_X20the_X20current_X20configuration_X20and_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E, + (const bstring *)&be_const_str__X2D_X2D_X3A_X2D_X2D }; static const struct bconststrtab m_const_string_table = { - .size = 505, - .count = 1033, + .size = 511, + .count = 1045, .table = m_string_table }; diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_bytes.h b/lib/libesp32/berry/generate/be_fixed_be_class_bytes.h index aec4366d4..75c6ae47c 100644 --- a/lib/libesp32/berry/generate/be_fixed_be_class_bytes.h +++ b/lib/libesp32/berry/generate/be_fixed_be_class_bytes.h @@ -1,42 +1,44 @@ #include "be_constobj.h" static be_define_const_map_slots(be_class_bytes_map) { - { be_const_key(deinit, -1), be_const_func(m_deinit) }, - { be_const_key(get, 5), be_const_func(m_getu) }, - { be_const_key(fromb64, 18), be_const_func(m_fromb64) }, - { be_const_key(copy, -1), be_const_func(m_copy) }, - { be_const_key(_buffer, -1), be_const_func(m_buffer) }, - { be_const_key(getfloat, -1), be_const_func(m_getfloat) }, - { be_const_key(getbits, -1), be_const_closure(getbits_closure) }, - { be_const_key(tob64, -1), be_const_func(m_tob64) }, - { be_const_key(item, -1), be_const_func(m_item) }, - { be_const_key(_X21_X3D, -1), be_const_func(m_nequal) }, - { be_const_key(clear, 28), be_const_func(m_clear) }, - { be_const_key(size, 4), be_const_func(m_size) }, - { be_const_key(fromstring, -1), be_const_func(m_fromstring) }, - { be_const_key(_X2Elen, 21), be_const_var(0) }, - { be_const_key(seti, -1), be_const_func(m_set) }, - { be_const_key(_X2B, 9), be_const_func(m_merge) }, - { be_const_key(_X2Esize, 13), be_const_var(1) }, - { be_const_key(setfloat, 6), be_const_func(m_setfloat) }, - { be_const_key(_X2Ep, -1), be_const_var(2) }, { be_const_key(set, -1), be_const_func(m_set) }, - { be_const_key(asstring, 0), be_const_func(m_asstring) }, - { be_const_key(add, 24), be_const_func(m_add) }, - { be_const_key(setitem, -1), be_const_func(m_setitem) }, - { be_const_key(_change_buffer, -1), be_const_func(m_change_buffer) }, - { be_const_key(_X3D_X3D, 15), be_const_func(m_equal) }, - { be_const_key(resize, 2), be_const_func(m_resize) }, - { be_const_key(tostring, -1), be_const_func(m_tostring) }, - { be_const_key(setbits, -1), be_const_closure(setbits_closure) }, + { be_const_key(_X2Elen, 0), be_const_var(0) }, + { be_const_key(tob64, 4), be_const_func(m_tob64) }, { be_const_key(_X2E_X2E, -1), be_const_func(m_connect) }, + { be_const_key(setfloat, -1), be_const_func(m_setfloat) }, + { be_const_key(get, 2), be_const_func(m_getu) }, + { be_const_key(asstring, -1), be_const_func(m_asstring) }, + { be_const_key(getfloat, 24), be_const_func(m_getfloat) }, + { be_const_key(_buffer, -1), be_const_func(m_buffer) }, { be_const_key(init, -1), be_const_func(m_init) }, + { be_const_key(_X2Esize, 23), be_const_var(1) }, + { be_const_key(tohex, 16), be_const_func(m_tohex) }, + { be_const_key(fromhex, -1), be_const_func(m_fromhex) }, + { be_const_key(setbits, 7), be_const_closure(setbits_closure) }, + { be_const_key(copy, 31), be_const_func(m_copy) }, + { be_const_key(size, 17), be_const_func(m_size) }, + { be_const_key(getbits, -1), be_const_closure(getbits_closure) }, + { be_const_key(fromb64, -1), be_const_func(m_fromb64) }, + { be_const_key(_change_buffer, -1), be_const_func(m_change_buffer) }, + { be_const_key(_X21_X3D, 30), be_const_func(m_nequal) }, + { be_const_key(clear, -1), be_const_func(m_clear) }, + { be_const_key(seti, 18), be_const_func(m_set) }, + { be_const_key(_X2B, -1), be_const_func(m_merge) }, + { be_const_key(add, 26), be_const_func(m_add) }, + { be_const_key(deinit, -1), be_const_func(m_deinit) }, + { be_const_key(tostring, -1), be_const_func(m_tostring) }, + { be_const_key(item, -1), be_const_func(m_item) }, { be_const_key(geti, -1), be_const_func(m_geti) }, + { be_const_key(resize, -1), be_const_func(m_resize) }, + { be_const_key(setitem, -1), be_const_func(m_setitem) }, + { be_const_key(_X2Ep, -1), be_const_var(2) }, + { be_const_key(fromstring, -1), be_const_func(m_fromstring) }, + { be_const_key(_X3D_X3D, -1), be_const_func(m_equal) }, }; static be_define_const_map( be_class_bytes_map, - 31 + 33 ); BE_EXPORT_VARIABLE be_define_const_class( diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_zb_coord_ntv.h b/lib/libesp32/berry/generate/be_fixed_be_class_zb_coord_ntv.h new file mode 100644 index 000000000..bbf05448d --- /dev/null +++ b/lib/libesp32/berry/generate/be_fixed_be_class_zb_coord_ntv.h @@ -0,0 +1,23 @@ +#include "be_constobj.h" + +static be_define_const_map_slots(be_class_zb_coord_ntv_map) { + { be_const_key(iter, -1), be_const_func(zc_iter) }, + { be_const_key(zcl_frame, -1), be_const_class(be_class_zcl_frame) }, + { be_const_key(zb_device, 3), be_const_class(be_class_zb_device) }, + { be_const_key(info, -1), be_const_func(zc_info) }, + { be_const_key(size, 1), be_const_ctype_func(zc_size) }, + { be_const_key(item, -1), be_const_func(zc_item) }, + { be_const_key(abort, 4), be_const_ctype_func(zc_abort) }, +}; + +static be_define_const_map( + be_class_zb_coord_ntv_map, + 7 +); + +BE_EXPORT_VARIABLE be_define_const_class( + be_class_zb_coord_ntv, + 0, + NULL, + zb_coord_ntv +); diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_zb_device.h b/lib/libesp32/berry/generate/be_fixed_be_class_zb_device.h new file mode 100644 index 000000000..4e486f6fa --- /dev/null +++ b/lib/libesp32/berry/generate/be_fixed_be_class_zb_device.h @@ -0,0 +1,20 @@ +#include "be_constobj.h" + +static be_define_const_map_slots(be_class_zb_device_map) { + { be_const_key(init, -1), be_const_ctype_func(zd_init) }, + { be_const_key(tostring, -1), be_const_closure(zb_device_tostring_closure) }, + { be_const_key(_p, -1), be_const_var(0) }, + { be_const_key(member, 0), be_const_func(zd_member) }, +}; + +static be_define_const_map( + be_class_zb_device_map, + 4 +); + +BE_EXPORT_VARIABLE be_define_const_class( + be_class_zb_device, + 1, + NULL, + zb_device +); diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_zcl_frame_ntv.h b/lib/libesp32/berry/generate/be_fixed_be_class_zcl_frame_ntv.h new file mode 100644 index 000000000..83cd61a45 --- /dev/null +++ b/lib/libesp32/berry/generate/be_fixed_be_class_zcl_frame_ntv.h @@ -0,0 +1,19 @@ +#include "be_constobj.h" + +static be_define_const_map_slots(be_class_zcl_frame_ntv_map) { + { be_const_key(_set_bytes, -1), be_const_ctype_func(zfn_set_bytes) }, + { be_const_key(_def, 2), be_const_comptr(&be_zigbee_zcl_frame_struct) }, + { be_const_key(_get_bytes, -1), be_const_ctype_func(zfn_get_bytes) }, +}; + +static be_define_const_map( + be_class_zcl_frame_ntv_map, + 3 +); + +BE_EXPORT_VARIABLE be_define_const_class( + be_class_zcl_frame_ntv, + 0, + (bclass *)&be_class_ctypes_bytes, + zcl_frame_ntv +); diff --git a/lib/libesp32/berry/generate/be_fixed_crc.h b/lib/libesp32/berry/generate/be_fixed_crc.h index 7c78f4490..468346ba7 100644 --- a/lib/libesp32/berry/generate/be_fixed_crc.h +++ b/lib/libesp32/berry/generate/be_fixed_crc.h @@ -2,13 +2,14 @@ static be_define_const_map_slots(m_libcrc_map) { { be_const_key(crc32, 1), be_const_ctype_func(c_crc32) }, - { be_const_key(crc8, 2), be_const_ctype_func(c_crc8) }, + { be_const_key(sum, -1), be_const_ctype_func(c_sum) }, { be_const_key(crc16, -1), be_const_ctype_func(c_crc16) }, + { be_const_key(crc8, -1), be_const_ctype_func(c_crc8) }, }; static be_define_const_map( m_libcrc_map, - 3 + 4 ); static be_define_const_module( diff --git a/lib/libesp32/berry/generate/be_fixed_zigbee.h b/lib/libesp32/berry/generate/be_fixed_zigbee.h new file mode 100644 index 000000000..ed5c510ae --- /dev/null +++ b/lib/libesp32/berry/generate/be_fixed_zigbee.h @@ -0,0 +1,17 @@ +#include "be_constobj.h" + +static be_define_const_map_slots(m_libzigbee_map) { + { be_const_key(init, -1), be_const_func(zigbee_init) }, +}; + +static be_define_const_map( + m_libzigbee_map, + 1 +); + +static be_define_const_module( + m_libzigbee, + "zigbee" +); + +BE_EXPORT_VARIABLE be_define_const_native_module(zigbee); diff --git a/lib/libesp32/berry/src/be_byteslib.c b/lib/libesp32/berry/src/be_byteslib.c index aab229839..44b25e2de 100644 --- a/lib/libesp32/berry/src/be_byteslib.c +++ b/lib/libesp32/berry/src/be_byteslib.c @@ -715,6 +715,24 @@ static int m_tostring(bvm *vm) be_return(vm); } +static int m_tohex(bvm *vm) +{ + buf_impl attr = m_read_attributes(vm, 1); + if (attr.bufptr) { /* pointer looks valid */ + int32_t len = attr.len; + size_t hex_len = len * 2 + 1; + + char * hex_out = be_pushbuffer(vm, hex_len); + size_t l = tohex(hex_out, hex_len, attr.bufptr, len); + + be_pushnstring(vm, hex_out, l); /* make escape string from buffer */ + be_remove(vm, -2); /* remove buffer */ + } else { /* pointer is null, don't try to dereference it as it would crash */ + be_pushstring(vm, ""); + } + be_return(vm); +} + /* * Copy the buffer into a string without any changes */ @@ -1184,6 +1202,45 @@ static int m_fromb64(bvm *vm) be_return_nil(vm); } +/* + * Converts hex to bytes() + * + * `bytes().fromhexx() -> bytes()` + */ +static int m_fromhex(bvm *vm) +{ + int argc = be_top(vm); + if (argc >= 2 && be_isstring(vm, 2)) { + int32_t from = 0; // skip x chars + if (argc >= 3 && be_isint(vm, 3)) { + from = be_toint(vm, 3); + } + const char *s = be_tostring(vm, 2); + size_t s_len = strlen(s); + if (from < 0) { from = 0; } + if (from > s_len) { from = s_len; } + int32_t bin_len = (s_len - from) / 2; + + buf_impl attr = m_read_attributes(vm, 1); + check_ptr(vm, &attr); + if (attr.fixed && attr.len != bin_len) { + be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); + } + bytes_resize(vm, &attr, bin_len); /* resize if needed */ + if (bin_len > attr.size) { /* avoid overflow */ + be_raise(vm, "memory_error", "cannot allocate buffer"); + } + attr.len = 0; + buf_add_hex(&attr, s + from, s_len - from); + + be_pop(vm, 1); /* remove arg to leave instance */ + m_write_attributes(vm, 1, &attr); /* update instance */ + be_pop(vm, be_top(vm) - 1); /* leave instance on stack */ + be_return(vm); + } + be_raise(vm, "type_error", "operand must be a string"); + be_return_nil(vm); +} /* * Advanced API @@ -1497,6 +1554,8 @@ void be_load_byteslib(bvm *vm) { "fromstring", m_fromstring }, { "tob64", m_tob64 }, { "fromb64", m_fromb64 }, + { "fromhex", m_fromhex }, + { "tohex", m_tohex }, { "add", m_add }, { "get", m_getu }, { "geti", m_geti }, @@ -1538,6 +1597,8 @@ class be_class_bytes (scope: global, name: bytes) { fromstring, func(m_fromstring) tob64, func(m_tob64) fromb64, func(m_fromb64) + fromhex, func(m_fromhex) + tohex, func(m_tohex) add, func(m_add) get, func(m_getu) geti, func(m_geti) diff --git a/lib/libesp32/berry/src/be_lexer.c b/lib/libesp32/berry/src/be_lexer.c index 1803300fe..cd5a0bc2f 100644 --- a/lib/libesp32/berry/src/be_lexer.c +++ b/lib/libesp32/berry/src/be_lexer.c @@ -168,21 +168,9 @@ static int check_next(blexer *lexer, int c) return 0; } -static int char2hex(int c) -{ - if (c >= '0' && c <= '9') { - return c - '0'; - } else if (c >= 'a' && c <= 'f') { - return c - 'a' + 0x0A; - } else if (c >= 'A' && c <= 'F') { - return c - 'A' + 0x0A; - } - return -1; -} - static int check2hex(blexer *lexer, int c) { - c = char2hex(c); + c = be_char2hex(c); if (c < 0) { be_lexerror(lexer, "invalid hexadecimal number"); } @@ -333,7 +321,7 @@ static bint scan_hexadecimal(blexer *lexer) { bint res = 0; int dig, num = 0; - while ((dig = char2hex(lgetc(lexer))) >= 0) { + while ((dig = be_char2hex(lgetc(lexer))) >= 0) { res = ((bint)res << 4) + dig; next(lexer); ++num; diff --git a/lib/libesp32/berry/src/be_strlib.c b/lib/libesp32/berry/src/be_strlib.c index 1196a5aad..44389f3a8 100644 --- a/lib/libesp32/berry/src/be_strlib.c +++ b/lib/libesp32/berry/src/be_strlib.c @@ -231,29 +231,54 @@ const char* be_pushvfstr(bvm *vm, const char *format, va_list arg) return concat2(vm); } +int be_char2hex(int c) +{ + if (c >= '0' && c <= '9') { + return c - '0'; + } else if (c >= 'a' && c <= 'f') { + return c - 'a' + 0x0A; + } else if (c >= 'A' && c <= 'F') { + return c - 'A' + 0x0A; + } + return -1; +} + /******************************************************************* * the function be_str2int(): - * >>-+------------+--+-----+----digits---->< - * '-whitespace-' +- + -+ - * '- - -' + * >>-+------------+--+--+-----+----digits-------+---------------->< + * '-whitespace-' | +- + -+ | + * | '- - -' | + * | | + * +- 0x or 0X ---hex_digits--+ + * *******************************************************************/ BERRY_API bint be_str2int(const char *str, const char **endstr) { int c, sign; bint sum = 0; skip_space(str); - sign = c = *str++; - if (c == '+' || c == '-') { - c = *str++; + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { + /* hex literal */ + str += 2; /* skip 0x or 0X */ + while ((c = be_char2hex(*str++)) >= 0) { + sum = sum * 16 + c; + } + return sum; + } else { + /* decimal literal */ + sign = c = *str++; + if (c == '+' || c == '-') { + c = *str++; + } + while (is_digit(c)) { + sum = sum * 10 + c - '0'; + c = *str++; + } + if (endstr) { + *endstr = str - 1; + } + return sign == '-' ? -sum : sum; } - while (is_digit(c)) { - sum = sum * 10 + c - '0'; - c = *str++; - } - if (endstr) { - *endstr = str - 1; - } - return sign == '-' ? -sum : sum; } /******************************************************************* diff --git a/lib/libesp32/berry/src/be_strlib.h b/lib/libesp32/berry/src/be_strlib.h index 992257648..703fce054 100644 --- a/lib/libesp32/berry/src/be_strlib.h +++ b/lib/libesp32/berry/src/be_strlib.h @@ -19,6 +19,7 @@ bstring* be_strcat(bvm *vm, bstring *s1, bstring *s2); int be_strcmp(bstring *s1, bstring *s2); bstring* be_num2str(bvm *vm, bvalue *v); void be_val2str(bvm *vm, int index); +int be_char2hex(int c); size_t be_strlcpy(char *dst, const char *src, size_t size); const char* be_splitpath(const char *path); const char* be_splitname(const char *path); diff --git a/lib/libesp32/berry/tests/int.be b/lib/libesp32/berry/tests/int.be index d5a7c79e9..21cfcf720 100644 --- a/lib/libesp32/berry/tests/int.be +++ b/lib/libesp32/berry/tests/int.be @@ -6,3 +6,9 @@ class Test_int end t=Test_int() assert(int(t) == 42) + +#- int can parse hex strings -# +assert(int("0x00") == 0) +assert(int("0X1") == 1) +assert(int("0x000000F") == 15) +assert(int("0x1000") == 0x1000) diff --git a/lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/package.json b/lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/package.json index 8faf7e245..1f206315b 100755 --- a/lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/package.json +++ b/lib/libesp32/berry/tools/plugins/vscode/skiars.berry-0.1.0/package.json @@ -3,7 +3,6 @@ "displayName": "Berry Script Language", "description": "A small embedded script language.", "version": "0.1.0", - "icon": "berry-icon.png", "publisher": "skiars", "engines": { "vscode": "^1.15.1" diff --git a/lib/libesp32/berry_mapping/src/be_cb_module.c b/lib/libesp32/berry_mapping/src/be_cb_module.c index 6b147da21..8488424ae 100644 --- a/lib/libesp32/berry_mapping/src/be_cb_module.c +++ b/lib/libesp32/berry_mapping/src/be_cb_module.c @@ -153,7 +153,6 @@ static int32_t be_cb_make_cb(bvm *vm) { int32_t argc = be_top(vm); if (argc >= 1 && be_isfunction(vm, 1)) { - bvalue *v = be_indexof(vm, 1); for (be_callback_handler_list_t *elt = be_callback_handler_list_head; elt != NULL; elt = elt->next) { if (elt->vm == vm || elt->vm == NULL) { // if elt->vm is NULL then we accept any VM // call the handler and check result @@ -215,7 +214,6 @@ static int32_t be_cb_gen_cb(bvm *vm) { \*********************************************************************************************/ static int32_t be_cb_get_cb_list(bvm *vm) { be_newobject(vm, "list"); - int32_t i; for (uint32_t i=0; i < BE_MAX_CB; i++) { if (be_cb_hooks[i].vm) { if (vm == be_cb_hooks[i].vm) { // make sure it corresponds to this vm diff --git a/lib/libesp32/berry_mapping/src/be_const_members.c b/lib/libesp32/berry_mapping/src/be_const_members.c index 66174ebca..810de4574 100644 --- a/lib/libesp32/berry_mapping/src/be_const_members.c +++ b/lib/libesp32/berry_mapping/src/be_const_members.c @@ -76,6 +76,7 @@ static bbool be_const_member_dual(bvm *vm, const be_const_member_t * definitions case '>': // call to a ctype function { be_ctype_var_args_t* args = (be_ctype_var_args_t*) definitions[idx].value; + be_pop(vm, be_top(vm) - 1); // make sure we have only the instance left on the stack int ret = be_call_c_func(vm, args->func, args->return_type, NULL); if ((ret == BE_OK) && !be_isnil(vm, -1)) { return btrue; diff --git a/lib/libesp32/berry_tasmota/src/be_crc32_module.c b/lib/libesp32/berry_tasmota/src/be_crc32_module.c index 6a5962ee6..ec9f436b1 100644 --- a/lib/libesp32/berry_tasmota/src/be_crc32_module.c +++ b/lib/libesp32/berry_tasmota/src/be_crc32_module.c @@ -10,21 +10,30 @@ #include "rom/crc.h" -uint32_t c_crc32(uint32_t crc, const uint8_t* buf, size_t size) { +static uint32_t c_crc32(uint32_t crc, const uint8_t* buf, size_t size) { return crc32_le(crc, buf, size); } BE_FUNC_CTYPE_DECLARE(c_crc32, "i", "i(bytes)~") -uint32_t c_crc16(uint32_t crc, const uint8_t* buf, size_t size) { +static uint32_t c_crc16(uint32_t crc, const uint8_t* buf, size_t size) { return crc16_le(crc, buf, size); } BE_FUNC_CTYPE_DECLARE(c_crc16, "i", "i(bytes)~") -uint32_t c_crc8(uint32_t crc, const uint8_t* buf, size_t size) { +static uint32_t c_crc8(uint32_t crc, const uint8_t* buf, size_t size) { return crc8_le(crc, buf, size); } BE_FUNC_CTYPE_DECLARE(c_crc8, "i", "i(bytes)~") +static uint32_t c_sum(const uint8_t* buf, size_t size) { + uint32_t sum = 0; + for (uint32_t i = 0; i < size; i++) { + sum = (sum + buf[i]) & 0xFF; + } + return sum; +} +BE_FUNC_CTYPE_DECLARE(c_sum, "i", "(bytes)~") + // const uint32_t crc32_tab[] = { // 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, // 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, @@ -83,6 +92,7 @@ module crc (scope: global) { crc32, ctype_func(c_crc32) crc16, ctype_func(c_crc16) crc8, ctype_func(c_crc8) + sum, ctype_func(c_sum) } @const_object_info_end */ #include "be_fixed_crc.h" diff --git a/lib/libesp32/berry_tasmota/src/be_ctypes.c b/lib/libesp32/berry_tasmota/src/be_ctypes.c index 7970356d8..7ebe74310 100644 --- a/lib/libesp32/berry_tasmota/src/be_ctypes.c +++ b/lib/libesp32/berry_tasmota/src/be_ctypes.c @@ -144,8 +144,6 @@ int be_ctypes_init(bvm *vm) { // copy ctypes_bytes, with same class and same content // int be_ctypes_copy(bvm *vm) { - size_t len; - const void * src = be_tobytes(vm, 1, &len); be_classof(vm, 1); // stack: 1/self + class_object be_call(vm, 0); // call empty constructor to build empty resizable copy @@ -184,7 +182,6 @@ int be_ctypes_copy(bvm *vm) { // arg2: name of the argument // The class has a `_def` static class attribute with the C low-level mapping definition int be_ctypes_member(bvm *vm) { - int argc = be_top(vm); be_getmember(vm, 1, "_def"); const be_ctypes_structure_t *definitions; definitions = (const be_ctypes_structure_t *) be_tocomptr(vm, -1); @@ -276,8 +273,6 @@ int be_ctypes_member(bvm *vm) { // 2: name of member // 3: value int be_ctypes_setmember(bvm *vm) { - int argc = be_top(vm); - // If the value is an instance, we call 'toint()' and replace the value if (be_isinstance(vm, 3)) { diff --git a/lib/libesp32/berry_tasmota/src/be_lv_openhasp.c b/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c similarity index 99% rename from lib/libesp32/berry_tasmota/src/be_lv_openhasp.c rename to lib/libesp32/berry_tasmota/src/be_lv_haspmota.c index 1f82d2643..2bb290dca 100644 --- a/lib/libesp32/berry_tasmota/src/be_lv_openhasp.c +++ b/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c @@ -1,10 +1,10 @@ /******************************************************************** - * Tasmota OpenHASP solidified + * Tasmota HASPmota solidified *******************************************************************/ #include "be_constobj.h" #ifdef USE_LVGL -#ifdef USE_LVGL_OPENHASP +#ifdef USE_LVGL_HASPMOTA extern const bclass be_class_lv_anim; extern const bclass be_class_lv_arc; @@ -5847,39 +5847,10 @@ void be_load_lvh_qrcode_class(bvm *vm) { be_pop(vm, 1); } -/******************************************************************** -** Solidified function: _anonymous_ -********************************************************************/ -be_local_closure(openhasp__anonymous_, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_literal("OpenHASP"), - }), - be_str_literal("_anonymous_"), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x5C080200, // 0001 MOVE R2 R1 - 0x7C080000, // 0002 CALL R2 0 - 0x80040400, // 0003 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: do_action ********************************************************************/ -be_local_closure(OpenHASP_do_action, /* name */ +be_local_closure(HASPmota_do_action, /* name */ be_nested_proto( 10, /* nstack */ 3, /* argc */ @@ -5991,7 +5962,7 @@ be_local_closure(OpenHASP_do_action, /* name */ /******************************************************************** ** Solidified function: pages_list_sorted ********************************************************************/ -be_local_closure(OpenHASP_pages_list_sorted, /* name */ +be_local_closure(HASPmota_pages_list_sorted, /* name */ be_nested_proto( 8, /* nstack */ 2, /* argc */ @@ -6071,7 +6042,7 @@ be_local_closure(OpenHASP_pages_list_sorted, /* name */ /******************************************************************** ** Solidified function: get_page_cur ********************************************************************/ -be_local_closure(OpenHASP_get_page_cur, /* name */ +be_local_closure(HASPmota_get_page_cur, /* name */ be_nested_proto( 3, /* nstack */ 1, /* argc */ @@ -6101,7 +6072,7 @@ be_local_closure(OpenHASP_get_page_cur, /* name */ /******************************************************************** ** Solidified function: start ********************************************************************/ -be_local_closure(OpenHASP_start, /* name */ +be_local_closure(HASPmota_start, /* name */ be_nested_proto( 11, /* nstack */ 3, /* argc */ @@ -6131,7 +6102,7 @@ be_local_closure(OpenHASP_start, /* name */ /* K16 */ be_nested_str_literal("font_embedded"), /* K17 */ be_nested_str_literal("robotocondensed"), /* K18 */ be_nested_str_literal("montserrat"), - /* K19 */ be_nested_str_literal("theme_openhasp_init"), + /* K19 */ be_nested_str_literal("theme_haspmota_init"), /* K20 */ be_const_int(0), /* K21 */ be_nested_str_literal("color"), /* K22 */ be_const_int(16711935), @@ -6263,7 +6234,7 @@ be_local_closure(OpenHASP_start, /* name */ /******************************************************************** ** Solidified function: init ********************************************************************/ -be_local_closure(OpenHASP_init, /* name */ +be_local_closure(HASPmota_init, /* name */ be_nested_proto( 5, /* nstack */ 1, /* argc */ @@ -6297,7 +6268,7 @@ be_local_closure(OpenHASP_init, /* name */ /******************************************************************** ** Solidified function: register_event ********************************************************************/ -be_local_closure(OpenHASP_register_event, /* name */ +be_local_closure(HASPmota_register_event, /* name */ be_nested_proto( 13, /* nstack */ 3, /* argc */ @@ -6373,7 +6344,7 @@ be_local_closure(OpenHASP_register_event, /* name */ /******************************************************************** ** Solidified function: parse_page ********************************************************************/ -be_local_closure(OpenHASP_parse_page, /* name */ +be_local_closure(HASPmota_parse_page, /* name */ be_nested_proto( 9, /* nstack */ 2, /* argc */ @@ -6465,7 +6436,7 @@ be_local_closure(OpenHASP_parse_page, /* name */ /******************************************************************** ** Solidified function: deinit ********************************************************************/ -be_local_closure(OpenHASP_deinit, /* name */ +be_local_closure(HASPmota_deinit, /* name */ be_nested_proto( 5, /* nstack */ 1, /* argc */ @@ -6512,7 +6483,7 @@ be_local_closure(OpenHASP_deinit, /* name */ /******************************************************************** ** Solidified function: page_dir_to ********************************************************************/ -be_local_closure(OpenHASP_page_dir_to, /* name */ +be_local_closure(HASPmota_page_dir_to, /* name */ be_nested_proto( 7, /* nstack */ 2, /* argc */ @@ -6573,7 +6544,7 @@ be_local_closure(OpenHASP_page_dir_to, /* name */ /******************************************************************** ** Solidified function: _load ********************************************************************/ -be_local_closure(OpenHASP__load, /* name */ +be_local_closure(HASPmota__load, /* name */ be_nested_proto( 14, /* nstack */ 2, /* argc */ @@ -6668,7 +6639,7 @@ be_local_closure(OpenHASP__load, /* name */ /******************************************************************** ** Solidified function: parse ********************************************************************/ -be_local_closure(OpenHASP_parse, /* name */ +be_local_closure(HASPmota_parse, /* name */ be_nested_proto( 9, /* nstack */ 2, /* argc */ @@ -6722,7 +6693,7 @@ be_local_closure(OpenHASP_parse, /* name */ /******************************************************************** ** Solidified function: sort ********************************************************************/ -be_local_closure(OpenHASP_sort, /* name */ +be_local_closure(HASPmota_sort, /* name */ be_nested_proto( 6, /* nstack */ 1, /* argc */ @@ -6778,7 +6749,7 @@ be_local_closure(OpenHASP_sort, /* name */ /******************************************************************** ** Solidified function: parse_obj ********************************************************************/ -be_local_closure(OpenHASP_parse_obj, /* name */ +be_local_closure(HASPmota_parse_obj, /* name */ be_nested_proto( 20, /* nstack */ 3, /* argc */ @@ -7022,7 +6993,7 @@ be_local_closure(OpenHASP_parse_obj, /* name */ /******************************************************************** ** Solidified function: event_dispatch ********************************************************************/ -be_local_closure(OpenHASP_event_dispatch, /* name */ +be_local_closure(HASPmota_event_dispatch, /* name */ be_nested_proto( 9, /* nstack */ 2, /* argc */ @@ -7090,27 +7061,27 @@ be_local_closure(OpenHASP_event_dispatch, /* name */ /******************************************************************** -** Solidified class: OpenHASP +** Solidified class: HASPmota ********************************************************************/ -be_local_class(OpenHASP, +be_local_class(HASPmota, 10, NULL, be_nested_map(43, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_literal("lvh_textarea", 41), be_const_class(be_class_lvh_textarea) }, { be_const_key_literal("scr", -1), be_const_var(3) }, - { be_const_key_literal("event_dispatch", 16), be_const_closure(OpenHASP_event_dispatch_closure) }, + { be_const_key_literal("event_dispatch", 16), be_const_closure(HASPmota_event_dispatch_closure) }, { be_const_key_literal("lvh_bar", -1), be_const_class(be_class_lvh_bar) }, { be_const_key_literal("lvh_img", -1), be_const_class(be_class_lvh_img) }, { be_const_key_literal("event", -1), be_const_var(8) }, - { be_const_key_literal("do_action", 33), be_const_closure(OpenHASP_do_action_closure) }, - { be_const_key_literal("pages_list_sorted", -1), be_const_closure(OpenHASP_pages_list_sorted_closure) }, + { be_const_key_literal("do_action", 33), be_const_closure(HASPmota_do_action_closure) }, + { be_const_key_literal("pages_list_sorted", -1), be_const_closure(HASPmota_pages_list_sorted_closure) }, { be_const_key_literal("lvh_btnmatrix", 42), be_const_class(be_class_lvh_btnmatrix) }, - { be_const_key_literal("start", -1), be_const_closure(OpenHASP_start_closure) }, - { be_const_key_literal("init", 5), be_const_closure(OpenHASP_init_closure) }, + { be_const_key_literal("start", -1), be_const_closure(HASPmota_start_closure) }, + { be_const_key_literal("init", 5), be_const_closure(HASPmota_init_closure) }, { be_const_key_literal("lvh_scr", -1), be_const_class(be_class_lvh_scr) }, - { be_const_key_literal("parse_page", -1), be_const_closure(OpenHASP_parse_page_closure) }, - { be_const_key_literal("register_event", 24), be_const_closure(OpenHASP_register_event_closure) }, + { be_const_key_literal("parse_page", -1), be_const_closure(HASPmota_parse_page_closure) }, + { be_const_key_literal("register_event", 24), be_const_closure(HASPmota_register_event_closure) }, { be_const_key_literal("lvh_roller", 34), be_const_class(be_class_lvh_roller) }, { be_const_key_literal("lvh_page", 11), be_const_class(be_class_lvh_page) }, { be_const_key_literal("lvh_page_cur_idx", -1), be_const_var(6) }, @@ -7118,13 +7089,13 @@ be_local_class(OpenHASP, { be_const_key_literal("hres", 38), be_const_var(1) }, { be_const_key_literal("dark", -1), be_const_var(0) }, { be_const_key_literal("lvh_label", 37), be_const_class(be_class_lvh_label) }, - { be_const_key_literal("deinit", 14), be_const_closure(OpenHASP_deinit_closure) }, - { be_const_key_literal("page_dir_to", -1), be_const_closure(OpenHASP_page_dir_to_closure) }, - { be_const_key_literal("parse_obj", -1), be_const_closure(OpenHASP_parse_obj_closure) }, + { be_const_key_literal("deinit", 14), be_const_closure(HASPmota_deinit_closure) }, + { be_const_key_literal("page_dir_to", -1), be_const_closure(HASPmota_page_dir_to_closure) }, + { be_const_key_literal("parse_obj", -1), be_const_closure(HASPmota_parse_obj_closure) }, { be_const_key_literal("lvh_spinner", -1), be_const_class(be_class_lvh_spinner) }, - { be_const_key_literal("_load", -1), be_const_closure(OpenHASP__load_closure) }, + { be_const_key_literal("_load", -1), be_const_closure(HASPmota__load_closure) }, { be_const_key_literal("lvh_qrcode", -1), be_const_class(be_class_lvh_qrcode) }, - { be_const_key_literal("parse", -1), be_const_closure(OpenHASP_parse_closure) }, + { be_const_key_literal("parse", -1), be_const_closure(HASPmota_parse_closure) }, { be_const_key_literal("lvh_pages", 2), be_const_var(5) }, { be_const_key_literal("lvh_line", -1), be_const_class(be_class_lvh_line) }, { be_const_key_literal("lvh_switch", -1), be_const_class(be_class_lvh_switch) }, @@ -7132,32 +7103,61 @@ be_local_class(OpenHASP, { be_const_key_literal("r16", -1), be_const_var(4) }, { be_const_key_literal("def_templ_name", -1), be_nested_str_literal("pages.jsonl") }, { be_const_key_literal("lvh_obj", 19), be_const_class(be_class_lvh_obj) }, - { be_const_key_literal("sort", 23), be_const_static_closure(OpenHASP_sort_closure) }, + { be_const_key_literal("sort", 23), be_const_static_closure(HASPmota_sort_closure) }, { be_const_key_literal("lvh_dropdown", -1), be_const_class(be_class_lvh_dropdown) }, { be_const_key_literal("lvh_checkbox", -1), be_const_class(be_class_lvh_checkbox) }, { be_const_key_literal("lvh_slider", -1), be_const_class(be_class_lvh_slider) }, { be_const_key_literal("vres", -1), be_const_var(2) }, { be_const_key_literal("lvh_btn", -1), be_const_class(be_class_lvh_btn) }, { be_const_key_literal("event_cb", -1), be_const_var(9) }, - { be_const_key_literal("get_page_cur", -1), be_const_closure(OpenHASP_get_page_cur_closure) }, + { be_const_key_literal("get_page_cur", -1), be_const_closure(HASPmota_get_page_cur_closure) }, })), - be_str_literal("OpenHASP") + be_str_literal("HASPmota") ); /******************************************************************** -** Solidified module: openhasp +** Solidified function: _anonymous_ ********************************************************************/ -be_local_module(openhasp, - "openhasp", +be_local_closure(haspmota__anonymous_, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_literal("HASPmota"), + }), + be_str_literal("_anonymous_"), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x5C080200, // 0001 MOVE R2 R1 + 0x7C080000, // 0002 CALL R2 0 + 0x80040400, // 0003 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified module: haspmota +********************************************************************/ +be_local_module(haspmota, + "haspmota", be_nested_map(2, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_literal("OpenHASP", -1), be_const_class(be_class_OpenHASP) }, - { be_const_key_literal("init", 0), be_const_closure(openhasp__anonymous__closure) }, + { be_const_key_literal("HASPmota", -1), be_const_class(be_class_HASPmota) }, + { be_const_key_literal("init", -1), be_const_closure(haspmota__anonymous__closure) }, })) ); -BE_EXPORT_VARIABLE be_define_const_native_module(openhasp); +BE_EXPORT_VARIABLE be_define_const_native_module(haspmota); /********************************************************************/ -#endif // USE_LVGL_OPENHASP +#endif // USE_LVGL_HASPMOTA #endif // USE_LVGL \ No newline at end of file diff --git a/lib/libesp32/berry_tasmota/src/be_partition_core_module.c b/lib/libesp32/berry_tasmota/src/be_partition_core_module.c index 68de711f5..840c6df92 100644 --- a/lib/libesp32/berry_tasmota/src/be_partition_core_module.c +++ b/lib/libesp32/berry_tasmota/src/be_partition_core_module.c @@ -1311,7 +1311,7 @@ be_local_closure(Partition_info_is_factory, /* name */ ********************************************************************/ be_local_closure(Partition_info_type_to_string, /* name */ be_nested_proto( - 2, /* nstack */ + 6, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -1319,16 +1319,19 @@ be_local_closure(Partition_info_type_to_string, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ + ( &(const bvalue[ 8]) { /* constants */ /* K0 */ be_nested_str(type), /* K1 */ be_const_int(0), /* K2 */ be_nested_str(app), /* K3 */ be_const_int(1), /* K4 */ be_nested_str(data), + /* K5 */ be_nested_str(string), + /* K6 */ be_nested_str(format), + /* K7 */ be_nested_str(0x_X2502X), }), &be_const_str_type_to_string, &be_const_str_solidified, - ( &(const binstruction[10]) { /* code */ + ( &(const binstruction[15]) { /* code */ 0x88040100, // 0000 GETMBR R1 R0 K0 0x1C040301, // 0001 EQ R1 R1 K1 0x78060001, // 0002 JMPF R1 #0005 @@ -1338,7 +1341,12 @@ be_local_closure(Partition_info_type_to_string, /* name */ 0x1C040303, // 0006 EQ R1 R1 K3 0x78060000, // 0007 JMPF R1 #0009 0x80060800, // 0008 RET 1 K4 - 0x80000000, // 0009 RET 0 + 0xA4060A00, // 0009 IMPORT R1 K5 + 0x8C080306, // 000A GETMET R2 R1 K6 + 0x58100007, // 000B LDCONST R4 K7 + 0x88140100, // 000C GETMBR R5 R0 K0 + 0x7C080600, // 000D CALL R2 3 + 0x80040400, // 000E RET 1 R2 }) ) ); @@ -1453,7 +1461,7 @@ be_local_closure(Partition_info_init, /* name */ ********************************************************************/ be_local_closure(Partition_info_subtype_to_string, /* name */ be_nested_proto( - 4, /* nstack */ + 6, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -1461,7 +1469,7 @@ be_local_closure(Partition_info_subtype_to_string, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[18]) { /* constants */ + ( &(const bvalue[21]) { /* constants */ /* K0 */ be_nested_str(type), /* K1 */ be_const_int(0), /* K2 */ be_nested_str(subtype), @@ -1480,10 +1488,13 @@ be_local_closure(Partition_info_subtype_to_string, /* name */ /* K15 */ be_nested_str(esphttpd), /* K16 */ be_nested_str(fat), /* K17 */ be_nested_str(spiffs), + /* K18 */ be_nested_str(string), + /* K19 */ be_nested_str(format), + /* K20 */ be_nested_str(0x_X2502X), }), &be_const_str_subtype_to_string, &be_const_str_solidified, - ( &(const binstruction[83]) { /* code */ + ( &(const binstruction[88]) { /* code */ 0x88040100, // 0000 GETMBR R1 R0 K0 0x1C040301, // 0001 EQ R1 R1 K1 0x7806001A, // 0002 JMPF R1 #001E @@ -1566,7 +1577,12 @@ be_local_closure(Partition_info_subtype_to_string, /* name */ 0x1C040202, // 004F EQ R1 R1 R2 0x78060000, // 0050 JMPF R1 #0052 0x80062200, // 0051 RET 1 K17 - 0x80000000, // 0052 RET 0 + 0xA4062400, // 0052 IMPORT R1 K18 + 0x8C080313, // 0053 GETMET R2 R1 K19 + 0x58100014, // 0054 LDCONST R4 K20 + 0x88140102, // 0055 GETMBR R5 R0 K2 + 0x7C080600, // 0056 CALL R2 3 + 0x80040400, // 0057 RET 1 R2 }) ) ); diff --git a/lib/libesp32/berry_tasmota/src/be_path_tasmota_lib.c b/lib/libesp32/berry_tasmota/src/be_path_tasmota_lib.c index 4c60e36d8..cfa7e829b 100644 --- a/lib/libesp32/berry_tasmota/src/be_path_tasmota_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_path_tasmota_lib.c @@ -62,7 +62,6 @@ static int m_path_remove(bvm *vm) extern int be_format_fs(void); static int m_path_format(bvm *vm) { - const char *path = NULL; if (be_top(vm) >= 1 && be_isbool(vm, 1)) { if (be_tobool(vm, 1)) { be_pushbool(vm, be_format_fs()); diff --git a/lib/libesp32/berry_tasmota/src/be_tasmota_log_reader_class.cpp b/lib/libesp32/berry_tasmota/src/be_tasmota_log_reader_class.cpp index 0ab880c9f..7f9ac60d8 100644 --- a/lib/libesp32/berry_tasmota/src/be_tasmota_log_reader_class.cpp +++ b/lib/libesp32/berry_tasmota/src/be_tasmota_log_reader_class.cpp @@ -6,7 +6,7 @@ #include "be_mapping.h" extern uint32_t* tlr_init(void); BE_FUNC_CTYPE_DECLARE(tlr_init, "+_p", "") -extern char* tlr_get_log(uint32_t* idx, int32_t log_level); BE_FUNC_CTYPE_DECLARE(tlr_get_log, "s", ".i") +extern char* tlr_get_log(uint32_t* idx, int32_t log_level); BE_FUNC_CTYPE_DECLARE(tlr_get_log, "$", ".i") #include "be_fixed_be_class_tasmota_log_reader.h" diff --git a/lib/libesp32/berry_tasmota/src/be_udp_lib.cpp b/lib/libesp32/berry_tasmota/src/be_udp_lib.cpp index 042962952..439771fba 100644 --- a/lib/libesp32/berry_tasmota/src/be_udp_lib.cpp +++ b/lib/libesp32/berry_tasmota/src/be_udp_lib.cpp @@ -1,8 +1,8 @@ /******************************************************************** * UDP lib - * + * * To use: `d = udp()` - * + * *******************************************************************/ #include "be_constobj.h" @@ -19,7 +19,7 @@ #include "be_mapping.h" extern "C" { - + // init() WiFiUDP *be_udp_init_ntv(void) { return new WiFiUDP(); @@ -39,7 +39,7 @@ extern "C" { // udp.begin(address:string, port:int) -> nil int32_t be_udp_begin_ntv(WiFiUDP *udp, const char *host, int32_t port) { - IPAddress addr(INADDR_ANY); + IPAddress addr((uint32_t)0); // if no host or host is "" then we defult to INADDR_ANY (0.0.0.0) if(host && (*host != 0) && !WiFiGenericClass::hostByName(host, addr)){ return 0; diff --git a/lib/libesp32/berry_tasmota/src/be_zigbee.c b/lib/libesp32/berry_tasmota/src/be_zigbee.c new file mode 100644 index 000000000..d18711f7c --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/be_zigbee.c @@ -0,0 +1,186 @@ +/******************************************************************** + * Zigbee + * + *******************************************************************/ +#ifdef USE_ZIGBEE + +#include "be_constobj.h" +#include "be_mapping.h" +#include "be_ctypes.h" + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +extern const void * zd_init(void* d); BE_FUNC_CTYPE_DECLARE(zd_init, "+_p", "c") + +extern int32_t zd_shortaddr(void* d); BE_VAR_CTYPE_DECLARE(zd_shortaddr, "i"); +extern const void* zd_longaddr(void* d, size_t *size, void* p2); BE_VAR_CTYPE_DECLARE(zd_longaddr, "&"); +extern const char* zd_manufacturer(void* d); BE_VAR_CTYPE_DECLARE(zd_manufacturer, "s"); +extern const char* zd_model(void* d); BE_VAR_CTYPE_DECLARE(zd_model, "s"); +extern const char* zd_name(void* d); BE_VAR_CTYPE_DECLARE(zd_name, "s"); +extern bbool zd_router(void* d); BE_VAR_CTYPE_DECLARE(zd_router, "b"); +extern bbool zd_hidden(void* d); BE_VAR_CTYPE_DECLARE(zd_hidden, "b"); +extern bbool zd_reachable(void* d); BE_VAR_CTYPE_DECLARE(zd_reachable, "b"); +extern int32_t zd_lastseen(void* d); BE_VAR_CTYPE_DECLARE(zd_lastseen, "i"); +extern int32_t zd_lqi(void* d); BE_VAR_CTYPE_DECLARE(zd_lqi, "i"); +extern int32_t zd_battery(void* d); BE_VAR_CTYPE_DECLARE(zd_battery, "i"); +extern int32_t zd_battery_lastseen(void* d); BE_VAR_CTYPE_DECLARE(zd_battery_lastseen, "i"); + +// moved to constants array +// MUST BE STORED IN SORTED LIST +const be_const_member_t zd_members[] = { + { ">battery", be_ctype(zd_battery) }, + { ">battery_lastseen", be_ctype(zd_battery_lastseen) }, + { ">hidden", be_ctype(zd_hidden) }, + { ">lastseen", be_ctype(zd_lastseen) }, + { ">longaddr", be_ctype(zd_longaddr) }, + { ">lqi", be_ctype(zd_lqi) }, + { ">manufacturer", be_ctype(zd_manufacturer) }, + { ">model", be_ctype(zd_model) }, + { ">name", be_ctype(zd_name) }, + { ">reachable", be_ctype(zd_reachable) }, + { ">router", be_ctype(zd_router) }, + { ">shortaddr", be_ctype(zd_shortaddr) }, +}; + +static int zd_member(bvm *vm) { + if (be_const_class_member(vm, zd_members, ARRAY_SIZE(zd_members))) { + be_return(vm); + } else { + be_return_nil(vm); + } +} + +extern int zc_info(struct bvm *vm); +extern int zc_item(struct bvm *vm); +extern int32_t zc_size(void* d); BE_FUNC_CTYPE_DECLARE(zc_size, "i", "."); +extern int zc_iter(bvm *vm); +extern void zc_abort(void); BE_FUNC_CTYPE_DECLARE(zc_abort, "", "."); + +extern const bclass be_class_ctypes_bytes; +extern const be_ctypes_structure_t be_zigbee_zcl_frame_struct; +extern const bclass be_class_zcl_frame; + +/******************************************************************** +** Solidified function: tostring +********************************************************************/ +be_local_closure(zb_device_tostring, /* name */ + be_nested_proto( + 14, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[11]) { /* constants */ + /* K0 */ be_nested_str_literal("json"), + /* K1 */ be_nested_str_literal("string"), + /* K2 */ be_nested_str_literal("longaddr"), + /* K3 */ be_nested_str_literal("format"), + /* K4 */ be_nested_str_literal(""), + /* K5 */ be_nested_str_literal("shortaddr"), + /* K6 */ be_nested_str_literal("get"), + /* K7 */ be_const_int(0), + /* K8 */ be_nested_str_literal("name"), + /* K9 */ be_nested_str_literal("model"), + /* K10 */ be_nested_str_literal("manufacturer"), + }), + be_str_literal("tostring"), + &be_const_str_solidified, + ( &(const binstruction[22]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0xA40A0200, // 0001 IMPORT R2 K1 + 0x880C0102, // 0002 GETMBR R3 R0 K2 + 0x8C100503, // 0003 GETMET R4 R2 K3 + 0x58180004, // 0004 LDCONST R6 K4 + 0x601C0005, // 0005 GETGBL R7 G5 + 0x5C200000, // 0006 MOVE R8 R0 + 0x7C1C0200, // 0007 CALL R7 1 + 0x88200105, // 0008 GETMBR R8 R0 K5 + 0x8C240706, // 0009 GETMET R9 R3 K6 + 0x542E0003, // 000A LDINT R11 4 + 0x54320003, // 000B LDINT R12 4 + 0x7C240600, // 000C CALL R9 3 + 0x8C280706, // 000D GETMET R10 R3 K6 + 0x58300007, // 000E LDCONST R12 K7 + 0x54360003, // 000F LDINT R13 4 + 0x7C280600, // 0010 CALL R10 3 + 0x882C0108, // 0011 GETMBR R11 R0 K8 + 0x88300109, // 0012 GETMBR R12 R0 K9 + 0x8834010A, // 0013 GETMBR R13 R0 K10 + 0x7C101200, // 0014 CALL R4 9 + 0x80040800, // 0015 RET 1 R4 + }) + ) +); +/*******************************************************************/ + + +// Module Zigbee +extern const bclass be_class_zb_coord; +static int zigbee_init(bvm *vm) { + be_pushntvclass(vm, &be_class_zb_coord); + be_call(vm, 0); + be_return(vm); +} + +/*******************************************************************/ + +extern void* zfn_get_bytes(void* sbuf_ptr, size_t *len_bytes); +BE_FUNC_CTYPE_DECLARE(zfn_get_bytes, "&", "-c"); + +extern void zfn_set_bytes(void* sbuf_ptr, const uint8_t* bytes, size_t len_bytes); +BE_FUNC_CTYPE_DECLARE(zfn_set_bytes, "", "-c(bytes)~"); + +/*******************************************************************/ + +#include "be_fixed_be_class_zb_device.h" +#include "be_fixed_be_class_zb_coord_ntv.h" +#include "be_fixed_be_class_zcl_frame_ntv.h" +#include "be_fixed_zigbee.h" + +/* @const_object_info_begin +class be_class_zb_device (scope: global, name: zb_device) { + _p, var + init, ctype_func(zd_init) + + member, func(zd_member) + + tostring, closure(zb_device_tostring_closure) +} +@const_object_info_end */ + +/* @const_object_info_begin +class be_class_zb_coord_ntv (scope: global, name: zb_coord_ntv) { + zcl_frame, class(be_class_zcl_frame) + zb_device, class(be_class_zb_device) + + info, func(zc_info) + item, func(zc_item) + size, ctype_func(zc_size) + iter, func(zc_iter) + + abort, ctype_func(zc_abort) +} +@const_object_info_end */ + + +/* @const_object_info_begin +class be_class_zcl_frame_ntv (scope: global, name: zcl_frame_ntv, super: be_class_ctypes_bytes) { + _def, comptr(&be_zigbee_zcl_frame_struct) + + _get_bytes, ctype_func(zfn_get_bytes) + _set_bytes, ctype_func(zfn_set_bytes) +} +@const_object_info_end */ + +/* @const_object_info_begin +module zigbee (scope: global) { + init, func(zigbee_init) +} +@const_object_info_end */ + +#endif // USE_LIGHT diff --git a/lib/libesp32/berry_tasmota/src/be_zigbee_zb_coord.c b/lib/libesp32/berry_tasmota/src/be_zigbee_zb_coord.c new file mode 100644 index 000000000..0600c1995 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/be_zigbee_zb_coord.c @@ -0,0 +1,214 @@ +/******************************************************************** + * Zigbee + * + *******************************************************************/ +#ifdef USE_ZIGBEE + +#include "be_constobj.h" + +extern const bclass be_class_zb_coord_ntv; + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(zb_coord_init, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_literal("init"), + }), + be_str_literal("init"), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x60040003, // 0000 GETGBL R1 G3 + 0x5C080000, // 0001 MOVE R2 R0 + 0x7C040200, // 0002 CALL R1 1 + 0x8C040300, // 0003 GETMET R1 R1 K0 + 0x7C040200, // 0004 CALL R1 1 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: add_handler +********************************************************************/ +be_local_closure(zb_coord_add_handler, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_literal("instance"), + /* K1 */ be_nested_str_literal("value_error"), + /* K2 */ be_nested_str_literal("instance required"), + /* K3 */ be_nested_str_literal("_handlers"), + /* K4 */ be_nested_str_literal("push"), + }), + be_str_literal("add_handler"), + &be_const_str_solidified, + ( &(const binstruction[18]) { /* code */ + 0x60080004, // 0000 GETGBL R2 G4 + 0x5C0C0200, // 0001 MOVE R3 R1 + 0x7C080200, // 0002 CALL R2 1 + 0x20080500, // 0003 NE R2 R2 K0 + 0x780A0000, // 0004 JMPF R2 #0006 + 0xB0060302, // 0005 RAISE 1 K1 K2 + 0x88080103, // 0006 GETMBR R2 R0 K3 + 0x780A0004, // 0007 JMPF R2 #000D + 0x88080103, // 0008 GETMBR R2 R0 K3 + 0x8C080504, // 0009 GETMET R2 R2 K4 + 0x5C100200, // 000A MOVE R4 R1 + 0x7C080400, // 000B CALL R2 2 + 0x70020003, // 000C JMP #0011 + 0x60080012, // 000D GETGBL R2 G18 + 0x7C080000, // 000E CALL R2 0 + 0x400C0401, // 000F CONNECT R3 R2 R1 + 0x90020602, // 0010 SETMBR R0 K3 R2 + 0x80000000, // 0011 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: dispatch +********************************************************************/ +be_local_closure(zb_coord_dispatch, /* name */ + be_nested_proto( + 19, /* nstack */ + 5, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[14]) { /* constants */ + /* K0 */ be_nested_str_literal("_handlers"), + /* K1 */ be_nested_str_literal("introspect"), + /* K2 */ be_nested_str_literal("string"), + /* K3 */ be_nested_str_literal("zcl_frame"), + /* K4 */ be_const_int(0), + /* K5 */ be_nested_str_literal("get"), + /* K6 */ be_nested_str_literal("function"), + /* K7 */ be_nested_str_literal("format"), + /* K8 */ be_nested_str_literal("BRY: Exception> '%s' - %s"), + /* K9 */ be_nested_str_literal("tasmota"), + /* K10 */ be_nested_str_literal("_debug_present"), + /* K11 */ be_nested_str_literal("debug"), + /* K12 */ be_nested_str_literal("traceback"), + /* K13 */ be_const_int(1), + }), + be_str_literal("dispatch"), + &be_const_str_solidified, + ( &(const binstruction[61]) { /* code */ + 0x88140100, // 0000 GETMBR R5 R0 K0 + 0x4C180000, // 0001 LDNIL R6 + 0x1C140A06, // 0002 EQ R5 R5 R6 + 0x78160000, // 0003 JMPF R5 #0005 + 0x80000A00, // 0004 RET 0 + 0xA4160200, // 0005 IMPORT R5 K1 + 0xA41A0400, // 0006 IMPORT R6 K2 + 0x5C1C0600, // 0007 MOVE R7 R3 + 0x1C200503, // 0008 EQ R8 R2 K3 + 0x78220003, // 0009 JMPF R8 #000E + 0x8C200103, // 000A GETMET R8 R0 K3 + 0x5C280600, // 000B MOVE R10 R3 + 0x7C200400, // 000C CALL R8 2 + 0x5C1C1000, // 000D MOVE R7 R8 + 0x58200004, // 000E LDCONST R8 K4 + 0x6024000C, // 000F GETGBL R9 G12 + 0x88280100, // 0010 GETMBR R10 R0 K0 + 0x7C240200, // 0011 CALL R9 1 + 0x14241009, // 0012 LT R9 R8 R9 + 0x78260027, // 0013 JMPF R9 #003C + 0x88240100, // 0014 GETMBR R9 R0 K0 + 0x94241208, // 0015 GETIDX R9 R9 R8 + 0x8C280B05, // 0016 GETMET R10 R5 K5 + 0x5C301200, // 0017 MOVE R12 R9 + 0x5C340200, // 0018 MOVE R13 R1 + 0x7C280600, // 0019 CALL R10 3 + 0x602C0004, // 001A GETGBL R11 G4 + 0x5C301400, // 001B MOVE R12 R10 + 0x7C2C0200, // 001C CALL R11 1 + 0x1C2C1706, // 001D EQ R11 R11 K6 + 0x782E001A, // 001E JMPF R11 #003A + 0xA8020008, // 001F EXBLK 0 #0029 + 0x5C2C1400, // 0020 MOVE R11 R10 + 0x5C301200, // 0021 MOVE R12 R9 + 0x5C340200, // 0022 MOVE R13 R1 + 0x5C380400, // 0023 MOVE R14 R2 + 0x5C3C0E00, // 0024 MOVE R15 R7 + 0x5C400800, // 0025 MOVE R16 R4 + 0x7C2C0A00, // 0026 CALL R11 5 + 0xA8040001, // 0027 EXBLK 1 1 + 0x70020010, // 0028 JMP #003A + 0xAC2C0002, // 0029 CATCH R11 0 2 + 0x7002000D, // 002A JMP #0039 + 0x60340001, // 002B GETGBL R13 G1 + 0x8C380D07, // 002C GETMET R14 R6 K7 + 0x58400008, // 002D LDCONST R16 K8 + 0x5C441600, // 002E MOVE R17 R11 + 0x5C481800, // 002F MOVE R18 R12 + 0x7C380800, // 0030 CALL R14 4 + 0x7C340200, // 0031 CALL R13 1 + 0xB8361200, // 0032 GETNGBL R13 K9 + 0x88341B0A, // 0033 GETMBR R13 R13 K10 + 0x78360002, // 0034 JMPF R13 #0038 + 0xA4361600, // 0035 IMPORT R13 K11 + 0x8C381B0C, // 0036 GETMET R14 R13 K12 + 0x7C380200, // 0037 CALL R14 1 + 0x70020000, // 0038 JMP #003A + 0xB0080000, // 0039 RAISE 2 R0 R0 + 0x0020110D, // 003A ADD R8 R8 K13 + 0x7001FFD2, // 003B JMP #000F + 0x80000000, // 003C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: zb_coord +********************************************************************/ +extern const bclass be_class_zb_coord_ntv; +be_local_class(zb_coord, + 1, + &be_class_zb_coord_ntv, + be_nested_map(4, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_literal("dispatch", 1), be_const_closure(zb_coord_dispatch_closure) }, + { be_const_key_literal("add_handler", 2), be_const_closure(zb_coord_add_handler_closure) }, + { be_const_key_literal("_handlers", -1), be_const_var(0) }, + { be_const_key_literal("init", 0), be_const_closure(zb_coord_init_closure) }, + })), + be_str_literal("zb_coord") +); +/*******************************************************************/ + +void be_load_zb_coord_class(bvm *vm) { + be_pushntvclass(vm, &be_class_zb_coord); + be_setglobal(vm, "zb_coord"); + be_pop(vm, 1); +} + + +#endif // USE_LIGHT diff --git a/lib/libesp32/berry_tasmota/src/be_zigbee_zcl_frame.c b/lib/libesp32/berry_tasmota/src/be_zigbee_zcl_frame.c new file mode 100644 index 000000000..7026fb2f5 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/be_zigbee_zcl_frame.c @@ -0,0 +1,239 @@ +/******************************************************************** + * Zigbee + * + *******************************************************************/ +#ifdef USE_ZIGBEE + +#include "be_constobj.h" + +extern const bclass be_class_zcl_frame_ntv; + + +/******************************************************************** +** Solidified function: member +********************************************************************/ +be_local_closure(zcl_frame_member, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_literal("payload"), + /* K1 */ be_nested_str_literal("_get_bytes"), + /* K2 */ be_nested_str_literal("payload_ptr"), + /* K3 */ be_nested_str_literal("member"), + }), + be_str_literal("member"), + &be_const_str_solidified, + ( &(const binstruction[15]) { /* code */ + 0x1C080300, // 0000 EQ R2 R1 K0 + 0x780A0004, // 0001 JMPF R2 #0007 + 0x8C080101, // 0002 GETMET R2 R0 K1 + 0x88100102, // 0003 GETMBR R4 R0 K2 + 0x7C080400, // 0004 CALL R2 2 + 0x80040400, // 0005 RET 1 R2 + 0x70020006, // 0006 JMP #000E + 0x60080003, // 0007 GETGBL R2 G3 + 0x5C0C0000, // 0008 MOVE R3 R0 + 0x7C080200, // 0009 CALL R2 1 + 0x8C080503, // 000A GETMET R2 R2 K3 + 0x5C100200, // 000B MOVE R4 R1 + 0x7C080400, // 000C CALL R2 2 + 0x80040400, // 000D RET 1 R2 + 0x80000000, // 000E RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: setmember +********************************************************************/ +be_local_closure(zcl_frame_setmember, /* name */ + be_nested_proto( + 7, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_literal("payload"), + /* K1 */ be_nested_str_literal("_set_bytes"), + /* K2 */ be_nested_str_literal("payload_ptr"), + /* K3 */ be_nested_str_literal("setmember"), + }), + be_str_literal("setmember"), + &be_const_str_solidified, + ( &(const binstruction[17]) { /* code */ + 0x1C0C0300, // 0000 EQ R3 R1 K0 + 0x780E0005, // 0001 JMPF R3 #0008 + 0x8C0C0101, // 0002 GETMET R3 R0 K1 + 0x88140102, // 0003 GETMBR R5 R0 K2 + 0x5C180400, // 0004 MOVE R6 R2 + 0x7C0C0600, // 0005 CALL R3 3 + 0x80040600, // 0006 RET 1 R3 + 0x70020007, // 0007 JMP #0010 + 0x600C0003, // 0008 GETGBL R3 G3 + 0x5C100000, // 0009 MOVE R4 R0 + 0x7C0C0200, // 000A CALL R3 1 + 0x8C0C0703, // 000B GETMET R3 R3 K3 + 0x5C140200, // 000C MOVE R5 R1 + 0x5C180400, // 000D MOVE R6 R2 + 0x7C0C0600, // 000E CALL R3 3 + 0x80040600, // 000F RET 1 R3 + 0x80000000, // 0010 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(zcl_frame_init, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_literal("init"), + /* K1 */ be_nested_str_literal("no_bytes"), + }), + be_str_literal("init"), + &be_const_str_solidified, + ( &(const binstruction[10]) { /* code */ + 0x60080003, // 0000 GETGBL R2 G3 + 0x5C0C0000, // 0001 MOVE R3 R0 + 0x7C080200, // 0002 CALL R2 1 + 0x8C080500, // 0003 GETMET R2 R2 K0 + 0x5C100200, // 0004 MOVE R4 R1 + 0x7C080400, // 0005 CALL R2 2 + 0x60080015, // 0006 GETGBL R2 G21 + 0x7C080000, // 0007 CALL R2 0 + 0x90020202, // 0008 SETMBR R0 K1 R2 + 0x80000000, // 0009 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: tomap +********************************************************************/ +be_local_closure(zcl_frame_tomap, /* name */ + be_nested_proto( + 7, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str_literal("string"), + /* K1 */ be_nested_str_literal("tomap"), + /* K2 */ be_nested_str_literal("shortaddr_hex"), + /* K3 */ be_nested_str_literal("format"), + /* K4 */ be_nested_str_literal("0x%04X"), + /* K5 */ be_nested_str_literal("shortaddr"), + /* K6 */ be_nested_str_literal("payload"), + }), + be_str_literal("tomap"), + &be_const_str_solidified, + ( &(const binstruction[14]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x60080003, // 0001 GETGBL R2 G3 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C080200, // 0003 CALL R2 1 + 0x8C080501, // 0004 GETMET R2 R2 K1 + 0x7C080200, // 0005 CALL R2 1 + 0x8C0C0303, // 0006 GETMET R3 R1 K3 + 0x58140004, // 0007 LDCONST R5 K4 + 0x88180105, // 0008 GETMBR R6 R0 K5 + 0x7C0C0600, // 0009 CALL R3 3 + 0x980A0403, // 000A SETIDX R2 K2 R3 + 0x880C0106, // 000B GETMBR R3 R0 K6 + 0x980A0C03, // 000C SETIDX R2 K6 R3 + 0x80040400, // 000D RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: tostring +********************************************************************/ +be_local_closure(zcl_frame_tostring, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_literal("tomap"), + }), + be_str_literal("tostring"), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x60080008, // 0002 GETGBL R2 G8 + 0x5C0C0200, // 0003 MOVE R3 R1 + 0x7C080200, // 0004 CALL R2 1 + 0x80040400, // 0005 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: zcl_frame +********************************************************************/ +extern const bclass be_class_zcl_frame_ntv; +be_local_class(zcl_frame, + 1, + &be_class_zcl_frame_ntv, + be_nested_map(6, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_literal("no_bytes", -1), be_const_var(0) }, + { be_const_key_literal("member", 2), be_const_closure(zcl_frame_member_closure) }, + { be_const_key_literal("tostring", 5), be_const_closure(zcl_frame_tostring_closure) }, + { be_const_key_literal("init", -1), be_const_closure(zcl_frame_init_closure) }, + { be_const_key_literal("tomap", -1), be_const_closure(zcl_frame_tomap_closure) }, + { be_const_key_literal("setmember", -1), be_const_closure(zcl_frame_setmember_closure) }, + })), + be_str_literal("zcl_frame") +); +/*******************************************************************/ + +void be_load_zcl_frame_class(bvm *vm) { + be_pushntvclass(vm, &be_class_zcl_frame); + be_setglobal(vm, "zcl_frame"); + be_pop(vm, 1); +} + + +#endif // USE_LIGHT diff --git a/lib/libesp32/berry_tasmota/src/embedded/partition_core.be b/lib/libesp32/berry_tasmota/src/embedded/partition_core.be index f72ace0ad..3c48bb7c2 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/partition_core.be +++ b/lib/libesp32/berry_tasmota/src/embedded/partition_core.be @@ -146,6 +146,8 @@ class Partition_info if self.type == 0 return "app" elif self.type == 1 return "data" end + import string + return string.format("0x%02X", self.type) end def subtype_to_string() @@ -166,6 +168,8 @@ class Partition_info elif self.subtype == 0x82 return "spiffs" end end + import string + return string.format("0x%02X", self.subtype) end # Human readable version of Partition information diff --git a/lib/libesp32/berry_tasmota/src/embedded/zigbee.be b/lib/libesp32/berry_tasmota/src/embedded/zigbee.be new file mode 100644 index 000000000..39d4eb227 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/embedded/zigbee.be @@ -0,0 +1,17 @@ +# zigbee code + +class zb_device + + def tostring() + import json + import string + + var la = self.longaddr # bytes() of size 8, little-endian + return string.format("", + classname(self), self.shortaddr, + la.get(4,4), la.get(0,4), + self.name, self.model, self.manufacturer) + return + end + +end \ No newline at end of file diff --git a/lib/libesp32/berry_tasmota/src/embedded/zigbee_zb_coord.be b/lib/libesp32/berry_tasmota/src/embedded/zigbee_zb_coord.be new file mode 100644 index 000000000..a1aa29fa5 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/embedded/zigbee_zb_coord.be @@ -0,0 +1,59 @@ +# zigbee zcl_frame class +# solidify.dump(zb_coord,true) + +class zb_coord_ntv end # fake class replaced with native one +#zb_coord_ntv = classof(super(zigbee)) + +class zb_coord : zb_coord_ntv + var _handlers + + def init() + super(self).init() + end + + def add_handler(h) + if type(h) != 'instance' + raise "value_error", "instance required" + end + if self._handlers + self._handlers.push(h) + else + self._handlers = [h] + end + end + + def dispatch(event_type, data_type, data_ptr, idx) + if self._handlers == nil return end + + import introspect + import string + + var data = data_ptr + if data_type == "zcl_frame" + data = self.zcl_frame(data_ptr) + end + + #print(string.format(">ZIG: cmd=%s data_type=%s data=%s idx=%i", event_type, data_type, str(data), idx)) + + var i = 0 + while i < size(self._handlers) + var h = self._handlers[i] + var f = introspect.get(h, event_type) # try to match a function or method with the same name + if type(f) == 'function' + try + f(h, event_type, data_type, data, idx) + except .. as e,m + print(string.format("BRY: Exception> '%s' - %s", e, m)) + if tasmota._debug_present + import debug + debug.traceback() + end + end + end + i += 1 + end + + end + +end + diff --git a/lib/libesp32/berry_tasmota/src/embedded/zigbee_zcl_frame.be b/lib/libesp32/berry_tasmota/src/embedded/zigbee_zcl_frame.be new file mode 100644 index 000000000..73b4b2a30 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/embedded/zigbee_zcl_frame.be @@ -0,0 +1,44 @@ +# zigbee zcl_frame class +# +# solidify.dump(zcl_frame,true) + +class zcl_frame_ntv end + +class zcl_frame : zcl_frame_ntv + var no_bytes + + def init(p) + super(self).init(p) + self.no_bytes = bytes() + end + + def member(name) + if name == "payload" + return self._get_bytes(self.payload_ptr) + else + return super(self).member(name) + end + end + + def setmember(name, val) + if name == "payload" + return self._set_bytes(self.payload_ptr, val) + else + return super(self).setmember(name, val) + end + end + + def tomap() + import string + var m = super(self).tomap() + m["shortaddr_hex"] = string.format("0x%04X", self.shortaddr) + m["payload"] = self.payload # add payload object which is a synthetic attribute not included in tomap() + return m + end + + def tostring() + var m = self.tomap() + return str(m) + end + +end \ No newline at end of file diff --git a/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_openhasp.c b/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_haspmota.c similarity index 99% rename from lib/libesp32_lvgl/LVGL_assets/src/lv_theme_openhasp.c rename to lib/libesp32_lvgl/LVGL_assets/src/lv_theme_haspmota.c index d0f78a955..96f4c4c5e 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_openhasp.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_haspmota.c @@ -8,7 +8,7 @@ *********************/ #include "../lvgl.h" /*To see all the widgets*/ -#include "lv_theme_openhasp.h" +#include "lv_theme_haspmota.h" #include "misc/lv_gc.h" /********************* @@ -625,7 +625,7 @@ static void style_init(void) * GLOBAL FUNCTIONS **********************/ -lv_theme_t * lv_theme_openhasp_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font) +lv_theme_t * lv_theme_haspmota_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font) { /*This trick is required only to avoid the garbage collection of @@ -658,7 +658,7 @@ lv_theme_t * lv_theme_openhasp_init(lv_disp_t * disp, lv_color_t color_primary, return (lv_theme_t *)&theme; } -bool lv_theme_openhasp_is_inited(void) +bool lv_theme_haspmota_is_inited(void) { return inited; } diff --git a/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_openhasp.h b/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_haspmota.h similarity index 89% rename from lib/libesp32_lvgl/LVGL_assets/src/lv_theme_openhasp.h rename to lib/libesp32_lvgl/LVGL_assets/src/lv_theme_haspmota.h index f1aacfe04..7276f485d 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_openhasp.h +++ b/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_haspmota.h @@ -1,5 +1,5 @@ /** - * @file lv_theme_openhasp.h + * @file lv_theme_haspmota.h * */ @@ -40,9 +40,9 @@ typedef enum { * @param font pointer to a font to use. * @return a pointer to reference this theme later */ -lv_theme_t * lv_theme_openhasp_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font); +lv_theme_t * lv_theme_haspmota_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font); -bool lv_theme_openhasp_is_inited(void); +bool lv_theme_haspmota_is_inited(void); /********************** * MACROS diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c index aec4cbf45..9f333f36b 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c @@ -9,7 +9,7 @@ #include "lvgl.h" #include "be_mapping.h" #include "lv_berry.h" -#include "lv_theme_openhasp.h" +#include "lv_theme_haspmota.h" extern int lv0_member(bvm *vm); // resolve virtual members extern int lv0_load_font(bvm *vm); @@ -163,9 +163,9 @@ const be_ntv_func_def_t lv_func[] = { { "theme_get_font_normal", { (const void*) &lv_theme_get_font_normal, "lv.lv_font", "(lv.lv_obj)" } }, { "theme_get_font_small", { (const void*) &lv_theme_get_font_small, "lv.lv_font", "(lv.lv_obj)" } }, { "theme_get_from_obj", { (const void*) &lv_theme_get_from_obj, "lv.lv_theme", "(lv.lv_obj)" } }, + { "theme_haspmota_init", { (const void*) &lv_theme_haspmota_init, "lv.lv_theme", "(lv.lv_disp)(lv.lv_color)(lv.lv_color)b(lv.lv_font)" } }, + { "theme_haspmota_is_inited", { (const void*) &lv_theme_haspmota_is_inited, "b", "" } }, { "theme_mono_init", { (const void*) &lv_theme_mono_init, "lv.lv_theme", "(lv.lv_disp)b(lv.lv_font)" } }, - { "theme_openhasp_init", { (const void*) &lv_theme_openhasp_init, "lv.lv_theme", "(lv.lv_disp)(lv.lv_color)(lv.lv_color)b(lv.lv_font)" } }, - { "theme_openhasp_is_inited", { (const void*) &lv_theme_openhasp_is_inited, "b", "" } }, { "theme_set_apply_cb", { (const void*) &lv_theme_set_apply_cb, "", "(lv.lv_theme)^lv_theme_apply_cb^" } }, { "theme_set_parent", { (const void*) &lv_theme_set_parent, "", "(lv.lv_theme)(lv.lv_theme)" } }, { "timer_create", { (const void*) &lv_timer_create, "lv.lv_timer", "^lv_timer_cb^i." } }, diff --git a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h index 9827808e3..46c91aa8f 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h +++ b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h @@ -1151,7 +1151,7 @@ void lv_textarea_cursor_left(lv_obj_t * obj) void lv_textarea_cursor_down(lv_obj_t * obj) void lv_textarea_cursor_up(lv_obj_t * obj) -// ../../LVGL_assets/src/lv_theme_openhasp.h -lv_theme_t * lv_theme_openhasp_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font) -bool lv_theme_openhasp_is_inited(void) +// ../../LVGL_assets/src/lv_theme_haspmota.h +lv_theme_t * lv_theme_haspmota_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font) +bool lv_theme_haspmota_is_inited(void) diff --git a/lib/libesp32_lvgl/lv_binding_berry/src/lv_berry.c b/lib/libesp32_lvgl/lv_binding_berry/src/lv_berry.c index 96b10355a..879c33f55 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/src/lv_berry.c +++ b/lib/libesp32_lvgl/lv_binding_berry/src/lv_berry.c @@ -181,8 +181,6 @@ int lco_init(bvm *vm) { int argc = be_top(vm); lv_color_t lv_color = {}; // default value is all zeroes (black) - uint32_t color32 = 0x000000; // default to black - if (argc > 1) { if (be_isint(vm, 2)) { // color is RGB 24 bits lv_color = lv_color_hex(be_toint(vm, 2)); @@ -209,7 +207,6 @@ int lco_tostring(bvm *vm) { } int lco_toint(bvm *vm) { - lv_color_t lv_color = {}; be_getmember(vm, 1, "_p"); uint32_t ntv_color = be_toint(vm, -1); be_pushint(vm, ntv_color); diff --git a/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py b/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py index c305bdc34..11f3a001c 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py +++ b/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py @@ -741,7 +741,7 @@ print("""/******************************************************************** #include "lvgl.h" #include "be_mapping.h" #include "lv_berry.h" -#include "lv_theme_openhasp.h" +#include "lv_theme_haspmota.h" extern int lv0_member(bvm *vm); // resolve virtual members extern int lv0_load_font(bvm *vm); diff --git a/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py b/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py index 892a9cc32..d9b56084c 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py +++ b/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py @@ -78,7 +78,7 @@ lv_fun_globs = [ #"**/*.h", ] headers_names = list_files(lv_src_prefix, lv_fun_globs) -headers_names += list_files("../../LVGL_assets/src/", ["lv_theme_openhasp.h"]) +headers_names += list_files("../../LVGL_assets/src/", ["lv_theme_haspmota.h"]) # headers_names += ["lv_pre_style.h"] # for LVGL v7, add pre-generated style functions from C preprocessor # unit test diff --git a/pio-tools/post_esp32.py b/pio-tools/post_esp32.py index 2e919391b..276b0c3ec 100644 --- a/pio-tools/post_esp32.py +++ b/pio-tools/post_esp32.py @@ -39,7 +39,7 @@ FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32") variants_dir = join(FRAMEWORK_DIR, "variants", "tasmota") def esp32_create_chip_string(chip): - tasmota_platform = env.subst("$BUILD_DIR").split('/')[-1] + tasmota_platform = env.subst("$BUILD_DIR").split(os.path.sep)[-1] tasmota_platform = tasmota_platform.split('-')[0] if 'tasmota' and chip[3:] not in tasmota_platform: # quick check for a valid name like 'tasmota' + '32c3' print('Unexpected naming conventions in this build environment -> Undefined behavior for further build process!!') @@ -54,6 +54,14 @@ def esp32_build_filesystem(fs_size): for file in files: if "no_files" in file: continue + if "http" and "://" in file: + response = requests.get(file) + if response.ok: + target = join(filesystem_dir,file.split(os.path.sep)[-1]) + open(target, "wb").write(response.content) + else: + print("Failed to download: ",file) + continue shutil.copy(file, filesystem_dir) if not os.listdir(filesystem_dir): print("No files added -> will NOT create littlefs.bin and NOT overwrite fs partition!") @@ -106,7 +114,7 @@ def esp32_create_combined_bin(source, target, env): app_offset = int(row[3],base=16) # elif(row[0] == 'factory'): # factory_offset = int(row[3],base=16) - elif(row[0] == 'spiffs'): + elif(row[0] == 'spiffs'): if esp32_build_filesystem(row[4]): fs_offset = int(row[3],base=16) @@ -152,7 +160,7 @@ def esp32_create_combined_bin(source, target, env): if exists(fs_bin): print(f" - {hex(fs_offset)}| {fs_bin}") cmd += [hex(fs_offset), fs_bin] - env.Replace( + env.Replace( UPLOADERFLAGS=[ "--chip", chip, "--port", '"$UPLOAD_PORT"', diff --git a/pio-tools/pre_source_dir.py b/pio-tools/pre_source_dir.py new file mode 100644 index 000000000..660f5df0a --- /dev/null +++ b/pio-tools/pre_source_dir.py @@ -0,0 +1,12 @@ +import glob +import os + +Import("env") + +def FindInoNodes(env): + src_dir = glob.escape(env.subst("$PROJECT_SRC_DIR")) + return env.Glob(os.path.join(src_dir, "*.ino")) + env.Glob( + os.path.join(src_dir, "tasmota_*", "*.ino") + ) + +env.AddMethod(FindInoNodes) diff --git a/platformio.ini b/platformio.ini index 6b77f47c1..773eb4401 100644 --- a/platformio.ini +++ b/platformio.ini @@ -64,7 +64,8 @@ lib_extra_dirs = ;bin_dir = /tmp/bin_files/ [scripts_defaults] -extra_scripts = pio-tools/strip-floats.py +extra_scripts = pre:pio-tools/pre_source_dir.py + pio-tools/strip-floats.py pio-tools/name-firmware.py pio-tools/gzip-firmware.py pio-tools/override_copy.py diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index e78d20cdb..f2b696b8a 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -27,18 +27,22 @@ default_envs = ; tasmota-zbbridge ; tasmota-ir ; tasmota32 +; tasmota32-zbbrdgpro ; tasmota32-bluetooth ; tasmota32-webcam ; tasmota32-knx ; tasmota32-sensors -; tasmota32-display +; tasmota32-lvgl ; tasmota32-ir ; tasmota32solo1 ; tasmota32c3 +; tasmota32c3usb ; tasmota32s2 ; tasmota32s3 +; tasmota32s3usb ; tasmota32-odroidgo ; tasmota32-core2 +; tasmota32-nspanel [env] @@ -46,7 +50,7 @@ default_envs = ;platform = https://github.com/platformio/platform-espressif8266.git ;platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git ; mcspr/toolchain-xtensa @ ~5.100300.211127 -; platformio/tool-esptoolpy @ ~1.30100 +; platformio/tool-esptoolpy @ ~1.30300 ;build_unflags = ${common.build_unflags} ; -Wswitch-unreachable ;build_flags = ${common.build_flags} @@ -92,11 +96,11 @@ lib_extra_dirs = ${library.lib_extra_dirs} [env:tasmota32_base] ; *** Uncomment next lines ";" to enable development Tasmota Arduino version ESP32 ;platform = https://github.com/tasmota/platform-espressif32/releases/download/v.2.0.3/platform-espressif32-v.2.0.3.zip -;platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/837/framework-arduinoespressif32-v4.4_dev-6fa4526c0d.tar.gz +;platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/847/framework-arduinoespressif32-v4.4_dev-d327997163.tar.gz build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} -; Build variant ESP32 4M Flash, Tasmota 1856k Code/OTA, 320k LITTLEFS (default) +; Build variant ESP32 4M Flash, Tasmota 1856k Code/OTA, 1344k LITTLEFS (default) ;board = esp32_4M ; Build variant ESP32 8M Flash, Tasmota 2944k Code/OTA, 2112k LITTLEFS ;board = esp32_8M diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 4a69368c9..d88649ef2 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -49,3 +49,9 @@ platform = https://github.com/tasmota/platform-espressif32/re platform_packages = build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} + +[core32itead] +platform = https://github.com/tasmota/platform-espressif32/releases/download/v.2.0.3/platform-espressif32-solo1-v.2.0.3.zip +platform_packages = framework-arduinoespressif32 @ https://github.com/tasmota/esp32-arduino-lib-builder/releases/download/v2.0.3/framework-arduinoespressif32-itead.tar.gz +build_unflags = ${esp32_defaults.build_unflags} +build_flags = ${esp32_defaults.build_flags} \ No newline at end of file diff --git a/platformio_tasmota_cenv_sample.ini b/platformio_tasmota_cenv_sample.ini index d2ac59086..3fe8dbb14 100644 --- a/platformio_tasmota_cenv_sample.ini +++ b/platformio_tasmota_cenv_sample.ini @@ -12,13 +12,14 @@ build_flags = ${env:tasmota32_base.build_flags} -D USE_WIFI_RANGE_EXTENDER -D USE_WIFI_RANGE_EXTENDER_NAPT -[env:tasmota32s3] +[env:tasmota32s3-file] extends = env:tasmota32_base board = esp32s3 build_flags = ${env:tasmota32_base.build_flags} -D FIRMWARE_TASMOTA32 ; example for custom file upload in Tasmota Filesystem ; custom_files_upload = ${env:tasmota32_base.custom_files_upload} ; tasmota/berry/modules/Partition_wizard.tapp +; https://github.com/tasmota/autoconf/raw/main/esp32s3/DevKitC-1.autoconf ; *** Debug version used for PlatformIO Home Project Inspection [env:tasmota-debug] diff --git a/platformio_tasmota_env32.ini b/platformio_tasmota_env32.ini index ee7be6bd1..a13344c74 100644 --- a/platformio_tasmota_env32.ini +++ b/platformio_tasmota_env32.ini @@ -40,6 +40,16 @@ lib_ignore = ; tasmota/berry/modules/Partition_Manager.tapp custom_files_upload = no_files +[env:tasmota32-safeboot] +extends = env:tasmota32_base +build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_SAFEBOOT +lib_extra_dirs = lib/lib_ssl, lib/libesp32 +lib_ignore = + TTGO TWatch Library + NimBLE-Arduino + Micro-RTSP + epdiy + [env:tasmota32] extends = env:tasmota32_base build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_TASMOTA32 @@ -54,13 +64,6 @@ extends = env:tasmota32_base board = esp32_16M build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_TASMOTA32 -[env:tasmota32solo1] -extends = env:tasmota32_base -board = esp32_solo1_4M -platform = ${core32solo1.platform} -platform_packages = ${core32solo1.platform_packages} -build_flags = ${core32solo1.build_flags} -DFIRMWARE_TASMOTA32 - [env:tasmota32-webcam] extends = env:tasmota32_base board = esp32-cam @@ -98,41 +101,12 @@ extends = env:tasmota32_base build_flags = ${env:tasmota32_base.build_flags} -DUSE_IR_REMOTE_FULL -DFIRMWARE_IR lib_extra_dirs = lib/libesp32, lib/lib_basic, lib/lib_ssl -[env:tasmota32c3] +[env:tasmota32solo1] extends = env:tasmota32_base -board = esp32c3 -build_unflags = ${env:tasmota32_base.build_unflags} - -flto - -mtarget-align -build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_TASMOTA32 - -fno-lto -lib_ignore = - TTGO TWatch Library - Micro-RTSP - epdiy -[env:tasmota32c3usb] -extends = env:tasmota32c3 -board = esp32c3usb - -[env:tasmota32s2] -extends = env:tasmota32_base -board = esp32s2 -build_flags = ${env:tasmota32_base.build_flags} -D FIRMWARE_TASMOTA32 -lib_ignore = - TTGO TWatch Library - NimBLE-Arduino - Micro-RTSP - epdiy - -[env:tasmota32-safeboot] -extends = env:tasmota32_base -build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_SAFEBOOT -lib_extra_dirs = lib/lib_ssl, lib/libesp32 -lib_ignore = - TTGO TWatch Library - NimBLE-Arduino - Micro-RTSP - epdiy +board = esp32_solo1_4M +platform = ${core32solo1.platform} +platform_packages = ${core32solo1.platform_packages} +build_flags = ${core32solo1.build_flags} -DFIRMWARE_TASMOTA32 [env:tasmota32solo1-safeboot] extends = env:tasmota32_base @@ -147,6 +121,64 @@ lib_ignore = Micro-RTSP epdiy +[env:tasmota32-zbbrdgpro] +extends = env:tasmota32_base +board = esp32_4M_FS +platform = ${core32itead.platform} +platform_packages = ${core32itead.platform_packages} +build_flags = ${env:tasmota32_base.build_flags} + -DFIRMWARE_ZBBRDGPRO +custom_files_upload = ${env:tasmota32_base.custom_files_upload} + tools/fw_SonoffZigbeeBridgePro_cc2652/Sonoff_ZBPro.autoconf + tasmota/berry/zigbee/cc2652_flasher.be + tasmota/berry/zigbee/intelhex.be + tasmota/berry/zigbee/sonoff_zb_pro_flasher.be + tools/fw_SonoffZigbeeBridgePro_cc2652/SonoffZBPro_coord_20220219.hex +lib_extra_dirs = lib/lib_basic, lib/lib_ssl, lib/libesp32 + +[env:tasmota32-nspanel] +extends = env:tasmota32_base +platform = ${core32itead.platform} +platform_packages = ${core32itead.platform_packages} +build_flags = ${env:tasmota32_base.build_flags} + -DFIRMWARE_NSPANEL + +[env:tasmota32c3-safeboot] +extends = env:tasmota32_base +board = esp32c3 +build_unflags = ${env:tasmota32_base.build_unflags} + -flto + -mtarget-align +build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_SAFEBOOT + -fno-lto +lib_extra_dirs = lib/lib_ssl, lib/libesp32 +lib_ignore = + TTGO TWatch Library + NimBLE-Arduino + Micro-RTSP + epdiy + +[env:tasmota32c3] +extends = env:tasmota32_base +board = esp32c3 +build_unflags = ${env:tasmota32_base.build_unflags} + -flto + -mtarget-align +build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_TASMOTA32 + -fno-lto +lib_ignore = + TTGO TWatch Library + Micro-RTSP + epdiy + +[env:tasmota32c3usb-safeboot] +extends = env:tasmota32c3-safeboot +board = esp32c3usb + +[env:tasmota32c3usb] +extends = env:tasmota32c3 +board = esp32c3usb + [env:tasmota32s2-safeboot] extends = env:tasmota32_base board = esp32s2 @@ -158,6 +190,16 @@ lib_ignore = Micro-RTSP epdiy +[env:tasmota32s2] +extends = env:tasmota32_base +board = esp32s2 +build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_TASMOTA32 +lib_ignore = + TTGO TWatch Library + NimBLE-Arduino + Micro-RTSP + epdiy + [env:tasmota32s3-safeboot] extends = env:tasmota32_base board = esp32s3 @@ -169,35 +211,22 @@ lib_ignore = Micro-RTSP epdiy -[env:tasmota32c3-safeboot] +[env:tasmota32s3] extends = env:tasmota32_base -board = esp32c3 -build_unflags = ${env:tasmota32_base.build_unflags} - -flto - -mtarget-align -build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_SAFEBOOT - -fno-lto -lib_extra_dirs = lib/lib_ssl, lib/libesp32 +board = esp32s3 +build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_TASMOTA32 lib_ignore = TTGO TWatch Library - NimBLE-Arduino Micro-RTSP epdiy -[env:tasmota32c3usb-safeboot] -extends = env:tasmota32_base -board = esp32c3usb -build_unflags = ${env:tasmota32_base.build_unflags} - -flto - -mtarget-align -build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_SAFEBOOT - -fno-lto -lib_extra_dirs = lib/lib_ssl, lib/libesp32 -lib_ignore = - TTGO TWatch Library - NimBLE-Arduino - Micro-RTSP - epdiy +[env:tasmota32s3usb-safeboot] +extends = env:tasmota32s3-safeboot +board = esp32s3usb + +[env:tasmota32s3usb] +extends = env:tasmota32s3 +board = esp32s3usb [env:tasmota32-AF] extends = env:tasmota32_base diff --git a/tasmota/berry/berry_tasmota_config.h b/tasmota/berry/berry_tasmota_config.h index d0ebf89fc..b3f4f2c17 100644 --- a/tasmota/berry/berry_tasmota_config.h +++ b/tasmota/berry/berry_tasmota_config.h @@ -1,4 +1,4 @@ // Configuration #include "my_user_config.h" -#include "tasmota_configurations.h" +#include "include/tasmota_configurations.h" diff --git a/tasmota/berry/openhasp/openhasp.tapp b/tasmota/berry/haspmota/haspmota.tapp similarity index 96% rename from tasmota/berry/openhasp/openhasp.tapp rename to tasmota/berry/haspmota/haspmota.tapp index f14e88438..4ea6c2bdf 100644 Binary files a/tasmota/berry/openhasp/openhasp.tapp and b/tasmota/berry/haspmota/haspmota.tapp differ diff --git a/tasmota/berry/openhasp/openhasp_demo.tapp b/tasmota/berry/haspmota/haspmota_demo.tapp similarity index 97% rename from tasmota/berry/openhasp/openhasp_demo.tapp rename to tasmota/berry/haspmota/haspmota_demo.tapp index aac2e5967..313b3158e 100644 Binary files a/tasmota/berry/openhasp/openhasp_demo.tapp and b/tasmota/berry/haspmota/haspmota_demo.tapp differ diff --git a/tasmota/berry/openhasp/openhasp_widgets.tapp b/tasmota/berry/haspmota/haspmota_widgets.tapp similarity index 100% rename from tasmota/berry/openhasp/openhasp_widgets.tapp rename to tasmota/berry/haspmota/haspmota_widgets.tapp diff --git a/tasmota/berry/openhasp/pages.jsonl b/tasmota/berry/haspmota/pages.jsonl similarity index 100% rename from tasmota/berry/openhasp/pages.jsonl rename to tasmota/berry/haspmota/pages.jsonl diff --git a/tasmota/berry/openhasp/robotocondensed_latin1.tapp b/tasmota/berry/haspmota/robotocondensed_latin1.tapp similarity index 100% rename from tasmota/berry/openhasp/robotocondensed_latin1.tapp rename to tasmota/berry/haspmota/robotocondensed_latin1.tapp diff --git a/tasmota/berry/haspmota_src/gen_haspmota.sh b/tasmota/berry/haspmota_src/gen_haspmota.sh new file mode 100755 index 000000000..c81c0fdac --- /dev/null +++ b/tasmota/berry/haspmota_src/gen_haspmota.sh @@ -0,0 +1,5 @@ +# generate all haspmota tapp files +rm haspmota.tapp; zip -j -0 haspmota.tapp haspmota_core/* +rm haspmota_demo.tapp ; zip -j -0 haspmota_demo.tapp haspmota_demo/* haspmota_core/haspmota.be +cp haspmota.tapp ../haspmota +cp haspmota_demo.tapp ../haspmota diff --git a/tasmota/berry/openhasp_src/openhasp.tapp b/tasmota/berry/haspmota_src/haspmota.tapp similarity index 96% rename from tasmota/berry/openhasp_src/openhasp.tapp rename to tasmota/berry/haspmota_src/haspmota.tapp index f14e88438..4ea6c2bdf 100644 Binary files a/tasmota/berry/openhasp_src/openhasp.tapp and b/tasmota/berry/haspmota_src/haspmota.tapp differ diff --git a/tasmota/berry/haspmota_src/haspmota_core/autoexec.be b/tasmota/berry/haspmota_src/haspmota_core/autoexec.be new file mode 100644 index 000000000..138301eab --- /dev/null +++ b/tasmota/berry/haspmota_src/haspmota_core/autoexec.be @@ -0,0 +1,7 @@ +# start haspmota +# package with +# rm haspmota.tapp; zip -j -0 haspmota.tapp haspmota_core/* +import haspmota + +# defer start to make sure all modules and tapp applications were loaded first +tasmota.set_timer(1000, /-> haspmota.start()) diff --git a/tasmota/berry/openhasp_src/openhasp_core/openhasp.be b/tasmota/berry/haspmota_src/haspmota_core/haspmota.be similarity index 97% rename from tasmota/berry/openhasp_src/openhasp_core/openhasp.be rename to tasmota/berry/haspmota_src/haspmota_core/haspmota.be index d4de2b209..2e101cef3 100644 --- a/tasmota/berry/openhasp_src/openhasp_core/openhasp.be +++ b/tasmota/berry/haspmota_src/haspmota_core/haspmota.be @@ -1,19 +1,19 @@ -# OpenHASP compatibility module +# HASPMota - OpenHASP compatibility module # -# use `import openhasp` and set the JSONL definitions in `pages.jsonl` +# use `import haspmota` and set the JSONL definitions in `pages.jsonl` # # As an optimization `0 #- lv.PART_MAIN | lv.STATE_DEFAULT -#` is replaced with `0` # -# rm openhasp.tapp; zip -j -0 openhasp.tapp openhasp_core/* +# rm haspmota.tapp; zip -j -0 haspmota.tapp haspmota_core/* ################################################################################# # How to solidify (needs an ESP32 with PSRAM) #- import path -path.remove("openhasp.bec") +path.remove("haspmota.bec") import solidify -var openhasp -load('openhasp.be') +var haspmota +load('haspmota.be') var classes = [ "page", "obj", "scr", @@ -23,12 +23,12 @@ var classes = [ "qrcode" ] for c:classes - solidify.dump(openhasp.OpenHASP.("lvh_"+c), true) + solidify.dump(haspmota.HASPmota.("lvh_"+c), true) end -solidify.dump(openhasp, true) +solidify.dump(haspmota, true) -# -var openhasp = module("openhasp") +var haspmota = module("haspmota") ################################################################################# ################################################################################# @@ -37,7 +37,7 @@ var openhasp = module("openhasp") # Provide a mapping for virtual members # Stores the associated page and object id # -# Adds specific virtual members used by OpenHASP +# Adds specific virtual members used by HASPmota ################################################################################# ################################################################################# class lvh_obj @@ -62,7 +62,7 @@ class lvh_obj # and the Berry or LVGL attribute to set # # We try to map directly an attribute to the LVGL - # Ex: OpenHASP attribute `w` is mapped to LVGL `width` + # Ex: HASPmota attribute `w` is mapped to LVGL `width` # # If mapping is null, we use set_X and get_X from our own class static _attr_map = { @@ -150,7 +150,7 @@ class lvh_obj var _lv_obj # native lvgl object var _lv_label # sub-label if exists var _page # parent page object - var _action # value of the OpenHASP `action` attribute, shouldn't be called `self.action` since we want to trigger the set/member functions + var _action # value of the HASPmota `action` attribute, shouldn't be called `self.action` since we want to trigger the set/member functions #==================================================================== # Rule engine to map value and text to rules @@ -242,10 +242,10 @@ class lvh_obj end #==================================================================== - # init OpenHASP object from its jsonl definition + # init HASPmota object from its jsonl definition # # arg1: LVGL parent object (used to create a sub-object) - # arg2: `jline` JSONL definition of the object from OpenHASP template (used in sub-classes) + # arg2: `jline` JSONL definition of the object from HASPmota template (used in sub-classes) # arg3: (opt) LVGL object if it already exists and was created prior to init() #==================================================================== def init(parent, page, jline, obj) @@ -323,7 +323,7 @@ class lvh_obj # the callback avoids doing anything sophisticated in the cb # defer the actual action to the Tasmota event loop # print("-> CB fired","self",self,"obj",obj,"event",event.tomap(),"code",event.code) - var oh = self._page._oh # openhasp global object + var oh = self._page._oh # haspmota global object var code = event.code # materialize to a local variable, otherwise the value can change (and don't capture event object) if self.action != "" && code == lv.EVENT_CLICKED # if clicked and action is declared, do the page change event @@ -507,7 +507,7 @@ class lvh_obj #==================================================================== # `text_font` # - # For OpenHASP compatiblity, default to "robotocondensed-latin1" + # For HASPmota compatiblity, default to "robotocondensed-latin1" # However we propose an extension to allow for other font names # # Arg1: (int) font size for `robotocondensed-latin1` @@ -1104,7 +1104,7 @@ class lvh_dropdown : lvh_obj end end - # direction needs a conversion from OpenHASP numbers and LVGL's + # direction needs a conversion from HASPmota numbers and LVGL's def set_direction(t) # 0 = down, 1 = up, 2 = left, 3 = right self._lv_obj.set_dir(self._dir[int(t)]) @@ -1119,7 +1119,7 @@ class lvh_dropdown : lvh_obj return -1 end - # show_selected (bool) is a OpenHASP addition + # show_selected (bool) is a HASPmota addition # only meaningful if set to `true`, setting to false requires a call to `set_text` def set_show_selected(t) if t @@ -1159,22 +1159,22 @@ class lvh_page var _obj_id # (map) of `lvh_obj` objects by id numbers var _page_id # (int) id number of this page var _lv_scr # (lv_obj) lvgl screen object - var _oh # OpenHASP global object - # openhasp attributes for page are on item `#0` + var _oh # HASPmota global object + # haspmota attributes for page are on item `#0` var prev, next, back # (int) id values for `prev`, `next`, `back` buttons #==================================================================== # `init` # - # arg1: `page_number` (int) OpenHASP page id + # arg1: `page_number` (int) HASPmota page id # defaults to `1` if not specified # page 0 is special, visible on all pages. Internally uses `layer_top` - # arg2: `oh` global OpenHASP monad object - # page_number: openhasp page number, defaults to `1` if not specified + # arg2: `oh` global HASPmota monad object + # page_number: haspmota page number, defaults to `1` if not specified #==================================================================== def init(page_number, oh) import global - self._oh = oh # memorize OpenHASP parent object + self._oh = oh # memorize HASPmota parent object # if no parameter, default to page #1 page_number = int(page_number) @@ -1283,17 +1283,17 @@ end ################################################################################# # -# class `OpenHASP` to initialize the OpenHASP parsing +# class `HASPmota` to initialize the HASPmota parsing # ################################################################################# # main class controller, meant to be a singleton and the only externally used class -class OpenHASP +class HASPmota var dark # (bool) use dark theme? var hres, vres # (int) resolution var scr # (lv_obj) default LVGL screen var r16 # (lv_font) robotocondensed fonts size 16 - # openhasp objects + # haspmota objects var lvh_pages # (list of lvg_page) list of pages var lvh_page_cur_idx # (int) current page index number # regex patterns @@ -1376,8 +1376,8 @@ class OpenHASP self.r16 = lv.font_embedded("montserrat", 14) # TODO what if does not exist end - # set the theme for OpenHASP - var th2 = lv.theme_openhasp_init(0, lv.color(0xFF00FF), lv.color(0x303030), self.dark, self.r16) + # set the theme for HASPmota + var th2 = lv.theme_haspmota_init(0, lv.color(0xFF00FF), lv.color(0x303030), self.dark, self.r16) self.scr.get_disp().set_theme(th2) self.scr.set_style_bg_color(self.dark ? lv.color(0x000000) : lv.color(0xFFFFFF),0) # set background to white # apply theme to layer_top, but keep it transparent @@ -1675,7 +1675,7 @@ class OpenHASP return end - # extract openhasp class, prefix with `lvh_`. Ex: `btn` becomes `lvh_btn` + # extract haspmota class, prefix with `lvh_`. Ex: `btn` becomes `lvh_btn` # extract parent var parent_lvgl var parent_id = int(jline.find("parentid")) @@ -1746,20 +1746,20 @@ class OpenHASP end end end -openhasp.OpenHASP = OpenHASP +haspmota.HASPmota = HASPmota ################################################################################# # General module initilization ################################################################################# -# automatically instanciate the OpenHASP() monad +# automatically instanciate the HASPmota() monad # note: value is cached in the module cache -# and is returned whenever you call `import openhasp` again +# and is returned whenever you call `import haspmota` again # This means that the object is never garbage collected # -openhasp.init = def (m) # `init(m)` is called during first `import openhasp` - var oh = m.OpenHASP +haspmota.init = def (m) # `init(m)` is called during first `import haspmota` + var oh = m.HASPmota return oh() end -return openhasp +return haspmota diff --git a/tasmota/berry/openhasp_src/openhasp_demo.tapp b/tasmota/berry/haspmota_src/haspmota_demo.tapp similarity index 97% rename from tasmota/berry/openhasp_src/openhasp_demo.tapp rename to tasmota/berry/haspmota_src/haspmota_demo.tapp index aac2e5967..313b3158e 100644 Binary files a/tasmota/berry/openhasp_src/openhasp_demo.tapp and b/tasmota/berry/haspmota_src/haspmota_demo.tapp differ diff --git a/tasmota/berry/openhasp_src/openhasp_demo/autoexec.be b/tasmota/berry/haspmota_src/haspmota_demo/autoexec.be similarity index 87% rename from tasmota/berry/openhasp_src/openhasp_demo/autoexec.be rename to tasmota/berry/haspmota_src/haspmota_demo/autoexec.be index 0d3a90376..0bc19a917 100644 --- a/tasmota/berry/openhasp_src/openhasp_demo/autoexec.be +++ b/tasmota/berry/haspmota_src/haspmota_demo/autoexec.be @@ -1,5 +1,5 @@ # OpenHASP demo -# rm openhasp_demo.tapp ; zip -j -0 openhasp_demo.tapp openhasp_demo/* openhasp_core/openhasp.be +# rm haspmota_demo.tapp ; zip -j -0 haspmota_demo.tapp haspmota_demo/* haspmota_core/haspmota.be if !tasmota.memory().contains("psram") print("HSP: Error: OpenHASP demo requires PSRAM") @@ -10,8 +10,8 @@ import lv_tasmota_log import lv_tasmota_info import lv_wifi_graph -import openhasp -openhasp.start(false, "openhasp_demo.tapp#pages.jsonl") +import haspmota +haspmota.start(false, "haspmota_demo.tapp#pages.jsonl") var prev_day = -1 def set_watch() diff --git a/tasmota/berry/openhasp_src/openhasp_demo/lv_tasmota_info.be b/tasmota/berry/haspmota_src/haspmota_demo/lv_tasmota_info.be similarity index 100% rename from tasmota/berry/openhasp_src/openhasp_demo/lv_tasmota_info.be rename to tasmota/berry/haspmota_src/haspmota_demo/lv_tasmota_info.be diff --git a/tasmota/berry/openhasp_src/openhasp_demo/lv_tasmota_log.be b/tasmota/berry/haspmota_src/haspmota_demo/lv_tasmota_log.be similarity index 100% rename from tasmota/berry/openhasp_src/openhasp_demo/lv_tasmota_log.be rename to tasmota/berry/haspmota_src/haspmota_demo/lv_tasmota_log.be diff --git a/tasmota/berry/openhasp_src/openhasp_demo/lv_wifi_graph.be b/tasmota/berry/haspmota_src/haspmota_demo/lv_wifi_graph.be similarity index 100% rename from tasmota/berry/openhasp_src/openhasp_demo/lv_wifi_graph.be rename to tasmota/berry/haspmota_src/haspmota_demo/lv_wifi_graph.be diff --git a/tasmota/berry/openhasp_src/openhasp_demo/noun_Fan_35097_140.png b/tasmota/berry/haspmota_src/haspmota_demo/noun_Fan_35097_140.png similarity index 100% rename from tasmota/berry/openhasp_src/openhasp_demo/noun_Fan_35097_140.png rename to tasmota/berry/haspmota_src/haspmota_demo/noun_Fan_35097_140.png diff --git a/tasmota/berry/openhasp_src/openhasp_demo/pages.jsonl b/tasmota/berry/haspmota_src/haspmota_demo/pages.jsonl similarity index 92% rename from tasmota/berry/openhasp_src/openhasp_demo/pages.jsonl rename to tasmota/berry/haspmota_src/haspmota_demo/pages.jsonl index 12cd03736..701cc32c9 100644 --- a/tasmota/berry/openhasp_src/openhasp_demo/pages.jsonl +++ b/tasmota/berry/haspmota_src/haspmota_demo/pages.jsonl @@ -36,16 +36,16 @@ {"page":4,"comment":"---------- Page 4 - fan animation ----------"} {"id":0,"bg_color":"#0000A0","bg_grad_color":"#000000","bg_grad_dir":1,"text_color":"#FFFFFF"} -{"id":11,"obj":"img","src":"A:/openhasp_demo.tapp#noun_Fan_35097_140.png","auto_size":1,"w":140,"h":140,"x":50,"y":50,"image_recolor":"#0080FF","image_recolor_opa":150} +{"id":11,"obj":"img","src":"A:/haspmota_demo.tapp#noun_Fan_35097_140.png","auto_size":1,"w":140,"h":140,"x":50,"y":50,"image_recolor":"#0080FF","image_recolor_opa":150} {"id":12,"obj":"spinner","parentid":11,"x":7,"y":6,"w":126,"h":126,"bg_opa":0,"border_width":0,"line_width":7,"line_width1":7,"type":2,"angle":120,"speed":1000,"value_str":3,"value_font":24} {"page":5,"comment":"---------- Page 5 - fancy watch ----------"} {"id":0,"bg_color":"#000000","bg_grad_color":"#000000","bg_grad_dir":1,"text_color":"#000000"} -{"id":10,"obj":"img","src":"A:/openhasp_demo.tapp#watch_ren_back_240.png","x":40,"y":0,"w":240,"h":240} -{"id":11,"obj":"img","parentid":10,"src":"A:/openhasp_demo.tapp#watch_ren_hour_240.png","auto_size":1,"x":110,"y":45} -{"id":12,"obj":"img","parentid":10,"src":"A:/openhasp_demo.tapp#watch_ren_min_240.png","auto_size":1} -{"id":13,"obj":"img","parentid":10,"src":"A:/openhasp_demo.tapp#watch_ren_sec_240.png","auto_size":1,"x":110,"y":10} +{"id":10,"obj":"img","src":"A:/haspmota_demo.tapp#watch_ren_back_240.png","x":40,"y":0,"w":240,"h":240} +{"id":11,"obj":"img","parentid":10,"src":"A:/haspmota_demo.tapp#watch_ren_hour_240.png","auto_size":1,"x":110,"y":45} +{"id":12,"obj":"img","parentid":10,"src":"A:/haspmota_demo.tapp#watch_ren_min_240.png","auto_size":1} +{"id":13,"obj":"img","parentid":10,"src":"A:/haspmota_demo.tapp#watch_ren_sec_240.png","auto_size":1,"x":110,"y":10} {"id":15,"obj":"label","parentid":10,"x":184,"y":112,"w":18,"h":16,"text":"","align":1,"text_font":"montserrat-14"} diff --git a/tasmota/berry/openhasp_src/openhasp_demo/watch_ren_back_240.png b/tasmota/berry/haspmota_src/haspmota_demo/watch_ren_back_240.png similarity index 100% rename from tasmota/berry/openhasp_src/openhasp_demo/watch_ren_back_240.png rename to tasmota/berry/haspmota_src/haspmota_demo/watch_ren_back_240.png diff --git a/tasmota/berry/openhasp_src/openhasp_demo/watch_ren_hour_240.png b/tasmota/berry/haspmota_src/haspmota_demo/watch_ren_hour_240.png similarity index 100% rename from tasmota/berry/openhasp_src/openhasp_demo/watch_ren_hour_240.png rename to tasmota/berry/haspmota_src/haspmota_demo/watch_ren_hour_240.png diff --git a/tasmota/berry/openhasp_src/openhasp_demo/watch_ren_min_240.png b/tasmota/berry/haspmota_src/haspmota_demo/watch_ren_min_240.png similarity index 100% rename from tasmota/berry/openhasp_src/openhasp_demo/watch_ren_min_240.png rename to tasmota/berry/haspmota_src/haspmota_demo/watch_ren_min_240.png diff --git a/tasmota/berry/openhasp_src/openhasp_demo/watch_ren_sec_240.png b/tasmota/berry/haspmota_src/haspmota_demo/watch_ren_sec_240.png similarity index 100% rename from tasmota/berry/openhasp_src/openhasp_demo/watch_ren_sec_240.png rename to tasmota/berry/haspmota_src/haspmota_demo/watch_ren_sec_240.png diff --git a/tasmota/berry/openhasp_src/openhasp_examples/demo-all.jsonl b/tasmota/berry/haspmota_src/haspmota_examples/demo-all.jsonl similarity index 100% rename from tasmota/berry/openhasp_src/openhasp_examples/demo-all.jsonl rename to tasmota/berry/haspmota_src/haspmota_examples/demo-all.jsonl diff --git a/tasmota/berry/openhasp_src/openhasp_examples/demo1.jsonl b/tasmota/berry/haspmota_src/haspmota_examples/demo1.jsonl similarity index 100% rename from tasmota/berry/openhasp_src/openhasp_examples/demo1.jsonl rename to tasmota/berry/haspmota_src/haspmota_examples/demo1.jsonl diff --git a/tasmota/berry/openhasp_src/openhasp_examples/demo2.jsonl b/tasmota/berry/haspmota_src/haspmota_examples/demo2.jsonl similarity index 100% rename from tasmota/berry/openhasp_src/openhasp_examples/demo2.jsonl rename to tasmota/berry/haspmota_src/haspmota_examples/demo2.jsonl diff --git a/tasmota/berry/openhasp_src/openhasp_examples/demo3.jsonl b/tasmota/berry/haspmota_src/haspmota_examples/demo3.jsonl similarity index 100% rename from tasmota/berry/openhasp_src/openhasp_examples/demo3.jsonl rename to tasmota/berry/haspmota_src/haspmota_examples/demo3.jsonl diff --git a/tasmota/berry/openhasp_src/openhasp_examples/lv.jsonl b/tasmota/berry/haspmota_src/haspmota_examples/lv.jsonl similarity index 100% rename from tasmota/berry/openhasp_src/openhasp_examples/lv.jsonl rename to tasmota/berry/haspmota_src/haspmota_examples/lv.jsonl diff --git a/tasmota/berry/openhasp_src/openhasp_widgets.tapp b/tasmota/berry/haspmota_src/haspmota_widgets.tapp similarity index 100% rename from tasmota/berry/openhasp_src/openhasp_widgets.tapp rename to tasmota/berry/haspmota_src/haspmota_widgets.tapp diff --git a/tasmota/berry/openhasp_src/openhasp_widgets/autoexec.be b/tasmota/berry/haspmota_src/haspmota_widgets/autoexec.be similarity index 64% rename from tasmota/berry/openhasp_src/openhasp_widgets/autoexec.be rename to tasmota/berry/haspmota_src/haspmota_widgets/autoexec.be index edada704e..e174a8098 100644 --- a/tasmota/berry/openhasp_src/openhasp_widgets/autoexec.be +++ b/tasmota/berry/haspmota_src/haspmota_widgets/autoexec.be @@ -1,6 +1,6 @@ # pre-load widgets so future `import` will be already in memory # create tapp file with: -# rm rm openhasp_widgets.tapp; zip -j -0 openhasp_widgets.tapp openhasp_widgets/* +# rm rm haspmota_widgets.tapp; zip -j -0 haspmota_widgets.tapp haspmota_widgets/* import lv_tasmota_log import lv_tasmota_info import lv_wifi_graph diff --git a/tasmota/berry/openhasp_src/openhasp_widgets/lv_tasmota_info.be b/tasmota/berry/haspmota_src/haspmota_widgets/lv_tasmota_info.be similarity index 100% rename from tasmota/berry/openhasp_src/openhasp_widgets/lv_tasmota_info.be rename to tasmota/berry/haspmota_src/haspmota_widgets/lv_tasmota_info.be diff --git a/tasmota/berry/openhasp_src/openhasp_widgets/lv_tasmota_log.be b/tasmota/berry/haspmota_src/haspmota_widgets/lv_tasmota_log.be similarity index 100% rename from tasmota/berry/openhasp_src/openhasp_widgets/lv_tasmota_log.be rename to tasmota/berry/haspmota_src/haspmota_widgets/lv_tasmota_log.be diff --git a/tasmota/berry/openhasp_src/openhasp_widgets/lv_wifi_graph.be b/tasmota/berry/haspmota_src/haspmota_widgets/lv_wifi_graph.be similarity index 100% rename from tasmota/berry/openhasp_src/openhasp_widgets/lv_wifi_graph.be rename to tasmota/berry/haspmota_src/haspmota_widgets/lv_wifi_graph.be diff --git a/tasmota/berry/openhasp_src/gen_openhasp.sh b/tasmota/berry/openhasp_src/gen_openhasp.sh deleted file mode 100755 index 711398637..000000000 --- a/tasmota/berry/openhasp_src/gen_openhasp.sh +++ /dev/null @@ -1,5 +0,0 @@ -# generate all openhasp tapp files -rm openhasp.tapp; zip -j -0 openhasp.tapp openhasp_core/* -rm openhasp_demo.tapp ; zip -j -0 openhasp_demo.tapp openhasp_demo/* openhasp_core/openhasp.be -cp openhasp.tapp ../openhasp -cp openhasp_demo.tapp ../openhasp diff --git a/tasmota/berry/openhasp_src/openhasp_core/autoexec.be b/tasmota/berry/openhasp_src/openhasp_core/autoexec.be deleted file mode 100644 index 7a74f523d..000000000 --- a/tasmota/berry/openhasp_src/openhasp_core/autoexec.be +++ /dev/null @@ -1,7 +0,0 @@ -# start openhasp -# package with -# rm openhasp.tapp; zip -j -0 openhasp.tapp openhasp_core/* -import openhasp - -# defer start to make sure all modules and tapp applications were loaded first -tasmota.set_timer(1000, /-> openhasp.start()) diff --git a/tasmota/berry/zigbee/cc2652_flasher.be b/tasmota/berry/zigbee/cc2652_flasher.be new file mode 100644 index 000000000..08cb2bd34 --- /dev/null +++ b/tasmota/berry/zigbee/cc2652_flasher.be @@ -0,0 +1,385 @@ + +################################################################################# +# +# class `cc2652_flasher` +# +# Flash libraries for CC2652: read, write, verify... +# +# The serial protocol requires the CC2652 to boot in BSL (bootloader) mode. +# On Sonoff Zigbee Bridge Pro, it requires to reset the MCU with DIO_8 low. +# +# When starting the flasher, normal zigbee operations are aborterd. Restarting +# normal zigbee functions requires a Tasmota restart. +# +# Required condiguration: +# - Zigbee Rx: must be configured as `Zigbee Rx` or `TCP Rx` +# - Zigbee Tx: must be configured as `Zigbee Tx` or `TCP Tx` +# - Zigbee Reset: must be configured as `Zigbee Rst - 1`` +# - Zigbee BSL mode (low): must be configured as `Zigbee Rts - 2` +# For Sonoff Zibeee Bridge Pro: Rx=23 Tx=19 Rst-1=15 Rst-2=22 +# +# How to use: +# - `import cc2652_flasher as cc` +# aborts all zigbee operations and configures the serial port +# Output: `FLH: cc2652_flasher rx=23 tx=19 rst=15 bsl=22` +# +# - `cc.start()` to start the flasher` +# restarts the CC2652 in BSL mode, and establishes connection +# Use `cc.start(true)` to enable debug verbose mode +# +# - `cc.ping()` sends a ping command and waits for ACK (does nothing) +# +# - `cc.cmd_get_chip_id()` returns the chip ID +# +# - `cc.flash_read(addr, len)` reads `len` bytes from address `addr`` +# len must be a multiple of 4 and less or equal than 128 bytes +# Returns a bytes() object +# +# - `cc.flash_crc32(addr, len)` returns the CRC32 of a flash region +# +# - `cc.flash_write(addr, data)` writes bytes to the flash +# `data` is a bytes() buffer, its len must be a multiple of 4 and less or equal than 128 +# This call does not erase the flash, so it must have been erased before. +# The bootloader checks that the bytes were correctly written, i.e. that +# the appropriate bits were changed from `1` to `0`. +# Chaning bits from `0` to `1` requires a flash erase. +# +# - `cc.flash_erase()` erase the entire flash. +# Use with caution. After the flash is erased, there is no valid application +# in flash so the MCU always starts in BSL bootloader mode until a valid +# app is flashed. +# +# - `cc.flash_dump_to_file(filename, addr, len)` dumps the CC2652 flash into a file +# `filename` is the output file in binary format, make sure there are 360KB free in filesystem. +# Dumping the complete file is done as follows (it takes 3 minutes during which Tasmota is unresponsive): +# `cc.dump_to_file("cc2652_dump.bin", 0x00000, 0x58000)` +# +################################################################################# + +#- Example + +import string +import cc2652_flasher as cc +cc.start() +cc.ping() +print(string.format("0x%08X", cc.cmd_get_chip_id())) +# output: 0x3202F000 + +# Dumping CC2652 flash into filesystem +# This takes 3 minutes during which Tasmota is unresponsive +# +import cc2652_flasher as cc +cc.start() +cc.flash_dump_to_file("cc2652_dump.bin", 0x00000, 0x58000) + +-# + +class cc2652_flasher + var ser # serial object + var debug # verbose logs? + var rx, tx, rst, bsl # GPIO numbers + + # init - abort zigbee operations and starts the serial driver + # args are optional + def init(rx, tx, rst, bsl) + import string + + self.debug = false + self.rx = (rx == nil) ? -1 : rx + self.tx = (tx == nil) ? -1 : tx + self.rst = (rst == nil) ? -1 : rst + self.bsl = (bsl == nil) ? -1 : bsl + # + if self.rx < 0 self.rx = gpio.pin(gpio.ZIGBEE_RX) end + if self.rx < 0 self.rx = gpio.pin(gpio.TCP_RX) end + if self.tx < 0 self.tx = gpio.pin(gpio.ZIGBEE_TX) end + if self.tx < 0 self.tx = gpio.pin(gpio.TCP_TX) end + if self.rst < 0 self.rst = gpio.pin(gpio.ZIGBEE_RST, 0) end + if self.bsl < 0 self.bsl = gpio.pin(gpio.ZIGBEE_RST, 1) end + print(string.format("FLH: cc2652_flasher rx=%i tx=%i rst=%i bsl=%i", self.rx, self.tx, self.rst, self.bsl)) + # tasmota.log(string.format("FLH: cc2652_flasher rx=%i tx=%i rst=%i bsl=%i", self.rx, self.tx, self.rst, self.bsl), 3) + if self.rx < 0 || self.tx < 0 || self.rst < 0 || self.bsl < 0 + raise "value_error", "cc2652_flasher unspecified GPIOs" + end + # stop all zigbee activity + import zigbee + zigbee.abort() + # good to go + self.ser = serial(self.rx, self.tx, 115200) # initialize UART serial port + end + + # restart the MCU in BSL mode and establish communication + def start(debug) + if debug == nil debug = false end + self.debug = bool(debug) + self.reset_bsl() + # + # print("FLH: cc2652_flasher started") + end + + ################################################################################# + # Low level methods + ################################################################################# + + # restart MCU and enter BSL + # + # arg: + # ser: serial object + def reset_bsl() + self.ser.flush() + + gpio.digital_write(self.bsl, 0) # trigger BSL + + gpio.digital_write(self.rst, 0) + tasmota.delay(10) # wait 10ms + gpio.digital_write(self.rst, 1) + tasmota.delay(100) # wait 100ms + + self.ser.write(bytes("5555")) # trigger auto baudrate detector + var ret = self.recv_raw(100) + if self.debug print("ret=", ret) end + if ret != bytes('CC') + raise "protocol_error" + end + end + + # received buffer and give up if timeout + def recv_raw(timeout) + var due = tasmota.millis() + timeout + while !tasmota.time_reached(due) + if self.ser.available() + var b = self.ser.read() + if self.debug print("b:",b) end + while size(b) > 0 && b[0] == 0 + b = b[1..] + end + return b + end + tasmota.delay(5) # check every 5ms + end + raise "timeout_error", "serial timeout" + end + + # send simple ACK + def send_ack() + if self.debug print("send ACK") end + self.ser.write(bytes("00CC")) + end + + # encode payload + static def encode_payload(b) + var checksum = 0 + for i:0..size(b)-1 + checksum = (checksum + b[i]) & 0xFF + end + var payload = bytes("0000") + payload[0] = size(b) + 2 + payload[1] = checksum + payload += b + payload += bytes("00") + return payload + end + + static def decode_ack(b) + # skip any 00 or CC bytes + while size(b) > 0 && b[0] == 0 + b = b[1..] + end + if size(b) == 0 || b[0] != 0xCC + raise "serial_error", "missing ACK" + end + end + + static def decode_payload(b) + # skip any 00 or CC bytes + while size(b) > 0 && (b[0] == 0 || b[0] == 0xCC) + b = b[1..] + end + + # check buffer + var sz = b[0] + if size(b) < sz || sz < 2 raise "serial_error", "buffer too small" end + # + var payload = b[2..sz-1] + + var checksum = 0 + for i:0..size(payload)-1 + checksum = (checksum + payload[i]) & 0xFF + end + if checksum != b[1] raise "serial_error", "invalid checksum received" end + + return payload + end + + # send + # args: + # b: logical bytes() to send + # no_response: true if ignore any response, or ignore to get a response + def send(b, no_response) + # compute + var payload = self.encode_payload(b) + if self.debug print("sending:", payload) end + self.ser.write(payload) + var ret = self.recv_raw(500) + if self.debug print("ret=", ret) end + if no_response == true + #ignore + self.decode_ack(ret) + return nil + else + payload = self.decode_payload(ret) + self.send_ack() + return payload + end + end + + # Higher level functions + # 64 - COMMAND_RET_SUCCESS + # 65 - COMMAND_RET_UNKNOWN_CMD + # 66 - COMMAND_RET_INVALID_CMD + # 67 - COMMAND_RET_INVALID_ADR + # 68 - COMMAND_RET_FLASH_FAIL + def cmd_get_status() + var payload = self.send(bytes("23")) + return payload[0] + end + + # Get the value of the 32-bit user ID from the AON_PMCTL JTAGUSERCODE register + def cmd_get_chip_id() + var payload = self.send(bytes("28")) + return payload.get(0, -4) + end + + def cmd_memory_read(addr, len) + if (len % 4 != 0) raise "value_error", "len must be a multiple of 4" end + if len > 128 raise "value_error", "len is bigger than 128" end + var b = bytes("2A") + b.add(addr, -4) + b.add(1) + b.add(len/4) + + return self.send(b) + end + + # does not look to be implemented + # def cmd_memory_write(addr, data) + # var sz = size(data) + # if (sz % 4 != 0) raise "value_error", "len must be a multiple of 4" end + # if sz > 128 raise "value_error", "len is bigger than 128" end + # var b = bytes("2B") + # b.add(addr, -4) + # b.add(1) + # b += data + # print("cmd_memory_write",b) + + # return self.send(b) + # end + + def cmd_download(addr, sz) + if (sz % 4 != 0) raise "value_error", "len must be a multiple of 4" end + if sz > 128 raise "value_error", "len is bigger than 128" end + var b = bytes("21") + b.add(addr, -4) + b.add(sz, -4) + if self.debug print("cmd_download",b) end + + return self.send(b, true) + end + + def cmd_send_data(data) + var sz = size(data) + if (sz % 4 != 0) raise "value_error", "len must be a multiple of 4" end + if sz > 128 raise "value_error", "len is bigger than 128" end + var b = bytes("24") + b += data + if self.debug print("cmd_send_data",b) end + + return self.send(b, true) + end + + # WARNING: this command erases all of the customer-accessible flash sectors + # After this operation, since CCFG is not configured, the device will always reboot in BSL (bootloader) mode + # until CCFG is actually re-written + # + def cmd_bank_erase() + self.send(bytes("2C"), true) + end + + # compute crc32 for a memory range + # repeat count if forced to 0x00000000 to read each location only once + def cmd_crc32(addr, len) + var b = bytes("27") + b.add(addr, -4) + b.add(len, -4) + b.add(0, -4) # repeat count = 0 + return self.send(b) + end + + ################################################################################# + # High level methods + ################################################################################# + + def flash_read(addr, len) + return self.cmd_memory_read(addr, len) + end + + def flash_crc32(addr, len) + return self.cmd_crc32(addr, len) + end + + def flash_erase() + self.cmd_bank_erase() + end + + # send ping + def ping() + self.send(bytes("20"), true) + end + + # higher level + def flash_write(addr, data) + import string + + var sz = size(data) + if (sz % 4 != 0) raise "value_error", "len must be a multiple of 4" end + if sz > 128 raise "value_error", "len is bigger than 128" end + + var ret + + ret = self.cmd_download(addr, size(data)) + #print(">cmd_download", r) + + var ack + ack = self.cmd_get_status() + if ack != 0x40 raise "serial_error", string.format("command failed: 0x%02X - 0x%06X (%i)", ack, addr, sz) end + + ret = self.cmd_send_data(data) + + ack = self.cmd_get_status() + if ack != 0x40 raise "serial_error", string.format("command failed: 0x%02X - 0x%06X (%i)", ack, addr, sz) end + + end + + # dump the flash into a bin file + def flash_dump_to_file(filename, addr, len) + var offset = addr + var f + + try + f = open(filename,"w") + while len > 0 + var b = self.cmd_memory_read(offset, 32) + f.write(b) + offset += 32 + len -= 32 + tasmota.yield() + end + except .. as e, m + if f != nil f.close() end + raise e, m + end + f.close() + end +end + +return cc2652_flasher() diff --git a/tasmota/berry/zigbee/cc2652_flasher_example.be b/tasmota/berry/zigbee/cc2652_flasher_example.be new file mode 100644 index 000000000..b1e7e725d --- /dev/null +++ b/tasmota/berry/zigbee/cc2652_flasher_example.be @@ -0,0 +1,5 @@ +import cc2652_flasher as fl + +fl.start(true) +print("CCFG=",fl.cmd_memory_read(0x57FD8,4)) +print("crc32=",fl.cmd_crc32(0x0,0x30000)) # bytes('1598929A') diff --git a/tasmota/berry/zigbee/intelhex.be b/tasmota/berry/zigbee/intelhex.be new file mode 100644 index 000000000..08393b585 --- /dev/null +++ b/tasmota/berry/zigbee/intelhex.be @@ -0,0 +1,133 @@ +# parse intelhex file +# +# use: `import intelhex` +# +# This class allows to open and parse an Intel HEX format file. +# Basic checks are done to make sure that the format is valid. +# +# If anything goes wrong, an exception is raised. +# +# You provide 3 callbacks: +# - pre: method called when file was opened, but content not parsed - no arg, no return (raise an exception if error) +# this is a good place to erase flash before writing +# - cb: method called for each line containing data to be flashed. args(address:int, len_in_bytes:int, data:bytes, offset:int) +# address: full address in Flash (high and low are automatically combined) +# len_in_bytes: length of the data line, generally max 32 bytes +# data: bytes() object containing raw bytes +# offset: offset in bytes() object, skipping first bytes without needing to reallocate buffer +# - post: method called when all data was parsed, and before the file is closed - no arg, no return (raise an exception if error) +# this is a good place to check CRC32 or any checksum +# + +class intelhex + var filename # filename of hex file + var f # file object + var file_parsed # was the file already parsed. It cannot be flashed if not previously parsed and validated + var file_validated # was the file already validated. It cannot be flashed if not previously parsed and validated + + def init(filename) + self.filename = str(filename) + self.file_parsed = false + self.file_validated = true + end + + def close() + if self.f != nil + self.f.close() + self.f = nil + end + end + + # open the intelhex file and parse from start to end + # + # Args: + # - pre: method called when file was opened, but content not parsed - no arg, no return (raise an exception if error) + # this is a good place to erase flash before writing + # - cb: method called for each line containing data to be flashed. args(address:int, len_in_bytes:int, data:bytes, offset:int) + # address: full address in Flash (high and low are automatically combined) + # len_in_bytes: length of the data line, generally max 32 bytes + # data: bytes() object containing raw bytes + # offset: offset in bytes() object, skipping first bytes without needing to reallocate buffer + # - post: method called when all data was parsed, and before the file is closed - no arg, no return (raise an exception if error) + # this is a good place to check CRC32 or any checksum + # + def parse(pre, parse_cb, post) + try + self.f = open(self.filename, "rb") + self.file_parsed = true # we tried to parse + pre() + + self.munch_line(parse_cb) + + post() # validated is computed internally + + except .. as e, m + self.close() + self.file_validated = false + raise e, m # re-raise + end + + self.close() + end + + # internally used, verify each line + def munch_line(parse_cb) + import crc + var crc_sum = crc.sum + var tas = tasmota + var yield = tasmota.yield + + var offset_high = 0 + var offset_low = 0 + var b = bytes() + var b_get = b.get + var b_fromhex = b.fromhex + var self_f = self.f + var readline = self_f.readline + while true + yield(tas) # tasmota.yield() -- faster version + var line = readline(self_f) # self.f.readline() + # print(line) + if line == "" raise "value_error", "unexpected end of file" end + if line[0] != ":" continue end # ignore empty line or not starting with ':' + + b = b_fromhex(b, line, 1) # b.fromhex(line, 1) # convert to bytes, avoid allocating a new object + var sz = b[0] + + # check size + if size(b) != sz+5 raise "value_error", "invalid size for line: "+line end + + var record_type = b[3] + # 00: low address + data + # 01: end of file + # 04: high address + if record_type != 0 && record_type != 1 && record_type != 4 + raise "value_error", "unsupported record_type: "+str(record_type) + end + + offset_low = b_get(b, 1, -2) # b.get(1,-2) + var checksum = crc_sum(b) + if checksum != 0 raise "value_error", "invalid checksum" end + + if record_type == 1 break end # end of file + if record_type == 0 + # data + var address = offset_high << 16 | offset_low # full address + #var data = b[4..-2] # actual payload + parse_cb(address, sz, b, 4) + + # OK + # do whatever needed + import string + # print(string.format("addr=0x%06X len=0x%02X", address, sz)) + elif record_type == 4 + if offset_low != 0 raise "value_error", "offset_low not null for cmd 04" end + offset_high = b_get(b, 4, -2) # b.get(4,-2) + + end + end + end + +end + +return intelhex diff --git a/tasmota/berry/zigbee/sonoff_zb_pro_flasher.be b/tasmota/berry/zigbee/sonoff_zb_pro_flasher.be new file mode 100644 index 000000000..7eb9f1cd5 --- /dev/null +++ b/tasmota/berry/zigbee/sonoff_zb_pro_flasher.be @@ -0,0 +1,176 @@ + +################################################################################# +# +# class `sonoff_zb_pro_flasher` +# +################################################################################# + +class sonoff_zb_pro_flasher + static CCFG_address = 0x057FD8 + static CCFG_reference = 0xC5FE08C5 + + ################################################################################# + # Flashing from Intel HEX files + ################################################################################# + var filename # filename of hex file + var f # file object + var file_checked # was the file already parsed. It cannot be flashed if not previously parsed and validated + var file_validated # was the file already validated. It cannot be flashed if not previously parsed and validated + var file_hex # intelhex object + var flasher # low-level flasher object (cc2652_flasher instance) + + def init() + self.file_checked = false + self.file_validated = false + end + + def load(filename) + import intelhex + + if type(filename) != 'string' raise "value_error", "invalid file name" end + self.filename = filename + self.file_hex = intelhex(filename) # prepare the parser object + self.file_checked = false + self.file_validated = false + end + + ################################################################################# + # check that the HEX file is valid + # parse it completely once, and verify some values + ################################################################################# + def check() + self.file_hex.parse(/ -> self._check_pre(), + / address, len, data, offset -> self._check_cb(address, len, data, offset), + / -> self._check_post() + ) + end + + ################################################################################# + # Flash the firmware to the device + # + ################################################################################# + def flash() + if !self.file_checked + print("FLH: firmware not checked, use `cc.check()`") + raise "flash_error", "firmware not checked" + end + if !self.file_validated + print("FLH: firmware not validated, use `cc.check()`") + raise "flash_error", "firmware not validated" + end + + import cc2652_flasher # this stops zigbee and configures serial + self.flasher = cc2652_flasher + + try + self.file_hex.parse(/ -> self._flash_pre(), + / address, len, data, offset -> self._flash_cb(address, len, data, offset), + / -> self._flash_post() + ) + except .. as e, m + self.file_checked = false + self.file_validated = false + raise e, m + end + end + + ################################################################################# + # Dump firmware to local file + # + ################################################################################# + def dump_to_file(filename) + import cc2652_flasher # this stops zigbee and configures serial + self.flasher = cc2652_flasher + print("FLH: Dump started (takes 3 minutes during which Tasmota is unresponsive)") + self.flasher.start() + self.flasher.ping() + self.flasher.flash_dump_to_file(filename, 0x000000, 0x58000) + print("FLH: Dump completed") + end + + ################################################################################# + # low-level + ################################################################################# + def _flash_pre() + print("FLH: Flashing started (takes 5 minutes during which Tasmota is unresponsive)") + self.flasher.start() + self.flasher.ping() + # erase flash + self.flasher.flash_erase() + end + + def _flash_post() + print("FLH: Flashing completed: OK") + var flash_crc = self.flasher.cmd_crc32(0x0,0x30000) + print("FLH: Flash crc32 0x000000 - 0x2FFFF = " + str(flash_crc)); + # tasmota.log("FLH: Verification of HEX file OK", 2) + end + + def _flash_cb(addr, sz, data, offset) + var payload = data[offset .. offset + sz - 1] + + # final check + if size(payload) != sz raise "flash_error", "incomplete payload" end + + self.flasher.flash_write(addr, payload) + end + + + # start verification (log only) + def _check_pre() + print("FLH: Starting verification of HEX file") + # tasmota.log("FLH: Starting verification of HEX file", 2) + end + + # don't flash so ignore data + # check CCFG at location 0x57FD8 (4 bytes) + def _check_cb(addr, sz, data, offset) + # import string + + # check than sz is a multiple of 4 + if (sz % 4 != 0) + import string + raise "value_error", string.format("size of payload is not a mutliple of 4: 0x%06X", addr) + end + + # print(string.format("> addr=0x%06X sz=0x%02X data=%s", addr, sz, data[offset..offset+sz-1])) + var CCFG = self.CCFG_address + if addr <= CCFG && addr+sz > CCFG+4 + # we have CCFG in the buffer + var ccfg_bytes = data.get(4 + CCFG - addr, 4) + + if ccfg_bytes != self.CCFG_reference + import string + raise "value_error", string.format("incorrect CCFG, BSL is not set to DIO_8 LOW (0x%08X expected 0x%08X)", ccfg_bytes, self.CCFG_reference) end + self.file_validated = true # if we are here, it means that the file looks correct + end + end + + def _check_post() + print("FLH: Verification of HEX file OK") + # tasmota.log("FLH: Verification of HEX file OK", 2) + self.file_checked = true + end + +end + +return sonoff_zb_pro_flasher() + + +#- +# Flash local firmware + +import sonoff_zb_pro_flasher as cc +cc.load("SonoffZBPro_coord_20220219.hex") +cc.check() +cc.flash() + +-# + +#- +# Dump local firmware + +import sonoff_zb_pro_flasher as cc +cc.dump_to_file("SonoffZBPro_dump.bin") + +-# diff --git a/tasmota/i18n.h b/tasmota/include/i18n.h similarity index 100% rename from tasmota/i18n.h rename to tasmota/include/i18n.h diff --git a/tasmota/local_ca_data_sample.h b/tasmota/include/local_ca_data_sample.h similarity index 95% rename from tasmota/local_ca_data_sample.h rename to tasmota/include/local_ca_data_sample.h index 160e362ad..2d874a0c8 100644 --- a/tasmota/local_ca_data_sample.h +++ b/tasmota/include/local_ca_data_sample.h @@ -25,7 +25,7 @@ is located. ./brssl ta pki/ca.crt | sed -e '/br_x509/,+999 d' >local_ca_data.h -Then copy local_ca_data.h into the same directory as user_config_override. +Then copy local_ca_data.h into directory include. Add this line to user_config_override.h: @@ -37,15 +37,15 @@ Be sure to generate both files: local_ca_data.h, and local_ca_descriptor.h // // this is what the result will look like, except there will be // a lot of data bytes defined in the first three arrays -// -static const unsigned char PROGMEM TA0_DN[] = { - // variable number of bytes go here (typically 100-140 or so) for the DN -}; - -static const unsigned char PROGMEM TA0_RSA_N[] = { - // 256 bytes go here for the public key modulus -}; - -static const unsigned char PROGMEM TA0_RSA_E[] = { - // 3 bytes go here for the public key exponent -}; +// +static const unsigned char PROGMEM TA0_DN[] = { + // variable number of bytes go here (typically 100-140 or so) for the DN +}; + +static const unsigned char PROGMEM TA0_RSA_N[] = { + // 256 bytes go here for the public key modulus +}; + +static const unsigned char PROGMEM TA0_RSA_E[] = { + // 3 bytes go here for the public key exponent +}; diff --git a/tasmota/local_ca_descriptor_sample.h b/tasmota/include/local_ca_descriptor_sample.h similarity index 91% rename from tasmota/local_ca_descriptor_sample.h rename to tasmota/include/local_ca_descriptor_sample.h index 3d4481981..cafe455f7 100644 --- a/tasmota/local_ca_descriptor_sample.h +++ b/tasmota/include/local_ca_descriptor_sample.h @@ -18,14 +18,14 @@ */ /* -To generate a version of this file containing data for your root certificate, -run the following command from a Linux or Cygwin bash shell, assuming that a +To generate a version of this file containing data for your root certificate, +run the following command from a Linux or Cygwin bash shell, assuming that a copy of brssl (or brssl.exe) is in the directory where the EasyRSA shell script -is located. +is located. ./brssl ta pki/ca.crt | sed -e '1,/br_x509/ d' -e '/};/,+999 d' >local_ca_descriptor.h -Then copy local_ca_descriptor.h into the same directory as user_config_override. +Then copy local_ca_descriptor.h into directory include. Add this line to user_config_override.h: @@ -37,14 +37,14 @@ Be sure to generate both files: local_ca_data.h, and local_ca_descriptor.h // // this is what the result will look like // - { - { (unsigned char *)TA0_DN, sizeof TA0_DN }, - BR_X509_TA_CA, - { - BR_KEYTYPE_RSA, - { .rsa = { - (unsigned char *)TA0_RSA_N, sizeof TA0_RSA_N, - (unsigned char *)TA0_RSA_E, sizeof TA0_RSA_E, - } } - } - } + { + { (unsigned char *)TA0_DN, sizeof TA0_DN }, + BR_X509_TA_CA, + { + BR_KEYTYPE_RSA, + { .rsa = { + (unsigned char *)TA0_RSA_N, sizeof TA0_RSA_N, + (unsigned char *)TA0_RSA_E, sizeof TA0_RSA_E, + } } + } + } diff --git a/tasmota/sendemail_ESP8266.h b/tasmota/include/sendemail_ESP8266.h similarity index 100% rename from tasmota/sendemail_ESP8266.h rename to tasmota/include/sendemail_ESP8266.h diff --git a/tasmota/tasmota.h b/tasmota/include/tasmota.h similarity index 100% rename from tasmota/tasmota.h rename to tasmota/include/tasmota.h diff --git a/tasmota/tasmota_compat.h b/tasmota/include/tasmota_compat.h similarity index 100% rename from tasmota/tasmota_compat.h rename to tasmota/include/tasmota_compat.h diff --git a/tasmota/tasmota_configurations.h b/tasmota/include/tasmota_configurations.h similarity index 99% rename from tasmota/tasmota_configurations.h rename to tasmota/include/tasmota_configurations.h index f6b7682c4..53bf86646 100644 --- a/tasmota/tasmota_configurations.h +++ b/tasmota/include/tasmota_configurations.h @@ -69,6 +69,7 @@ #define USE_MY92X1 // Add support for MY92X1 RGBCW led controller as used in Sonoff B1, Ailight and Lohas #define USE_SM16716 // Add support for SM16716 RGB LED controller (+0k7 code) #define USE_SM2135 // Add support for SM2135 RGBCW led control as used in Action LSC (+0k6 code) +#define USE_BP5758D // Add support for BP5758D RGBCW led control as used in some Tuya lightbulbs (+0k8 code) #define USE_SONOFF_L1 // Add support for Sonoff L1 led control #define USE_ELECTRIQ_MOODL // Add support for ElectriQ iQ-wifiMOODL RGBW LED controller #define USE_LIGHT_PALETTE // Add support for color palette (+0k9 code) @@ -149,6 +150,7 @@ //#define USE_T67XX // [I2cDriver61] Enable Telaire T67XX CO2 sensor (I2C address 0x15) (+1k3 code) //#define USE_HDC2010 // [I2cDriver64] Enable HDC2010 temperature/humidity sensor (I2C address 0x40) (+1k5 code) //#define USE_DS3502 // [I2CDriver67] Enable DS3502 digital potentiometer (I2C address 0x28 - 0x2B) (+0k4 code) +//#define USE_HYT // [I2CDriver68] Enable HYTxxx temperature and humidity sensor (I2C address 0x28) (+0k5 code) //#define USE_RTC_CHIPS // Enable RTC chip support and NTP server - Select only one // #define USE_DS3231 // [I2cDriver26] Enable DS3231 RTC (I2C address 0x68) (+1k2 code) @@ -174,7 +176,7 @@ //#define USE_DYP // Add support for DYP ME-007 ultrasonic distance sensor, serial port version (+0k5 code) #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) #define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop - #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) + #define MP3_VOLUME 30 // Set the startup volume on init, the range can be 0..100(max) //#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger #define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) //#define USE_ZIGBEE // Enable serial communication with Zigbee CC2530 flashed with ZNP @@ -402,6 +404,7 @@ #undef USE_MY92X1 // Disable support for MY92X1 RGBCW led controller as used in Sonoff B1, Ailight and Lohas #undef USE_SM16716 // Disable support for SM16716 RGB LED controller (+0k7 code) #undef USE_SM2135 // Disable support for SM2135 RGBCW led control as used in Action LSC (+0k6 code) +#undef USE_BP5758D // Disable support for BP5758D RGBCW led control as used in some Tuya lightbulbs (+0k8 code) #undef USE_SONOFF_L1 // Disable support for Sonoff L1 led control #undef USE_ELECTRIQ_MOODL // Disable support for ElectriQ iQ-wifiMOODL RGBW LED controller #undef USE_LIGHT_PALETTE // Disable support for color palette (+0k9 code) @@ -550,6 +553,7 @@ #undef USE_MY92X1 // Disable support for MY92X1 RGBCW led controller as used in Sonoff B1, Ailight and Lohas #undef USE_SM16716 // Disable support for SM16716 RGB LED controller (+0k7 code) #undef USE_SM2135 // Disable support for SM2135 RGBCW led control as used in Action LSC (+0k6 code) +#undef USE_BP5758D // Disable support for BP5758D RGBCW led control as used in some Tuya lightbulbs (+0k8 code) #undef USE_SONOFF_L1 // Disable support for Sonoff L1 led control #undef USE_ELECTRIQ_MOODL // Disable support for ElectriQ iQ-wifiMOODL RGBW LED controller #undef USE_LIGHT_PALETTE // Disable support for color palette (+0k9 code) @@ -694,6 +698,7 @@ #undef USE_MY92X1 // Disable support for MY92X1 RGBCW led controller as used in Sonoff B1, Ailight and Lohas #undef USE_SM16716 // Disable support for SM16716 RGB LED controller (+0k7 code) #undef USE_SM2135 // Disable support for SM2135 RGBCW led control as used in Action LSC (+0k6 code) +#undef USE_BP5758D // Disable support for BP5758D RGBCW led control as used in some Tuya lightbulbs (+0k8 code) #undef USE_SONOFF_L1 // Disable support for Sonoff L1 led control #undef USE_ELECTRIQ_MOODL // Disable support for ElectriQ iQ-wifiMOODL RGBW LED controller #undef USE_LIGHT_PALETTE // Disable support for color palette (+0k9 code) diff --git a/tasmota/tasmota_configurations_ESP32.h b/tasmota/include/tasmota_configurations_ESP32.h similarity index 93% rename from tasmota/tasmota_configurations_ESP32.h rename to tasmota/include/tasmota_configurations_ESP32.h index eb96edc9f..17531767c 100644 --- a/tasmota/tasmota_configurations_ESP32.h +++ b/tasmota/include/tasmota_configurations_ESP32.h @@ -260,7 +260,7 @@ #ifdef FIRMWARE_LVGL #undef CODE_IMAGE_STR -#define CODE_IMAGE_STR "lvgl-openhasp" +#define CODE_IMAGE_STR "lvgl-haspmota" #undef MODULE #define MODULE WEMOS // [Module] Select default module from tasmota_template.h @@ -276,7 +276,7 @@ #define USE_I2S #define USE_SPI #define USE_LVGL -#define USE_LVGL_OPENHASP +#define USE_LVGL_HASPMOTA #define USE_LVGL_FREETYPE #undef SET_ESP32_STACK_SIZE #define SET_ESP32_STACK_SIZE (24 * 1024) @@ -405,6 +405,7 @@ //#define USE_AM2320 // [I2cDriver60] Enable AM2320 temperature and humidity Sensor (I2C address 0x5C) (+1k code) //#define USE_T67XX // [I2cDriver61] Enable Telaire T67XX CO2 sensor (I2C address 0x15) (+1k3 code) //#define USE_DS3502 // [I2CDriver67] Enable DS3502 digital potentiometer (I2C address 0x28 - 0x2B) (+0k4 code) +//#define USE_HYT // [I2CDriver68] Enable HYTxxx temperature and humidity sensor (I2C address 0x28) (+0k5 code) //#define USE_RTC_CHIPS // Enable RTC chip support and NTP server - Select only one // #define USE_DS3231 // [I2cDriver26] Enable DS3231 RTC (I2C address 0x68) (+1k2 code) @@ -428,7 +429,7 @@ //#define USE_DYP // Add support for DYP ME-007 ultrasonic distance sensor, serial port version (+0k5 code) #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) //#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop - #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) + #define MP3_VOLUME 30 // Set the startup volume on init, the range can be 0..100(max) //#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger //#define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) //#define USE_ZIGBEE // Enable serial communication with Zigbee CC2530 flashed with ZNP @@ -438,6 +439,72 @@ #endif // FIRMWARE_TASMOTA_LVGL ******************************************************************* +/*********************************************************************************************\ + * [tasmota32-zbbrdgpro] + * Provide an image for Sonoff Zigbee Bridge Pro +\*********************************************************************************************/ + +#ifdef FIRMWARE_ZBBRDGPRO + +#undef CODE_IMAGE_STR +#define CODE_IMAGE_STR "zbbrdgpro" + +#undef MODULE +#define MODULE WEMOS // [Module] Select default module from tasmota_template.h +#undef FALLBACK_MODULE +#define FALLBACK_MODULE WEMOS // [Module2] Select default module on fast reboot where USER_MODULE is user template + +#undef USE_DOMOTICZ +#undef USE_HOME_ASSISTANT +#define USE_TASMOTA_DISCOVERY // Enable Tasmota Discovery support (+2k code) + +#define USE_WEBCLIENT_HTTPS + +#define USE_ZIGBEE +#define USE_TCP_BRIDGE + +#define USE_ENHANCED_GUI_WIFI_SCAN + +#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) +#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer (+2k code) +#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) +//#define USE_BUZZER // Add support for a buzzer (+0k6 code) +#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller (+0k8 code, 252 iram (non 2.3.0)) +//#define USE_DEEPSLEEP // Add support for deepsleep (+1k code) +#undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer +#undef USE_KEELOQ // Disable support for Jarolift rollers by Keeloq algorithm (+4k5 code) +#undef USE_SONOFF_D1 // Disable support for Sonoff D1 Dimmer (+0k7 code) +#undef USE_SHELLY_DIMMER // Disable support for Shelly Dimmer (+3k code) + +#define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) +#define USE_SPI // Hardware SPI using GPIO12(MISO), GPIO13(MOSI) and GPIO14(CLK) in addition to two user selectable GPIOs(CS and DC) + +#define USE_ETHERNET // Add support for ethernet (+20k code) + +//#ifndef USE_KNX +//#define USE_KNX // Enable KNX IP Protocol Support (+23k code, +3k3 mem) +//#endif + +#endif // FIRMWARE_ZBBRDGPRO + +/*********************************************************************************************\ + * [tasmota32-nspanel] + * Provide an image for ths Sonoff NsPanel +\*********************************************************************************************/ + +#ifdef FIRMWARE_NSPANEL + +#undef CODE_IMAGE_STR +#define CODE_IMAGE_STR "nspanel" + +#undef MODULE +#define MODULE WEMOS // [Module] Select default module from tasmota_template.h +#undef FALLBACK_MODULE +#define FALLBACK_MODULE WEMOS // [Module2] Select default module on fast reboot where USER_MODULE is user template + +#define FIRMWARE_TASMOTA32 + +#endif // FIRMWARE_NSPANEL /*********************************************************************************************\ * [tasmota32.bin] @@ -544,6 +611,7 @@ //#define USE_EZOPMP // [I2cDriver55] Enable support for EZO's PMP sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) //#define USE_SEESAW_SOIL // [I2cDriver56] Enable Capacitice Soil Moisture & Temperature Sensor (I2C addresses 0x36 - 0x39) (+1k3 code) //#define USE_DS3502 // [I2CDriver67] Enable DS3502 digital potentiometer (I2C address 0x28 - 0x2B) (+0k4 code) +//#define USE_HYT // [I2CDriver68] Enable HYTxxx temperature and humidity sensor (I2C address 0x28) (+0k5 code) //#define USE_RTC_CHIPS // Enable RTC chip support and NTP server - Select only one // #define USE_DS3231 // [I2cDriver26] Enable DS3231 RTC (I2C address 0x68) (+1k2 code) @@ -570,7 +638,7 @@ //#define USE_DYP // Add support for DYP ME-007 ultrasonic distance sensor, serial port version (+0k5 code) #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) #define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop - #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) + #define MP3_VOLUME 30 // Set the startup volume on init, the range can be 0..100(max) //#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger #define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) //#define USE_ZIGBEE // Enable serial communication with Zigbee CC2530 flashed with ZNP diff --git a/tasmota/tasmota_globals.h b/tasmota/include/tasmota_globals.h similarity index 99% rename from tasmota/tasmota_globals.h rename to tasmota/include/tasmota_globals.h index 284e7f314..1909d2c66 100644 --- a/tasmota/tasmota_globals.h +++ b/tasmota/include/tasmota_globals.h @@ -63,7 +63,7 @@ String EthernetMacAddress(void); * Preconfigured configurations \*********************************************************************************************/ -#include "tasmota_configurations.h" // Preconfigured configurations +#include "include/tasmota_configurations.h" // Preconfigured configurations /*********************************************************************************************\ * ESP8266 specific parameters diff --git a/tasmota/tasmota_template.h b/tasmota/include/tasmota_template.h similarity index 99% rename from tasmota/tasmota_template.h rename to tasmota/include/tasmota_template.h index 5c6fa8237..80cfa3fe8 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/include/tasmota_template.h @@ -188,6 +188,7 @@ enum UserSelectablePins { GPIO_MS01, // Sonoff MS01 Moisture Sensor 1wire interface GPIO_SDIO_CMD, GPIO_SDIO_CLK, GPIO_SDIO_D0, GPIO_SDIO_D1, GPIO_SDIO_D2, GPIO_SDIO_D3, // SD Card SDIO interface, including 1-bit and 4-bit modes GPIO_FLOWRATEMETER_IN, // Flowrate Meter + GPIO_BP5758D_CLK, GPIO_BP5758D_DAT, // BP5758D PWM controller GPIO_SENSOR_END }; enum ProgramSelectablePins { @@ -420,6 +421,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_SDIO_D2 "|" D_SENSOR_SDIO_D3 "|" D_SENSOR_FLOWRATEMETER "|" + D_SENSOR_BP5758D_CLK "|" D_SENSOR_BP5758D_DAT "|" ; const char kSensorNamesFixed[] PROGMEM = @@ -661,6 +663,10 @@ const uint16_t kGpioNiceList[] PROGMEM = { AGPIO(GPIO_SM2135_CLK), // SM2135 CLOCK AGPIO(GPIO_SM2135_DAT) + MAX_SM2135_DAT, // SM2135 DATA #endif // USE_SM2135 +#ifdef USE_BP5758D + AGPIO(GPIO_BP5758D_CLK), // BP5758D CLOCK + AGPIO(GPIO_BP5758D_DAT), // BP5758D DATA +#endif // USE_BP5758D #ifdef USE_TUYA_MCU AGPIO(GPIO_TUYA_TX), // Tuya Serial interface AGPIO(GPIO_TUYA_RX), // Tuya Serial interface @@ -1233,7 +1239,7 @@ typedef struct MYTMPLT { //******************************************************************************************** #ifdef ESP8266 -#include "tasmota_template_legacy.h" +#include "include/tasmota_template_legacy.h" /********************************************************************************************\ * ESP8266 Module Templates diff --git a/tasmota/tasmota_template_legacy.h b/tasmota/include/tasmota_template_legacy.h similarity index 100% rename from tasmota/tasmota_template_legacy.h rename to tasmota/include/tasmota_template_legacy.h diff --git a/tasmota/settings.h b/tasmota/include/tasmota_types.h similarity index 95% rename from tasmota/settings.h rename to tasmota/include/tasmota_types.h index 9eaa8605c..443f7db18 100644 --- a/tasmota/settings.h +++ b/tasmota/include/tasmota_types.h @@ -1,5 +1,5 @@ /* - settings.h - setting variables for Tasmota + tasmota_types.h - setting variables for Tasmota Copyright (C) 2021 Theo Arends @@ -17,10 +17,8 @@ along with this program. If not, see . */ -#ifndef _SETTINGS_H_ -#define _SETTINGS_H_ - -const uint8_t PARAM8_SIZE = 18; // Number of param bytes (SetOption) +#ifndef _TASMOTA_TYPES_H_ +#define _TASMOTA_TYPES_H_ // Bitfield to be used for any SetOption0 .. SetOption31 persistent single bit typedef union { // Restricted by MISRA-C Rule 18.4 but so useful... @@ -170,7 +168,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t gui_table_align : 1; // bit 24 (v11.0.0.7) - SetOption138 - (GUI) Align (energy) table values left (0) or right (1) uint32_t mm_vs_inch : 1; // bit 25 (v11.1.0.1) - SetOption139 - (Pressure) Switch between mmHg (0) or inHg (1) when SO24 1 uint32_t mqtt_persistent : 1; // bit 26 (v11.1.0.1) - SetOption140 - (MQTT) MQTT clean session (0 = default) or persistent session (1) - uint32_t spare27 : 1; // bit 27 + uint32_t gui_module_name : 1; // bit 27 (v11.1.0.3) - SetOption141 - (GUI) Disable display of GUI module name (1) uint32_t spare28 : 1; // bit 28 uint32_t spare29 : 1; // bit 29 uint32_t spare30 : 1; // bit 30 @@ -178,6 +176,44 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu }; } SOBitfield5; +typedef union { // Restricted by MISRA-C Rule 18.4 but so useful... + uint32_t data; // Allow bit manipulation using SetOption + struct { // SetOption146 .. SetOption177 + uint32_t spare00 : 1; // bit 0 + uint32_t spare01 : 1; // bit 1 + uint32_t spare02 : 1; // bit 2 + uint32_t spare03 : 1; // bit 3 + uint32_t spare04 : 1; // bit 4 + uint32_t spare05 : 1; // bit 5 + uint32_t spare06 : 1; // bit 6 + uint32_t spare07 : 1; // bit 7 + uint32_t spare08 : 1; // bit 8 + uint32_t spare09 : 1; // bit 9 + uint32_t spare10 : 1; // bit 10 + uint32_t spare11 : 1; // bit 11 + uint32_t spare12 : 1; // bit 12 + uint32_t spare13 : 1; // bit 13 + uint32_t spare14 : 1; // bit 14 + uint32_t spare15 : 1; // bit 15 + uint32_t spare16 : 1; // bit 16 + uint32_t spare17 : 1; // bit 17 + uint32_t spare18 : 1; // bit 18 + uint32_t spare19 : 1; // bit 19 + uint32_t spare20 : 1; // bit 20 + uint32_t spare21 : 1; // bit 21 + uint32_t spare22 : 1; // bit 22 + uint32_t spare23 : 1; // bit 23 + uint32_t spare24 : 1; // bit 24 + uint32_t spare25 : 1; // bit 25 + uint32_t spare26 : 1; // bit 26 + uint32_t spare27 : 1; // bit 27 + uint32_t spare28 : 1; // bit 28 + uint32_t spare29 : 1; // bit 29 + uint32_t spare30 : 1; // bit 30 + uint32_t spare31 : 1; // bit 31 + }; +} SOBitfield6; + // Bitfield to be used for persistent multi bit typedef union { uint32_t data; // Allow bit manipulation @@ -339,7 +375,7 @@ typedef union { uint32_t gainceiling : 3; uint32_t agc_gain: 5; uint32_t special_effect : 3; - uint32_t spare28 : 1; + uint32_t auth : 1; uint32_t spare29 : 1; uint32_t spare30 : 1; uint32_t upgraded : 1; @@ -452,6 +488,7 @@ typedef union { const uint32_t settings_text_size = 699; // Settings->text_pool[size] = Settings->display_model (2D2) - Settings->text_pool (017) const uint8_t MAX_TUYA_FUNCTIONS = 16; +const uint8_t PARAM8_SIZE = 18; // Number of param bytes (SetOption) typedef struct { uint16_t cfg_holder; // 000 v6 header @@ -798,9 +835,10 @@ typedef struct { uint8_t tcp_config; // F5F uint8_t light_step_pixels; // F60 - uint8_t free_f61[23]; // F61 - Decrement if adding new Setting variables just above and below + uint8_t free_f61[19]; // F61 - Decrement if adding new Setting variables just above and below // Only 32 bit boundary variables below + SOBitfield6 flag6; // F74 uint16_t flowratemeter_calibration[2];// F78 int32_t energy_kWhexport_ph[3]; // F7C uint32_t eth_ipv4_address[5]; // F88 @@ -828,70 +866,6 @@ typedef struct { static_assert(sizeof(TSettings) == 4096, "TSettings Size is not correct"); -typedef struct { - uint16_t valid; // 280 (RTC memory offset 100 - sizeof(RTCRBT)) - uint8_t fast_reboot_count; // 282 - uint8_t free_003[1]; // 283 -} TRtcReboot; -TRtcReboot RtcReboot; -#ifdef ESP32 -RTC_NOINIT_ATTR TRtcReboot RtcDataReboot; -#endif // ESP32 - -typedef struct { - uint16_t valid; // 290 (RTC memory offset 100) - uint8_t oswatch_blocked_loop; // 292 - uint8_t ota_loader; // 293 - uint32_t energy_kWhtoday; // 294 - uint32_t energy_kWhtotal; // 298 - volatile uint32_t pulse_counter[MAX_COUNTERS]; // 29C - See #9521 why volatile - power_t power; // 2AC - EnergyUsage energy_usage; // 2B0 - uint32_t nextwakeup; // 2C8 - uint32_t baudrate; // 2CC - uint32_t ultradeepsleep; // 2D0 - uint16_t deepsleep_slip; // 2D4 - uint8_t improv_state; // 2D6 - - uint8_t free_2d7[1]; // 2D7 - - int32_t energy_kWhtoday_ph[3]; // 2D8 - int32_t energy_kWhtotal_ph[3]; // 2E4 - int32_t energy_kWhexport_ph[3]; // 2F0 - - uint8_t free_2fc[4]; // 2FC -} TRtcSettings; -TRtcSettings RtcSettings; -#ifdef ESP32 -RTC_NOINIT_ATTR TRtcSettings RtcDataSettings; -#endif // ESP32 - -struct TIME_T { - uint8_t second; - uint8_t minute; - uint8_t hour; - uint8_t day_of_week; // sunday is day 1 - uint8_t day_of_month; - uint8_t month; - char name_of_month[4]; - uint16_t day_of_year; - uint16_t year; - uint32_t days; - uint32_t valid; -} RtcTime; - -struct XDRVMAILBOX { - bool grpflg; - bool usridx; - uint16_t command_code; - uint32_t index; - uint32_t data_len; - int32_t payload; - char *topic; - char *data; - char *command; -} XdrvMailbox; - typedef union { // Restricted by MISRA-C Rule 18.4 but so useful... uint16_t data; // Allow bit manipulation struct { @@ -935,4 +909,4 @@ typedef union { #endif #endif -#endif // _SETTINGS_H_ +#endif // _TASMOTA_TYPES_H_ diff --git a/tasmota/tasmota_version.h b/tasmota/include/tasmota_version.h similarity index 94% rename from tasmota/tasmota_version.h rename to tasmota/include/tasmota_version.h index f4b32b051..8543e8fc8 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/include/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x0B010003; // 11.1.0.3 +const uint32_t VERSION = 0x0B010004; // 11.1.0.4 #endif // _TASMOTA_VERSION_H_ diff --git a/tasmota/xdrv_53_projector_ctrl.h b/tasmota/include/xdrv_53_projector_ctrl.h similarity index 100% rename from tasmota/xdrv_53_projector_ctrl.h rename to tasmota/include/xdrv_53_projector_ctrl.h diff --git a/tasmota/xsns_62_esp32_mi.h b/tasmota/include/xsns_62_esp32_mi.h similarity index 98% rename from tasmota/xsns_62_esp32_mi.h rename to tasmota/include/xsns_62_esp32_mi.h index ba01d619a..3b5a2e000 100644 --- a/tasmota/xsns_62_esp32_mi.h +++ b/tasmota/include/xsns_62_esp32_mi.h @@ -169,6 +169,8 @@ struct { uint32_t autoScan:1; uint32_t canScan:1; uint32_t runningScan:1; + uint32_t updateScan:1; + uint32_t deleteScanTask:1; uint32_t canConnect:1; uint32_t willConnect:1; @@ -387,7 +389,7 @@ const char * kMI32DeviceType[] PROGMEM = {kMI32DeviceType1,kMI32DeviceType2,kMI3 const char kMI32_ConnErrorMsg[] PROGMEM = "no Error|could not connect|did disconnect|got no service|got no characteristic|can not read|can not notify|can not write|did not write|notify time out"; -const char kMI32_BLEInfoMsg[] PROGMEM = "Scan ended|Got Notification|Did connect|Did disconnect|Still connected|Start scanning"; +const char kMI32_BLEInfoMsg[] PROGMEM = "Scan ended|Got Notification|Did connect|Did disconnect|Still connected|Start passive scanning|Start active scanning"; const char kMI32_HKInfoMsg[] PROGMEM = "HAP core started|HAP core did not start!!|HAP controller disconnected|HAP controller connected|HAP outlet added"; @@ -426,7 +428,8 @@ enum MI32_BLEInfoMsg { MI32_DID_CONNECT, MI32_DID_DISCONNECT, MI32_STILL_CONNECTED, - MI32_START_SCANNING + MI32_START_SCANNING_PASSIVE, + MI32_START_SCANNING_ACTIVE }; enum MI32_HKInfoMsg { diff --git a/tasmota/language/af_AF.h b/tasmota/language/af_AF.h index 968c0e1cd..d07ea47f8 100644 --- a/tasmota/language/af_AF.h +++ b/tasmota/language/af_AF.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "Diep slaap" #define D_SENSOR_EXS_ENABLE "EXS Inskakel" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h index c59f70c66..155da5507 100644 --- a/tasmota/language/bg_BG.h +++ b/tasmota/language/bg_BG.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h index b1b1ec1ab..d57e42a24 100644 --- a/tasmota/language/cs_CZ.h +++ b/tasmota/language/cs_CZ.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index 1d7916525..da558a560 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/el_GR.h b/tasmota/language/el_GR.h index 45c6f9038..bc9cae4d1 100644 --- a/tasmota/language/el_GR.h +++ b/tasmota/language/el_GR.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index ba25d36ae..6f5b040ea 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/es_ES.h b/tasmota/language/es_ES.h index acc71ce36..c730b9bdf 100644 --- a/tasmota/language/es_ES.h +++ b/tasmota/language/es_ES.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h index c27665fe7..2718ed619 100644 --- a/tasmota/language/fr_FR.h +++ b/tasmota/language/fr_FR.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 RX" #define D_SENSOR_SM2135_CLK "SM2135 CLK" #define D_SENSOR_SM2135_DAT "SM2135 DAT" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "Hibernation" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Esclave TX" diff --git a/tasmota/language/fy_NL.h b/tasmota/language/fy_NL.h index db6150f80..4890eb1fd 100644 --- a/tasmota/language/fy_NL.h +++ b/tasmota/language/fy_NL.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h index 9ca125c10..7207d6197 100644 --- a/tasmota/language/he_HE.h +++ b/tasmota/language/he_HE.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h index ee64407b3..b964ef793 100644 --- a/tasmota/language/hu_HU.h +++ b/tasmota/language/hu_HU.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index dd6d4e146..c8d2085bc 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v9.4.0.1 - Last update 15.05.2022 + * Updated until v9.4.0.1 - Last update 30.05.2022 \*********************************************************************/ #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -771,6 +771,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 - RX" #define D_SENSOR_SM2135_CLK "SM2135 - CLK" #define D_SENSOR_SM2135_DAT "SM2135 - DATI" +#define D_SENSOR_BP5758D_CLK "BP5758D - CLK" +#define D_SENSOR_BP5758D_DAT "BP5758D - DATI" #define D_SENSOR_DEEPSLEEP "Sleep profondo" #define D_SENSOR_EXS_ENABLE "EXS - Abilita" #define D_SENSOR_CLIENT_TX "Client - TX" diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h index 40f4cd824..aa4232772 100644 --- a/tasmota/language/ko_KO.h +++ b/tasmota/language/ko_KO.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h index 0e5cf5a06..4060e3cd7 100644 --- a/tasmota/language/nl_NL.h +++ b/tasmota/language/nl_NL.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/pl_PL.h b/tasmota/language/pl_PL.h index a8b514340..6bf3b66d2 100644 --- a/tasmota/language/pl_PL.h +++ b/tasmota/language/pl_PL.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "Głęboko uÅ›piony" #define D_SENSOR_EXS_ENABLE "Załącz EXS" #define D_SENSOR_CLIENT_TX "Klient TX" diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h index 866960151..fc8f54ad7 100644 --- a/tasmota/language/pt_BR.h +++ b/tasmota/language/pt_BR.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h index 6da2d62cb..d02cfb137 100644 --- a/tasmota/language/pt_PT.h +++ b/tasmota/language/pt_PT.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h index 4cfa25cb6..b6fb28845 100644 --- a/tasmota/language/ro_RO.h +++ b/tasmota/language/ro_RO.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/ru_RU.h b/tasmota/language/ru_RU.h index fc83143b0..d69309c34 100644 --- a/tasmota/language/ru_RU.h +++ b/tasmota/language/ru_RU.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h index 840edb230..3820d88e8 100644 --- a/tasmota/language/sk_SK.h +++ b/tasmota/language/sk_SK.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h index 1a3b7c6fd..e5ae351bb 100644 --- a/tasmota/language/sv_SE.h +++ b/tasmota/language/sv_SE.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h index a2c341ee6..942936615 100644 --- a/tasmota/language/tr_TR.h +++ b/tasmota/language/tr_TR.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h index c93062ef7..a0e5c5eaf 100644 --- a/tasmota/language/uk_UA.h +++ b/tasmota/language/uk_UA.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/vi_VN.h b/tasmota/language/vi_VN.h index 44d92507b..8833d1046 100644 --- a/tasmota/language/vi_VN.h +++ b/tasmota/language/vi_VN.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h index cde32877e..7db58cadb 100644 --- a/tasmota/language/zh_CN.h +++ b/tasmota/language/zh_CN.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h index 95639cc38..7f067f023 100644 --- a/tasmota/language/zh_TW.h +++ b/tasmota/language/zh_TW.h @@ -773,6 +773,8 @@ #define D_SENSOR_DDSU666_RX "DDSU666 Rx" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_BP5758D_CLK "BP5758D Clk" +#define D_SENSOR_BP5758D_DAT "BP5758D Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_CLIENT_TX "Client TX" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index b28dc2184..b8c9901a8 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -555,6 +555,7 @@ #define USE_MY92X1 // Add support for MY92X1 RGBCW led controller as used in Sonoff B1, Ailight and Lohas #define USE_SM16716 // Add support for SM16716 RGB LED controller (+0k7 code) #define USE_SM2135 // Add support for SM2135 RGBCW led control as used in Action LSC (+0k6 code) +#define USE_BP5758D // Add support for BP5758D RGBCW led control as used in some Tuya lightbulbs (+0k8 code) #define USE_SONOFF_L1 // Add support for Sonoff L1 led control #define USE_ELECTRIQ_MOODL // Add support for ElectriQ iQ-wifiMOODL RGBW LED controller (+0k3 code) #define USE_LIGHT_PALETTE // Add support for color palette (+0k7 code) @@ -673,6 +674,7 @@ // #define HM330X_HIDE_OUT_OF_DATE false // Option: change to true to hide data from web GUI and SENSOR while sensor is asleep // #define USE_HDC2010 // [I2cDriver64] Enable HDC2010 temperature/humidity sensor (I2C address 0x40) (+1k5 code) // #define USE_DS3502 // [I2CDriver67] Enable DS3502 digital potentiometer (I2C address 0x28 - 0x2B) (+0k4 code) +// #define USE_HYT // [I2CDriver68] Enable HYTxxx temperature and humidity sensor (I2C address 0x28) (+0k5 code) // #define USE_RTC_CHIPS // Enable RTC chip support and NTP server - Select only one // #define USE_DS3231 // [I2cDriver26] Enable DS3231 RTC (I2C address 0x68) (+1k2 code) @@ -750,7 +752,7 @@ #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) //#define USE_TCP_BRIDGE // Add support for Serial to TCP bridge (+1.3k code) //#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, pause, stop, track, volume and reset - #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) + #define MP3_VOLUME 30 // Set the startup volume on init, the range can be 0..100(max) // #define USE_DY_SV17F // Use of DY-SV17F MP3 Player commands: play, stop, track and volume //#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger (+1k6 code) //#define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) @@ -1026,8 +1028,8 @@ //#define USE_MI_ESP32 // Add support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash) //#define USE_BLE_ESP32 // Add support for ESP32 as a BLE-bridge (+9k2? mem, +292k? flash) //#define BLE_ESP32_ENABLE false // [SetOption115] Default value for SetOption115 -//#define USE_IBEACON // Add support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) -//#define USE_IBEACON_ESP32 + //#define USE_IBEACON // Add support for Bluetooth LE passive scan of iBeacon devices (uses HM17 module) + //#define USE_IBEACON_ESP32 // Add support for Bluetooth LE passive scan of iBeacon devices using the internal ESP32 Bluetooth module //#define USE_WEBCAM // Add support for webcam #define USE_AUTOCONF // Enable Esp32 autoconf feature, requires USE_BERRY and USE_WEBCLIENT_HTTPS (12KB Flash) @@ -1048,7 +1050,7 @@ // -- LVGL Graphics Library --------------------------------- //#define USE_LVGL // LVGL Engine, requires Berry (+382KB) #define USE_LVGL_PSRAM // Allocate LVGL memory in PSRAM if PSRAM is connected - this might be slightly slower but leaves main memory intact - // #define USE_LVGL_OPENHASP // Enable OpenHASP compatiblity and Robotocondensed fonts (+90KB flash) + // #define USE_LVGL_HASPMOTA // Enable OpenHASP compatiblity and Robotocondensed fonts (+90KB flash) #define USE_LVGL_MAX_SLEEP 10 // max sleep in ms when LVGL is enabled, more than 10ms will make display less responsive #define USE_LVGL_PNG_DECODER // include a PNG image decoder from file system (+16KB) //#define USE_LVGL_TOUCHSCREEN // Use virtual touch screen with Berry driver diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index d15cfc001..3232fccec 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -21,16 +21,16 @@ #ifndef ESP32_STAGE // ESP32 Stage has no core_version.h file. Disable include via PlatformIO Option #include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_7_1) #endif // ESP32_STAGE -#include "tasmota_compat.h" -#include "tasmota_version.h" // Tasmota version information -#include "tasmota.h" // Enumeration used in my_user_config.h +#include "include/tasmota_compat.h" +#include "include/tasmota_version.h" // Tasmota version information +#include "include/tasmota.h" // Enumeration used in my_user_config.h #include "my_user_config.h" // Fixed user configurable options #ifdef USE_TLS #include // We need to include before "tasmota_globals.h" to take precedence over the BearSSL version in Arduino #endif // USE_TLS -#include "tasmota_globals.h" // Function prototypes and global configuration -#include "i18n.h" // Language support configured by my_user_config.h -#include "tasmota_template.h" // Hardware configuration +#include "include/tasmota_globals.h" // Function prototypes and global configuration +#include "include/i18n.h" // Language support configured by my_user_config.h +#include "include/tasmota_template.h" // Hardware configuration // Libraries #include // Ota @@ -83,7 +83,7 @@ #endif // USE_UFILESYS // Structs -#include "settings.h" +#include "include/tasmota_types.h" #ifdef CONFIG_IDF_TARGET_ESP32 #include "soc/efuse_reg.h" @@ -95,6 +95,70 @@ const uint32_t VERSION_MARKER[] PROGMEM = { 0x5AA55AA5, 0xFFFFFFFF, 0xA55AA55A }; +typedef struct { + uint16_t valid; // 280 (RTC memory offset 100 - sizeof(RTCRBT)) + uint8_t fast_reboot_count; // 282 + uint8_t free_003[1]; // 283 +} TRtcReboot; +TRtcReboot RtcReboot; +#ifdef ESP32 +RTC_NOINIT_ATTR TRtcReboot RtcDataReboot; +#endif // ESP32 + +typedef struct { + uint16_t valid; // 290 (RTC memory offset 100) + uint8_t oswatch_blocked_loop; // 292 + uint8_t ota_loader; // 293 + uint32_t energy_kWhtoday; // 294 + uint32_t energy_kWhtotal; // 298 + volatile uint32_t pulse_counter[MAX_COUNTERS]; // 29C - See #9521 why volatile + power_t power; // 2AC + EnergyUsage energy_usage; // 2B0 + uint32_t nextwakeup; // 2C8 + uint32_t baudrate; // 2CC + uint32_t ultradeepsleep; // 2D0 + uint16_t deepsleep_slip; // 2D4 + uint8_t improv_state; // 2D6 + + uint8_t free_2d7[1]; // 2D7 + + int32_t energy_kWhtoday_ph[3]; // 2D8 + int32_t energy_kWhtotal_ph[3]; // 2E4 + int32_t energy_kWhexport_ph[3]; // 2F0 + + uint8_t free_2fc[4]; // 2FC +} TRtcSettings; +TRtcSettings RtcSettings; +#ifdef ESP32 +RTC_NOINIT_ATTR TRtcSettings RtcDataSettings; +#endif // ESP32 + +struct TIME_T { + uint8_t second; + uint8_t minute; + uint8_t hour; + uint8_t day_of_week; // sunday is day 1 + uint8_t day_of_month; + uint8_t month; + char name_of_month[4]; + uint16_t day_of_year; + uint16_t year; + uint32_t days; + uint32_t valid; +} RtcTime; + +struct XDRVMAILBOX { + bool grpflg; + bool usridx; + uint16_t command_code; + uint32_t index; + uint32_t data_len; + int32_t payload; + char *topic; + char *data; + char *command; +} XdrvMailbox; + WiFiUDP PortUdp; // UDP Syslog and Alexa #ifdef ESP32 diff --git a/tasmota/homekit.c b/tasmota/tasmota_support/homekit.c old mode 100755 new mode 100644 similarity index 100% rename from tasmota/homekit.c rename to tasmota/tasmota_support/homekit.c diff --git a/tasmota/sendemail_ESP32.ino b/tasmota/tasmota_support/sendemail_ESP32.ino similarity index 100% rename from tasmota/sendemail_ESP32.ino rename to tasmota/tasmota_support/sendemail_ESP32.ino diff --git a/tasmota/sendemail_ESP8266.ino b/tasmota/tasmota_support/sendemail_ESP8266.ino similarity index 99% rename from tasmota/sendemail_ESP8266.ino rename to tasmota/tasmota_support/sendemail_ESP8266.ino index 4abc897fc..508ca8131 100644 --- a/tasmota/sendemail_ESP8266.ino +++ b/tasmota/tasmota_support/sendemail_ESP8266.ino @@ -1,6 +1,6 @@ #ifdef ESP8266 #ifdef USE_SENDMAIL -#include "sendemail_ESP8266.h" +#include "include/sendemail_ESP8266.h" // enable serial debugging //#define DEBUG_EMAIL_PORT diff --git a/tasmota/settings.ino b/tasmota/tasmota_support/settings.ino similarity index 100% rename from tasmota/settings.ino rename to tasmota/tasmota_support/settings.ino diff --git a/tasmota/support.ino b/tasmota/tasmota_support/support.ino similarity index 99% rename from tasmota/support.ino rename to tasmota/tasmota_support/support.ino index 6f8dc8288..a09a6fe59 100644 --- a/tasmota/support.ino +++ b/tasmota/tasmota_support/support.ino @@ -1326,10 +1326,16 @@ void SetPin(uint32_t lpin, uint32_t gpio) { TasmotaGlobal.gpio_pin[lpin] = gpio; } -void DigitalWrite(uint32_t gpio_pin, uint32_t index, uint32_t state) -{ +void DigitalWrite(uint32_t gpio_pin, uint32_t index, uint32_t state) { + static uint32_t pinmode_init[2] = { 0 }; // Pins 0 to 63 !!! + if (PinUsed(gpio_pin, index)) { - digitalWrite(Pin(gpio_pin, index), state &1); + uint32_t pin = Pin(gpio_pin, index) & 0x3F; // Fix possible overflow over 63 gpios + if (!bitRead(pinmode_init[pin / 32], pin % 32)) { + bitSet(pinmode_init[pin / 32], pin % 32); + pinMode(pin, OUTPUT); + } + digitalWrite(pin, state &1); } } diff --git a/tasmota/support_button.ino b/tasmota/tasmota_support/support_button.ino similarity index 100% rename from tasmota/support_button.ino rename to tasmota/tasmota_support/support_button.ino diff --git a/tasmota/support_command.ino b/tasmota/tasmota_support/support_command.ino similarity index 98% rename from tasmota/support_command.ino rename to tasmota/tasmota_support/support_command.ino index 0f1bbc082..524434559 100644 --- a/tasmota/support_command.ino +++ b/tasmota/tasmota_support/support_command.ino @@ -605,11 +605,11 @@ void CmndStatus(void) if ((0 == payload) || (3 == payload)) { Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS3_LOGGING "\":{\"" D_CMND_SERIALLOG "\":%d,\"" D_CMND_WEBLOG "\":%d,\"" D_CMND_MQTTLOG "\":%d,\"" D_CMND_SYSLOG "\":%d,\"" D_CMND_LOGHOST "\":\"%s\",\"" D_CMND_LOGPORT "\":%d,\"" D_CMND_SSID "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\"" - D_JSON_RESOLUTION "\":\"%08X\",\"" D_CMND_SETOPTION "\":[\"%08X\",\"%s\",\"%08X\",\"%08X\",\"%08X\"]}}"), + D_JSON_RESOLUTION "\":\"%08X\",\"" D_CMND_SETOPTION "\":[\"%08X\",\"%s\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]}}"), Settings->seriallog_level, Settings->weblog_level, Settings->mqttlog_level, Settings->syslog_level, SettingsText(SET_SYSLOG_HOST), Settings->syslog_port, EscapeJSONString(SettingsText(SET_STASSID1)).c_str(), EscapeJSONString(SettingsText(SET_STASSID2)).c_str(), Settings->tele_period, Settings->flag2.data, Settings->flag.data, ToHex_P((unsigned char*)Settings->param, PARAM8_SIZE, stemp2, sizeof(stemp2)), - Settings->flag3.data, Settings->flag4.data, Settings->flag5.data); + Settings->flag3.data, Settings->flag4.data, Settings->flag5.data, Settings->flag6.data); CmndStatusResponse(3); } @@ -999,7 +999,7 @@ void CmndBlinktime(void) void CmndBlinkcount(void) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 65536)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 32000)) { Settings->blinkcount = XdrvMailbox.payload; // 0 - 65535 if (TasmotaGlobal.blink_counter) { TasmotaGlobal.blink_counter = Settings->blinkcount *2; } } @@ -1025,28 +1025,32 @@ void CmndSetoption(void) { CmndSetoptionBase(1); } -// Code called by SetOption and by Berrt +// Code called by SetOption and by Berry bool SetoptionDecode(uint32_t index, uint32_t *ptype, uint32_t *pindex) { - if (index < 146) { + if (index < 178) { if (index <= 31) { // SetOption0 .. 31 = Settings->flag *ptype = 2; - *pindex = index; // 0 .. 31 + *pindex = index; // 0 .. 31 } else if (index <= 49) { // SetOption32 .. 49 = Settings->param *ptype = 1; - *pindex = index -32; // 0 .. 17 (= PARAM8_SIZE -1) + *pindex = index -32; // 0 .. 17 (= PARAM8_SIZE -1) } else if (index <= 81) { // SetOption50 .. 81 = Settings->flag3 *ptype = 3; - *pindex = index -50; // 0 .. 31 + *pindex = index -50; // 0 .. 31 } - else if (index <= 113) { // SetOption82 .. 113 = Settings->flag4 + else if (index <= 113) { // SetOption82 .. 113 = Settings->flag4 *ptype = 4; - *pindex = index -82; // 0 .. 31 + *pindex = index -82; // 0 .. 31 } - else { // SetOption114 .. 145 = Settings->flag5 + else if (index <= 145) { // SetOption114 .. 145 = Settings->flag5 *ptype = 5; - *pindex = index -114; // 0 .. 31 + *pindex = index -114; // 0 .. 31 + } + else { // SetOption146 .. 177 = Settings->flag6 + *ptype = 6; + *pindex = index -146; // 0 .. 31 } return true; } @@ -1070,6 +1074,9 @@ uint32_t GetOption(uint32_t index) { else if (5 == ptype) { flag = Settings->flag5.data; } + else if (6 == ptype) { + flag = Settings->flag6.data; + } return bitRead(flag, pindex); } } else { @@ -1208,6 +1215,9 @@ void CmndSetoptionBase(bool indexed) { break; } } + else if (6 == ptype) { // SetOption146 .. 177 + bitWrite(Settings->flag6.data, pindex, XdrvMailbox.payload); + } } else { ptype = 99; // Command Error } @@ -1232,6 +1242,9 @@ void CmndSetoptionBase(bool indexed) { else if (5 == ptype) { flag = Settings->flag5.data; } + else if (6 == ptype) { + flag = Settings->flag6.data; + } if (indexed) { ResponseCmndIdxChar(GetStateText(bitRead(flag, pindex))); } else { diff --git a/tasmota/support_cores.ino b/tasmota/tasmota_support/support_cores.ino similarity index 100% rename from tasmota/support_cores.ino rename to tasmota/tasmota_support/support_cores.ino diff --git a/tasmota/support_crash_recorder.ino b/tasmota/tasmota_support/support_crash_recorder.ino similarity index 100% rename from tasmota/support_crash_recorder.ino rename to tasmota/tasmota_support/support_crash_recorder.ino diff --git a/tasmota/support_device_groups.ino b/tasmota/tasmota_support/support_device_groups.ino similarity index 100% rename from tasmota/support_device_groups.ino rename to tasmota/tasmota_support/support_device_groups.ino diff --git a/tasmota/support_eeprom.ino b/tasmota/tasmota_support/support_eeprom.ino similarity index 100% rename from tasmota/support_eeprom.ino rename to tasmota/tasmota_support/support_eeprom.ino diff --git a/tasmota/support_esp.ino b/tasmota/tasmota_support/support_esp.ino similarity index 100% rename from tasmota/support_esp.ino rename to tasmota/tasmota_support/support_esp.ino diff --git a/tasmota/support_esptool.ino b/tasmota/tasmota_support/support_esptool.ino similarity index 100% rename from tasmota/support_esptool.ino rename to tasmota/tasmota_support/support_esptool.ino diff --git a/tasmota/support_features.ino b/tasmota/tasmota_support/support_features.ino similarity index 95% rename from tasmota/support_features.ino rename to tasmota/tasmota_support/support_features.ino index bf3b17011..aae6e897c 100644 --- a/tasmota/support_features.ino +++ b/tasmota/tasmota_support/support_features.ino @@ -798,7 +798,7 @@ void ResponseAppendFeatures(void) feature8 |= 0x00800000; // xnrg_23_ade7880.ino #endif #if defined(USE_I2C) && defined(USE_PCF85363) - feature8 |= 0x01000000; // xsns_96_pcf85393.ino + feature8 |= 0x01000000; // xdrv_56_rtc_chips.ino #endif #if defined(USE_I2C) && defined(USE_DS3502) feature8 |= 0x02000000; // xdrv_61_ds3502.ino @@ -809,15 +809,61 @@ void ResponseAppendFeatures(void) #ifdef USE_FLOWRATEMETER feature8 |= 0x08000000; // xsns_96_flowratemeter.ino #endif - -// feature8 |= 0x10000000; -// feature8 |= 0x20000000; +#if defined(USE_LIGHT) && defined(USE_BP5758D) + feature8 |= 0x10000000; // xlgt_08_bp5758d.ino +#endif +#if defined(USE_I2C) && defined(USE_HYT) + feature8 |= 0x20000000; // xsns_97_hyt.ino +#endif // feature8 |= 0x40000000; // feature8 |= 0x80000000; } + static uint32_t feature9 = 0x00000000; + if (!feature9) { // Only fill this once +// feature9 |= 0x00000001; +// feature9 |= 0x00000002; +// feature9 |= 0x00000004; +// feature9 |= 0x00000008; + +// feature9 |= 0x00000010; +// feature9 |= 0x00000020; +// feature9 |= 0x00000040; +// feature9 |= 0x00000080; + +// feature9 |= 0x00000100; +// feature9 |= 0x00000200; +// feature9 |= 0x00000400; +// feature9 |= 0x00000800; + +// feature9 |= 0x00001000; +// feature9 |= 0x00002000; +// feature9 |= 0x00004000; +// feature9 |= 0x00008000; + +// feature9 |= 0x00010000; +// feature9 |= 0x00020000; +// feature9 |= 0x00040000; +// feature9 |= 0x00080000; + +// feature9 |= 0x00100000; +// feature9 |= 0x00200000; +// feature9 |= 0x00400000; +// feature9 |= 0x00800000; + +// feature9 |= 0x01000000; +// feature9 |= 0x02000000; +// feature9 |= 0x04000000; +// feature9 |= 0x08000000; + +// feature9 |= 0x10000000; +// feature9 |= 0x20000000; +// feature9 |= 0x40000000; +// feature9 |= 0x80000000; + } + /*********************************************************************************************/ - ResponseAppend_P(PSTR(",\"" D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]"), - LANGUAGE_LCID, feature1, feature2, feature3, feature4, feature5, feature6, feature7, feature8); + ResponseAppend_P(PSTR(",\"" D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]"), + LANGUAGE_LCID, feature1, feature2, feature3, feature4, feature5, feature6, feature7, feature8, feature9); } diff --git a/tasmota/support_flash_log.ino b/tasmota/tasmota_support/support_flash_log.ino similarity index 97% rename from tasmota/support_flash_log.ino rename to tasmota/tasmota_support/support_flash_log.ino index 58a8c2dc0..c28528a7f 100644 --- a/tasmota/support_flash_log.ino +++ b/tasmota/tasmota_support/support_flash_log.ino @@ -1,430 +1,430 @@ -/* - support_flash_log.ino - log to flash support for Sonoff-Tasmota - - Copyright (C) 2021 Theo Arends & Christian Baars - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - -------------------------------------------------------------------------------------------- - Version Date Action Description - -------------------------------------------------------------------------------------------- - - - --- - 1.0.0.0 20190923 started - further development by Christian Baars - https://github.com/Staars/Sonoff-Tasmota - forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota - base - code base from arendst and - written from scratch - -*/ - -/********************************************************************************************\ -| * Generic helper class to log arbitrary data to the OTA-partition -| * Working principle: Add preferrable small chunks of data to the sector buffer, which will -| * be written to FLASH when full automatically. The next sector will be -| * erased and is the anchor point for downloading and state configuration -| * after reboot. -\*********************************************************************************************/ - -#ifdef USE_FLOG -#ifdef ESP8266 - -class FLOG - -#define MAGIC_WORD_FL 0x464c //F, L - -{ - -struct header_t{ - uint16_t magic_word; // FL - uint16_t padding; // leave something for the future - uint32_t physical_start_sector:10; //first used sector of the current FLOG - uint32_t number:10; // number of this sector, starting with 0 for the first sector - uint32_t buf_pointer:12; //internal pointer to the next free position in the buffer = first empty byte when reading - }; // should be 4-byte-aligned - -private: -void _readSector(uint8_t one_sector); -void _eraseSector(uint8_t one_sector); -void _writeSector(uint8_t one_sector); -void _clearBuffer(void); -void _searchSaves(void); -void _findFirstErasedSector(void); -void _showBuffer(void); -void _initBuffer(void); -void _saveBufferToSector(void); -header_t _saved_header; - -public: - uint32_t size; // size of OTA-partition - uint32_t start; // start position of OTA-partition in bytes - uint32_t end; // end position of OTA-partition in bytes - uint16_t num_sectors; // calculated number of sectors with a size of 4096 bytes - - uint16_t first_erased_sector; // this will be our new start - uint16_t current_sector; // always point to next sector, where data from the buffer will be written to - - uint16_t bytes_left; // byte per buffer (of sector size 4096 bytes - 8 byte header size) - uint16_t sectors_left; // number of saved sectors for download - - uint8_t mode = 0; // 0 - write once on all sectors, then stop, 1 - write infinitely through the sectors - bool found_saved_data = false; // possible saved data has been found - bool ready = false; // the FLOG is initialized - bool running_download = false; // a download operation is running - bool recording = false; // ready for recording - - union sector_t{ - uint32_t dword_buffer[FLASH_SECTOR_SIZE/4]; - uint8_t byte_buffer[FLASH_SECTOR_SIZE]; - header_t header; // should be 4-byte-aligned - } sector; // the global buffer of 4096 bytes, used for reading and writing - - void init(void); - void addToBuffer(uint8_t src[], uint32_t size); - void startRecording(bool append); - void stopRecording(void); - - typedef void (*CallbackNoArgs) (); // simple typedef for a callback - typedef void (*CallbackWithArgs) (uint8_t *_record); // typedef for a callback with one argument - - void startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter); -}; - -extern "C" uint32_t _SPIFFS_start; // we make shure later, that only one of the two is really used ... -extern "C" uint32_t _FS_start; // ... depending on core-sdk-version - -/** - * @brief Will examine the start and end of the OTA-partition. Then the sector size will be computed, saved data should be found and the initial state will be configured. - */ -void FLOG::init(void) -{ -DEBUG_SENSOR_LOG(PSTR("FLOG: init ...")); -size = ESP.getSketchSize(); -// round one sector up -start = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); -end = (uint32_t)&_FS_start - 0x40200000; -num_sectors = (end - start)/FLASH_SECTOR_SIZE; -DEBUG_SENSOR_LOG(PSTR("FLOG: size: 0x%lx, start: 0x%lx, end: 0x%lx, num_sectors(dec): %lu"), size, start, end, num_sectors ); -_findFirstErasedSector(); -if(first_erased_sector == 0xffff){ - _eraseSector(0); - first_erased_sector = 0; // start with sector 0, could be first run or after crash -} -_searchSaves(); -_initBuffer(); -ready = true; -} - -/********************************************************************************************\ -| * -| * private helper functions -| * -\*********************************************************************************************/ - -/** - * @brief Read a sector into the global buffer - * - * @param one_sector as an uint8_t - */ -void FLOG::_readSector(uint8_t one_sector){ - DEBUG_SENSOR_LOG(PSTR("FLOG: read sector number: %u" ), one_sector); - ESP.flashRead(start+(one_sector * FLASH_SECTOR_SIZE),(uint32_t *)§or.dword_buffer, FLASH_SECTOR_SIZE); -} -/** - * @brief Erase the given sector og the OTA-partition - * - * @param one_sector as an uint8_t - */ -void FLOG::_eraseSector(uint8_t one_sector){ // Erase sector of FLOG/OTA - DEBUG_SENSOR_LOG(PSTR("FLOG: erasing sector number: %u" ), one_sector); - ESP.flashEraseSector((start/FLASH_SECTOR_SIZE)+one_sector); -} -/** - * @brief Write the global buffer to the given sector - * - * @param one_sector as an uint8_t - */ -void FLOG::_writeSector(uint8_t one_sector){ // Write sector of FLOG/OTA - DEBUG_SENSOR_LOG(PSTR("FLOG: write buffer to sector number: %u" ), one_sector); - ESP.flashWrite(start+(one_sector * FLASH_SECTOR_SIZE),(uint32_t *)§or.dword_buffer, FLASH_SECTOR_SIZE); -} -/** - * @brief Clear the global buffer, but leave the header intact - * - */ -void FLOG::_clearBuffer(){ //not the header - for (uint32_t i = sizeof(sector.header)/4; i<(sizeof(sector.dword_buffer)/4); i++){ - sector.dword_buffer[i] = 0; - } - sector.header.buf_pointer = sizeof(sector.header); - // _showBuffer(); -} -/** - * @brief Write global buffer to FLASH and set the current sector to the next valid position, maybe to 0 - * - */ -void FLOG::_saveBufferToSector(){ // save buffer to already erased(!) sector, erase next sector, clear buffer, increment number - DEBUG_SENSOR_LOG(PSTR("FLOG: write buffer to current sector: %u" ),current_sector); - _writeSector(current_sector); - if(current_sector == num_sectors){ // 1 MB means ~110 sectors in OTA-partition, if we reach this, start a again - current_sector = 0; - } - else{ - current_sector++; - } - _eraseSector(current_sector); // we always erase the next sector, to find out were we are after restart - _clearBuffer(); - sector.header.number++; - DEBUG_SENSOR_LOG(PSTR("FLOG: new sector header number: %u" ),sector.header.number); -} - -/** - * @brief Typically after restart find the first erased sector as a starting point for further operations - * - */ -void FLOG::_findFirstErasedSector(){ - for (uint32_t i = 0; i3){ - break; - } - } -} - -/** - * @brief pass a data entry/record as uint8_t array with its size - * - * @param src uint8_t array - * @param size uint32_t size of the array - */ -void FLOG::addToBuffer(uint8_t src[], uint32_t size){ - if(mode == 0){ - if(sector.header.number == num_sectors && !ready){ - return; // we ignore additional calls and are done, TODO: maybe use meaningful return values - } - } - if((FLASH_SECTOR_SIZE-sector.header.buf_pointer-sizeof(sector.header))>size){ - // DEBUG_SENSOR_LOG(PSTR("FLOG: enough space left in buffer: %u"), FLASH_SECTOR_SIZE - sector.header.buf_pointer - sizeof(sector.header)); - // DEBUG_SENSOR_LOG(PSTR("FLOG: current buf_pointer: %u, size of added: %u"), sector.header.buf_pointer, size); - - memcpy(sector.byte_buffer + sector.header.buf_pointer, src, size); - sector.header.buf_pointer+=size; // this is the next free spot - // DEBUG_SENSOR_LOG(PSTR("FLOG: current buf_pointer: %u"), sector.header.buf_pointer); - } - else{ - DEBUG_SENSOR_LOG(PSTR("FLOG: save buffer to flash sector: %u"), current_sector); - DEBUG_SENSOR_LOG(PSTR("FLOG: current buf_pointer: %u"), sector.header.buf_pointer); - _saveBufferToSector(); - sectors_left++; - // but now save the data to the fresh buffer - if((FLASH_SECTOR_SIZE-sector.header.buf_pointer-sizeof(sector.header))>size){ - memcpy(sector.byte_buffer + sector.header.buf_pointer, src, size); - sector.header.buf_pointer+=size; // this is the next free spot - } - } -} - -/** - * @brief shows that it is ready to accept recording - * - * @param append - if true append to current log, else start a new log - */ -void FLOG::startRecording(bool append){ - if(recording){ - DEBUG_SENSOR_LOG(PSTR("FLOG: already recording")); - return; - } - recording = true; - DEBUG_SENSOR_LOG(PSTR("FLOG: start recording")); - _initBuffer(); - if(!found_saved_data) { - append = false; // nothing to append to, we silently start a new log - } - if(append){ - sector.header.number = _saved_header.number+1; // continue with the next number - sector.header.physical_start_sector = _saved_header.physical_start_sector; // keep the old start sector - } - else{ //new log, old data is lost - sector.header.physical_start_sector = (uint16_t)first_erased_sector; - found_saved_data = false; - sectors_left = 0; - } - } - -/** - * @brief stop recording including saving current buffer to FLASH - * - */ -void FLOG::stopRecording(void){ - _saveBufferToSector(); - _findFirstErasedSector(); - _searchSaves(); - _initBuffer(); - recording = false; - found_saved_data = true; - } - -/** - * @brief Will start a downloads, needs the correct implementation of 3 callback functions - * - * @param size: size of the data entry/record in bytes, i.e. sizeof(myStruct) - * @param sendHeader: should implement at least something like: - * @example Webserver->setContentLength(CONTENT_LENGTH_UNKNOWN); // This is very likely unknown!! - * Webserver->sendHeader(F("Content-Disposition"), F("attachment; filename=myfile.txt")); - * @param sendRecord: will receive the memory address as "uint8_t* addr" and should consume the current entry/record - * @example myStruct_t *entry = (myStruct_t*)addr; - * Then make useful Strings and send it, i.e.: Webserver->sendContent_P(myString); - * @param sendFooter: finish the download, should implement at least: - * @example Webserver->sendContent(""); - */ - void FLOG::startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter){ - - _readSector(sector.header.physical_start_sector); - uint32_t next_sector = sector.header.physical_start_sector; - bytes_left = sector.header.buf_pointer - sizeof(sector.header); - DEBUG_SENSOR_LOG(PSTR("FLOG: create file for download, will process %u bytes"), bytes_left); - running_download = true; - // Callback 1: Create the header incl. file name, content length (probably unknown!!) and additional header stuff - sendHeader(); - - while(sectors_left){ - DEBUG_SENSOR_LOG(PSTR("FLOG: next sector: %u"), next_sector); - //initially we have the first sector already loaded, so we do it at the bottom - uint32_t k = sizeof(sector.header); - while(bytes_left){ - // DEBUG_SENSOR_LOG(PSTR("FLOG: DL %u %u"), Flog->sector.byte_buffer[k],Flog->sector.byte_buffer[k+1]); - uint8_t *_record_start = (uint8_t*)§or.byte_buffer[k]; // this is basically the start address of the current record/entry of the Log - // Callback 2: send the pointer for consuming the next record/entry and doing something useful to create a file - sendRecord(_record_start); - if(k%128 == 0){ // give control to the system every x iteration, TODO: This will fail, when record/entry-size is not 8 - // DEBUG_SENSOR_LOG(PSTR("FLOG: now loop(), %u bytes left"), Flog->bytes_left); - OsWatchLoop(); - delay(TasmotaGlobal.sleep); - } - k+=size; - if(bytes_left>7){ - bytes_left-=size; - } - else{ - bytes_left = 0; - DEBUG_SENSOR_LOG(PSTR("FLOG: Flog->bytes_left not dividable by 8 ??????")); - } - } - next_sector++; - if(next_sector>num_sectors){ - next_sector = 0; - } - sectors_left--; - _readSector(next_sector); - bytes_left = sector.header.buf_pointer - sizeof(sector.header); - OsWatchLoop(); - delay(TasmotaGlobal.sleep); - } - running_download = false; - // Callback 3: create a footer or simply finish the download with an empty payload - sendFooter(); - // refresh settings for another download - _searchSaves(); - _initBuffer(); - } - - #endif // ESP8266 +/* + support_flash_log.ino - log to flash support for Sonoff-Tasmota + + Copyright (C) 2021 Theo Arends & Christian Baars + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + -------------------------------------------------------------------------------------------- + Version Date Action Description + -------------------------------------------------------------------------------------------- + + + --- + 1.0.0.0 20190923 started - further development by Christian Baars - https://github.com/Staars/Sonoff-Tasmota + forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota + base - code base from arendst and - written from scratch + +*/ + +/********************************************************************************************\ +| * Generic helper class to log arbitrary data to the OTA-partition +| * Working principle: Add preferrable small chunks of data to the sector buffer, which will +| * be written to FLASH when full automatically. The next sector will be +| * erased and is the anchor point for downloading and state configuration +| * after reboot. +\*********************************************************************************************/ + +#ifdef USE_FLOG +#ifdef ESP8266 + +class FLOG + +#define MAGIC_WORD_FL 0x464c //F, L + +{ + +struct header_t{ + uint16_t magic_word; // FL + uint16_t padding; // leave something for the future + uint32_t physical_start_sector:10; //first used sector of the current FLOG + uint32_t number:10; // number of this sector, starting with 0 for the first sector + uint32_t buf_pointer:12; //internal pointer to the next free position in the buffer = first empty byte when reading + }; // should be 4-byte-aligned + +private: +void _readSector(uint8_t one_sector); +void _eraseSector(uint8_t one_sector); +void _writeSector(uint8_t one_sector); +void _clearBuffer(void); +void _searchSaves(void); +void _findFirstErasedSector(void); +void _showBuffer(void); +void _initBuffer(void); +void _saveBufferToSector(void); +header_t _saved_header; + +public: + uint32_t size; // size of OTA-partition + uint32_t start; // start position of OTA-partition in bytes + uint32_t end; // end position of OTA-partition in bytes + uint16_t num_sectors; // calculated number of sectors with a size of 4096 bytes + + uint16_t first_erased_sector; // this will be our new start + uint16_t current_sector; // always point to next sector, where data from the buffer will be written to + + uint16_t bytes_left; // byte per buffer (of sector size 4096 bytes - 8 byte header size) + uint16_t sectors_left; // number of saved sectors for download + + uint8_t mode = 0; // 0 - write once on all sectors, then stop, 1 - write infinitely through the sectors + bool found_saved_data = false; // possible saved data has been found + bool ready = false; // the FLOG is initialized + bool running_download = false; // a download operation is running + bool recording = false; // ready for recording + + union sector_t{ + uint32_t dword_buffer[FLASH_SECTOR_SIZE/4]; + uint8_t byte_buffer[FLASH_SECTOR_SIZE]; + header_t header; // should be 4-byte-aligned + } sector; // the global buffer of 4096 bytes, used for reading and writing + + void init(void); + void addToBuffer(uint8_t src[], uint32_t size); + void startRecording(bool append); + void stopRecording(void); + + typedef void (*CallbackNoArgs) (); // simple typedef for a callback + typedef void (*CallbackWithArgs) (uint8_t *_record); // typedef for a callback with one argument + + void startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter); +}; + +extern "C" uint32_t _SPIFFS_start; // we make shure later, that only one of the two is really used ... +extern "C" uint32_t _FS_start; // ... depending on core-sdk-version + +/** + * @brief Will examine the start and end of the OTA-partition. Then the sector size will be computed, saved data should be found and the initial state will be configured. + */ +void FLOG::init(void) +{ +DEBUG_SENSOR_LOG(PSTR("FLOG: init ...")); +size = ESP.getSketchSize(); +// round one sector up +start = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); +end = (uint32_t)&_FS_start - 0x40200000; +num_sectors = (end - start)/FLASH_SECTOR_SIZE; +DEBUG_SENSOR_LOG(PSTR("FLOG: size: 0x%lx, start: 0x%lx, end: 0x%lx, num_sectors(dec): %lu"), size, start, end, num_sectors ); +_findFirstErasedSector(); +if(first_erased_sector == 0xffff){ + _eraseSector(0); + first_erased_sector = 0; // start with sector 0, could be first run or after crash +} +_searchSaves(); +_initBuffer(); +ready = true; +} + +/********************************************************************************************\ +| * +| * private helper functions +| * +\*********************************************************************************************/ + +/** + * @brief Read a sector into the global buffer + * + * @param one_sector as an uint8_t + */ +void FLOG::_readSector(uint8_t one_sector){ + DEBUG_SENSOR_LOG(PSTR("FLOG: read sector number: %u" ), one_sector); + ESP.flashRead(start+(one_sector * FLASH_SECTOR_SIZE),(uint32_t *)§or.dword_buffer, FLASH_SECTOR_SIZE); +} +/** + * @brief Erase the given sector og the OTA-partition + * + * @param one_sector as an uint8_t + */ +void FLOG::_eraseSector(uint8_t one_sector){ // Erase sector of FLOG/OTA + DEBUG_SENSOR_LOG(PSTR("FLOG: erasing sector number: %u" ), one_sector); + ESP.flashEraseSector((start/FLASH_SECTOR_SIZE)+one_sector); +} +/** + * @brief Write the global buffer to the given sector + * + * @param one_sector as an uint8_t + */ +void FLOG::_writeSector(uint8_t one_sector){ // Write sector of FLOG/OTA + DEBUG_SENSOR_LOG(PSTR("FLOG: write buffer to sector number: %u" ), one_sector); + ESP.flashWrite(start+(one_sector * FLASH_SECTOR_SIZE),(uint32_t *)§or.dword_buffer, FLASH_SECTOR_SIZE); +} +/** + * @brief Clear the global buffer, but leave the header intact + * + */ +void FLOG::_clearBuffer(){ //not the header + for (uint32_t i = sizeof(sector.header)/4; i<(sizeof(sector.dword_buffer)/4); i++){ + sector.dword_buffer[i] = 0; + } + sector.header.buf_pointer = sizeof(sector.header); + // _showBuffer(); +} +/** + * @brief Write global buffer to FLASH and set the current sector to the next valid position, maybe to 0 + * + */ +void FLOG::_saveBufferToSector(){ // save buffer to already erased(!) sector, erase next sector, clear buffer, increment number + DEBUG_SENSOR_LOG(PSTR("FLOG: write buffer to current sector: %u" ),current_sector); + _writeSector(current_sector); + if(current_sector == num_sectors){ // 1 MB means ~110 sectors in OTA-partition, if we reach this, start a again + current_sector = 0; + } + else{ + current_sector++; + } + _eraseSector(current_sector); // we always erase the next sector, to find out were we are after restart + _clearBuffer(); + sector.header.number++; + DEBUG_SENSOR_LOG(PSTR("FLOG: new sector header number: %u" ),sector.header.number); +} + +/** + * @brief Typically after restart find the first erased sector as a starting point for further operations + * + */ +void FLOG::_findFirstErasedSector(){ + for (uint32_t i = 0; i3){ + break; + } + } +} + +/** + * @brief pass a data entry/record as uint8_t array with its size + * + * @param src uint8_t array + * @param size uint32_t size of the array + */ +void FLOG::addToBuffer(uint8_t src[], uint32_t size){ + if(mode == 0){ + if(sector.header.number == num_sectors && !ready){ + return; // we ignore additional calls and are done, TODO: maybe use meaningful return values + } + } + if((FLASH_SECTOR_SIZE-sector.header.buf_pointer-sizeof(sector.header))>size){ + // DEBUG_SENSOR_LOG(PSTR("FLOG: enough space left in buffer: %u"), FLASH_SECTOR_SIZE - sector.header.buf_pointer - sizeof(sector.header)); + // DEBUG_SENSOR_LOG(PSTR("FLOG: current buf_pointer: %u, size of added: %u"), sector.header.buf_pointer, size); + + memcpy(sector.byte_buffer + sector.header.buf_pointer, src, size); + sector.header.buf_pointer+=size; // this is the next free spot + // DEBUG_SENSOR_LOG(PSTR("FLOG: current buf_pointer: %u"), sector.header.buf_pointer); + } + else{ + DEBUG_SENSOR_LOG(PSTR("FLOG: save buffer to flash sector: %u"), current_sector); + DEBUG_SENSOR_LOG(PSTR("FLOG: current buf_pointer: %u"), sector.header.buf_pointer); + _saveBufferToSector(); + sectors_left++; + // but now save the data to the fresh buffer + if((FLASH_SECTOR_SIZE-sector.header.buf_pointer-sizeof(sector.header))>size){ + memcpy(sector.byte_buffer + sector.header.buf_pointer, src, size); + sector.header.buf_pointer+=size; // this is the next free spot + } + } +} + +/** + * @brief shows that it is ready to accept recording + * + * @param append - if true append to current log, else start a new log + */ +void FLOG::startRecording(bool append){ + if(recording){ + DEBUG_SENSOR_LOG(PSTR("FLOG: already recording")); + return; + } + recording = true; + DEBUG_SENSOR_LOG(PSTR("FLOG: start recording")); + _initBuffer(); + if(!found_saved_data) { + append = false; // nothing to append to, we silently start a new log + } + if(append){ + sector.header.number = _saved_header.number+1; // continue with the next number + sector.header.physical_start_sector = _saved_header.physical_start_sector; // keep the old start sector + } + else{ //new log, old data is lost + sector.header.physical_start_sector = (uint16_t)first_erased_sector; + found_saved_data = false; + sectors_left = 0; + } + } + +/** + * @brief stop recording including saving current buffer to FLASH + * + */ +void FLOG::stopRecording(void){ + _saveBufferToSector(); + _findFirstErasedSector(); + _searchSaves(); + _initBuffer(); + recording = false; + found_saved_data = true; + } + +/** + * @brief Will start a downloads, needs the correct implementation of 3 callback functions + * + * @param size: size of the data entry/record in bytes, i.e. sizeof(myStruct) + * @param sendHeader: should implement at least something like: + * @example Webserver->setContentLength(CONTENT_LENGTH_UNKNOWN); // This is very likely unknown!! + * Webserver->sendHeader(F("Content-Disposition"), F("attachment; filename=myfile.txt")); + * @param sendRecord: will receive the memory address as "uint8_t* addr" and should consume the current entry/record + * @example myStruct_t *entry = (myStruct_t*)addr; + * Then make useful Strings and send it, i.e.: Webserver->sendContent_P(myString); + * @param sendFooter: finish the download, should implement at least: + * @example Webserver->sendContent(""); + */ + void FLOG::startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter){ + + _readSector(sector.header.physical_start_sector); + uint32_t next_sector = sector.header.physical_start_sector; + bytes_left = sector.header.buf_pointer - sizeof(sector.header); + DEBUG_SENSOR_LOG(PSTR("FLOG: create file for download, will process %u bytes"), bytes_left); + running_download = true; + // Callback 1: Create the header incl. file name, content length (probably unknown!!) and additional header stuff + sendHeader(); + + while(sectors_left){ + DEBUG_SENSOR_LOG(PSTR("FLOG: next sector: %u"), next_sector); + //initially we have the first sector already loaded, so we do it at the bottom + uint32_t k = sizeof(sector.header); + while(bytes_left){ + // DEBUG_SENSOR_LOG(PSTR("FLOG: DL %u %u"), Flog->sector.byte_buffer[k],Flog->sector.byte_buffer[k+1]); + uint8_t *_record_start = (uint8_t*)§or.byte_buffer[k]; // this is basically the start address of the current record/entry of the Log + // Callback 2: send the pointer for consuming the next record/entry and doing something useful to create a file + sendRecord(_record_start); + if(k%128 == 0){ // give control to the system every x iteration, TODO: This will fail, when record/entry-size is not 8 + // DEBUG_SENSOR_LOG(PSTR("FLOG: now loop(), %u bytes left"), Flog->bytes_left); + OsWatchLoop(); + delay(TasmotaGlobal.sleep); + } + k+=size; + if(bytes_left>7){ + bytes_left-=size; + } + else{ + bytes_left = 0; + DEBUG_SENSOR_LOG(PSTR("FLOG: Flog->bytes_left not dividable by 8 ??????")); + } + } + next_sector++; + if(next_sector>num_sectors){ + next_sector = 0; + } + sectors_left--; + _readSector(next_sector); + bytes_left = sector.header.buf_pointer - sizeof(sector.header); + OsWatchLoop(); + delay(TasmotaGlobal.sleep); + } + running_download = false; + // Callback 3: create a footer or simply finish the download with an empty payload + sendFooter(); + // refresh settings for another download + _searchSaves(); + _initBuffer(); + } + + #endif // ESP8266 #endif // USE_FLOG \ No newline at end of file diff --git a/tasmota/support_float.ino b/tasmota/tasmota_support/support_float.ino similarity index 100% rename from tasmota/support_float.ino rename to tasmota/tasmota_support/support_float.ino diff --git a/tasmota/support_jpeg.ino b/tasmota/tasmota_support/support_jpeg.ino similarity index 100% rename from tasmota/support_jpeg.ino rename to tasmota/tasmota_support/support_jpeg.ino diff --git a/tasmota/support_network.ino b/tasmota/tasmota_support/support_network.ino similarity index 100% rename from tasmota/support_network.ino rename to tasmota/tasmota_support/support_network.ino diff --git a/tasmota/support_profiling.ino b/tasmota/tasmota_support/support_profiling.ino similarity index 100% rename from tasmota/support_profiling.ino rename to tasmota/tasmota_support/support_profiling.ino diff --git a/tasmota/support_pwm.ino b/tasmota/tasmota_support/support_pwm.ino similarity index 99% rename from tasmota/support_pwm.ino rename to tasmota/tasmota_support/support_pwm.ino index ba6c81347..b5ec67d72 100644 --- a/tasmota/support_pwm.ino +++ b/tasmota/tasmota_support/support_pwm.ino @@ -76,7 +76,6 @@ void PwmApplyGPIO(bool force_update_all) { // compute phase uint32_t pwm_phase = TasmotaGlobal.pwm_cur_phase[i]; // pwm_phase is the logical phase of the active pulse, ignoring inverted - uint32_t gpio_phase = pwm_phase; // gpio is the physical phase taking into account inverted if (TasmotaGlobal.pwm_phase[i] >= 0) { pwm_phase = TasmotaGlobal.pwm_phase[i]; // if explicit set explicitly, } else if (Settings->flag5.pwm_force_same_phase) { diff --git a/tasmota/support_rotary.ino b/tasmota/tasmota_support/support_rotary.ino similarity index 100% rename from tasmota/support_rotary.ino rename to tasmota/tasmota_support/support_rotary.ino diff --git a/tasmota/support_rtc.ino b/tasmota/tasmota_support/support_rtc.ino similarity index 100% rename from tasmota/support_rtc.ino rename to tasmota/tasmota_support/support_rtc.ino diff --git a/tasmota/support_statistics.ino b/tasmota/tasmota_support/support_statistics.ino similarity index 100% rename from tasmota/support_statistics.ino rename to tasmota/tasmota_support/support_statistics.ino diff --git a/tasmota/support_switch.ino b/tasmota/tasmota_support/support_switch.ino similarity index 100% rename from tasmota/support_switch.ino rename to tasmota/tasmota_support/support_switch.ino diff --git a/tasmota/support_tasmota.ino b/tasmota/tasmota_support/support_tasmota.ino similarity index 99% rename from tasmota/support_tasmota.ino rename to tasmota/tasmota_support/support_tasmota.ino index 42f573d54..a362a91e5 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/tasmota_support/support_tasmota.ino @@ -2048,10 +2048,7 @@ void GpioInit(void) #endif // ESP8266 } - if (PinUsed(GPIO_HEARTBEAT)) { - pinMode(Pin(GPIO_HEARTBEAT), OUTPUT); - digitalWrite(Pin(GPIO_HEARTBEAT), TasmotaGlobal.heartbeat_inverted); - } + DigitalWrite(GPIO_HEARTBEAT, 0, TasmotaGlobal.heartbeat_inverted); // Digital input for (uint32_t i = 0; i < MAX_SWITCHES; i++) { @@ -2106,10 +2103,8 @@ void GpioInit(void) for (uint32_t i = 0; i < MAX_RELAYS; i++) { if (PinUsed(GPIO_REL1, i)) { TasmotaGlobal.devices_present++; - pinMode(Pin(GPIO_REL1, i), OUTPUT); #ifdef ESP8266 if (EXS_RELAY == TasmotaGlobal.module_type) { - digitalWrite(Pin(GPIO_REL1, i), bitRead(TasmotaGlobal.rel_inverted, i) ? 1 : 0); if (i &1) { TasmotaGlobal.devices_present--; } } #endif // ESP8266 @@ -2124,17 +2119,13 @@ void GpioInit(void) } else { #endif TasmotaGlobal.leds_present++; - pinMode(Pin(GPIO_LED1, i), OUTPUT); - digitalWrite(Pin(GPIO_LED1, i), bitRead(TasmotaGlobal.led_inverted, i)); + DigitalWrite(GPIO_LED1, i, bitRead(TasmotaGlobal.led_inverted, i)); #ifdef USE_ARILUX_RF } #endif } } - if (PinUsed(GPIO_LEDLNK)) { - pinMode(Pin(GPIO_LEDLNK), OUTPUT); - digitalWrite(Pin(GPIO_LEDLNK), TasmotaGlobal.ledlnk_inverted); - } + DigitalWrite(GPIO_LEDLNK, 0, TasmotaGlobal.ledlnk_inverted); #ifdef USE_PWM_DIMMER if (PWM_DIMMER == TasmotaGlobal.module_type && PinUsed(GPIO_REL1)) { TasmotaGlobal.devices_present--; } diff --git a/tasmota/support_udp.ino b/tasmota/tasmota_support/support_udp.ino similarity index 100% rename from tasmota/support_udp.ino rename to tasmota/tasmota_support/support_udp.ino diff --git a/tasmota/support_wifi.ino b/tasmota/tasmota_support/support_wifi.ino similarity index 100% rename from tasmota/support_wifi.ino rename to tasmota/tasmota_support/support_wifi.ino diff --git a/tasmota/tasmota_ca.ino b/tasmota/tasmota_support/tasmota_ca.ino similarity index 98% rename from tasmota/tasmota_ca.ino rename to tasmota/tasmota_support/tasmota_ca.ino index 007685863..03091aa3e 100644 --- a/tasmota/tasmota_ca.ino +++ b/tasmota/tasmota_support/tasmota_ca.ino @@ -20,17 +20,17 @@ // // Certificates are stored in flash (PROGMEM) to avoid consuming valuable RAM. // -// To save space in flash, the Let's Encrypt and Amazon AWS certificates may be -// individually omitted if TLS is enabled, but the certificates are not used. -// This is typically the case when a locally generated root certificate is used +// To save space in flash, the Let's Encrypt and Amazon AWS certificates may be +// individually omitted if TLS is enabled, but the certificates are not used. +// This is typically the case when a locally generated root certificate is used // for TLS authentication. -// -// To omit these certificates, define one or both of the +// +// To omit these certificates, define one or both of the // OMIT_LETS_ENCRYPT_CERT and/or OMIT_AWS_CERT macros in user_config_override.h. // // To include a locally generated root certificate, define the // INCLUDE_LOCAL_CERT macro in user_config_override.h. -// +// // See the files tasmota/local_ca_data_sample.h and tasmota/local_ca_descriptor_sample.h // in the Tasmota source for instructions for generating them from a local root // certificate in .crt format. @@ -145,7 +145,7 @@ static const unsigned char PROGMEM AmazonRootCA1_RSA_E[] = { #endif #if defined(INCLUDE_LOCAL_CERT) -#include +#include #endif // // ========== cumulative CA ================= @@ -189,7 +189,7 @@ const br_x509_trust_anchor PROGMEM Tasmota_TA[] = { #if defined(INCLUDE_LOCAL_CERT) -#include +#include #endif }; diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_01_webserver.ino similarity index 99% rename from tasmota/xdrv_01_webserver.ino rename to tasmota/tasmota_xdrv_driver/xdrv_01_webserver.ino index 55e98e862..6fdbf7e64 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_01_webserver.ino @@ -893,7 +893,7 @@ void WSContentSendStyle_P(const char* formatP, ...) { WebColor(COL_TEXT_WARNING), #endif WebColor(COL_TITLE), - (Web.initial_config) ? "" : ModuleName().c_str(), SettingsText(SET_DEVICENAME)); + (Web.initial_config) ? "" : (Settings->flag5.gui_module_name) ? "" : ModuleName().c_str(), SettingsText(SET_DEVICENAME)); // SetOption53 - Show hostname and IP address in GUI main menu #if (RESTART_AFTER_INITIAL_WIFI_CONFIG) @@ -2514,8 +2514,11 @@ void HandleInformation(void) } char running[2] = { 0 }; if (part->subtype == cur_part) { running[0] = '*'; } - uint32_t part_used = ((prog_size / 1024) * 100) / part_size; - WSContentSend_PD(PSTR("}1" D_PARTITION " %s%s}2%d KB (" D_USED " %d%%)"), part->label, running, part_size, part_used); + WSContentSend_PD(PSTR("}1" D_PARTITION " %s%s}2%d KB"), part->label, running, part_size); + if (prog_size) { + uint32_t part_used = ((prog_size / 1024) * 100) / part_size; + WSContentSend_PD(PSTR(" (" D_USED " %d%%)"), part_used); + } } if ((ESP_PARTITION_TYPE_DATA == part->type) && (ESP_PARTITION_SUBTYPE_DATA_SPIFFS == part->subtype)) { WSContentSend_PD(PSTR("}1" D_PARTITION " fs}2%d KB"), part_size); @@ -3794,7 +3797,7 @@ bool Xdrv01(uint8_t function) } Web.wifi_test_AP_TIMEOUT = true; } - int n = WiFi.scanNetworks(); // restart scan + WiFi.scanNetworks(); // restart scan } } break; diff --git a/tasmota/xdrv_02_1_mqtt_file.ino b/tasmota/tasmota_xdrv_driver/xdrv_02_1_mqtt_file.ino similarity index 100% rename from tasmota/xdrv_02_1_mqtt_file.ino rename to tasmota/tasmota_xdrv_driver/xdrv_02_1_mqtt_file.ino diff --git a/tasmota/xdrv_02_9_mqtt.ino b/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino similarity index 100% rename from tasmota/xdrv_02_9_mqtt.ino rename to tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino diff --git a/tasmota/xdrv_03_energy.ino b/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino similarity index 100% rename from tasmota/xdrv_03_energy.ino rename to tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino diff --git a/tasmota/xdrv_04_light.ino b/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino similarity index 99% rename from tasmota/xdrv_04_light.ino rename to tasmota/tasmota_xdrv_driver/xdrv_04_light.ino index 4a11cabf6..dc4b027b5 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino @@ -2193,12 +2193,15 @@ void LightSetOutputs(const uint16_t *cur_col_10) { char *tmp_data = XdrvMailbox.data; char *tmp_topic = XdrvMailbox.topic; + char *tmp_command = XdrvMailbox.command; XdrvMailbox.data = (char*)cur_col; XdrvMailbox.topic = (char*)scale_col; + XdrvMailbox.command = (char*)cur_col_10; if (XlgtCall(FUNC_SET_CHANNELS)) { /* Serviced */ } else if (XdrvCall(FUNC_SET_CHANNELS)) { /* Serviced */ } XdrvMailbox.data = tmp_data; XdrvMailbox.topic = tmp_topic; + XdrvMailbox.command = tmp_command; } // Just apply basic Gamma to each channel @@ -2344,7 +2347,7 @@ bool calcGammaBulbs(uint16_t cur_col_10[5]) { calcGammaBulb5Channels_8(*pivot, from10); calcGammaBulb5Channels_8(*(pivot+1), to10); - vct_pivot_t *pivot1 = pivot + 1; + // vct_pivot_t *pivot1 = pivot + 1; // AddLog(LOG_LEVEL_INFO, PSTR("+++ from_ct %d, to_ct %d [%03X,%03X,%03X,%03X,%03X] - [%03X,%03X,%03X,%03X,%03X]"), // *from_ct, *(from_ct+1), (*pivot)[0], (*pivot)[1], (*pivot)[2], (*pivot)[3], (*pivot)[4], // (*pivot1)[0], (*pivot1)[1], (*pivot1)[2], (*pivot1)[3], (*pivot1)[4]); diff --git a/tasmota/xdrv_04_light_utils.ino b/tasmota/tasmota_xdrv_driver/xdrv_04_light_utils.ino similarity index 100% rename from tasmota/xdrv_04_light_utils.ino rename to tasmota/tasmota_xdrv_driver/xdrv_04_light_utils.ino diff --git a/tasmota/xdrv_05_irremote.ino b/tasmota/tasmota_xdrv_driver/xdrv_05_irremote.ino similarity index 98% rename from tasmota/xdrv_05_irremote.ino rename to tasmota/tasmota_xdrv_driver/xdrv_05_irremote.ino index 6ba461aac..1ac9e5cbd 100644 --- a/tasmota/xdrv_05_irremote.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_05_irremote.ino @@ -76,7 +76,8 @@ const char kIrRemoteCommands[] PROGMEM = "|" D_CMND_IRSEND ; void (* const IrRemoteCommand[])(void) PROGMEM = { &CmndIrSend }; -char* ulltoa(unsigned long long value, char *str, int radix) +// 20220531 renamed as newer arduino core now also has this function +char* ir_ulltoa(unsigned long long value, char *str, int radix) { char digits[64]; char *dst = str; @@ -98,7 +99,7 @@ char* ulltoa(unsigned long long value, char *str, int radix) char* Uint64toHex(uint64_t value, char *str, uint16_t bits) { - ulltoa(value, str, 16); // Get 64bit value + ir_ulltoa(value, str, 16); // Get 64bit value int fill = 8; if ((bits > 3) && (bits < 65)) { @@ -251,7 +252,7 @@ void IrReceiveCheck(void) char svalue[64]; if (Settings->flag.ir_receive_decimal) { // SetOption29 - IR receive data format - ulltoa(results.value, svalue, 10); + ir_ulltoa(results.value, svalue, 10); } else { snprintf_P(svalue, sizeof(svalue), PSTR("\"0x%s\""), hvalue); } diff --git a/tasmota/xdrv_05_irremote_full.ino b/tasmota/tasmota_xdrv_driver/xdrv_05_irremote_full.ino similarity index 100% rename from tasmota/xdrv_05_irremote_full.ino rename to tasmota/tasmota_xdrv_driver/xdrv_05_irremote_full.ino diff --git a/tasmota/xdrv_06_snfbridge.ino b/tasmota/tasmota_xdrv_driver/xdrv_06_snfbridge.ino similarity index 100% rename from tasmota/xdrv_06_snfbridge.ino rename to tasmota/tasmota_xdrv_driver/xdrv_06_snfbridge.ino diff --git a/tasmota/xdrv_07_domoticz.ino b/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino similarity index 81% rename from tasmota/xdrv_07_domoticz.ino rename to tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino index b469ef1d5..7687ac644 100644 --- a/tasmota/xdrv_07_domoticz.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino @@ -179,14 +179,25 @@ void DomoticzMqttSubscribe(void) { for (uint32_t i = 0; i < maxdev; i++) { if (Settings->domoticz_relay_idx[i]) { domoticz_subscribe = true; + char stopic[TOPSZ]; + snprintf_P(stopic, sizeof(stopic), PSTR(DOMOTICZ_OUT_TOPIC "/#")); // domoticz topic + MqttSubscribe(stopic); + return; } } +} - if (domoticz_subscribe) { - char stopic[TOPSZ]; - snprintf_P(stopic, sizeof(stopic), PSTR(DOMOTICZ_OUT_TOPIC "/#")); // domoticz topic - MqttSubscribe(stopic); +int32_t DomoticzIdx2Relay(uint32_t idx) { + if (0 == idx) { + return -1; // Idx not mine } + uint32_t maxdev = (TasmotaGlobal.devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : TasmotaGlobal.devices_present; + for (uint32_t i = 0; i < maxdev; i++) { + if (idx == Settings->domoticz_relay_idx[i]) { + return i; + } + } + return -1; // Idx not mine } bool DomoticzMqttData(void) { @@ -202,123 +213,123 @@ bool DomoticzMqttData(void) { return false; // Process unchanged data } - // topic is domoticz/out so try to analyse + // topic is domoticz/out so check if valid data could be available if (XdrvMailbox.data_len < 20) { return true; // No valid data } + int32_t relay_index = -1; + + // Quick check if this is mine using topic domoticz/out/{$idx} + if (strlen(XdrvMailbox.topic) > strlen(DOMOTICZ_OUT_TOPIC)) { + char* topic_index = &XdrvMailbox.topic[strlen(DOMOTICZ_OUT_TOPIC) +1]; + relay_index = DomoticzIdx2Relay(atoi(topic_index)); + if (relay_index < 0) { + return true; // Idx not mine + } + } + String domoticz_data = XdrvMailbox.data; // Copy the string into a new buffer that will be modified JsonParser parser((char*)domoticz_data.c_str()); JsonParserObject domoticz = parser.getRootObject(); if (!domoticz) { return true; // To much or invalid data } -// if (strcmp_P(domoticz["dtype"],PSTR("Light/Switch"))) { -// return true; -// } - uint32_t idx = domoticz.getUInt(PSTR("idx"), 0); - int16_t nvalue = domoticz.getInt(PSTR("nvalue"), -1); - - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), idx, nvalue); - - bool found = false; - if ((idx > 0) && (nvalue >= 0) && (nvalue <= 15)) { - uint8_t maxdev = (TasmotaGlobal.devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : TasmotaGlobal.devices_present; - for (uint32_t i = 0; i < maxdev; i++) { - if (idx == Settings->domoticz_relay_idx[i]) { - bool iscolordimmer = strcmp_P(domoticz.getStr(PSTR("dtype")), PSTR("Color Switch")) == 0; - bool isShutter = strcmp_P(domoticz.getStr(PSTR("dtype")), PSTR("Light/Switch")) == 0 & strncmp_P(domoticz.getStr(PSTR("switchType")),PSTR("Blinds"), 6) == 0; - - char stemp1[10]; - snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan() && (1 == i)) { // Idx 2 is fanspeed - JsonParserToken svalue_tok = domoticz[PSTR("svalue1")]; - if (!svalue_tok) { - return true; - } - uint8_t svalue = svalue_tok.getUInt(); - svalue = (2 == nvalue) ? svalue / 10 : 0; - if (GetFanspeed() == svalue) { - return true; // Stop loop as already set - } - if (TimePassedSince(domoticz_fan_debounce) < 1000) { - return true; // Stop loop if device in limbo - } - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_FANSPEED)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), svalue); - found = true; - } else -#endif // USE_SONOFF_IFAN -#ifdef USE_SHUTTER - if (isShutter) { - uint8_t position = domoticz.getUInt(PSTR("svalue1"), 0); - if (nvalue != 2) { - position = (0 == nvalue) ? 0 : 100; - } - - snprintf_P(XdrvMailbox.topic, TOPSZ, PSTR("/" D_PRFX_SHUTTER D_CMND_SHUTTER_POSITION)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), position); - XdrvMailbox.data_len = position > 99 ? 3 : (position > 9 ? 2 : 1); - - found = true; - } else -#endif // USE_SHUTTER -#ifdef USE_LIGHT - if (iscolordimmer && 10 == nvalue) { // Color_SetColor - // https://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s#Set_a_light_to_a_certain_color_or_color_temperature - JsonParserObject color = domoticz[PSTR("Color")].getObject(); - // JsonObject& color = domoticz["Color"]; - uint16_t level = nvalue = domoticz.getUInt(PSTR("svalue1"), 0); - uint16_t r = color.getUInt(PSTR("r"), 0) * level / 100; - uint16_t g = color.getUInt(PSTR("g"), 0) * level / 100; - uint16_t b = color.getUInt(PSTR("b"), 0) * level / 100; - uint16_t cw = color.getUInt(PSTR("cw"), 0) * level / 100; - uint16_t ww = color.getUInt(PSTR("ww"), 0) * level / 100; - uint16_t m = color.getUInt(PSTR("m"), 0); - uint16_t t = color.getUInt(PSTR("t"), 0); - if (2 == m) { // White with color temperature. Valid fields: t - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_BACKLOG)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR(D_CMND_COLORTEMPERATURE " %d;" D_CMND_DIMMER " %d"), changeUIntScale(t, 0, 255, CT_MIN, CT_MAX), level); - } else { - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_COLOR)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%02x%02x%02x%02x%02x"), r, g, b, cw, ww); - } - found = true; - } - else if ((!iscolordimmer && 2 == nvalue) || // gswitch_sSetLevel - (iscolordimmer && 15 == nvalue)) { // Color_SetBrightnessLevel - if (domoticz[PSTR("svalue1")]) { - nvalue = domoticz.getUInt(PSTR("svalue1"), 0); - } else { - return true; // Invalid data - } - if (TasmotaGlobal.light_type && (Settings->light_dimmer == nvalue) && ((TasmotaGlobal.power >> i) &1)) { - return true; // State already set - } - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); - found = true; - } else -#endif // USE_LIGHT - if (1 == nvalue || 0 == nvalue) { - if (((TasmotaGlobal.power >> i) &1) == (power_t)nvalue) { - return true; // Stop loop - } - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (TasmotaGlobal.devices_present > 1) ? stemp1 : ""); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); - found = true; - } - break; - } + if (relay_index < 0) { + relay_index = DomoticzIdx2Relay(domoticz.getUInt(PSTR("idx"), 0)); + if (relay_index < 0) { + return true; // Idx not mine } } - if (!found) { return true; } // No command received + int32_t nvalue = domoticz.getInt(PSTR("nvalue"), -1); + if ((nvalue < 0) || (nvalue > 16)) { + return true; // Nvalue out of boundaries + } + + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), Settings->domoticz_relay_idx[relay_index], nvalue); + + bool iscolordimmer = (strcmp_P(domoticz.getStr(PSTR("dtype")), PSTR("Color Switch")) == 0); + bool isShutter = (strcmp_P(domoticz.getStr(PSTR("dtype")), PSTR("Light/Switch")) == 0) && (strncmp_P(domoticz.getStr(PSTR("switchType")),PSTR("Blinds"), 6) == 0); + +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan() && (1 == relay_index)) { // Idx 2 is fanspeed + JsonParserToken svalue_tok = domoticz[PSTR("svalue1")]; + if (!svalue_tok) { + return true; + } + uint32_t svalue = svalue_tok.getUInt(); + svalue = (2 == nvalue) ? svalue / 10 : 0; + if (GetFanspeed() == svalue) { + return true; // Stop as already set + } + if (TimePassedSince(domoticz_fan_debounce) < 1000) { + return true; // Stop if device in limbo + } + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_FANSPEED)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), svalue); + } else +#endif // USE_SONOFF_IFAN +#ifdef USE_SHUTTER + if (isShutter) { + uint32_t position = domoticz.getUInt(PSTR("svalue1"), 0); + if (nvalue != 2) { + position = (0 == nvalue) ? 0 : 100; + } + snprintf_P(XdrvMailbox.topic, TOPSZ, PSTR("/" D_PRFX_SHUTTER D_CMND_SHUTTER_POSITION)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), position); + XdrvMailbox.data_len = position > 99 ? 3 : (position > 9 ? 2 : 1); + } else +#endif // USE_SHUTTER +#ifdef USE_LIGHT + if (iscolordimmer && 10 == nvalue) { // Color_SetColor + // https://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s#Set_a_light_to_a_certain_color_or_color_temperature + JsonParserObject color = domoticz[PSTR("Color")].getObject(); + // JsonObject& color = domoticz["Color"]; + uint32_t level = nvalue = domoticz.getUInt(PSTR("svalue1"), 0); + uint32_t r = color.getUInt(PSTR("r"), 0) * level / 100; + uint32_t g = color.getUInt(PSTR("g"), 0) * level / 100; + uint32_t b = color.getUInt(PSTR("b"), 0) * level / 100; + uint32_t cw = color.getUInt(PSTR("cw"), 0) * level / 100; + uint32_t ww = color.getUInt(PSTR("ww"), 0) * level / 100; + uint32_t m = color.getUInt(PSTR("m"), 0); + uint32_t t = color.getUInt(PSTR("t"), 0); + if (2 == m) { // White with color temperature. Valid fields: t + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_BACKLOG)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR(D_CMND_COLORTEMPERATURE " %d;" D_CMND_DIMMER " %d"), changeUIntScale(t, 0, 255, CT_MIN, CT_MAX), level); + } else { + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_COLOR)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%02x%02x%02x%02x%02x"), r, g, b, cw, ww); + } + } + else if ((!iscolordimmer && 2 == nvalue) || // gswitch_sSetLevel + (iscolordimmer && 15 == nvalue)) { // Color_SetBrightnessLevel + if (domoticz[PSTR("svalue1")]) { + nvalue = domoticz.getUInt(PSTR("svalue1"), 0); + } else { + return true; // Invalid data + } + if (TasmotaGlobal.light_type && (Settings->light_dimmer == nvalue) && ((TasmotaGlobal.power >> relay_index) &1)) { + return true; // State already set + } + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); + } else +#endif // USE_LIGHT + if (1 == nvalue || 0 == nvalue) { + if (((TasmotaGlobal.power >> relay_index) &1) == (power_t)nvalue) { + return true; // Stop loop + } + char stemp1[10]; + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (TasmotaGlobal.devices_present > 1) ? itoa(relay_index +1, stemp1, 10) : ""); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); + } else { + return true; // No command received + } AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ D_RECEIVED_TOPIC " %s, " D_DATA " %s"), XdrvMailbox.topic, XdrvMailbox.data); domoticz_update_flag = false; - return false; // Process new data + return false; // Process new data } /*********************************************************************************************/ diff --git a/tasmota/xdrv_08_serial_bridge.ino b/tasmota/tasmota_xdrv_driver/xdrv_08_serial_bridge.ino similarity index 100% rename from tasmota/xdrv_08_serial_bridge.ino rename to tasmota/tasmota_xdrv_driver/xdrv_08_serial_bridge.ino diff --git a/tasmota/xdrv_09_timers.ino b/tasmota/tasmota_xdrv_driver/xdrv_09_timers.ino similarity index 100% rename from tasmota/xdrv_09_timers.ino rename to tasmota/tasmota_xdrv_driver/xdrv_09_timers.ino diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino similarity index 99% rename from tasmota/xdrv_10_rules.ino rename to tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino index c630676a1..3aeb88b76 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino @@ -1868,7 +1868,6 @@ bool findNextLogicObjectValue(char * &pointer, bool &value) */ bool evaluateLogicalExpression(const char * expression, int len) { - bool bResult = false; //Make a copy first char expbuff[len + 1]; memcpy(expbuff, expression, len); diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino old mode 100755 new mode 100644 similarity index 94% rename from tasmota/xdrv_10_scripter.ino rename to tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino index dd677e18e..49b177fe0 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino @@ -74,6 +74,7 @@ keywords if then else endif, or, and are better readable for beginners (others m uint32_t EncodeLightId(uint8_t relay_id); uint32_t DecodeLightId(uint32_t hue_id); char *web_send_line(char mc, char *lp); +int32_t web_send_file(char mc, char *file); #define SPECIAL_EEPMODE_SIZE 6200 @@ -451,7 +452,7 @@ struct SCRIPT_MEM { char *fast_script = 0; char *event_script = 0; char *html_script = 0; - char *web_pages[7]; + char *web_pages[10]; uint32_t script_lastmillis; bool event_handeled = false; #ifdef USE_BUTTON_EVENT @@ -1241,16 +1242,17 @@ float *Get_MFAddr(uint8_t index, uint16_t *len, uint16_t *ipos) { char *isvar(char *lp, uint8_t *vtype, struct T_INDEX *tind, float *fp, char *sp, struct GVARS *gv); -char *get_array_by_name(char *lp, float **fp, uint16_t *alen) { +char *get_array_by_name(char *lp, float **fp, uint16_t *alen, uint16_t *ipos) { struct T_INDEX ind; uint8_t vtype; + while (*lp == ' ') lp++; lp = isvar(lp, &vtype, &ind, 0, 0, 0); if (vtype==VAR_NV) return 0; if (vtype&STYPE) return 0; uint16_t index = glob_script_mem.type[ind.index].index; if (glob_script_mem.type[ind.index].bits.is_filter) { - float *fa = Get_MFAddr(index, alen, 0); + float *fa = Get_MFAddr(index, alen, ipos); *fp = fa; return lp; } @@ -2023,6 +2025,10 @@ char *isvar(char *lp, uint8_t *vtype, struct T_INDEX *tind, float *fp, char *sp, iob = '\n'; } else if (*lp == 'r') { iob = '\r'; + } else if (*lp == '0' && *(lp+1) == 'x') { + lp += 2; + iob = strtol(lp, 0, 16); + lp++; } else if (*lp == '\\') { iob = '\\'; } else { @@ -2295,11 +2301,11 @@ chknext: uint16_t alend; fvar = -1; float *fpd; - lp = get_array_by_name(lp, &fpd, &alend); + lp = get_array_by_name(lp, &fpd, &alend, 0); SCRIPT_SKIP_SPACES uint16_t alens; float *fps; - lp = get_array_by_name(lp, &fps, &alens); + lp = get_array_by_name(lp, &fps, &alens, 0); SCRIPT_SKIP_SPACES if (alens < alend) { alend = alens; @@ -2308,6 +2314,35 @@ chknext: fvar = alend; goto nfuncexit; } + + if (!strncmp(lp, "af(", 3)) { + // array to float + uint16_t alend; + float *fpd; + lp = get_array_by_name(lp + 3, &fpd, &alend, 0); + SCRIPT_SKIP_SPACES + if (*lp != ')') { + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); + uint16_t offset = 0; + offset = fvar; + if (offset > (alend - 4)) { + offset = alend - 4; + } + fpd += offset; + } + if (fpd) { + uint8_t fbytes[4]; + fbytes[0] = *fpd++; + fbytes[1] = *fpd++; + fbytes[2] = *fpd++; + fbytes[3] = *fpd++; + fpd = (float*)fbytes; + fvar = *fpd; + } else { + fvar = 0; + } + goto nfuncexit; + } break; case 'b': @@ -2906,7 +2941,7 @@ chknext: uint8_t index = 0; while (index < MAX_EXT_ARRAYS) { - lp = get_array_by_name(lp, &a_ptr[index], &a_len[index]); + lp = get_array_by_name(lp, &a_ptr[index], &a_len[index], 0); SCRIPT_SKIP_SPACES index++; if (*lp == ')' || *lp == '\n') { @@ -2952,7 +2987,7 @@ chknext: if (!strncmp(lp, "fwa(", 4)) { uint16_t alen; float *fa; - lp = get_array_by_name(lp + 4, &fa, &alen); + lp = get_array_by_name(lp + 4, &fa, &alen, 0); if (!fa) { fvar = 0; goto exit; @@ -2993,7 +3028,7 @@ chknext: if (!strncmp(lp, "fra(", 4)) { uint16_t alen; float *fa; - lp = get_array_by_name(lp + 4, &fa, &alen); + lp = get_array_by_name(lp + 4, &fa, &alen, 0); if (!fa) { fvar = 0; goto exit; @@ -3370,6 +3405,20 @@ chknext: #endif // USE_SCRIPT_I2C break; +#ifdef USE_KNX + case 'k': + if (!strncmp(lp, "knx(", 4)) { + float type; + lp = GetNumericArgument(lp + 4, OPER_EQU, &type, gv); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &fvar, gv); + SCRIPT_SKIP_SPACES + KnxSensor(type, fvar); + goto nfuncexit; + } + break; +#endif + case 'l': if (!strncmp(lp, "lip", 3)) { if (sp) strlcpy(sp, (const char*)WiFi.localIP().toString().c_str(), glob_script_mem.max_ssize); @@ -3945,7 +3994,7 @@ extern char *SML_GetSVal(uint32_t index); if (*lp!=')') { lp = GetNumericArgument(lp, OPER_EQU, &rxbsiz, gv); } - fvar= -1; + fvar = -1; if (glob_script_mem.sp) { fvar == -1; } else { @@ -4058,17 +4107,84 @@ extern char *SML_GetSVal(uint32_t index); len = 0; goto exit; } + // serial write array + if (!strncmp(lp, "swa(", 4)) { + fvar = -1; + if (glob_script_mem.sp) { + uint8_t modbus_buffer[64]; + uint16_t alen; + float *array; + lp = get_array_by_name(lp + 4, &array, &alen, 0); + SCRIPT_SKIP_SPACES + if (!array) { + goto exit; + } + float len; + lp = GetNumericArgument(lp, OPER_EQU, &len, 0); + SCRIPT_SKIP_SPACES + if (len > alen) len = alen; + if (len < 1) len = 1; + if (*lp != ')') { + float opts = 0; + lp = GetNumericArgument(lp, OPER_EQU, &opts, 0); + SCRIPT_SKIP_SPACES + // calc modbus checksum +#ifdef USE_SML_M + // calc modbus checksum + if (len > sizeof(modbus_buffer)) len = sizeof(modbus_buffer); + for (uint32_t cnt = 0; cnt < len; cnt++) { + modbus_buffer[cnt] = *array++; + } + uint16_t crc = 0xffff; + uint8_t *mbp = modbus_buffer; + if (opts == 1) { + mbp++; + crc = 0; + } + crc = MBUS_calculateCRC(mbp, mbp[2] + 3, crc); + if (opts == 1) { + mbp[mbp[2] + 3] = highByte(crc); + mbp[mbp[2] + 4] = lowByte(crc); + } else { + mbp[mbp[2] + 3] = lowByte(crc); + mbp[mbp[2] + 4] = highByte(crc); + } +#endif + uint8_t *ucp = modbus_buffer; + while (len) { + glob_script_mem.sp->write(*ucp); + //AddLog(LOG_LEVEL_INFO,PSTR(">> %02x"),*ucp); + ucp++; + len--; + } + } else { + while (len) { + glob_script_mem.sp->write((uint8_t)*array++); + len--; + } + } + } + goto nfuncexit; + } // serial read array if (!strncmp(lp, "sra(", 4)) { fvar = -1; if (glob_script_mem.sp) { uint16_t alen; - float *array; - lp = get_array_by_name(lp + 4, &array, &alen); + float *array = 0; + lp = get_array_by_name(lp + 4, &array, &alen, 0); + SCRIPT_SKIP_SPACES if (!array) { goto exit; } - uint16_t index; + float opts = -1; + if (*lp != ')') { + lp = GetNumericArgument(lp, OPER_EQU, &opts, 0); + SCRIPT_SKIP_SPACES + // calc modbus checksum + } + + uint16_t index = 0; for (index = 0; index < alen; index++) { if (!glob_script_mem.sp->available()) { break; @@ -4077,21 +4193,34 @@ extern char *SML_GetSVal(uint32_t index); } fvar = index; #ifdef USE_SML_M - if (index == 8) { - uint8_t modbus_response[10]; - for (uint8_t cnt = 0; cnt < 8; cnt++) { - modbus_response[cnt] = array[cnt]; - } - uint16_t crc = MBUS_calculateCRC(modbus_response, 6); - if ( (lowByte(crc) != modbus_response[6]) || (highByte(crc) != modbus_response[7]) ) { - fvar = -2; + if (index == 8 || opts >= 0) { + uint8_t *modbus_response = (uint8_t*)special_malloc(alen); + if (modbus_response) { + for (uint8_t cnt = 0; cnt < alen; cnt++) { + modbus_response[cnt] = array[cnt]; + } + uint16_t crc = 0xffff; + uint8_t *mbp = modbus_response; + if (opts == 1) { + mbp++; + crc = 0; + } + crc = MBUS_calculateCRC(mbp, mbp[2] + 3, crc); + if (opts == 1) { + if ((mbp[mbp[2] + 3] != highByte(crc)) || (mbp[mbp[2] + 4] != lowByte(crc))) { + fvar = -2; + } + } else { + if ((mbp[mbp[2] + 3] != lowByte(crc)) || (mbp[mbp[2] + 4] != highByte(crc))) { + fvar = -2; + } + } + free(modbus_response); } } #endif } - lp++; - len = 0; - goto exit; + goto nfuncexit; } #ifdef USE_SML_M // serial modbus write float, 010404ffffffffxxxx @@ -4104,52 +4233,95 @@ extern char *SML_GetSVal(uint32_t index); float mode; lp = GetNumericArgument(lp, OPER_EQU, &mode, 0); SCRIPT_SKIP_SPACES - float mval; - lp = GetNumericArgument(lp, OPER_EQU, &mval, 0); + + uint16_t alend; + float *fpd; + lp = get_array_by_name(lp, &fpd, &alend, 0); SCRIPT_SKIP_SPACES - uint32_t uval, *uvp; - uvp = &uval; - *(uvp) = *(uint32_t*)&mval; - uint8_t modbus_response[10]; + float nvals; + lp = GetNumericArgument(lp, OPER_EQU, &nvals, 0); + SCRIPT_SKIP_SPACES - uint32_t ui32 = mval; - modbus_response[0] = addr; - modbus_response[1] = 4; - switch ((uint8_t)mode) { - case 0: - // UINT16 - modbus_response[2] = 2; - modbus_response[3] = (ui32 >> 16); - modbus_response[4] = (ui32 >> 0); - break; - case 1: - // UINT32 - modbus_response[2] = 4; - modbus_response[3] = (ui32 >> 24); - modbus_response[4] = (ui32 >> 16); - modbus_response[5] = (ui32 >> 8); - modbus_response[6] = (ui32 >> 0); - break; - - default: - // float - modbus_response[2] = 4; - modbus_response[3] = (uval >> 24); - modbus_response[4] = (uval >> 16); - modbus_response[5] = (uval >> 8); - modbus_response[6] = (uval >> 0); - break; + if (nvals > alend) { + nvals = alend; } + uint8_t modbus_response[128]; - // calc mobus checksum - uint16_t crc = MBUS_calculateCRC(modbus_response, modbus_response[2] + 3); + uint8_t mb_index = 0; + modbus_response[mb_index] = addr; + mb_index++; + modbus_response[mb_index] = 4; + mb_index++; + + if (mode == 0) { + modbus_response[mb_index] = 2 * nvals; + } else { + modbus_response[mb_index] = 4 * nvals; + } + mb_index++; + + for (uint16_t cnt = 0; cnt < nvals; cnt++) { + float fpval = *fpd++; + uint32_t ui32 = fpval; + uint32_t uval, *uvp; + uvp = &uval; + *(uvp) = *(uint32_t*)&fpval; + + switch ((uint8_t)mode) { + case 0: + // UINT16 + modbus_response[mb_index] = (ui32 >> 16); + mb_index++; + modbus_response[mb_index] = (ui32 >> 0); + mb_index++; + break; + case 1: + // UINT32 + modbus_response[mb_index] = (ui32 >> 24); + mb_index++; + modbus_response[mb_index] = (ui32 >> 16); + mb_index++; + modbus_response[mb_index] = (ui32 >> 8); + mb_index++; + modbus_response[mb_index] = (ui32 >> 0); + mb_index++; + break; + default: + // float + modbus_response[mb_index] = (uval >> 24); + mb_index++; + modbus_response[mb_index] = (uval >> 16); + mb_index++; + modbus_response[mb_index] = (uval >> 8); + mb_index++; + modbus_response[mb_index] = (uval >> 0); + mb_index++; + break; + } + } + + // calc modbus checksum + uint16_t crc = MBUS_calculateCRC(modbus_response, modbus_response[2] + 3, 0xFFFF); modbus_response[modbus_response[2] + 3] = lowByte(crc); modbus_response[modbus_response[2] + 4] = highByte(crc); - glob_script_mem.sp->write(modbus_response, 9); + glob_script_mem.sp->write(modbus_response, mb_index + 2); fvar = 0; - +#if 0 + // show response + char hexbuff[256]; + sprintf(hexbuff,"%02x%02x%02x - ",modbus_response[0],modbus_response[1],modbus_response[2]); + for (uint16_t cnt = 3; cnt < mb_index; cnt+=4) { + char cbuff[32]; + sprintf(cbuff," %02x%02x%02x%02x",modbus_response[cnt],modbus_response[cnt+1],modbus_response[cnt+2],modbus_response[cnt+3]); + strcat(hexbuff,cbuff); + } + char cbuff[32]; + sprintf(cbuff," - %02x%02x",modbus_response[mb_index],modbus_response[mb_index+1]); + strcat(hexbuff,cbuff); + AddLog(LOG_LEVEL_INFO,PSTR(">> %s"),hexbuff); +#endif } lp++; len = 0; @@ -4223,7 +4395,7 @@ extern char *SML_GetSVal(uint32_t index); case 1: // set cs lp = GetNumericArgument(lp , OPER_EQU, &fvar, 0); - index = fvar; + index = fvar - 1; index &= 3; lp = GetNumericArgument(lp , OPER_EQU, &fvar, 0); glob_script_mem.spi.cs[index] = fvar; @@ -4237,11 +4409,23 @@ extern char *SML_GetSVal(uint32_t index); case 2: // transfer bytes lp = GetNumericArgument(lp , OPER_EQU, &fvar, 0); - uint8_t index = fvar; + int8_t index = fvar - 1; + + float *fpd = 0; + uint16_t alend; + lp = get_array_by_name(lp, &fpd, &alend, 0); + + // len + float len = alend; + lp = GetNumericArgument(lp , OPER_EQU, &len, 0); + if (len > alend) { + len = alend; + } + + // type lp = GetNumericArgument(lp , OPER_EQU, &fvar, 0); - uint32_t val = fvar; - lp = GetNumericArgument(lp , OPER_EQU, &fvar, 0); - script_sspi_trans(index & 3, val, fvar); + + script_sspi_trans(index, fpd, len, fvar); break; } len = 0; @@ -4477,6 +4661,16 @@ extern char *SML_GetSVal(uint32_t index); fvar = WcSetMotionDetect(fvar2); } break; + /* +#ifdef USE_FACE_DETECT + case 7: + { float fvar2; + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, gv); + fvar = WcSetFaceDetect(fvar2); + } + break; +#endif //USE_FACE_DETECT +*/ default: fvar = 0; } @@ -5827,22 +6021,22 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) { } #ifdef USE_SCRIPT_WEB_DISPLAY else if (!strncmp(lp, "wcs", 3)) { - lp+=4; + lp += 4; // skip one space after cmd web_send_line(0, lp); - /* - char tmp[256]; - Replace_Cmd_Vars(lp ,1 , tmp, sizeof(tmp)); WSContentFlush(); - WSContentSend_P(PSTR("%s"),tmp); - */ - + goto next_line; + } + else if (!strncmp(lp, "wfs", 3)) { + lp += 4; + // skip one space after cmd + web_send_file(0, lp); WSContentFlush(); goto next_line; } #endif else if (!strncmp(lp, "rapp", 3)) { - lp+=4; + lp += 4; // skip one space after cmd char *tmp = (char*)malloc(256); if (tmp) { @@ -6246,49 +6440,59 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) { #ifdef USE_SCRIPT_SPI // transfer 1-3 bytes -uint32_t script_sspi_trans(uint32_t cs_index, uint32_t val, uint32_t size) { +uint32_t script_sspi_trans(int32_t cs_index, float *array, uint32_t len, uint32_t size) { uint32_t out = 0; - - digitalWrite(glob_script_mem.spi.cs[cs_index], 0); + if (cs_index >= 0) { + cs_index &= 3; + digitalWrite(glob_script_mem.spi.cs[cs_index], 0); + } if (glob_script_mem.spi.sclk < 0) { // use existing hardware spi glob_script_mem.spi.spip->beginTransaction(glob_script_mem.spi.settings); - if (size == 1) { - out = glob_script_mem.spi.spip->transfer(val); - } - if (size == 2) { - out = glob_script_mem.spi.spip->transfer16(val); - } - if (size == 3) { - out = glob_script_mem.spi.spip->transfer(val >> 16); - out <<= 16; - out |= glob_script_mem.spi.spip->transfer16(val); - } - //SPI.transferBytes(); - glob_script_mem.spi.spip->endTransaction(); - digitalWrite(glob_script_mem.spi.cs[cs_index], 1); - return out; - } - - if (size < 1 || size > 3) size = 1; - uint32_t bit = 1 << ((size * 8) - 1); - while (bit) { - digitalWrite(glob_script_mem.spi.sclk, 0); - if (glob_script_mem.spi.mosi >= 0) { - if (val & bit) digitalWrite(glob_script_mem.spi.mosi, 1); - else digitalWrite(glob_script_mem.spi.mosi, 0); - } - digitalWrite(glob_script_mem.spi.sclk, 1); - if (glob_script_mem.spi.miso >= 0) { - if (digitalRead(glob_script_mem.spi.miso)) { - out |= bit; + for (uint32_t cnt = 0; cnt < len; cnt++) { + if (size == 1) { + out = glob_script_mem.spi.spip->transfer((uint8_t)*array); } + if (size == 2) { + out = glob_script_mem.spi.spip->transfer16((uint16_t)*array); + } + if (size == 3) { + out = glob_script_mem.spi.spip->transfer((uint32_t)*array >> 16); + out <<= 16; + out |= glob_script_mem.spi.spip->transfer16((uint32_t)*array); + } + *array++ = out; + } + glob_script_mem.spi.spip->endTransaction(); + + } else { + if (size < 1 || size > 3) size = 1; + for (uint32_t cnt = 0; cnt < len; cnt++) { + uint32_t bit = 1 << ((size * 8) - 1); + out = 0; + uint32_t uvar = *array; + while (bit) { + digitalWrite(glob_script_mem.spi.sclk, 0); + if (glob_script_mem.spi.mosi >= 0) { + if (uvar & bit) digitalWrite(glob_script_mem.spi.mosi, 1); + else digitalWrite(glob_script_mem.spi.mosi, 0); + } + digitalWrite(glob_script_mem.spi.sclk, 1); + if (glob_script_mem.spi.miso >= 0) { + if (digitalRead(glob_script_mem.spi.miso)) { + out |= bit; + } + } + bit >>= 1; + } + *array++ = out; } - bit >>= 1; } - digitalWrite(glob_script_mem.spi.cs[cs_index], 1); - return out; + if (cs_index >= 0) { + digitalWrite(glob_script_mem.spi.cs[cs_index], 1); + } + return len; } #endif // USE_SCRIPT_SPI @@ -6810,20 +7014,39 @@ void SaveScriptEnd(void) { } } + + void set_callbacks() { if (Run_Scripter1(">F", -2, 0) == 99) {glob_script_mem.fast_script = glob_script_mem.section_ptr + 2;} else {glob_script_mem.fast_script = 0;} if (Run_Scripter1(">E", -2, 0) == 99) {glob_script_mem.event_script = glob_script_mem.section_ptr + 2;} else {glob_script_mem.event_script = 0;} if (Run_Scripter1(">C", -2, 0) == 99) {glob_script_mem.html_script = glob_script_mem.section_ptr + 2;} else {glob_script_mem.html_script = 0;} } +void set_wpages(char *id, uint16_t index) { + uint16_t idlen = strlen(id); + uint16_t idl2 = idlen; + if (id[idlen - 1] ==' ') idl2--; + if (Run_Scripter1(id, -idlen, 0) == 99) {glob_script_mem.web_pages[index] = glob_script_mem.section_ptr + idl2;} else {glob_script_mem.web_pages[index] = 0;} +} + +#define WEB_PAGE_WS 8 +#define WEB_PAGE_WM 9 + +const char SWPAGES[] PROGMEM = {"W|w |w1 |w2 |w3 |w4 |w5 |w6 |WS|WM|$"}; + void script_set_web_pages(void) { - if (Run_Scripter1(">W", -2, 0) == 99) {glob_script_mem.web_pages[0] = glob_script_mem.section_ptr + 2;} else {glob_script_mem.web_pages[0] = 0;} - if (Run_Scripter1(">w ", -3, 0) == 99) {glob_script_mem.web_pages[1] = glob_script_mem.section_ptr + 2;} else {glob_script_mem.web_pages[1] = 0;} - if (Run_Scripter1(">w1 ", -4, 0) == 99) {glob_script_mem.web_pages[2] = glob_script_mem.section_ptr + 3;} else {glob_script_mem.web_pages[2] = 0;} - if (Run_Scripter1(">w2 ", -4, 0) == 99) {glob_script_mem.web_pages[3] = glob_script_mem.section_ptr + 3;} else {glob_script_mem.web_pages[3] = 0;} - if (Run_Scripter1(">w3 ", -4, 0) == 99) {glob_script_mem.web_pages[4] = glob_script_mem.section_ptr + 3;} else {glob_script_mem.web_pages[4] = 0;} - if (Run_Scripter1(">WS", -3, 0) == 99) {glob_script_mem.web_pages[5] = glob_script_mem.section_ptr + 3;} else {glob_script_mem.web_pages[5] = 0;} - if (Run_Scripter1(">WM", -3, 0) == 99) {glob_script_mem.web_pages[6] = glob_script_mem.section_ptr + 3;} else {glob_script_mem.web_pages[6] = 0;} + char lbl[6]; + lbl[0] = '>'; + + uint16_t index = 0; + while (1) { + GetTextIndexed(&lbl[1], sizeof(lbl) - 1, index, SWPAGES); + if (lbl[1] == '$') { + break; + } + set_wpages(lbl, index); + index++; + } } #endif // USE_WEBSERVER @@ -7869,6 +8092,8 @@ void script_download_task(void *path) { } #endif // USE_DLTASK +#define REVERT_M5EPD + void SendFile_sub(char *fname) { char buff[512]; uint8_t sflg = 0; @@ -7915,7 +8140,9 @@ char buff[512]; memset(lbuf, 0, Settings->display_width * 3); if (!lbuf) return; uint8_t dmflg = 0; - if (renderer->disp_bpp & 0x40) dmflg = 1; + if (renderer->disp_bpp & 0x40) { + dmflg = 1; + } int8_t bpp = renderer->disp_bpp & 0xbf;; uint8_t *lbp; uint8_t fileHeader[fileHeaderSize]; @@ -7939,9 +8166,16 @@ char buff[512]; Webserver->client().write((const char*)lbuf, Settings->display_width * 3); } } else { - for (uint32_t lins = 0; linsdisplay_height; lins++) { + for (uint32_t lins = 0; lins < Settings->display_height; lins++) { lbp = lbuf + (Settings->display_width * 3); if (bpp == 4) { + // 16 gray scales +#ifdef REVERT_M5EPD + if (dmflg) { + bp = &renderer->framebuffer[(Settings->display_height - lins) * (Settings->display_width / 2)]; + bp--; + } +#endif for (uint32_t cols = 0; cols < Settings->display_width; cols += 2) { uint8_t pixel; if (!dmflg) { @@ -7956,10 +8190,14 @@ char buff[512]; *--lbp = pixel; *--lbp = pixel; } - + bp++; } else { for (uint32_t cnt = 0; cnt <= 1; cnt++) { +#ifdef REVERT_M5EPD + if (cnt & 1) { +#else if (!(cnt & 1)) { +#endif pixel = *bp >> 4; } else { pixel = *bp & 0xf; @@ -7969,10 +8207,15 @@ char buff[512]; *--lbp = pixel; *--lbp = pixel; } +#ifdef REVERT_M5EPD + bp--; +#else + bp++; +#endif } - bp++; } } else { + // one bit for (uint32_t cols = 0; cols < Settings->display_width; cols += 8) { uint8_t bits = 0x80; while (bits) { @@ -8081,6 +8324,15 @@ void ScriptFullWebpage3(void) { void ScriptFullWebpage4(void) { ScriptFullWebpage(4); } +void ScriptFullWebpage5(void) { + ScriptFullWebpage(5); +} +void ScriptFullWebpage6(void) { + ScriptFullWebpage(6); +} +void ScriptFullWebpage7(void) { + ScriptFullWebpage(7); +} void ScriptFullWebpage(uint8_t page) { uint32_t fullpage_refresh = 10000; @@ -8248,7 +8500,8 @@ const char SCRIPT_MSG_GTABLEbx[] PROGMEM = "google.charts.setOnLoadCallback(drawChart);"; const char SCRIPT_MSG_GOPT1[] PROGMEM = -"title:'%s',isStacked:false"; +"title:'%s',isStacked:%s"; + const char SCRIPT_MSG_GAUGEOPT[] PROGMEM = "max:%d,redFrom:%d,redTo:%d,yellowFrom:%d,yellowTo:%d"; @@ -8257,7 +8510,7 @@ const char SCRIPT_MSG_GOPT2[] PROGMEM = "showRowNumber:true,sort:'disable',allowHtml:true,width:'100%%',height:'100%%',cssClassNames:cssc"; const char SCRIPT_MSG_GOPT3[] PROGMEM = -"title:'%s',isStacked:false,vAxes:{0:{maxValue:%s},1:{maxValue:%s}},series:{0:{targetAxisIndex:0},1:{targetAxisIndex:1}}%s"; +"title:'%s',isStacked:%s,vAxes:{0:{maxValue:%s},1:{maxValue:%s}},series:{0:{targetAxisIndex:0},1:{targetAxisIndex:1}}%s"; const char SCRIPT_MSG_GOPT4[] PROGMEM = //"hAxis:{minValue:new Date(0,1,1,0,0),maxValue:new Date(0,1,2,0,0),format:'HH:mm'}"; @@ -8267,7 +8520,7 @@ const char SCRIPT_MSG_GOPT5[] PROGMEM = "new Date(0,0,0,%d,%d)"; const char SCRIPT_MSG_GOPT6[] PROGMEM = -"title:'%s',isStacked:false,vAxis:{viewWindow:{min:%s,max:%s}}%s"; +"title:'%s',isStacked:%s,vAxis:{viewWindow:{min:%s,max:%s}}%s"; const char SCRIPT_MSG_GTE1[] PROGMEM = "'%s'"; @@ -8387,6 +8640,7 @@ uint32_t cnt; #define WSO_NOCENTER 1 #define WSO_NODIV 2 #define WSO_FORCEPLAIN 4 +#define WSO_FORCEMAIN 8 #define WSO_STOP_DIV 0x80 void WCS_DIV(uint8_t flag) { @@ -8414,7 +8668,7 @@ void ScriptWebShow(char mc, uint8_t page) { //uint8_t web_script; glob_script_mem.web_mode = mc; - if (mc == 'w' || mc == 'x' || page >= 5) { + if (mc == 'w' || mc == 'x' || page >= WEB_PAGE_WS) { if (mc == 'x') { mc = '$'; } @@ -8485,6 +8739,11 @@ void ScriptWebShow(char mc, uint8_t page) { lp = scripter_sub(lp + 1, 0); specopt = sflg; //goto nextwebline; + } else if (!strncmp(lp, "%/", 2)) { + // send file + if (mc) { + web_send_file(mc, lp + 1); + } } else { web_send_line(mc, lp); } @@ -8501,6 +8760,44 @@ nextwebline: } } +#define WSF_BSIZE 256 +int32_t web_send_file(char mc, char *fname) { + char path[32]; + +#ifdef USE_UFILESYS + + char *lbuff = (char*)special_malloc(WSF_BSIZE); + if (!lbuff) { + return -1; + } + + cpy2lf(path, sizeof(path), fname); + File file = ufsp->open(path, FS_FILE_READ); + if (file) { + WSContentFlush(); + while (file.available()) { + uint16_t len; + len = file.readBytesUntil('\n', lbuff, WSF_BSIZE); + lbuff[len] = 0; + char *lp = lbuff; + while (*lp == ' ') lp++; + if (*lp == '/' && *(lp + 1) == '/') { + // skip comment lines + continue; + } + web_send_line(mc, lbuff); + } + file.close(); + free(lbuff); + return 0; + } else { + AddLog(LOG_LEVEL_INFO, PSTR("WEB file %s not found"), path); + } + free(lbuff); +#endif + return -2; +} + char *web_send_line(char mc, char *lp1) { char tmp[256]; char center[10]; @@ -8510,8 +8807,24 @@ const char *gc_str; Replace_Cmd_Vars(lp1, 1, tmp, sizeof(tmp)); char *lin = tmp; - if ((!mc && (*lin != '$')) || (mc == 'w' && (*lin != '$'))) { + + if (!strncmp(lin, "so(", 3)) { + // set options + float var; + lin = GetNumericArgument(lin + 3, OPER_EQU, &var, 0); + specopt = var; + return lin; + } + + if (specopt & WSO_NOCENTER) { + center[0] = 0; + } else { + strcpy_P(center, PSTR("
")); + } + + if ( ((!mc && (*lin != '$')) || (mc == 'w' && (*lin != '$'))) && (!(specopt&WSO_FORCEMAIN)) ) { // normal web section + //AddLog(LOG_LEVEL_INFO, PSTR("normal %s"), lin); if (*lin == '@') { lin++; optflg = 1; @@ -8525,21 +8838,7 @@ const char *gc_str; strcpy_P(center, PSTR("
")); } - if (!strncmp(lin, "so(", 3)) { - // set options - char *lp = lin; - float var; - lp = GetNumericArgument(lp + 3, OPER_EQU, &var, 0); - SCRIPT_SKIP_SPACES - lp++; - specopt = var; - // bit 0 = center mode - if (specopt & WSO_NOCENTER) { - center[0] = 0; - } else { - strcpy_P(center, PSTR("
")); - } - } else if (!strncmp(lin, "sl(", 3)) { + if (!strncmp(lin, "sl(", 3)) { // insert slider sl(min max var left mid right) char *lp = lin; float min; @@ -8864,14 +9163,63 @@ const char *gc_str; // end standard web interface } else { // main section interface - if (*lin == mc || mc == 'z') { + //AddLog(LOG_LEVEL_INFO, PSTR("main %s"), lin); + if ( (*lin == mc) || (mc == 'z') || (specopt&WSO_FORCEMAIN)) { #ifdef USE_GOOGLE_CHARTS if (mc != 'z') { - lin++; + if (!(specopt&WSO_FORCEMAIN)) { + lin++; + } } exgc: char *lp; + + char *cp = strstr_P(lin, PSTR("insa(")); + if (cp) { + // insert array + char valstr[128]; + uint16_t len = (uint32_t)cp - (uint32_t)lin; + strncpy(valstr, lin, len); + valstr[len] = 0; + WSContentSend_PD(PSTR("%s"), valstr); + float *fpd = 0; + uint16_t alend; + uint16_t ipos; + lp = get_array_by_name(cp + 5, &fpd, &alend, &ipos); + if (ipos >= alend) ipos = 0; + if (fpd) { + for (uint32_t cnt = 0; cnt < alend; cnt++) { + dtostrfd(fpd[ipos], 3, valstr); + ipos++; + if (ipos >= alend) { + ipos = 0; + } + if (cnt == 0) { + WSContentSend_PD(PSTR("%s"), valstr); + } else { + WSContentSend_PD(PSTR(",%s"), valstr); + } + } + } + lp++; + WSContentSend_PD(PSTR("%s"), lp); + return lp; + } + + cp = strstr_P(lin, PSTR("=#")); + if (cp) { + // insert from subroutine + char valstr[128]; + uint16_t len = (uint32_t)cp - (uint32_t)lin; + strncpy(valstr, lin, len); + valstr[len] = 0; + WSContentSend_PD(PSTR("%s"), valstr); + lp = scripter_sub(cp , 0); + WSContentSend_PD(PSTR("%s"), lp); + return lp; + } + if (!strncmp(lin, "gc(", 3)) { // get google table lp = lin + 3; @@ -8920,13 +9268,18 @@ exgc: return lp1; } - - if (gs_ctype=='l' && *lp=='f') { + char stacked[6]; + strcpy_P(stacked,"false"); + if (gs_ctype == 'l' && *lp == 'f') { lp++; func = PSTR(",curveType:'function'"); } else { func = ""; } + if (gs_ctype == 'c' && *lp == 's') { + lp++; + strcpy_P(stacked,"true"); + } if (*lp=='2') { lp++; nanum = 2; @@ -8939,6 +9292,22 @@ exgc: SCRIPT_SKIP_SPACES //Serial.printf("type %d\n",ctype); + float max_entries = 0; + + struct T_INDEX ind; + uint8_t vtype; + char *slp = lp; + lp = isvar(lp, &vtype, &ind, &max_entries, 0, 0); + if (vtype != VAR_NV) { + if ((vtype&STYPE) == 0) { + // numeric result + if (!ind.bits.constant && glob_script_mem.type[ind.index].bits.is_filter) { + // is 1. array + lp = slp; + } + } + } + SCRIPT_SKIP_SPACES float *arrays[MAX_GARRAY]; uint8_t anum = 0; @@ -8950,6 +9319,15 @@ exgc: return lp1; //goto nextwebline; } + + // override array size + if (max_entries > 0) { + if (max_entries > entries) { + max_entries = entries; + } + entries = max_entries; + } + // we know how many arrays and the number of entries //Serial.printf("arrays %d\n",anum); //Serial.printf("entries %d\n",entries); @@ -9061,6 +9439,7 @@ exgc: } } divflg = entries / segments; + if (!divflg) divflg = 1; } uint32_t aind = ipos; @@ -9070,7 +9449,11 @@ exgc: char lbl[16]; if (todflg >= 0) { uint16_t mins = (float)(todflg % divflg) * (float)((float)60 / (float)divflg); - sprintf(lbl, "%d:%02d", todflg / divflg, mins); + if (hmflg) { + sprintf(lbl, "%d:%02d", todflg / divflg, mins); + } else { + sprintf(lbl, "%d", todflg / divflg); + } todflg++; if (hmflg == 0) { if (todflg >= entries) { @@ -9128,7 +9511,7 @@ exgc: snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT2); break; default: - snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT1, header); + snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT1, header, stacked); break; } // check for 2 axis option @@ -9146,11 +9529,11 @@ exgc: char maxstr2[16]; dtostrfd(max2, 3, maxstr2); //snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT3, header, (uint32_t)max1, (uint32_t)max2, func); - snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT3, header, maxstr1, maxstr2, func); + snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT3, header, stacked, maxstr1, maxstr2, func); } else { SCRIPT_SKIP_SPACES - if (gs_ctype!='g') { - if (*lp!=')') { + if (gs_ctype != 'g') { + if (*lp != ')') { float max1; lp = GetNumericArgument(lp, OPER_EQU, &max1, 0); SCRIPT_SKIP_SPACES @@ -9162,12 +9545,12 @@ exgc: char maxstr2[16]; dtostrfd(max2, 3, maxstr2); //nprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT6, header, (uint32_t)max1, (uint32_t)max2, func); - snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT6, header, maxstr1, maxstr2, func); + snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT6, header, stacked, maxstr1, maxstr2, func); } } } - if (gs_ctype=='g') { + if (gs_ctype == 'g') { float yellowFrom; lp = GetNumericArgument(lp, OPER_EQU, &yellowFrom, 0); SCRIPT_SKIP_SPACES @@ -9190,7 +9573,9 @@ exgc: WSContentSend_PD(PSTR("%s"), lin); } #else - lin++; + if (!(specopt&WSO_FORCEMAIN)) { + lin++; + } WSContentSend_PD(PSTR("%s"), lin); } else { // WSContentSend_PD(PSTR("%s"),lin); @@ -10060,6 +10445,15 @@ void script_add_subpage(uint8_t num) { case 4: wptr = ScriptFullWebpage4; break; + case 5: + wptr = ScriptFullWebpage5; + break; + case 6: + wptr = ScriptFullWebpage6; + break; + case 7: + wptr = ScriptFullWebpage7; + break; } sprintf_P(id, PSTR("/sfd%1d"), num); Webserver->on(id, wptr); @@ -10293,8 +10687,8 @@ bool Xdrv10(uint8_t function) #ifdef USE_SCRIPT_WEB_DISPLAY case FUNC_WEB_ADD_MAIN_BUTTON: if (bitRead(Settings->rule_enabled, 0)) { - if (glob_script_mem.web_pages[6]) { - ScriptWebShow('z', 6); + if (glob_script_mem.web_pages[WEB_PAGE_WM]) { + ScriptWebShow('z', WEB_PAGE_WM); } else { ScriptWebShow('$', 0); } @@ -10303,6 +10697,9 @@ bool Xdrv10(uint8_t function) script_add_subpage(2); script_add_subpage(3); script_add_subpage(4); + script_add_subpage(5); + script_add_subpage(6); + script_add_subpage(7); #endif // SCRIPT_FULL_WEBPAGE } @@ -10338,8 +10735,8 @@ bool Xdrv10(uint8_t function) #ifdef USE_SCRIPT_WEB_DISPLAY case FUNC_WEB_SENSOR: if (bitRead(Settings->rule_enabled, 0)) { - if (glob_script_mem.web_pages[5]) { - ScriptWebShow(0, 5); + if (glob_script_mem.web_pages[WEB_PAGE_WS]) { + ScriptWebShow(0, WEB_PAGE_WS); } else { ScriptWebShow(0, 0); } diff --git a/tasmota/xdrv_11_knx.ino b/tasmota/tasmota_xdrv_driver/xdrv_11_knx.ino similarity index 100% rename from tasmota/xdrv_11_knx.ino rename to tasmota/tasmota_xdrv_driver/xdrv_11_knx.ino diff --git a/tasmota/xdrv_12_discovery.ino b/tasmota/tasmota_xdrv_driver/xdrv_12_discovery.ino similarity index 100% rename from tasmota/xdrv_12_discovery.ino rename to tasmota/tasmota_xdrv_driver/xdrv_12_discovery.ino diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/tasmota_xdrv_driver/xdrv_12_home_assistant.ino similarity index 100% rename from tasmota/xdrv_12_home_assistant.ino rename to tasmota/tasmota_xdrv_driver/xdrv_12_home_assistant.ino diff --git a/tasmota/xdrv_13_display.ino b/tasmota/tasmota_xdrv_driver/xdrv_13_display.ino old mode 100755 new mode 100644 similarity index 100% rename from tasmota/xdrv_13_display.ino rename to tasmota/tasmota_xdrv_driver/xdrv_13_display.ino diff --git a/tasmota/xdrv_14_mp3.ino b/tasmota/tasmota_xdrv_driver/xdrv_14_mp3.ino similarity index 100% rename from tasmota/xdrv_14_mp3.ino rename to tasmota/tasmota_xdrv_driver/xdrv_14_mp3.ino diff --git a/tasmota/xdrv_15_pca9685.ino b/tasmota/tasmota_xdrv_driver/xdrv_15_pca9685.ino similarity index 100% rename from tasmota/xdrv_15_pca9685.ino rename to tasmota/tasmota_xdrv_driver/xdrv_15_pca9685.ino diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu.ino similarity index 100% rename from tasmota/xdrv_16_tuyamcu.ino rename to tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu.ino diff --git a/tasmota/xdrv_17_rcswitch.ino b/tasmota/tasmota_xdrv_driver/xdrv_17_rcswitch.ino similarity index 100% rename from tasmota/xdrv_17_rcswitch.ino rename to tasmota/tasmota_xdrv_driver/xdrv_17_rcswitch.ino diff --git a/tasmota/xdrv_18_armtronix_dimmers.ino b/tasmota/tasmota_xdrv_driver/xdrv_18_armtronix_dimmers.ino similarity index 100% rename from tasmota/xdrv_18_armtronix_dimmers.ino rename to tasmota/tasmota_xdrv_driver/xdrv_18_armtronix_dimmers.ino diff --git a/tasmota/xdrv_19_ps16dz_dimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_19_ps16dz_dimmer.ino similarity index 100% rename from tasmota/xdrv_19_ps16dz_dimmer.ino rename to tasmota/tasmota_xdrv_driver/xdrv_19_ps16dz_dimmer.ino diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/tasmota_xdrv_driver/xdrv_20_hue.ino similarity index 100% rename from tasmota/xdrv_20_hue.ino rename to tasmota/tasmota_xdrv_driver/xdrv_20_hue.ino diff --git a/tasmota/xdrv_21_wemo.ino b/tasmota/tasmota_xdrv_driver/xdrv_21_wemo.ino similarity index 100% rename from tasmota/xdrv_21_wemo.ino rename to tasmota/tasmota_xdrv_driver/xdrv_21_wemo.ino diff --git a/tasmota/xdrv_21_wemo_multi.ino b/tasmota/tasmota_xdrv_driver/xdrv_21_wemo_multi.ino similarity index 100% rename from tasmota/xdrv_21_wemo_multi.ino rename to tasmota/tasmota_xdrv_driver/xdrv_21_wemo_multi.ino diff --git a/tasmota/xdrv_22_sonoff_ifan.ino b/tasmota/tasmota_xdrv_driver/xdrv_22_sonoff_ifan.ino similarity index 100% rename from tasmota/xdrv_22_sonoff_ifan.ino rename to tasmota/tasmota_xdrv_driver/xdrv_22_sonoff_ifan.ino diff --git a/tasmota/xdrv_23_zigbee_0_constants.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_0_constants.ino similarity index 100% rename from tasmota/xdrv_23_zigbee_0_constants.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_0_constants.ino diff --git a/tasmota/xdrv_23_zigbee_1_headers.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_1_headers.ino similarity index 98% rename from tasmota/xdrv_23_zigbee_1_headers.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_1_headers.ino index 38359d00b..a28afeae1 100644 --- a/tasmota/xdrv_23_zigbee_1_headers.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_1_headers.ino @@ -73,7 +73,6 @@ public: bool state_machine = false; // the state machine is running bool state_waiting = false; // the state machine is waiting for external event or timeout bool state_no_timeout = false; // the current wait loop does not generate a timeout but only continues running - bool ready = false; // cc2530 initialization is complet, ready to operate bool init_phase = true; // initialization phase, before accepting zigbee traffic bool recv_until = false; // ignore all messages until the received frame fully matches bool eeprom_present = false; // is the ZBBridge EEPROM present? @@ -98,6 +97,12 @@ public: ZB_RecvMsgFunc recv_func = nullptr; // function to call when message is expected ZB_RecvMsgFunc recv_unexpected = nullptr; // function called when unexpected message is received + // version + uint8_t major_rel = 0; + uint8_t minor_rel = 0; + uint8_t maint_rel = 0; + uint32_t revision = 0; + // Energy scan int8_t energy[USE_ZIGBEE_CHANNEL_COUNT]; diff --git a/tasmota/xdrv_23_zigbee_1z_libs.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_1z_libs.ino similarity index 100% rename from tasmota/xdrv_23_zigbee_1z_libs.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_1z_libs.ino diff --git a/tasmota/xdrv_23_zigbee_2_devices.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2_devices.ino similarity index 99% rename from tasmota/xdrv_23_zigbee_2_devices.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2_devices.ino index 929676bfb..ad4c892b2 100644 --- a/tasmota/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2_devices.ino @@ -995,7 +995,7 @@ private: * Berry support \*********************************************************************************************/ #ifdef USE_BERRY -extern "C" void callBerryZigbeeDispatcher(const char* type, ZCLFrame* zcl_received); +extern "C" int32_t callBerryZigbeeDispatcher(const char* cmd, const char* type, void* data, int32_t idx); #endif // USE_BERRY /*********************************************************************************************\ diff --git a/tasmota/xdrv_23_zigbee_2a_devices_impl.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2a_devices_impl.ino similarity index 99% rename from tasmota/xdrv_23_zigbee_2a_devices_impl.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2a_devices_impl.ino index b28ee0462..afa448761 100644 --- a/tasmota/xdrv_23_zigbee_2a_devices_impl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2a_devices_impl.ino @@ -665,7 +665,6 @@ Z_Device & Z_Devices::parseDeviceFromName(const char * param, uint16_t * parsed_ // Add "Device":"0x1234","Name":"FrienflyName" void Z_Device::jsonAddDeviceNamme(Z_attribute_list & attr_list) const { const char * fname = friendlyName; - bool use_fname = (Settings->flag4.zigbee_use_names) && (fname); // should we replace shortaddr with friendlyname? attr_list.addAttributePMEM(PSTR(D_JSON_ZIGBEE_DEVICE)).setHex32(shortaddr); if (fname) { diff --git a/tasmota/xdrv_23_zigbee_4a_nano_fs.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_4a_nano_fs.ino similarity index 100% rename from tasmota/xdrv_23_zigbee_4a_nano_fs.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_4a_nano_fs.ino diff --git a/tasmota/xdrv_23_zigbee_4b_data.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_4b_data.ino similarity index 100% rename from tasmota/xdrv_23_zigbee_4b_data.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_4b_data.ino diff --git a/tasmota/xdrv_23_zigbee_4c_devices.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_4c_devices.ino similarity index 100% rename from tasmota/xdrv_23_zigbee_4c_devices.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_4c_devices.ino diff --git a/tasmota/xdrv_23_zigbee_5__constants.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5__constants.ino similarity index 100% rename from tasmota/xdrv_23_zigbee_5__constants.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5__constants.ino diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_converters.ino similarity index 99% rename from tasmota/xdrv_23_zigbee_5_converters.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_converters.ino index 5c45df943..dda3b7c4a 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_converters.ino @@ -849,16 +849,16 @@ public: uint8_t transactseq = 0; // transaction sequence number uint8_t cmd = 0; SBuffer payload; - uint16_t cluster = 0; + uint16_t cluster = 0xFFFF; // invalid cluster by default uint16_t groupaddr = 0; // information from decoded ZCL frame uint16_t shortaddr = BAD_SHORTADDR; // BAD_SHORTADDR is broadcast, so considered invalid uint8_t dstendpoint = 0x00; // 0x00 is invalid for the dst endpoint // attributes used in send-only mode - bool clusterSpecific = false; - bool needResponse = true; - bool direct = false; // true if direct, false if discover router - bool transacSet = false; // is transac already set + bool clusterSpecific = false; + bool needResponse = true; + bool direct = false; // true if direct, false if discover router + bool transacSet = false; // is transac already set // below private attributes are not used when sending a message private: diff --git a/tasmota/xdrv_23_zigbee_6_5_hue.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_5_hue.ino similarity index 99% rename from tasmota/xdrv_23_zigbee_6_5_hue.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_5_hue.ino index 33d6c9a61..1dfe71f49 100644 --- a/tasmota/xdrv_23_zigbee_6_5_hue.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_5_hue.ino @@ -226,7 +226,6 @@ void ZigbeeHueHS(uint16_t shortaddr, uint16_t hue, uint8_t sat) { int32_t ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) { uint8_t bri, sat; uint16_t ct, hue; - int code = 200; int8_t bulbtype = zigbee_devices.getHueBulbtype(shortaddr); if (bulbtype < 0) { // respond only if eligible diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_commands.ino similarity index 100% rename from tasmota/xdrv_23_zigbee_6_commands.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_commands.ino diff --git a/tasmota/xdrv_23_zigbee_7_0_statemachine.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_7_0_statemachine.ino similarity index 100% rename from tasmota/xdrv_23_zigbee_7_0_statemachine.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_7_0_statemachine.ino diff --git a/tasmota/xdrv_23_zigbee_7_5_map.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_7_5_map.ino similarity index 100% rename from tasmota/xdrv_23_zigbee_7_5_map.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_7_5_map.ino diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_8_parsers.ino similarity index 99% rename from tasmota/xdrv_23_zigbee_8_parsers.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_8_parsers.ino index 348e8e7b7..382cf1377 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_8_parsers.ino @@ -447,20 +447,21 @@ int32_t ZNP_ReceiveCheckVersion(int32_t res, SBuffer &buf) { // MinorRel = 6 // MaintRel = 3 // Revision = 20190425 d (0x013414D9) - uint8_t major_rel = buf.get8(4); - uint8_t minor_rel = buf.get8(5); - uint8_t maint_rel = buf.get8(6); - uint32_t revision = buf.get32(7); + zigbee.major_rel = buf.get8(4); + zigbee.minor_rel = buf.get8(5); + zigbee.maint_rel = buf.get8(6); + zigbee.revision = buf.get32(7); Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" "\"Status\":%d,\"MajorRel\":%d,\"MinorRel\":%d" ",\"MaintRel\":%d,\"Revision\":%d}}"), - ZIGBEE_STATUS_CC_VERSION, major_rel, minor_rel, - maint_rel, revision); + ZIGBEE_STATUS_CC_VERSION, + zigbee.major_rel, zigbee.minor_rel, + zigbee.maint_rel, zigbee.revision); MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - if ((0x02 == major_rel) && ((0x06 == minor_rel) || (0x07 == minor_rel))) { + if ((0x02 == zigbee.major_rel) && ((0x06 == zigbee.minor_rel) || (0x07 == zigbee.minor_rel))) { return 0; // version 2.6.x and 2.7.x are ok } else { return ZIGBEE_LABEL_UNSUPPORTED_VERSION; // abort @@ -474,14 +475,17 @@ int32_t EZ_ReceiveCheckVersion(int32_t res, SBuffer &buf) { uint8_t stack_type = buf.get8(3); zigbee.ezsp_version = buf.get16(4); + zigbee.major_rel = (zigbee.ezsp_version & 0xF000) >> 12; + zigbee.minor_rel = (zigbee.ezsp_version & 0x0F00) >> 8; + zigbee.maint_rel = (zigbee.ezsp_version & 0x00F0) >> 4; + zigbee.revision = zigbee.ezsp_version & 0x000F; + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" "\"Status\":%d,\"Version\":\"%d.%d.%d.%d\",\"Protocol\":%d" ",\"Stack\":%d}}"), ZIGBEE_STATUS_EZ_VERSION, - (zigbee.ezsp_version & 0xF000) >> 12, - (zigbee.ezsp_version & 0x0F00) >> 8, - (zigbee.ezsp_version & 0x00F0) >> 4, - zigbee.ezsp_version & 0x000F, + zigbee.major_rel, zigbee.minor_rel, + zigbee.maint_rel, zigbee.revision, protocol_version, stack_type ); @@ -1641,7 +1645,7 @@ void Z_IncomingMessage(class ZCLFrame &zcl_received) { #ifdef USE_BERRY // Berry pre-process messages - // callBerryZigbeeDispatcher("pre", &zcl_received); + callBerryZigbeeDispatcher("incoming", "zcl_frame", &zcl_received, 0); #endif // USE_BERRY // create the device entry if it does not exist and if it's not the local device @@ -1950,8 +1954,6 @@ int32_t ZNP_ReceiveAfIncomingMessage(int32_t res, const SBuffer &buf) { // uint32_t timestamp = buf.get32(13); uint8_t seqnumber = buf.get8(17); - bool defer_attributes = false; // do we defer attributes reporting to coalesce - ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 19, buf.get8(18), clusterid, groupid, srcaddr, srcendpoint, dstendpoint, wasbroadcast, diff --git a/tasmota/xdrv_23_zigbee_9_serial.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_9_serial.ino similarity index 99% rename from tasmota/xdrv_23_zigbee_9_serial.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_9_serial.ino index ef3ef350b..7badbcf77 100644 --- a/tasmota/xdrv_23_zigbee_9_serial.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_9_serial.ino @@ -300,11 +300,8 @@ void ZigbeeInitSerial(void) ZigbeeSerial->begin(115200); if (ZigbeeSerial->hardwareSerial()) { ClaimSerial(); - uint32_t aligned_buffer = ((uint32_t)TasmotaGlobal.serial_in_buffer + 3) & ~3; - zigbee_buffer = new PreAllocatedSBuffer(sizeof(TasmotaGlobal.serial_in_buffer) - 3, (char*) aligned_buffer); - } else { - zigbee_buffer = new SBuffer(ZIGBEE_BUFFER_SIZE); } + zigbee_buffer = new SBuffer(ZIGBEE_BUFFER_SIZE); zigbee.active = true; zigbee.init_phase = true; // start the state machine diff --git a/tasmota/xdrv_23_zigbee_9a_upload.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_9a_upload.ino similarity index 100% rename from tasmota/xdrv_23_zigbee_9a_upload.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_9a_upload.ino diff --git a/tasmota/xdrv_23_zigbee_A_impl.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino similarity index 99% rename from tasmota/xdrv_23_zigbee_A_impl.ino rename to tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino index 26d634b8b..f182316ea 100644 --- a/tasmota/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino @@ -1931,6 +1931,19 @@ uint32_t convert_seconds_to_dhm(uint32_t seconds, char *unit, uint8_t *color){ return 0; } +const char HTTP_ZB_VERSION[] PROGMEM = + "
" + "Zigbee: " +#if defined(USE_ZIGBEE_EZSP) + "EZSP" +#elif defined(USE_ZIGBEE_ZNP) + "ZNP" +#else + "unknown" +#endif + " v%d.%d.%d.%d" + "
"; + const char HTTP_BTN_ZB_BUTTONS[] PROGMEM = "" "

" @@ -2114,6 +2127,12 @@ void ZigbeeShow(bool json) WSContentSend_P(msg[ZB_WEB_PERMITJOIN_ACTIVE], PSTR(D_ZIGBEE_PERMITJOIN_ACTIVE)); } + // show Zigbee MCU version + if (!zigbee.init_phase) { + WSContentSend_P(HTTP_ZB_VERSION, + zigbee.major_rel, zigbee.minor_rel, + zigbee.maint_rel, zigbee.revision); + } #endif } } diff --git a/tasmota/xdrv_24_buzzer.ino b/tasmota/tasmota_xdrv_driver/xdrv_24_buzzer.ino similarity index 100% rename from tasmota/xdrv_24_buzzer.ino rename to tasmota/tasmota_xdrv_driver/xdrv_24_buzzer.ino diff --git a/tasmota/xdrv_25_A4988_Stepper.ino b/tasmota/tasmota_xdrv_driver/xdrv_25_A4988_Stepper.ino similarity index 100% rename from tasmota/xdrv_25_A4988_Stepper.ino rename to tasmota/tasmota_xdrv_driver/xdrv_25_A4988_Stepper.ino diff --git a/tasmota/xdrv_26_ariluxrf.ino b/tasmota/tasmota_xdrv_driver/xdrv_26_ariluxrf.ino similarity index 100% rename from tasmota/xdrv_26_ariluxrf.ino rename to tasmota/tasmota_xdrv_driver/xdrv_26_ariluxrf.ino diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino similarity index 100% rename from tasmota/xdrv_27_shutter.ino rename to tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino diff --git a/tasmota/xdrv_28_pcf8574.ino b/tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574.ino similarity index 100% rename from tasmota/xdrv_28_pcf8574.ino rename to tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574.ino diff --git a/tasmota/xdrv_29_deepsleep.ino b/tasmota/tasmota_xdrv_driver/xdrv_29_deepsleep.ino similarity index 100% rename from tasmota/xdrv_29_deepsleep.ino rename to tasmota/tasmota_xdrv_driver/xdrv_29_deepsleep.ino diff --git a/tasmota/xdrv_30_exs_dimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_30_exs_dimmer.ino similarity index 100% rename from tasmota/xdrv_30_exs_dimmer.ino rename to tasmota/tasmota_xdrv_driver/xdrv_30_exs_dimmer.ino diff --git a/tasmota/xdrv_31_tasmota_client.ino b/tasmota/tasmota_xdrv_driver/xdrv_31_tasmota_client.ino similarity index 100% rename from tasmota/xdrv_31_tasmota_client.ino rename to tasmota/tasmota_xdrv_driver/xdrv_31_tasmota_client.ino diff --git a/tasmota/xdrv_32_hotplug.ino b/tasmota/tasmota_xdrv_driver/xdrv_32_hotplug.ino similarity index 100% rename from tasmota/xdrv_32_hotplug.ino rename to tasmota/tasmota_xdrv_driver/xdrv_32_hotplug.ino diff --git a/tasmota/xdrv_33_nrf24l01.ino b/tasmota/tasmota_xdrv_driver/xdrv_33_nrf24l01.ino similarity index 100% rename from tasmota/xdrv_33_nrf24l01.ino rename to tasmota/tasmota_xdrv_driver/xdrv_33_nrf24l01.ino diff --git a/tasmota/xdrv_34_wemos_motor_v1.ino b/tasmota/tasmota_xdrv_driver/xdrv_34_wemos_motor_v1.ino similarity index 100% rename from tasmota/xdrv_34_wemos_motor_v1.ino rename to tasmota/tasmota_xdrv_driver/xdrv_34_wemos_motor_v1.ino diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_35_pwm_dimmer.ino similarity index 100% rename from tasmota/xdrv_35_pwm_dimmer.ino rename to tasmota/tasmota_xdrv_driver/xdrv_35_pwm_dimmer.ino diff --git a/tasmota/xdrv_36_keeloq.ino b/tasmota/tasmota_xdrv_driver/xdrv_36_keeloq.ino similarity index 100% rename from tasmota/xdrv_36_keeloq.ino rename to tasmota/tasmota_xdrv_driver/xdrv_36_keeloq.ino diff --git a/tasmota/xdrv_37_sonoff_d1.ino b/tasmota/tasmota_xdrv_driver/xdrv_37_sonoff_d1.ino similarity index 100% rename from tasmota/xdrv_37_sonoff_d1.ino rename to tasmota/tasmota_xdrv_driver/xdrv_37_sonoff_d1.ino diff --git a/tasmota/xdrv_38_ping.ino b/tasmota/tasmota_xdrv_driver/xdrv_38_ping.ino similarity index 100% rename from tasmota/xdrv_38_ping.ino rename to tasmota/tasmota_xdrv_driver/xdrv_38_ping.ino diff --git a/tasmota/xdrv_39_thermostat.ino b/tasmota/tasmota_xdrv_driver/xdrv_39_thermostat.ino similarity index 100% rename from tasmota/xdrv_39_thermostat.ino rename to tasmota/tasmota_xdrv_driver/xdrv_39_thermostat.ino diff --git a/tasmota/xdrv_40_telegram.ino b/tasmota/tasmota_xdrv_driver/xdrv_40_telegram.ino similarity index 100% rename from tasmota/xdrv_40_telegram.ino rename to tasmota/tasmota_xdrv_driver/xdrv_40_telegram.ino diff --git a/tasmota/xdrv_41_tcp_bridge.ino b/tasmota/tasmota_xdrv_driver/xdrv_41_tcp_bridge.ino similarity index 100% rename from tasmota/xdrv_41_tcp_bridge.ino rename to tasmota/tasmota_xdrv_driver/xdrv_41_tcp_bridge.ino diff --git a/tasmota/xdrv_42_i2s_audio.ino b/tasmota/tasmota_xdrv_driver/xdrv_42_i2s_audio.ino similarity index 100% rename from tasmota/xdrv_42_i2s_audio.ino rename to tasmota/tasmota_xdrv_driver/xdrv_42_i2s_audio.ino diff --git a/tasmota/xdrv_43_mlx90640.ino b/tasmota/tasmota_xdrv_driver/xdrv_43_mlx90640.ino similarity index 100% rename from tasmota/xdrv_43_mlx90640.ino rename to tasmota/tasmota_xdrv_driver/xdrv_43_mlx90640.ino diff --git a/tasmota/xdrv_44_miel_hvac.ino b/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino similarity index 100% rename from tasmota/xdrv_44_miel_hvac.ino rename to tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino diff --git a/tasmota/xdrv_45_shelly_dimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_45_shelly_dimmer.ino similarity index 100% rename from tasmota/xdrv_45_shelly_dimmer.ino rename to tasmota/tasmota_xdrv_driver/xdrv_45_shelly_dimmer.ino diff --git a/tasmota/xdrv_46_ccloader.ino b/tasmota/tasmota_xdrv_driver/xdrv_46_ccloader.ino similarity index 100% rename from tasmota/xdrv_46_ccloader.ino rename to tasmota/tasmota_xdrv_driver/xdrv_46_ccloader.ino diff --git a/tasmota/xdrv_47_ftc532.ino b/tasmota/tasmota_xdrv_driver/xdrv_47_ftc532.ino similarity index 100% rename from tasmota/xdrv_47_ftc532.ino rename to tasmota/tasmota_xdrv_driver/xdrv_47_ftc532.ino diff --git a/tasmota/xdrv_48_timeprop.ino b/tasmota/tasmota_xdrv_driver/xdrv_48_timeprop.ino similarity index 100% rename from tasmota/xdrv_48_timeprop.ino rename to tasmota/tasmota_xdrv_driver/xdrv_48_timeprop.ino diff --git a/tasmota/xdrv_49_pid.ino b/tasmota/tasmota_xdrv_driver/xdrv_49_pid.ino similarity index 100% rename from tasmota/xdrv_49_pid.ino rename to tasmota/tasmota_xdrv_driver/xdrv_49_pid.ino diff --git a/tasmota/xdrv_50_filesystem.ino b/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino similarity index 100% rename from tasmota/xdrv_50_filesystem.ino rename to tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino diff --git a/tasmota/xdrv_51_bs814a2.ino b/tasmota/tasmota_xdrv_driver/xdrv_51_bs814a2.ino similarity index 100% rename from tasmota/xdrv_51_bs814a2.ino rename to tasmota/tasmota_xdrv_driver/xdrv_51_bs814a2.ino diff --git a/tasmota/xdrv_52_0_berry_struct.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_0_berry_struct.ino similarity index 100% rename from tasmota/xdrv_52_0_berry_struct.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_0_berry_struct.ino diff --git a/tasmota/xdrv_52_1_berry_native.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_1_berry_native.ino similarity index 100% rename from tasmota/xdrv_52_1_berry_native.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_1_berry_native.ino diff --git a/tasmota/xdrv_52_3_berry_MI32.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_MI32.ino similarity index 100% rename from tasmota/xdrv_52_3_berry_MI32.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_MI32.ino diff --git a/tasmota/xdrv_52_3_berry_audio.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_audio.ino similarity index 100% rename from tasmota/xdrv_52_3_berry_audio.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_audio.ino diff --git a/tasmota/xdrv_52_3_berry_crypto.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_crypto.ino similarity index 100% rename from tasmota/xdrv_52_3_berry_crypto.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_crypto.ino diff --git a/tasmota/xdrv_52_3_berry_display.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_display.ino similarity index 100% rename from tasmota/xdrv_52_3_berry_display.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_display.ino diff --git a/tasmota/xdrv_52_3_berry_flash.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_flash.ino similarity index 100% rename from tasmota/xdrv_52_3_berry_flash.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_flash.ino diff --git a/tasmota/xdrv_52_3_berry_gpio.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_gpio.ino similarity index 100% rename from tasmota/xdrv_52_3_berry_gpio.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_gpio.ino diff --git a/tasmota/xdrv_52_3_berry_hue.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_hue.ino similarity index 100% rename from tasmota/xdrv_52_3_berry_hue.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_hue.ino diff --git a/tasmota/xdrv_52_3_berry_leds.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino similarity index 99% rename from tasmota/xdrv_52_3_berry_leds.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino index 89001bbc0..54c6c2c15 100644 --- a/tasmota/xdrv_52_3_berry_leds.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino @@ -182,7 +182,7 @@ extern "C" { uint8_t g = (rgbw & 0xFF00) >> 8; uint8_t b = (rgbw & 0xFF); if (s_ws2812_grb) s_ws2812_grb->ClearTo(RgbColor(r, g, b)); - if (s_sk6812_grbw) s_sk6812_grbw->ClearTo(RgbwColor(r, g, b, 0)); + if (s_sk6812_grbw) s_sk6812_grbw->ClearTo(RgbwColor(r, g, b, w)); } break; case 10: // # 10 : SetPixelColor (idx:int, color:??) -> void @@ -194,7 +194,7 @@ extern "C" { uint8_t g = (rgbw & 0xFF00) >> 8; uint8_t b = (rgbw & 0xFF); if (s_ws2812_grb) s_ws2812_grb->SetPixelColor(idx, RgbColor(r, g, b)); - if (s_sk6812_grbw) s_sk6812_grbw->SetPixelColor(idx, RgbwColor(r, g, b, 0)); + if (s_sk6812_grbw) s_sk6812_grbw->SetPixelColor(idx, RgbwColor(r, g, b, w)); } break; case 11: // # 11 : GetPixelColor (idx:int) -> color:?? diff --git a/tasmota/xdrv_52_3_berry_light.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_light.ino similarity index 100% rename from tasmota/xdrv_52_3_berry_light.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_light.ino diff --git a/tasmota/xdrv_52_3_berry_light_state.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_light_state.ino similarity index 99% rename from tasmota/xdrv_52_3_berry_light_state.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_light_state.ino index b3b10dd7b..330d38f33 100644 --- a/tasmota/xdrv_52_3_berry_light_state.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_light_state.ino @@ -95,8 +95,6 @@ int32_t ls_get_power(class LightStateClass* l) { } void ls_set_xy(class LightStateClass* l, float x, float y) { uint8_t rr, gg, bb; - uint16_t hue; - uint8_t sat; XyToRgb(x, y, &rr, &gg, &bb); l->setRGB(rr, gg, bb, false); } diff --git a/tasmota/xdrv_52_3_berry_lvgl.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_lvgl.ino similarity index 99% rename from tasmota/xdrv_52_3_berry_lvgl.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_lvgl.ino index fcd270179..56aa6e833 100644 --- a/tasmota/xdrv_52_3_berry_lvgl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_lvgl.ino @@ -306,7 +306,7 @@ extern "C" { { "montserrat", lv_montserrat_fonts }, { "seg7", lv_seg7_fonts }, { "unscii", lv_unscii_fonts}, -#ifdef USE_LVGL_OPENHASP +#ifdef USE_LVGL_HASPMOTA { "robotocondensed", lv_robotocondensed_fonts }, #endif { nullptr, nullptr} @@ -355,9 +355,9 @@ extern "C" { } int lv0_load_robotocondensed_latin1_font(bvm *vm) { -#ifdef USE_LVGL_OPENHASP +#ifdef USE_LVGL_HASPMOTA return lv_load_embedded_font(vm, "robotocondensed", 0); -#endif // USE_LVGL_OPENHASP +#endif // USE_LVGL_HASPMOTA be_raise(vm, kTypeError, nullptr); } diff --git a/tasmota/xdrv_52_3_berry_mqtt.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_mqtt.ino similarity index 100% rename from tasmota/xdrv_52_3_berry_mqtt.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_mqtt.ino diff --git a/tasmota/xdrv_52_3_berry_onewire.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_onewire.ino similarity index 100% rename from tasmota/xdrv_52_3_berry_onewire.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_onewire.ino diff --git a/tasmota/xdrv_52_3_berry_serial.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_serial.ino similarity index 100% rename from tasmota/xdrv_52_3_berry_serial.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_serial.ino diff --git a/tasmota/xdrv_52_3_berry_tasmota.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino similarity index 100% rename from tasmota/xdrv_52_3_berry_tasmota.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino diff --git a/tasmota/xdrv_52_3_berry_tasmota_global.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota_global.ino similarity index 100% rename from tasmota/xdrv_52_3_berry_tasmota_global.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota_global.ino diff --git a/tasmota/xdrv_52_3_berry_webclient.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webclient.ino similarity index 100% rename from tasmota/xdrv_52_3_berry_webclient.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webclient.ino diff --git a/tasmota/xdrv_52_3_berry_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webserver.ino similarity index 100% rename from tasmota/xdrv_52_3_berry_webserver.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webserver.ino diff --git a/tasmota/xdrv_52_3_berry_wire.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_wire.ino similarity index 100% rename from tasmota/xdrv_52_3_berry_wire.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_wire.ino diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_zigbee.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_zigbee.ino new file mode 100644 index 000000000..e0ff79ab2 --- /dev/null +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_zigbee.ino @@ -0,0 +1,262 @@ +/* + xdrv_52_3_berry_zigbee.ino - Berry scripting language, native fucnctions + + Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Mappgin from internal light and a generic `light_state` Berry class + +#ifdef USE_BERRY +#ifdef USE_ZIGBEE + +#include "berry.h" +#include "be_func.h" + +extern "C" { + extern const bclass be_class_zb_device; + + // Zigbee Device `zd` + const void* zd_init(const class Z_Device* device) { + return device; + } + + int32_t zd_shortaddr(const class Z_Device* d) { + return d->shortaddr; + } + const void* zd_longaddr(const class Z_Device* d, size_t *size, void* p2) { + *size = 8; // 64 bits + return &d->longaddr; + } + + const char* zd_manufacturer(const class Z_Device* d) { + return d->manufacturerId ? d->manufacturerId : ""; + } + extern const char* zd_model(const class Z_Device* d) { + return d->modelId ? d->modelId : ""; + } + extern const char* zd_name(const class Z_Device* d) { + return d->friendlyName ? d->friendlyName : ""; + } + bool zd_router(const class Z_Device* d) { + return d->is_router; + } + bool zd_hidden(const class Z_Device* d) { + return d->hidden; + } + bool zd_reachable(const class Z_Device* d) { + return d->reachable; + } + int32_t zd_lastseen(const class Z_Device* d) { + return d->last_seen; + } + int32_t zd_lqi(const class Z_Device* d) { + return d->lqi == 255 ? -1 : d->lqi; + } + int32_t zd_battery(const class Z_Device* d) { + return d->batterypercent == 255 ? -1 : d->batterypercent; + } + int32_t zd_battery_lastseen(const class Z_Device* d) { + return 0; // TODO not yet known + } +} + +extern "C" { + // Zigbee Coordinator `zc` + int zc_info(struct bvm *vm); + int zc_info(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 1) { // no argument (instance only) + be_newobject(vm, "map"); + be_map_insert_int(vm, "channel", Settings->zb_channel); + be_map_insert_int(vm, "tx_radio", Settings->zb_txradio_dbm); + char tmp[24]; + ext_snprintf_P(tmp, sizeof(tmp), "0x%04X", Settings->zb_pan_id); + be_map_insert_str(vm, "pan_id_hex", tmp); + be_map_insert_int(vm, "pan_id", Settings->zb_pan_id); + ext_snprintf_P(tmp, sizeof(tmp), "0x%_X", &Settings->zb_ext_panid); + be_map_insert_str(vm, "ext_pan_id", tmp); + ext_snprintf_P(tmp, sizeof(tmp), "0x%04X", localShortAddr); + be_map_insert_str(vm, "shortaddr_hex", tmp); + be_map_insert_int(vm, "shortaddr", localShortAddr); + ext_snprintf_P(tmp, sizeof(tmp), "0x%_X", &localIEEEAddr); + be_map_insert_str(vm, "longaddr", tmp); + be_pop(vm, 1); + be_return(vm); + } + be_raise(vm, kTypeError, nullptr); + } + + int zc_item(struct bvm *vm); + int zc_item(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (zigbee.init_phase) { + be_raise(vm, "internal_error", "zigbee not started"); + } + if (top >= 2 && (be_isint(vm, 2) || be_isstring(vm, 2))) { + const Z_Device & device = be_isint(vm, 2) ? zigbee_devices.findShortAddr(be_toint(vm, 2)) + : zigbee_devices.parseDeviceFromName(be_tostring(vm, 2)); + if (!device.valid()) { + be_raise(vm, "value_error", "unknown device"); + } + + be_pushntvclass(vm, &be_class_zb_device); + be_pushcomptr(vm, (void*) &device); + be_call(vm, 1); + be_pop(vm, 1); + be_return(vm); + } + be_raise(vm, kTypeError, nullptr); + } + + int32_t zc_size(void*) { + return zigbee_devices.devicesSize(); + } + + // stop zigbee, abort + // The abort state corresponds to state machine stopped but init not finished + void zc_abort(void) { + zigbee.active = false; + zigbee.state_machine = false; // not ready + zigbee.init_phase = false; + } + + // iterator for devices in the coordinator's list of devices + // upval 0: index from 0 to size-1 + static int zc_iter_closure(bvm *vm) + { + /* for better performance, we operate the upvalues + * directly without using by the stack. */ + bntvclos *func = (bntvclos*) var_toobj(vm->cf->func); + bvalue *uv0 = be_ntvclos_upval(func, 0)->value; + bint idx = var_toint(uv0); /* upvalue[0] => lower */ + if (idx >= zigbee_devices.devicesSize()) { + be_stop_iteration(vm); + } + var_toint(uv0) = idx + 1; /* set upvale[0] */ + be_pushntvclass(vm, &be_class_zb_device); + const Z_Device & device = zigbee_devices.isKnownIndexDevice(idx); + be_pushcomptr(vm, (void*) &device); + be_call(vm, 1); + be_pop(vm, 1); + be_return(vm); + } + + int zc_iter(bvm *vm); + int zc_iter(bvm *vm) { + if (zigbee.init_phase) { + be_raise(vm, "internal_error", "zigbee not started"); + } + be_pushntvclosure(vm, zc_iter_closure, 1); + be_pushint(vm, 0); + be_setupval(vm, -2, 0); + be_pop(vm, 1); + be_return(vm); + } + + int32_t callBerryZigbeeDispatcher(const char* cmd, const char* type, void* data, int32_t idx); + int32_t callBerryZigbeeDispatcher(const char* cmd, const char* type, void* data, int32_t idx) { + int32_t ret = 0; + bvm *vm = berry.vm; + + if (nullptr == vm) { return ret; } + checkBeTop(); + be_getglobal(vm, PSTR("zigbee")); // global object of type zb_coord() + if (!be_isnil(vm, -1)) { + be_getmethod(vm, -1, PSTR("dispatch")); // method dispatch + if (!be_isnil(vm, -1)) { + be_pushvalue(vm, -2); // add instance as first arg + be_pushstring(vm, cmd != nullptr ? cmd : ""); + be_pushstring(vm, type != nullptr ? type : ""); + be_pushcomptr(vm, data); + be_pushint(vm, idx); + BrTimeoutStart(); + ret = be_pcall(vm, 5); // 5 arguments + BrTimeoutReset(); + if (ret != 0) { + be_error_pop_all(berry.vm); // clear Berry stack + return ret; + } + be_pop(vm, 5); + if (be_isint(vm, -1) || be_isbool(vm, -1)) { + if (be_isint(vm, -1)) { ret = be_toint(vm, -1); } + if (be_isbool(vm, -1)) { ret = be_tobool(vm, -1); } + } + } + be_pop(vm, 1); // remove method + } + be_pop(vm, 1); // remove instance object + checkBeTop(); + return ret; + } + +} + +/*********************************************************************************************\ + * Mapping for zcl_message + * +\*********************************************************************************************/ +extern "C" { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winvalid-offsetof" // avoid warnings since we're using offsetof() in a risky way + + extern const be_ctypes_structure_t be_zigbee_zcl_frame_struct = { + sizeof(ZCLFrame), /* size in bytes */ + 12, /* number of elements */ + nullptr, + (const be_ctypes_structure_item_t[12]) { + { "cluster", offsetof(ZCLFrame, cluster), 0, 0, ctypes_u16, 0 }, + { "cluster_specific", offsetof(ZCLFrame, clusterSpecific), 0, 0, ctypes_u8, 0 }, + { "cmd", offsetof(ZCLFrame, cmd), 0, 0, ctypes_u8, 0 }, + { "direct", offsetof(ZCLFrame, direct), 0, 0, ctypes_u8, 0 }, + { "dstendpoint", offsetof(ZCLFrame, dstendpoint), 0, 0, ctypes_u8, 0 }, + { "groupaddr", offsetof(ZCLFrame, groupaddr), 0, 0, ctypes_u16, 0 }, + { "manuf", offsetof(ZCLFrame, manuf), 0, 0, ctypes_u16, 0 }, + { "need_response", offsetof(ZCLFrame, needResponse), 0, 0, ctypes_u8, 0 }, + { "payload_ptr", offsetof(ZCLFrame, payload), 0, 0, ctypes_ptr32, 0 }, + { "shortaddr", offsetof(ZCLFrame, shortaddr), 0, 0, ctypes_u16, 0 }, + { "transactseq", offsetof(ZCLFrame, transactseq), 0, 0, ctypes_u8, 0 }, + { "transactseq_set", offsetof(ZCLFrame, transacSet), 0, 0, ctypes_u8, 0 }, + }}; + +#pragma GCC diagnostic pop +} + +/*********************************************************************************************\ + * Functions for zcl_frame + * +\*********************************************************************************************/ +extern "C" { + void* zfn_get_bytes(void* sbuf_ptr, size_t *len_bytes) { + if (sbuf_ptr == NULL || len_bytes == NULL) { return NULL; } + const SBuffer &sbuf = (const SBuffer&) sbuf_ptr; + + *len_bytes = sbuf.getLen(); + return sbuf.getBuffer(); + } + + void zfn_set_bytes(void* sbuf_ptr, const uint8_t* bytes, size_t len_bytes) { + if (sbuf_ptr == NULL || bytes == NULL) { return; } + + SBuffer &sbuf = (SBuffer&) sbuf_ptr; + + sbuf.reserve(len_bytes); // make sure it's large enough + sbuf.setLen(0); // clear content + sbuf.addBuffer(bytes, len_bytes); // add content of bytes() buffer + } +} + +#endif // USE_ZIGBEE +#endif // USE_BERRY diff --git a/tasmota/xdrv_52_7_berry_embedded.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_7_berry_embedded.ino similarity index 100% rename from tasmota/xdrv_52_7_berry_embedded.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_7_berry_embedded.ino diff --git a/tasmota/xdrv_52_9_berry.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino similarity index 99% rename from tasmota/xdrv_52_9_berry.ino rename to tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino index 5e5c3e0e5..e4c302bdb 100644 --- a/tasmota/xdrv_52_9_berry.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino @@ -112,7 +112,6 @@ bool callBerryRule(const char *event, bool teleperiod) { bool exec_rule = !save_rules_busy; // true if the rule is executed, false if we only record the value // if (berry.rules_busy) { return false; } berry.rules_busy = true; - char * json_event = XdrvMailbox.data; bool serviced = false; serviced = callBerryEventDispatcher(teleperiod ? "tele" : "rule", nullptr, exec_rule, event ? event : XdrvMailbox.data); berry.rules_busy = save_rules_busy; @@ -345,9 +344,6 @@ void BerryInit(void) { void BrLoad(const char * script_name) { if (berry.vm == nullptr || TasmotaGlobal.no_autoexec) { return; } // abort is berry is not running, or bootloop prevention kicked in - int32_t ret_code1, ret_code2; - bool berry_init_ok = false; - be_getglobal(berry.vm, PSTR("load")); if (!be_isnil(berry.vm, -1)) { be_pushstring(berry.vm, script_name); @@ -376,7 +372,7 @@ void BrLoad(const char * script_name) { // void CmndBrRun(void) { int32_t ret_code; - const char * ret_type, * ret_val; + const char * ret_val; if (berry.vm == nullptr) { ResponseCmndChar_P(PSTR(D_BR_NOT_STARTED)); return; } diff --git a/tasmota/xdrv_53_projector_ctrl.ino b/tasmota/tasmota_xdrv_driver/xdrv_53_projector_ctrl.ino similarity index 99% rename from tasmota/xdrv_53_projector_ctrl.ino rename to tasmota/tasmota_xdrv_driver/xdrv_53_projector_ctrl.ino index 1fd8f8446..be0af2e5a 100644 --- a/tasmota/xdrv_53_projector_ctrl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_53_projector_ctrl.ino @@ -72,7 +72,7 @@ struct projector_ctrl_command_info_s { const uint8_t fail_value_bytes; } __packed; -#include "xdrv_53_projector_ctrl.h" +#include "include/xdrv_53_projector_ctrl.h" struct projector_ctrl_softc_s { TasmotaSerial *sc_serial; diff --git a/tasmota/xdrv_54_lvgl.ino b/tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino similarity index 100% rename from tasmota/xdrv_54_lvgl.ino rename to tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino diff --git a/tasmota/xdrv_55_touch.ino b/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino similarity index 100% rename from tasmota/xdrv_55_touch.ino rename to tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino diff --git a/tasmota/xdrv_56_rtc_chips.ino b/tasmota/tasmota_xdrv_driver/xdrv_56_rtc_chips.ino similarity index 100% rename from tasmota/xdrv_56_rtc_chips.ino rename to tasmota/tasmota_xdrv_driver/xdrv_56_rtc_chips.ino diff --git a/tasmota/xdrv_57_1_tasmesh_support.ino b/tasmota/tasmota_xdrv_driver/xdrv_57_1_tasmesh_support.ino similarity index 100% rename from tasmota/xdrv_57_1_tasmesh_support.ino rename to tasmota/tasmota_xdrv_driver/xdrv_57_1_tasmesh_support.ino diff --git a/tasmota/xdrv_57_9_tasmesh.ino b/tasmota/tasmota_xdrv_driver/xdrv_57_9_tasmesh.ino similarity index 100% rename from tasmota/xdrv_57_9_tasmesh.ino rename to tasmota/tasmota_xdrv_driver/xdrv_57_9_tasmesh.ino diff --git a/tasmota/xdrv_58_range_extender.ino b/tasmota/tasmota_xdrv_driver/xdrv_58_range_extender.ino similarity index 100% rename from tasmota/xdrv_58_range_extender.ino rename to tasmota/tasmota_xdrv_driver/xdrv_58_range_extender.ino diff --git a/tasmota/xdrv_59_influxdb.ino b/tasmota/tasmota_xdrv_driver/xdrv_59_influxdb.ino similarity index 100% rename from tasmota/xdrv_59_influxdb.ino rename to tasmota/tasmota_xdrv_driver/xdrv_59_influxdb.ino diff --git a/tasmota/xdrv_60_shift595.ino b/tasmota/tasmota_xdrv_driver/xdrv_60_shift595.ino similarity index 100% rename from tasmota/xdrv_60_shift595.ino rename to tasmota/tasmota_xdrv_driver/xdrv_60_shift595.ino diff --git a/tasmota/xdrv_61_ds3502.ino b/tasmota/tasmota_xdrv_driver/xdrv_61_ds3502.ino similarity index 100% rename from tasmota/xdrv_61_ds3502.ino rename to tasmota/tasmota_xdrv_driver/xdrv_61_ds3502.ino diff --git a/tasmota/xdrv_62_improv.ino b/tasmota/tasmota_xdrv_driver/xdrv_62_improv.ino similarity index 100% rename from tasmota/xdrv_62_improv.ino rename to tasmota/tasmota_xdrv_driver/xdrv_62_improv.ino diff --git a/tasmota/xdrv_79_esp32_ble.ino b/tasmota/tasmota_xdrv_driver/xdrv_79_esp32_ble.ino similarity index 100% rename from tasmota/xdrv_79_esp32_ble.ino rename to tasmota/tasmota_xdrv_driver/xdrv_79_esp32_ble.ino diff --git a/tasmota/xdrv_81_esp32_webcam.ino b/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam.ino similarity index 97% rename from tasmota/xdrv_81_esp32_webcam.ino rename to tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam.ino index fb75a5ffa..b49f781d8 100644 --- a/tasmota/xdrv_81_esp32_webcam.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam.ino @@ -729,6 +729,34 @@ pcopy: return _jpg_buf_len; } +//////////////// Handle authentication ///////////////// + + +bool WebcamAuthenticate(void) +{ + if (strlen(SettingsText(SET_WEBPWD)) && (HTTP_MANAGER_RESET_ONLY != Web.state)) { + return Wc.CamServer->authenticate(WEB_USERNAME, SettingsText(SET_WEBPWD)); + } else { + return true; + } +} + +bool WebcamCheckPriviledgedAccess(bool autorequestauth = true) +{ + + if(Settings->webcam_config2.auth == 0){ + return true; + } + + if (autorequestauth && !WebcamAuthenticate()) { + Wc.CamServer->requestAuthentication(); + return false; + } + return true; +} + +/////////////////////////////////////////////////// + void HandleImage(void) { if (!HttpCheckPriviledgedAccess()) { return; } @@ -818,6 +846,10 @@ void HandleImageBasic(void) { } void HandleWebcamMjpeg(void) { + if(!WebcamCheckPriviledgedAccess()){ + Wc.CamServer->send(403,"",""); + return; + } AddLog(LOG_LEVEL_DEBUG, PSTR("CAM: Handle camserver")); // if (!Wc.stream_active) { // always restart stream @@ -910,8 +942,12 @@ void HandleWebcamMjpegTask(void) { } void HandleWebcamRoot(void) { + if(!WebcamCheckPriviledgedAccess()){ + Wc.CamServer->send(403,"",""); + return; + } //CamServer->redirect("http://" + String(ip) + ":81/cam.mjpeg"); - Wc.CamServer->sendHeader("Location", WiFi.localIP().toString() + ":81/cam.mjpeg"); + Wc.CamServer->sendHeader("Location", "/cam.mjpeg"); Wc.CamServer->send(302, "", ""); AddLog(LOG_LEVEL_DEBUG, PSTR("CAM: Root called")); } @@ -1081,6 +1117,8 @@ void WcInit(void) { #define D_CMND_WC_INIT "Init" #define D_CMND_RTSP "Rtsp" +#define D_CMND_WC_AUTH "Auth" + const char kWCCommands[] PROGMEM = D_PRFX_WEBCAM "|" // Prefix "|" D_CMND_WC_STREAM "|" D_CMND_WC_RESOLUTION "|" D_CMND_WC_MIRROR "|" D_CMND_WC_FLIP "|" D_CMND_WC_SATURATION "|" D_CMND_WC_BRIGHTNESS "|" D_CMND_WC_CONTRAST "|" D_CMND_WC_SPECIALEFFECT "|" @@ -1088,7 +1126,7 @@ const char kWCCommands[] PROGMEM = D_PRFX_WEBCAM "|" // Prefix D_CMND_WC_AEC_VALUE "|" D_CMND_WC_AE_LEVEL "|" D_CMND_WC_AEC2 "|" D_CMND_WC_AGC "|" D_CMND_WC_AGC_GAIN "|" D_CMND_WC_GAINCEILING "|" D_CMND_WC_RAW_GMA "|" D_CMND_WC_LENC "|" D_CMND_WC_WPC "|" D_CMND_WC_DCW "|" D_CMND_WC_BPC "|" D_CMND_WC_COLORBAR "|" D_CMND_WC_FEATURE "|" - D_CMND_WC_SETDEFAULTS "|" D_CMND_WC_STATS "|" D_CMND_WC_INIT + D_CMND_WC_SETDEFAULTS "|" D_CMND_WC_STATS "|" D_CMND_WC_INIT "|" D_CMND_WC_AUTH #ifdef ENABLE_RTSPSERVER "|" D_CMND_RTSP #endif // ENABLE_RTSPSERVER @@ -1101,7 +1139,7 @@ void (* const WCCommand[])(void) PROGMEM = { &CmndWebcamAELevel, &CmndWebcamAEC2, &CmndWebcamAGC, &CmndWebcamAGCGain, &CmndWebcamGainCeiling, &CmndWebcamGammaCorrect, &CmndWebcamLensCorrect, &CmndWebcamWPC, &CmndWebcamDCW, &CmndWebcamBPC, &CmndWebcamColorbar, &CmndWebcamFeature, &CmndWebcamSetDefaults, - &CmndWebcamStats, &CmndWebcamInit + &CmndWebcamStats, &CmndWebcamInit, &CmndWebcamAuth #ifdef ENABLE_RTSPSERVER , &CmndWebRtsp #endif // ENABLE_RTSPSERVER @@ -1116,7 +1154,7 @@ void CmndWebcam(void) { D_CMND_WC_AE_LEVEL "\":%d,\"" D_CMND_WC_AEC2 "\":%d,\"" D_CMND_WC_AGC "\":%d,\"" D_CMND_WC_AGC_GAIN "\":%d,\"" D_CMND_WC_GAINCEILING "\":%d,\"" D_CMND_WC_RAW_GMA "\":%d,\"" D_CMND_WC_LENC "\":%d,\"" D_CMND_WC_WPC "\":%d,\"" D_CMND_WC_DCW "\":%d,\"" D_CMND_WC_BPC "\":%d,\"" - D_CMND_WC_COLORBAR "\":%d,\"" D_CMND_WC_FEATURE "\":%d" + D_CMND_WC_COLORBAR "\":%d,\"" D_CMND_WC_FEATURE "\":%d,\"" D_CMND_WC_AUTH "\":%d" #ifdef ENABLE_RTSPSERVER ",\"" D_CMND_RTSP "\":%d" #endif // ENABLE_RTSPSERVER @@ -1129,7 +1167,7 @@ void CmndWebcam(void) { Settings->webcam_config2.ae_level -2, Settings->webcam_config.aec2, Settings->webcam_config.agc, Settings->webcam_config2.agc_gain, Settings->webcam_config2.gainceiling, Settings->webcam_config.raw_gma, Settings->webcam_config.lenc, Settings->webcam_config.wpc, Settings->webcam_config.dcw, Settings->webcam_config.bpc, - Settings->webcam_config.colorbar, Settings->webcam_config.feature + Settings->webcam_config.colorbar, Settings->webcam_config.feature, Settings->webcam_config2.auth #ifdef ENABLE_RTSPSERVER , Settings->webcam_config.rtsp #endif // ENABLE_RTSPSERVER @@ -1336,6 +1374,13 @@ void CmndWebcamFeature(void) { ResponseCmndNumber(Settings->webcam_config.feature); } +void CmndWebcamAuth(void){ + if((XdrvMailbox.payload >=0) && (XdrvMailbox.payload <= 1)){ + Settings->webcam_config2.auth = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings->webcam_config2.auth); +} + void CmndWebcamInit(void) { WcInterruptControl(); ResponseCmndDone(); diff --git a/tasmota/xdrv_82_esp32_ethernet.ino b/tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino similarity index 100% rename from tasmota/xdrv_82_esp32_ethernet.ino rename to tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino diff --git a/tasmota/xdrv_83_esp32_watch.ino b/tasmota/tasmota_xdrv_driver/xdrv_83_esp32_watch.ino similarity index 100% rename from tasmota/xdrv_83_esp32_watch.ino rename to tasmota/tasmota_xdrv_driver/xdrv_83_esp32_watch.ino diff --git a/tasmota/xdrv_85_esp32_ble_eq3_trv.ino b/tasmota/tasmota_xdrv_driver/xdrv_85_esp32_ble_eq3_trv.ino similarity index 100% rename from tasmota/xdrv_85_esp32_ble_eq3_trv.ino rename to tasmota/tasmota_xdrv_driver/xdrv_85_esp32_ble_eq3_trv.ino diff --git a/tasmota/xdrv_86_esp32_sonoff_spm.ino b/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino similarity index 93% rename from tasmota/xdrv_86_esp32_sonoff_spm.ino rename to tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino index 55b91e1c1..ca25ba979 100644 --- a/tasmota/xdrv_86_esp32_sonoff_spm.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino @@ -49,7 +49,7 @@ * - Yellow led blinks 2 seconds if an ARM-ESP comms CRC error is detected. * - Persistence for module mapping, total energy and energy yesterday * - Supported commands: - * SspmDisplay 0|1 - Select alternative GUI rotating display either all (0) or powered on only (1) + * SspmDisplay 0|1|2 - Select alternative GUI rotating display either all (0), powered on only (1) or user selected (2) * SspmDump 0|1 - Select shortenend (0) or full (1) serial receive buffer dumps * SspmEnergyTotal - (p)reset total energy without today's energy * SspmEnergyYesterday - (p)reset energy yesterday @@ -124,7 +124,7 @@ #define SSPM_MAX_MODULES 8 // Currently supports up to 8 SPM-4RELAY units for a total of 32 relays restricted by 32-bit power_t size #define SSPM_SERIAL_BUFFER_SIZE 548 // Needs to accomodate firmware upload data blocks (546 bytes) -//#define SSPM_SIMULATE 2 // Simulate additional 4Relay modules based on first detected 4Relay module (debugging purposes only!!) +//#define SSPM_SIMULATE // Simulate additional 4Relay modules based on first detected 4Relay module (debugging purposes only!!) // From ESP to ARM #define SSPM_FUNC_FIND 0 // 0x00 @@ -137,16 +137,15 @@ #define SSPM_FUNC_SET_TIME 12 // 0x0C #define SSPM_FUNC_IAMHERE 13 // 0x0D #define SSPM_FUNC_INIT_SCAN 16 // 0x10 -#define SSPM_FUNC_UPLOAD_HEADER 20 // 0x14 - Upload header +#define SSPM_FUNC_UPLOAD_HEADER 20 // 0x14 - SPI Upload header #define SSPM_FUNC_UNITS 21 // 0x15 #define SSPM_FUNC_GET_ENERGY_TOTAL 22 // 0x16 #define SSPM_FUNC_GET_ENERGY 24 // 0x18 #define SSPM_FUNC_GET_LOG 26 // 0x1A #define SSPM_FUNC_ENERGY_PERIOD 27 // 0x1B #define SSPM_FUNC_RESET 28 // 0x1C - Remove device from eWelink and factory reset -#define SSPM_FUNC_ARM_RESTART 30 // 0x1E - Restart ARM -#define SSPM_FUNC_UPLOAD_DATA 31 // 0x1F - Upload incremental data blocks of max 512 bytes to ARM -#define SSPM_FUNC_UPLOAD_DONE 33 // 0x21 - Finish upload +#define SSPM_FUNC_UPLOAD_DATA 31 // 0x1F - SPI Upload incremental data blocks of max 512 bytes to ARM +#define SSPM_FUNC_UPLOAD_DONE 33 // 0x21 - SPI Finish upload #define SSPM_FUNC_GET_NEW1 37 // 0x25 // From ARM to ESP @@ -155,6 +154,7 @@ #define SSPM_FUNC_SCAN_START 15 // 0x0F #define SSPM_FUNC_SCAN_RESULT 19 // 0x13 #define SSPM_FUNC_SCAN_DONE 25 // 0x19 +#define SSPM_FUNC_UPLOAD_DONE_ACK 30 // 0x1E - Restart ARM // Unknown #define SSPM_FUNC_01 1 // 0x01 @@ -201,6 +201,8 @@ enum SspmMachineStates { SPM_NONE, // Do nothing SPM_UPDATE_CHANNELS // Update Energy for powered on channels }; +enum SspmDisplayModes { SPM_DISPLAY_ROTATE, SPM_DISPLAY_ROTATE_POWERED_ON, SPM_DISPLAY_TABS, SPM_DISPLAY_MAX_OPTION }; + const char kSSPMTriggers[] PROGMEM = "Tasmota|Device|Overload|Overtemp"; const char kSSPMOverload[] PROGMEM = "Tbd1|Voltage|Current|Power|Tbd2|Tbd3|Tbd4"; @@ -210,9 +212,8 @@ TasmotaSerial *SspmSerial; typedef union { uint16_t data; struct { - uint16_t dump : 1; // bit 0 (v10.1.0.6) - SSPMDump - Short receive dump (0) or full receive dump (1) - uint16_t display : 1; // bit 1 (v10.1.0.6) - SSPMDisplay - GUI display all relays (0) or only powered on relays (1) - uint16_t spare02 : 1; // bit 2 + uint16_t dump : 1; // bit 0 (v10.1.0.6) - SSPMDump - Short receive dump (0) or full receive dump (1) + uint16_t display : 2; // bit 1,2 (v10.1.0.6) - SSPMDisplay - GUI display all relays (0), only powered on relays (1) or user selected relays (2) uint16_t spare03 : 1; // bit 3 uint16_t spare04 : 1; // bit 4 uint16_t spare05 : 1; // bit 5 @@ -236,6 +237,7 @@ typedef struct { uint16_t module_map[SSPM_TOTAL_MODULES]; // Max possible SPM relay modules float energy_total[SSPM_TOTAL_MODULES][4]; // Total energy in kWh - float allows up to 262143.99 kWh float energy_yesterday[SSPM_TOTAL_MODULES][4]; // Energy yesterday in kWh - float allows up to 262143.99 kWh + uint32_t simulate_count; } tSspmSettings; typedef struct { @@ -278,6 +280,7 @@ typedef struct { #endif uint8_t allow_updates; uint8_t get_energy_relay; + int8_t get_energy_relay_focus; uint8_t get_totals; uint8_t rotate; uint8_t module_max; @@ -315,6 +318,7 @@ void SSPMSettingsDefault(void) { memset(&Sspm->Settings, 0x00, sizeof(tSspmSettings)); Sspm->Settings.version = SSPM_VERSION; + Sspm->Settings.flag.display = SPM_DISPLAY_TABS; // Init any other parameter in struct SSPMSettings } @@ -412,9 +416,11 @@ uint32_t SSPMGetMappedModuleId(uint32_t module) { module_nr = module; // input module number if not found used as fallback } #ifdef SSPM_SIMULATE - Sspm->simulated_module = module_nr; - if (Sspm->simulate && (module_nr > 0) && (module_nr <= Sspm->simulate)) { - module_nr = 0; // Emulate modules by 0 + if (Sspm->Settings.simulate_count) { + Sspm->simulated_module = module_nr; + if (Sspm->simulate && (module_nr > 0) && (module_nr <= Sspm->simulate)) { + module_nr = 0; // Emulate modules by 0 + } } #endif return (uint32_t)module_nr; // 0, 1, ... @@ -535,6 +541,20 @@ void SSPMSendCmnd(uint32_t command) { /*********************************************************************************************/ +void SSPMSendFindAck(void) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 01 00 00 FC 73 + Marker |Module id |Ac|Cm|Size | |Ix|Chksm| + */ + SSPMInitSend(); + SspmBuffer[15] = 0x80; // Ack +// SspmBuffer[16] = SSPM_FUNC_FIND; // 0x00 + SspmBuffer[18] = 1; + SspmBuffer[19] = 0; + SSPMSend(23); +} + void SSPMSendOPS(uint32_t relay) { /* Overload Protection @@ -799,21 +819,6 @@ void SSPMSendInitScan(void) { AddLog(LOG_LEVEL_DEBUG, PSTR("SPM: Start relay scan...")); } -void SSPMSendUploadHeader(void) { - /* - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 - AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 14 00 0b 09 09 00 1b e5 a4 c7 00 02 88 74 00 6d df - Marker | | |Cm|Size | |Checksum |UploadSize |Ix|Chksm| - */ - SSPMInitSend(); - SspmBuffer[16] = SSPM_FUNC_UPLOAD_HEADER; // 0x14 - SspmBuffer[18] = 0x0B; - - - SspmBuffer[30] = 0; - SSPMSend(33); -} - void SSPMSendGetEnergyTotal(uint32_t relay) { /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 @@ -923,49 +928,6 @@ void SSPMSendGetEnergyPeriod(uint32_t relay) { } -void SSPMSendArmRestart(void) { - /* - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 - aa 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 1e 00 01 00 01 fe 05 - Marker | | |Cm|Size | |Ix|Chksm| - */ - SSPMInitSend(); - SspmBuffer[16] = SSPM_FUNC_ARM_RESTART; // 0x1E - SspmBuffer[18] = 1; - Sspm->command_sequence++; - SspmBuffer[20] = Sspm->command_sequence; - SSPMSend(23); -} - -void SSPMSendUpload(void) { - /* - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 539 540 541 542 543 544 545 - AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 1f 02 0c 00 00 00 00 00 00 02 00 a2 99 c3 22 00 00 01 20 cd 95 01 08 ... 04 48 af f3 01 xx yy - AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 1f 02 0c 00 00 02 00 00 00 02 00 27 f7 24 87 00 80 01 23 23 70 10 bd ... 21 fa 04 f3 02 xx yy - ... - AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 1f 02 0c 00 02 86 00 00 00 02 00 f8 f5 25 6d f1 61 00 08 02 01 ff 00 ... 44 xx yy - AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 1f 00 80 00 02 88 00 00 00 00 74 95 4e 01 c1 c5 e5 02 08 c5 e5 02 08 ... 45 xx yy - Marker | | |Cm|Size |Address |UploadSize |Checksum |512 data bytes |Ix |Chksm | - */ - SSPMInitSend(); - SspmBuffer[16] = SSPM_FUNC_UPLOAD_DATA; // 0x1F - - - - Sspm->command_sequence++; - SspmBuffer[543] = Sspm->command_sequence; - SSPMSend(546); -} - -void SSPMSendUploadDone(void) { - /* - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 - AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 21 00 00 46 32 da - Marker | | |Cm|Size |Ix|Chksm| - */ - SSPMSendCmnd(SSPM_FUNC_UPLOAD_DONE); // 0x21 -} - void SSPMSendGetNew1(uint32_t module) { /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @@ -1162,7 +1124,7 @@ void SSPMHandleReceivedData(void) { // SspmBuffer[20] & 0x0F // Relays operational uint32_t module = SSPMGetModuleNumberFromMap(SspmBuffer[3] << 8 | SspmBuffer[4]); #ifdef SSPM_SIMULATE - module = Sspm->simulated_module; + if (Sspm->Settings.simulate_count) { module = Sspm->simulated_module; } #endif power_t current_state = (SspmBuffer[20] >> 4) << (module * 4); // Relays state power_t mask = 0x0000000F << (module * 4); @@ -1259,7 +1221,7 @@ void SSPMHandleReceivedData(void) { uint32_t channel = SspmBuffer[32]; uint32_t module = SSPMGetModuleNumberFromMap(SspmBuffer[20] << 8 | SspmBuffer[21]); #ifdef SSPM_SIMULATE - module = Sspm->simulated_module; + if (Sspm->Settings.simulate_count) { module = Sspm->simulated_module; } #endif if (Sspm->history_relay < 255) { uint32_t history_module = Sspm->history_relay >> 2; @@ -1455,7 +1417,7 @@ void SSPMHandleReceivedData(void) { } uint32_t module = SSPMGetModuleNumberFromMap(SspmBuffer[19] << 8 | SspmBuffer[20]); #ifdef SSPM_SIMULATE - module = Sspm->simulated_module; + if (Sspm->Settings.simulate_count) { module = Sspm->simulated_module; } #endif Sspm->current[module][channel] = SspmBuffer[32] + (float)SspmBuffer[33] / 100; // x.xxA Sspm->voltage[module][channel] = SSPMGetValue(&SspmBuffer[34]); // x.xxV @@ -1481,7 +1443,7 @@ void SSPMHandleReceivedData(void) { if (!Sspm->no_send_key) { uint32_t module = SSPMGetModuleNumberFromMap(SspmBuffer[19] << 8 | SspmBuffer[20]); #ifdef SSPM_SIMULATE -// module = Sspm->simulated_module; // Won't work as this is initiated from device +// if (Sspm->Settings.simulate_count) { module = Sspm->simulated_module; } // Won't work as this is initiated from device #endif power_t relay = (SspmBuffer[31] & 0x0F) << (module * 4); // Relays active power_t relay_state = (SspmBuffer[31] >> 4) << (module * 4); // Relays state @@ -1565,10 +1527,10 @@ void SSPMHandleReceivedData(void) { if (0x24 == expected_bytes) { SSPMAddModule(); #ifdef SSPM_SIMULATE - if (0 == Sspm->simulate) { + if (Sspm->Settings.simulate_count && (0 == Sspm->simulate)) { uint8_t current_idh = SspmBuffer[19]; uint8_t current_idl = SspmBuffer[20]; - for (Sspm->simulate = 0; Sspm->simulate < SSPM_SIMULATE; Sspm->simulate++) { + for (Sspm->simulate = 0; Sspm->simulate < Sspm->Settings.simulate_count; Sspm->simulate++) { SspmBuffer[19] = Sspm->simulate +1; SspmBuffer[20] = Sspm->simulate +1; SSPMAddModule(); @@ -1635,6 +1597,14 @@ void SSPMHandleReceivedData(void) { SSPMSendSetTime(); break; + case SSPM_FUNC_UPLOAD_DONE_ACK: + /* 0x1E + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + aa 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 1e 00 01 00 01 fe 05 + Marker | | |Cm|Size | |Ix|Chksm| + */ + SSPMSendFindAck(); + break; } } } @@ -1766,6 +1736,54 @@ bool SSPMSendSPIFind(void) { return false; } +void SSPMSendSPIUploadHeader(void) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 14 00 0b 09 09 00 1b e5 a4 c7 00 02 88 74 00 6d df + Marker | | |Cm|Size | |Checksum |UploadSize |Ix|Chksm| + */ + SSPMInitSend(); + SspmBuffer[16] = SSPM_FUNC_UPLOAD_HEADER; // 0x14 + SspmBuffer[18] = 0x0B; + + + SspmBuffer[30] = 0; + SSPMSendSPI(33); +} + +void SSPMSendSPIUpload(void) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 539 540 541 542 543 544 545 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 1f 02 0c 00 00 00 00 00 00 02 00 a2 99 c3 22 00 00 01 20 cd 95 01 08 ... 04 48 af f3 01 xx yy + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 1f 02 0c 00 00 02 00 00 00 02 00 27 f7 24 87 00 80 01 23 23 70 10 bd ... 21 fa 04 f3 02 xx yy + ... + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 1f 02 0c 00 02 86 00 00 00 02 00 f8 f5 25 6d f1 61 00 08 02 01 ff 00 ... 44 xx yy + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 1f 00 80 00 02 88 00 00 00 00 74 95 4e 01 c1 c5 e5 02 08 c5 e5 02 08 ... 45 xx yy + Marker | | |Cm|Size |Address |UploadSize |Checksum |512 data bytes |Ix |Chksm | + */ + SSPMInitSend(); + SspmBuffer[16] = SSPM_FUNC_UPLOAD_DATA; // 0x1F + + + + Sspm->command_sequence++; + SspmBuffer[543] = Sspm->command_sequence; + SSPMSendSPI(546); +} + +void SSPMSendSPIUploadDone(void) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 21 00 00 46 32 da + Marker | | |Cm|Size |Ix|Chksm| + */ + SSPMInitSend(); + SspmBuffer[16] = SSPM_FUNC_UPLOAD_DONE; // 0x21 + Sspm->command_sequence++; + SspmBuffer[19] = Sspm->command_sequence; + SSPMSendSPI(22); +} + /*********************************************************************************************/ void SSPMInit(void) { @@ -1848,7 +1866,7 @@ void SSPMEvery100ms(void) { // Fix race condition if the ARM doesn't respond if ((Sspm->mstate > SPM_NONE) && (Sspm->mstate < SPM_SEND_FUNC_UNITS)) { Sspm->counter++; - if (Sspm->counter > 20) { + if (Sspm->counter > 30) { Sspm->mstate = SPM_NONE; Sspm->error_led_blinks = 255; } @@ -1910,11 +1928,15 @@ void SSPMEvery100ms(void) { break; case SPM_SCAN_COMPLETE: // Scan sequence finished -#ifndef SSPM_SIMULATE - if (Sspm->power_on_state) { - TasmotaGlobal.power = Sspm->power_on_state; - Sspm->power_on_state = 0; // Reset power on state solving re-scan - SetPowerOnState(); // Set power on state now that all relays have been detected +#ifdef SSPM_SIMULATE + if (!Sspm->Settings.simulate_count) { +#endif + if (Sspm->power_on_state) { + TasmotaGlobal.power = Sspm->power_on_state; + Sspm->power_on_state = 0; // Reset power on state solving re-scan + SetPowerOnState(); // Set power on state now that all relays have been detected + } +#ifdef SSPM_SIMULATE } #endif TasmotaGlobal.discovery_counter = 1; // Force TasDiscovery() @@ -1937,6 +1959,7 @@ void SSPMEvery100ms(void) { Sspm->get_energy_relay++; if (Sspm->get_energy_relay >= TasmotaGlobal.devices_present) { Sspm->get_energy_relay = TasmotaGlobal.devices_present; + Sspm->get_energy_relay_focus = -1; Sspm->mstate = SPM_UPDATE_CHANNELS; } } @@ -1959,6 +1982,25 @@ void SSPMEvery100ms(void) { Sspm->get_totals = 0; } } + + // If focused on one module increase focused relay polling + if ((SPM_DISPLAY_TABS == Sspm->Settings.flag.display) && (TasmotaGlobal.devices_present > 8) && (0 == Sspm->get_totals)) { + if ((Sspm->get_energy_relay % 4) == 0) { // Every fourth relay + uint32_t next = Sspm->rotate +4; + if (next >= TasmotaGlobal.devices_present) { next = 0; } + if ((Sspm->get_energy_relay_focus > -1) || !((Sspm->get_energy_relay == Sspm->rotate) || (Sspm->get_energy_relay == next))) { + if (-1 == Sspm->get_energy_relay_focus) { + Sspm->get_energy_relay_focus = Sspm->get_energy_relay; + Sspm->get_energy_relay = Sspm->rotate; + } else { + Sspm->get_energy_relay = Sspm->get_energy_relay_focus; + Sspm->get_energy_relay_focus = -1; + } + } + } + } +// AddLog(LOG_LEVEL_DEBUG, PSTR("SPM: Totals %d, Relay %d"), Sspm->get_totals, Sspm->get_energy_relay); + power_t powered_on = TasmotaGlobal.power >> Sspm->get_energy_relay; if (powered_on &1) { SSPMSetLock(4); @@ -2084,41 +2126,58 @@ void SSPMEnergyShow(bool json) { ResponseAppend_P(PSTR("]}")); #ifdef USE_WEBSERVER } else { - uint8_t relay[SSPM_MAX_MODULES * 4]; + uint8_t relays[SSPM_MAX_MODULES * 4]; uint8_t indirect[SSPM_MAX_MODULES * 4]; - uint32_t index = 0; + uint32_t relay_show = 0; power_t power = TasmotaGlobal.power; for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { - if ((0 == Sspm->Settings.flag.display) || - ((1 == Sspm->Settings.flag.display) && (power >> i) &1)) { - relay[index] = i +1; - indirect[index] = i; - index++; + if ((SPM_DISPLAY_ROTATE == Sspm->Settings.flag.display) || + ((SPM_DISPLAY_ROTATE_POWERED_ON == Sspm->Settings.flag.display) && (power >> i) &1) || + (SPM_DISPLAY_TABS == Sspm->Settings.flag.display)) { + relays[relay_show] = i +1; + indirect[relay_show] = i; + relay_show++; } } - if (index) { - if (index > 4) { - Sspm->rotate++; - } else { - Sspm->rotate = 0; + if (relay_show) { + if (Sspm->Settings.flag.display != SPM_DISPLAY_TABS) { + if (relay_show > 4) { + Sspm->rotate++; + } else { + Sspm->rotate = 0; + } } - if (Sspm->rotate > ((index -1) | 0x3)) { // Always test in case index has changed due to use of SspmDisplay command + if (Sspm->rotate > ((relay_show -1) | 0x3)) { // Always test in case relay has changed due to use of SspmDisplay command Sspm->rotate = 0; } uint32_t offset = (Sspm->rotate >> 2) * 4; - uint32_t count = index - offset; + uint32_t count = relay_show - offset; if (count > 4) { count = 4; } + WSContentSend_P(PSTR("
")); // Close current table as we will use different column count + if (SPM_DISPLAY_TABS == Sspm->Settings.flag.display) { + uint32_t modules = relay_show / 4; + if (modules > 1) { + WSContentSend_P(PSTR("{t}")); // {t} = + uint32_t cols_width = 100 / modules; + uint32_t current_module = Sspm->rotate >> 2; + for (uint32_t idx = 0; idx < modules; idx++) { + WSContentSend_P(PSTR(""), // &k86 is related to WebGetArg("k", tmp, sizeof(tmp)); + cols_width, (current_module == idx) ? WebColor(COL_BACKGROUND) : WebColor(COL_FORM), (current_module == idx) ? "bold" : "normal", idx, (idx *4) +1); + } + WSContentSend_P(PSTR("
")); // Close current table as we will use different column count + } + } // {s}Head1{e} // {s}Head1Head2{e} // {s}Head1Head2Head3{e} // {s}Head1Head2Head3Head4{e} + WSContentSend_P(PSTR("{t}{s}")); // First column is empty ({t} = , {s} =
) char value_chr[SSPM_SIZE]; - WSContentSend_P(PSTR("

{t}{s}")); // First column is empty ({t} = , {s} = "), (no_label)?"":"L", (no_label)?"":itoa(relay[offset +i], value_chr, 10)); + WSContentSend_P(PSTR(""), (no_label)?"":"L", (no_label)?"":itoa(relays[offset +i], value_chr, 10)); } WSContentSend_P(PSTR(") WSContentSend_PD(HTTP_SNS_VOLTAGE, SSPMEnergyFormat(value_chr, Sspm->voltage[0], Settings->flag2.voltage_resolution, indirect, offset, count)); @@ -2138,26 +2197,42 @@ void SSPMEnergyShow(bool json) { } } +#ifdef USE_WEBSERVER + +void SSPMWebGetArg(void) { + char tmp[8]; // WebGetArg numbers only + WebGetArg(PSTR("k86"), tmp, sizeof(tmp)); // 1 - 8 relay modules + if (strlen(tmp)) { Sspm->rotate = atoi(tmp) *4; } +} + +#endif // USE_WEBSERVER + /*********************************************************************************************\ * Commands \*********************************************************************************************/ const char kSSPMCommands[] PROGMEM = "SSPM|" // Prefix "Display|Dump|" // SetOptions +#ifdef SSPM_SIMULATE + "Simulate|" +#endif "Log|Energy|History|Scan|IamHere|" "Reset|Map|Overload|" - D_CMND_ENERGYTOTAL "|" D_CMND_ENERGYYESTERDAY; + D_CMND_ENERGYTOTAL "|" D_CMND_ENERGYYESTERDAY "|Send"; void (* const SSPMCommand[])(void) PROGMEM = { &CmndSSPMDisplay, &CmndSSPMDump, +#ifdef SSPM_SIMULATE + &CmndSSPMSimulate, +#endif &CmndSSPMLog, &CmndSSPMEnergy, &CmndSSPMHistory, &CmndSSPMScan, &CmndSSPMIamHere, &CmndSSPMReset, &CmndSSPMMap, &CmndSSPMOverload, - &CmndSpmEnergyTotal, &CmndSpmEnergyYesterday }; + &CmndSpmEnergyTotal, &CmndSpmEnergyYesterday, &CmndSSPMSend }; void CmndSSPMDisplay(void) { - // Select either all relays or only powered on relays - // SspmDisplay 0 or SspmDisplay 1 - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + // Select either all relays, only powered on relays or user selected relay module + // SspmDisplay 0, SspmDisplay 1 or SspmDisplay 2 + if ((XdrvMailbox.payload >= SPM_DISPLAY_ROTATE) && (XdrvMailbox.payload < SPM_DISPLAY_MAX_OPTION)) { Sspm->Settings.flag.display = XdrvMailbox.payload; } ResponseCmndNumber(Sspm->Settings.flag.display); @@ -2172,6 +2247,19 @@ void CmndSSPMDump(void) { ResponseCmndNumber(Sspm->Settings.flag.dump); } +#ifdef SSPM_SIMULATE +void CmndSSPMSimulate(void) { + // Simulate 4Relay modules based on first detected 4Relay module + // SspmSimulate 0 to turn simulation off + // SspmSimulate 6 to add 6 simulated modules + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < SSPM_MAX_MODULES)) { + Sspm->Settings.simulate_count = XdrvMailbox.payload; + TasmotaGlobal.restart_flag = 2; + } + ResponseCmndNumber(Sspm->Settings.simulate_count); +} +#endif + void CmndSpmEnergyTotal(void) { // Reset Energy Total // SspmEnergyTotal 0 - Set total energy from midnight with sum of last month history @@ -2377,6 +2465,26 @@ void CmndSSPMMap(void) { } } +void CmndSSPMSend(void) { + // Want to send AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 21 00 00 ix ch ks + // SspmSend 00 00 00 00 00 00 00 00 00 00 00 00 00 21 00 00 + char data[TOPSZ]; + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(data))) { + strlcpy(data, XdrvMailbox.data, sizeof(data)); + uint32_t len = (XdrvMailbox.data_len +1) / 3; + char *p = data; + SSPMInitSend(); + for (uint32_t i = 0; i < len; i++) { + SspmBuffer[i +3] = strtol(p, &p, 16); + } + Sspm->command_sequence++; + SspmBuffer[len +3] = Sspm->command_sequence; + SSPMSend(len +6); + + ResponseCmndIdxChar(ToHex_P((unsigned char *)SspmBuffer, len +6, data, sizeof(data), ' ')); + } +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -2408,6 +2516,9 @@ bool Xdrv86(uint8_t function) { case FUNC_WEB_SENSOR: SSPMEnergyShow(false); break; + case FUNC_WEB_GET_ARG: + SSPMWebGetArg(); + break; #endif // USE_WEBSERVER case FUNC_COMMAND: result = DecodeCommand(kSSPMCommands, SSPMCommand); diff --git a/tasmota/xdrv_98_file_settings_demo.ino b/tasmota/tasmota_xdrv_driver/xdrv_98_file_settings_demo.ino similarity index 100% rename from tasmota/xdrv_98_file_settings_demo.ino rename to tasmota/tasmota_xdrv_driver/xdrv_98_file_settings_demo.ino diff --git a/tasmota/xdrv_99_debug.ino b/tasmota/tasmota_xdrv_driver/xdrv_99_debug.ino similarity index 100% rename from tasmota/xdrv_99_debug.ino rename to tasmota/tasmota_xdrv_driver/xdrv_99_debug.ino diff --git a/tasmota/xdsp_01_lcd.ino b/tasmota/tasmota_xdsp_display/xdsp_01_lcd.ino similarity index 100% rename from tasmota/xdsp_01_lcd.ino rename to tasmota/tasmota_xdsp_display/xdsp_01_lcd.ino diff --git a/tasmota/xdsp_02_ssd1306.ino b/tasmota/tasmota_xdsp_display/xdsp_02_ssd1306.ino similarity index 100% rename from tasmota/xdsp_02_ssd1306.ino rename to tasmota/tasmota_xdsp_display/xdsp_02_ssd1306.ino diff --git a/tasmota/xdsp_03_matrix.ino b/tasmota/tasmota_xdsp_display/xdsp_03_matrix.ino similarity index 100% rename from tasmota/xdsp_03_matrix.ino rename to tasmota/tasmota_xdsp_display/xdsp_03_matrix.ino diff --git a/tasmota/xdsp_04_ili9341.ino b/tasmota/tasmota_xdsp_display/xdsp_04_ili9341.ino old mode 100755 new mode 100644 similarity index 100% rename from tasmota/xdsp_04_ili9341.ino rename to tasmota/tasmota_xdsp_display/xdsp_04_ili9341.ino diff --git a/tasmota/xdsp_05_epaper_29.ino b/tasmota/tasmota_xdsp_display/xdsp_05_epaper_29.ino similarity index 100% rename from tasmota/xdsp_05_epaper_29.ino rename to tasmota/tasmota_xdsp_display/xdsp_05_epaper_29.ino diff --git a/tasmota/xdsp_06_epaper_42.ino b/tasmota/tasmota_xdsp_display/xdsp_06_epaper_42.ino similarity index 100% rename from tasmota/xdsp_06_epaper_42.ino rename to tasmota/tasmota_xdsp_display/xdsp_06_epaper_42.ino diff --git a/tasmota/xdsp_07_sh1106.ino b/tasmota/tasmota_xdsp_display/xdsp_07_sh1106.ino similarity index 100% rename from tasmota/xdsp_07_sh1106.ino rename to tasmota/tasmota_xdsp_display/xdsp_07_sh1106.ino diff --git a/tasmota/xdsp_09_SSD1351.ino b/tasmota/tasmota_xdsp_display/xdsp_09_SSD1351.ino similarity index 100% rename from tasmota/xdsp_09_SSD1351.ino rename to tasmota/tasmota_xdsp_display/xdsp_09_SSD1351.ino diff --git a/tasmota/xdsp_10_RA8876.ino b/tasmota/tasmota_xdsp_display/xdsp_10_RA8876.ino similarity index 100% rename from tasmota/xdsp_10_RA8876.ino rename to tasmota/tasmota_xdsp_display/xdsp_10_RA8876.ino diff --git a/tasmota/xdsp_11_sevenseg.ino b/tasmota/tasmota_xdsp_display/xdsp_11_sevenseg.ino similarity index 100% rename from tasmota/xdsp_11_sevenseg.ino rename to tasmota/tasmota_xdsp_display/xdsp_11_sevenseg.ino diff --git a/tasmota/xdsp_12_ST7789.ino b/tasmota/tasmota_xdsp_display/xdsp_12_ST7789.ino similarity index 100% rename from tasmota/xdsp_12_ST7789.ino rename to tasmota/tasmota_xdsp_display/xdsp_12_ST7789.ino diff --git a/tasmota/xdsp_14_SSD1331.ino b/tasmota/tasmota_xdsp_display/xdsp_14_SSD1331.ino similarity index 100% rename from tasmota/xdsp_14_SSD1331.ino rename to tasmota/tasmota_xdsp_display/xdsp_14_SSD1331.ino diff --git a/tasmota/xdsp_15_tm1637.ino b/tasmota/tasmota_xdsp_display/xdsp_15_tm1637.ino similarity index 100% rename from tasmota/xdsp_15_tm1637.ino rename to tasmota/tasmota_xdsp_display/xdsp_15_tm1637.ino diff --git a/tasmota/xdsp_16_esp32_epaper_47.ino b/tasmota/tasmota_xdsp_display/xdsp_16_esp32_epaper_47.ino similarity index 100% rename from tasmota/xdsp_16_esp32_epaper_47.ino rename to tasmota/tasmota_xdsp_display/xdsp_16_esp32_epaper_47.ino diff --git a/tasmota/xdsp_17_universal.ino b/tasmota/tasmota_xdsp_display/xdsp_17_universal.ino similarity index 100% rename from tasmota/xdsp_17_universal.ino rename to tasmota/tasmota_xdsp_display/xdsp_17_universal.ino diff --git a/tasmota/xdsp_18_berry_display.ino b/tasmota/tasmota_xdsp_display/xdsp_18_berry_display.ino similarity index 100% rename from tasmota/xdsp_18_berry_display.ino rename to tasmota/tasmota_xdsp_display/xdsp_18_berry_display.ino diff --git a/tasmota/xdsp_19_max7219_matrix.ino b/tasmota/tasmota_xdsp_display/xdsp_19_max7219_matrix.ino similarity index 100% rename from tasmota/xdsp_19_max7219_matrix.ino rename to tasmota/tasmota_xdsp_display/xdsp_19_max7219_matrix.ino diff --git a/tasmota/xlgt_01_ws2812.ino b/tasmota/tasmota_xlgt_light/xlgt_01_ws2812.ino similarity index 100% rename from tasmota/xlgt_01_ws2812.ino rename to tasmota/tasmota_xlgt_light/xlgt_01_ws2812.ino diff --git a/tasmota/xlgt_02_my92x1.ino b/tasmota/tasmota_xlgt_light/xlgt_02_my92x1.ino similarity index 100% rename from tasmota/xlgt_02_my92x1.ino rename to tasmota/tasmota_xlgt_light/xlgt_02_my92x1.ino diff --git a/tasmota/xlgt_03_sm16716.ino b/tasmota/tasmota_xlgt_light/xlgt_03_sm16716.ino similarity index 100% rename from tasmota/xlgt_03_sm16716.ino rename to tasmota/tasmota_xlgt_light/xlgt_03_sm16716.ino diff --git a/tasmota/xlgt_04_sm2135.ino b/tasmota/tasmota_xlgt_light/xlgt_04_sm2135.ino similarity index 100% rename from tasmota/xlgt_04_sm2135.ino rename to tasmota/tasmota_xlgt_light/xlgt_04_sm2135.ino diff --git a/tasmota/xlgt_05_sonoff_l1.ino b/tasmota/tasmota_xlgt_light/xlgt_05_sonoff_l1.ino similarity index 100% rename from tasmota/xlgt_05_sonoff_l1.ino rename to tasmota/tasmota_xlgt_light/xlgt_05_sonoff_l1.ino diff --git a/tasmota/xlgt_06_electriq_moodl.ino b/tasmota/tasmota_xlgt_light/xlgt_06_electriq_moodl.ino similarity index 100% rename from tasmota/xlgt_06_electriq_moodl.ino rename to tasmota/tasmota_xlgt_light/xlgt_06_electriq_moodl.ino diff --git a/tasmota/xlgt_07_lsc_mcsl.ino b/tasmota/tasmota_xlgt_light/xlgt_07_lsc_mcsl.ino similarity index 100% rename from tasmota/xlgt_07_lsc_mcsl.ino rename to tasmota/tasmota_xlgt_light/xlgt_07_lsc_mcsl.ino diff --git a/tasmota/tasmota_xlgt_light/xlgt_08_bp5758d.ino b/tasmota/tasmota_xlgt_light/xlgt_08_bp5758d.ino new file mode 100644 index 000000000..e2e93fe97 --- /dev/null +++ b/tasmota/tasmota_xlgt_light/xlgt_08_bp5758d.ino @@ -0,0 +1,193 @@ +/* + xlgt_08_bp5758d.ino - bp5758d five channel led support for Tasmota + + Copyright (C) 2022 Theo Arends and oomg + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_LIGHT +#ifdef USE_BP5758D +/*********************************************************************************************\ + * BP5758D RGBCW Led bulbs commonly used by Tuya hardware + * + * Example configuration for a Fitop RGBCCT filament light bulb: + * {"NAME":"Fitop Filament RGBCCT","GPIO":[1,1,0,1,1,0,0,0,8416,0,8384,0,0,0],"FLAG":0,"BASE":18,"CMND":"RGBWWTable 255,109,245,255,255"} +\*********************************************************************************************/ + +#define XLGT_08 8 + +// Layout: Bits B[7:8]=10 (address selection identification bits), B[5:6] sleep mode if set to 00, B[0:4] Address selection +#define BP5758D_ADDR_SLEEP 0x86 //10 00 0110: Sleep mode bits set (OUT1 gray-scale level setup selected, ignored by chip) +#define BP5758D_ADDR_SETUP 0x90 //10 01 0000: OUT1-5 enable/disable setup - used during init +#define BP5758D_ADDR_OUT1_CR 0x91 //10 01 0001: OUT1 current range +#define BP5758D_ADDR_OUT2_CR 0x92 //10 01 0010: OUT2 current range +#define BP5758D_ADDR_OUT3_CR 0x93 //10 01 0011: OUT3 current range +#define BP5758D_ADDR_OUT4_CR 0x94 //10 01 0100: OUT4 current range +#define BP5758D_ADDR_OUT5_CR 0x95 //10 01 0101: OUT5 current range +#define BP5758D_ADDR_OUT1_GL 0x96 //10 01 0110: OUT1 gray-scale level +#define BP5758D_ADDR_OUT2_GL 0x98 //10 01 1000: OUT2 gray-scale level +#define BP5758D_ADDR_OUT3_GL 0x9A //10 01 1010: OUT3 gray-scale level +#define BP5758D_ADDR_OUT4_GL 0x9C //10 01 1100: OUT4 gray-scale level +#define BP5758D_ADDR_OUT5_GL 0x9E //10 01 1110: OUT5 gray-scale level + +// Output enabled (OUT1-5, represented by lower 5 bits) +#define BP5758D_ENABLE_OUTPUTS_ALL 0x1F + +// Current values: Bit 6 to 0 represent 30mA, 32mA, 16mA, 8mA, 4mA, 2mA, 1mA respectively +#define BP5758D_10MA 0x0A // 0 0001010 +#define BP5758D_14MA 0x0E // 0 0001110 +#define BP5758D_15MA 0x0F // 0 0001111 +#define BP5758D_65MA 0x63 // 0 1100011 +#define BP5758D_90MA 0x7C // 0 1111100 + +struct BP5758D { + uint8_t clk = 0; + uint8_t data = 0; + uint8_t current; +} Bp5758d; + +/*********************************************************************************************\ + * Bp5758d code - inspired by SM2135 and github.com/dbuezas/esphome-bp5758 +\*********************************************************************************************/ +const uint8_t BP5758D_DELAY = 2; + +void Bp5758dInit(void) { + pinMode(Bp5758d.data, OUTPUT); + pinMode(Bp5758d.clk, OUTPUT); + Bp5758dStop(); +} + +void Bp5758dWrite(uint8_t value) { + for (int bit_idx = 7; bit_idx >= 0; bit_idx--) { + bool bit = bitRead(value, bit_idx); + digitalWrite(Bp5758d.data, bit); + delayMicroseconds(BP5758D_DELAY); + digitalWrite(Bp5758d.clk, HIGH); + delayMicroseconds(BP5758D_DELAY); + digitalWrite(Bp5758d.clk, LOW); + delayMicroseconds(BP5758D_DELAY); + } + // Wait for ACK + pinMode(Bp5758d.data, INPUT); + digitalWrite(Bp5758d.clk, HIGH); + delayMicroseconds(BP5758D_DELAY); + digitalWrite(Bp5758d.clk, LOW); + delayMicroseconds(BP5758D_DELAY); + pinMode(Bp5758d.data, OUTPUT); +} + +void Bp5758dStart(uint8_t addr) { + digitalWrite(Bp5758d.data, LOW); + delayMicroseconds(BP5758D_DELAY); + digitalWrite(Bp5758d.clk, LOW); + delayMicroseconds(BP5758D_DELAY); + Bp5758dWrite(addr); +} + +void Bp5758dStop(void) { + digitalWrite(Bp5758d.clk, HIGH); + delayMicroseconds(BP5758D_DELAY); + digitalWrite(Bp5758d.data, HIGH); + delayMicroseconds(BP5758D_DELAY); +} + +/********************************************************************************************/ + +bool Bp5758dSetChannels(void) { + uint16_t *cur_col_10 = (uint16_t*)XdrvMailbox.command; + + // If we receive 0 for all channels, we'll assume that the lightbulb is off, and activate BP5758d's sleep mode. + if (cur_col_10[0]==0 && cur_col_10[1]==0 && cur_col_10[2]==0 && cur_col_10[3]==0 && cur_col_10[4]==0) { + Bp5758dStart(BP5758D_ADDR_SLEEP); + Bp5758dStop(); + return true; + } + + // Even though we could address changing channels only, in practice we observed that the lightbulb always sets all channels. + Bp5758dStart(BP5758D_ADDR_OUT1_GL); + // Brigtness values are transmitted as two bytes. The light-bulb accepts a 10-bit integer (0-1023) as an input value. + // The first 5bits of this input are transmitted in second byte, the second 5bits in the first byte. + Bp5758dWrite((uint8_t)(cur_col_10[0] & 0x1F)); //Red + Bp5758dWrite((uint8_t)(cur_col_10[0] >> 5)); + Bp5758dWrite((uint8_t)(cur_col_10[1] & 0x1F)); //Green + Bp5758dWrite((uint8_t)(cur_col_10[1] >> 5)); + Bp5758dWrite((uint8_t)(cur_col_10[2] & 0x1F)); //Blue + Bp5758dWrite((uint8_t)(cur_col_10[2] >> 5)); + Bp5758dWrite((uint8_t)(cur_col_10[4] & 0x1F)); //Cold + Bp5758dWrite((uint8_t)(cur_col_10[4] >> 5)); + Bp5758dWrite((uint8_t)(cur_col_10[3] & 0x1F)); //Warm + Bp5758dWrite((uint8_t)(cur_col_10[3] >> 5)); + + Bp5758dStop(); + return true; +} + +void Bp5758dModuleSelected(void) +{ + if (PinUsed(GPIO_BP5758D_CLK) && PinUsed(GPIO_BP5758D_DAT)) { + Bp5758d.clk = Pin(GPIO_BP5758D_CLK); + Bp5758d.data = Pin(GPIO_BP5758D_DAT); + + // For it's init sequence, BP5758D just sets all fields + Bp5758dInit(); + Bp5758dStart(BP5758D_ADDR_SETUP); + // Output enabled: enable all outputs since we're using a RGBCW light + Bp5758dWrite(BP5758D_ENABLE_OUTPUTS_ALL); + // Set currents for OUT1-OUT5 + Bp5758dWrite(BP5758D_14MA); + Bp5758dWrite(BP5758D_14MA); + Bp5758dWrite(BP5758D_14MA); + Bp5758dWrite(BP5758D_14MA); + Bp5758dWrite(BP5758D_14MA); + // Set grayscale levels ouf all outputs to 0 + Bp5758dWrite(0x00); + Bp5758dWrite(0x00); + Bp5758dWrite(0x00); + Bp5758dWrite(0x00); + Bp5758dWrite(0x00); + Bp5758dWrite(0x00); + Bp5758dWrite(0x00); + Bp5758dWrite(0x00); + Bp5758dWrite(0x00); + Bp5758dWrite(0x00); + Bp5758dStop(); + + TasmotaGlobal.light_type = LT_RGBWC; + TasmotaGlobal.light_driver = XLGT_08; + AddLog(LOG_LEVEL_DEBUG, PSTR("LGT: BP5758D Found")); + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xlgt08(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SET_CHANNELS: + result = Bp5758dSetChannels(); + break; + case FUNC_MODULE_INIT: + Bp5758dModuleSelected(); + break; + } + return result; +} + +#endif // USE_BP5758D +#endif // USE_LIGHT diff --git a/tasmota/xnrg_01_hlw8012.ino b/tasmota/tasmota_xnrg_energy/xnrg_01_hlw8012.ino similarity index 100% rename from tasmota/xnrg_01_hlw8012.ino rename to tasmota/tasmota_xnrg_energy/xnrg_01_hlw8012.ino diff --git a/tasmota/xnrg_02_cse7766.ino b/tasmota/tasmota_xnrg_energy/xnrg_02_cse7766.ino similarity index 100% rename from tasmota/xnrg_02_cse7766.ino rename to tasmota/tasmota_xnrg_energy/xnrg_02_cse7766.ino diff --git a/tasmota/xnrg_03_pzem004t.ino b/tasmota/tasmota_xnrg_energy/xnrg_03_pzem004t.ino similarity index 100% rename from tasmota/xnrg_03_pzem004t.ino rename to tasmota/tasmota_xnrg_energy/xnrg_03_pzem004t.ino diff --git a/tasmota/xnrg_04_mcp39f501.ino b/tasmota/tasmota_xnrg_energy/xnrg_04_mcp39f501.ino similarity index 100% rename from tasmota/xnrg_04_mcp39f501.ino rename to tasmota/tasmota_xnrg_energy/xnrg_04_mcp39f501.ino diff --git a/tasmota/xnrg_05_pzem_ac.ino b/tasmota/tasmota_xnrg_energy/xnrg_05_pzem_ac.ino similarity index 100% rename from tasmota/xnrg_05_pzem_ac.ino rename to tasmota/tasmota_xnrg_energy/xnrg_05_pzem_ac.ino diff --git a/tasmota/xnrg_06_pzem_dc.ino b/tasmota/tasmota_xnrg_energy/xnrg_06_pzem_dc.ino similarity index 100% rename from tasmota/xnrg_06_pzem_dc.ino rename to tasmota/tasmota_xnrg_energy/xnrg_06_pzem_dc.ino diff --git a/tasmota/xnrg_07_ade7953.ino b/tasmota/tasmota_xnrg_energy/xnrg_07_ade7953.ino similarity index 100% rename from tasmota/xnrg_07_ade7953.ino rename to tasmota/tasmota_xnrg_energy/xnrg_07_ade7953.ino diff --git a/tasmota/xnrg_08_sdm120.ino b/tasmota/tasmota_xnrg_energy/xnrg_08_sdm120.ino similarity index 100% rename from tasmota/xnrg_08_sdm120.ino rename to tasmota/tasmota_xnrg_energy/xnrg_08_sdm120.ino diff --git a/tasmota/xnrg_09_dds2382.ino b/tasmota/tasmota_xnrg_energy/xnrg_09_dds2382.ino similarity index 100% rename from tasmota/xnrg_09_dds2382.ino rename to tasmota/tasmota_xnrg_energy/xnrg_09_dds2382.ino diff --git a/tasmota/xnrg_10_sdm630.ino b/tasmota/tasmota_xnrg_energy/xnrg_10_sdm630.ino similarity index 100% rename from tasmota/xnrg_10_sdm630.ino rename to tasmota/tasmota_xnrg_energy/xnrg_10_sdm630.ino diff --git a/tasmota/xnrg_11_ddsu666.ino b/tasmota/tasmota_xnrg_energy/xnrg_11_ddsu666.ino similarity index 100% rename from tasmota/xnrg_11_ddsu666.ino rename to tasmota/tasmota_xnrg_energy/xnrg_11_ddsu666.ino diff --git a/tasmota/xnrg_12_solaxX1.ino b/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino similarity index 97% rename from tasmota/xnrg_12_solaxX1.ino rename to tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino index 6bad53255..f454b1c06 100644 --- a/tasmota/xnrg_12_solaxX1.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino @@ -1,615 +1,615 @@ -/* - xnrg_12_solaxX1.ino - Solax X1 inverter RS485 support for Tasmota - - Copyright (C) 2021 by Pablo Zerón - Copyright (C) 2022 by Stefan Wershoven - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifdef USE_ENERGY_SENSOR -#ifdef USE_SOLAX_X1 -/*********************************************************************************************\ - * Solax X1 Inverter -\*********************************************************************************************/ - -#define XNRG_12 12 - -#ifndef SOLAXX1_SPEED -#define SOLAXX1_SPEED 9600 // default solax rs485 speed -#endif - -#define SOLAXX1_READCONFIG // enable to read inverters config; disable to save codespace (3k1) - -#define INVERTER_ADDRESS 0x0A - -#define D_SOLAX_X1 "SolaxX1" - -#include - -const char kSolaxMode[] PROGMEM = - D_OFF "|" D_SOLAX_MODE_0 "|" D_SOLAX_MODE_1 "|" D_SOLAX_MODE_2 "|" D_SOLAX_MODE_3 "|" D_SOLAX_MODE_4 "|" - D_SOLAX_MODE_5 "|" D_SOLAX_MODE_6; - -const char kSolaxError[] PROGMEM = - D_SOLAX_ERROR_0 "|" D_SOLAX_ERROR_1 "|" D_SOLAX_ERROR_2 "|" D_SOLAX_ERROR_3 "|" D_SOLAX_ERROR_4 "|" D_SOLAX_ERROR_5 "|" - D_SOLAX_ERROR_6 "|" D_SOLAX_ERROR_7 "|" D_SOLAX_ERROR_8; - -#ifdef SOLAXX1_READCONFIG -const char kSolaxSafetyType[] PROGMEM = - "VDE0126|ARN4105|AS4777_AU|G98/1|C10/11|OVE/ONORME8001|EN50438_NL|EN50438_DK|CEB|CEI021|NRS097_2_1|" - "VDE0126_Gr_Is|UTE_C15_712|IEC61727|G99/1|VDE0126_Gr_Co|France_VFR2014|C15_712_is_50|C15_712_is_60|" - "AS4777_NZ|RD1699|Chile|EN50438_Ireland|Philippines|Czech_PPDS|Czech_50438"; -#endif // SOLAXX1_READCONFIG - -union { - uint32_t ErrMessage; - struct { - //BYTE0 - uint8_t TzProtectFault:1;//0 - uint8_t MainsLostFault:1;//1 - uint8_t GridVoltFault:1;//2 - uint8_t GridFreqFault:1;//3 - uint8_t PLLLostFault:1;//4 - uint8_t BusVoltFault:1;//5 - uint8_t ErrBit06:1;//6 - uint8_t OciFault:1;//7 - //BYTE1 - uint8_t Dci_OCP_Fault:1;//8 - uint8_t ResidualCurrentFault:1;//9 - uint8_t PvVoltFault:1;//10 - uint8_t Ac10Mins_Voltage_Fault:1;//11 - uint8_t IsolationFault:1;//12 - uint8_t TemperatureOverFault:1;//13 - uint8_t FanFault:1;//14 - uint8_t ErrBit15:1;//15 - //BYTE2 - uint8_t SpiCommsFault:1;//16 - uint8_t SciCommsFault:1;//17 - uint8_t ErrBit18:1;//18 - uint8_t InputConfigFault:1;//19 - uint8_t EepromFault:1;//20 - uint8_t RelayFault:1;//21 - uint8_t SampleConsistenceFault:1;//22 - uint8_t ResidualCurrent_DeviceFault:1;//23 - //BYTE3 - uint8_t ErrBit24:1;//24 - uint8_t ErrBit25:1;//25 - uint8_t ErrBit26:1;//26 - uint8_t ErrBit27:1;//27 - uint8_t ErrBit28:1;//28 - uint8_t DCI_DeviceFault:1;//29 - uint8_t OtherDeviceFault:1;//30 - uint8_t ErrBit31:1;//31 - }; -} solaxX1_ErrCode; - -struct SOLAXX1_LIVEDATA { - int16_t temperature = 0; - float energy_today = 0; - float dc1_voltage = 0; - float dc2_voltage = 0; - float dc1_current = 0; - float dc2_current = 0; - uint32_t runtime_total = 0; - float dc1_power = 0; - float dc2_power = 0; - int16_t runMode = 0; - uint32_t errorCode = 0; - uint8_t SerialNumber[16] = {0x6e, 0x2f, 0x61}; // "n/a" -} solaxX1; - -struct SOLAXX1_GLOBALDATA { - bool AddressAssigned = true; - uint8_t SendRetry_count = 20; - uint8_t QueryData_count = 0; - uint8_t QueryID_count = 240; - bool Command_QueryID = false;; - bool Command_QueryConfig = false; -} solaxX1_global; - -struct SOLAXX1_SENDDATA { - uint8_t Header[2] = {0xAA, 0x55}; - uint8_t Source[2] = {0x00, 0x00}; - uint8_t Destination[2] = {0x00, 0x00}; - uint8_t ControlCode[1] = {0x00}; - uint8_t FunctionCode[1] = {0x00}; - uint8_t DataLength[1] = {0x00}; - uint8_t Payload[16] = {0}; -} solaxX1_SendData; - -TasmotaSerial *solaxX1Serial; - -/*********************************************************************************************/ - -void solaxX1_RS485Send(void) -{ - uint8_t message[30]; - memcpy(message, solaxX1_SendData.Header, 2); - memcpy(message + 2, solaxX1_SendData.Source, 2); - memcpy(message + 4, solaxX1_SendData.Destination, 2); - memcpy(message + 6, solaxX1_SendData.ControlCode, 1); - memcpy(message + 7, solaxX1_SendData.FunctionCode, 1); - memcpy(message + 8, solaxX1_SendData.DataLength, 1); - memcpy(message + 9, solaxX1_SendData.Payload, sizeof(solaxX1_SendData.Payload)); - uint16_t crc = solaxX1_calculateCRC(message, 9 + solaxX1_SendData.DataLength[0]); // calculate out crc bytes - while (solaxX1Serial->available() > 0) { // read serial if any old data is available - solaxX1Serial->read(); - } - if (PinUsed(GPIO_SOLAXX1_RTS)) { - digitalWrite(Pin(GPIO_SOLAXX1_RTS), HIGH); - } - solaxX1Serial->flush(); - solaxX1Serial->write(message, 9 + solaxX1_SendData.DataLength[0]); - solaxX1Serial->write(highByte(crc)); - solaxX1Serial->write(lowByte(crc)); - solaxX1Serial->flush(); - if (PinUsed(GPIO_SOLAXX1_RTS)) { - digitalWrite(Pin(GPIO_SOLAXX1_RTS), LOW); - } - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, message, 9 + solaxX1_SendData.DataLength[0]); -} - -bool solaxX1_RS485Receive(uint8_t *ReadBuffer) -{ - uint8_t len = 0; - while (solaxX1Serial->available() > 0) { - ReadBuffer[len++] = (uint8_t)solaxX1Serial->read(); - } - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, ReadBuffer, len); - uint16_t crc = solaxX1_calculateCRC(ReadBuffer, len - 2); // calculate out crc bytes - return !(ReadBuffer[len - 1] == lowByte(crc) && ReadBuffer[len - 2] == highByte(crc)); -} - -uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen) -{ - uint8_t i; - uint16_t wChkSum = 0; - for (i = 0; i < bLen; i++) { - wChkSum = wChkSum + bExternTxPackage[i]; - } - return wChkSum; -} - -void solaxX1_ExtractText(uint8_t *DataIn, uint8_t *DataOut, uint8_t Begin, uint8_t End) -{ - uint8_t i; - for (i = Begin; i <= End; i++) { - DataOut[i - Begin] = DataIn[i]; - } - DataOut[End - Begin + 1] = 0; -} - -void solaxX1_QueryOfflineInverters(void) -{ - solaxX1_SendData.Source[0] = 0x01; - solaxX1_SendData.Destination[0] = 0x00; - solaxX1_SendData.Destination[1] = 0x00; - solaxX1_SendData.ControlCode[0] = 0x10; - solaxX1_SendData.FunctionCode[0] = 0x00; - solaxX1_SendData.DataLength[0] = 0x00; - solaxX1_RS485Send(); -} - -void solaxX1_SendInverterAddress(void) -{ - solaxX1_SendData.Source[0] = 0x00; - solaxX1_SendData.Destination[0] = 0x00; - solaxX1_SendData.Destination[1] = 0x00; - solaxX1_SendData.ControlCode[0] = 0x10; - solaxX1_SendData.FunctionCode[0] = 0x01; - solaxX1_SendData.DataLength[0] = 0x0F; - solaxX1_SendData.Payload[14] = INVERTER_ADDRESS; // Inverter Address, It must be unique in case of more inverters in the same rs485 net. - solaxX1_RS485Send(); -} - -void solaxX1_QueryLiveData(void) -{ - solaxX1_SendData.Source[0] = 0x01; - solaxX1_SendData.Destination[0] = 0x00; - solaxX1_SendData.Destination[1] = INVERTER_ADDRESS; - solaxX1_SendData.ControlCode[0] = 0x11; - solaxX1_SendData.FunctionCode[0] = 0x02; - solaxX1_SendData.DataLength[0] = 0x00; - solaxX1_RS485Send(); -} - -void solaxX1_QueryIDData(void) -{ - solaxX1_SendData.Source[0] = 0x01; - solaxX1_SendData.Destination[0] = 0x00; - solaxX1_SendData.Destination[1] = INVERTER_ADDRESS; - solaxX1_SendData.ControlCode[0] = 0x11; - solaxX1_SendData.FunctionCode[0] = 0x03; - solaxX1_SendData.DataLength[0] = 0x00; - solaxX1_RS485Send(); -} - -void solaxX1_QueryConfigData(void) -{ - solaxX1_SendData.Source[0] = 0x01; - solaxX1_SendData.Destination[0] = 0x00; - solaxX1_SendData.Destination[1] = INVERTER_ADDRESS; - solaxX1_SendData.ControlCode[0] = 0x11; - solaxX1_SendData.FunctionCode[0] = 0x04; - solaxX1_SendData.DataLength[0] = 0x00; - solaxX1_RS485Send(); -} - -uint8_t solaxX1_ParseErrorCode(uint32_t code){ - solaxX1_ErrCode.ErrMessage = code; - if (code == 0) return 0; - if (solaxX1_ErrCode.MainsLostFault) return 1; - if (solaxX1_ErrCode.GridVoltFault) return 2; - if (solaxX1_ErrCode.GridFreqFault) return 3; - if (solaxX1_ErrCode.PvVoltFault) return 4; - if (solaxX1_ErrCode.IsolationFault) return 5; - if (solaxX1_ErrCode.TemperatureOverFault) return 6; - if (solaxX1_ErrCode.FanFault) return 7; - if (solaxX1_ErrCode.OtherDeviceFault) return 8; - return 0; -} - -/*********************************************************************************************/ - -void solaxX1_250MSecond(void) // Every 250 milliseconds -{ - uint8_t DataRead[80] = {0}; - uint8_t TempData[16] = {0}; - char TempDataChar[16]; - float TempFloat; - - if (solaxX1Serial->available()) { - if (solaxX1_RS485Receive(DataRead)) { // CRC-error -> no further action - DEBUG_SENSOR_LOG(PSTR("SX1: Data response CRC error")); - return; - } - - solaxX1_global.SendRetry_count = 20; // Inverter is responding - - if (DataRead[0] != 0xAA || DataRead[1] != 0x55) { // Check for header - DEBUG_SENSOR_LOG(PSTR("SX1: Check for header failed")); - return; - } - - if (DataRead[6] == 0x11 && DataRead[7] == 0x82) { // received "Response for query (live data)" - Energy.data_valid[0] = 0; - solaxX1.temperature = (DataRead[9] << 8) | DataRead[10]; // Temperature - solaxX1.energy_today = ((DataRead[11] << 8) | DataRead[12]) * 0.1f; // Energy Today - solaxX1.dc1_voltage = ((DataRead[13] << 8) | DataRead[14]) * 0.1f; // PV1 Voltage - solaxX1.dc2_voltage = ((DataRead[15] << 8) | DataRead[16]) * 0.1f; // PV2 Voltage - solaxX1.dc1_current = ((DataRead[17] << 8) | DataRead[18]) * 0.1f; // PV1 Current - solaxX1.dc2_current = ((DataRead[19] << 8) | DataRead[20]) * 0.1f; // PV2 Current - Energy.current[0] = ((DataRead[21] << 8) | DataRead[22]) * 0.1f; // AC Current - Energy.voltage[0] = ((DataRead[23] << 8) | DataRead[24]) * 0.1f; // AC Voltage - Energy.frequency[0] = ((DataRead[25] << 8) | DataRead[26]) * 0.01f; // AC Frequency - Energy.active_power[0] = ((DataRead[27] << 8) | DataRead[28]); // AC Power - //temporal = (float)((DataRead[29] << 8) | DataRead[30]) * 0.1f; // Not Used - Energy.import_active[0] = ((DataRead[31] << 24) | (DataRead[32] << 16) | (DataRead[33] << 8) | DataRead[34]) * 0.1f; // Energy Total - solaxX1.runtime_total = (DataRead[35] << 24) | (DataRead[36] << 16) | (DataRead[37] << 8) | DataRead[38]; // Work Time Total - solaxX1.runMode = (DataRead[39] << 8) | DataRead[40]; // Work mode - //temporal = (float)((DataRead[41] << 8) | DataRead[42]); // Grid voltage fault value 0.1V - //temporal = (float)((DataRead[43] << 8) | DataRead[44]); // Gird frequency fault value 0.01Hz - //temporal = (float)((DataRead[45] << 8) | DataRead[46]); // Dc injection fault value 1mA - //temporal = (float)((DataRead[47] << 8) | DataRead[48]); // Temperature fault value - //temporal = (float)((DataRead[49] << 8) | DataRead[50]); // Pv1 voltage fault value 0.1V - //temporal = (float)((DataRead[51] << 8) | DataRead[52]); // Pv2 voltage fault value 0.1V - //temporal = (float)((DataRead[53] << 8) | DataRead[54]); // GFC fault value - solaxX1.errorCode = (DataRead[58] << 24) | (DataRead[57] << 16) | (DataRead[56] << 8) | DataRead[55]; // Error Code - solaxX1.dc1_power = solaxX1.dc1_voltage * solaxX1.dc1_current; - solaxX1.dc2_power = solaxX1.dc2_voltage * solaxX1.dc2_current; - EnergyUpdateTotal(); // 484.708 kWh - DEBUG_SENSOR_LOG(PSTR("SX1: received live data")); - return; - } // end received "Response for query (live data)" - - if (DataRead[6] == 0x11 && DataRead[7] == 0x83) { // received "Response for query (ID data)" - solaxX1_ExtractText(DataRead, solaxX1.SerialNumber, 49, 62); // extract "real" serial number - if (solaxX1_global.Command_QueryID) { - AddLog(LOG_LEVEL_INFO, PSTR("SX1: Inverter phases: %d"),DataRead[9]); // number of phases - solaxX1_ExtractText(DataRead, TempData, 10, 15); // extract rated bus power (my be empty) - AddLog(LOG_LEVEL_INFO, PSTR("SX1: Inverter rated bus power: %s"),(char*)TempData); - solaxX1_ExtractText(DataRead, TempData, 16, 20); // extract firmware version - AddLog(LOG_LEVEL_INFO, PSTR("SX1: Inverter firmware version: %s"),(char*)TempData); - solaxX1_ExtractText(DataRead, TempData, 21, 34); // extract module name (my be empty) - AddLog(LOG_LEVEL_INFO, PSTR("SX1: Inverter module name: %s"),(char*)TempData); - solaxX1_ExtractText(DataRead, TempData, 35, 48); // extract factory name - AddLog(LOG_LEVEL_INFO, PSTR("SX1: Inverter factory name: %s"),(char*)TempData); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: Inverter serial number: %s"),(char*)solaxX1.SerialNumber); - solaxX1_ExtractText(DataRead, TempData, 63, 66); // extract rated bus voltage - AddLog(LOG_LEVEL_INFO, PSTR("SX1: Inverter rated bus voltage: %s"),(char*)TempData); - solaxX1_global.Command_QueryID = false; - } else { - AddLog(LOG_LEVEL_DEBUG, PSTR("SX1: Inverter serial number: %s"),(char*)solaxX1.SerialNumber); - } - DEBUG_SENSOR_LOG(PSTR("SX1: received ID data")); - return; - } // end received "Response for query (ID data)" - -#ifdef SOLAXX1_READCONFIG - if (DataRead[6] == 0x11 && DataRead[7] == 0x84) { // received "Response for query (config data)" - if (solaxX1_global.Command_QueryConfig) { - // This values are displayed as they were received from the inverter. They are not interpreted in any way. - TempFloat = ((DataRead[9] << 8) | DataRead[10]) * 0.1f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wVpvStart: %1_f V (Inverter launch voltage threshold)"), &TempFloat); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wTimeStart: %d sec (launch wait time)"), (DataRead[11] << 8) | DataRead[12]); - TempFloat = ((DataRead[13] << 8) | DataRead[14]) * 0.1f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wVacMinProtect: %1_f V (allowed minimum grid voltage)"), &TempFloat); - TempFloat = ((DataRead[15] << 8) | DataRead[16]) * 0.1f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wVacMaxProtect: %1_f V (allowed maximum grid voltage)"), &TempFloat); - TempFloat = ((DataRead[17] << 8) | DataRead[18]) * 0.01f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wFacMinProtect: %2_f Hz (allowed minimum grid frequency)"), &TempFloat); - TempFloat = ((DataRead[19] << 8) | DataRead[20]) * 0.01f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wFacMaxProtect: %2_f Hz (allowed maximum grid frequency)"), &TempFloat); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wDciLimits: %d mA (DC component limits)"), (DataRead[21] << 8) | DataRead[22]); - TempFloat = ((DataRead[23] << 8) | DataRead[24]) * 0.1f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wGrid10MinAvgProtect: %1_f V (10 minutes over voltage protect)"), &TempFloat); - TempFloat = ((DataRead[25] << 8) | DataRead[26]) * 0.1f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wVacMinSlowProtect: %1_f V (grid undervoltage protect value)"), &TempFloat); - TempFloat = ((DataRead[27] << 8) | DataRead[28]) * 0.1f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wVacMaxSlowProtect: %1_f V (grid overvoltage protect value)"), &TempFloat); - TempFloat = ((DataRead[29] << 8) | DataRead[30]) * 0.01f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wFacMinSlowProtect: %2_f Hz (grid underfrequency protect value)"), &TempFloat); - TempFloat = ((DataRead[31] << 8) | DataRead[32]) * 0.01f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wFacMaxSlowProtect: %2_f Hz (grid overfrequency protect value)"), &TempFloat); - GetTextIndexed(TempDataChar, sizeof(TempDataChar), (DataRead[33] << 8) | DataRead[34], kSolaxSafetyType); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wSafety: %d ≙ %s"), (DataRead[33] << 8) | DataRead[34], TempDataChar); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wPowerfactor_mode: %d"), DataRead[35]); - TempFloat = DataRead[36] * 0.01f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wPowerfactor_data: %2_f"), &TempFloat); - TempFloat = DataRead[37] * 0.01f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wUpperLimit: %2_f (overexcite limits)"), &TempFloat); - TempFloat = DataRead[38] * 0.01f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wLowerLimit: %2_f (underexcite limits)"), &TempFloat); - TempFloat = DataRead[39] * 0.01f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wPowerLow: %2_f (power ratio change upper limits)"), &TempFloat); - TempFloat = DataRead[40] * 0.01f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wPowerUp: %2_f (power ratio change lower limits)"), &TempFloat); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: Qpower_set: %d"), (DataRead[41] << 8) | DataRead[42]); - TempFloat = ((DataRead[43] << 8) | DataRead[44]) * 0.01f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: WFreqSetPoint: %2_f Hz (Over Frequency drop output setpoint)"), &TempFloat); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: WFreqDroopRate: %d %% (drop output slope)"), (DataRead[45] << 8) | DataRead[46]); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: QuVupRate: %d %% (Q(U) curve up set point)"), (DataRead[47] << 8) | DataRead[48]); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: QuVlowRate: %d %% (Q(U) curve low set point)"), (DataRead[49] << 8) | DataRead[50]); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: WPowerLimitsPercent: %d %%"), (DataRead[51] << 8) | DataRead[52]); - TempFloat = ((DataRead[53] << 8) | DataRead[54]) * 0.01f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: WWgra: %2_f %%"), &TempFloat); - TempFloat = ((DataRead[55] << 8) | DataRead[56]) * 0.1f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wWv2: %1_f V"), &TempFloat); - TempFloat = ((DataRead[57] << 8) | DataRead[58]) * 0.1f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wWv3: %1_f V"), &TempFloat); - TempFloat = ((DataRead[59] << 8) | DataRead[60]) * 0.1f; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wWv4: %1_f V"), &TempFloat); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wQurangeV1: %d %%"), (DataRead[61] << 8) | DataRead[62]); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: wQurangeV4: %d %%"), (DataRead[63] << 8) | DataRead[64]); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: BVoltPowerLimit: %d"), (DataRead[65] << 8) | DataRead[66]); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: WPowerManagerEnable: %d"), (DataRead[67] << 8) | DataRead[68]); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: WGlobalSeachMPPTStrartFlg: %d"), (DataRead[69] << 8) | DataRead[70]); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: WFrqProtectRestrictive: %d"), (DataRead[71] << 8) | DataRead[72]); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: WQuDelayTimer: %d sec"), (DataRead[73] << 8) | DataRead[74]); - AddLog(LOG_LEVEL_INFO, PSTR("SX1: WFreqActivePowerDelayTimer: %d ms"), (DataRead[75] << 8) | DataRead[76]); - - solaxX1_global.Command_QueryConfig = false; - } - DEBUG_SENSOR_LOG(PSTR("SX1: received config data")); - return; - } // end received "Response for query (config data)" -#endif // SOLAXX1_READCONFIG - - if (DataRead[6] == 0x10 && DataRead[7] == 0x80) { // received "register request" - solaxX1_global.QueryData_count = 5; // give time for next query - solaxX1_ExtractText(DataRead, solaxX1_SendData.Payload, 9, 22); // store serial number for register - DEBUG_SENSOR_LOG(PSTR("SX1: received register request and send register address")); - solaxX1_SendInverterAddress(); // "send register address" - return; - } - - if (DataRead[6] == 0x10 && DataRead[7] == 0x81 && DataRead[9] == 0x06) { // received "address confirm (ACK)" - solaxX1_global.QueryData_count = 5; // give time for next query - solaxX1_global.AddressAssigned = true; - DEBUG_SENSOR_LOG(PSTR("SX1: received \"address confirm (ACK)\"")); - return; - } - - } // end solaxX1Serial->available() - -// DEBUG_SENSOR_LOG(PSTR("SX1: solaxX1_global.AddressAssigned: %d, solaxX1_global.QueryData_count: %d, solaxX1_global.SendRetry_count: %d, solaxX1_global.QueryID_count: %d"), solaxX1_global.AddressAssigned, solaxX1_global.QueryData_count, solaxX1_global.SendRetry_count, solaxX1_global.QueryID_count); - if (solaxX1_global.AddressAssigned) { - if (!solaxX1_global.QueryData_count) { // normal periodically query - solaxX1_global.QueryData_count = 5; - if (!solaxX1_global.QueryID_count || solaxX1_global.Command_QueryID) { // ID query - DEBUG_SENSOR_LOG(PSTR("SX1: Send ID query")); - solaxX1_QueryIDData(); - } else if (solaxX1_global.Command_QueryConfig) { // Config query - DEBUG_SENSOR_LOG(PSTR("SX1: Send config query")); - solaxX1_QueryConfigData(); - } else { // live query - DEBUG_SENSOR_LOG(PSTR("SX1: Send live query")); - solaxX1_QueryLiveData(); - } - solaxX1_global.QueryID_count++; // query ID every 256th time - } // end normal periodically query - solaxX1_global.QueryData_count--; - if (!solaxX1_global.SendRetry_count) { // Inverter went "off" - solaxX1_global.SendRetry_count = 20; - DEBUG_SENSOR_LOG(PSTR("SX1: Inverter went \"off\"")); - Energy.data_valid[0] = ENERGY_WATCHDOG; - solaxX1.temperature = solaxX1.dc1_voltage = solaxX1.dc2_voltage = solaxX1.dc1_current = solaxX1.dc2_current = solaxX1.dc1_power = 0; - solaxX1.dc2_power = Energy.current[0] = Energy.voltage[0] = Energy.frequency[0] = Energy.active_power[0] = 0; - solaxX1.runMode = -1; // off(line) - solaxX1_global.AddressAssigned = false; - } // end Inverter went "off" - } else { // sent query for inverters in offline status - if (!solaxX1_global.SendRetry_count) { - solaxX1_global.SendRetry_count = 20; - DEBUG_SENSOR_LOG(PSTR("SX1: Sent query for inverters in offline state")); - solaxX1_QueryOfflineInverters(); - } - } - solaxX1_global.SendRetry_count--; - -return; -} // end solaxX1_250MSecond - -void solaxX1_SnsInit(void) -{ - AddLog(LOG_LEVEL_INFO, PSTR("SX1: Init - RX-pin: %d, TX-pin: %d, RTS-pin: %d"), Pin(GPIO_SOLAXX1_RX), Pin(GPIO_SOLAXX1_TX), Pin(GPIO_SOLAXX1_RTS)); - solaxX1Serial = new TasmotaSerial(Pin(GPIO_SOLAXX1_RX), Pin(GPIO_SOLAXX1_TX), 1); - if (solaxX1Serial->begin(SOLAXX1_SPEED)) { - if (solaxX1Serial->hardwareSerial()) { ClaimSerial(); } - } else { - TasmotaGlobal.energy_driver = ENERGY_NONE; - } - if (PinUsed(GPIO_SOLAXX1_RTS)) { - pinMode(Pin(GPIO_SOLAXX1_RTS), OUTPUT); - } -} - -void solaxX1_DrvInit(void) -{ - if (PinUsed(GPIO_SOLAXX1_RX) && PinUsed(GPIO_SOLAXX1_TX)) { - TasmotaGlobal.energy_driver = XNRG_12; - } -} - -bool SolaxX1_cmd(void) -{ - if (!solaxX1_global.AddressAssigned) { - AddLog(LOG_LEVEL_INFO, PSTR("SX1: No inverter registered")); - return false; - } - - if (!strcasecmp(XdrvMailbox.data, "ReadIDinfo")) { - solaxX1_global.Command_QueryID = true; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: ReadIDinfo sent...")); - return true; - } else if (!strcasecmp(XdrvMailbox.data, "ReadConfig")) { -#ifdef SOLAXX1_READCONFIG - solaxX1_global.Command_QueryConfig = true; - AddLog(LOG_LEVEL_INFO, PSTR("SX1: ReadConfig sent...")); - return true; -#else - AddLog(LOG_LEVEL_INFO, PSTR("SX1: Command not available. Please set compiler directive '#define SOLAXX1_READCONFIG'.")); - return false; -#endif // SOLAXX1_READCONFIG - } - AddLog(LOG_LEVEL_INFO, PSTR("SX1: Unknown command: \"%s\""),XdrvMailbox.data); - return false; -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_solaxX1_DATA1[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_SOLAR_POWER "{m}%s " D_UNIT_WATT "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_POWER "{m}%s " D_UNIT_WATT "{e}"; -#ifdef SOLAXX1_PV2 -const char HTTP_SNS_solaxX1_DATA2[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_PV2_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}" D_SOLAX_X1 " " D_PV2_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}" D_SOLAX_X1 " " D_PV2_POWER "{m}%s " D_UNIT_WATT "{e}"; -#endif -const char HTTP_SNS_solaxX1_DATA3[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_UPTIME "{m}%d " D_UNIT_HOUR "{e}" - "{s}" D_SOLAX_X1 " " D_STATUS "{m}%s" - "{s}" D_SOLAX_X1 " " D_ERROR "{m}%s" - "{s}" D_SOLAX_X1 " Inverter SN{m}%s"; -#endif // USE_WEBSERVER - -void solaxX1_Show(bool json) -{ - char solar_power[33]; - dtostrfd(solaxX1.dc1_power + solaxX1.dc2_power, Settings->flag2.wattage_resolution, solar_power); - char pv1_voltage[33]; - dtostrfd(solaxX1.dc1_voltage, Settings->flag2.voltage_resolution, pv1_voltage); - char pv1_current[33]; - dtostrfd(solaxX1.dc1_current, Settings->flag2.current_resolution, pv1_current); - char pv1_power[33]; - dtostrfd(solaxX1.dc1_power, Settings->flag2.wattage_resolution, pv1_power); -#ifdef SOLAXX1_PV2 - char pv2_voltage[33]; - dtostrfd(solaxX1.dc2_voltage, Settings->flag2.voltage_resolution, pv2_voltage); - char pv2_current[33]; - dtostrfd(solaxX1.dc2_current, Settings->flag2.current_resolution, pv2_current); - char pv2_power[33]; - dtostrfd(solaxX1.dc2_power, Settings->flag2.wattage_resolution, pv2_power); -#endif - char status[33]; - GetTextIndexed(status, sizeof(status), solaxX1.runMode + 1, kSolaxMode); - - if (json) { - ResponseAppend_P(PSTR(",\"" D_JSON_SOLAR_POWER "\":%s,\"" D_JSON_PV1_VOLTAGE "\":%s,\"" D_JSON_PV1_CURRENT "\":%s,\"" D_JSON_PV1_POWER "\":%s"), - solar_power, pv1_voltage, pv1_current, pv1_power); -#ifdef SOLAXX1_PV2 - ResponseAppend_P(PSTR(",\"" D_JSON_PV2_VOLTAGE "\":%s,\"" D_JSON_PV2_CURRENT "\":%s,\"" D_JSON_PV2_POWER "\":%s"), - pv2_voltage, pv2_current, pv2_power); -#endif - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%d,\"" D_JSON_RUNTIME "\":%d,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d"), - solaxX1.temperature, solaxX1.runtime_total, status, solaxX1.errorCode); - -#ifdef USE_DOMOTICZ - // Avoid bad temperature report at beginning of the day (spikes of 1200 celsius degrees) - if (0 == TasmotaGlobal.tele_period && solaxX1.temperature < 100) { DomoticzSensor(DZ_TEMP, solaxX1.temperature); } -#endif // USE_DOMOTICZ - -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_solaxX1_DATA1, solar_power, pv1_voltage, pv1_current, pv1_power); -#ifdef SOLAXX1_PV2 - WSContentSend_PD(HTTP_SNS_solaxX1_DATA2, pv2_voltage, pv2_current, pv2_power); -#endif - WSContentSend_Temp(D_SOLAX_X1, solaxX1.temperature); - char errorCodeString[33]; - WSContentSend_PD(HTTP_SNS_solaxX1_DATA3, solaxX1.runtime_total, status, - GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1.errorCode), kSolaxError), - solaxX1.SerialNumber); -#endif // USE_WEBSERVER - } -} - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ - -bool Xnrg12(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - solaxX1_250MSecond(); - break; - case FUNC_JSON_APPEND: - solaxX1_Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - solaxX1_Show(0); - break; -#endif // USE_WEBSERVER - case FUNC_INIT: - solaxX1_SnsInit(); - break; - case FUNC_PRE_INIT: - solaxX1_DrvInit(); - break; - case FUNC_COMMAND: - result = SolaxX1_cmd(); - break; - } - return result; -} - -#endif // USE_SOLAX_X1_NRG -#endif // USE_ENERGY_SENSOR +/* + xnrg_12_solaxX1.ino - Solax X1 inverter RS485 support for Tasmota + + Copyright (C) 2021 by Pablo Zerón + Copyright (C) 2022 by Stefan Wershoven + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_ENERGY_SENSOR +#ifdef USE_SOLAX_X1 +/*********************************************************************************************\ + * Solax X1 Inverter +\*********************************************************************************************/ + +#define XNRG_12 12 + +#ifndef SOLAXX1_SPEED +#define SOLAXX1_SPEED 9600 // default solax rs485 speed +#endif + +#define SOLAXX1_READCONFIG // enable to read inverters config; disable to save codespace (3k1) + +#define INVERTER_ADDRESS 0x0A + +#define D_SOLAX_X1 "SolaxX1" + +#include + +const char kSolaxMode[] PROGMEM = + D_OFF "|" D_SOLAX_MODE_0 "|" D_SOLAX_MODE_1 "|" D_SOLAX_MODE_2 "|" D_SOLAX_MODE_3 "|" D_SOLAX_MODE_4 "|" + D_SOLAX_MODE_5 "|" D_SOLAX_MODE_6; + +const char kSolaxError[] PROGMEM = + D_SOLAX_ERROR_0 "|" D_SOLAX_ERROR_1 "|" D_SOLAX_ERROR_2 "|" D_SOLAX_ERROR_3 "|" D_SOLAX_ERROR_4 "|" D_SOLAX_ERROR_5 "|" + D_SOLAX_ERROR_6 "|" D_SOLAX_ERROR_7 "|" D_SOLAX_ERROR_8; + +#ifdef SOLAXX1_READCONFIG +const char kSolaxSafetyType[] PROGMEM = + "VDE0126|ARN4105|AS4777_AU|G98/1|C10/11|OVE/ONORME8001|EN50438_NL|EN50438_DK|CEB|CEI021|NRS097_2_1|" + "VDE0126_Gr_Is|UTE_C15_712|IEC61727|G99/1|VDE0126_Gr_Co|France_VFR2014|C15_712_is_50|C15_712_is_60|" + "AS4777_NZ|RD1699|Chile|EN50438_Ireland|Philippines|Czech_PPDS|Czech_50438"; +#endif // SOLAXX1_READCONFIG + +union { + uint32_t ErrMessage; + struct { + //BYTE0 + uint8_t TzProtectFault:1;//0 + uint8_t MainsLostFault:1;//1 + uint8_t GridVoltFault:1;//2 + uint8_t GridFreqFault:1;//3 + uint8_t PLLLostFault:1;//4 + uint8_t BusVoltFault:1;//5 + uint8_t ErrBit06:1;//6 + uint8_t OciFault:1;//7 + //BYTE1 + uint8_t Dci_OCP_Fault:1;//8 + uint8_t ResidualCurrentFault:1;//9 + uint8_t PvVoltFault:1;//10 + uint8_t Ac10Mins_Voltage_Fault:1;//11 + uint8_t IsolationFault:1;//12 + uint8_t TemperatureOverFault:1;//13 + uint8_t FanFault:1;//14 + uint8_t ErrBit15:1;//15 + //BYTE2 + uint8_t SpiCommsFault:1;//16 + uint8_t SciCommsFault:1;//17 + uint8_t ErrBit18:1;//18 + uint8_t InputConfigFault:1;//19 + uint8_t EepromFault:1;//20 + uint8_t RelayFault:1;//21 + uint8_t SampleConsistenceFault:1;//22 + uint8_t ResidualCurrent_DeviceFault:1;//23 + //BYTE3 + uint8_t ErrBit24:1;//24 + uint8_t ErrBit25:1;//25 + uint8_t ErrBit26:1;//26 + uint8_t ErrBit27:1;//27 + uint8_t ErrBit28:1;//28 + uint8_t DCI_DeviceFault:1;//29 + uint8_t OtherDeviceFault:1;//30 + uint8_t ErrBit31:1;//31 + }; +} solaxX1_ErrCode; + +struct SOLAXX1_LIVEDATA { + int16_t temperature = 0; + float energy_today = 0; + float dc1_voltage = 0; + float dc2_voltage = 0; + float dc1_current = 0; + float dc2_current = 0; + uint32_t runtime_total = 0; + float dc1_power = 0; + float dc2_power = 0; + int16_t runMode = 0; + uint32_t errorCode = 0; + uint8_t SerialNumber[16] = {0x6e, 0x2f, 0x61}; // "n/a" +} solaxX1; + +struct SOLAXX1_GLOBALDATA { + bool AddressAssigned = true; + uint8_t SendRetry_count = 20; + uint8_t QueryData_count = 0; + uint8_t QueryID_count = 240; + bool Command_QueryID = false;; + bool Command_QueryConfig = false; +} solaxX1_global; + +struct SOLAXX1_SENDDATA { + uint8_t Header[2] = {0xAA, 0x55}; + uint8_t Source[2] = {0x00, 0x00}; + uint8_t Destination[2] = {0x00, 0x00}; + uint8_t ControlCode[1] = {0x00}; + uint8_t FunctionCode[1] = {0x00}; + uint8_t DataLength[1] = {0x00}; + uint8_t Payload[16] = {0}; +} solaxX1_SendData; + +TasmotaSerial *solaxX1Serial; + +/*********************************************************************************************/ + +void solaxX1_RS485Send(void) +{ + uint8_t message[30]; + memcpy(message, solaxX1_SendData.Header, 2); + memcpy(message + 2, solaxX1_SendData.Source, 2); + memcpy(message + 4, solaxX1_SendData.Destination, 2); + memcpy(message + 6, solaxX1_SendData.ControlCode, 1); + memcpy(message + 7, solaxX1_SendData.FunctionCode, 1); + memcpy(message + 8, solaxX1_SendData.DataLength, 1); + memcpy(message + 9, solaxX1_SendData.Payload, sizeof(solaxX1_SendData.Payload)); + uint16_t crc = solaxX1_calculateCRC(message, 9 + solaxX1_SendData.DataLength[0]); // calculate out crc bytes + while (solaxX1Serial->available() > 0) { // read serial if any old data is available + solaxX1Serial->read(); + } + if (PinUsed(GPIO_SOLAXX1_RTS)) { + digitalWrite(Pin(GPIO_SOLAXX1_RTS), HIGH); + } + solaxX1Serial->flush(); + solaxX1Serial->write(message, 9 + solaxX1_SendData.DataLength[0]); + solaxX1Serial->write(highByte(crc)); + solaxX1Serial->write(lowByte(crc)); + solaxX1Serial->flush(); + if (PinUsed(GPIO_SOLAXX1_RTS)) { + digitalWrite(Pin(GPIO_SOLAXX1_RTS), LOW); + } + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, message, 9 + solaxX1_SendData.DataLength[0]); +} + +bool solaxX1_RS485Receive(uint8_t *ReadBuffer) +{ + uint8_t len = 0; + while (solaxX1Serial->available() > 0) { + ReadBuffer[len++] = (uint8_t)solaxX1Serial->read(); + } + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, ReadBuffer, len); + uint16_t crc = solaxX1_calculateCRC(ReadBuffer, len - 2); // calculate out crc bytes + return !(ReadBuffer[len - 1] == lowByte(crc) && ReadBuffer[len - 2] == highByte(crc)); +} + +uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen) +{ + uint8_t i; + uint16_t wChkSum = 0; + for (i = 0; i < bLen; i++) { + wChkSum = wChkSum + bExternTxPackage[i]; + } + return wChkSum; +} + +void solaxX1_ExtractText(uint8_t *DataIn, uint8_t *DataOut, uint8_t Begin, uint8_t End) +{ + uint8_t i; + for (i = Begin; i <= End; i++) { + DataOut[i - Begin] = DataIn[i]; + } + DataOut[End - Begin + 1] = 0; +} + +void solaxX1_QueryOfflineInverters(void) +{ + solaxX1_SendData.Source[0] = 0x01; + solaxX1_SendData.Destination[0] = 0x00; + solaxX1_SendData.Destination[1] = 0x00; + solaxX1_SendData.ControlCode[0] = 0x10; + solaxX1_SendData.FunctionCode[0] = 0x00; + solaxX1_SendData.DataLength[0] = 0x00; + solaxX1_RS485Send(); +} + +void solaxX1_SendInverterAddress(void) +{ + solaxX1_SendData.Source[0] = 0x00; + solaxX1_SendData.Destination[0] = 0x00; + solaxX1_SendData.Destination[1] = 0x00; + solaxX1_SendData.ControlCode[0] = 0x10; + solaxX1_SendData.FunctionCode[0] = 0x01; + solaxX1_SendData.DataLength[0] = 0x0F; + solaxX1_SendData.Payload[14] = INVERTER_ADDRESS; // Inverter Address, It must be unique in case of more inverters in the same rs485 net. + solaxX1_RS485Send(); +} + +void solaxX1_QueryLiveData(void) +{ + solaxX1_SendData.Source[0] = 0x01; + solaxX1_SendData.Destination[0] = 0x00; + solaxX1_SendData.Destination[1] = INVERTER_ADDRESS; + solaxX1_SendData.ControlCode[0] = 0x11; + solaxX1_SendData.FunctionCode[0] = 0x02; + solaxX1_SendData.DataLength[0] = 0x00; + solaxX1_RS485Send(); +} + +void solaxX1_QueryIDData(void) +{ + solaxX1_SendData.Source[0] = 0x01; + solaxX1_SendData.Destination[0] = 0x00; + solaxX1_SendData.Destination[1] = INVERTER_ADDRESS; + solaxX1_SendData.ControlCode[0] = 0x11; + solaxX1_SendData.FunctionCode[0] = 0x03; + solaxX1_SendData.DataLength[0] = 0x00; + solaxX1_RS485Send(); +} + +void solaxX1_QueryConfigData(void) +{ + solaxX1_SendData.Source[0] = 0x01; + solaxX1_SendData.Destination[0] = 0x00; + solaxX1_SendData.Destination[1] = INVERTER_ADDRESS; + solaxX1_SendData.ControlCode[0] = 0x11; + solaxX1_SendData.FunctionCode[0] = 0x04; + solaxX1_SendData.DataLength[0] = 0x00; + solaxX1_RS485Send(); +} + +uint8_t solaxX1_ParseErrorCode(uint32_t code){ + solaxX1_ErrCode.ErrMessage = code; + if (code == 0) return 0; + if (solaxX1_ErrCode.MainsLostFault) return 1; + if (solaxX1_ErrCode.GridVoltFault) return 2; + if (solaxX1_ErrCode.GridFreqFault) return 3; + if (solaxX1_ErrCode.PvVoltFault) return 4; + if (solaxX1_ErrCode.IsolationFault) return 5; + if (solaxX1_ErrCode.TemperatureOverFault) return 6; + if (solaxX1_ErrCode.FanFault) return 7; + if (solaxX1_ErrCode.OtherDeviceFault) return 8; + return 0; +} + +/*********************************************************************************************/ + +void solaxX1_250MSecond(void) // Every 250 milliseconds +{ + uint8_t DataRead[80] = {0}; + uint8_t TempData[16] = {0}; + char TempDataChar[16]; + float TempFloat; + + if (solaxX1Serial->available()) { + if (solaxX1_RS485Receive(DataRead)) { // CRC-error -> no further action + DEBUG_SENSOR_LOG(PSTR("SX1: Data response CRC error")); + return; + } + + solaxX1_global.SendRetry_count = 20; // Inverter is responding + + if (DataRead[0] != 0xAA || DataRead[1] != 0x55) { // Check for header + DEBUG_SENSOR_LOG(PSTR("SX1: Check for header failed")); + return; + } + + if (DataRead[6] == 0x11 && DataRead[7] == 0x82) { // received "Response for query (live data)" + Energy.data_valid[0] = 0; + solaxX1.temperature = (DataRead[9] << 8) | DataRead[10]; // Temperature + solaxX1.energy_today = ((DataRead[11] << 8) | DataRead[12]) * 0.1f; // Energy Today + solaxX1.dc1_voltage = ((DataRead[13] << 8) | DataRead[14]) * 0.1f; // PV1 Voltage + solaxX1.dc2_voltage = ((DataRead[15] << 8) | DataRead[16]) * 0.1f; // PV2 Voltage + solaxX1.dc1_current = ((DataRead[17] << 8) | DataRead[18]) * 0.1f; // PV1 Current + solaxX1.dc2_current = ((DataRead[19] << 8) | DataRead[20]) * 0.1f; // PV2 Current + Energy.current[0] = ((DataRead[21] << 8) | DataRead[22]) * 0.1f; // AC Current + Energy.voltage[0] = ((DataRead[23] << 8) | DataRead[24]) * 0.1f; // AC Voltage + Energy.frequency[0] = ((DataRead[25] << 8) | DataRead[26]) * 0.01f; // AC Frequency + Energy.active_power[0] = ((DataRead[27] << 8) | DataRead[28]); // AC Power + //temporal = (float)((DataRead[29] << 8) | DataRead[30]) * 0.1f; // Not Used + Energy.import_active[0] = ((DataRead[31] << 24) | (DataRead[32] << 16) | (DataRead[33] << 8) | DataRead[34]) * 0.1f; // Energy Total + solaxX1.runtime_total = (DataRead[35] << 24) | (DataRead[36] << 16) | (DataRead[37] << 8) | DataRead[38]; // Work Time Total + solaxX1.runMode = (DataRead[39] << 8) | DataRead[40]; // Work mode + //temporal = (float)((DataRead[41] << 8) | DataRead[42]); // Grid voltage fault value 0.1V + //temporal = (float)((DataRead[43] << 8) | DataRead[44]); // Gird frequency fault value 0.01Hz + //temporal = (float)((DataRead[45] << 8) | DataRead[46]); // Dc injection fault value 1mA + //temporal = (float)((DataRead[47] << 8) | DataRead[48]); // Temperature fault value + //temporal = (float)((DataRead[49] << 8) | DataRead[50]); // Pv1 voltage fault value 0.1V + //temporal = (float)((DataRead[51] << 8) | DataRead[52]); // Pv2 voltage fault value 0.1V + //temporal = (float)((DataRead[53] << 8) | DataRead[54]); // GFC fault value + solaxX1.errorCode = (DataRead[58] << 24) | (DataRead[57] << 16) | (DataRead[56] << 8) | DataRead[55]; // Error Code + solaxX1.dc1_power = solaxX1.dc1_voltage * solaxX1.dc1_current; + solaxX1.dc2_power = solaxX1.dc2_voltage * solaxX1.dc2_current; + EnergyUpdateTotal(); // 484.708 kWh + DEBUG_SENSOR_LOG(PSTR("SX1: received live data")); + return; + } // end received "Response for query (live data)" + + if (DataRead[6] == 0x11 && DataRead[7] == 0x83) { // received "Response for query (ID data)" + solaxX1_ExtractText(DataRead, solaxX1.SerialNumber, 49, 62); // extract "real" serial number + if (solaxX1_global.Command_QueryID) { + AddLog(LOG_LEVEL_INFO, PSTR("SX1: Inverter phases: %d"),DataRead[9]); // number of phases + solaxX1_ExtractText(DataRead, TempData, 10, 15); // extract rated bus power (my be empty) + AddLog(LOG_LEVEL_INFO, PSTR("SX1: Inverter rated bus power: %s"),(char*)TempData); + solaxX1_ExtractText(DataRead, TempData, 16, 20); // extract firmware version + AddLog(LOG_LEVEL_INFO, PSTR("SX1: Inverter firmware version: %s"),(char*)TempData); + solaxX1_ExtractText(DataRead, TempData, 21, 34); // extract module name (my be empty) + AddLog(LOG_LEVEL_INFO, PSTR("SX1: Inverter module name: %s"),(char*)TempData); + solaxX1_ExtractText(DataRead, TempData, 35, 48); // extract factory name + AddLog(LOG_LEVEL_INFO, PSTR("SX1: Inverter factory name: %s"),(char*)TempData); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: Inverter serial number: %s"),(char*)solaxX1.SerialNumber); + solaxX1_ExtractText(DataRead, TempData, 63, 66); // extract rated bus voltage + AddLog(LOG_LEVEL_INFO, PSTR("SX1: Inverter rated bus voltage: %s"),(char*)TempData); + solaxX1_global.Command_QueryID = false; + } else { + AddLog(LOG_LEVEL_DEBUG, PSTR("SX1: Inverter serial number: %s"),(char*)solaxX1.SerialNumber); + } + DEBUG_SENSOR_LOG(PSTR("SX1: received ID data")); + return; + } // end received "Response for query (ID data)" + +#ifdef SOLAXX1_READCONFIG + if (DataRead[6] == 0x11 && DataRead[7] == 0x84) { // received "Response for query (config data)" + if (solaxX1_global.Command_QueryConfig) { + // This values are displayed as they were received from the inverter. They are not interpreted in any way. + TempFloat = ((DataRead[9] << 8) | DataRead[10]) * 0.1f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wVpvStart: %1_f V (Inverter launch voltage threshold)"), &TempFloat); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wTimeStart: %d sec (launch wait time)"), (DataRead[11] << 8) | DataRead[12]); + TempFloat = ((DataRead[13] << 8) | DataRead[14]) * 0.1f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wVacMinProtect: %1_f V (allowed minimum grid voltage)"), &TempFloat); + TempFloat = ((DataRead[15] << 8) | DataRead[16]) * 0.1f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wVacMaxProtect: %1_f V (allowed maximum grid voltage)"), &TempFloat); + TempFloat = ((DataRead[17] << 8) | DataRead[18]) * 0.01f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wFacMinProtect: %2_f Hz (allowed minimum grid frequency)"), &TempFloat); + TempFloat = ((DataRead[19] << 8) | DataRead[20]) * 0.01f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wFacMaxProtect: %2_f Hz (allowed maximum grid frequency)"), &TempFloat); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wDciLimits: %d mA (DC component limits)"), (DataRead[21] << 8) | DataRead[22]); + TempFloat = ((DataRead[23] << 8) | DataRead[24]) * 0.1f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wGrid10MinAvgProtect: %1_f V (10 minutes over voltage protect)"), &TempFloat); + TempFloat = ((DataRead[25] << 8) | DataRead[26]) * 0.1f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wVacMinSlowProtect: %1_f V (grid undervoltage protect value)"), &TempFloat); + TempFloat = ((DataRead[27] << 8) | DataRead[28]) * 0.1f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wVacMaxSlowProtect: %1_f V (grid overvoltage protect value)"), &TempFloat); + TempFloat = ((DataRead[29] << 8) | DataRead[30]) * 0.01f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wFacMinSlowProtect: %2_f Hz (grid underfrequency protect value)"), &TempFloat); + TempFloat = ((DataRead[31] << 8) | DataRead[32]) * 0.01f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wFacMaxSlowProtect: %2_f Hz (grid overfrequency protect value)"), &TempFloat); + GetTextIndexed(TempDataChar, sizeof(TempDataChar), (DataRead[33] << 8) | DataRead[34], kSolaxSafetyType); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wSafety: %d ≙ %s"), (DataRead[33] << 8) | DataRead[34], TempDataChar); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wPowerfactor_mode: %d"), DataRead[35]); + TempFloat = DataRead[36] * 0.01f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wPowerfactor_data: %2_f"), &TempFloat); + TempFloat = DataRead[37] * 0.01f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wUpperLimit: %2_f (overexcite limits)"), &TempFloat); + TempFloat = DataRead[38] * 0.01f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wLowerLimit: %2_f (underexcite limits)"), &TempFloat); + TempFloat = DataRead[39] * 0.01f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wPowerLow: %2_f (power ratio change upper limits)"), &TempFloat); + TempFloat = DataRead[40] * 0.01f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wPowerUp: %2_f (power ratio change lower limits)"), &TempFloat); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: Qpower_set: %d"), (DataRead[41] << 8) | DataRead[42]); + TempFloat = ((DataRead[43] << 8) | DataRead[44]) * 0.01f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: WFreqSetPoint: %2_f Hz (Over Frequency drop output setpoint)"), &TempFloat); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: WFreqDroopRate: %d %% (drop output slope)"), (DataRead[45] << 8) | DataRead[46]); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: QuVupRate: %d %% (Q(U) curve up set point)"), (DataRead[47] << 8) | DataRead[48]); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: QuVlowRate: %d %% (Q(U) curve low set point)"), (DataRead[49] << 8) | DataRead[50]); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: WPowerLimitsPercent: %d %%"), (DataRead[51] << 8) | DataRead[52]); + TempFloat = ((DataRead[53] << 8) | DataRead[54]) * 0.01f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: WWgra: %2_f %%"), &TempFloat); + TempFloat = ((DataRead[55] << 8) | DataRead[56]) * 0.1f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wWv2: %1_f V"), &TempFloat); + TempFloat = ((DataRead[57] << 8) | DataRead[58]) * 0.1f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wWv3: %1_f V"), &TempFloat); + TempFloat = ((DataRead[59] << 8) | DataRead[60]) * 0.1f; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wWv4: %1_f V"), &TempFloat); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wQurangeV1: %d %%"), (DataRead[61] << 8) | DataRead[62]); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: wQurangeV4: %d %%"), (DataRead[63] << 8) | DataRead[64]); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: BVoltPowerLimit: %d"), (DataRead[65] << 8) | DataRead[66]); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: WPowerManagerEnable: %d"), (DataRead[67] << 8) | DataRead[68]); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: WGlobalSeachMPPTStrartFlg: %d"), (DataRead[69] << 8) | DataRead[70]); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: WFrqProtectRestrictive: %d"), (DataRead[71] << 8) | DataRead[72]); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: WQuDelayTimer: %d sec"), (DataRead[73] << 8) | DataRead[74]); + AddLog(LOG_LEVEL_INFO, PSTR("SX1: WFreqActivePowerDelayTimer: %d ms"), (DataRead[75] << 8) | DataRead[76]); + + solaxX1_global.Command_QueryConfig = false; + } + DEBUG_SENSOR_LOG(PSTR("SX1: received config data")); + return; + } // end received "Response for query (config data)" +#endif // SOLAXX1_READCONFIG + + if (DataRead[6] == 0x10 && DataRead[7] == 0x80) { // received "register request" + solaxX1_global.QueryData_count = 5; // give time for next query + solaxX1_ExtractText(DataRead, solaxX1_SendData.Payload, 9, 22); // store serial number for register + DEBUG_SENSOR_LOG(PSTR("SX1: received register request and send register address")); + solaxX1_SendInverterAddress(); // "send register address" + return; + } + + if (DataRead[6] == 0x10 && DataRead[7] == 0x81 && DataRead[9] == 0x06) { // received "address confirm (ACK)" + solaxX1_global.QueryData_count = 5; // give time for next query + solaxX1_global.AddressAssigned = true; + DEBUG_SENSOR_LOG(PSTR("SX1: received \"address confirm (ACK)\"")); + return; + } + + } // end solaxX1Serial->available() + +// DEBUG_SENSOR_LOG(PSTR("SX1: solaxX1_global.AddressAssigned: %d, solaxX1_global.QueryData_count: %d, solaxX1_global.SendRetry_count: %d, solaxX1_global.QueryID_count: %d"), solaxX1_global.AddressAssigned, solaxX1_global.QueryData_count, solaxX1_global.SendRetry_count, solaxX1_global.QueryID_count); + if (solaxX1_global.AddressAssigned) { + if (!solaxX1_global.QueryData_count) { // normal periodically query + solaxX1_global.QueryData_count = 5; + if (!solaxX1_global.QueryID_count || solaxX1_global.Command_QueryID) { // ID query + DEBUG_SENSOR_LOG(PSTR("SX1: Send ID query")); + solaxX1_QueryIDData(); + } else if (solaxX1_global.Command_QueryConfig) { // Config query + DEBUG_SENSOR_LOG(PSTR("SX1: Send config query")); + solaxX1_QueryConfigData(); + } else { // live query + DEBUG_SENSOR_LOG(PSTR("SX1: Send live query")); + solaxX1_QueryLiveData(); + } + solaxX1_global.QueryID_count++; // query ID every 256th time + } // end normal periodically query + solaxX1_global.QueryData_count--; + if (!solaxX1_global.SendRetry_count) { // Inverter went "off" + solaxX1_global.SendRetry_count = 20; + DEBUG_SENSOR_LOG(PSTR("SX1: Inverter went \"off\"")); + Energy.data_valid[0] = ENERGY_WATCHDOG; + solaxX1.temperature = solaxX1.dc1_voltage = solaxX1.dc2_voltage = solaxX1.dc1_current = solaxX1.dc2_current = solaxX1.dc1_power = 0; + solaxX1.dc2_power = Energy.current[0] = Energy.voltage[0] = Energy.frequency[0] = Energy.active_power[0] = 0; + solaxX1.runMode = -1; // off(line) + solaxX1_global.AddressAssigned = false; + } // end Inverter went "off" + } else { // sent query for inverters in offline status + if (!solaxX1_global.SendRetry_count) { + solaxX1_global.SendRetry_count = 20; + DEBUG_SENSOR_LOG(PSTR("SX1: Sent query for inverters in offline state")); + solaxX1_QueryOfflineInverters(); + } + } + solaxX1_global.SendRetry_count--; + +return; +} // end solaxX1_250MSecond + +void solaxX1_SnsInit(void) +{ + AddLog(LOG_LEVEL_INFO, PSTR("SX1: Init - RX-pin: %d, TX-pin: %d, RTS-pin: %d"), Pin(GPIO_SOLAXX1_RX), Pin(GPIO_SOLAXX1_TX), Pin(GPIO_SOLAXX1_RTS)); + solaxX1Serial = new TasmotaSerial(Pin(GPIO_SOLAXX1_RX), Pin(GPIO_SOLAXX1_TX), 1); + if (solaxX1Serial->begin(SOLAXX1_SPEED)) { + if (solaxX1Serial->hardwareSerial()) { ClaimSerial(); } + } else { + TasmotaGlobal.energy_driver = ENERGY_NONE; + } + if (PinUsed(GPIO_SOLAXX1_RTS)) { + pinMode(Pin(GPIO_SOLAXX1_RTS), OUTPUT); + } +} + +void solaxX1_DrvInit(void) +{ + if (PinUsed(GPIO_SOLAXX1_RX) && PinUsed(GPIO_SOLAXX1_TX)) { + TasmotaGlobal.energy_driver = XNRG_12; + } +} + +bool SolaxX1_cmd(void) +{ + if (!solaxX1_global.AddressAssigned) { + AddLog(LOG_LEVEL_INFO, PSTR("SX1: No inverter registered")); + return false; + } + + if (!strcasecmp(XdrvMailbox.data, "ReadIDinfo")) { + solaxX1_global.Command_QueryID = true; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: ReadIDinfo sent...")); + return true; + } else if (!strcasecmp(XdrvMailbox.data, "ReadConfig")) { +#ifdef SOLAXX1_READCONFIG + solaxX1_global.Command_QueryConfig = true; + AddLog(LOG_LEVEL_INFO, PSTR("SX1: ReadConfig sent...")); + return true; +#else + AddLog(LOG_LEVEL_INFO, PSTR("SX1: Command not available. Please set compiler directive '#define SOLAXX1_READCONFIG'.")); + return false; +#endif // SOLAXX1_READCONFIG + } + AddLog(LOG_LEVEL_INFO, PSTR("SX1: Unknown command: \"%s\""),XdrvMailbox.data); + return false; +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_solaxX1_DATA1[] PROGMEM = + "{s}" D_SOLAX_X1 " " D_SOLAR_POWER "{m}%s " D_UNIT_WATT "{e}" + "{s}" D_SOLAX_X1 " " D_PV1_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}" D_SOLAX_X1 " " D_PV1_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}" D_SOLAX_X1 " " D_PV1_POWER "{m}%s " D_UNIT_WATT "{e}"; +#ifdef SOLAXX1_PV2 +const char HTTP_SNS_solaxX1_DATA2[] PROGMEM = + "{s}" D_SOLAX_X1 " " D_PV2_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}" D_SOLAX_X1 " " D_PV2_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}" D_SOLAX_X1 " " D_PV2_POWER "{m}%s " D_UNIT_WATT "{e}"; +#endif +const char HTTP_SNS_solaxX1_DATA3[] PROGMEM = + "{s}" D_SOLAX_X1 " " D_UPTIME "{m}%d " D_UNIT_HOUR "{e}" + "{s}" D_SOLAX_X1 " " D_STATUS "{m}%s" + "{s}" D_SOLAX_X1 " " D_ERROR "{m}%s" + "{s}" D_SOLAX_X1 " Inverter SN{m}%s"; +#endif // USE_WEBSERVER + +void solaxX1_Show(bool json) +{ + char solar_power[33]; + dtostrfd(solaxX1.dc1_power + solaxX1.dc2_power, Settings->flag2.wattage_resolution, solar_power); + char pv1_voltage[33]; + dtostrfd(solaxX1.dc1_voltage, Settings->flag2.voltage_resolution, pv1_voltage); + char pv1_current[33]; + dtostrfd(solaxX1.dc1_current, Settings->flag2.current_resolution, pv1_current); + char pv1_power[33]; + dtostrfd(solaxX1.dc1_power, Settings->flag2.wattage_resolution, pv1_power); +#ifdef SOLAXX1_PV2 + char pv2_voltage[33]; + dtostrfd(solaxX1.dc2_voltage, Settings->flag2.voltage_resolution, pv2_voltage); + char pv2_current[33]; + dtostrfd(solaxX1.dc2_current, Settings->flag2.current_resolution, pv2_current); + char pv2_power[33]; + dtostrfd(solaxX1.dc2_power, Settings->flag2.wattage_resolution, pv2_power); +#endif + char status[33]; + GetTextIndexed(status, sizeof(status), solaxX1.runMode + 1, kSolaxMode); + + if (json) { + ResponseAppend_P(PSTR(",\"" D_JSON_SOLAR_POWER "\":%s,\"" D_JSON_PV1_VOLTAGE "\":%s,\"" D_JSON_PV1_CURRENT "\":%s,\"" D_JSON_PV1_POWER "\":%s"), + solar_power, pv1_voltage, pv1_current, pv1_power); +#ifdef SOLAXX1_PV2 + ResponseAppend_P(PSTR(",\"" D_JSON_PV2_VOLTAGE "\":%s,\"" D_JSON_PV2_CURRENT "\":%s,\"" D_JSON_PV2_POWER "\":%s"), + pv2_voltage, pv2_current, pv2_power); +#endif + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%d,\"" D_JSON_RUNTIME "\":%d,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d"), + solaxX1.temperature, solaxX1.runtime_total, status, solaxX1.errorCode); + +#ifdef USE_DOMOTICZ + // Avoid bad temperature report at beginning of the day (spikes of 1200 celsius degrees) + if (0 == TasmotaGlobal.tele_period && solaxX1.temperature < 100) { DomoticzSensor(DZ_TEMP, solaxX1.temperature); } +#endif // USE_DOMOTICZ + +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_solaxX1_DATA1, solar_power, pv1_voltage, pv1_current, pv1_power); +#ifdef SOLAXX1_PV2 + WSContentSend_PD(HTTP_SNS_solaxX1_DATA2, pv2_voltage, pv2_current, pv2_power); +#endif + WSContentSend_Temp(D_SOLAX_X1, solaxX1.temperature); + char errorCodeString[33]; + WSContentSend_PD(HTTP_SNS_solaxX1_DATA3, solaxX1.runtime_total, status, + GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1.errorCode), kSolaxError), + solaxX1.SerialNumber); +#endif // USE_WEBSERVER + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xnrg12(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + solaxX1_250MSecond(); + break; + case FUNC_JSON_APPEND: + solaxX1_Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + solaxX1_Show(0); + break; +#endif // USE_WEBSERVER + case FUNC_INIT: + solaxX1_SnsInit(); + break; + case FUNC_PRE_INIT: + solaxX1_DrvInit(); + break; + case FUNC_COMMAND: + result = SolaxX1_cmd(); + break; + } + return result; +} + +#endif // USE_SOLAX_X1_NRG +#endif // USE_ENERGY_SENSOR diff --git a/tasmota/xnrg_13_fif_le01mr.ino b/tasmota/tasmota_xnrg_energy/xnrg_13_fif_le01mr.ino similarity index 100% rename from tasmota/xnrg_13_fif_le01mr.ino rename to tasmota/tasmota_xnrg_energy/xnrg_13_fif_le01mr.ino diff --git a/tasmota/xnrg_14_bl09xx.ino b/tasmota/tasmota_xnrg_energy/xnrg_14_bl09xx.ino similarity index 100% rename from tasmota/xnrg_14_bl09xx.ino rename to tasmota/tasmota_xnrg_energy/xnrg_14_bl09xx.ino diff --git a/tasmota/xnrg_15_teleinfo.ino b/tasmota/tasmota_xnrg_energy/xnrg_15_teleinfo.ino old mode 100755 new mode 100644 similarity index 100% rename from tasmota/xnrg_15_teleinfo.ino rename to tasmota/tasmota_xnrg_energy/xnrg_15_teleinfo.ino diff --git a/tasmota/xnrg_16_iem3000.ino b/tasmota/tasmota_xnrg_energy/xnrg_16_iem3000.ino similarity index 100% rename from tasmota/xnrg_16_iem3000.ino rename to tasmota/tasmota_xnrg_energy/xnrg_16_iem3000.ino diff --git a/tasmota/xnrg_17_ornowe517.ino b/tasmota/tasmota_xnrg_energy/xnrg_17_ornowe517.ino similarity index 100% rename from tasmota/xnrg_17_ornowe517.ino rename to tasmota/tasmota_xnrg_energy/xnrg_17_ornowe517.ino diff --git a/tasmota/xnrg_18_sdm72.ino b/tasmota/tasmota_xnrg_energy/xnrg_18_sdm72.ino similarity index 100% rename from tasmota/xnrg_18_sdm72.ino rename to tasmota/tasmota_xnrg_energy/xnrg_18_sdm72.ino diff --git a/tasmota/xnrg_19_cse7761.ino b/tasmota/tasmota_xnrg_energy/xnrg_19_cse7761.ino similarity index 100% rename from tasmota/xnrg_19_cse7761.ino rename to tasmota/tasmota_xnrg_energy/xnrg_19_cse7761.ino diff --git a/tasmota/xnrg_21_sdm230.ino b/tasmota/tasmota_xnrg_energy/xnrg_21_sdm230.ino similarity index 100% rename from tasmota/xnrg_21_sdm230.ino rename to tasmota/tasmota_xnrg_energy/xnrg_21_sdm230.ino diff --git a/tasmota/xnrg_22_bl6523.ino b/tasmota/tasmota_xnrg_energy/xnrg_22_bl6523.ino similarity index 100% rename from tasmota/xnrg_22_bl6523.ino rename to tasmota/tasmota_xnrg_energy/xnrg_22_bl6523.ino diff --git a/tasmota/xnrg_23_ade7880.ino b/tasmota/tasmota_xnrg_energy/xnrg_23_ade7880.ino similarity index 99% rename from tasmota/xnrg_23_ade7880.ino rename to tasmota/tasmota_xnrg_energy/xnrg_23_ade7880.ino index 2bdf9f486..7adacaa97 100644 --- a/tasmota/xnrg_23_ade7880.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_23_ade7880.ino @@ -476,12 +476,21 @@ void Ade7880Cycle(void) { #endif // ADE7880_PROFILING uint32_t status0 = Ade7880ReadVerify(ADE7880_STATUS0); // 0xE502 - 0x000FEFE0 +/* if (!bitRead(status0, 5)) { // LENERGY + AddLog(LOG_LEVEL_DEBUG, PSTR("A78: Unexpected ISR0 0x%08X"), status0); return; } else { Ade7880WriteVerify(ADE7880_STATUS0, 0x00000020); // 0xE502 - Acknowledge LENERGY - Reset IRQ0 line status0 = Ade7880ReadVerify(ADE7880_STATUS0); // 0xE502 - 0x000FEFC0 } +*/ + if (!bitRead(status0, 5)) { // LENERGY + AddLog(LOG_LEVEL_DEBUG, PSTR("A78: Unexpected ISR0 0x%08X"), status0); + } + Ade7880WriteVerify(ADE7880_STATUS0, 0x00000020); // 0xE502 - Acknowledge LENERGY - Reset IRQ0 line + status0 = Ade7880ReadVerify(ADE7880_STATUS0); // 0xE502 - 0x000FEFC0 + if (Ade7880.cycle_count) { // Allow calibration stabilization Ade7880.cycle_count--; return; // Skip first cycles diff --git a/tasmota/xnrg_30_dummy.ino b/tasmota/tasmota_xnrg_energy/xnrg_30_dummy.ino similarity index 100% rename from tasmota/xnrg_30_dummy.ino rename to tasmota/tasmota_xnrg_energy/xnrg_30_dummy.ino diff --git a/tasmota/xsns_01_counter.ino b/tasmota/tasmota_xsns_sensor/xsns_01_counter.ino similarity index 100% rename from tasmota/xsns_01_counter.ino rename to tasmota/tasmota_xsns_sensor/xsns_01_counter.ino diff --git a/tasmota/xsns_02_analog.ino b/tasmota/tasmota_xsns_sensor/xsns_02_analog.ino similarity index 100% rename from tasmota/xsns_02_analog.ino rename to tasmota/tasmota_xsns_sensor/xsns_02_analog.ino diff --git a/tasmota/xsns_04_snfsc.ino b/tasmota/tasmota_xsns_sensor/xsns_04_snfsc.ino similarity index 100% rename from tasmota/xsns_04_snfsc.ino rename to tasmota/tasmota_xsns_sensor/xsns_04_snfsc.ino diff --git a/tasmota/xsns_05_ds18x20.ino b/tasmota/tasmota_xsns_sensor/xsns_05_ds18x20.ino similarity index 100% rename from tasmota/xsns_05_ds18x20.ino rename to tasmota/tasmota_xsns_sensor/xsns_05_ds18x20.ino diff --git a/tasmota/xsns_05_esp32_ds18x20.ino b/tasmota/tasmota_xsns_sensor/xsns_05_esp32_ds18x20.ino similarity index 100% rename from tasmota/xsns_05_esp32_ds18x20.ino rename to tasmota/tasmota_xsns_sensor/xsns_05_esp32_ds18x20.ino diff --git a/tasmota/xsns_06_dht.ino b/tasmota/tasmota_xsns_sensor/xsns_06_dht.ino similarity index 100% rename from tasmota/xsns_06_dht.ino rename to tasmota/tasmota_xsns_sensor/xsns_06_dht.ino diff --git a/tasmota/xsns_06_esp32_dht.ino b/tasmota/tasmota_xsns_sensor/xsns_06_esp32_dht.ino similarity index 100% rename from tasmota/xsns_06_esp32_dht.ino rename to tasmota/tasmota_xsns_sensor/xsns_06_esp32_dht.ino diff --git a/tasmota/xsns_07_sht1x.ino b/tasmota/tasmota_xsns_sensor/xsns_07_sht1x.ino similarity index 100% rename from tasmota/xsns_07_sht1x.ino rename to tasmota/tasmota_xsns_sensor/xsns_07_sht1x.ino diff --git a/tasmota/xsns_08_htu21.ino b/tasmota/tasmota_xsns_sensor/xsns_08_htu21.ino similarity index 100% rename from tasmota/xsns_08_htu21.ino rename to tasmota/tasmota_xsns_sensor/xsns_08_htu21.ino diff --git a/tasmota/xsns_09_bmp.ino b/tasmota/tasmota_xsns_sensor/xsns_09_bmp.ino similarity index 100% rename from tasmota/xsns_09_bmp.ino rename to tasmota/tasmota_xsns_sensor/xsns_09_bmp.ino diff --git a/tasmota/xsns_10_bh1750.ino b/tasmota/tasmota_xsns_sensor/xsns_10_bh1750.ino similarity index 100% rename from tasmota/xsns_10_bh1750.ino rename to tasmota/tasmota_xsns_sensor/xsns_10_bh1750.ino diff --git a/tasmota/xsns_11_veml6070.ino b/tasmota/tasmota_xsns_sensor/xsns_11_veml6070.ino similarity index 100% rename from tasmota/xsns_11_veml6070.ino rename to tasmota/tasmota_xsns_sensor/xsns_11_veml6070.ino diff --git a/tasmota/xsns_127_esp32_sensors.ino b/tasmota/tasmota_xsns_sensor/xsns_127_esp32_sensors.ino similarity index 100% rename from tasmota/xsns_127_esp32_sensors.ino rename to tasmota/tasmota_xsns_sensor/xsns_127_esp32_sensors.ino diff --git a/tasmota/xsns_12_ads1115.ino b/tasmota/tasmota_xsns_sensor/xsns_12_ads1115.ino similarity index 100% rename from tasmota/xsns_12_ads1115.ino rename to tasmota/tasmota_xsns_sensor/xsns_12_ads1115.ino diff --git a/tasmota/xsns_13_ina219.ino b/tasmota/tasmota_xsns_sensor/xsns_13_ina219.ino similarity index 100% rename from tasmota/xsns_13_ina219.ino rename to tasmota/tasmota_xsns_sensor/xsns_13_ina219.ino diff --git a/tasmota/tasmota_xsns_sensor/xsns_14_sht3x.ino b/tasmota/tasmota_xsns_sensor/xsns_14_sht3x.ino new file mode 100644 index 000000000..5a0f4b57d --- /dev/null +++ b/tasmota/tasmota_xsns_sensor/xsns_14_sht3x.ino @@ -0,0 +1,195 @@ +/* + xsns_14_sht3x.ino - SHT3X, SHT4X and SHTCX temperature and humidity sensor support for Tasmota + + Copyright (C) 2022 Theo Arends, Stefan Tibus + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_I2C +#ifdef USE_SHT3X +/*********************************************************************************************\ + * Sensirion I2C temperature and humidity sensors + * + * This driver supports the following sensors: + * - SHT3x series: SHT30, SHT31, SHT35 (addresses: A: 0x44, B: 0x45) + * - SHTC series: SHTC1, SHTC3 (address: 0x70) + * - SHT4x series: SHT40, SHT41, SHT45 (addresses: A: 0x44, B: 0x45) +\*********************************************************************************************/ + +#define XSNS_14 14 +#define XI2C_15 15 // See I2CDEVICES.md + +#define SHT3X_ADDRESSES 2 // 2 addresses for SHT3x +#define SHT3X_ADDR_GND 0x44 // Address A pin low (GND) +#define SHT3X_ADDR_VDD 0x45 // Address B pin high (VDD) +#define SHTCX_ADDRESSES 1 // 1 address for SHTCx +#define SHTCX_ADDR 0x70 // Address for SHTCx sensors +#define SHT4X_ADDRESSES 2 // 2 addresses for SHT4x +#define SHT4X_ADDR_A 0x44 // Address SHT4x A +#define SHT4X_ADDR_B 0x45 // Address SHT4x B + +#define SHT3X_MAX_SENSORS 3 // Only one of 0x44, 0x45 and 0x70 + +enum SHT3X_Types { + SHT3X_TYPE_SHT3X, + SHT3X_TYPE_SHTCX, + SHT3X_TYPE_SHT4X +}; + +const char kSht3xTypes[] PROGMEM = "SHT3X|SHTC3|SHT4X"; +uint8_t sht3x_addresses[] = { SHT3X_ADDR_GND, SHT3X_ADDR_VDD, SHTCX_ADDR }; + +uint8_t sht3x_count = 0; +struct SHT3XSTRUCT { + uint8_t type; // Sensor type + uint8_t address; // I2C bus address + char types[6]; // Sensor type name and address, e.g. "SHT3X" +} sht3x_sensors[SHT3X_MAX_SENSORS]; + +uint8_t Sht3xComputeCrc(uint8_t data[], uint8_t len) { + // Compute CRC as per datasheet + uint8_t crc = 0xFF; + + for (uint8_t x = 0; x < len; x++) { + crc ^= data[x]; + for (uint8_t i = 0; i < 8; i++) { + if (crc & 0x80) { + crc = (crc << 1) ^ 0x31; + } else { + crc <<= 1; + } + } + } + return crc; +} + +bool Sht3xRead(uint32_t type, float &t, float &h, uint8_t i2c_address) { + uint8_t data[6]; + + t = NAN; + h = NAN; + + Wire.beginTransmission(i2c_address); + switch (type) { + case SHT3X_TYPE_SHT3X: + // TODO: Clock stretching is used for SHT3x but not for SHTC3. Why? + Wire.write(0x2C); // Enable clock stretching + Wire.write(0x06); // High repeatability measurement + break; + case SHT3X_TYPE_SHTCX: + Wire.write(0x35); // Wake from + Wire.write(0x17); // sleep + Wire.endTransmission(); + Wire.beginTransmission(i2c_address); + // TODO: Clock stretching is used for SHT3x but not for SHTC3. Why? + Wire.write(0x78); // Disable clock stretching + Wire.write(0x66); // Normal mode measurement + break; + case SHT3X_TYPE_SHT4X: + Wire.write(0xFD); // High repeatability measurement + break; + } + if (Wire.endTransmission() != 0) { // Stop I2C transmission + return false; + } + delay(30); // Timing verified with logic analyzer (10 is to short) + Wire.requestFrom(i2c_address, (uint8_t)6); // Request 6 bytes of data + for (uint32_t i = 0; i < 6; i++) { + data[i] = Wire.read(); // temperature (MSB, LSB, CRC), humidity (MSB, LSB, CRC) + }; + if ((Sht3xComputeCrc(&data[0], 2) != data[2]) || (Sht3xComputeCrc(&data[3], 2) != data[5])) { + return false; + } + t = ConvertTemp((float)((((data[0] << 8) | data[1]) * 175) / 65535.0) - 45); + h = ConvertHumidity((float)((((data[3] << 8) | data[4]) * 100) / 65535.0)); + return (!isnan(t) && !isnan(h)); +} + +/********************************************************************************************/ + +void Sht3xDetect(void) { + float t; + float h; + + for (uint32_t i = 0; i < SHT3X_MAX_SENSORS; i++) { + if (!I2cSetDevice(sht3x_addresses[i])) { continue; } + if (i < 2) { // 0x44 and 0x45 + sht3x_sensors[sht3x_count].type = SHT3X_TYPE_SHT3X; + if (!Sht3xRead(sht3x_sensors[sht3x_count].type, t, h, sht3x_addresses[i])) { + sht3x_sensors[sht3x_count].type = SHT3X_TYPE_SHT4X; + if (!Sht3xRead(sht3x_sensors[sht3x_count].type, t, h, sht3x_addresses[i])) { + continue; + } + } + } else { // 0x70 + sht3x_sensors[sht3x_count].type = SHT3X_TYPE_SHTCX; + if (!Sht3xRead(sht3x_sensors[sht3x_count].type, t, h, sht3x_addresses[i])) { + continue; + } + } + sht3x_sensors[sht3x_count].address = sht3x_addresses[i]; + GetTextIndexed(sht3x_sensors[sht3x_count].types, sizeof(sht3x_sensors[sht3x_count].types), SHT3X_TYPE_SHT3X, kSht3xTypes); + I2cSetActiveFound(sht3x_sensors[sht3x_count].address, sht3x_sensors[sht3x_count].types); + sht3x_count++; + } +} + +void Sht3xShow(bool json) { + float t; + float h; + char types[11]; + + for (uint32_t i = 0; i < sht3x_count; i++) { + if (Sht3xRead(sht3x_sensors[i].type, t, h, sht3x_sensors[i].address)) { + t = ConvertTemp(t); + h = ConvertHumidity(h); + strlcpy(types, sht3x_sensors[i].types, sizeof(types)); + if (sht3x_count > 1) { + snprintf_P(types, sizeof(types), PSTR("%s%c%02X"), sht3x_sensors[i].types, IndexSeparator(), sht3x_sensors[i].address); // "SHT3X-0xXX" + } + TempHumDewShow(json, ((0 == TasmotaGlobal.tele_period) && (0 == i)), types, t, h); + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xsns14(uint8_t function) { + if (!I2cEnabled(XI2C_15)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Sht3xDetect(); + } + else if (sht3x_count) { + switch (function) { + case FUNC_JSON_APPEND: + Sht3xShow(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Sht3xShow(0); + break; + #endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_SHT3X +#endif // USE_I2C \ No newline at end of file diff --git a/tasmota/xsns_15_mhz19.ino b/tasmota/tasmota_xsns_sensor/xsns_15_mhz19.ino similarity index 100% rename from tasmota/xsns_15_mhz19.ino rename to tasmota/tasmota_xsns_sensor/xsns_15_mhz19.ino diff --git a/tasmota/xsns_16_tsl2561.ino b/tasmota/tasmota_xsns_sensor/xsns_16_tsl2561.ino similarity index 100% rename from tasmota/xsns_16_tsl2561.ino rename to tasmota/tasmota_xsns_sensor/xsns_16_tsl2561.ino diff --git a/tasmota/xsns_17_senseair.ino b/tasmota/tasmota_xsns_sensor/xsns_17_senseair.ino similarity index 100% rename from tasmota/xsns_17_senseair.ino rename to tasmota/tasmota_xsns_sensor/xsns_17_senseair.ino diff --git a/tasmota/xsns_18_pms5003.ino b/tasmota/tasmota_xsns_sensor/xsns_18_pms5003.ino similarity index 100% rename from tasmota/xsns_18_pms5003.ino rename to tasmota/tasmota_xsns_sensor/xsns_18_pms5003.ino diff --git a/tasmota/xsns_19_mgs.ino b/tasmota/tasmota_xsns_sensor/xsns_19_mgs.ino similarity index 100% rename from tasmota/xsns_19_mgs.ino rename to tasmota/tasmota_xsns_sensor/xsns_19_mgs.ino diff --git a/tasmota/xsns_20_novasds.ino b/tasmota/tasmota_xsns_sensor/xsns_20_novasds.ino similarity index 100% rename from tasmota/xsns_20_novasds.ino rename to tasmota/tasmota_xsns_sensor/xsns_20_novasds.ino diff --git a/tasmota/xsns_21_sgp30.ino b/tasmota/tasmota_xsns_sensor/xsns_21_sgp30.ino similarity index 100% rename from tasmota/xsns_21_sgp30.ino rename to tasmota/tasmota_xsns_sensor/xsns_21_sgp30.ino diff --git a/tasmota/xsns_22_sr04.ino b/tasmota/tasmota_xsns_sensor/xsns_22_sr04.ino similarity index 100% rename from tasmota/xsns_22_sr04.ino rename to tasmota/tasmota_xsns_sensor/xsns_22_sr04.ino diff --git a/tasmota/xsns_24_si1145.ino b/tasmota/tasmota_xsns_sensor/xsns_24_si1145.ino similarity index 100% rename from tasmota/xsns_24_si1145.ino rename to tasmota/tasmota_xsns_sensor/xsns_24_si1145.ino diff --git a/tasmota/xsns_26_lm75ad.ino b/tasmota/tasmota_xsns_sensor/xsns_26_lm75ad.ino similarity index 100% rename from tasmota/xsns_26_lm75ad.ino rename to tasmota/tasmota_xsns_sensor/xsns_26_lm75ad.ino diff --git a/tasmota/xsns_27_apds9960.ino b/tasmota/tasmota_xsns_sensor/xsns_27_apds9960.ino similarity index 100% rename from tasmota/xsns_27_apds9960.ino rename to tasmota/tasmota_xsns_sensor/xsns_27_apds9960.ino diff --git a/tasmota/xsns_28_tm1638.ino b/tasmota/tasmota_xsns_sensor/xsns_28_tm1638.ino similarity index 100% rename from tasmota/xsns_28_tm1638.ino rename to tasmota/tasmota_xsns_sensor/xsns_28_tm1638.ino diff --git a/tasmota/xsns_29_mcp230xx.ino b/tasmota/tasmota_xsns_sensor/xsns_29_mcp230xx.ino similarity index 100% rename from tasmota/xsns_29_mcp230xx.ino rename to tasmota/tasmota_xsns_sensor/xsns_29_mcp230xx.ino diff --git a/tasmota/xsns_30_mpr121.ino b/tasmota/tasmota_xsns_sensor/xsns_30_mpr121.ino similarity index 100% rename from tasmota/xsns_30_mpr121.ino rename to tasmota/tasmota_xsns_sensor/xsns_30_mpr121.ino diff --git a/tasmota/xsns_31_ccs811.ino b/tasmota/tasmota_xsns_sensor/xsns_31_ccs811.ino similarity index 100% rename from tasmota/xsns_31_ccs811.ino rename to tasmota/tasmota_xsns_sensor/xsns_31_ccs811.ino diff --git a/tasmota/xsns_31_ccs811_v2.ino b/tasmota/tasmota_xsns_sensor/xsns_31_ccs811_v2.ino similarity index 100% rename from tasmota/xsns_31_ccs811_v2.ino rename to tasmota/tasmota_xsns_sensor/xsns_31_ccs811_v2.ino diff --git a/tasmota/xsns_32_mpu6050.ino b/tasmota/tasmota_xsns_sensor/xsns_32_mpu6050.ino similarity index 100% rename from tasmota/xsns_32_mpu6050.ino rename to tasmota/tasmota_xsns_sensor/xsns_32_mpu6050.ino diff --git a/tasmota/xsns_34_hx711.ino b/tasmota/tasmota_xsns_sensor/xsns_34_hx711.ino similarity index 100% rename from tasmota/xsns_34_hx711.ino rename to tasmota/tasmota_xsns_sensor/xsns_34_hx711.ino diff --git a/tasmota/xsns_35_tx20.ino b/tasmota/tasmota_xsns_sensor/xsns_35_tx20.ino similarity index 100% rename from tasmota/xsns_35_tx20.ino rename to tasmota/tasmota_xsns_sensor/xsns_35_tx20.ino diff --git a/tasmota/xsns_36_mgc3130.ino b/tasmota/tasmota_xsns_sensor/xsns_36_mgc3130.ino similarity index 100% rename from tasmota/xsns_36_mgc3130.ino rename to tasmota/tasmota_xsns_sensor/xsns_36_mgc3130.ino diff --git a/tasmota/xsns_37_rfsensor.ino b/tasmota/tasmota_xsns_sensor/xsns_37_rfsensor.ino similarity index 100% rename from tasmota/xsns_37_rfsensor.ino rename to tasmota/tasmota_xsns_sensor/xsns_37_rfsensor.ino diff --git a/tasmota/xsns_38_az7798.ino b/tasmota/tasmota_xsns_sensor/xsns_38_az7798.ino similarity index 100% rename from tasmota/xsns_38_az7798.ino rename to tasmota/tasmota_xsns_sensor/xsns_38_az7798.ino diff --git a/tasmota/xsns_39_max31855.ino b/tasmota/tasmota_xsns_sensor/xsns_39_max31855.ino similarity index 100% rename from tasmota/xsns_39_max31855.ino rename to tasmota/tasmota_xsns_sensor/xsns_39_max31855.ino diff --git a/tasmota/xsns_40_pn532.ino b/tasmota/tasmota_xsns_sensor/xsns_40_pn532.ino similarity index 100% rename from tasmota/xsns_40_pn532.ino rename to tasmota/tasmota_xsns_sensor/xsns_40_pn532.ino diff --git a/tasmota/xsns_41_max44009.ino b/tasmota/tasmota_xsns_sensor/xsns_41_max44009.ino similarity index 100% rename from tasmota/xsns_41_max44009.ino rename to tasmota/tasmota_xsns_sensor/xsns_41_max44009.ino diff --git a/tasmota/xsns_42_scd30.ino b/tasmota/tasmota_xsns_sensor/xsns_42_scd30.ino similarity index 100% rename from tasmota/xsns_42_scd30.ino rename to tasmota/tasmota_xsns_sensor/xsns_42_scd30.ino diff --git a/tasmota/xsns_43_hre.ino b/tasmota/tasmota_xsns_sensor/xsns_43_hre.ino similarity index 100% rename from tasmota/xsns_43_hre.ino rename to tasmota/tasmota_xsns_sensor/xsns_43_hre.ino diff --git a/tasmota/xsns_44_sps30.ino b/tasmota/tasmota_xsns_sensor/xsns_44_sps30.ino similarity index 100% rename from tasmota/xsns_44_sps30.ino rename to tasmota/tasmota_xsns_sensor/xsns_44_sps30.ino diff --git a/tasmota/xsns_45_vl53l0x.ino b/tasmota/tasmota_xsns_sensor/xsns_45_vl53l0x.ino similarity index 100% rename from tasmota/xsns_45_vl53l0x.ino rename to tasmota/tasmota_xsns_sensor/xsns_45_vl53l0x.ino diff --git a/tasmota/xsns_46_MLX90614.ino b/tasmota/tasmota_xsns_sensor/xsns_46_MLX90614.ino similarity index 100% rename from tasmota/xsns_46_MLX90614.ino rename to tasmota/tasmota_xsns_sensor/xsns_46_MLX90614.ino diff --git a/tasmota/xsns_47_max31865.ino b/tasmota/tasmota_xsns_sensor/xsns_47_max31865.ino similarity index 100% rename from tasmota/xsns_47_max31865.ino rename to tasmota/tasmota_xsns_sensor/xsns_47_max31865.ino diff --git a/tasmota/xsns_48_chirp.ino b/tasmota/tasmota_xsns_sensor/xsns_48_chirp.ino similarity index 100% rename from tasmota/xsns_48_chirp.ino rename to tasmota/tasmota_xsns_sensor/xsns_48_chirp.ino diff --git a/tasmota/xsns_50_paj7620.ino b/tasmota/tasmota_xsns_sensor/xsns_50_paj7620.ino similarity index 100% rename from tasmota/xsns_50_paj7620.ino rename to tasmota/tasmota_xsns_sensor/xsns_50_paj7620.ino diff --git a/tasmota/xsns_51_rdm6300.ino b/tasmota/tasmota_xsns_sensor/xsns_51_rdm6300.ino similarity index 100% rename from tasmota/xsns_51_rdm6300.ino rename to tasmota/tasmota_xsns_sensor/xsns_51_rdm6300.ino diff --git a/tasmota/xsns_52_esp32_ibeacon_ble.ino b/tasmota/tasmota_xsns_sensor/xsns_52_esp32_ibeacon_ble.ino similarity index 99% rename from tasmota/xsns_52_esp32_ibeacon_ble.ino rename to tasmota/tasmota_xsns_sensor/xsns_52_esp32_ibeacon_ble.ino index 2e22b58db..84e6e01b1 100644 --- a/tasmota/xsns_52_esp32_ibeacon_ble.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_52_esp32_ibeacon_ble.ino @@ -52,7 +52,7 @@ // for testing of BLE_ESP32, we remove xsns_52_ibeacon.ino completely, and instead add this modified xsns_52_ibeacon_BLE_ESP32.ino // in the future this may be more fine-grained, e.g. to allow hm17 for this, and BLE-ESP32 for other -#if CONFIG_IDF_TARGET_ESP32 +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 #ifdef USE_BLE_ESP32 #define XSNS_52 52 diff --git a/tasmota/xsns_52_ibeacon.ino b/tasmota/tasmota_xsns_sensor/xsns_52_ibeacon.ino old mode 100755 new mode 100644 similarity index 100% rename from tasmota/xsns_52_ibeacon.ino rename to tasmota/tasmota_xsns_sensor/xsns_52_ibeacon.ino diff --git a/tasmota/xsns_53_sml.ino b/tasmota/tasmota_xsns_sensor/xsns_53_sml.ino old mode 100755 new mode 100644 similarity index 99% rename from tasmota/xsns_53_sml.ino rename to tasmota/tasmota_xsns_sensor/xsns_53_sml.ino index d4f5e4ca5..a7885f8f0 --- a/tasmota/xsns_53_sml.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_53_sml.ino @@ -2171,7 +2171,7 @@ void SML_Decode(uint8_t index) { } uint16_t pos = smltbuf[mindex][2]+3; if (pos>32) pos=32; - uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0],pos); + uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0],pos,0xFFFF); if (lowByte(crc)!=smltbuf[mindex][pos]) goto nextsect; if (highByte(crc)!=smltbuf[mindex][pos+1]) goto nextsect; dval=mbus_dval; @@ -3279,7 +3279,7 @@ void SML_Send_Seq(uint32_t meter,char *seq) { slen += 2; } // append crc - uint16_t crc = MBUS_calculateCRC(sbuff, slen); + uint16_t crc = MBUS_calculateCRC(sbuff, slen, 0xFFFF); *ucp++ = lowByte(crc); *ucp++ = highByte(crc); slen += 2; @@ -3313,9 +3313,10 @@ void SML_Send_Seq(uint32_t meter,char *seq) { } #endif // USE_SCRIPT -uint16_t MBUS_calculateCRC(uint8_t *frame, uint8_t num) { +uint16_t MBUS_calculateCRC(uint8_t *frame, uint8_t num, uint16_t start) { uint16_t crc, flag; - crc = 0xFFFF; + //crc = 0xFFFF; + crc = start; for (uint32_t i = 0; i < num; i++) { crc ^= frame[i]; for (uint32_t j = 8; j; j--) { diff --git a/tasmota/xsns_54_ina226.ino b/tasmota/tasmota_xsns_sensor/xsns_54_ina226.ino similarity index 100% rename from tasmota/xsns_54_ina226.ino rename to tasmota/tasmota_xsns_sensor/xsns_54_ina226.ino diff --git a/tasmota/xsns_55_hih_series.ino b/tasmota/tasmota_xsns_sensor/xsns_55_hih_series.ino similarity index 100% rename from tasmota/xsns_55_hih_series.ino rename to tasmota/tasmota_xsns_sensor/xsns_55_hih_series.ino diff --git a/tasmota/xsns_56_hpma.ino b/tasmota/tasmota_xsns_sensor/xsns_56_hpma.ino similarity index 100% rename from tasmota/xsns_56_hpma.ino rename to tasmota/tasmota_xsns_sensor/xsns_56_hpma.ino diff --git a/tasmota/xsns_57_tsl2591.ino b/tasmota/tasmota_xsns_sensor/xsns_57_tsl2591.ino similarity index 100% rename from tasmota/xsns_57_tsl2591.ino rename to tasmota/tasmota_xsns_sensor/xsns_57_tsl2591.ino diff --git a/tasmota/xsns_58_dht12.ino b/tasmota/tasmota_xsns_sensor/xsns_58_dht12.ino similarity index 100% rename from tasmota/xsns_58_dht12.ino rename to tasmota/tasmota_xsns_sensor/xsns_58_dht12.ino diff --git a/tasmota/xsns_59_ds1624.ino b/tasmota/tasmota_xsns_sensor/xsns_59_ds1624.ino similarity index 100% rename from tasmota/xsns_59_ds1624.ino rename to tasmota/tasmota_xsns_sensor/xsns_59_ds1624.ino diff --git a/tasmota/xsns_60_GPS.ino b/tasmota/tasmota_xsns_sensor/xsns_60_GPS.ino similarity index 97% rename from tasmota/xsns_60_GPS.ino rename to tasmota/tasmota_xsns_sensor/xsns_60_GPS.ino index 7108f9757..edf3d9c81 100644 --- a/tasmota/xsns_60_GPS.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_60_GPS.ino @@ -1,930 +1,930 @@ -/* - xsns_60_GPS.ino - GPS UBLOX support for Tasmota - - Copyright (C) 2021 Theo Arends, Christian Baars and Adrian Scillato - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifdef USE_GPS -#if defined(ESP32) && defined(USE_FLOG) - #undef USE_FLOG - #warning FLOG deactivated on ESP32 -#endif //ESP32 -/*********************************************************************************************\ - -------------------------------------------------------------------------------------------- - Version Date Action Description - -------------------------------------------------------------------------------------------- - - 0.9.3.0 20200214 integrate - fix set lat/lon via commandd 13, V-Port now works parallel - --- - 0.9.2.0 20200110 integrate - Added UART-over-TCP/IP-bridge (virtual serial port). Minor tweaks. - --- - 0.9.1.0 20191216 integrate - Added pin specifications from Tasmota WEB UI. Minor tweaks. - --- - 0.9.0.0 20190817 started - further development by Christian Baars - https://github.com/Staars/Sonoff-Tasmota - forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota - base - code base from arendst and - https://www.youtube.com/watch?v=TwhCX0c8Xe0 - -## GPS-driver for the Ublox-series 6-8 -Driver is tested on a NEO-6m and a Beitian-220. Series 7 should work too. This adds only about 6kb to the program size, because the efficient UBX-protocol is used. These modules are quite cheap, starting at about 3.50€ for the NEO-6m. - -## Features: -- get position and time data -- sets system time automatically and Settings->latitude and Settings->longitude via command -- can log postion data with timestamp to flash with a small memory footprint of only 12 Bytes per record -- constructs a GPX-file for download of this data -- Web-UI -- simplified NTP-server and UART-over-TCP/IP-bridge (virtual serial port) -- command interface - -## Usage: -The serial pins are GPS_RX and GPS_TX, no further installation steps needed. To get more debug information compile it with option "DEBUG_TASMOTA_SENSOR". - - -## Commands: - -+ sensor60 0 - write to all available sectors, then restart and overwrite the older ones - -+ sensor60 1 - write to all available sectors, then restart and overwrite the older ones - -+ sensor60 2 - filter out horizontal drift noise - -+ sensor60 3 - turn off noise filter - -+ sensor60 4 - start recording, new data will be appended - -+ sensor60 5 - start new recording, old data will lost - -+ sensor60 6 - stop recording, download link will be visible in Web-UI - -+ sensor60 7 - send mqtt on new postion + TELE -> consider to set TELE to a very high value - -+ sensor60 8 - only TELE message - -+ sensor60 9 - start NTP-server - -+ sensor60 10 - deactivate NTP-server - -+ sensor60 11 - force update of Tasmota-system-UTC with every new GPS-time-message - -+ sensor60 12 - do not update of Tasmota-system-UTC with every new GPS-time-message - -+ sensor60 13 - set latitude and longitude in settings - -+ sensor60 14 - open virtual serial port over TCP, usable for u-center - -+ sensor60 15 - pause virtual serial port over TCP - -## Rules examples for SSD1306 32x128 - - -rule1 on tele-GPS#lat do DisplayText [s1p21c1l01f1]LAT: %value% endon on tele-GPS#lon do DisplayText [s1p21c1l2]LON: %value% endon on switch1#state==3 do sensor60 4 endon on switch1#state==2 do sensor60 6 endon - -rule2 on tele-GPS#int>9 do DisplayText [f0c9l4]I%value% endon on tele-GPS#int<10 do DisplayText [f0c9l4]I0%value% endon on tele-GPS#fil==1 do DisplayText [f0c18l4]F endon on tele-GPS#fil==0 do DisplayText [f0c18l4]N endon - -rule3 on tele-FLOG#sec do DisplayText [f0c1l4]SAV:%value% endon on tele-FLOG#rec==1 do DisplayText [f0c1l4]REC: endon on tele-FLOG#mode do DisplayText [f0c14l4]M%value% endon - -\*********************************************************************************************/ - -#define XSNS_60 60 - -#include "NTPServer.h" -#include "NTPPacket.h" - -/*********************************************************************************************\ - * constants -\*********************************************************************************************/ - -#define D_CMND_UBX "UBX" - -const char S_JSON_UBX_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_UBX "%s\":%d}"; - -const char kUBXTypes[] PROGMEM = "UBX"; - -#define UBX_LAT_LON_THRESHOLD 1000 // filter out some noise of local drift - -#define UBX_SERIAL_BUFFER_SIZE 256 -#define UBX_TCP_PORT 1234 -#define NTP_MILLIS_OFFSET 50 // estimated latency in milliseconds - -/********************************************************************************************\ -| *globals -\*********************************************************************************************/ - -const char UBLOX_INIT[] PROGMEM = { - // Disable NMEA - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x24, // GxGGA off - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x2B, // GxGLL off - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x32, // GxGSA off - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x39, // GxGSV off - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x40, // GxRMC off - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x05,0x47, // GxVTG off - - // Disable UBX - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0xDC, //NAV-PVT off - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xB9, //NAV-POSLLH off - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xC0, //NAV-STATUS off - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x92, //NAV-TIMEUTC off - - // Enable UBX - // 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x07,0x00,0x01,0x00,0x00,0x00,0x00,0x18,0xE1, //NAV-PVT on - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x13,0xBE, //NAV-POSLLH on - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x14,0xC5, //NAV-STATUS on - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x01,0x00,0x00,0x00,0x00,0x32,0x97, //NAV-TIMEUTC on - - // Rate - we will not reset it for the moment after restart - // 0xB5,0x62,0x06,0x08,0x06,0x00,0x64,0x00,0x01,0x00,0x01,0x00,0x7A,0x12, //(10Hz) - // 0xB5,0x62,0x06,0x08,0x06,0x00,0xC8,0x00,0x01,0x00,0x01,0x00,0xDE,0x6A, //(5Hz) - // 0xB5,0x62,0x06,0x08,0x06,0x00,0xE8,0x03,0x01,0x00,0x01,0x00,0x01,0x39 //(1Hz) - // 0xB5,0x62,0x06,0x08,0x06,0x00,0xD0,0x07,0x01,0x00,0x01,0x00,0xED,0xBD //(0.5Hz) -}; - -char UBX_name[4]; - -struct UBX_t { - const char UBX_HEADER[2] = { 0xB5, 0x62 }; // TODO: Check if we really save space here inside the struct - const char NAV_POSLLH_HEADER[2] = { 0x01, 0x02 }; - const char NAV_STATUS_HEADER[2] = { 0x01, 0x03 }; - const char NAV_TIME_HEADER[2] = { 0x01, 0x21 }; - - struct entry_t { - int32_t lat; //raw sensor value - int32_t lon; //raw sensor value - uint32_t time; //local time from system (maybe provided by the sensor) - }; - - union { - entry_t values; - uint8_t bytes[sizeof(entry_t)]; - } rec_buffer; - - struct POLL_MSG { - uint8_t cls; - uint8_t id; - uint16_t zero; - }; - - struct NAV_POSLLH { - uint8_t cls; - uint8_t id; - uint16_t len; - uint32_t iTOW; - int32_t lon; - int32_t lat; - int32_t alt; - int32_t hMSL; - uint32_t hAcc; - uint32_t vAcc; - }; - - struct NAV_STATUS { - uint8_t cls; - uint8_t id; - uint16_t len; - uint32_t iTOW; - uint8_t gpsFix; - uint8_t flags; //bit 0 - gpsfix valid - uint8_t fixStat; - uint8_t flags2; - uint32_t ttff; - uint32_t msss; - }; - - struct NAV_TIME_UTC { - uint8_t cls; - uint8_t id; - uint16_t len; - uint32_t iTOW; - uint32_t tAcc; - int32_t nano; // Nanoseconds of second, range -1e9 .. 1e9 (UTC) - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t min; - uint8_t sec; - struct { - uint8_t UTC:1; - uint8_t WKN:1; // week number - uint8_t TOW:1; // time of week - uint8_t padding:5; - } valid; - }; - - struct CFG_RATE { - uint8_t cls; //0x06 - uint8_t id; //0x08 - uint16_t len; // 6 bytes - uint16_t measRate; // in every ms -> 1 Hz = 1000 ms; 10 Hz = 100 ms -> x = 1000 ms / Hz - uint16_t navRate; // x measurements for 1 navigation event - uint16_t timeRef; // align to time system: 0= UTC, 1 = GPS, 2 = GLONASS, ... - char CK[2]; // checksum - }; - - struct { - uint32_t last_iTOW; - int32_t last_alt; - uint32_t last_hAcc; - uint32_t last_vAcc; - uint8_t gpsFix; - uint8_t non_empty_loops; // in case of an unintended reset of the GPS, the serial interface will get flooded with NMEA - uint16_t log_interval; // in tenth of seconds - int32_t timeOffset; // roughly computed offset millis() - iTOW - } state; - - struct { - uint32_t init:1; - uint32_t filter_noise:1; - uint32_t send_when_new:1; // no teleinterval - uint32_t send_UI_only:1; - uint32_t runningNTP:1; - // uint32_t blockedNTP:1; - uint32_t forceUTCupdate:1; - uint32_t runningVPort:1; - // TODO: more to come - } mode; - - union { - NAV_POSLLH navPosllh; - NAV_STATUS navStatus; - NAV_TIME_UTC navTime; - POLL_MSG pollMsg; - CFG_RATE cfgRate; - } Message; - - uint32_t utc_time; - - uint8_t TCPbuf[UBX_SERIAL_BUFFER_SIZE]; - size_t TCPbufSize; -} UBX; - -enum UBXMsgType { - MT_NONE, - MT_NAV_POSLLH, - MT_NAV_STATUS, - MT_NAV_TIME, - MT_POLL -}; - -#ifdef USE_FLOG -FLOG *Flog = nullptr; -#endif //USE_FLOG -TasmotaSerial *UBXSerial; - -NtpServer timeServer(PortUdp); - -WiFiServer vPortServer(UBX_TCP_PORT); -WiFiClient vPortClient; - -/*********************************************************************************************\ - * helper function -\*********************************************************************************************/ - -void UBXcalcChecksum(char* CK, size_t msgSize) -{ - memset(CK, 0, 2); - for (int i = 0; i < msgSize; i++) { - CK[0] += ((char*)(&UBX.Message))[i]; - CK[1] += CK[0]; - } -} - -bool UBXcompareMsgHeader(const char* msgHeader) -{ - char* ptr = (char*)(&UBX.Message); - return ptr[0] == msgHeader[0] && ptr[1] == msgHeader[1]; -} - -void UBXinitCFG(void) -{ - for (uint32_t i = 0; i < sizeof(UBLOX_INIT); i++) { - UBXSerial->write( pgm_read_byte(UBLOX_INIT+i) ); - } - DEBUG_SENSOR_LOG(PSTR("UBX: turn off NMEA")); -} - -void UBXsendCFGLine(uint8_t _line) -{ - if (_line>sizeof(UBLOX_INIT)/16) return; - for (uint32_t i = 0; i < 16; i++) { - UBXSerial->write( pgm_read_byte(UBLOX_INIT+i+(_line*16)) ); - } - DEBUG_SENSOR_LOG(PSTR("UBX: send line %u of UBLOX_INIT"), _line); -} - -/********************************************************************************************/ - -void UBXDetect(void) -{ - UBX.mode.init = 0; - if (PinUsed(GPIO_GPS_RX) && PinUsed(GPIO_GPS_TX)) { - UBXSerial = new TasmotaSerial(Pin(GPIO_GPS_RX), Pin(GPIO_GPS_TX), 1, 0, UBX_SERIAL_BUFFER_SIZE); // 64 byte buffer is NOT enough - if (UBXSerial->begin(9600)) { - DEBUG_SENSOR_LOG(PSTR("UBX: started serial")); - if (UBXSerial->hardwareSerial()) { - ClaimSerial(); - DEBUG_SENSOR_LOG(PSTR("UBX: claim HW")); - } - } - } - else { - return; - } - - UBXinitCFG(); // turn off NMEA, only use "our" UBX-messages - UBX.mode.init = 1; - -#ifdef USE_FLOG - if (!Flog) { - Flog = new FLOG; // init Flash Log - Flog->init(); - } -#endif // USE_FLOG - - UBX.state.log_interval = 10; // 1 second - UBX.mode.send_UI_only = true; // send UI data ... -// MqttPublishTeleperiodSensor(); // ... once at after start (No MQTT ready yet so do NOT try to send) -} - -uint32_t UBXprocessGPS() -{ - static uint32_t fpos = 0; - static char checksum[2]; - static uint8_t currentMsgType = MT_NONE; - static size_t payloadSize = sizeof(UBX.Message); - - // DEBUG_SENSOR_LOG(PSTR("UBX: check for serial data")); - uint32_t data_bytes = 0; - while ( UBXSerial->available() ) { - data_bytes++; - byte c = UBXSerial->read(); - if (UBX.mode.runningVPort){ - UBX.TCPbuf[data_bytes-1] = c; // immediately copy byte to TCP-buf - UBX.TCPbufSize = data_bytes; - } - if ( fpos < 2 ) { - // For the first two bytes we are simply looking for a match with the UBX header bytes (0xB5,0x62) - if ( c == UBX.UBX_HEADER[fpos] ) { - fpos++; - } else { - fpos = 0; // Reset to beginning state. - } - } else { - // If we come here then fpos >= 2, which means we have found a match with the UBX_HEADER - // and we are now reading in the bytes that make up the payload. - - // Place the incoming byte into the ubxMessage struct. The position is fpos-2 because - // the struct does not include the initial two-byte header (UBX_HEADER). - if ( (fpos-2) < payloadSize ) { - ((char*)(&UBX.Message))[fpos-2] = c; - } - fpos++; - - if ( fpos == 4 ) { - // We have just received the second byte of the message type header, - // so now we can check to see what kind of message it is. - if ( UBXcompareMsgHeader(UBX.NAV_POSLLH_HEADER) ) { - currentMsgType = MT_NAV_POSLLH; - payloadSize = sizeof(UBX_t::NAV_POSLLH); - DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_POSLLH")); - } - else if ( UBXcompareMsgHeader(UBX.NAV_STATUS_HEADER) ) { - currentMsgType = MT_NAV_STATUS; - payloadSize = sizeof(UBX_t::NAV_STATUS); - DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_STATUS")); - } - else if ( UBXcompareMsgHeader(UBX.NAV_TIME_HEADER) ) { - currentMsgType = MT_NAV_TIME; - payloadSize = sizeof(UBX_t::NAV_TIME_UTC); - DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_TIME_UTC")); - } - else { - // unknown message type, bail - fpos = 0; - continue; - } - } - - if ( fpos == (payloadSize+2) ) { - // All payload bytes have now been received, so we can calculate the - // expected checksum value to compare with the next two incoming bytes. - UBXcalcChecksum(checksum, payloadSize); - } - else if ( fpos == (payloadSize+3) ) { - // First byte after the payload, ie. first byte of the checksum. - // Does it match the first byte of the checksum we calculated? - if ( c != checksum[0] ) { - // Checksum doesn't match, reset to beginning state and try again. - fpos = 0; - } - } - else if ( fpos == (payloadSize+4) ) { - // Second byte after the payload, ie. second byte of the checksum. - // Does it match the second byte of the checksum we calculated? - fpos = 0; // We will reset the state regardless of whether the checksum matches. - if ( c == checksum[1] ) { - // Checksum matches, we have a valid message. - return currentMsgType; - } - } - else if ( fpos > (payloadSize+4) ) { - // We have now read more bytes than both the expected payload and checksum - // together, so something went wrong. Reset to beginning state and try again. - fpos = 0; - } - } - } - // DEBUG_SENSOR_LOG(PSTR("UBX: got none or unknown Message")); - if (data_bytes!=0) { - UBX.state.non_empty_loops++; - DEBUG_SENSOR_LOG(PSTR("UBX: got %u bytes, non-empty-loop: %u"), data_bytes, UBX.state.non_empty_loops); - } else { - UBX.state.non_empty_loops = 0; // now a hidden GPS-device reset is unlikely - } - return MT_NONE; -} - -/********************************************************************************************\ -| * callback functions for the download -\*********************************************************************************************/ - -#ifdef USE_FLOG -void UBXsendHeader(void) -{ - Webserver->setContentLength(CONTENT_LENGTH_UNKNOWN); - Webserver->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx")); - WSSend(200, CT_APP_STREAM, F( - "\r\n" - "\r\n" - "\r\n\r\n")); -} - -void UBXsendRecord(uint8_t *buf) -{ - char record[100]; - char stime[32]; - UBX_t::entry_t *entry = (UBX_t::entry_t*)buf; - snprintf_P(stime, sizeof(stime), GetDT(entry->time).c_str()); - char lat[12]; - char lon[12]; - dtostrfd((double)entry->lat/10000000.0f,7,lat); - dtostrfd((double)entry->lon/10000000.0f,7,lon); - snprintf_P(record, sizeof(record),PSTR("\n\t\n\n"),lat ,lon, stime); - // DEBUG_SENSOR_LOG(PSTR("FLOG: DL %u %u"), Flog->sector.dword_buffer[k+j],Flog->sector.dword_buffer[k+j+1]); - Webserver->sendContent_P(record); -} - -void UBXsendFooter(void) -{ - Webserver->sendContent(F("\n\n")); - Webserver->sendContent(""); - Rtc.user_time_entry = false; // we have blocked the main loop and want a new valid time -} - -/********************************************************************************************/ - -void UBXsendFile(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - Flog->startDownload(sizeof(UBX.rec_buffer),UBXsendHeader,UBXsendRecord,UBXsendFooter); -} -#endif //USE_FLOG - -/********************************************************************************************/ - -void UBXSetRate(uint16_t interval) -{ - UBX.Message.cfgRate.cls = 0x06; - UBX.Message.cfgRate.id = 0x08; - UBX.Message.cfgRate.len = 6; - uint32_t measRate = (1000*(uint32_t)interval); //seconds to milliseconds - if (measRate > 0xffff) { - measRate = 0xffff; // max. 65535 ms interval - } - UBX.Message.cfgRate.measRate = (uint16_t)measRate; - UBX.Message.cfgRate.navRate = 1; - UBX.Message.cfgRate.timeRef = 1; - UBXcalcChecksum(UBX.Message.cfgRate.CK, sizeof(UBX.Message.cfgRate)-sizeof(UBX.Message.cfgRate.CK)); - DEBUG_SENSOR_LOG(PSTR("UBX: requested interval: %u seconds measRate: %u ms"), interval, UBX.Message.cfgRate.measRate); - UBXSerial->write(UBX.UBX_HEADER[0]); - UBXSerial->write(UBX.UBX_HEADER[1]); - for (uint32_t i =0; iwrite(((uint8_t*)(&UBX.Message.cfgRate))[i]); - DEBUG_SENSOR_LOG(PSTR("UBX: cfgRate byte %u: %x"), i, ((uint8_t*)(&UBX.Message.cfgRate))[i]); - } - UBX.state.log_interval = 10*interval; -} - -void UBXSelectMode(uint16_t mode) -{ - DEBUG_SENSOR_LOG(PSTR("UBX: set mode to %u"),mode); - switch(mode){ -#ifdef USE_FLOG - case 0: - Flog->mode = 0; // write once to all available sectors, then stop - break; - case 1: - Flog->mode = 1; // write to all available sectors, then restart and overwrite the older ones - break; - case 2: - UBX.mode.filter_noise = true; // filter out horizontal drift noise, TODO: find useful values - break; - case 3: - UBX.mode.filter_noise = false; - break; - case 4: - Flog->startRecording(true); - AddLog(LOG_LEVEL_INFO, PSTR("UBX: start recording - appending")); - break; - case 5: - Flog->startRecording(false); - AddLog(LOG_LEVEL_INFO, PSTR("UBX: start recording - new log")); - break; - case 6: - if(Flog->recording == true){ - Flog->stopRecording(); - } - AddLog(LOG_LEVEL_INFO, PSTR("UBX: stop recording")); - break; -#endif //USE_FLOG - case 7: - UBX.mode.send_when_new = 1; // send mqtt on new postion + TELE -> consider to set TELE to a very high value - break; - case 8: - UBX.mode.send_when_new = 0; // only TELE - break; - case 9: - if (timeServer.beginListening()) { - UBX.mode.runningNTP = true; - } - break; - case 10: - UBX.mode.runningNTP = false; - UBXsendCFGLine(10); //NAV-POSLLH on - UBXsendCFGLine(11); //NAV-STATUS on - break; - case 11: - UBX.mode.forceUTCupdate = true; - break; - case 12: - UBX.mode.forceUTCupdate = false; - break; - case 13: - Settings->latitude = UBX.rec_buffer.values.lat/10; - Settings->longitude = UBX.rec_buffer.values.lon/10; - break; - case 14: - vPortServer.begin(); - UBX.mode.runningVPort = 1; - break; - case 15: - // vPortServer.stop(); // seems not to work reliably - UBX.mode.runningVPort = 0; - break; - default: - if (mode>1000 && mode <1066) { - UBXSetRate(mode-1000); // set interval between measurements in seconds from 1 to 65 - } - break; - } - UBX.mode.send_UI_only = true; - MqttPublishTeleperiodSensor(); -} - -/********************************************************************************************/ - -bool UBXHandlePOSLLH() -{ - DEBUG_SENSOR_LOG(PSTR("UBX: iTOW: %u"),UBX.Message.navPosllh.iTOW); - if (UBX.state.gpsFix>1) { - if (UBX.mode.filter_noise) { - if ((UBX.Message.navPosllh.lat-UBX.rec_buffer.values.lat go to pure NTP-mode - UBXsendCFGLine(7); //NAV-POSLLH off - UBXsendCFGLine(8); //NAV-STATUS off - } - return true; // new position - } else { - DEBUG_SENSOR_LOG(PSTR("UBX: no valid position data")); - } - return false; // no GPS-fix -} - -void UBXHandleSTATUS() -{ - DEBUG_SENSOR_LOG(PSTR("UBX: gpsFix: %u, valid: %u"), UBX.Message.navStatus.gpsFix, (UBX.Message.navStatus.flags)&1); - if ((UBX.Message.navStatus.flags)&1) { - UBX.state.gpsFix = UBX.Message.navStatus.gpsFix; //only store fixed status if flag is valid - } else { - UBX.state.gpsFix = 0; // without valid flag, everything is "no fix" - } -} - -void UBXHandleTIME() -{ - DEBUG_SENSOR_LOG(PSTR("UBX: UTC-Time: %u-%u-%u %u:%u:%u"), UBX.Message.navTime.year, UBX.Message.navTime.month ,UBX.Message.navTime.day,UBX.Message.navTime.hour,UBX.Message.navTime.min,UBX.Message.navTime.sec); - if (UBX.Message.navTime.valid.UTC == 1) { - UBX.state.timeOffset = millis(); // iTOW%1000 should be 0 here, when NTP-server is enabled and in "pure mode" - DEBUG_SENSOR_LOG(PSTR("UBX: UTC-Time is valid")); - bool resync = (Rtc.utc_time > UBX.utc_time); // Sync local time every hour - if (Rtc.user_time_entry == false || UBX.mode.forceUTCupdate || UBX.mode.runningNTP || resync) { - TIME_T gpsTime; - gpsTime.year = UBX.Message.navTime.year - 1970; - gpsTime.month = UBX.Message.navTime.month; - gpsTime.day_of_month = UBX.Message.navTime.day; - gpsTime.hour = UBX.Message.navTime.hour; - gpsTime.minute = UBX.Message.navTime.min; - gpsTime.second = UBX.Message.navTime.sec; - UBX.rec_buffer.values.time = MakeTime(gpsTime); - if (UBX.mode.forceUTCupdate || (Rtc.user_time_entry == false) || resync) { -// AddLog(LOG_LEVEL_INFO, PSTR("UBX: UTC-Time is valid, set system time")); - UBX.utc_time = UBX.rec_buffer.values.time + 3600; - Rtc.utc_time = UBX.rec_buffer.values.time; - RtcSync("UBX"); - } - Rtc.user_time_entry = true; - } - } -} - -void UBXHandleOther(void) -{ - if (UBX.state.non_empty_loops>6) { // we expect only 4-5 non-empty loops in a row, could change with other sensor speed (Hz) - if(UBX.mode.runningVPort) return; - UBXinitCFG(); // this should only happen with lots of NMEA-messages, but it is only a guess!! - AddLog(LOG_LEVEL_ERROR, PSTR("UBX: possible device-reset, will re-init")); - UBXSerial->flush(); - UBX.state.non_empty_loops = 0; - } -} - -/********************************************************************************************/ - -void UBXLoop50msec(void) -{ - // handle virtual serial port - if (UBX.mode.runningVPort){ - if(!vPortClient.connected()) { - vPortClient = vPortServer.available(); - } - while(vPortClient.available()) { - byte _newByte = vPortClient.read(); - UBXSerial->write(_newByte); - } - - if (UBX.TCPbufSize!=0){ - vPortClient.write((char*)UBX.TCPbuf, UBX.TCPbufSize); - UBX.TCPbufSize = 0; - } - } - // handle NTP-server - if(UBX.mode.runningNTP){ - timeServer.processOneRequest(UBX.rec_buffer.values.time, UBX.state.timeOffset - NTP_MILLIS_OFFSET); - } -} - -void UBXLoop(void) -{ - static uint16_t counter; //count up every 100 msec - static bool new_position; - - uint32_t msgType = UBXprocessGPS(); - - switch(msgType){ - case MT_NAV_POSLLH: - new_position = UBXHandlePOSLLH(); - break; - case MT_NAV_STATUS: - UBXHandleSTATUS(); - break; - case MT_NAV_TIME: - UBXHandleTIME(); - break; - default: - UBXHandleOther(); - break; - } - -#ifdef USE_FLOG - if (counter>UBX.state.log_interval) { - if (Flog->recording && new_position) { - UBX.rec_buffer.values.time = Rtc.local_time; - Flog->addToBuffer(UBX.rec_buffer.bytes, sizeof(UBX.rec_buffer.bytes)); - counter = 0; - } - } -#endif // USE_FLOG - - counter++; -} - -/********************************************************************************************/ -// normaly in i18n.h - -#ifdef USE_WEBSERVER - // {s} = - -#ifdef USE_FLOG -#ifdef DEBUG_TASMOTA_SENSOR - const char HTTP_SNS_FLOGVER[] PROGMEM = "{s}
{m}
{e}{s} FLOG with %u sectors: {m}%u bytes{e}" - "{s} FLOG next sector for REC: {m} %u {e}" - "{s} %u sector(s) with data at sector: {m} %u {e}"; - const char HTTP_SNS_FLOGREC[] PROGMEM = "{s} RECORDING (bytes in buffer) {m}%u{e}"; -#endif // DEBUG_TASMOTA_SENSOR - - const char HTTP_SNS_FLOG[] PROGMEM = "{s}
{m}
{e}{s} Flash-Log {m} %s{e}"; - const char kFLOG_STATE0[] PROGMEM = "ready"; - const char kFLOG_STATE1[] PROGMEM = "recording"; - const char * kFLOG_STATE[] ={kFLOG_STATE0, kFLOG_STATE1}; - - const char HTTP_BTN_FLOG_DL[] PROGMEM = ""; - -#endif //USE_FLOG - const char HTTP_SNS_NTPSERVER[] PROGMEM = "{s} NTP server {m}active{e}"; - - const char HTTP_SNS_GPS[] PROGMEM = "{s} GPS latitude {m}%s{e}" - "{s} GPS longitude {m}%s{e}" - "{s} GPS altitude {m}%s m{e}" - "{s} GPS hor. Accuracy {m}%s m{e}" - "{s} GPS vert. Accuracy {m}%s m{e}" - "{s} GPS sat-fix status {m}%s{e}"; - - const char kGPSFix0[] PROGMEM = "no fix"; - const char kGPSFix1[] PROGMEM = "dead reckoning only"; - const char kGPSFix2[] PROGMEM = "2D-fix"; - const char kGPSFix3[] PROGMEM = "3D-fix"; - const char kGPSFix4[] PROGMEM = "GPS + dead reckoning combined"; - const char kGPSFix5[] PROGMEM = "Time only fix"; - const char * kGPSFix[] PROGMEM ={kGPSFix0, kGPSFix1, kGPSFix2, kGPSFix3, kGPSFix4, kGPSFix5}; - -// const char UBX_GOOGLE_MAPS[] =""; - - -#endif // USE_WEBSERVER - -/********************************************************************************************/ - -void UBXShow(bool json) -{ - char lat[12]; - char lon[12]; - char alt[12]; - char hAcc[12]; - char vAcc[12]; - dtostrfd((double)UBX.rec_buffer.values.lat/10000000.0f,7,lat); - dtostrfd((double)UBX.rec_buffer.values.lon/10000000.0f,7,lon); - dtostrfd((double)UBX.state.last_alt/1000.0f,3,alt); - dtostrfd((double)UBX.state.last_vAcc/1000.0f,3,hAcc); - dtostrfd((double)UBX.state.last_hAcc/1000.0f,3,vAcc); - - if (json) { - ResponseAppend_P(PSTR(",\"GPS\":{")); - if (UBX.mode.send_UI_only) { - uint32_t i = UBX.state.log_interval / 10; - ResponseAppend_P(PSTR("\"fil\":%u,\"int\":%u}"), UBX.mode.filter_noise, i); - } else { - ResponseAppend_P(PSTR("\"lat\":%s,\"lon\":%s,\"alt\":%s,\"hAcc\":%s,\"vAcc\":%s}"), lat, lon, alt, hAcc, vAcc); - } -#ifdef USE_FLOG - ResponseAppend_P(PSTR(",\"FLOG\":{\"rec\":%u,\"mode\":%u,\"sec\":%u}"), Flog->recording, Flog->mode, Flog->sectors_left); -#endif //USE_FLOG - UBX.mode.send_UI_only = false; -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_GPS, lat, lon, alt, hAcc, vAcc, kGPSFix[UBX.state.gpsFix]); - //WSContentSend_P(UBX_GOOGLE_MAPS, lat, lon); -#ifdef DEBUG_TASMOTA_SENSOR -#ifdef USE_FLOG - WSContentSend_PD(HTTP_SNS_FLOGVER, Flog->num_sectors, Flog->size, Flog->current_sector, Flog->sectors_left, Flog->sector.header.physical_start_sector); - if (Flog->recording) { - WSContentSend_PD(HTTP_SNS_FLOGREC, Flog->sector.header.buf_pointer - 8); - } -#endif //USE_FLOG -#endif // DEBUG_TASMOTA_SENSOR -#ifdef USE_FLOG - if (Flog->ready) { - WSContentSend_P(HTTP_SNS_FLOG,kFLOG_STATE[Flog->recording]); - } - if (!Flog->recording && Flog->found_saved_data) { - WSContentSend_P(HTTP_BTN_FLOG_DL); - } -#endif //USE_FLOG - if (UBX.mode.runningNTP) { - WSContentSend_P(HTTP_SNS_NTPSERVER); - } -#endif // USE_WEBSERVER - } -} - -/*********************************************************************************************\ - * check the UBX commands -\*********************************************************************************************/ - -bool UBXCmd(void) -{ - bool serviced = true; - if (XdrvMailbox.data_len > 0) { - UBXSelectMode(XdrvMailbox.payload); - Response_P(S_JSON_UBX_COMMAND_NVALUE, XdrvMailbox.command, XdrvMailbox.payload); - } - return serviced; -} - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ - -bool Xsns60(uint8_t function) -{ - bool result = false; - - if (FUNC_INIT == function) { - UBXDetect(); - } - - if (UBX.mode.init) { - switch (function) { - case FUNC_COMMAND_SENSOR: - if (XSNS_60 == XdrvMailbox.index) { - result = UBXCmd(); - } - break; - case FUNC_EVERY_50_MSECOND: - UBXLoop50msec(); // handles virtual serial port and NTP server - break; - case FUNC_EVERY_100_MSECOND: -#ifdef USE_FLOG - if (!Flog->running_download) -#endif //USE_FLOG - { - UBXLoop(); - } - break; -#ifdef USE_FLOG - case FUNC_WEB_ADD_HANDLER: - WebServer_on(PSTR("/UBX"), UBXsendFile); - break; -#endif //USE_FLOG - case FUNC_JSON_APPEND: - UBXShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: -#ifdef USE_FLOG - if (!Flog->running_download) -#endif //USE_FLOG - { - UBXShow(0); - } - break; -#endif // USE_WEBSERVER - } - } - return result; -} - +/* + xsns_60_GPS.ino - GPS UBLOX support for Tasmota + + Copyright (C) 2021 Theo Arends, Christian Baars and Adrian Scillato + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_GPS +#if defined(ESP32) && defined(USE_FLOG) + #undef USE_FLOG + #warning FLOG deactivated on ESP32 +#endif //ESP32 +/*********************************************************************************************\ + -------------------------------------------------------------------------------------------- + Version Date Action Description + -------------------------------------------------------------------------------------------- + + 0.9.3.0 20200214 integrate - fix set lat/lon via commandd 13, V-Port now works parallel + --- + 0.9.2.0 20200110 integrate - Added UART-over-TCP/IP-bridge (virtual serial port). Minor tweaks. + --- + 0.9.1.0 20191216 integrate - Added pin specifications from Tasmota WEB UI. Minor tweaks. + --- + 0.9.0.0 20190817 started - further development by Christian Baars - https://github.com/Staars/Sonoff-Tasmota + forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota + base - code base from arendst and - https://www.youtube.com/watch?v=TwhCX0c8Xe0 + +## GPS-driver for the Ublox-series 6-8 +Driver is tested on a NEO-6m and a Beitian-220. Series 7 should work too. This adds only about 6kb to the program size, because the efficient UBX-protocol is used. These modules are quite cheap, starting at about 3.50€ for the NEO-6m. + +## Features: +- get position and time data +- sets system time automatically and Settings->latitude and Settings->longitude via command +- can log postion data with timestamp to flash with a small memory footprint of only 12 Bytes per record +- constructs a GPX-file for download of this data +- Web-UI +- simplified NTP-server and UART-over-TCP/IP-bridge (virtual serial port) +- command interface + +## Usage: +The serial pins are GPS_RX and GPS_TX, no further installation steps needed. To get more debug information compile it with option "DEBUG_TASMOTA_SENSOR". + + +## Commands: + ++ sensor60 0 + write to all available sectors, then restart and overwrite the older ones + ++ sensor60 1 + write to all available sectors, then restart and overwrite the older ones + ++ sensor60 2 + filter out horizontal drift noise + ++ sensor60 3 + turn off noise filter + ++ sensor60 4 + start recording, new data will be appended + ++ sensor60 5 + start new recording, old data will lost + ++ sensor60 6 + stop recording, download link will be visible in Web-UI + ++ sensor60 7 + send mqtt on new postion + TELE -> consider to set TELE to a very high value + ++ sensor60 8 + only TELE message + ++ sensor60 9 + start NTP-server + ++ sensor60 10 + deactivate NTP-server + ++ sensor60 11 + force update of Tasmota-system-UTC with every new GPS-time-message + ++ sensor60 12 + do not update of Tasmota-system-UTC with every new GPS-time-message + ++ sensor60 13 + set latitude and longitude in settings + ++ sensor60 14 + open virtual serial port over TCP, usable for u-center + ++ sensor60 15 + pause virtual serial port over TCP + +## Rules examples for SSD1306 32x128 + + +rule1 on tele-GPS#lat do DisplayText [s1p21c1l01f1]LAT: %value% endon on tele-GPS#lon do DisplayText [s1p21c1l2]LON: %value% endon on switch1#state==3 do sensor60 4 endon on switch1#state==2 do sensor60 6 endon + +rule2 on tele-GPS#int>9 do DisplayText [f0c9l4]I%value% endon on tele-GPS#int<10 do DisplayText [f0c9l4]I0%value% endon on tele-GPS#fil==1 do DisplayText [f0c18l4]F endon on tele-GPS#fil==0 do DisplayText [f0c18l4]N endon + +rule3 on tele-FLOG#sec do DisplayText [f0c1l4]SAV:%value% endon on tele-FLOG#rec==1 do DisplayText [f0c1l4]REC: endon on tele-FLOG#mode do DisplayText [f0c14l4]M%value% endon + +\*********************************************************************************************/ + +#define XSNS_60 60 + +#include "NTPServer.h" +#include "NTPPacket.h" + +/*********************************************************************************************\ + * constants +\*********************************************************************************************/ + +#define D_CMND_UBX "UBX" + +const char S_JSON_UBX_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_UBX "%s\":%d}"; + +const char kUBXTypes[] PROGMEM = "UBX"; + +#define UBX_LAT_LON_THRESHOLD 1000 // filter out some noise of local drift + +#define UBX_SERIAL_BUFFER_SIZE 256 +#define UBX_TCP_PORT 1234 +#define NTP_MILLIS_OFFSET 50 // estimated latency in milliseconds + +/********************************************************************************************\ +| *globals +\*********************************************************************************************/ + +const char UBLOX_INIT[] PROGMEM = { + // Disable NMEA + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x24, // GxGGA off + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x2B, // GxGLL off + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x32, // GxGSA off + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x39, // GxGSV off + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x40, // GxRMC off + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x05,0x47, // GxVTG off + + // Disable UBX + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0xDC, //NAV-PVT off + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xB9, //NAV-POSLLH off + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xC0, //NAV-STATUS off + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x92, //NAV-TIMEUTC off + + // Enable UBX + // 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x07,0x00,0x01,0x00,0x00,0x00,0x00,0x18,0xE1, //NAV-PVT on + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x13,0xBE, //NAV-POSLLH on + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x14,0xC5, //NAV-STATUS on + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x01,0x00,0x00,0x00,0x00,0x32,0x97, //NAV-TIMEUTC on + + // Rate - we will not reset it for the moment after restart + // 0xB5,0x62,0x06,0x08,0x06,0x00,0x64,0x00,0x01,0x00,0x01,0x00,0x7A,0x12, //(10Hz) + // 0xB5,0x62,0x06,0x08,0x06,0x00,0xC8,0x00,0x01,0x00,0x01,0x00,0xDE,0x6A, //(5Hz) + // 0xB5,0x62,0x06,0x08,0x06,0x00,0xE8,0x03,0x01,0x00,0x01,0x00,0x01,0x39 //(1Hz) + // 0xB5,0x62,0x06,0x08,0x06,0x00,0xD0,0x07,0x01,0x00,0x01,0x00,0xED,0xBD //(0.5Hz) +}; + +char UBX_name[4]; + +struct UBX_t { + const char UBX_HEADER[2] = { 0xB5, 0x62 }; // TODO: Check if we really save space here inside the struct + const char NAV_POSLLH_HEADER[2] = { 0x01, 0x02 }; + const char NAV_STATUS_HEADER[2] = { 0x01, 0x03 }; + const char NAV_TIME_HEADER[2] = { 0x01, 0x21 }; + + struct entry_t { + int32_t lat; //raw sensor value + int32_t lon; //raw sensor value + uint32_t time; //local time from system (maybe provided by the sensor) + }; + + union { + entry_t values; + uint8_t bytes[sizeof(entry_t)]; + } rec_buffer; + + struct POLL_MSG { + uint8_t cls; + uint8_t id; + uint16_t zero; + }; + + struct NAV_POSLLH { + uint8_t cls; + uint8_t id; + uint16_t len; + uint32_t iTOW; + int32_t lon; + int32_t lat; + int32_t alt; + int32_t hMSL; + uint32_t hAcc; + uint32_t vAcc; + }; + + struct NAV_STATUS { + uint8_t cls; + uint8_t id; + uint16_t len; + uint32_t iTOW; + uint8_t gpsFix; + uint8_t flags; //bit 0 - gpsfix valid + uint8_t fixStat; + uint8_t flags2; + uint32_t ttff; + uint32_t msss; + }; + + struct NAV_TIME_UTC { + uint8_t cls; + uint8_t id; + uint16_t len; + uint32_t iTOW; + uint32_t tAcc; + int32_t nano; // Nanoseconds of second, range -1e9 .. 1e9 (UTC) + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t min; + uint8_t sec; + struct { + uint8_t UTC:1; + uint8_t WKN:1; // week number + uint8_t TOW:1; // time of week + uint8_t padding:5; + } valid; + }; + + struct CFG_RATE { + uint8_t cls; //0x06 + uint8_t id; //0x08 + uint16_t len; // 6 bytes + uint16_t measRate; // in every ms -> 1 Hz = 1000 ms; 10 Hz = 100 ms -> x = 1000 ms / Hz + uint16_t navRate; // x measurements for 1 navigation event + uint16_t timeRef; // align to time system: 0= UTC, 1 = GPS, 2 = GLONASS, ... + char CK[2]; // checksum + }; + + struct { + uint32_t last_iTOW; + int32_t last_alt; + uint32_t last_hAcc; + uint32_t last_vAcc; + uint8_t gpsFix; + uint8_t non_empty_loops; // in case of an unintended reset of the GPS, the serial interface will get flooded with NMEA + uint16_t log_interval; // in tenth of seconds + int32_t timeOffset; // roughly computed offset millis() - iTOW + } state; + + struct { + uint32_t init:1; + uint32_t filter_noise:1; + uint32_t send_when_new:1; // no teleinterval + uint32_t send_UI_only:1; + uint32_t runningNTP:1; + // uint32_t blockedNTP:1; + uint32_t forceUTCupdate:1; + uint32_t runningVPort:1; + // TODO: more to come + } mode; + + union { + NAV_POSLLH navPosllh; + NAV_STATUS navStatus; + NAV_TIME_UTC navTime; + POLL_MSG pollMsg; + CFG_RATE cfgRate; + } Message; + + uint32_t utc_time; + + uint8_t TCPbuf[UBX_SERIAL_BUFFER_SIZE]; + size_t TCPbufSize; +} UBX; + +enum UBXMsgType { + MT_NONE, + MT_NAV_POSLLH, + MT_NAV_STATUS, + MT_NAV_TIME, + MT_POLL +}; + +#ifdef USE_FLOG +FLOG *Flog = nullptr; +#endif //USE_FLOG +TasmotaSerial *UBXSerial; + +NtpServer timeServer(PortUdp); + +WiFiServer vPortServer(UBX_TCP_PORT); +WiFiClient vPortClient; + +/*********************************************************************************************\ + * helper function +\*********************************************************************************************/ + +void UBXcalcChecksum(char* CK, size_t msgSize) +{ + memset(CK, 0, 2); + for (int i = 0; i < msgSize; i++) { + CK[0] += ((char*)(&UBX.Message))[i]; + CK[1] += CK[0]; + } +} + +bool UBXcompareMsgHeader(const char* msgHeader) +{ + char* ptr = (char*)(&UBX.Message); + return ptr[0] == msgHeader[0] && ptr[1] == msgHeader[1]; +} + +void UBXinitCFG(void) +{ + for (uint32_t i = 0; i < sizeof(UBLOX_INIT); i++) { + UBXSerial->write( pgm_read_byte(UBLOX_INIT+i) ); + } + DEBUG_SENSOR_LOG(PSTR("UBX: turn off NMEA")); +} + +void UBXsendCFGLine(uint8_t _line) +{ + if (_line>sizeof(UBLOX_INIT)/16) return; + for (uint32_t i = 0; i < 16; i++) { + UBXSerial->write( pgm_read_byte(UBLOX_INIT+i+(_line*16)) ); + } + DEBUG_SENSOR_LOG(PSTR("UBX: send line %u of UBLOX_INIT"), _line); +} + +/********************************************************************************************/ + +void UBXDetect(void) +{ + UBX.mode.init = 0; + if (PinUsed(GPIO_GPS_RX) && PinUsed(GPIO_GPS_TX)) { + UBXSerial = new TasmotaSerial(Pin(GPIO_GPS_RX), Pin(GPIO_GPS_TX), 1, 0, UBX_SERIAL_BUFFER_SIZE); // 64 byte buffer is NOT enough + if (UBXSerial->begin(9600)) { + DEBUG_SENSOR_LOG(PSTR("UBX: started serial")); + if (UBXSerial->hardwareSerial()) { + ClaimSerial(); + DEBUG_SENSOR_LOG(PSTR("UBX: claim HW")); + } + } + } + else { + return; + } + + UBXinitCFG(); // turn off NMEA, only use "our" UBX-messages + UBX.mode.init = 1; + +#ifdef USE_FLOG + if (!Flog) { + Flog = new FLOG; // init Flash Log + Flog->init(); + } +#endif // USE_FLOG + + UBX.state.log_interval = 10; // 1 second + UBX.mode.send_UI_only = true; // send UI data ... +// MqttPublishTeleperiodSensor(); // ... once at after start (No MQTT ready yet so do NOT try to send) +} + +uint32_t UBXprocessGPS() +{ + static uint32_t fpos = 0; + static char checksum[2]; + static uint8_t currentMsgType = MT_NONE; + static size_t payloadSize = sizeof(UBX.Message); + + // DEBUG_SENSOR_LOG(PSTR("UBX: check for serial data")); + uint32_t data_bytes = 0; + while ( UBXSerial->available() ) { + data_bytes++; + byte c = UBXSerial->read(); + if (UBX.mode.runningVPort){ + UBX.TCPbuf[data_bytes-1] = c; // immediately copy byte to TCP-buf + UBX.TCPbufSize = data_bytes; + } + if ( fpos < 2 ) { + // For the first two bytes we are simply looking for a match with the UBX header bytes (0xB5,0x62) + if ( c == UBX.UBX_HEADER[fpos] ) { + fpos++; + } else { + fpos = 0; // Reset to beginning state. + } + } else { + // If we come here then fpos >= 2, which means we have found a match with the UBX_HEADER + // and we are now reading in the bytes that make up the payload. + + // Place the incoming byte into the ubxMessage struct. The position is fpos-2 because + // the struct does not include the initial two-byte header (UBX_HEADER). + if ( (fpos-2) < payloadSize ) { + ((char*)(&UBX.Message))[fpos-2] = c; + } + fpos++; + + if ( fpos == 4 ) { + // We have just received the second byte of the message type header, + // so now we can check to see what kind of message it is. + if ( UBXcompareMsgHeader(UBX.NAV_POSLLH_HEADER) ) { + currentMsgType = MT_NAV_POSLLH; + payloadSize = sizeof(UBX_t::NAV_POSLLH); + DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_POSLLH")); + } + else if ( UBXcompareMsgHeader(UBX.NAV_STATUS_HEADER) ) { + currentMsgType = MT_NAV_STATUS; + payloadSize = sizeof(UBX_t::NAV_STATUS); + DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_STATUS")); + } + else if ( UBXcompareMsgHeader(UBX.NAV_TIME_HEADER) ) { + currentMsgType = MT_NAV_TIME; + payloadSize = sizeof(UBX_t::NAV_TIME_UTC); + DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_TIME_UTC")); + } + else { + // unknown message type, bail + fpos = 0; + continue; + } + } + + if ( fpos == (payloadSize+2) ) { + // All payload bytes have now been received, so we can calculate the + // expected checksum value to compare with the next two incoming bytes. + UBXcalcChecksum(checksum, payloadSize); + } + else if ( fpos == (payloadSize+3) ) { + // First byte after the payload, ie. first byte of the checksum. + // Does it match the first byte of the checksum we calculated? + if ( c != checksum[0] ) { + // Checksum doesn't match, reset to beginning state and try again. + fpos = 0; + } + } + else if ( fpos == (payloadSize+4) ) { + // Second byte after the payload, ie. second byte of the checksum. + // Does it match the second byte of the checksum we calculated? + fpos = 0; // We will reset the state regardless of whether the checksum matches. + if ( c == checksum[1] ) { + // Checksum matches, we have a valid message. + return currentMsgType; + } + } + else if ( fpos > (payloadSize+4) ) { + // We have now read more bytes than both the expected payload and checksum + // together, so something went wrong. Reset to beginning state and try again. + fpos = 0; + } + } + } + // DEBUG_SENSOR_LOG(PSTR("UBX: got none or unknown Message")); + if (data_bytes!=0) { + UBX.state.non_empty_loops++; + DEBUG_SENSOR_LOG(PSTR("UBX: got %u bytes, non-empty-loop: %u"), data_bytes, UBX.state.non_empty_loops); + } else { + UBX.state.non_empty_loops = 0; // now a hidden GPS-device reset is unlikely + } + return MT_NONE; +} + +/********************************************************************************************\ +| * callback functions for the download +\*********************************************************************************************/ + +#ifdef USE_FLOG +void UBXsendHeader(void) +{ + Webserver->setContentLength(CONTENT_LENGTH_UNKNOWN); + Webserver->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx")); + WSSend(200, CT_APP_STREAM, F( + "\r\n" + "\r\n" + "\r\n\r\n")); +} + +void UBXsendRecord(uint8_t *buf) +{ + char record[100]; + char stime[32]; + UBX_t::entry_t *entry = (UBX_t::entry_t*)buf; + snprintf_P(stime, sizeof(stime), GetDT(entry->time).c_str()); + char lat[12]; + char lon[12]; + dtostrfd((double)entry->lat/10000000.0f,7,lat); + dtostrfd((double)entry->lon/10000000.0f,7,lon); + snprintf_P(record, sizeof(record),PSTR("\n\t\n\n"),lat ,lon, stime); + // DEBUG_SENSOR_LOG(PSTR("FLOG: DL %u %u"), Flog->sector.dword_buffer[k+j],Flog->sector.dword_buffer[k+j+1]); + Webserver->sendContent_P(record); +} + +void UBXsendFooter(void) +{ + Webserver->sendContent(F("\n\n")); + Webserver->sendContent(""); + Rtc.user_time_entry = false; // we have blocked the main loop and want a new valid time +} + +/********************************************************************************************/ + +void UBXsendFile(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + Flog->startDownload(sizeof(UBX.rec_buffer),UBXsendHeader,UBXsendRecord,UBXsendFooter); +} +#endif //USE_FLOG + +/********************************************************************************************/ + +void UBXSetRate(uint16_t interval) +{ + UBX.Message.cfgRate.cls = 0x06; + UBX.Message.cfgRate.id = 0x08; + UBX.Message.cfgRate.len = 6; + uint32_t measRate = (1000*(uint32_t)interval); //seconds to milliseconds + if (measRate > 0xffff) { + measRate = 0xffff; // max. 65535 ms interval + } + UBX.Message.cfgRate.measRate = (uint16_t)measRate; + UBX.Message.cfgRate.navRate = 1; + UBX.Message.cfgRate.timeRef = 1; + UBXcalcChecksum(UBX.Message.cfgRate.CK, sizeof(UBX.Message.cfgRate)-sizeof(UBX.Message.cfgRate.CK)); + DEBUG_SENSOR_LOG(PSTR("UBX: requested interval: %u seconds measRate: %u ms"), interval, UBX.Message.cfgRate.measRate); + UBXSerial->write(UBX.UBX_HEADER[0]); + UBXSerial->write(UBX.UBX_HEADER[1]); + for (uint32_t i =0; iwrite(((uint8_t*)(&UBX.Message.cfgRate))[i]); + DEBUG_SENSOR_LOG(PSTR("UBX: cfgRate byte %u: %x"), i, ((uint8_t*)(&UBX.Message.cfgRate))[i]); + } + UBX.state.log_interval = 10*interval; +} + +void UBXSelectMode(uint16_t mode) +{ + DEBUG_SENSOR_LOG(PSTR("UBX: set mode to %u"),mode); + switch(mode){ +#ifdef USE_FLOG + case 0: + Flog->mode = 0; // write once to all available sectors, then stop + break; + case 1: + Flog->mode = 1; // write to all available sectors, then restart and overwrite the older ones + break; + case 2: + UBX.mode.filter_noise = true; // filter out horizontal drift noise, TODO: find useful values + break; + case 3: + UBX.mode.filter_noise = false; + break; + case 4: + Flog->startRecording(true); + AddLog(LOG_LEVEL_INFO, PSTR("UBX: start recording - appending")); + break; + case 5: + Flog->startRecording(false); + AddLog(LOG_LEVEL_INFO, PSTR("UBX: start recording - new log")); + break; + case 6: + if(Flog->recording == true){ + Flog->stopRecording(); + } + AddLog(LOG_LEVEL_INFO, PSTR("UBX: stop recording")); + break; +#endif //USE_FLOG + case 7: + UBX.mode.send_when_new = 1; // send mqtt on new postion + TELE -> consider to set TELE to a very high value + break; + case 8: + UBX.mode.send_when_new = 0; // only TELE + break; + case 9: + if (timeServer.beginListening()) { + UBX.mode.runningNTP = true; + } + break; + case 10: + UBX.mode.runningNTP = false; + UBXsendCFGLine(10); //NAV-POSLLH on + UBXsendCFGLine(11); //NAV-STATUS on + break; + case 11: + UBX.mode.forceUTCupdate = true; + break; + case 12: + UBX.mode.forceUTCupdate = false; + break; + case 13: + Settings->latitude = UBX.rec_buffer.values.lat/10; + Settings->longitude = UBX.rec_buffer.values.lon/10; + break; + case 14: + vPortServer.begin(); + UBX.mode.runningVPort = 1; + break; + case 15: + // vPortServer.stop(); // seems not to work reliably + UBX.mode.runningVPort = 0; + break; + default: + if (mode>1000 && mode <1066) { + UBXSetRate(mode-1000); // set interval between measurements in seconds from 1 to 65 + } + break; + } + UBX.mode.send_UI_only = true; + MqttPublishTeleperiodSensor(); +} + +/********************************************************************************************/ + +bool UBXHandlePOSLLH() +{ + DEBUG_SENSOR_LOG(PSTR("UBX: iTOW: %u"),UBX.Message.navPosllh.iTOW); + if (UBX.state.gpsFix>1) { + if (UBX.mode.filter_noise) { + if ((UBX.Message.navPosllh.lat-UBX.rec_buffer.values.lat go to pure NTP-mode + UBXsendCFGLine(7); //NAV-POSLLH off + UBXsendCFGLine(8); //NAV-STATUS off + } + return true; // new position + } else { + DEBUG_SENSOR_LOG(PSTR("UBX: no valid position data")); + } + return false; // no GPS-fix +} + +void UBXHandleSTATUS() +{ + DEBUG_SENSOR_LOG(PSTR("UBX: gpsFix: %u, valid: %u"), UBX.Message.navStatus.gpsFix, (UBX.Message.navStatus.flags)&1); + if ((UBX.Message.navStatus.flags)&1) { + UBX.state.gpsFix = UBX.Message.navStatus.gpsFix; //only store fixed status if flag is valid + } else { + UBX.state.gpsFix = 0; // without valid flag, everything is "no fix" + } +} + +void UBXHandleTIME() +{ + DEBUG_SENSOR_LOG(PSTR("UBX: UTC-Time: %u-%u-%u %u:%u:%u"), UBX.Message.navTime.year, UBX.Message.navTime.month ,UBX.Message.navTime.day,UBX.Message.navTime.hour,UBX.Message.navTime.min,UBX.Message.navTime.sec); + if (UBX.Message.navTime.valid.UTC == 1) { + UBX.state.timeOffset = millis(); // iTOW%1000 should be 0 here, when NTP-server is enabled and in "pure mode" + DEBUG_SENSOR_LOG(PSTR("UBX: UTC-Time is valid")); + bool resync = (Rtc.utc_time > UBX.utc_time); // Sync local time every hour + if (Rtc.user_time_entry == false || UBX.mode.forceUTCupdate || UBX.mode.runningNTP || resync) { + TIME_T gpsTime; + gpsTime.year = UBX.Message.navTime.year - 1970; + gpsTime.month = UBX.Message.navTime.month; + gpsTime.day_of_month = UBX.Message.navTime.day; + gpsTime.hour = UBX.Message.navTime.hour; + gpsTime.minute = UBX.Message.navTime.min; + gpsTime.second = UBX.Message.navTime.sec; + UBX.rec_buffer.values.time = MakeTime(gpsTime); + if (UBX.mode.forceUTCupdate || (Rtc.user_time_entry == false) || resync) { +// AddLog(LOG_LEVEL_INFO, PSTR("UBX: UTC-Time is valid, set system time")); + UBX.utc_time = UBX.rec_buffer.values.time + 3600; + Rtc.utc_time = UBX.rec_buffer.values.time; + RtcSync("UBX"); + } + Rtc.user_time_entry = true; + } + } +} + +void UBXHandleOther(void) +{ + if (UBX.state.non_empty_loops>6) { // we expect only 4-5 non-empty loops in a row, could change with other sensor speed (Hz) + if(UBX.mode.runningVPort) return; + UBXinitCFG(); // this should only happen with lots of NMEA-messages, but it is only a guess!! + AddLog(LOG_LEVEL_ERROR, PSTR("UBX: possible device-reset, will re-init")); + UBXSerial->flush(); + UBX.state.non_empty_loops = 0; + } +} + +/********************************************************************************************/ + +void UBXLoop50msec(void) +{ + // handle virtual serial port + if (UBX.mode.runningVPort){ + if(!vPortClient.connected()) { + vPortClient = vPortServer.available(); + } + while(vPortClient.available()) { + byte _newByte = vPortClient.read(); + UBXSerial->write(_newByte); + } + + if (UBX.TCPbufSize!=0){ + vPortClient.write((char*)UBX.TCPbuf, UBX.TCPbufSize); + UBX.TCPbufSize = 0; + } + } + // handle NTP-server + if(UBX.mode.runningNTP){ + timeServer.processOneRequest(UBX.rec_buffer.values.time, UBX.state.timeOffset - NTP_MILLIS_OFFSET); + } +} + +void UBXLoop(void) +{ + static uint16_t counter; //count up every 100 msec + static bool new_position; + + uint32_t msgType = UBXprocessGPS(); + + switch(msgType){ + case MT_NAV_POSLLH: + new_position = UBXHandlePOSLLH(); + break; + case MT_NAV_STATUS: + UBXHandleSTATUS(); + break; + case MT_NAV_TIME: + UBXHandleTIME(); + break; + default: + UBXHandleOther(); + break; + } + +#ifdef USE_FLOG + if (counter>UBX.state.log_interval) { + if (Flog->recording && new_position) { + UBX.rec_buffer.values.time = Rtc.local_time; + Flog->addToBuffer(UBX.rec_buffer.bytes, sizeof(UBX.rec_buffer.bytes)); + counter = 0; + } + } +#endif // USE_FLOG + + counter++; +} + +/********************************************************************************************/ +// normaly in i18n.h + +#ifdef USE_WEBSERVER + // {s} = + +#ifdef USE_FLOG +#ifdef DEBUG_TASMOTA_SENSOR + const char HTTP_SNS_FLOGVER[] PROGMEM = "{s}
{m}
{e}{s} FLOG with %u sectors: {m}%u bytes{e}" + "{s} FLOG next sector for REC: {m} %u {e}" + "{s} %u sector(s) with data at sector: {m} %u {e}"; + const char HTTP_SNS_FLOGREC[] PROGMEM = "{s} RECORDING (bytes in buffer) {m}%u{e}"; +#endif // DEBUG_TASMOTA_SENSOR + + const char HTTP_SNS_FLOG[] PROGMEM = "{s}
{m}
{e}{s} Flash-Log {m} %s{e}"; + const char kFLOG_STATE0[] PROGMEM = "ready"; + const char kFLOG_STATE1[] PROGMEM = "recording"; + const char * kFLOG_STATE[] ={kFLOG_STATE0, kFLOG_STATE1}; + + const char HTTP_BTN_FLOG_DL[] PROGMEM = ""; + +#endif //USE_FLOG + const char HTTP_SNS_NTPSERVER[] PROGMEM = "{s} NTP server {m}active{e}"; + + const char HTTP_SNS_GPS[] PROGMEM = "{s} GPS latitude {m}%s{e}" + "{s} GPS longitude {m}%s{e}" + "{s} GPS altitude {m}%s m{e}" + "{s} GPS hor. Accuracy {m}%s m{e}" + "{s} GPS vert. Accuracy {m}%s m{e}" + "{s} GPS sat-fix status {m}%s{e}"; + + const char kGPSFix0[] PROGMEM = "no fix"; + const char kGPSFix1[] PROGMEM = "dead reckoning only"; + const char kGPSFix2[] PROGMEM = "2D-fix"; + const char kGPSFix3[] PROGMEM = "3D-fix"; + const char kGPSFix4[] PROGMEM = "GPS + dead reckoning combined"; + const char kGPSFix5[] PROGMEM = "Time only fix"; + const char * kGPSFix[] PROGMEM ={kGPSFix0, kGPSFix1, kGPSFix2, kGPSFix3, kGPSFix4, kGPSFix5}; + +// const char UBX_GOOGLE_MAPS[] =""; + + +#endif // USE_WEBSERVER + +/********************************************************************************************/ + +void UBXShow(bool json) +{ + char lat[12]; + char lon[12]; + char alt[12]; + char hAcc[12]; + char vAcc[12]; + dtostrfd((double)UBX.rec_buffer.values.lat/10000000.0f,7,lat); + dtostrfd((double)UBX.rec_buffer.values.lon/10000000.0f,7,lon); + dtostrfd((double)UBX.state.last_alt/1000.0f,3,alt); + dtostrfd((double)UBX.state.last_vAcc/1000.0f,3,hAcc); + dtostrfd((double)UBX.state.last_hAcc/1000.0f,3,vAcc); + + if (json) { + ResponseAppend_P(PSTR(",\"GPS\":{")); + if (UBX.mode.send_UI_only) { + uint32_t i = UBX.state.log_interval / 10; + ResponseAppend_P(PSTR("\"fil\":%u,\"int\":%u}"), UBX.mode.filter_noise, i); + } else { + ResponseAppend_P(PSTR("\"lat\":%s,\"lon\":%s,\"alt\":%s,\"hAcc\":%s,\"vAcc\":%s}"), lat, lon, alt, hAcc, vAcc); + } +#ifdef USE_FLOG + ResponseAppend_P(PSTR(",\"FLOG\":{\"rec\":%u,\"mode\":%u,\"sec\":%u}"), Flog->recording, Flog->mode, Flog->sectors_left); +#endif //USE_FLOG + UBX.mode.send_UI_only = false; +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_GPS, lat, lon, alt, hAcc, vAcc, kGPSFix[UBX.state.gpsFix]); + //WSContentSend_P(UBX_GOOGLE_MAPS, lat, lon); +#ifdef DEBUG_TASMOTA_SENSOR +#ifdef USE_FLOG + WSContentSend_PD(HTTP_SNS_FLOGVER, Flog->num_sectors, Flog->size, Flog->current_sector, Flog->sectors_left, Flog->sector.header.physical_start_sector); + if (Flog->recording) { + WSContentSend_PD(HTTP_SNS_FLOGREC, Flog->sector.header.buf_pointer - 8); + } +#endif //USE_FLOG +#endif // DEBUG_TASMOTA_SENSOR +#ifdef USE_FLOG + if (Flog->ready) { + WSContentSend_P(HTTP_SNS_FLOG,kFLOG_STATE[Flog->recording]); + } + if (!Flog->recording && Flog->found_saved_data) { + WSContentSend_P(HTTP_BTN_FLOG_DL); + } +#endif //USE_FLOG + if (UBX.mode.runningNTP) { + WSContentSend_P(HTTP_SNS_NTPSERVER); + } +#endif // USE_WEBSERVER + } +} + +/*********************************************************************************************\ + * check the UBX commands +\*********************************************************************************************/ + +bool UBXCmd(void) +{ + bool serviced = true; + if (XdrvMailbox.data_len > 0) { + UBXSelectMode(XdrvMailbox.payload); + Response_P(S_JSON_UBX_COMMAND_NVALUE, XdrvMailbox.command, XdrvMailbox.payload); + } + return serviced; +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xsns60(uint8_t function) +{ + bool result = false; + + if (FUNC_INIT == function) { + UBXDetect(); + } + + if (UBX.mode.init) { + switch (function) { + case FUNC_COMMAND_SENSOR: + if (XSNS_60 == XdrvMailbox.index) { + result = UBXCmd(); + } + break; + case FUNC_EVERY_50_MSECOND: + UBXLoop50msec(); // handles virtual serial port and NTP server + break; + case FUNC_EVERY_100_MSECOND: +#ifdef USE_FLOG + if (!Flog->running_download) +#endif //USE_FLOG + { + UBXLoop(); + } + break; +#ifdef USE_FLOG + case FUNC_WEB_ADD_HANDLER: + WebServer_on(PSTR("/UBX"), UBXsendFile); + break; +#endif //USE_FLOG + case FUNC_JSON_APPEND: + UBXShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: +#ifdef USE_FLOG + if (!Flog->running_download) +#endif //USE_FLOG + { + UBXShow(0); + } + break; +#endif // USE_WEBSERVER + } + } + return result; +} + #endif // USE_GPS \ No newline at end of file diff --git a/tasmota/xsns_61_MI_NRF24.ino b/tasmota/tasmota_xsns_sensor/xsns_61_MI_NRF24.ino similarity index 100% rename from tasmota/xsns_61_MI_NRF24.ino rename to tasmota/tasmota_xsns_sensor/xsns_61_MI_NRF24.ino diff --git a/tasmota/xsns_62_MI_HM10.ino b/tasmota/tasmota_xsns_sensor/xsns_62_MI_HM10.ino similarity index 100% rename from tasmota/xsns_62_MI_HM10.ino rename to tasmota/tasmota_xsns_sensor/xsns_62_MI_HM10.ino diff --git a/tasmota/xsns_62_esp32_mi.ino b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino similarity index 97% rename from tasmota/xsns_62_esp32_mi.ino rename to tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino index cf67afb92..82bd6b24b 100644 --- a/tasmota/xsns_62_esp32_mi.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino @@ -24,15 +24,15 @@ -------------------------------------------------------------------------------------------- 0.9.5.5 20220326 changed - refactored connection task for asynchronous op, add response option, fixed MI32Key command - ------- + ------- 0.9.5.4 20220325 changed - add Berry adv_watch and adv_block to BLE class - ------- + ------- 0.9.5.3 20220315 changed - reworked Berry part, active scanning and holding active connections possible, new format of advertisement buffer - ------- + ------- 0.9.5.1 20220209 changed - rename YEERC to YLYK01, add dimmer YLKG08 (incl. YLKG07), change button report scheme ------- 0.9.5.0 20211016 changed - major rewrite, added mi32cfg (file and command), Homekit-Bridge, - extended GUI, + extended GUI, removed BLOCK, PERIOD, TIME, UNIT, BATTERY and PAGE -> replaced via Berry-Support ------- 0.9.1.7 20201116 changed - small bugfixes, add BLOCK and OPTION command, send BLE scan via MQTT @@ -63,8 +63,11 @@ #include -#include "xsns_62_esp32_mi.h" +#include "include/xsns_62_esp32_mi.h" +#if USE_MI_HOMEKIT==0 + #undef USE_MI_HOMEKIT +#endif #ifdef USE_MI_HOMEKIT extern "C" void mi_homekit_main(void); extern "C" void mi_homekit_update_value(void* handle, float value, uint32_t type); @@ -81,7 +84,6 @@ std::vector MIBLEsensors; static BLEScan* MI32Scan; - /*********************************************************************************************\ * Classes \*********************************************************************************************/ @@ -141,7 +143,7 @@ class MI32AdvCallbacks: public NimBLEAdvertisedDeviceCallbacks { _mutex = false; return; } - + uint16_t UUID = advertisedDevice->getServiceDataUUID(0).getNative()->u16.value; ServiceDataLength = advertisedDevice->getServiceData(0).length(); @@ -518,7 +520,7 @@ void MI32StatusInfo() { #ifdef USE_MI_EXT_GUI /** * @brief Saves a sensor value mapped to the graph range of 0-20 pixel, this function automatically reads the actual hour from system time - * + * * @param history - pointer to uint8_t[23] * @param value - value as float, this * @param type - internal type. for BLE: 0 - temperature, 1 - humidity, 2 - illuminance, for internal sensors: 100 - wattage @@ -551,7 +553,7 @@ void MI32addHistory(uint8_t *history, float value, uint32_t type){ /** * @brief Returns a value betwenn 0-21 for use as a data point in the history graph of the extended web UI - * + * * @param history - pointer to uint8_t[23] * @param hour - hour of datapoint * @return uint8_t - value for the y-axis, should be between 0-21 @@ -567,7 +569,7 @@ uint8_t MI32fetchHistory(uint8_t *history, uint32_t hour){ /** * @brief Invalidates the history data of the following hour by setting MSB to 0, should be called at FUNC_JSON_APPEND - * + * */ void Mi32invalidateOldHistory(){ uint32_t _hour = (LocalTime()%SECS_PER_DAY)/SECS_PER_HOUR; @@ -635,12 +637,14 @@ void MI32Init(void) { MI32getSetupCodeFromMAC(MI32.hk_setup_code); AddLog(LOG_LEVEL_INFO,PSTR("M32: Init HAP core")); mi_homekit_main(); - #else + #else MI32.mode.didStartHAP = 1; #endif //USE_MI_HOMEKIT } - + if (!MI32.mode.init) { + NimBLEDevice::setScanFilterMode(CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE); + NimBLEDevice::setScanDuplicateCacheSize(40); // will not be perfect for every situation (few vs many BLE devices nearby) NimBLEDevice::init(""); AddLog(LOG_LEVEL_INFO,PSTR("M32: Init BLE device")); MI32.mode.init = 1; @@ -819,8 +823,8 @@ extern "C" { /** * @brief Get at least a bit of the status of the HAP core, i.e. to reduce the activy of the driver while doing the pairing - * - * @param event + * + * @param event */ void MI32passHapEvent(uint32_t event){ switch(event){ @@ -851,7 +855,7 @@ extern "C" { /** * @brief Simply store the writeable HAP characteristics as void pointers in the "main" driver for updates of the values - * + * * @param slot - sensor slot in MIBLEsensors * @param type - sensors type, except for the buttons this is equal to the mibeacon types * @param handle - a void ponter to a characteristic @@ -896,7 +900,7 @@ extern "C" { * Example: AABBCC1234f2 * -> 111-11-234 * This is no security feature, only for convenience - * * @param setupcode + * * @param setupcode */ void MI32getSetupCodeFromMAC(char *setupcode){ uint8_t _mac[6]; @@ -1031,13 +1035,11 @@ void MI32StartTask(uint32_t task){ switch(task){ case MI32_TASK_SCAN: if (MI32.mode.connected == 1) return; - if(MI32.option.activeScan){ - AddLog(LOG_LEVEL_INFO,PSTR("M32: Scan mode: active!")); // may have negative side effects!! - } MI32StartScanTask(); break; case MI32_TASK_CONN: if (MI32.mode.canConnect == 0) return; + MI32.mode.deleteScanTask = 1; MI32StartConnectionTask(); break; default: @@ -1063,25 +1065,37 @@ void MI32ScanTask(void *pvParameters){ if(MI32.mode.didGetConfig){ vTaskDelay(5000/ portTICK_PERIOD_MS); } - if (MI32Scan == nullptr) MI32Scan = NimBLEDevice::getScan(); - MI32Scan->setInterval(70); - MI32Scan->setWindow(50); - MI32Scan->setAdvertisedDeviceCallbacks(&MI32ScanCallbacks,true); + MI32Scan = NimBLEDevice::getScan(); + + MI32Scan->setAdvertisedDeviceCallbacks(&MI32ScanCallbacks,false); if(NimBLEDevice::getWhiteListCount()>0){ - MI32Scan->setFilterPolicy(BLE_HCI_SCAN_FILT_USE_WL); + MI32Scan->setFilterPolicy(BLE_HCI_SCAN_FILT_USE_WL); } else { MI32Scan->setFilterPolicy(BLE_HCI_SCAN_FILT_NO_WL); } - MI32Scan->setActiveScan(MI32.option.activeScan); + + MI32Scan->setActiveScan(MI32.option.activeScan == 1); MI32Scan->setMaxResults(0); MI32Scan->start(0, MI32scanEndedCB, false); // never stop scanning, will pause automatically while connecting - MI32.infoMsg = MI32_START_SCANNING; - + MI32.infoMsg = MI32.option.activeScan?MI32_START_SCANNING_ACTIVE:MI32_START_SCANNING_PASSIVE; + uint32_t timer = 0; for(;;){ - vTaskDelay(10000/ portTICK_PERIOD_MS); + vTaskDelay(1000/ portTICK_PERIOD_MS); + if(MI32.mode.deleteScanTask){ + MI32Scan->stop(); + MI32.mode.runningScan = 0; + break; + } + if(MI32.mode.updateScan){ + MI32Scan->stop(); + MI32Scan->setActiveScan(MI32.option.activeScan == 1); + MI32Scan->start(0,true); + MI32.mode.updateScan = 0; + MI32.infoMsg = MI32.option.activeScan?MI32_START_SCANNING_ACTIVE:MI32_START_SCANNING_PASSIVE; + } } vTaskDelete( NULL ); } @@ -1143,8 +1157,8 @@ bool MI32StartConnectionTask(){ void MI32ConnectionTask(void *pvParameters){ #if !defined(CONFIG_IDF_TARGET_ESP32C3) //needs more testing ... - NimBLEDevice::setOwnAddrType(BLE_OWN_ADDR_RANDOM,false); //seems to be important for i.e. xbox controller, hopefully not breaking other things - NimBLEDevice::setSecurityAuth(true, true, true); + // NimBLEDevice::setOwnAddrType(BLE_OWN_ADDR_RANDOM,false); //seems to be important for i.e. xbox controller, hopefully not breaking other things + // NimBLEDevice::setSecurityAuth(true, true, true); #endif //CONFIG_IDF_TARGET_ESP32C3 MI32.conCtx->error = MI32_CONN_NO_ERROR; if (MI32ConnectActiveSensor()){ @@ -1213,7 +1227,7 @@ void MI32ConnectionTask(void *pvParameters){ // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: write op done")); } else{ - MI32.conCtx->error = MI32_CONN_DID_NOT_WRITE; + MI32.conCtx->error = MI32_CONN_DID_NOT_WRITE; } } else{ @@ -1341,7 +1355,7 @@ if(decryptRet!=0){ if((void**)MIBLEsensors[_slot].button_hap_service[0] != nullptr){ mi_homekit_update_value(MIBLEsensors[_slot].button_hap_service[0], (float)2.0f, 0x01); // only one button, long press = 2 } -#endif //USE_MI_HOMEKIT +#endif //USE_MI_HOMEKIT break; } // single, double, long @@ -1650,10 +1664,10 @@ void MI32Every50mSecond(){ else if(MI32.beAdvBuf[_index+1] == 0xff){ _manu = _index + 2; } - _index += MI32.beAdvBuf[_index] + 1; + _index += MI32.beAdvBuf[_index] + 1; } // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: svc:%u , manu:%u"),_svc,_manu); - void (*func_ptr)(int,int) = (void (*)(int,int))MI32.beAdvCB; + void (*func_ptr)(int,int) = (void (*)(int,int))MI32.beAdvCB; func_ptr(_svc,_manu); } MI32.mode.triggerBerryAdvCB = 0; @@ -1742,25 +1756,55 @@ void CmndMi32Option(void){ bool onOff = atoi(XdrvMailbox.data); switch(XdrvMailbox.index) { case 0: - MI32.option.allwaysAggregate = onOff; + if(XdrvMailbox.data_len>0){ + MI32.option.allwaysAggregate = onOff; + } + else{ + onOff = MI32.option.allwaysAggregate; + } break; case 1: - MI32.option.noSummary = onOff; + if(XdrvMailbox.data_len>0){ + MI32.option.noSummary = onOff; + } + else{ + onOff = MI32.option.noSummary; + } break; case 2: - MI32.option.directBridgeMode = onOff; + if(XdrvMailbox.data_len>0){ + MI32.option.directBridgeMode = onOff; + } + else{ + onOff = MI32.option.directBridgeMode; + } break; case 3: - MI32.mode.didGetConfig = onOff; + if(XdrvMailbox.data_len>0){ + MI32.mode.didGetConfig = onOff; + } + else{ + onOff = MI32.mode.didGetConfig; + } break; case 4: - if(MI32.option.activeScan != onOff){ - MI32.option.activeScan = onOff; - MI32StartTask(MI32_TASK_SCAN); + if(XdrvMailbox.data_len>0){ + if(MI32.option.activeScan != onOff){ + MI32.option.activeScan = onOff; + if(MI32.mode.runningScan){ + MI32.mode.updateScan = 1; + } + else{ + MI32StartTask(MI32_TASK_SCAN); + } + } + } + else{ + onOff = MI32.option.activeScan; } break; } - ResponseCmndDone(); + ResponseCmndIdxNumber(onOff?1:0); } /*********************************************************************************************\ @@ -2301,9 +2345,9 @@ int ExtStopBLE(){ if(Settings->flag5.mi32_enable == 0) return 0; if (MI32.ScanTask != nullptr){ MI32Scan->stop(); - vTaskDelete(MI32.ScanTask); + MI32.mode.deleteScanTask = 1; AddLog(LOG_LEVEL_INFO,PSTR("M32: stop BLE")); - } + } #ifdef USE_MI_HOMEKIT if(MI32.mode.didStartHAP) { AddLog(LOG_LEVEL_INFO,PSTR("M32: stop Homebridge")); diff --git a/tasmota/xsns_62_esp32_mi_ble.ino b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino similarity index 100% rename from tasmota/xsns_62_esp32_mi_ble.ino rename to tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino diff --git a/tasmota/xsns_62_esp32_mi_homekit.c b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_homekit.c similarity index 100% rename from tasmota/xsns_62_esp32_mi_homekit.c rename to tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_homekit.c diff --git a/tasmota/xsns_63_aht1x.ino b/tasmota/tasmota_xsns_sensor/xsns_63_aht1x.ino similarity index 100% rename from tasmota/xsns_63_aht1x.ino rename to tasmota/tasmota_xsns_sensor/xsns_63_aht1x.ino diff --git a/tasmota/xsns_64_hrxl.ino b/tasmota/tasmota_xsns_sensor/xsns_64_hrxl.ino similarity index 100% rename from tasmota/xsns_64_hrxl.ino rename to tasmota/tasmota_xsns_sensor/xsns_64_hrxl.ino diff --git a/tasmota/xsns_65_hdc1080.ino b/tasmota/tasmota_xsns_sensor/xsns_65_hdc1080.ino similarity index 100% rename from tasmota/xsns_65_hdc1080.ino rename to tasmota/tasmota_xsns_sensor/xsns_65_hdc1080.ino diff --git a/tasmota/xsns_66_iAQ.ino b/tasmota/tasmota_xsns_sensor/xsns_66_iAQ.ino similarity index 100% rename from tasmota/xsns_66_iAQ.ino rename to tasmota/tasmota_xsns_sensor/xsns_66_iAQ.ino diff --git a/tasmota/xsns_67_as3935.ino b/tasmota/tasmota_xsns_sensor/xsns_67_as3935.ino similarity index 100% rename from tasmota/xsns_67_as3935.ino rename to tasmota/tasmota_xsns_sensor/xsns_67_as3935.ino diff --git a/tasmota/xsns_68_windmeter.ino b/tasmota/tasmota_xsns_sensor/xsns_68_windmeter.ino similarity index 100% rename from tasmota/xsns_68_windmeter.ino rename to tasmota/tasmota_xsns_sensor/xsns_68_windmeter.ino diff --git a/tasmota/xsns_69_opentherm.ino b/tasmota/tasmota_xsns_sensor/xsns_69_opentherm.ino similarity index 100% rename from tasmota/xsns_69_opentherm.ino rename to tasmota/tasmota_xsns_sensor/xsns_69_opentherm.ino diff --git a/tasmota/xsns_69_opentherm_protocol.ino b/tasmota/tasmota_xsns_sensor/xsns_69_opentherm_protocol.ino similarity index 100% rename from tasmota/xsns_69_opentherm_protocol.ino rename to tasmota/tasmota_xsns_sensor/xsns_69_opentherm_protocol.ino diff --git a/tasmota/xsns_70_veml6075.ino b/tasmota/tasmota_xsns_sensor/xsns_70_veml6075.ino similarity index 100% rename from tasmota/xsns_70_veml6075.ino rename to tasmota/tasmota_xsns_sensor/xsns_70_veml6075.ino diff --git a/tasmota/xsns_71_veml7700.ino b/tasmota/tasmota_xsns_sensor/xsns_71_veml7700.ino similarity index 100% rename from tasmota/xsns_71_veml7700.ino rename to tasmota/tasmota_xsns_sensor/xsns_71_veml7700.ino diff --git a/tasmota/xsns_72_mcp9808.ino b/tasmota/tasmota_xsns_sensor/xsns_72_mcp9808.ino similarity index 100% rename from tasmota/xsns_72_mcp9808.ino rename to tasmota/tasmota_xsns_sensor/xsns_72_mcp9808.ino diff --git a/tasmota/xsns_73_hp303b.ino b/tasmota/tasmota_xsns_sensor/xsns_73_hp303b.ino similarity index 100% rename from tasmota/xsns_73_hp303b.ino rename to tasmota/tasmota_xsns_sensor/xsns_73_hp303b.ino diff --git a/tasmota/xsns_74_lmt01.ino b/tasmota/tasmota_xsns_sensor/xsns_74_lmt01.ino similarity index 100% rename from tasmota/xsns_74_lmt01.ino rename to tasmota/tasmota_xsns_sensor/xsns_74_lmt01.ino diff --git a/tasmota/xsns_75_prometheus.ino b/tasmota/tasmota_xsns_sensor/xsns_75_prometheus.ino similarity index 100% rename from tasmota/xsns_75_prometheus.ino rename to tasmota/tasmota_xsns_sensor/xsns_75_prometheus.ino diff --git a/tasmota/xsns_76_dyp.ino b/tasmota/tasmota_xsns_sensor/xsns_76_dyp.ino similarity index 100% rename from tasmota/xsns_76_dyp.ino rename to tasmota/tasmota_xsns_sensor/xsns_76_dyp.ino diff --git a/tasmota/xsns_77_vl53l1x.ino b/tasmota/tasmota_xsns_sensor/xsns_77_vl53l1x.ino similarity index 100% rename from tasmota/xsns_77_vl53l1x.ino rename to tasmota/tasmota_xsns_sensor/xsns_77_vl53l1x.ino diff --git a/tasmota/xsns_78_ezo.ino b/tasmota/tasmota_xsns_sensor/xsns_78_ezo.ino similarity index 100% rename from tasmota/xsns_78_ezo.ino rename to tasmota/tasmota_xsns_sensor/xsns_78_ezo.ino diff --git a/tasmota/xsns_78_ezoco2.ino b/tasmota/tasmota_xsns_sensor/xsns_78_ezoco2.ino similarity index 100% rename from tasmota/xsns_78_ezoco2.ino rename to tasmota/tasmota_xsns_sensor/xsns_78_ezoco2.ino diff --git a/tasmota/xsns_78_ezodo.ino b/tasmota/tasmota_xsns_sensor/xsns_78_ezodo.ino similarity index 100% rename from tasmota/xsns_78_ezodo.ino rename to tasmota/tasmota_xsns_sensor/xsns_78_ezodo.ino diff --git a/tasmota/xsns_78_ezoec.ino b/tasmota/tasmota_xsns_sensor/xsns_78_ezoec.ino similarity index 100% rename from tasmota/xsns_78_ezoec.ino rename to tasmota/tasmota_xsns_sensor/xsns_78_ezoec.ino diff --git a/tasmota/xsns_78_ezoflo.ino b/tasmota/tasmota_xsns_sensor/xsns_78_ezoflo.ino similarity index 100% rename from tasmota/xsns_78_ezoflo.ino rename to tasmota/tasmota_xsns_sensor/xsns_78_ezoflo.ino diff --git a/tasmota/xsns_78_ezohum.ino b/tasmota/tasmota_xsns_sensor/xsns_78_ezohum.ino similarity index 100% rename from tasmota/xsns_78_ezohum.ino rename to tasmota/tasmota_xsns_sensor/xsns_78_ezohum.ino diff --git a/tasmota/xsns_78_ezoo2.ino b/tasmota/tasmota_xsns_sensor/xsns_78_ezoo2.ino similarity index 100% rename from tasmota/xsns_78_ezoo2.ino rename to tasmota/tasmota_xsns_sensor/xsns_78_ezoo2.ino diff --git a/tasmota/xsns_78_ezoorp.ino b/tasmota/tasmota_xsns_sensor/xsns_78_ezoorp.ino similarity index 100% rename from tasmota/xsns_78_ezoorp.ino rename to tasmota/tasmota_xsns_sensor/xsns_78_ezoorp.ino diff --git a/tasmota/xsns_78_ezoph.ino b/tasmota/tasmota_xsns_sensor/xsns_78_ezoph.ino similarity index 100% rename from tasmota/xsns_78_ezoph.ino rename to tasmota/tasmota_xsns_sensor/xsns_78_ezoph.ino diff --git a/tasmota/xsns_78_ezopmp.ino b/tasmota/tasmota_xsns_sensor/xsns_78_ezopmp.ino similarity index 100% rename from tasmota/xsns_78_ezopmp.ino rename to tasmota/tasmota_xsns_sensor/xsns_78_ezopmp.ino diff --git a/tasmota/xsns_78_ezoprs.ino b/tasmota/tasmota_xsns_sensor/xsns_78_ezoprs.ino similarity index 100% rename from tasmota/xsns_78_ezoprs.ino rename to tasmota/tasmota_xsns_sensor/xsns_78_ezoprs.ino diff --git a/tasmota/xsns_78_ezorgb.ino b/tasmota/tasmota_xsns_sensor/xsns_78_ezorgb.ino similarity index 100% rename from tasmota/xsns_78_ezorgb.ino rename to tasmota/tasmota_xsns_sensor/xsns_78_ezorgb.ino diff --git a/tasmota/xsns_78_ezortd.ino b/tasmota/tasmota_xsns_sensor/xsns_78_ezortd.ino similarity index 100% rename from tasmota/xsns_78_ezortd.ino rename to tasmota/tasmota_xsns_sensor/xsns_78_ezortd.ino diff --git a/tasmota/xsns_78_xezo.ino b/tasmota/tasmota_xsns_sensor/xsns_78_xezo.ino similarity index 100% rename from tasmota/xsns_78_xezo.ino rename to tasmota/tasmota_xsns_sensor/xsns_78_xezo.ino diff --git a/tasmota/xsns_79_as608.ino b/tasmota/tasmota_xsns_sensor/xsns_79_as608.ino similarity index 100% rename from tasmota/xsns_79_as608.ino rename to tasmota/tasmota_xsns_sensor/xsns_79_as608.ino diff --git a/tasmota/xsns_80_mfrc522.ino b/tasmota/tasmota_xsns_sensor/xsns_80_mfrc522.ino similarity index 100% rename from tasmota/xsns_80_mfrc522.ino rename to tasmota/tasmota_xsns_sensor/xsns_80_mfrc522.ino diff --git a/tasmota/xsns_81_seesaw_soil.ino b/tasmota/tasmota_xsns_sensor/xsns_81_seesaw_soil.ino similarity index 100% rename from tasmota/xsns_81_seesaw_soil.ino rename to tasmota/tasmota_xsns_sensor/xsns_81_seesaw_soil.ino diff --git a/tasmota/xsns_82_wiegand.ino b/tasmota/tasmota_xsns_sensor/xsns_82_wiegand.ino similarity index 100% rename from tasmota/xsns_82_wiegand.ino rename to tasmota/tasmota_xsns_sensor/xsns_82_wiegand.ino diff --git a/tasmota/xsns_83_neopool.ino b/tasmota/tasmota_xsns_sensor/xsns_83_neopool.ino similarity index 100% rename from tasmota/xsns_83_neopool.ino rename to tasmota/tasmota_xsns_sensor/xsns_83_neopool.ino diff --git a/tasmota/xsns_84_tof10120.ino b/tasmota/tasmota_xsns_sensor/xsns_84_tof10120.ino similarity index 100% rename from tasmota/xsns_84_tof10120.ino rename to tasmota/tasmota_xsns_sensor/xsns_84_tof10120.ino diff --git a/tasmota/xsns_85_mpu6886.ino b/tasmota/tasmota_xsns_sensor/xsns_85_mpu6886.ino similarity index 100% rename from tasmota/xsns_85_mpu6886.ino rename to tasmota/tasmota_xsns_sensor/xsns_85_mpu6886.ino diff --git a/tasmota/xsns_86_tfminiplus.ino b/tasmota/tasmota_xsns_sensor/xsns_86_tfminiplus.ino similarity index 100% rename from tasmota/xsns_86_tfminiplus.ino rename to tasmota/tasmota_xsns_sensor/xsns_86_tfminiplus.ino diff --git a/tasmota/xsns_87_mcp2515.ino b/tasmota/tasmota_xsns_sensor/xsns_87_mcp2515.ino similarity index 100% rename from tasmota/xsns_87_mcp2515.ino rename to tasmota/tasmota_xsns_sensor/xsns_87_mcp2515.ino diff --git a/tasmota/xsns_88_am2320.ino b/tasmota/tasmota_xsns_sensor/xsns_88_am2320.ino similarity index 100% rename from tasmota/xsns_88_am2320.ino rename to tasmota/tasmota_xsns_sensor/xsns_88_am2320.ino diff --git a/tasmota/xsns_89_t67xx.ino b/tasmota/tasmota_xsns_sensor/xsns_89_t67xx.ino similarity index 100% rename from tasmota/xsns_89_t67xx.ino rename to tasmota/tasmota_xsns_sensor/xsns_89_t67xx.ino diff --git a/tasmota/xsns_90_hrg15.ino b/tasmota/tasmota_xsns_sensor/xsns_90_hrg15.ino similarity index 100% rename from tasmota/xsns_90_hrg15.ino rename to tasmota/tasmota_xsns_sensor/xsns_90_hrg15.ino diff --git a/tasmota/xsns_91_vindriktning.ino b/tasmota/tasmota_xsns_sensor/xsns_91_vindriktning.ino similarity index 100% rename from tasmota/xsns_91_vindriktning.ino rename to tasmota/tasmota_xsns_sensor/xsns_91_vindriktning.ino diff --git a/tasmota/xsns_92_scd40.ino b/tasmota/tasmota_xsns_sensor/xsns_92_scd40.ino similarity index 100% rename from tasmota/xsns_92_scd40.ino rename to tasmota/tasmota_xsns_sensor/xsns_92_scd40.ino diff --git a/tasmota/xsns_93_hm330x.ino b/tasmota/tasmota_xsns_sensor/xsns_93_hm330x.ino similarity index 100% rename from tasmota/xsns_93_hm330x.ino rename to tasmota/tasmota_xsns_sensor/xsns_93_hm330x.ino diff --git a/tasmota/xsns_94_hdc2010.ino b/tasmota/tasmota_xsns_sensor/xsns_94_hdc2010.ino old mode 100755 new mode 100644 similarity index 100% rename from tasmota/xsns_94_hdc2010.ino rename to tasmota/tasmota_xsns_sensor/xsns_94_hdc2010.ino diff --git a/tasmota/xsns_95_cm110x.ino b/tasmota/tasmota_xsns_sensor/xsns_95_cm110x.ino similarity index 100% rename from tasmota/xsns_95_cm110x.ino rename to tasmota/tasmota_xsns_sensor/xsns_95_cm110x.ino diff --git a/tasmota/xsns_96_flowratemeter.ino b/tasmota/tasmota_xsns_sensor/xsns_96_flowratemeter.ino similarity index 100% rename from tasmota/xsns_96_flowratemeter.ino rename to tasmota/tasmota_xsns_sensor/xsns_96_flowratemeter.ino diff --git a/tasmota/tasmota_xsns_sensor/xsns_97_hyt.ino b/tasmota/tasmota_xsns_sensor/xsns_97_hyt.ino new file mode 100644 index 000000000..c8b84320e --- /dev/null +++ b/tasmota/tasmota_xsns_sensor/xsns_97_hyt.ino @@ -0,0 +1,128 @@ +/* + xsns_97_hyt.ino - HYT I2C temperature and humidity sensor support for Tasmota + + Copyright (C) 2020 Thomas Schnittcher + Copyright (C) 2022 Adjan Kretz, fix compatibility issues with current HYT + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#ifdef USE_I2C +#ifdef USE_HYT +/*********************************************************************************************\ + * HYT221, HYT271, HYT371 and HYT939 Temperature and Humidity + * https://www.ist-ag.com/en/products-services/humidity-modules-sensors + * + * I2C Address: 0x28 +\*********************************************************************************************/ + +#define XSNS_97 97 +#define XI2C_68 68 // See I2CDEVICES.md + +#define HYT_ADDR 0x28 // I2C address of HYT 221, 271, 371 etc. + +struct HYT { + float humidity = NAN; + float temperature = NAN; + uint8_t valid = 0; + uint8_t count = 0; + char name[6] = "HYT"; +} HYT; + +bool HYT_Read(void) { + if (HYT.valid) { HYT.valid--; } + + Wire.beginTransmission(HYT_ADDR); + Wire.requestFrom(HYT_ADDR, 4); + if (Wire.available() == 4) { + uint8_t data1 = Wire.read(); + uint8_t data2 = Wire.read(); + uint8_t data3 = Wire.read(); + uint8_t data4 = Wire.read(); + Wire.endTransmission(); + + // Convert the data to 14-bits + float humidity = ((((data1 & 0x3F) * 256) + data2) * 100.0) / 16383.0; + int temp = ((data3 * 256) + (data4 & 0xFC)) / 4; + float temperature = (temp / 16384.0) * 165.0 - 40.0; + + HYT.humidity = ConvertHumidity(humidity); + HYT.temperature = ConvertTemp(temperature); + } + if (isnan(HYT.temperature) || isnan(HYT.humidity)) { return false; } + + HYT.valid = SENSOR_MAX_MISS; + +// HYT.valid = 1; + return true; +} + +/********************************************************************************************/ + +void HYT_Detect(void) { + if (I2cSetDevice(HYT_ADDR)) { + I2cSetActiveFound(HYT_ADDR, "HYT"); + HYT.count = 1; + } +} + +/********************************************************************************************/ + +void HYT_EverySecond(void) { + if (!(TasmotaGlobal.uptime %4)) { // Every 4 seconds + if (!HYT_Read()) { + AddLogMissed(HYT.name, HYT.valid); + } + } +} + +void HYT_Show(bool json) { + if (HYT.valid) { + TempHumDewShow(json, (0 == TasmotaGlobal.tele_period), HYT.name, HYT.temperature, HYT.humidity); + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xsns97(uint8_t function) { + if (!I2cEnabled(XI2C_68)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + HYT_Detect(); + } + else if (HYT.count) { + switch (function) { + case FUNC_EVERY_SECOND: + HYT_EverySecond(); + break; + case FUNC_JSON_APPEND: + HYT_Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HYT_Show(0); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_HYT +#endif // USE_I2C \ No newline at end of file diff --git a/tasmota/xdrv_interface.ino b/tasmota/tasmota_xx2c_global/xdrv_interface.ino similarity index 100% rename from tasmota/xdrv_interface.ino rename to tasmota/tasmota_xx2c_global/xdrv_interface.ino diff --git a/tasmota/xdsp_interface.ino b/tasmota/tasmota_xx2c_global/xdsp_interface.ino similarity index 100% rename from tasmota/xdsp_interface.ino rename to tasmota/tasmota_xx2c_global/xdsp_interface.ino diff --git a/tasmota/xlgt_interface.ino b/tasmota/tasmota_xx2c_global/xlgt_interface.ino similarity index 100% rename from tasmota/xlgt_interface.ino rename to tasmota/tasmota_xx2c_global/xlgt_interface.ino diff --git a/tasmota/xnrg_interface.ino b/tasmota/tasmota_xx2c_global/xnrg_interface.ino similarity index 100% rename from tasmota/xnrg_interface.ino rename to tasmota/tasmota_xx2c_global/xnrg_interface.ino diff --git a/tasmota/xsns_interface.ino b/tasmota/tasmota_xx2c_global/xsns_interface.ino similarity index 100% rename from tasmota/xsns_interface.ino rename to tasmota/tasmota_xx2c_global/xsns_interface.ino diff --git a/tasmota/xx2c_interface.ino b/tasmota/tasmota_xx2c_global/xx2c_interface.ino similarity index 100% rename from tasmota/xx2c_interface.ino rename to tasmota/tasmota_xx2c_global/xx2c_interface.ino diff --git a/tasmota/xsns_14_sht3x.ino b/tasmota/xsns_14_sht3x.ino deleted file mode 100644 index 438ee601a..000000000 --- a/tasmota/xsns_14_sht3x.ino +++ /dev/null @@ -1,140 +0,0 @@ -/* - xsns_14_sht3x.ino - SHT3X temperature and humidity sensor support for Tasmota - - Copyright (C) 2021 Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifdef USE_I2C -#ifdef USE_SHT3X -/*********************************************************************************************\ - * SHT3X and SHTC3 - Temperature and Humidity - * - * I2C Address: 0x44, 0x45 or 0x70 (SHTC3) -\*********************************************************************************************/ - -#define XSNS_14 14 -#define XI2C_15 15 // See I2CDEVICES.md - -#define SHT3X_ADDR_GND 0x44 // address pin low (GND) -#define SHT3X_ADDR_VDD 0x45 // address pin high (VDD) -#define SHTC3_ADDR 0x70 // address for shtc3 sensor - -#define SHT3X_MAX_SENSORS 3 - -const char kShtTypes[] PROGMEM = "SHT3X|SHT3X|SHTC3"; -uint8_t sht3x_addresses[] = { SHT3X_ADDR_GND, SHT3X_ADDR_VDD, SHTC3_ADDR }; - -uint8_t sht3x_count = 0; -struct SHT3XSTRUCT { - uint8_t address; // I2C bus address - char types[6]; // Sensor type name and address - "SHT3X-0xXX" -} sht3x_sensors[SHT3X_MAX_SENSORS]; - -bool Sht3xRead(float &t, float &h, uint8_t sht3x_address) -{ - unsigned int data[6]; - - t = NAN; - h = NAN; - - Wire.beginTransmission(sht3x_address); - if (SHTC3_ADDR == sht3x_address) { - Wire.write(0x35); // Wake from - Wire.write(0x17); // sleep - Wire.endTransmission(); - Wire.beginTransmission(sht3x_address); - Wire.write(0x78); // Disable clock stretching ( I don't think that wire library support clock stretching ) - Wire.write(0x66); // High resolution - } else { - Wire.write(0x2C); // Enable clock stretching - Wire.write(0x06); // High repeatability - } - if (Wire.endTransmission() != 0) { // Stop I2C transmission - return false; - } - delay(30); // Timing verified with logic analyzer (10 is to short) - Wire.requestFrom(sht3x_address, (uint8_t)6); // Request 6 bytes of data - for (uint32_t i = 0; i < 6; i++) { - data[i] = Wire.read(); // cTemp msb, cTemp lsb, cTemp crc, humidity msb, humidity lsb, humidity crc - }; - t = ConvertTemp((float)((((data[0] << 8) | data[1]) * 175) / 65535.0) - 45); - h = ConvertHumidity((float)((((data[3] << 8) | data[4]) * 100) / 65535.0)); - return (!isnan(t) && !isnan(h) && (h != 0)); -} - -/********************************************************************************************/ - -void Sht3xDetect(void) -{ - for (uint32_t i = 0; i < SHT3X_MAX_SENSORS; i++) { - if (!I2cSetDevice(sht3x_addresses[i])) { continue; } - float t; - float h; - if (Sht3xRead(t, h, sht3x_addresses[i])) { - sht3x_sensors[sht3x_count].address = sht3x_addresses[i]; - GetTextIndexed(sht3x_sensors[sht3x_count].types, sizeof(sht3x_sensors[sht3x_count].types), i, kShtTypes); - I2cSetActiveFound(sht3x_sensors[sht3x_count].address, sht3x_sensors[sht3x_count].types); - sht3x_count++; - } - } -} - -void Sht3xShow(bool json) -{ - for (uint32_t i = 0; i < sht3x_count; i++) { - float t; - float h; - if (Sht3xRead(t, h, sht3x_sensors[i].address)) { - char types[11]; - strlcpy(types, sht3x_sensors[i].types, sizeof(types)); - if (sht3x_count > 1) { - snprintf_P(types, sizeof(types), PSTR("%s%c%02X"), sht3x_sensors[i].types, IndexSeparator(), sht3x_sensors[i].address); // "SHT3X-0xXX" - } - TempHumDewShow(json, ((0 == TasmotaGlobal.tele_period) && (0 == i)), types, t, h); - } - } -} - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ - -bool Xsns14(uint8_t function) -{ - if (!I2cEnabled(XI2C_15)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Sht3xDetect(); - } - else if (sht3x_count) { - switch (function) { - case FUNC_JSON_APPEND: - Sht3xShow(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Sht3xShow(0); - break; - #endif // USE_WEBSERVER - } - } - return result; -} - -#endif // USE_SHT3X -#endif // USE_I2C diff --git a/tools/decode-status.py b/tools/decode-status.py index a86e10eeb..21b75ed3b 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -195,7 +195,16 @@ a_setoption = [[ "(GUI) Align (energy) table values left (0) or right (1)", "(Pressure) Switch between mmHg (0) or inHg (1) when SO24 1", "(MQTT) MQTT clean session (0 = default) or persistent session (1)", - "", + "(GUI) Disable display of GUI module name (1)", + "","","","" + ],[ + "","","","", + "","","","", + "","","","", + "","","","", + "","","","", + "","","","", + "","","","", "","","","" ]] @@ -270,6 +279,15 @@ a_features = [[ "USE_HDC2010","USE_LSC_MCSL","USE_SONOFF_SPM","USE_SHIFT595", "USE_SDM230","USE_CM110x","USE_BL6523","USE_ADE7880", "USE_PCF85363","USE_DS3502","USE_IMPROV","USE_FLOWRATEMETER", + "USE_BP5758D","USE_HYT","","" + ],[ + "","","","", + "","","","", + "","","","", + "","","","", + "","","","", + "","","","", + "","","","", "","","","" ]] @@ -298,7 +316,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v11.1.0.1 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v11.1.0.3 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj)) @@ -334,13 +352,18 @@ def StartDecode(): options.append(str("{0:3d} ({1:3d}) {2}".format(i, split_register[opt_idx], option))) i += 1 - if r in (0, 2, 3, 4): #registers 1 and 4 hold binary values + if r in (0, 2, 3, 4, 5): # register 1 holds binary values for opt_idx, option in enumerate(opt_group): + if len(option) == 0: + continue # Skip empty line i_register = int(register,16) state = (i_register >> opt_idx) & 1 options.append(str("{0:3d} ({1}) {2}".format(i, a_on_off[state], option))) i += 1 + if r >= len(obj["StatusLOG"]["SetOption"]) -1: + break # Versions before 11.1.0.3 hold SO until 145 + print("\nOptions") for o in options: print(" {}".format(o)) diff --git a/tools/fw_SonoffZigbeeBridgePro_cc2652/SonoffZBPro_coord_20220219.hex b/tools/fw_SonoffZigbeeBridgePro_cc2652/SonoffZBPro_coord_20220219.hex new file mode 100644 index 000000000..7e9feb2a0 --- /dev/null +++ b/tools/fw_SonoffZigbeeBridgePro_cc2652/SonoffZBPro_coord_20220219.hex @@ -0,0 +1,5242 @@ +:20000000003A0120D1F8010039FB021039FB021039FB021039FB021039FB021039FB021017 +:1C00200039FB021039FB021039FB021039FB021039FB021039FB021011FB021002 +:20004000BA492DE9F04F0446B74ADFF8E8920E68A578507800279046ADF1540D29460C29B1 +:2000600007D9DFF8CCB2DFF8D0A2203933290FD953E3DFE811F06D055E0543052D050D0506 +:20008000F704F304DD04C7045203BA04B6049604DFE811F083047F047B046B046704EC0242 +:2000A00051042F04B10287024303430343034303430343030B04F003D303B80359029D034A +:2000C0003402FC01430343034303430343034303E801B5019C0143038C03790183037703BE +:2000E0006A0354012A01E500660362035803C000480382004503670046003400E1788DF871 +:200100002A7031F07F0006D011F07F0F0CBF381C0120CA49087053210DF12A0300F004BD25 +:2001200008F1110332203946012226F039F808F1120333203946012226F032F8C84898F894 +:2001400011100078012905D04FF400611EF0EAFC00F001BD4FF40061642226F0ADFB00F0E9 +:20016000FABC8DF82B7078B9E41C204626F058FA0546A01C0446083026F052FA0246214610 +:20018000284624F0C0F900E012208DF82B0051210DF12B0300F0C8BCE01C26F041FAE51C02 +:2001A000AE784FF6FF748DF80A600546ADF80850AC4218D0E01EA84215D0A01EA84212D0FD +:2001C00002208DF80C00ADF80E5003A81BF040FE012818BF4FF001090CD1BDF80E00ADF8E7 +:2001E0000800012000E038468DF80B0002A81DF0E1FC8146E41EAC4204DC012088F82A00F2 +:2002000088F82B6021F096FD8DF82C904F210BAB00F08ABC20798DF82E00E078012814D0E1 +:20022000022809D0032805D052200DF12E0124F027FB0FE03C4600E0012452200DF12E01D1 +:2002400021F0B8FD88F8004004E052200DF12E0121F0B0FD4D210DF12E0300F065BCE178D0 +:2002600038465EB13279914205D1F2880DEB4003401CC0B21A813668002EF3D18DF830003A +:200280009DF83000012404EB4000C0B2054619F097FE5FEA000806D18DF8307049212246CB +:2002A0000CAB00F042BC02469DF8300002F8010B38469DF8301081420ADC652049212A462B +:2002C000434622F0A5F8404621F0D4FB00F043BC0DEB400108310B7813700988401CC0B2BA +:2002E00009125170921CE4E7301CE4788DF8317013D03E4601798C420BD11EB905680B49B8 +:200300000D6002E001683160056821F0B3FB284601E0064600680028ECD121F06BFD0DF109 +:200320003103472100F000BCE404012064F20020671B0120280401208A010120E01C10F856 +:20034000014B26F06DF90146C7480068224650B13E4603799A4202D1C388994205D00646B8 +:2003600000680028F5D1012008E006B9BE4E0168316021F07FFB21F03DFD38468DF832004E +:200380000DF13203CDE739460DF12200062207911BF024FDE01C07A924F09EFF8DF82200E7 +:2003A000079870B101888DF8231046888DF8256009128DF8241031128DF8261000798DF894 +:2003C0002700432106220DF12203AEE364788DF8377048B1012805D002281CBF01208DF80C +:2003E000370004D1022000E004200DF0BFFE24F01F04202C40F0AF830DF13703EEE22046BE +:2004000090F80180C01C26F00BF959460A7849468E6856B13C4633799A4202D1F3889842FE +:2004200005D034463668002EF5D101200EE03CB9346804B93C468C6004E0C046DC01012028 +:2004400030682060304621F015FB384628F01F088DF83800B8F1200F40F07D830EABBDE213 +:200460005001012020464478C01C26F0D9F80146584600781FF042FF24F01F048DF8390083 +:20048000202C40F068830DF13903A7E2E41C204626F0C6F8A41CADF8080014F8010B04214E +:2004A0008DF81000204625F015F80646201D10F8019B10F8018B26F0B3F8044631464A464C +:2004C000434602A800941DF031FA8DF83A009DF810000F280FD1022053468DF810001888B2 +:2004E00031464A46ADF80800434602A800941DF01DFA8DF83A000DF13A036FE2207826460E +:20050000042806F1030614BF16F8010B02208DF81000304626F084F8D54CADF80800B01C69 +:2005200010F8018B012626700278414602A81EF047FE8DF83B002770404625F0CBFB0DF1B6 +:200540003B0332464BE20220E41C8DF81000204626F066F84E46A11CADF808000C7A7068CB +:2005600026F0CEF97168C4F3400804F00104B8F1010F0F7204D17268107A40F04000107268 +:20058000012C03D1087A40F080000872484602A9342209231DF080FD0DF13D038DF83D0069 +:2005A000C1E20226E41C8DF81060204626F038F8A41CADF80800204626F032F8A2788046DC +:2005C00002A84146144625F023F98DF845009DF810000F280CD1504600888DF81060414642 +:2005E0002246ADF8080002A825F012F98DF845000DF14503F2E10226E41C8DF810602046B6 +:2006000026F00EF8A41CADF8080014F8010B8DF84700204626F004F8A41C14F8019B8046C7 +:2006200002A90DF14700424600944B46019721F011F88DF846009DF810000F2811D150464C +:2006400000888DF810603E4602A94246ADF808004B4600940DF14700019620F0FBFF8DF829 +:2006600046000DF14603B9E164F20020A946E51CA878B846FE280BD1E878FF2808D12078D5 +:20068000082805DB284625F0CBFF294624F0BFF9284608A925F09CF9041C0ED1182019F0B9 +:2006A0008FFC5FEA000807D0BDF8200039461822434625F075FD00B1C824192019F080FC8E +:2006C000061C20D05CB9701C2946082225F066FA06F109004146102225F060FA04E0701CC1 +:2006E000FF2118221BF07AFB3470652049461922334621F08DFE3046394619221BF06EFB74 +:20070000304621F0B7F9B8F1000F00F024824046394618221BF062FBD5E502271BE21BF0C2 +:200720008DFF18E2E01C25F07BFFE51C0246A81C10F8011B1CF074FA4E210DF12D038DF8DB +:200740002D00F1E18DF82F7025F0DCFA0DF12F034C218DF82F00E7E120461BF035FFFAE1F2 +:2007600020461EF08CF8F6E1E01C25F059FF6179A2791DF054FA46210DF133038DF833009E +:20078000D2E1E01C25F04CFF6179A27911F032FE45210DAB8DF83400C6E1E01C11F04CFB62 +:2007A00044210DF135038DF83500BDE1E01C25F037FFE51CA91C0B4608310A4619461FF0F1 +:2007C0005BF842210DF136038DF83600ACE10220E41C8DF81000204625F022FF4E46A11C40 +:2007E000ADF808000C7A706826F08AF8706802A935220923047248461DF04EFC0FAB8DF8B6 +:200800003C00EBE00220E41C8DF81000204625F007FFADF80800A0780DF13F0602A9332291 +:200820008DF83F00012300964846019720F012FF0DF13E038DF83E00D0E00220E41C8DF89A +:200840001000204625F0ECFEADF80800A0780DF1410602A932228DF841000123009648460C +:20086000019720F0F7FE10AB8DF840005BE1C0468C0A01200220E41C8DF81000204625F030 +:20088000CFFEADF80800A0780DF1430602A931228DF84300012300964846019720F0DAFEF1 +:2008A0000DF142038DF842003DE10220E41C8DF81000204625F0B4FEA41CADF8080004219A +:2008C000204624F007FE4E46221D014612F8018B7068137825F056F902A900F8018B3022A1 +:2008E0000370484606231DF0D7FB11AB8DF8440019E10126E41C8DF84860601C25F090FEFD +:20090000814604F10B0025F08BFE804694F800A0637BA07B22F036FC0093E01C494652468D +:20092000434613F06BFC12AB8D498DF84800042025F0A0FE05E60126E41C04218DF8496028 +:20094000204624F0C7FD21791EF08CF885498DF84900022025F08EFE83490DF14903032095 +:20096000E6E7204619F0E6FDF5E0E41C204625F057FEA11C0B4608310A4619461EF07CFF34 +:200980000DF14A038DF84A00CDE020461AF089F9E1E020461AF042F9DDE020460FF0A4FE6E +:2009A000D9E0E01C25F03CFE4E464FF6FD740F22ADF8084071688DF81020022304121522CB +:2009C00001F8010B48460C7002A9F7701DF064FB39468DF84B000DF14B03F17001222946FC +:2009E000A3E0204618F0D8FDB5E0E41C204625F017FEA11C0A7A3B4622F028F813AB8DF8D5 +:200A00004C0090E00220E41C8DF81000204625F007FEADF80800A01C25F002FE01461122EB +:200A200002A824F0F5FE0DF14D038DF84D007AE00220E41C8DF81000204625F0F1FDADF8C6 +:200A40000800A01C25F0ECFD0146102202A824F0DFFE0DF14E038DF84E0064E020460FF0F5 +:200A6000A3F978E00220E41C8DF81000204625F0D7FDADF80800A01C25F0D2FD01460522C1 +:200A800002A824F0C5FE0DF14F038DF84F004AE00220E41C8DF81000204625F0C1FDA41CD7 +:200AA000ADF80800204625F0BBFD4E467268A1781070726803125370706803230422817088 +:200AC00002A948461DF0E8FA14AB8DF850002AE00220E41C8DF81000204625F0A1FDADF8DB +:200AE0000800A01C25F09CFD0146032202A824F08FFE0DF151038DF8510014E00226E41C89 +:200B00008DF81060204625F08BFDADF80800A01C25F086FD0146324602A824F079FE0DF1EA +:200B200052038DF8520029460122652021F070FC11E0E41C204625F073FDA41C14F8011B31 +:200B4000227822F053FB0DF153038DF85300EAE7204617F0FFF9384615B0BDE8F08FC046CC +:200B60006D290200CD4A0200C15101002DE9F04F04464FF6FE70ADF15C0DADF85400A44873 +:200B800040784FF00008022812D1A148007878B92089002807BF30204146102001210EF0F9 +:200BA000FDFE8DF8568052200DF1560121F002F96068217A08AA12F01DFA002800F0D98469 +:200BC0009DF822000228B4BF012747469DF824000228A8BF4746BDF82A104FF6FE7BABF1EC +:200BE000060B8B450ED04FF6FE70401F884209D04FF6FE70001F884204D04FF6FE70C01E80 +:200C0000884200D1474625F0D5FC9DF82310884240F0AF84002F00F0AC847D4840780228DB +:200C200004D19DF85100002840F0A384208D9DF82660678EADF84C00ADF82E70D6B1616839 +:200C40009DF821209DF83C30012024F0FBFF002840F08F84C448001D007801280AD1208DD1 +:200C600025F0F1FD30B1417901F0EF01417141F0080141719DF82570DFF8E492DFF8E4A283 +:200C80004646002F49D19DF83D00474658BBBDF82A00034620F08EFE4546022808BF0125A7 +:200CA000002D9DF8225018BF012749460988994208BF47F0020727B1002D14BF4021202185 +:200CC0000F43184620F076FE012808BF47F00107002D3BD01298007825F0A6FA012818BFA2 +:200CE00027F0010732E09DF8411041B1FF2906D09DF84000119A22F02BFA50B126E0524697 +:200D0000BDF82A10508F884205D092F84A0004281CD101261AE0222718E0BDF82A10FF2009 +:200D200023F0E6F9002804BF3D1C082708D09DF8250047F001052C2740F001008DF8250051 +:200D400005F00305012D08BF47F0110730489DF82650407830F0010005D107F002010E43D5 +:200D600008BF47F08007DFF8DCC295B961460E787EB107F0220122290BD007F042014229EA +:200D800040F0F78312990978062918BF072940F0F083F9094FEAA7155AD3BDF82A201299D6 +:200DA00048B96046C01C0078800804D30878401E0A282FD909E00878C01E01282AD9001F2F +:200DC00028D0C01E26D0801E24D0B8F1000F21D148460088904240F0CC830D780520BDF845 +:200DE0002C408DF8110004A824F036F9002800F0C0830269032313271370511C0F704C70B1 +:200E000022128A70CD70448009F022FAB1E3C046E404012068081BD30878032802D148784F +:200E20000D2815D09DF8280038B1BDF82C000E990EF0AAFB012800F098839DF8270038B1EE +:200E4000BDF82A000D990EF09FFB012800F08A8309F10E00B4F844100088884209D1CDF856 +:200E60000080208DB4F8421094F8462043460AF0C9FF9DF82600002843D0208DB4F8421069 +:200E800020F092FC061C25D19DF8510088B99AF89000012835D112980078062801D1680892 +:200EA0002FD2BDF82E100BF10700884240F0C5805FE3042024F04AF8011C00F05A836420D2 +:200EC000087001274F70208D48809AF800001FF089FC4EE39DF821106068F3780A18527BFF +:200EE0009A4203D0F27040467060606840180421401C24F0EFFA7168814200F23A83401C46 +:200F00007060B348DFF8C4B24078022800F08F8230F0010040F02D839AF832008008C0F0D9 +:200F200028839DF8510030B3BDF82C0024F0E1FDE0B9A5495C46BDF82C000B686269990188 +:200F4000A1EB83019047012840F01383A169BDF82C008847E168BDF82C00884709E3C04616 +:200F60008A01012050010120500101206168487800F0DF0048709DF8320038B16168887957 +:200F8000401E8871C0B28DF8320008B907F07F07380924D39DF82500F9084FF4805814D29F +:200FA00079091AD3811011F0070F01F0070604D0072E1CBF761EF6B20EB907F07F0700F0C8 +:200FC000E30040EA8600C0B205E020F01C00C11021F0030108438DF82500616808729AF84B +:200FE0004A00042800F0E981092800F0E68117F0610F40F0EF809DF82200012811D1129817 +:201000000078052800F0D88003280AD1BDF82A0024F06FFD28B1218D08A815AA002301F074 +:20102000CFFB9DF8320078B99DF82200012804D112980078032800F09C8208A821461EF0B9 +:20104000CBFC96E27F01012024F09EFA002840F090829DF83D0000286DD19DF82400BDF8F4 +:201060002A10FD100028ADF854102ED13A0930D29DF82220012A28D0084600211BF0AEFC96 +:20108000002620B14079012816D0022814D0BDF85400B4F8441020F087FB28B1807823F004 +:2010A00088FF08B1082807DBBDF82C0024F021FD18B104208DF824000126BDF82A10002EF1 +:2010C00008BF022272D09DF824006A0838BF002300D340230DF13D021BF0BAFC30B16168C0 +:2010E000087848F0200800F03F0008709DF83D0040B1BDF82A1010A820F03CFC48F0400837 +:20110000ADF854009DF82200012806D0BDF82A00BDF82C10002217F047FF68082CBF402224 +:201120000022BDF82C10BDF82A0015F029F908B148F0200833E09DF840009DF84110119A04 +:2011400022F006F800282ED09DF8410038B9BDF82A00ADF8540025F076FB00BB1DE01199D2 +:201160009DF8286001EB400030F8020C002EADF854000CBF082110219DF8270008B10831F6 +:20118000C9B29DF82500002200B1012266688918491CCAB2905D401E905548F0400823F011 +:2011A000F1FC8146A8E0BDF82A100B22BDF82C0000231BF059F9DCE1218D08A815AA002379 +:2011C00001F0FEFAD5E1C046BC800200E4020120E404012078084FF0000967D39DF8330052 +:2011E000B4F828B0C04D494616901E20EA79169B934206D1BDF82C302A88934201D1AE789B +:201200002EB9401E05F1080501F10101EED11E2921D0AE79E6B1BAF84810584623F044F8E6 +:2012200008B1761EAE71BE4833210279FF2A02D00288934504D0491E00F12400F5D102E018 +:20124000A879401EA871A8794828A4BF4E46AE7127F060072AE023F095FC81469DF8320095 +:2012600028B9BDF82C00218D814202D11EE0BDF82C00BAF83A10884202D19AF80600A8B1FF +:20128000218D08A84A4610F0DDFA58B1380932BFBDF82A004FF6FE70401C48F00408ADF877 +:2012A000540003E027F020074FF00009B8094FEAA71510D394F8460094F8476094F94830CE +:2012C0008DF81000E26B8DF8116004A98DF8123008A804F037FF68080ED3218D08A815AA7A +:2012E0004B4601F06DFA5FEA000905D012980078012808BF48F01008BDF854104FF6FE70B0 +:20130000884208BF4FF000099C49C97E012927D1628E411C914223D0228D914220D0BDF86C +:201320002A10401F88421BDDBDF82C00904217D025F089FAA0B10179012918BF02290FD149 +:2013400001218DF810104088ADF81C0004A81EF06DFE28B105A81EF0B3F908B120F0EAFC29 +:2013600037F07F0000F00581B9F1000F00F00181208918F025FE071C00F0FB806168228950 +:2013800024F00CFC002605969DF822008DF81000CDF80090CDF8048004AD0296BDF8541024 +:2013A0000395228D237A384614F09EFC002800F0E080384620F05EFBDBE04946BDF82A00A5 +:2013C000098881420AD020F0F5FA022806D09DF8250000F00300012840F0CB809DF82200D8 +:2013E00098B112980178042904D19DF83C10022900F090800078072804D19DF83C100429E9 +:2014000000F0848003287CD0B3E094F846008DF8100094F847708DF8117094F948608DF864 +:201420001260E26B08A804A904F08CFEA1E09AF84A00042818BF092840F09B80B80971D232 +:2014400012986908C0F095800178042903D19DF83C1002295ED00178072903D19DF83C208A +:20146000042A53D003294CD00C2940F08280401C424A10F8017B0578164601215120D21CA6 +:20148000F57025F051F93D4B3B49012658465C79067057B9002C14BF4EF660204FF47A706C +:2014A00051F8241000FB01F405E00846203000684EF6602444430320B4FBF0F441464FF405 +:2014C00080400EF06BFA9AF8000002211DF02AFB68080BD2A8084CD39AF8000002212246C9 +:2014E00025F0E7F945E0C046440200204FF48040214616F085FC4FF4804031460EF04EFAB5 +:2015000037E008A8002112F017FA32E008A81AF0B1FA2EE0002008A90BF018FD29E0C0465B +:201520002C10002094F8460094F847709DF832508DF8100094F948608DF81170012D8DF8A0 +:2015400012607FF46EAF208DBDF82C1088427FF468AFBDF82A0020F02DFA022808BF8DF80B +:2015600032805EE7BDF82A0001E0BDF82C001EF08DFF17B0BDE8F08F98800200E40401202B +:20158000B94A2DE9F04F0846ADF14C0D11780F90000C80F067849246B44D0F9A6878920B20 +:2015A00080F03184022813D10F9A520810D39AF850000F2807D19AF84A0020B1012802D079 +:2015C000002020F09DFF0F9880F0010000F06ABC0F9A920980F04C83DFF89892DFF898829C +:2015E00030F0010740F0BC820F9A520980F03D820F99C90980F0C4819D490F9F0A78390A9A +:2016000080F0AD813946490A43D23946090B2AD20F999AF80370490B1AD20F99C90BC0F09D +:201620009F824C46A06A70B1297D01290BD18047E06A00B180479AF800004FF480414FF4BE +:201640007A7225F036F90F9880F4804000F02ABC27B100208AF803001FF052FF0F9880F4B1 +:20166000805000F01FBC1FF04BFF687C01280BD1A97C49B19AF800004FF47A7212FB01F2AD +:201680004FF4006125F015F9384680F4006000F009BC24F095FF4FF6FE7B834500F05B8182 +:2016A0009AF832008008C0F0568100263446304623F00AF8071C19D03879012816D0022836 +:2016C00014D0F879411CF9719AF88B1081420DDABC727C72388822F011F9388801A923F0A2 +:2016E00096F901A81DF0ECFF20F024FB761C332EDDDBA8F11C0614275D46119436F81C0F49 +:2017000085420CD0307B9AF88B40411C8442317305DA1198B0747074308822F0EFF87F1E79 +:20172000ECD14C46032104F13C0010F8047F0FB17F1E0770491EF8D1B04C332605F1010921 +:2017400034F8240F81451FD001208DF804006788ADF8107001A81EF069FCA8B1A8F11C0588 +:20176000142735F81C0F2188814208D0BDF80610814204D002A8A91C24F000F910B1284685 +:2017800024F08EF97F1EECD1761ED9D1119D2C46284622F099FF48B1077937F0040705D15D +:2017A000807A23F006FC08B1641CE4B26D1C332DEEDB23F02BFB119E5FEA00080ED0354607 +:2017C000284622F087FD28B1807C23F0F2FB08B1761CF6B26D1CEDB2A845F1DCA019C7B229 +:2017E000002F4BD0B80018F0EBFB1090002808BF119F45D0BA00FF211AF0F0FA119E3546AD +:20180000B44218DD284622F05FFF031C10D0187930F004000CD1987A23F0CBFB011C07D08F +:20182000009718885A7A109B19F07EFA761CF6B26D1C332DE4DBB8F1000F21D0119C2046D3 +:2018400022F048FD061C0AD0B07C23F0B2FB011C05D00097109B3088727C19F065FA641C87 +:20186000E4B2A045EBDC0BE050010120E4040120FE090120E40201209C0400201198109088 +:201880009AF83000002808BF4FF0620805D024F0CDF9C0F154005FFA80F80320B8F1600F2E +:2018A00098FBF0FAA8BF4FF01F0ADDF84090ABF1020BB8F1000F0EBF119D2025DDF844807D +:2018C000BA45A6BF3C1C45F040055446032014FB00F0801C8DF8050001A823F0BDFB4E46E8 +:2018E000031C26D01869082104F01F02017045EA02014170801CA4B12246C01E361F16F826 +:20190000041F00F8031F318809124170B17801F0070CF178521E01F0070141EA0C118170CD +:20192000EDD1A3F802B001209876184608F090FC00E00120E90906D2641EE4B20CB109EBF7 +:2019400084093F1BFFB205F040052843B1D0109808B120F08FF80F9880F48070A2E21043EF +:2019600008D1B3480179012902D10021C170017121F0F4F91EF09EFE384680F0800091E2CF +:20198000B44C1E2600214FF006084FF00409A778002F43D07F1EFBB26079A37023F0B6FFEA +:2019A000071C3AD06BB9787B022808BF87F80D8033D087F80D803868407BF0211FF0FEFB63 +:2019C0002BE0A3791BB9787B032812D025E023791BB3E078401EC3B2E370F3B99AF82500BC +:2019E000E0702079401EC3B22371787B032814D133B92046394620F0BDF80EE008100020D8 +:201A000087F80D9024F0C7FE00F00F00401C38819AF8000020211DF01BFB0121761E04F11C +:201A20000804B4D19AF80000012910D040211DF079F895F82A00012813D1002085F82A000F +:201A400095F82B0016F0B0FE20F074F909E040211FF0F0FF28B99AF800004021642224F0E7 +:201A600028FF0F9880F040001CE2084610211FF0E1FF30B99AF8000010214FF47A7224F08D +:201A800018FFBB48DFF8EC82417808F2AC54491ECFB217BB012141700020052123F09CFCB6 +:201AA000071C1BD006253846052123F095FC0646388978B1401E80B2388158B97889C0084C +:201AC00002D3387B21F002FF7D733868407BF0211FF074FB371CE6D100E0477064274FF621 +:201AE000FE7600252079A0B1FF2812D0401E2071C0B270B96079032805D160882188022241 +:201B00001CF060FD6079012803D0268066806571A5717F1E04F10804E4D108F15A04082736 +:201B2000207A401E2072C0B230B9C048214622F01DF890B9668025707F1E04F10A04EFD106 +:201B4000BB4AC82112F8080F08B1401E1070491EF8D10F9880F01000A4E11FF07DF8E4E7B4 +:201B60004C460F992778890864D20F992289890A40D20F99090906D301200F9F8AF80600E3 +:201B800087F008008EE10F99C90A26D20F98400C38BF0020C0F08681C44C332501262079FB +:201BA00080B105280EDA607900090BD28DF804606088ADF8100001A81EF038FA10B102A846 +:201BC0001DF07EFD6D1E04F12404E8D100200F9F8AF8040087F4803064E1022801D11AF052 +:201BE000DBFABAF84800012119F0F2FA0F9880F4806057E1BAF8485004F108015020AAF872 +:201C0000482020F0D7F82689142744466089854205D0864204D0204623F042FF00E0668167 +:201C20007F1E04F11C04F1D10F9880F4007039E1CCE8002087B9BAF83E10012021F0BCFA8F +:201C40006878022810D19AF8000001211CF06AFF0AE0C0464402002001A824F0F8FD24F054 +:201C60009DFC01A91DF03CF90F9880F0020019E1084620211FF0DEFE28B9DAF81000002867 +:201C800008BF012616D024F0D9FF044624F074FC4FF47A716043B0FBF1F1DAF8100000284E +:201CA00008BF002004D088428CBF4FF0FF30081A46086AD00020042123F08EFB071C64D004 +:201CC000FF254FF0FF3B06244FF001093846042123F082FB10903889864204D8801B83B2EC +:201CE0003B8113B14EE000203881BB7B012B02D17889C00840D3002B36D08DF804508DF8BD +:201D000005508DF806B03968086AC97F02AA11F071F94FF00008012808BFC8465FEA08002B +:201D20001DD0788A40F08000ADF83600B87B8DF838007889000908D3BDF8360040F4807045 +:201D4000ADF83600387B8DF83A007B6913B1187BADF8180001A9002202A804F0F3F97C73F9 +:201D6000387B19F007FE0DE087F80D900AE0C046640F0120200100207C733868407BB721B2 +:201D80001FF01CFA109F002FA0D10CF061F89AF800300020012123F01FFB18B118462021E1 +:201DA0001DF056F90020042123F016FBB3B278B152460789147823F00FFBF8B9BB42AEBFE4 +:201DC0000027FF1ABFB2204627B920211DF040F900200DE07A00202124F06EFD24F02EFFFD +:201DE000044624F0C9FB4FF47A716043B0FBF1F0CAF810000F9880F0200053E00289BA42A1 +:201E0000D8BF171CD7E724F095FD294C0546201D00680746C0B157F80C1C9AF8000049B966 +:201E20004FF400511CF06AFB08E0C04621130200E40900204FF400511DF00AF920463946E3 +:201E40000022001D21F0BEFB284624F0F3FE2FB13846FEF78BFE384623F07EF90F9880F407 +:201E600000501FE008461DF0C5F8071C17D0114920310A78FF2A0FD03C780B4600209442C1 +:201E800007D0401CC0B2C200D1189A5CFF2AF6D102E0496838468847384623F05DF90F989E +:201EA00080F4004013B0BDE8F08FC0462C100020E40A0120987C02002DE9F04FC14DC24C8F +:201EC000DFF808A3C44E88465FEA1840ADF11C0D80F09E826F78DFF8F892DFF8F8B25FEA96 +:201EE000580080F01B82384630F0010040F091805FEA980058D25FEA981044D25FEAD8303A +:201F0000C0F087800120022122F0CAFBC5B20DB3E80018F055F8071C1DD0C04C82464FF058 +:201F2000010933262079012818BF02280DD18DF804906088ADF8100001A81EF077F820B1F0 +:201F400002A9504624F0DCFC8246761E04F12404E8D100E0002797B175B10F204FF6FC76C7 +:201F60008DF80C001F24ADF8046001A92A463B46C248009415F032FC38461FF07BFD88F497 +:201F8000804000F00DBC207A38B92078062802D1072023F087FE23F06FF9E07910211DF0D3 +:201FA00057F888F02000FBE3207AE8B92178E079082917D123F0F8FA092023F073FEBF485D +:201FC0000078052806D0072809D10720012105F0D3FA04E0012022F067FC1BF0C1FF23F01A +:201FE0004BF913E010210FE024F0DEFAEF2803DB002022F059FC09E024F0D6FA1030C0B2A3 +:2020000024F0E4FAE07901211DF022F888F00200C6E3CE48CE4B0668B3F900005FEA58110E +:2020200080F04E815FEA181028BF88F0080080F0B7835FEA582080F0D1805FEAD80080F0CC +:20204000B78037F001001CD15FEAD81019D32069A0B116F071F92069076820691FF00AFD36 +:2020600027615FB1FA8802E0F888801AF8803F68002FF9D1E079402124F01EFC88F0400092 +:202080008EE35FEA182064D25FEA98205CD2C84C5FEA18302CD25FEAD82027D3142017F0D0 +:2020A0008FFF071C1FD0002524342E46207A012812D10097042029463246142320F0A6FB5F +:2020C00050B9206838606068294614223B467860042021F0DDF926726D1C0C34C82DE5DBF0 +:2020E00038461FF0C7FC88F4806059E3002057E3182017F065FF071C23D000252E46207AB2 +:20210000012812D10097062029463246182320F07DFB50B9206838616068294618223B4630 +:202120007861062021F0B4F926726D1C0C34032DE5DB38463146182219F050FE38461FF07E +:2021400099FC88F400602BE319F000F888F4007026E31BF005FF207805281DD1E0790421CA +:202160001CF0E0FCE07904211CF0C8F9062023F099FD687830F0010007D15046007800F086 +:202180000700022801D024F0FFF81FF0D3FD18F0DDFF1EF08BF801E01FF0CCFD012021F0F3 +:2021A00055FC0320012105F0E7F988F08000F7E2FF20032120F00AFE24F00EFAC249012040 +:2021C0000860FEE7E4040120C4030120501A0120500101203C0501204C1A01204A4692F8C1 +:2021E0004A00082818BF042845D124322120742124F09AFABF4E6878716832880024B146DD +:20220000A2423DDC30F001002DD1044CFF25002694F82100802822D102E0C0462C1000207C +:202220006788ADF8067023798DF80830A1798DF80A1062798DF809202088ADF80400E77948 +:2022400084F82150237D8DF80B70A7698DF80C3031461022032001AB049721F019F9761C58 +:202260002434332ED4DBBB48006800B180470020022120F0ABFD88F4807091E228040120EC +:20228000A30003EBC403CF5C37F07F0C13D017F07F07CF540B4405D101A8FF210C2219F051 +:2022A0009DFD01AB012021460C2221F0F1F86878D9F804103288641CA4B2A1E76F060120B5 +:2022C000B0F1FF3F37465C4602D1B8480078A0805FB17968087818B1486800781AF088FDA4 +:2022E0003F68002FF5D1B4F90400B0F1FF3F02D0C0B21AF07DFD24F063F9AD49088023F0E9 +:202300001DFC687C012806D14C4620784FF40061642224F0D1FA88F0100041E2012023F0AE +:20232000C1FC3046677801793546122201F0070A11F0070F16D1022F0CD0012F12D108201A +:2023400023F0B0FC24F020F80BE0C046C00A012040050120082023F0A5FC0020014612F00B +:2023600031F90246BAF1010F18BFBAF1020F45D107B3032F1ED0012F40D1BAF1010F3DD1A3 +:202380000A2023F08FFC4C4620784FF480611CF0C9FB502005A922F073FABDF81400A4F855 +:2023A0004800BDF81400002118F012FF2DE0C046E0E8002023F0A8FF002818BF032F16D105 +:2023C000022023F06FFCB749E06809781CF04AFB0246A879000911D28AB959464878401CF0 +:2023E000C0B20428487004BFBB48E06006E024F0D2F90146012012F0E5F802462AB1E079F9 +:2024000001214FF47A7224F057FA88F00100C7E1DFF8CCB2BBE10646B04A337827781168EB +:2024200068781A46521E00F08D81521E00F09480183A00F0A681B93A00F09F812A3A00F0BA +:2024400083801B1F77D05B1E6ED05B1E54D05B1E3CD05B1E2CD05B1E40F0968120BB707F20 +:20246000DBF8109000BBB9F1000F06F1050A1BD0BAF1000F18D04F46B81C5146082222F0A6 +:202480005BFE18B9FF68002FF6D104E038461DF079FDDBF81090B9F1000F05D19BF800003B +:2024A0004FF400611CF03EFB304622F005FF6BE1012818BF022840F06781307916F074F9FD +:2024C0001FF038FC60E1C0467C052043002840F05B813079012800F05781022806D0042894 +:2024E00040F05281304618F001FA4DE1304612F0B7FF49E1DC0A0120012840F045817088BC +:20250000002840F04181301D01A921F0D7F8012840F03A8124F054F8ADF80C00361D0296BA +:2025200001A816F0BBFB2FE1002840F02D81304611F0F2FC28E1012818BF022840F02481B3 +:20254000304608F031FD1FE1002900F01D813046884719E13C090120012818BF022840F029 +:2025600013815846C0795E46072818BF082805D1237A1BB9012104F0FFFF2778032F00F0FA +:2025800093800A2F16D0042F1AD00D2F18D00E2F16D00C2F14D0002F00F0F6801DF086FE60 +:2025A000E07910211CF054FDEEE0C046671B0120E00301208048007800F00700012873D016 +:2025C000277A6078002F35D10020E0720746F7701FF01EF8F8B120780D281CD00E281AD080 +:2025E000062023F05FFB70480078000904D34FF4004001210DF0D2F9687830F0010007D1F2 +:202600006E48007900F00700022801D023F0BCFE1DF04CFEB8E06878022803D108200121B5 +:202620000DF0BCF9052023F03DFB42F2107022F013FEA9E0E17A01280BD003281ED16878BF +:2026400002281BD1594900260E7001270320677113E0491CC8B20428E07204DB54480078B8 +:20266000012809D00AE0534800884FF6FF7181421CBF0426A672E8D10020607021F08EFA74 +:2026800020F07CFC48480078000902D3287D01287AD16078032877D1082001210DF07EF9AA +:2026A00072E0C04699060120207A002848D1E07910211CF0CDFC1EF0ABFF98B968780228B5 +:2026C00003D1082001210DF069F9052023F0EAFA01201FF0CFFB57E000F8FF0728070120E2 +:2026E000680601206F78207837F001070AD10A2808D13149097801F00701022902D02B4A51 +:202700000821117003280BD11DF0D0FDF079022806D1012021F09AF90220012104F02CFF9C +:20272000062023F0BFFA687830F001002CD12248007800F00700022826D023F025FE23E077 +:202740000020C6E7022F1FD1012818BF02281BD123F0A8FF28B113F09BFBA8B168780228E6 +:2027600008D023F0D5FF00280CBF002001201FF099FF09E019F010FD06E0304605F0A2F8D5 +:2027800002E0304606F082FC069822F0E5FCE0791CF030FC002806907FF43DAE88F4004073 +:2027A00007B0BDE8F08FC046521A01209A010120E006012098010120501A01204C1A01201C +:2027C0002DE9F04F064693460020ADF13C0DABF80000B06A099303460078884623F024FD5C +:2027E00048B1708904461FF0E5F8022804BFABF80040B36A01D0002009901878C84DDFF8BE +:202800002493401E0A2800F20B84DFE810F02F03B3020C04A0028D0151010904BE0088005D +:2028200066000B00BD4C207D012840F0F9835B1CB06913F8015B1F7824F032F8002800F0C8 +:20284000F7830379002B00F0F383032B80F2F0830E2D1CDCDFB9D04907752DB901EB850126 +:202860000A6BC261096B0AE001EB85010B6B9A01A2EB8302C2610A6B9101A1EB82018161B2 +:20288000012180F820101FF055FA002500E001250320B689E4788DF8190006A822F0DCFBF2 +:2028A000071C00F0C58338690C2100F8011B00F8015B04700124BC7723F040F9786204A9E8 +:2028C000304622F0A4F810B17C7704A838627E80BC76384607F0BCFCAAE35C1C207820F0D0 +:2028E0001F0700F01F00012840F09A83641C04A8214624F005F8284604A95D3023F03EF898 +:20290000002800F08D83002F40F08A830834A2786178207801EB022120F0B0F988E3688F32 +:202920007189884240F07C835C1C14F8016B04A8214623F0E5FF284604A95D3023F01EF8D9 +:2029400006F01F0726F01F06002800F07183002E40F06E83780017F033FB011C00F0688320 +:2029600067B184460834384663782278401E04F1020402EB03222CF8022BF5D100910EF035 +:2029800058FC08461FF076F852E35C789A1C34F07F0704F01F0E40F04B83377F03201EFB9E +:2029A00000F0801CC1B2B94240F04283002714F01F0F04BF4FF6FE7C614618D0D9789B785A +:2029C00070464D4603EB012C5378117812F802EF01EB03213EF0770340F02A832B888B422F +:2029E00008BF0EF00707521C401EEDD1BFB960464FF6FE72824212D004F06002602A0ED043 +:202A00004D462A88A30907D2E30902D2904203DD0EE3904203DD0BE39142C0F20983B0899F +:202A200023F011FF002836D1B0894FF6FF7121F03BFC041C14D120F011FD041C00F0F88261 +:202A400000211C2219F0CAF9B0894D460E35208028886081AA23A374062222740121617472 +:202A6000207C0C2805DB0620072F2074BCBF7F1CFFB2677400202073A01C22F01CFD002852 +:202A800040F0D682307A002800F0D282B169A01C23F036FFCCE20021C171017A0C2905DBE9 +:202AA0000621072F0172BCBF7F1CFFB24772BFE2484671890088884240F0B282307F02280E +:202AC00040F0AE82AA4CA01D00884FF6FE71814240F0AE82162022F039FA071C00F0A882CC +:202AE00001213970B07900280CBF081C02207870B06A4078B872000902D2B0891FF068FE3A +:202B0000B169B81C23F0FCFE0020F874287839461DF068FEB089E0808AE2C046E404012088 +:202B2000500101208A01012070891EF043FF002840F076825F78B94987B10C2F03F1020399 +:202B400080F276828C463D465A7818786D1E03F1020300EB02202CF8020BF5D14846758940 +:202B60000488DFF8D892AC4200F0B280B37C002B00F05E823B1C0A974FF0000811D0A74A3D +:202B800038464146921E32F8023F9C4206D0401E01F10101F7D104E0688002000A914FF09F +:202BA00001082846002119F019FF00280B907ED0407901287BD10B98807910F0180F76D014 +:202BC0000B984188384622F0AFFE10B9B8F1010F6DD109F55F794FF6FE704FF000080C9719 +:202BE000B6F80CB0CDF820904FF0010A0D90C14611E0B8F1010F08BF4FF0010908D023F063 +:202C0000CAFDC0B290FBF8F101FB08F1A0EB01094FF00008C246089D14271C3D35F81C4F5D +:202C20004FF6FE70A04213D0A34511D00C98214622F07AFE60B96B7C53B1072B08DA08F1AD +:202C40000100BAF1000F5FFA80F801D1C14521DD7F1EE3D1B34D332735F8244F0D98A04240 +:202C60001AD0A34518D00C98214622F05DFE98B96B7A8BB1072B0FDA287901280CD00228C5 +:202C80000AD008F10100BAF1000F5FFA80F803D1C14501DC0D9407E07F1EDDD1B8F1000F93 +:202CA00002D0B9F1000FA4D00D980B994880B37C5A4C581EB074F77C00970A9D01950294B8 +:202CC00001220392B189B269708915F02BFCAFE1B4890C2F80F2AC818846ADF81040BD4853 +:202CE0008DF812700168CDF8148009B104A8884720461CF009FAC82803D14FF6FE701CF0DE +:202D000003FAC82880F2948109EBC00000F6CC05686808B11EF0AEFE2FB1780017F050F9D9 +:202D2000686010B984E1002068606C80C2486F70007828706878002800F07A8168680028E5 +:202D400000F076817A00414622F028FF70E1307F022840F06581099828B94D467189288853 +:202D6000884240F06581099831460AF0EFF85EE1E4020120B5F8481040461EF015FDA8469B +:202D8000074608202FB17D781DB90621397007257D70B16A0A79CC788B794D7891F802A054 +:202DA000CF7904EB02244A7902EB03296A0928BF1020AA0924BF0830C0B235F0700340F048 +:202DC0003781327F904240F0338105F07005680938BF002006D306A8083123F091FD25F06C +:202DE00010050820A90907D3B16A091804A8083123F086FD25F020052046514621F0B2F861 +:202E000008280DDA8D4B410001EBC001C9188879B84240F30D818F71002002E044010020D1 +:202E20000420B8F83A10A14219D048B9B189484601222B460EF06CFC28B1F9E020010020F2 +:202E4000042840F0F58006A804AE009049463A46534601962046029512F0CCF8E8E0B189AD +:202E6000484601222B460EF053FCE1E0B5F8481040461EF099FC4FF00609041C03D06078DB +:202E8000002800F0CD80B06A817847780891C378017900F1050A03EB0120099040461DF072 +:202EA000EDFC9AF8001009185FFA81FAB80928BF4FF00E0937F0780040F0B28007F0180084 +:202EC000182800F0AD80307F814540F0A9804FF00009CDF800900899B0895246434619F026 +:202EE000F1FD032800F09C80002807F078074DD117F0180F18D195F8310028B1B089414683 +:202F000001223B460EF004FC09984FF6FE714A463B460EF0FDFB002838D14FF6FF70ABF82B +:202F2000000039E00810002047F00107780928BF47F00207B089394619F050FD90B1817910 +:202F400011F0180F0ED0417901290BD154B14088B5F848101EF028FC20B1437813B160787F +:202F600098425DDCB089414601223B460EF0D0FB60B94FF6FF70347AABF80000002C0CBFFC +:202F80004946B169B089524622F034FCBBF800104FF6FF70884243D1012000900899B08995 +:202FA0005246434619F08EFD099839461DF0E6FF698F81422ED1099823F045FC60B1007911 +:202FC000012818BF022807D1099804A921F01FFD08E0C0460404012022F0B0FD014604A8AB +:202FE00023F08EFC307A012803D1B16906A823F087FC06A8009004AF0197B06A407840F0A4 +:20300000300002900999089BB0894A4611F0F2FF48460CE0B06A80F805A021F0B3FD06E096 +:203020004FF00009F4E70999304610F085FC099009980FB0BDE8F08FFE0401207A010020F9 +:203040002DE9F04FAD4C04F12C000768ADF1540D17B1002087F84500DFF89C82002517F1C5 +:2030600048030BD0BF6DA34E73612FB940460068D0F84C05804773695868706023F05AFCAE +:203080001390082014F086F91AF0E6F8464610B181A023F0CBFD1CF0C3FB684623F03AF8F4 +:2030A0000427284669468DF8007023F0ADF9206422F072FF09A823F0FFF8284609A98DF8B3 +:2030C000247023F001F9A06322F070FF0DA823F003F928460DA98DF8347023F005F9A16B9D +:2030E000E06319B974A023F0A1FDE06B10B977A023F09CFD206C10B979A023F097FD306872 +:20310000D0F8E00380473068D0F8180280473068D0F8F0028047404600682F460726A03083 +:2031200001687B5823B11846804740460068A030761E07F10407F3D1D0F8B8028047EB20ED +:2031400023F044FAE06A2F4670B105A8FF21082218F044FEE06A05A9082221F0EDFF04F1E9 +:203160002C06012818BF3768654A0CCA05A8391C80E80C0021D1082016F022FF5FEA0008F1 +:2031800056D0A8F10206032723F005FB06F8020F7F1E4FEA20207070F6D13020F82706F8F2 +:2031A000020F4146082204F1480088F8077022F0F5FC40461EF05EFC04E004F148000822DD +:2031C00022F0ECFC0120082105AA23F0A7FA04F14806002818BF092826D121F08AFC8008BF +:2031E0001DD205A8FF21082218F0F8FD07AFFF210822384618F0F2FD0120294608223B463C +:2032000022F0CEFF80B9384605A9082221F094FF28B930463946082222F0C0FC04E00120C9 +:203220000821324623F080FAE22031461EF0C2FD21F05FFC400834BF2F1C0127314E55200C +:20324000012106F1320223F069FA18B917B1284620F0FCFB2C4EE22006F1400121F010FBCD +:2032600038461BF0AFFD05A82946102218F0B6FD707830F001004ED1DFF8908005A9102221 +:20328000404621F059FF002842D105A84146102222F084FC3FE0C04652616E646F6D5F73B4 +:2032A0006565644175746F6D617469632829206661696C656400C04641455343434D206F22 +:2032C00070656E206661696C656400C0414553454342206F70656E206661696C656400C0AC +:2032E00054524E47206F70656E206661696C656400C046C0D405012014010020D4DB002078 +:203300001083020068060120E40401207880020005A820F06BFB6220102105AA23F0FEF9F7 +:2033200028B927B16220102105AA23F0FDF905A82946102218F052FD384612F03FFD38468A +:203340001FF056F9384613F083F87078A8B905A820F04CFB40F20110102105AA23F0DEF9B9 +:2033600030B92FB140F20110102105AA23F0DCF905A82946102218F031FD1FB12846012195 +:203380001FF024FD282016F01BFE0028606400F04081206B616B221D1AF07AFDCA49087057 +:2033A00010211BF055FE616C201D0860206B616B04F108021AF06CFDC2490968D1F84C139F +:2033C0008847616C04F108004860206B616B04F10C021AF05DFD0DF071FB616C04F10C00B7 +:2033E0008860206B616B04F110094A461AF050FDB64F7870B18EBD70381D0180303006F113 +:203400005001119007F1340023F07AFADFF8C08296F8230006F148032946FB604FF4B472C8 +:20342000387008F5057018F0D9FC04F1340B04F1300A626CDBF80010DAF800003C2308F553 +:20344000057C0C324FF6FE7E5B1E2CF806EBF9D1C2F8009004F114021AF01AFD9F4B9D494E +:203460007B629D4A08709E4B606CBA6004F11802DBF80010BB6204F114030361DAF80000F0 +:2034800012921AF005FDDFF85C9289F80700022289F824204FF6FE70A9F81C0022F04EFB7B +:2034A000914811990560AF4823F02AFA4046FF210E22801C18F092FC8C488E4B83608E4A86 +:2034C000C2608B49416005708C4B03618C4A42618E4939618B4B83618B4AC2618C4B7B6156 +:2034E0008C4ABA618E488C4B8C4AFB618E4910618C4FD16009F1300097601EF0CDF81EF0A6 +:2035000065F8984809272C307F1E40F8045BFBD14F46F87948F201011CF0F0FEF8794FF4F2 +:2035200000411CF0EBFEF87948F221011CF0E6FEF87948F222011CF0E1FEF87920211CF021 +:20354000DDFEF87921211CF0D9FEF87922211CF0D5FE606C12994161DAF80000DBF8001099 +:2035600004F11C021AF094FC704F48F2150138701CF0C4FE387838211CF0C0FE6D4B6E4AD6 +:20358000FB606B483A61616C786102234FF6FE72DAF8000087F8283004F11C038B61DBF886 +:2035A00000103A8404F120021AF072FC634904F12003634A0870634F606CDBF80010C36140 +:2035C000DAF80000176004F124073A461AF060FC65497378087023B991F833300BB10221E4 +:2035E000F17148F202011CF089FE606CDBF800100762DAF8000004F128021AF049FC2070B1 +:203600005149087022F0C4FF4870616C04F1280048621BF073FF12F00FFD139823F00AFB29 +:203620000FF03EFA21F086FB26480068D0F8D40090F8430021F090FB22480068D0F85824D2 +:2036400029460120904722F079FD40481D4F05707868C068007830B938460068D0F858247F +:2036600028460146904717F051FA3A4F3D703848058145818581C581058245828582C58282 +:2036800005832B464583344C858307210360344A43603248257021F0A3F816F0BFFB1EF0AC +:2036A000E3FF1DF041FA7078022807D13078012804D14FF4004001210CF070F915B0BDE8DC +:2036C000F08FC04614010020671B0120E006012020010020800A0120892001004D81010021 +:2036E000F9620200C40301204805012020090120DDC700004941020099D901003B2E0200BF +:20370000F14602006913020019470200D5690100D54401003D4B02009DA40000FC09012046 +:20372000F1420100E9B40100193401001C070120152A02001540020031480200C40A012023 +:20374000D00A0120751C020028180020701B0120D8180120691B0120681B0120EC00002069 +:20376000B9690200D8030120680601202DE9F04F0446B54DB5480021ADF14C0D001D2E6831 +:203780000768A0780C910146102910DC102900F0AC80002900F0AE82491E012940F2FD81BA +:2037A000891E00F05581491E00F0248144E3113966D0491E1ED0491E03D0491E00F042834E +:2037C0003AE3207967798DF81000E0788DF8117022F02CF8002808BF022005D00C3004A95B +:2037E000022222F0DBF90C988DF82000132108AB01223BE3204634460421C61C304621F0E0 +:2038000069FE0C9F0121002C35D0A268904203D02468002CF9D12EE06CB3361D304622F00A +:20382000FFFEB778804657B92868844218BF251C2068286020461EF01DF90C991BE0B81C0A +:2038400016F0BEFB051C04BF10210C9F13D00C9828706F7061683A46A81C414422F09EF9B0 +:20386000BE1C642012212B46F2B21EF0D1FD28461EF000F9FDE23170334612217770F4E268 +:2038800020460126C41C8DF82160204622F0C8FE6F68A3780FB3B3B938680090686818300F +:2038A0000190787E0290B87E03903969BA8AFB8A381D08F0A5F98DF8210068681EF0DAF87A +:2038C0000C9868600CE03968E41C1A4609180846214622F063F90C9800E010208DF82100F1 +:2038E000112132460DF12103C0E22546BD4C89462D1DA07815F8011C002937D0491E10D014 +:20390000491E02D0481E67D064E0287822F08CFD002869D041680978E170007820710C98C9 +:2039200054E02D7800285FD1E1200DF1230120F0A7FF9DF8230085424AD00126A670304631 +:2039400022F024FC0C9809A98DF8240052201EF031FA28461CF05AFC002839D0657020781D +:203960003146642222F0A8FFBA202FE000283BD1E1200DF1250120F083FF9B4E06F13C079A +:203980009DF825103878884222D0DDF8308001255220A5700DF126018DF826801EF00AFA5D +:2039A00096F83C000A2805DD1B2803DAE12039461EF000FA8DF8265052200DF126011EF0E1 +:2039C000F9F9404622F0E2FB4046A07002460CE00C9A0AE00220F9E7284622F021FE0C9ADF +:2039E000A97822F0FBFE00B901228DF822200DF122031FE210218DF82710E1788046DFB138 +:203A00007A681278384691420ED03F683FB17A681278914205D038463F68002FF7D1022022 +:203A20000BE03968016002E0B1493868486038461EF020F80C9800E001208DF827000DF182 +:203A40002703CDF83480A5E0FC0A0120BC0A012001218DF828100C990D900C2204A818F02D +:203A6000BDF925460224ED1C8DF81840284622F0D7FDAF1CADF8100017F8010B8DF819008C +:203A800017F8010B22F0D0FC8146384622F0C8FDBD1C0E9015F8010B15F801AB15F8018B2F +:203AA0002E788DF82900700016F08AFA0F9000286CD06D1C4EB183463746284622F0B0FDBA +:203AC000AD1C7F1E2BF8020BF7D1B9F1000F57D0CDF8409015F8013BDDF83C903746AB46BB +:203AE0000C2FBDF8105011934ADA28461BF00CFBC82815D14FF6FE701BF006FBC8280FD1C9 +:203B0000C34890F8CC38012100F6D40C0C981CF8082B9342C4BF131C081C491CC829F6DB59 +:203B2000C74C4FF6FE7604EBC0046068668018B11DF0A0FF0C9860606FB17E00304616F065 +:203B40003FFA6060002808BF102419D060684946324622F023F8C9486580007867700DF121 +:203B6000290620701099CDF800B00E9A0196119BCDF808A004A8CDF80C8008F041F8044698 +:203B80000F988DF828401DF075FF02E010208DF828000AAB0D9881464CE194F801B00121A4 +:203BA0000228814604F103048DF82B101ED114F8010B03288DF8180005D0204622F030FD0F +:203BC000ADF8100004E004A82146082221F0E6FF083414F8010B8DF81900204622F020FD92 +:203BE000A41C11E0C40A01205001012002208DF81800204622F014FDA41CADF8100014F8EA +:203C0000010B8DF819000C98ADF81A0014F8010B22F00AFC8046204622F002FDA41C0D90CD +:203C2000B9F1020F14F8010B14F801AB14F8017B8DF82A001CBF14F8016B06F10A0006D197 +:203C4000204622F0EDFCA41C064606F11400B8F1000F80B240D0FA2830DD6C68002C3BD1B7 +:203C600006F11C0016F0ACF904466C6024B30C9804F11C0504A98DF82B000C222560201D92 +:203C800021F08CFFC4F810800D98A082E6829DF82A50257684F819A0A7760F23E376784CC2 +:203CA000207808214FF47A7222F006FEB8B1207808211BF0CDF912E010200EE000940DF161 +:203CC0002A000D9A019041463346CDF808A004A8039707F095FF00E002208DF82B002BF077 +:203CE0001F0BBBF1200F40F0C4800DF12B03A1E0BC0A01204FF0100A89468DF82CA05046A8 +:203D000016F05EF9071C00F094805D48E41C7860207822F089FB00287CD120780C9E387015 +:203D2000B04687F80C80142016F04AF90028B8606BD014F8011B017062782178A61C01EBD0 +:203D40000221418031787278B41C01EB02218180817914F8022B01F0F00102F00F020A43A7 +:203D60008271B96814F8010BC871BD68EB79464673B1580016F024F9A860B8688568002DE8 +:203D800008BF564604D03046BA68D179814231DC2078B9680873BD682B7B73B1580016F0B9 +:203DA0000FF92861BD682B69002B08BF564606D0641C4046297B814210DC102E2BD1A868B2 +:203DC00010B11DF057FEBD68287B18B128691DF051FEBD6828461DF04DFE1CE062782178E8 +:203DE0002B6901EB022123F81010BD68A41C421CD0B2DFE7637821789268451CA41C01EBDF +:203E0000032122F81010E8B2BEE7564603E0C04620010020B8268DF82C603EB938461DF0CE +:203E20003BFC8DF82C009DF82C0010B138461DF021FE0BAB4946DBE402200C9019E0C046AD +:203E4000EC0900200C988DF810008DF81100E07804A921F09DF89DF8117014219DF81000E3 +:203E60008DF81D7007AB8DF81C00022264201EF0CFFA0C9813B0BDE8F08FC046FE040120AA +:203E8000671B01202DE9F04FADF13C0DC54C0B90C3480C91002147780E919FB137F00106F2 +:203EA00008D0022F12D1207900F0F80141F00201204605E02046017901F0F80141F0010118 +:203EC000017103E0207900F0F8002071261D3078402537F00102657100F00700307005D1BE +:203EE0008E20A0716FB940F0010009E0022F08D1AB4980200978A071012902D140F008005C +:203F0000A0710E99F170317150256572A020B071F171B072F172A089099140F43050A0813A +:203F20002174B2B1022F1CD1012019F00DFE28B9206820F00F0040F0020004E0206820F000 +:203F40000F0040F001006FF30F1048F22021014306E0216894484CF21017084047EA0001B7 +:203F60002160934B9149A0791F780A9381F8320067B90E981AF026FF8C4890F83200000984 +:203F800011D30E9808A98DF8200009E0084690F83200000907D301200DF121018DF8210086 +:203FA00052201DF007FF1BF0A9FA20F0A2FD800838BF0E9803D30E981FF048FD01200028E1 +:203FC000DFF80CA30D9040F0D8800FF031FE5FEA000B40F0C380754ADDF83880212074211F +:203FE0002432174622F09AFB002859D12120414674223B4622F0D4F8002851D16B48408F8C +:204000004FF6FE7181424BD0684890F84A004FF00108082806D0042804D010F0A1FDDDF8CB +:2040200038803DE0C14642200DF122018DF822901DF0C0FE07F12F0143201DF0BBFE07F1D6 +:204040002C0147201DF0B6FE07F11C014A201DF0B1FE07F11A014B201DF0ACFE07F124017E +:2040600028461DF0A7FE07F1160153201DF0A2FE07F12D0154201DF09DFE07F11801E1209D +:204080001DF098FE494890F83200000938BFDDF8389052200DF122018DF822901DF08AFE36 +:2040A0000E9D17E0DAF804100E9AA80000EBC5000C23401881460090294601201EF0A6FB5B +:2040C00030B999F80000FF2804BF099889F800006D1CADB23248BAF800104078A942E1DCD6 +:2040E00030F0010001D10FF0A7FC9548001D006800B180471EF000FCB8F1000F1BD022F092 +:204100005FFA0A99888318B9307800F0F800307023484078022818BF012104D1234A09986E +:20412000032182F84A000A98393741703946143022F0E6FB01E04FF0090B804D0999184F14 +:20414000A81C0180787818B91DF062FA38464078BBF1000FA94605D10E9904E01048DFF880 +:20416000DC91407801210D9110490A9D91F83C20012707FA02F1E96087E00FF059FD10F054 +:20418000EFFC0A4A21207421243222F0CDFA02A8FF210C2217F022FE0E9D574612E0C0467C +:2041A000E40401204C1A01200000FFFF50010120C4030120294601200C2202AB1FF068F93C +:2041C0006D1CADB23888A842F4DCB848407830F001000ED102A8FF21102217F0FFFD0E9D1B +:2041E00003202946102202AB1FF052F96D1C332DF6DB5348006800B180471FF08FFF099881 +:2042000006220E99ADF8100002A817F0E7FD142015F0D6FE5FEA00081BD0A34810300768A2 +:20422000A7B103270225A8B202A90622404421F0B5FCAD1D7F1EF6D104A94046022221F0CC +:20424000ADFC4C201421424622F06EFA40461DF011FC182015F0B4FE071C10D00E9D18229B +:20426000294617F0BBFD0620294618223B461FF00FF96D1C032DF6DB38461DF0FBFB17F097 +:2042800013FF8A48DFF8B49040780D99864D012966D1B44F2437E8B1012807D002280BD190 +:2042A000307800F0F80040F0020004E0307800F0F80040F001003070A34820F08BFE00284B +:2042C00008BF09980BD00A9A04210320917206E0DC0A01203178022001F0F8013170DDF894 +:2042E000288088F8010022F056FA0B996F4E00F07F000818643080B20E90F06B0221C8F8A1 +:204300000C00FF201EF062FD96494FF6FE70431C48870E46F0870998A1F848301EF048FE74 +:2043200062484078012810D10C9801280AD0099902A8082217F052FD02A804E0100A0120D5 +:204340003409012009981DF015FD212074213A4622F0EAF9099802211EF038FD534840789A +:20436000DDF834A018B9A08940F00100A0812F6987B9122015F024FE0646002E2E616ED0D0 +:204380004FF6FE70B61F0327411C26F8060F7F1E7180FAD1BAF1000F61D1099906AB4C20D7 +:2043A000022221F0FDFE002852D1BDF8180000284ED004284CDA182015F002FE03274FF077 +:2043C00002084FF6FE7B0646099C2B691FFA88F14C2006221B1921F0E3FE78BB2869015B24 +:2043E0008B452BD056B300962018099A4188182306201EF00BFA30692A6900F2E93333616D +:204400001019418805F11402880000EBC10029691350081973694188880000EBC1008018E3 +:2044200029694360081941881822334606201FF02FF809993046182217F0D0FC7F1E04F197 +:20444000060408F10608C0D116B130461DF012FB164B099971200822483321F0A1FE13481F +:204460004778381C06D121F069FB21F055FF0F48477817B121F048FF18B10120E870099E59 +:204480002E713248324EC9F80C00C9F810607FB137F0010003D120F0B3F82F480BE020F02C +:2044A000AFF82E4807E0C046CCE80020E404012020F0A6F82A482749BAF1000F086019D07A +:2044C000284890F86500A8B92748407890B9DDF82480622102AA404618F068FB02A84146E4 +:2044E0001FF078FC404614F05FF902A81022414617F074FC0A98006950B10A9C1034076818 +:2045000020681DF0B7FA0A99384600280861F6D10A9A099F01200146107002F109045772DF +:204520008520093222F0FAF828B9852039460122234621F035FE0E9821F040F920F034FB93 +:2045400050460FB0BDE8F08F1407012001F00000E9630200C808012091780100995402007D +:20456000F181010050010120E40401202DE9F04FBE48C84CADF1340D069025694068012111 +:204580004FF0E047C06809934FF000080170C24808921F4080F800804FF0020000EA020011 +:2045A00008BF002840F0E682DFF8F092DFF8F0A21E4611464FF4803018EA060700EA01000A +:2045C00008BF002833D141464FF4003011EA060700EA020008BF00280ED137464FF48000EC +:2045E000394000EA020008BF002800F0B78285F8048019F0B9FDB1E285F80480EB201EF0D1 +:2046000091FE4A46514682F800800878862801D11EF00AFF22F08EF9E1690A6882F8048080 +:204620000968E16122F006FB21F09AF996E285F804801EF0DFFE81262778A4F80C8099495C +:20464000A770994D0860994B2E70FF221A702169069E087A801E81B230684A46D0F8000156 +:2046600082F80080C0890B918842C0F26B82E1690831096804F1180001600426A6810B989C +:20468000657EA17E04F11902C01E80B2069EE37E0B9005EB01205178C1F301193168608136 +:2046A00001F1B80CDCF80010237109780792002908BFB9F1020F00F04582B9F1020F00F3A2 +:2046C000418219B110F0070F00F03C82667800F00705AD1E022D08BF002E00F0338231B139 +:2046E00051460978862902D1002D40F02B82001300F00200022864DA35435AD1DCF81C0016 +:2047000090F88300022851D0E1690C31097805A801700527A78122F00DF95546064628782A +:20472000862840D106980068403001680F6837B9D0F80C05804706980068006C07689DF95D +:20474000140022F035F9787706980068016C096881F81E80006C9DF914100068C1773046DF +:2047600022F068FA2679678922F0E4F851460A7807F01007862A15D1BA4D05F11E031A88CB +:20478000521C1A8087220A7022F054FAE879B04206D11FB9404615F043FE07E01B20FAE7BD +:2047A000E920F8E70646304622F044FA21F0D8F8CAE151460878862803D11EF035FEA7787A +:2047C00066788FB186B9012F00F0BC816089022F03D110F0070F40F0B581032F05D100F0BD +:2047E0000701032901D0ADE16089010980F0AA81011301F00201022902DA810A80F0A2816B +:2048000007994978C1F3810BBBF1010F4FEAA1110A9100F09781012900F09481B9F1020FC3 +:2048200014DA00F00701012918BF03290ED1BBF1000F0BD10A9F002F00F084810699096812 +:20484000AC3109680F78002F00F07C81BC49B9F1020F0DD00A9E11F80B708A5DB918CFB265 +:204860005EB3C10929D3BF1E12E0C046140100200A460A990BEB0207891809793A79521825 +:20488000C109D7B214D20A995BEA010615D0BF1CFFB212E0B4180120B40A0120711B012014 +:2048A000741B0120501B01206F1B01202D1A00200A995BEA010608BF02270B9AC0F3002152 +:2048C000781A61718242C0F23D81069E1046C01B4018316880B2D1F850122081743080B2A6 +:2048E000884700286678606100F02C814146742217F074FA84F8038062891EB9C14902F036 +:2049000020000870BF4861790678C446002E30D000292ED102F00700032808D0012828D122 +:2049200006980068D0F8D40090F882600EB306984068406906781EB121F060FBFE2815D0F7 +:2049400006980068D0F84C02804750B906980068D0F84402804720B96289617994F803C0A3 +:2049600007E00420E0706289617901E00420E07084466569268905F1740305F17400AB6594 +:20498000079B686093F801A02E812089CAF301190029A5F85C001878AA8100F0780049EADA +:2049A00000004CEA000028744FF0FF06AE730CBF2079404685F83AB085F849000A9885F88A +:2049C0003000A089002FA0EB010086B2A68100F0B480E169E78068463A468919083114F082 +:2049E00095FABF19B8B2A0812846017C4FEAAA0212F0030F02F003076D4601F0400B42D0E4 +:204A0000B9F1020F434601D1C9090BD29DF801209DF8001001EB0221A0F844100DF1020576 +:204A2000A0F84210814EB0F84410B6F846208A4203D04FF6FF728A4223D1032F14D06A78A0 +:204A4000297801EB022189B24186B6F84420AD1C01208A4214D04FF6FF728A4218BF181C6B +:204A60000EE0C0460418002060692946323021F047FF60693B363146323020F07FFF083537 +:204A80000346002B56D00798407886111ED06169B9F1020F03D0087CC00903D309E05BEAF7 +:204AA000070306D16A782878AD1C00EB0220A1F84200032E05D068782A7802EB00220A85BC +:204AC00004E060692946283021F01AFF06990968AC310A686089167886B1B9F1020F0DDA89 +:204AE00000F00702012A18BF032A0BD162692FB94F4BB2F842201B8893421BD100F00702FC +:204B0000032A05D0012A18D1886A90F88200A0B1D1F89C116069884778B90798817867698B +:204B2000407884F80380C1F3011100F078000843387402E019F018FB06E00BF087FC03E054 +:204B4000D487020020F0FEFE21F0F4FEE1690A6882F804800968E16122F06CF80899099EBE +:204B6000202047460840374008BF002830D020F0B1FE2DE02F4991F90000002803DD91F95A +:204B80000000401E08702C4991F90000002803DD91F90000401E0870114640461E464FF058 +:204BA00080770840374008BF00280DD0234991F90000002803DD91F90000401E08702048AD +:204BC0000121017021F0CEF885F8048019F0CCFADFF864C09CF90070B7B108994FF0E0472C +:204BE0000220374000EA010008BF002816D09CF90000002812DC06980068D0F84C058047CB +:204C00000CE0C046711B01200E48069F80F800803868D0F85824414608469047069840682C +:204C2000C06880F800800DB0BDE8F08FD40501201A060120B70A0120B60A0120B80A012092 +:204C4000B50A0120B20A01202DE9F04F0446B54EA578F06A4FF0000BADF14C0D2946312974 +:204C600011DC312900F0E280DFF8C882B24F142914D91C3900F06281491E00F01B811339E8 +:204C800000F0E9807FE2323900F0BA80491E69D0491E012929D9891E17D074E2DFE811F0E6 +:204CA0006402A502A102500299027302730224024E010A010D02F8018F0273028902DE0175 +:204CC00073027302C901B801760240B1C06830B1E01C21F0A5FCF16AC968884700E00320E9 +:204CE0008DF8380036210EAB61E201270028A8468DF839702ED0406A60B3204602A920F05C +:204D00009BF9342D044618BF584602D121F088FCA41C2578E0B902A821F07DFA641C0128A6 +:204D20000DD1BDF80C00294622461FF06DFBBDF80C00012803D1E22021461DF03BF8F06AC5 +:204D4000466A02AB93E803002A462346B04702E0042000E003208DF8390041460DF1390320 +:204D60003D46A5E0002840D0C06900283DD0204602A920F061F9054602A821F04CFA0128A5 +:204D800018BF584603D1BDF80C0021F041F90446284621F045FCAD788046F82DA8BFF72521 +:204DA000A81C5FFA80F9484615F00AF9071C1AD0A4B9F06ABE1C02ABC469009693E803003B +:204DC00042462B46A047041C08D1584638704A4633213B467D7061201DF01AFB38461CF035 +:204DE00049FE1CB90DE2102400E0032408A85946022216F0F3FF8DF82040332108ABFCE139 +:204E000068B1806A58B104A9204620F015F9F06A826A04AF97E803009047014600E059463D +:204E200002A820F0AFFE32210422D8E160B1806950B1204602A920F0FFF8F06A826902AFD0 +:204E400097E80300904700E003208DF83A0031210DF13A03ABE101258DF83B5010B30069BC +:204E600000B3204602A920F0E7F8042120F032FB5FEA000814D015F0A3F8F46A071C14D0E3 +:204E80005946424616F0AAFF246902A803C842463B46A0478DF83B0038461CF0EBFD04E034 +:204EA000052000E003208DF83B0030210DF13B032A46A3E1E41C8DF83CB0204621F0B0FBF6 +:204EC000A846092D064609D0A01C21F0A9FB0746201D21F0A5FBA41D054602E0A778E57873 +:204EE000241D242E03D12088352606AC069030461FF006FA7919884216DB27B93046294669 +:204F000022461FF081FA30462946224621F00CFC30B9012E0BD1E22021461CF04BFF04E0A2 +:204F20000A2002E0D4DB002002208DF83C0041460FAB3CE1671B01200C8802002646F61C9E +:204F4000304621F06DFBA9468046B8F1240F46D021F05EF80446082D08BFB67803D0B01C41 +:204F600021F05EFB064640461FF0CAF986422BDA5CBB801B85B2F82DA8BFF725A81C5FFAA8 +:204F800080FA504615F01CF8071C1BD0B81C59462A4616F023FFBB1C404631462A4621F07A +:204FA000FFF848B958463870524649463B467D7061201DF02DFA00E00A2438461CF05AFD7A +:204FC0001CB91EE1102400E002240AA85946022216F004FF8DF8284049460AAB0DE13520D1 +:204FE0005946042207AB21F0DBF838B9BDF81C20584602210425ADF8262002E001205946FD +:2050000002258DF824008DF8251009AB08214FE7E01C21F005FB242802D01FF071F900E06F +:2050200058468DF82C00001213210BAB8DF82D00E3E0E01C21F0F4FA0546601D21F0F0FAF2 +:205040000146242D03D0284621F0EBFB00E058468DF83F0012210DF13F03A8E0E078211DAD +:2050600070B1401E0AD10878012805D020B1522010A91FF005FC08E0522002E0022002E00C +:20508000E0201CF097FE8DF840000F2110AB8EE041460125087814F8031F8DF842500429B2 +:2050A000A8BF022003DA37F8111019F03BFD8DF842000B210DF14203FAE6E41C207804281F +:2050C000A8BF02200ADA601C21F0AAFA267841460246087837F8161021F0EEFB8DF843002E +:2050E0000A210DF1430362E0E01C21F099FA0646601D21F095FAE779E51C0146242E19D013 +:20510000B94205F1050510DD30465A4621F006FB8DF844009DF8440009280ED16FB1304637 +:2051200039462A4621F000FB07E030462A4621F0F5FA00E058468DF84400072111AB36E066 +:205140000127E41CE2208DF8457021461CF032FE30B938460821224621F0E6FA8DF8450095 +:2051600003210DF14503FBE5E078284C30B1401E47D121F031FA01202060FEE721F02CFAC9 +:2051800001202060FEE74FF0020B3AE094F903001F4F8DF83D003868D0F830240DF13D016B +:2051A000E020904714210DF13E038DF83E00012224E08DF841B00E210DF14103F7E721F0E4 +:2051C000EAFA8DF830000C210CAB00128DF8310013E0E22002A91FF053FB0421082202AB91 +:2051E0000CE00C4B02210A2208E05920062701218DF834000DAB8DF83570022261201DF020 +:2052000007F9584613B0BDE8F08FC0467C05204314010020C0870200D249D14A03462DE90C +:20522000F04301F108009D78177800680024ADF1440D2A46402A2ADC402A00F0DE81202A3F +:2052400014DC202A00F010820A2A45D9103A00F03282521E00F02582D21E00F01982521E60 +:2052600000F00F82501E00F0048263E1B2F1210000F0F481401E00F0EB81401E00F0DE81F5 +:20528000401E00F0D481401E00F0C98152E14A2A11DC4A2A00F08E81413A00F0A381D21E4D +:2052A00000F09C81521E30D0D21E00F08B81521E00F084813EE1B2F14B0000F06881801E9C +:2052C00000F06181163800F04F81401E00F039817C3800F031812DE1121E00F0CE80521EA4 +:2052E00070D0521E00F02A82521E00F01582521E00F00282521E00F0F281521E41D0D21E43 +:2053000000F0DE81521E1DD014E1184606A9C01C20F05EFB2E468DF81E0048B99DF81800D5 +:20532000BDF818708DF81F0038128DF8200005E00DF11F00FF21022216F050FD03220DF1E1 +:205340001E031CE0DB1C5F782E460D4638B9684620F058FF012069460DF0B4FCA8603FB120 +:20536000052F03D064211DF083FD03E0012129701DF012F88DF836400DF13603012235468F +:20538000EFE118468DF83740C71C384621F048F9BF782E46C0F304213FB9052903D04FF66F +:2053A000FF7181420BD1204607E0052903D04FF6FF71814203D14FF0FF30D64908600DF151 +:2053C0003703DBE7202014F0FBFD061C00F0CD81FF21202216F002FD731C0120214608228D +:2053E00020F0DEFE751C071C18BF01272146042205AB842020F0D4FE083560B99DF8170049 +:2054000028709DF8160068709DF81500A8709DF81400E87001E047F002078320214602225F +:2054200007AB20F0BDFE2D1D38B99DF81C002870BDF81C000012687001E047F00407ED1C84 +:205440006120214601226B1E20F0AAFE08B147F008072146102262202B4620F0A1FE08B10D +:2054600047F01007012120223346672037701CF0CFFF30461CF0FEFA77E1264637F0010093 +:205480008DF83C600AD10FA818F070FF9DF83C1080460E2000EB4100C7B201E0A0460E276C +:2054A000384614F08DFD5FEA00093DD0054621460822012005F8016B2B4620F071FE21F01A +:2054C0007FF80835072305F8010B001205F8010BA84A05F8013B1078A74905F8010B4B785B +:2054E00033F0010316D19DF83C0028709DF83C308BB141466D1C20469DF83C2082420ADDE6 +:205500000A782A7031F8022B401CC0B212126A70AD1CF1E72E70672021463A464B461CF003 +:2055200077FF48461CF0A6FAB8F1000F00F01D8146469EE7022418E122464720E02113461C +:2055400011E11846C11C4A7A087A00EB02208A7A8DF82E400EF0D8FD0DF12E0300E1C046EB +:20556000E5040120CCE8002018468DF82F400822C01C0146684620F011FB68461AF0A0F894 +:205580000DF12F03ECE018460FF0C0FCEDE0D91C6846082220F002FB8DF80840CDF80CD0E1 +:2055A00002208DF8090002A816F022F80CAB8DF83000D5E018461CF049FFD6E018461FF07B +:2055C00072FAD2E0DE1C307871781FF069F80222307000127070294630466FE0184612F068 +:2055E000F3FFC2E0D81C21F01BF8ADF80200684616F02EFC01AE0822EDE7D91C01A8082205 +:2056000020F0CCFA684618F073FBBDF802000DF122038DF8220000128DF8230016E0F5204A +:205620008DF827400DF126038DF826000EE0F52011460DF131038DF831003AE0F520FF2715 +:205640008DF82A000DF12A038DF82B70022288E0F5200DF132038DF8320081E0F5200DF151 +:2056600033038DF833007BE0F5200DAB8DF8340076E068462146092216F0B0FB16210922B2 +:205680000DE068462146062216F0A8FB152105E068462146062216F0A1FB142106226E462C +:2056A0009AE7D8781CF02CFF11210DF135038DF83500012256E01A78D81C1021034651E036 +:2056C00021F0BCFA054620F057FF2C496843B0FBF1F1684620F056FA09210422DFE7DE1C87 +:2056E00062201EF00DFE01463246622021F01CF80EAB8DF8380033E0DE1C61201EF000FE99 +:2057000001463246612021F00FF80DF139038DF8390025E0900A0120D81C04211FF0DAFE79 +:20572000049084201EF0ECFD014604AA842020F0FBFF0DF13A038DF83A0011E0D81C20F0A8 +:205740006FFFADF81A0083201EF0DAFD01460DF11A02832020F0E8FF0DF13B038DF83B009D +:205760000122294667201CF053FE204611B0BDE8F083C046C4030120E404012040420F00EC +:205780002DE9F04FCF48D04CDFF840830F46390CADF1240D80F06582790927D30023037015 +:2057A000D7494370184620F065FFD649012020F061FFD549062020F05DFFD449072020F090 +:2057C00059FFD849082020F055FF0522D6498DF80C300DF10D0020F0E1F94120802106229E +:2057E00003AB1CF015FE87F0100044E2B80828BF87F0020080F03F822068390931D217F406 +:20580000706F08BF002000F03682380B04D3002020F008FC87F40067F80A04D3012020F0E0 +:2058200001FC87F48067B80A04D3022020F0FAFB87F40077780A04D3032020F0F3FB87F462 +:205840008077384617E22168884205D0016829601CF010F9286804E0016821601CF00AF93E +:20586000206808BB606858B1C27EC17E521E491ED6B2C17626B960681CF0FCF80020606070 +:205880002668002E08BF00280BD04446207808214FF47A7221F010F818B12078082119F05C +:2058A000D7FB87F00800E6E1017B491E0173C9B20029C8D005460068D3E70546D9F8046050 +:2058C00028781A280EDC1A2854D0401E00F06C81401E00F02B81801E00F0B581801E00F00F +:2058E0001781BBE1243800F0A881AD3800F09E81801E03D02A3800F08B81AFE1A87C09304F +:20590000C0B2804614F05CFB061C00F0A781A97800F8011B6988091200F8011B99F80C10B8 +:2059200000F8011B99F80E1000F8011BB9F80E10091200F8011B99F8101000F8011B99F83C +:20594000111000F8011B99F8141000F8011BB9F81410091200F8011BAA7CA96920F01EF9E6 +:205960004520FF21424633461CF052FD30461CF081F873E1B5F824A0E97B0AF114001FFAFA +:2059800080F820F02BFF002640B9A87B032805D0B8F1F00FD8BF4FF0810B16DD08F10A0013 +:2059A0004FF0820B1FFA80F8B8F1FA0F0DDD0AF1100014F005FB061C00F0508106F11000F5 +:2059C000A8EB0A0470601FFA84F8404614F0F8FA079020B9002E00F041813046A0E00446B5 +:2059E000A87804F8010B6888001204F8010B287904F8010BA888BBF1820F4FEA202004F8EA +:205A0000010B1AD1A87B04F8010BA87B032805D0A8792070E8880012607004E0A91D20462E +:205A2000082220F0BBF8E87B083404F8010B287C04F8010B288A001207E0A87904F8010B52 +:205A4000E888001204F8010BE87B04F8010B287D04F8010B687D04F8010BA87D04F8010B8A +:205A6000687E04F8010BE969204620F08BF8241DBBF1820F04D0002004F8010B504606E0F7 +:205A8000002004F8010B04F801AB4FEA2A2004F8010B0E480078DEB10B4909680A4B3160A3 +:205AA0004FF47A721E6008210F23337320F004FF20B106480078082119F0CAFAE869B06037 +:205AC000706807E088040120FC0A0120671B012020465444A96A524620F060F895F82C00C6 +:205AE00004F8010BA88D5FFA88F85946001204F8010B95F82E00079E2070442032E7C04664 +:205B0000D1E3010093350200351902004D370200A878401DC0B214F053FA002800F09E80BA +:205B2000064623E785280200C087020029790B2000EB4100C0B21FF009FA002800F08E8074 +:205B4000A9782E798DF80010EC788DF802608DF801400DF10301FEB1AA792C79EE880A706E +:205B6000022C4FEA26218DF804100DF1050113DB2A7A2C792E890A70032C4FEA26218DF83E +:205B800006100DF1070107D1AA7A6E890A7031128DF808100DF109012A7BAE890A703212FA +:205BA0004A701FF0D9FA59E0002E57D070788DF81500B0788DF816003078FA2819DC9DF822 +:205BC000150000F01E00162811DA2C499DF815000D4600F01F00820050194068091D30B15E +:205BE0008958304688478DF8140028B9BEE6012000E004208DF814009DF8150020F01F00CA +:205C000020287FF4B3AE60200021032205ABABE66878AE78EC788DF8180006AB8DF81960AB +:205C200003228DF81A404420802103E06B1C4520C02101221CF0ECFB10E0F0783346401D67 +:205C4000C2B26920F0E7F078401DC4B2A11E701CC9B220F0E7F8A41904F8010C48461FF01D +:205C60007BFA0748007819F0C5F95FEA00097FF424AE87F4004009B0BDE8F08F8804012045 +:205C8000671B01202DE9FC47D44C0F460646F80B80F00C826078B90F80F0AC81B90880F0D8 +:205CA0009F81DFF84C83F90A80F00281390B80F0CC80380907D2F80FC0F02E8227F08047C9 +:205CC00017F05CFD28E220F035FE81461FF084FA002800F0B480082020F0C0FC002840F02B +:205CE000AE80802020F0BAFC002840F0A880684613F040FA012803D10098002800F09F80D9 +:205D000094F84102002840F09A8000250126E8B220F0E2F948B1837A3BB1867290F9090005 +:205D200006FA00F0C0B21DF0DFF96D1C032DEED3032084F8240004F5CE7020F0F5FD484618 +:205D400020F078FFC34800252A460168056050F8081CD44940F8085C04F160001FF04BF981 +:205D600040460068006B8047A168401A010BE06AC1F1FF3282422CBF08444FF0FF30E062BC +:205D800094F8300020B12069E16AB1EBC02F25D91FF032FA294600B13146081C1BD0C2482E +:205DA00040F6090101804580417B06F00F0221F00F010A434273017B05F00F0321F00F01D3 +:205DC00043EA010202732946416020F0F5FA418811F4406FFBD084F83060E5621AF0D2FF99 +:205DE000D1482946056002201EF038FF02201DF03DFD112011F036F8207818B960685030D5 +:205E000020F0AEFDC948007810B90E2011F02AF894F8310020B184F8315005201DF026FD44 +:205E2000C348A06284F82450B4F9B400B4F9B610884214BF0220072015F0C2F802E048467C +:205E400020F0F8FE27F008073AE720B104201DF00DFD0020607065681CF0C0FD38B128460C +:205E60002D6A6FF4807100224FF00073A847E06858B140460068006B8047E2686168801A56 +:205E8000C860000BC8600026E660AA4904F1600000221FF0B0F80221D4F8A00084F82410DB +:205EA00018B104F1E00020F063FD27F4006707E720F040FD06461FF08FF9D4F89810002898 +:205EC000894600F08480002900F081809A49042504F16000002284F824501FF08CF8304669 +:205EE00020F0A8FE04F5CE7020F01EFD40460068006B8047E0604FF0010884F80180284677 +:205F00001DF0CCFCD9F810006060D9F81000816AC90803D3436A294600229847404618F0ED +:205F200031FE606880F81980606811F0BBF86568D5F808A040F60A02D01F564600F1010CD0 +:205F400000E01E46736833B119888A4203D0884218BF8C45F5D100217160727B08F00F03DD +:205F600022F00F0213437373D9F80C201288904224D06046904221D02B8F03B3E96305F14A +:205F80003802518095F8440001F00F0320F00F00034385F8443095F8450008F00F0320F0E0 +:205FA0000F00034385F845307260707B01F00F0520F00F0045EA0001717300E0E1605046EE +:205FC00020F0FAF9514640461EF048FE02E0304620F030FE27F480679EE0C04668F20020B7 +:205FE0000AF036F8D4F8A00008B927F0020793E08C010010514A116841F08001116020B114 +:2060000004201DF033FC0020607020F093FC80464B480068016804208847216A81421BD13A +:20602000357ECDB1A568BDB1D4F8A8506DB1E968098840F60300884204D0E9680988401CDB +:20604000884202D106F1140001E006F110001BF071FD06E01410044040F6C411316171617A +:206060002062404620F0E6FD1CF0B8FC80B1356A30466FF4807100224FF00073A847D4F83C +:206080009800002808BF47F0020701D017F076FBF569002130464FF080630A46A84727F083 +:2060A000005739E0ADF00100601A012020F042FCD4F8B06066B306F1280106C90A234FF099 +:2060C000E0450B40154008BF002B21D106F1280191E8000306F1280595E8060006F12803B2 +:2060E00022EA090221EA080183E8060020F0A2FDB16879B1B9F1000F08BFB8F1000F09D001 +:206100003069B6F93010B5684B464246A84701E020F090FD27F4804727B104F1E000394646 +:2061200020F026FCBDE8FC870000046086870200B546010035380100B9510200CC210840E7 +:20614000E00100102DE9F04FADF17C0D1B91C0491C923CC9064610A83CC00EC980E80E001D +:2061600000248DF84240327F8DF84340B08D8DF84D40D6F828C0ADF844401746ADF85A00B1 +:20618000F0898DF854706146ADF84A00087800F00303022B8DF8400000F3FD8123461D93B5 +:2061A000491C1E9343083CD200F00C0EBEF10C0F0CD043093CBF11F8013B8DF84230BEF18E +:2061C000080F04BF01238DF84C3001D08DF84C40BEF10C0F0AD0737903F00303012B0CD14C +:2061E00040F00C0073898DF8400004E04D780B78891C03EB0523ADF84430430911D24D78AE +:206200000B78891C03EB0523ADF846300B784D78891C03EB0523ADF8483011F8013B8DF83B +:20622000433011F8013B30F07F058DF855301ED00B7833F003058DF8413040F0A88103F01A +:20624000030EBEF1030F00F0A28113F0030F01F101010ED011F8013B00F00305022D8DF881 +:20626000573004BF11F8013B8DF8583001E08DF841401491A1EB0C017F1AFFB2BA42C0F265 +:206280008681D21B8DF85470D1B28DF84D100F4300F08181C10907D370891BF08BFB0028C2 +:2062A00040F079819DF8400000F00C012746091F08BF0127820932D301221E9279B3B28994 +:2062C00020F07EF9904202D1F08D000A0DD220F077F9904221D0F18D080A38BF101C07D35C +:2062E0009DF8400000F003032DE07089ADF85A20804620F065F9BDF85A10884205D0404636 +:2063000019F09BFC002800F04681A448026810A940469047002840F03E819DF84000F18D28 +:2063200000F003030A0A0ED2C2090CD39DF8412012F0030F07D100F00C020C2A03D0082AAE +:206340001CBF01221D92DFF86082022B00F00081012B00F0CE8010F0030F40F01C81904818 +:2063600090F82F00012803D1B579002D00F013819DF8540002221A900B0A9DF84240BDF8F2 +:2063800046B0BDF848A09DF855E09DF857C0DDF850908DF86420B0899DF84350ADF85C00D4 +:2063A00075D2454605F11C021468002F52D11D9F17B110A913F0ABFA7A484178022936D197 +:2063C0000078012833D1B07C002830D070891BF0F1FA022801D0707948B37449B2893C20A2 +:2063E0008B1F33F8064F944204D19C78F77CBC4200F0D180401EF4D16878891F3C234FF6B3 +:20640000FE7731F8064FA74202D05B1EF9D1C2E00A80F27C8A700C228A8004211BF00AFB8A +:2064200028B9687804214FF4FA7220F045FAF07C1E9F00901C9D0197594C0295B07C1B9B50 +:206440000390B4F8482017A910A811F02FFDA2E068850200307C002C8DF8560000F09B80C1 +:2064600020F0AEF8BDF85C20904240F0948030791E9F00901C9D01971B9A02951D9B039140 +:2064800096F8300010A9049017A8A04783E08DF820208DF822508DF82340ADF83010708966 +:2064A000ADF818008DF835E0ADF826B0ADF828A0CDF82C901A9B8DF836C0327CADF82A303F +:2064C00035798DF83220B47C8DF8335096F832108DF83440324F8DF83810B7F84800ADF84C +:2064E000240096F830708DF8377006A805F08AFD51E01D9FB58937B1080A04D2284610A9D2 +:2065000013F005FAB5899DF85400B6791030C0B21EF01CFD071C3ED07D81022038703E73A0 +:206520007C709DF854203A7207F110057D609DF84000800928BF01247C72149978681FF0DC +:206540002DFB45466D1C287839461AF04BF922E09DF84100B189454624352B6810F0030FF7 +:2065600010D110A807901248ADF8181006A91DF0FDFA80B1062141730068407B21461AF071 +:206580001DFE08E03BB110A82246984703E08DF84D408DF854401FB0BDE8F08FC40801201F +:2065A00050010120E4040120E0060120340300201B0602002DE9F04F4FF0FF084146ADF11F +:2065C0004C0D0E910F914FF0000910914E46089609960A96AD4C0B9604F1300B0C96E06815 +:2065E0000D96494611919EE0E068710306AA042320F0CCF8119903AA30461FF01BF802AA47 +:20660000304601211FF016F83046022101AA1FF011F8069800F0FF0028709DF81900069FF1 +:206620006870C7F30140E8709DF80E30AB702878FF2834D0BDF80C70FE2830D04FF6FF706B +:20664000B8422AD107A81BF03DFFE06871034FF088524FF4005320F099F8BA484FF40057A7 +:2066600050F8041D3F1FBFB2B1F1FF3F07F1885201D1032FF4D810684FF0010A514600F017 +:20668000FF03FF2B18BF8A46491C000A0529F6DB106007981FF06AFA5744EF8001E010201C +:2066A000E8809DF80A00BDF8087028719DF806302F81BDF804206B7129786A81E068FF29E1 +:2066C0002AD0FE2922D07E291AD07C2912D078290BD0702904D00D99491CC9B20D9120E082 +:2066E0000C99491CC9B20C911BE00B99491CC9B20B9116E00A990F96491CC9B20A9110E0B4 +:2067000009990E96491CC9B209910AE00899B046491CC9B2089104E009F1010710965FFADA +:2067200087F9761CF6B2E578B54200F323810D9F002F38D10898022835DA0C98022832DA1D +:20674000099802282FDA4D452BD00C98C0B90898A0B90B980A99084325D01EF019F8854256 +:2067600019DCB9F1000F14D094F83200FE211DF01DF8E5780120DDF8408015E0012013E06C +:20678000089860B9B9F1000F07D11EF001F8854201DC062008E0032006E00220EBE70220D7 +:2067A00002E0119800E004200028A07000F0CC80401E49D0401E00F0AA80401E06D0401E55 +:2067C00000F09880801E00F094800EE11DF0E0FF05460C2084F83C5015FB00B0817E84F87A +:2067E0003D10C07E84F83E000EF030FAE2782D1895FBF2F050432D1AE8B284F83200401C9D +:2068000090FBF2F15143401A84F831007C201CF0C9F8FF2810D17E201CF0C4F8FF280BD195 +:20682000FF201CF0BFF8FF2806D178201CF0BAF8FF2808BF94F8310084F833000C2110FB90 +:2068400001B0808BE0868FE00F9F08F1010090FBF5F184F832806943FF2FA0EB0100C1B287 +:2068600084F8311014D10E98FF2804D10C200E9111FB00B004E00146880000EBC100584452 +:2068800084F83310808BE086AFE0C046C01900203A46D0B2910084F8330001EBC2015944AC +:2068A000898B1729E18640F2A080C91F01AA89B212F058F99DF80F00C0083FD3119F0097E5 +:2068C000BDF81220E18E94F833000323891AC91F01AA89B209F012FB002840F08680BDF8F3 +:2068E0001010002900F081809DF8140019F054FF7BE0FEE7119EB54226DD304610F052FAAE +:206900006178E578761CF6B201436170F3E708F1010084F8328090FBF5F16943401A84F8FD +:2069200031005FFA88F010F03DFA6070FE215FFA88F01CF03BFF012084F83500119801F0AC +:2069400083FF52E00020001111986D1E84F831000C2184F8325010FB01B184F83300898BC6 +:20696000E1867E211CF022FF94F83200FE211CF01DFF3AE00C2116FB01B506AA0423710386 +:206980001FF004FF1199304603AA1EF053FE304602AA01211EF04EFE3046022101AA1EF0C9 +:2069A00049FE0699163501F0FF0201F0FF00FF2A09D0FE2A07D07E2A05D07C2A03D0782A2B +:2069C00018BF702A0AD1119F47B9C1F38542032A04D19622B2EB116F3FF41EAE304610F0F4 +:2069E000E1F9002860703FF4FFAD13B0BDE8F08F2DE9F04FC24CC44AE0790E46F108ADF14A +:206A00001C0D80F07281BF49330C07D3DFF8FCB24FF6FF7A9146AAF1010A42E00F78710BE4 +:206A200027D2300A28BF86F0800080F0D581B0080BD2300B38BF0020C0F0CE81381C01D174 +:206A40000EF04CFB86F40060C6E1012F18BF022F0CD168460021082215F0C0F9684610F0F6 +:206A600009FE18B12078022118F0F2FA86F00200B2E1012F18BF022F10D1401E0AD0801E9D +:206A80000CD1607A022809D10120607200201BF0F1F903E0217A00201CF0DCFB86F4805068 +:206AA0009AE1207818F0A6FA071C08BF86F4004000F092813D78D32D00F00B81E079A84200 +:206AC00020D094F82F000A2D0BD08E480378002B40F00781092D40F004810021B81C884716 +:206AE000FFE03871B9788DF812100322F9788DF814000DF112038DF813104F2080211BF031 +:206B000087FCEEE099F801006D1E00F09080AD1E40F0E780012818BF022840F0E280BD78B4 +:206B200075B36D1E40F0DD807D7820781DB31FF047FD4FF6FE720021824218BF0121081CAE +:206B400004D15846408F1146814209D010465D46ADF8100004A9A5F83AA053201BF02AF98D +:206B60001DF01CF81CF00AFA5946002081F84A0014F040FEB5E0022140F6B83261729DE0F8 +:206B80007D78002D4FD11FF0C3FD002201460BF10800E1600D4602601046002D3FD10029C5 +:206BA000E6D000280D46E3D080468D481EF012FA012809D0B9F830004FF6FF71814209D008 +:206BC0002988884206D022E0854805F10C011EF0D5FEE0B1BBF83E002989884201D182451A +:206BE0000BD199F8010030F0010302D1EB7823B90DE0022801D12B794BB19BF836006979BD +:206C0000884207D199F80600A979884202D028461CF004FFAD69B8F10108C6D1A8E7AD69FC +:206C2000401CC0B2B9E700201BF03CFD59E0012818BF022855D17D7894F838003DB194F8C6 +:206C40003710491CC9B2884284F837103EDB207A401E04D0401E36D0401E1AD041E01FF0BF +:206C600053FB78B994F8390000283AD1002102200D468DF808000246ADF8005068461EF081 +:206C8000C7FD13E001201FF013FD014600F074FC27E0AB2000216A4619F0E6FCCDF808D02B +:206CA00004208DF80C0002A80DF0E4FE20784FF4805117F037FF207841F288324FF4805114 +:206CC0001FF0FAFD0DE01BF015FF0AE001200021DCE7F88948F20201814202D138460AF0E7 +:206CE000E5FE38461EF038FADBE65778217878B1401E6BD0C01E64D0801E58D06AE0C046E0 +:206D000068060120E5040120E40401205001012094F82F00022F904601D181095AD2C1084C +:206D20002CD2800856D3042594F83000E571400850D394F832309BB9012F18BF022F17D19C +:206D40000127E01D00212A46A77015F047F80320E071384619F0FAFA38461EF07AFE05E04A +:206D60001EF072FD2846012100F006FC98F8017087BB2846002100F0FFFB2BE0E01D052526 +:206D800094F8301005708908F3D394F832100029EFD10121A1700422002115F01FF8E571B8 +:206DA000002019F0D3FA02201EF053FE12E0002084F82E00E0713222084604211FF07CFD00 +:206DC00008E01EF041FD04200121D4E7012001461CF040FA86F0040007B0BDE8F08FC04675 +:206DE000D80301202DE9F04FD14CDFF84893DFF84883080CADF1140D019180F0D38108465A +:206E0000400838BF0020C0F0D78167681FF016FF05461FF0B1FB4FF47A764FF6FF7268437E +:206E2000B0FBF6F081B267B13B887888CB1A9BB2984210DDC01A8242C8BF82B2FF68002FCB +:206E4000F2D14FF6FF70904200F09380207801211FF032FD8DE0B87902287DD01FF0EEFEDE +:206E600005461FF089FB97F838106843B0FBF6F0D34D38802878884266DD97F83600FF28B0 +:206E800008D197F83800401C87F8380097F8370087F8360097F8356097F839200020012176 +:206EA00001E0401CC0B282420FDD97F8365001FA00F385F0FF052B42F3D03618814097F829 +:206EC0003600F6B2014387F8361097F83400B98F10FB06F2891A89B28842C7BFFF2087F8F1 +:206EE0003600011C97F8360099F82220FF2818BF97F83A0006D140460078642510FB02F283 +:206F000012FB05F0788046B9388D3E7A40F020003885386C87F82E600BE03A8D4FF6DF70F7 +:206F2000104038853D6C87F82E6097F8342012FB06507862F879CEB287F82D0007F11000C9 +:206F40007E8405F05FF810E0B87E97F82A10FA8BE9231BF097FD05E0387CFF2802D0B86911 +:206F60001EF0FAF838461CF091FB2078012118F06FF8019880F001001EE12878012840F0D0 +:206F80000E8195F8338095F813A06F6995F83100698802221CF036FF05F11C0405F1020BDD +:206FA00006460020002E02907BD1687F400876D3A87FCDF80CA01FF037FABA4605F11009FA +:206FC000071C60D01C2012F0FBFF061C59D000211C2214F003FFA87F69461DF0D9FF9DF826 +:206FE00001000221307530461DF0E2FA6888317DB08095F83100FF22F07102FA01F070748A +:2070000078680078307495F83000B07495F8331011FB00F0303080B21DF098FF0746B7612C +:2070200027B930461CF032FB00262AE01A20387000237B701A467A80E0885946B880B81D33 +:207040001EF05AF9E0783C4BF87303F1200000883882608BB88560897882A0783875207BC4 +:20706000787599F80000B87599F80100F87599F902003876039A7A76C7F81CA007F13001F3 +:20708000B962304600E000200028064600F08780274886F808800078012117F0D9FF002ED8 +:2070A0007DD0307AA8EB0000B0F1FF3F04BF01200290307CFF285DD06078400828BF4FF0AB +:2070C0000008317DF07C4018404503DCF074FF2088407074B069B17C227D806A08FB0100D0 +:2070E00021691EF05BFD029F317D727C012398FBF1F04843A8EB000003FA00F11143C9B2F0 +:207100007174DFB1401CFF2202FA00F001437174B769B17C207D08FB0100B884707CFF282B +:207120000CD1307CB16919F05DFBFF20307421E0800A0120E4040120780101201FF07EFDAF +:2071400007461FF019FA204B204A4FF47A717843B0FBF1F0308093F8221010781F4610FB11 +:2071600001F197F821006423401C10FB01F010FB03F07080F17C327DA8EB0100801AB0F1B5 +:20718000FF3F04D0707CFF2801D0029F3FB1E175707C2076BBF80000214612F0B8FB284653 +:2071A0001DF0DAFF0748007817F024FF051C7FF4E4AE019880F4004005B0BDE8F08FC046A6 +:2071C00005050120800A0120E4040120780101202DE9F04FB64AB74CDFF8DCA20B46ADF19A +:2071E000340D90465178607805931A0C80F09C8031F0010709D11A46520806D3206A00B1BC +:207200008047059880F00100AEE11A46920805D301201F46E07087F00200A5E1022906D161 +:2072200098F80010012902D11946C9085DD21846000938BF0020C0F0978150463230E76AC3 +:2072400000780026B146000922D21FF0F7FC05461FF092F9236BB8F836204FF47A71684348 +:20726000B0FBF1F098F825100690C01A824238D8B0FBF2F39BB29942ACBFDDB20D1C069BFD +:20728000B0FBF2F15143401A81B2581A206300E00125EFB1C846F878A8420ADD401BC0B288 +:2072A000F87040B109F101061FFA86F93E467F680CE087F803807868002E82460CBFC4F826 +:2072C0002CA0706038461AF0D5FB5746002FE2D16078B9F1000F04D100212163082117F000 +:2072E00021FC059880F008003EE1A14B00263C244FF6FE71354633F8062F914208D09A886F +:20730000521E97B2002F9F8006BF19809D700126641EF0D126B104214FF4FA721FF0CCFA11 +:20732000059880F004001FE117F064FE071C00F01881B87FC0B9788CE56A132815D1B7F854 +:207340000290281C11D000260188894508D14568002E0CBFE56275601AF08CFB284601E07E +:20736000064640680028EFD1E56AB87A97F831102E46022853D1788856B13288904204D1B6 +:20738000B27898F82530914247D07668002EF4D181460E46002D08BF002004D0012015B139 +:2073A0006B68002B35D1B8F83810814237DD082012F006FE98F82510002830D0A0F80090B7 +:2073C0008670C17000234360E66A86B9E0629AF83200000911D21FF031FC05461FF0CCF8E5 +:2073E0004FF47A716843B0FBF1F0206300E06860504690F83200000911D3607808211AF0B5 +:2074000019FB60B96078B8F8362008211FF051FA05E0401C1D4680B2C1E7F3709EE05548E2 +:2074200005683878012806D0022840F09780384616F0CCF892E007F11004B81CBE89089442 +:207440003B7E0690FA7C07967969099397F819B00A923C7F0B9107F11C0604F00C000C28B3 +:207460000DD0B87F4FF0FE09FF2804D01EF0DCFF041C11D172E0002D70D06C6810E0B08811 +:20748000FE211BF01BFB8146B9F1FE0F08BF01201EF0CAFF041C61D020781EF0C7F905466D +:2074A0004FF6FF7A11E020781EF0C0F905460CE0E4040120E006012050010120B078FF28B6 +:2074C0004CD12D68002D49D06C68002C46D0AB68AAF1010823B9A3680BB1B3F8028007E030 +:2074E00021780220984718B1B0F800801AF0C2FA3389227898450BD00AB913B908E09A45D7 +:2075000006D0B3F5807F18DB4FF60240984214DD96F80280B27008980090099B01930A996C +:2075200002910B9A0392CDF810B0079B069A3046214610F053FF86F80280307800F00C00E4 +:207540000C28BBD1B08849461BF0B8FA8146B9F1FE0F03D01EF068FF041CA4D138461DF001 +:20756000FBFD059880F400400DB0BDE8F08FC0462E030020C00A01202DE97C43CD4C0E465D +:207580000146DFF83483DFF834936078491E00F04E81491E00F02281491E00F0E580C84AB2 +:2075A000491E00F0B380491E6CD0891E2BD0491E40F07481052102288DF8011040F06E816B +:2075C000444694F82F00B6B1A07AE0710021A17242F2080008F0E2F994F82F00217900F00C +:2075E000DF0084F82F000D2084F82E0001B904201EF058FB52E140F0200084F82F00022695 +:2076000084F82E604AE10025012E8DF801501AD0022813D11FF046F880B1052044468DF861 +:20762000010004F12F01087840F0200008700820294608F0B3F90A201EF034FB444602208E +:2076400084F82E0019E018B909201EF02BFB6078022806D10820294608F0A0F904201EF026 +:2076600021FB14F0E5FC44460D200421C82284F82E002078E5711FF01FF994F82F0000F0D9 +:20768000EF00D1E00221012E8DF8011017D04446082130F0010084F82E102BD194F8320033 +:2076A00040BB002552200DF105018DF805501AF081FB1EF0F8FD15F035F8284618E0002514 +:2076C000484616460570308804F13002208683201FF02AF8032128461BF078FB60780128E1 +:2076E00003D107201EF0DEFA6078444610B909201EF0D8FA0020E0712078042132221FF0E4 +:20770000DBF894F82F0000F0FB008DE00121012E8DF8011004D0D0B902214846017016E027 +:20772000002148461688017004F130022686022183201EF0F9FF6078012803D107201EF0E2 +:20774000B1FA6078022802D106201EF0ABFA44460020E0712078042132221FF0ADF894F884 +:207760002F0000F0FD005FE0012818BF022840F0958044462078042132221FF09DF894F874 +:207780002F10E0685EB101210028E17100F090801CF044F9E0680028FAD1BDE87C8302206D +:2077A00084F82E0000258DF80450E57101268DF8016021F0020184F82F10522001A91AF0C9 +:2077C000F9FA1EF070FD14F0ADFF28461EF06AFAE068002862D01CF021F9F9E700201EF0D5 +:2077E000D5FC04250120207260788DF801507EB1002188F82E10012888F82F1003D107203D +:207800001EF050FA6078022802D106201EF04AFA44460020E0712078294632221FF04CF81A +:2078200094F82F0000F0FE0084F82F0036E0012818BF022832D1012E18D0012044460726C2 +:207840008DF801004FF48051207884F82E6017F069F900201CF0FAF8002084F82F00207802 +:20786000022141F288321FF027F817E0002003211BF0ACFA4446042132222078E1711FF0E2 +:207880001BF80820002108F089F80020207220784FF4805117F046F9BDE87C8348460078C5 +:2078A000002103226B468DF800000A201AF0C2FABDE87C83E4040120680601209606012063 +:2078C000980101202DE9F0410646B948B94DF1890078ADF1380D0F46203F64D07F1E012FCA +:2078E00032D947F6DF72BF1A012F16D9213F012F00F28481002840F0818108352F68002F13 +:2079000000F07C8142328A420CBF03200220B169727C097805F0C0FD70E1304615F09AFF8A +:20792000041C00F06B81207860B9608800218DF80810ADF80A00211D03A81EF0CBFD02A8DC +:207940000BF062FC204657E1307B002840F05681B16902A80C461EF0D3FF083414F8010B0C +:207960008DF8100061782078A41C00EB0120ADF8120014F8010B03288DF81C0006D06178EB +:20798000207800EB0120ADF8140007E005A821461EF0B6FF14F8080F8DF81E00304602A9E5 +:2079A00007F0A0FE2AE1002840F02881707C77888DF80800337CADF80A70B4698DF8093005 +:2079C00061782078A71C00EB0120ADF80C0039460DF10E001EF094FF07F1080414F8010B6E +:2079E00000268DF81600617820780796E41C099600EB0120ADF8180014F8010C8DF81A0098 +:207A000070B19DF81A00400012F0DAFA0246079030B19DF81A0021461DF07AFD044601E0FB +:207A20008DF81A6014F8010B8DF8200068B19DF82000400012F0C4FA0246099028B19DF86D +:207A4000200021461DF064FD01E08DF82060A868C8B9502012F0B4FA0746AF608FB1314687 +:207A6000502214F0BBF9384602A915F034FA40B1A9680120634F81F8400038881CF0D4FD55 +:207A8000B0E0882065E090F84010012940F09480022780F8407002A9203015F01CFA28B9DB +:207AA00088204FF001088DF8340000E0B046AC68207EE16994F83220636B19F083FA84F89D +:207AC0004300B0B110FB07F000B212F079FA6064AC68606C28B988204FF001088DF83400AB +:207AE00007E094F84320606C05F1180152001EF055F894F83800E16BA27C636919F062FAC9 +:207B000084F84800A8B110FB07F000B212F058FAE064AC68E06C002804BF88208DF8340050 +:207B200016D094F84820E06C05F1180152001EF035F8B8F1000F0BD194F8431094F848003C +:207B4000084305D0304601460A4605F0A5FC49E086208DF83400BDF80A000DAF0224ADF894 +:207B600028000AAE009748F2200201239DF809008DF830403146019002A819F06BFDA86848 +:207B800098B190F8401002290FD18DF830400DAF41880097ADF8281040780190A86848F238 +:207BA00020020123314619F055FD17F0DBFA19E0E50401203C050120BDF80A6088200DADEB +:207BC0008DF83400022700950AA948F220028DF830709DF80900ADF828600123019002A8D0 +:207BE00019F038FD9DF81A0010B1079819F042FF9DF8200010B1099819F03CFF0EB0BDE830 +:207C0000F081C046E40601202DE9F04F0E46074630687C68BD68ADF1140D00283AD01EF04C +:207C200089FED4F8E81081460120019008294FF0000088BF0198B168084202D171680842D7 +:207C400005D0019880F00100C0B201281DD1D4F8C000B8B9C4F8C060C4F8C4600020C4F827 +:207C6000D0000146C4F8D41094F8FC30C4F8D810002BC4F8DC100CBF01980520D4F8C410F5 +:207C8000087410E094F8F80030B90320307448461EF0D0FF002050E1D4F8C4004661C4F895 +:207CA000C46006233374D4F8C4000021416194F8FC00012808D1022194F8FB0084F8FC10C1 +:207CC0004FF4E0211CF0CAF8706810F0704F06D128B104201BF0E2FD06201BF0DFFD02200E +:207CE0001BF0DCFD94F8F800DFF85482002840F0B480E86B3168884240F2AF8094F8FC0044 +:207D0000002840F0AA8094F8F90028B1D4F8EC00B0F1FF3F40F0A18048461EF08BFFB76856 +:207D2000AA463FB1D4F8E800B94609282CBF0220019802E004F1F40900207768039037B18B +:207D4000D4F8E80009282CBF0220019802E004F1F60700200290DAF80010D6F800B0486802 +:207D60005FEA0B0540F0020048604ED04046A0F11008D4F8E800ABF1010B092820D301986A +:207D800003460DE0D8F800108A68398890470346002003B10198031C02D002986D1E3F1820 +:207DA000DAF800000DB1012BECD0D8F80010C9680A4669469047BDF80000A9F800001FE00F +:207DC000019803460DE0D8F800108A68397890470346002003B10198031C02D002986D1EAE +:207DE0003F18DAF800000DB1012BECD0D8F80010C9680A46694690479DF8000089F80000B7 +:207E00000398BBF1000F8144B3D17768DAF80010D4F8F030CA680020134218BF0198102BC4 +:207E200018BF80F001000028F4D117F0704F06D12FB106201BF01AFD04201BF017FD0220E3 +:207E40001BF014FDD4F8C010002008740746C4F8C4703E46C4F8C0606EE0D4F8D800002817 +:207E600043D1D4F8DC00002842D128791EF064FD4646D4F8CC0032682969406852680068E1 +:207E800091FAA1F1B1FA81F1134602229847D4F8CC003268696940685268006891FAA1F161 +:207EA000B1FA81F113460222984728791EF03EFD28791EF043FD2046294609F091FE0021F2 +:207EC000D4F8C000C4F8E0100068B0F5806F03D92046294609F084FE94F8FE0060B929680E +:207EE000486840F00200486006E0D4F8DC0018B92046294609F074FE2968486940F00100E6 +:207F0000486148461EF096FE94F8F800A0B9D4F8EC1004F16C0528461EF0BCF960B1D4F86F +:207F2000C00003210174384606F02AFC284600211EF0B0F900200190019805B0BDE8F08FE5 +:207F4000D40100102DE9F04FBF4CDFF80083207889465FEA1941ADF11C0D3FD25FEA5901FD +:207F600011D32079211D88F83C00E12019F022FF1DF032FC0020A8F89400012016F05CF954 +:207F800089F001005CE1E7885FEA990116D25FEA191038BF0020C0F0538194F8310050B125 +:207FA000E06A94F830101DF02DFD20B994F83100401E84F8310089F0080041E1002F04BF3E +:207FC0000020A07007D07F1EB9B24EF66022E18002211EF071FC89F0020031E117F00AF837 +:207FE000071C00F02B81C346387894F83120A178313800F00B81401E00F0BC80A13840F09B +:208000001481FE89383E0FD047F6DD70361A40F00C81B8690678002E40F007814078C00952 +:20802000C0F0038178885CE089490EC904A880E80E00D7F818A0042150461DF04BFA3D46EE +:2080400006460AF1040010F8011B049606298DF8141010DBFE2918BFFF290FD10278FF29AC +:208060008DF816200AD1401C4278007800EB0220ADF8180002E000788DF8150006295ADBBA +:20808000FE2931D0FF2912D0287B002840F0CD8068882084002600963346019332460292FD +:2080A00031460391687C802111F054FBBDE09DF816509BF89600A84205DB002D40F0B580C3 +:2080C000FF2840F0B28028461AF072FF3EB1DBF84C00864203D0CBF84C601DF07DFBBDF8DC +:2080E00018001DF0EBFDA0E09DF8165098F89600A84205DB002D40F09880FF2840F0958027 +:2081000028461AF055FF002001218140314202D1401C1B28F8DB98F83C10884200F085803D +:20812000207198F82B00642110FB01F2012120781EF0C2FB79E02B7B002B76D19DF815A030 +:20814000BAF1000F71D0BAF1060F6EDA30461DF059FC002869D1AAF10106687C8DF8156062 +:208160006B88607004A923840EC904F12C0585E80E005AE0FF2A12D0002016F05DF8024668 +:20818000002000906078B8F894103B4613F071FA94F83100002848D008213222C7E798F85C +:2081A0003C007A6801213B46814011420EBF00213844017A5D68002001228240154203D011 +:2081C000C218127A8A4204DB401C1B28F4DB002018D0B8F8920020841026009621896289D1 +:2081E000002013F046FA0120E070A07840B93C20E080207802214EF660221EF05DFBA078DF +:20820000401CA070002084F831000EE004290CDA1048017810481DF0F5FB30B97888208174 +:20822000FF2684F83160B888608138461CF094FF207816F0DFFE071C7FF4D6AE89F400407C +:2082400007B0BDE8F08FC0461C07012050010120BC860200A201012000F8FF072DE9F04F2C +:20826000ADF1440D0B908069007800210DF12A020F909C200EF01CF8B54D681C007830F03D +:20828000010009D1002004211CF00AFA5FFA80FA9DF82A00504402E001204FF0000A8DF8B7 +:2082A0002A000F989DF82A10884280F2DE809DF82A000F99401AC0B20D900228C4BF0220E5 +:2082C0000D901A2110FB01F000B211F079FE0E90002800F0CD800F980D9F0E9C0C90002FD5 +:2082E00008BF002074D04FF00008B946012645460C9882450ADC0F9940468A4504DAA1EBA3 +:208300000A01C9B20C9163E00C9561E0411CC9B20C911CF0D9F9071C54D08E480146B0F8B6 +:2083200048005D312080A01C1EF0EAFA388860820223E375FF222276B87A60768DF81C5048 +:208340003888ADF81E0007A813F082FDAB46012808BFB34604F10A00BBF1000F06D104F109 +:208360000A00FF21082213F039FD02E008A91EF0C7FA3B797BB93F88002F04BF2575281C8F +:2083800004D07448267590F85C00401E207602206075A57515E06F4890F85C00401C207647 +:2083A0003879032804DB26753879032805D106E0022020753879012801D0667500E06575D8 +:2083C000A6751A34B9F1010908F1010890D140460D9981424CDD0D9DDFF878B104F102085C +:2083E00004F10A0702264FF0000A4FF001091A3C2D1A0C9987206A460DF05AFF5749BDF879 +:208400000A0024F81A0F40461EF07AFA0DF1020138461EF075FABDF800004D4B608258780A +:2084200030F0010003D16675A675FF2006E084F8159084F816A09BF85C00401E2076E675BB +:20844000638A9DF81200002B60760CBF84F814A084F814900C9808F11A081A376D1E00F1E0 +:208460000100C0B20C90C4D102E000200E900D900B98417C0D9F0E9D8DF82B10801C1621D1 +:208480000B9017FB01F0001DC0B28346401C11F097FD5FEA000854D008F101040020A2467A +:2084A0008AF800009DF82A000F9F88F802000D9E88F8037088F8046096B30D9F2E46241D1F +:2084C00006F102090A36204649461EF019FA0834314620461EF014FA0446A87C04F8010B99 +:2084E000688A001204F8010B287D2070697D40EA8100C0B22070A97D40EA011004F8010B3F +:20850000E87D04F8010B287E04F8010B687E09F11A091A367F1E05F11A0504F8010BD2D190 +:208520000D4D0B990DF12B0048F231025B462C1DC4F800A015F0B0FD404619F09BFA09344E +:208540006C600E9808B119F095FA11B0BDE8F08FE40401205001012028040120AD010120DC +:20856000B8492DE9F04F0A68B449ADF11C0D002A06BF8B1C1D780225AB4BDF689E686D1F4E +:2085800000F04B816D1E00F04581DFF8A482002A65D09279012A62D0A44C276B022A04D098 +:2085A000E169002900F03C8139E138460027002851D1780011F004FD5FEA000900F0238132 +:2085C000206B40B10021028829F8112040684E1CF1B20028F7D14446B4F89200618F814202 +:2085E00033D080460A2000EB47008DF80D0003A81CF032FD061C2CD035690920287004F16C +:208600005D016F70A81C1EF07BF95FB108354846017805F8021F30F8021B7F1E4FEA212108 +:208620006970F5D10124B4771DF088FA706201A940461CF0ECF910B1747701A83062A6F844 +:208640000280304601F004FE03E0CDF8009008F0F0FD4E46D4E040687F1CFFB2A7E7407890 +:20866000DFF8D0B18DF810009BF8030070B90BF14801086838B900208DF8050001A9012033 +:208680001BF09CF9CCE0096804A8C8E000208BF803001EF03DF805461EF03AF80027002806 +:2086A00040F0B48064484078002630F0010037D11EF02EF858B10A8801888A4204D08469BE +:2086C00014B1201CF8D102E008B18A4228D01C2011F076FC061C23D04146B1F84800308085 +:2086E00091F83C40B4701DF065FF7071524880795D31B07106F10C001EF002F941200DF152 +:2087000011011CF0BDF89DF8110000280CBF4FF6FE70BBF81C007F1CB5613546FFB23081DD +:208720009BF804A0574510DBA7EB0A005FFA80F8B8F1060FA8BF4FF00508BAF1000F06D00D +:208740005046AD69401EFCD101E04FF000089BF802000C248DF8120018FB04F0001DC0B228 +:208760000690401C11F02CFC5FEA000942D009F10104002120460170059089F8027089F87A +:2087800003A0B8F1000F89F8048021D04746241D4FF0FF0A4FF6FE7805F10C0120461EF040 +:2087A000AFF8A878083404F8010BA8792070697940EA011004F8010B04F801AB28898045BA +:2087C0000CBF0020012004F8010BAD697F1EE3D11B4D05982C1D0BF1260148F23002069BA0 +:2087E00020600DF1120015F057FC484619F042F909346C601048407830F0010003D116B1EA +:20880000304619F037F91AF0B9FB09E080697F1CFFB244E727B1394601E00EB13146884765 +:2088200007B0BDE8F08FC046FC090120E402012050010120C4030120E4040120980101200D +:2088400028040120000A01202DE9F04FB04E4FF0000A8146ADF1140D57467069CDF808A09B +:20886000CDF80CA010B1804700B90B27F078002F40F09B8096F8314096F832700146B9F112 +:20888000000FA1F101011FFA81F818BF012155464FF0F80B86F83F1022E0AF421ED0F068C7 +:2088A00069036A4604231DF071FF009911F4403F1CBF0AF101005FFA80FA01F0FF017C299B +:2088C00018BF782909D1284606215A461CF0C0FE0C2015FB006080F848B0F0786D1CEDB2AB +:2088E000A842DADC401E504503D196F8350000285BD0B8F1000F06F1300500F0CF8003983D +:208900004FF4005B019096F83F30F06813B9012186F83F106A46610304231DF037FFB9F1F0 +:20892000000F05D00099F07811F4403F40F09B80009800F0FF00702803D0204670211AF090 +:2089400035FFF06879036A4604231DF01FFF009800F0FF00FE2803D03846FE211AF026FFC1 +:2089600038460621FE221CF073FEB800FE2300EBC700FF2186F83C70A200A6F840B0401957 +:2089800086F83D4000F1180A8AF80030019B86F83E1002EBC4004019A6F84430808BA6F8EA +:2089A000420001F0C5F8102801D10020ADE0B9F1000F0CBF10214946B9F1000F07D0B6F88E +:2089C0004000C0F50050814207DC01200390B6F84000C0F50050814201DD782100E07C214E +:2089E00038461AF0E3FE0CF031F996F83F300446A8EB04000621FC221FFA80F8181B86F883 +:208A00003F0038461CF024FEFC208AF80000029A96F83210F078091996F83E400C278918F7 +:208A200091FBF0F24243891AC9B286F83210491C91FBF0F24243891A86F8311014FB075144 +:208A4000898B102905D1611C91FBF0F24243891ACCB20198B9F1000F96F83270029019D065 +:208A60000398B8B11AE096F83F30641C94FBF0F1A8F101024143A6F840B01FFA82F8581E54 +:208A8000641A029986F83F00E4B286F83D40481C80B20290B8F1000F7FF435AF7C2019F093 +:208AA00081FF00240746FF2F1CD17E2019F07AFF0746FF2F16D196F831700C2017FB00506B +:208AC000807DFF280AD0F27896F832008018401E90FBF2F15143401AC7B203E038467E21A3 +:208AE0001AF064FE0C2086F8337017FB0050808BF08696F83200FE211AF058FEB6F84000AD +:208B000086F83540C0F5005000B205B0BDE8F08FC01900202DE9F04F81460D462C20ADF180 +:208B2000240D11F04DFA071C00F049811DF048FD698B884214BF012002203870697B28699C +:208B40000026401A7860687B87F82660B8707C68B87887F827602418207800F007007870E0 +:208B60002078C0F3C100387420780421C0F3401A601C1CF0AFFC4FF00508B861BAF1010F20 +:208B800087F81C8006D007F108003146082213F025F908E0397F07F1080009191DF0B0FEA5 +:208BA000387F08303877387C012805D1387F205CB875387F401C38772878DFF80CA200F02D +:208BC0000300012803D0504630300078804687F8018078781DF02AF87877397F28692C7D62 +:208BE00040182861397F7B7F601AC01AC0B22875F8704FF6FF74BC82B869B0F1FF3F32D01F +:208C0000387C01281CD038B9062078823946484614F012FD40B30CE0387C022802D00328A0 +:208C200007D01EE0062078823946484614F004FDD0B1042078823946484608F0BFF913E0DE +:208C40009AF82F507E82B32075B99AF8651001290AD1B87D17F0B2FAB882844218BF301CEB +:208C600002D1A12000E0A32004463878022806D11CF064FF014607F108001DF041FE002C94 +:208C800040F09980514D6878B046012818BF02281CD197F82600012803D097F82700012870 +:208CA00014D1B978F8784018397F4018001D11F087F95FEA000809D0B878FA783C7F7968C0 +:208CC000121840461219121D1CF068FF38460AF081F804466878012818BF022865D1002C70 +:208CE00063D0B8F1000F66D040F203154FF0680A4FF0010900E05C4697F82600012803D0DC +:208D000097F82700012850D1B978FA783B7F786852184146D218121D1CF040FF97F826000C +:208D2000A34630B997F8270040B1BD8287F8276003E0A7F814A087F826607E8238460AF0C2 +:208D400049F8041CD8D168463146142213F046F87B8A8DF81190D3B9B88A682803D085424A +:208D600015D1FF2011E07868C17B0529C3D12A30FF211CF054FE0028BDD005A8082213F0B8 +:208D80002DF805A81DF0C8FAFC208DF8100002A807A9324612F0A4FF01469DF81C0020B141 +:208DA000042014226B461AF073FBB8F1000F02D0404618F05FFE384618F05CFE00E01024C7 +:208DC000204609B0BDE8F08F50010120E40401202DE9F84F1DF0DCFBA94CE06011F0AAF8BC +:208DE000A94800681DF01EFFA64D4FF000084FF0010A4FF0020B38E085F80080A3691CF0F3 +:208E00003BF920B9E06920F00200E06103E018461DF008FFE069010917D360691DF0FEFE45 +:208E2000071C05D0B86817F0D1FF384618F022FE60691DF0EFFE20B9A0691DF0F3FEE069B1 +:208E400003E0E06920F00800E061C1080DD320F00400E06120691DF0DDFE30B9E06940F0BC +:208E60001000E061A0691DF0DDFEA0694FF0FF311DF0CCFE1BF0CEFEE7882689A4F806804A +:208E8000A288A4F80880E169A4F80480114347EA010246EA0201E1611DF047F8E069010A7D +:208EA00024BF20F08000E061207816F0A3F868B316F044F8071C29D00C2011F081F8061C84 +:208EC0001ED01BF0A7FEB7603B7881465BB9206931461DF097FEE06940F01000E061A069DA +:208EE0001DF0A0FE08E0304618F0C4FD78681CF033F9384618F0BEFD48461DF016F805E0B9 +:208F000078681CF029F9384618F0B4FDE06941092DD320691DF07EFEE0B91DF069FBC8B9DC +:208F20001BF078FE064620691DF078FE071C0ED0B9684868498811F07DFFB86840681CF064 +:208F40000BF9B86818F096FD384618F093FD30461CF0EBFF20691DF05DFE20B9A0691DF0F0 +:208F600061FEE06903E0E06920F01000E0618108FFF451AF66E09DF800006B78AE686F6895 +:208F8000A870D81C5FFA80F9494630461CF04AFF9DF80010814205D13FB1484631464246DE +:208FA000B84702E030461CF0D7F885F8008049E0AF68E8789DF80010C019C170E878401C77 +:208FC000C3B2EB701CF058F86978C6B2C91AB1420CDBD8193146C01C1AF038F8E878697890 +:208FE0008019C0B2E870814222D02BE0DB1989B2DB1C18461AF02AF86878E87018E09DF8D9 +:20900000000085F803809DF800706870F81C1BF09DFF0028A8603FF4EFAE6978017085F8E9 +:2090200000A00FE09DF80000A9688870687808B9052006E0042004E09DF80000FE2801D1C2 +:20904000032028701CF018F800283FF4D7AE6846514619F0FBFF28780028EDD0401E08D056 +:20906000401EDFD0401ECAD0401EA1D0401E82D0E8E79DF80000A968487085F800B0E1E74A +:2090800070F70020680A0120EC0101202DE9F04F064606F1060BBBF80000ADF1440DADF8B8 +:2090A0000A00707D8DF81400B088ADF81600707E8DF81800B08C4FF00208401E8DF81A0020 +:2090C000B06A8DF81280411C089100788DF81900708AADF81C00B08DADF824009648076845 +:2090E0000024002F30D04FF0D30A4FF6FF79BDF81600F988884206D0894522D1C10BCD03FB +:2091000001D113281DD19DF81A00203080B21BF01DFF051C15D002A920221CF03FFD9DF82C +:209120001A203AB105F12000A861089905F120001CF034FD85F800A03879294617F052FB66 +:2091400001243F68002FD2D17C4800780D940024002800F0BB80BDF81600B6F804901338C5 +:209160005ED047F6ED71401A01280BD9001F40F08580B08C062880F28180A6F824804020EC +:20918000B0807BE002A814F065FB071C74D0387800286ED1397BBDF816A00D20884600EBB3 +:2091A000480200EB4105D2B20E92E8B210F008FF00280F905DD005463878391D05F8010B21 +:2091C00028461DF09DFBB878083505F8010B7888001205F8010B787B4AF0800A5FFA8AFA57 +:2091E00005F8010B07F10E0005F8018B06E00178297030F8021B09126970AD1C41464A1EEE +:2092000000295FFA82F8F2D1DDF83C800E9A45205146434619F0FCF8404618F02BFC28E017 +:2092200002A80AA91BF0A3FEBDF80A500D2010F0C7FE071C20D0804608F8015B281208F8B5 +:20924000010B9DF8280008F8010BBDF828000DF12A01001208F8010B40461DF051FB9DF8A1 +:209260003200C1210D223B4608F8080F452019F0CFF8384618F0FEFB012027D14FEAD93004 +:20928000C00323D0B08C401CC0B2814610F098FE071C1BD0B0889BF8005040F080003D702B +:2092A0005FFA80F8BBF8000000127870B16AB28CB81C491C521E1CF071FC45204A463B463F +:2092C000414619F0A5F8384618F0D4FB1C48083002884FF6FF7191420DD0BDF81630E500A1 +:2092E0002A18455BAB4221D0641CE4B2E5002A18455BA942F6D10D98D8B9BDF81610C80B3B +:20930000C00316D19DF8140098B9132911D041F4004100919DF8180001909DF819008422F3 +:2093200000230DF10A011AF08BFE02E0516802A8884711B0BDE8F08F3004012011050120E9 +:20934000E07B02002DE9F04305468078ADF14C0D1CF0DCFAA14C071C00F02B816878F87354 +:20936000DFF88092DFF880826878F12809D0CD2807D01A2805D0E92803D0E12818BF1D286D +:2093800011D1607830F0010006D17889000B24BF0520787380F0EA803846002103F0EAFCCA +:2093A000002840F0A38010976B788DF84430A87B8DF84500387C002866D1894802685AB169 +:2093C000384619469047012804D179894FF6FE70084078819DF84430787B02282AD17989C2 +:2093E000890825D3CD2B23D0F02B21D0788A000A07D3B87E28B1B8733868008818F0DAFAC9 +:2094000003E094F82100401CB873B87B401EC0B2B876B87304267E73608E43463881A3F1FA +:2094200032000078202115F013FE9DF84430787B022801D0062818D17889400815D37E6905 +:2094400046B1707810F0030F04D1B078317BB28819F018FB79894FF6FE7008407881386886 +:20946000008818F0A7FA9DF84430607830F001000FD173B948463E680368308818F09AFABA +:2094800028B923B1984702E010A807F0B9FB9DF84430E92B18BF002B07D1396801200090AA +:2094A000EA7B0888498902F0ADFC607830F0010077D140460078800873D3787B022802D14D +:2094C0007889C00806D26878E9286AD1384618F049F966E03B68188818F06CFA20B94FF6E2 +:2094E000FF701880052060E003205EE0607830F001002AD140460078800826D33968086A19 +:2095000018B3C97F02AA09F075FD6B78E92B07D1396801200090EA7B0888498902F072FCD9 +:20952000BDF81200396808809DF80D0000280CBF00224022BDF81200BDF814100CF020FF67 +:2095400018B1788940F0200078816E783889E13E18BFB6F1100608D1798911F0300F04D0AF +:209560001DF019F900F00700801C3881607830F0010016D16878E92813D04846006800B125 +:2095800080471A4E706A60B140460078800808D339680888498918F007F910B1726A6978C7 +:2095A0009047787B022801D106207873A87812F0E1F904F04DFC607802280CD1207850B91B +:2095C00000208DF8480012A9522018F0F3FB2020012106F0E3F913B0BDE8F083E404012063 +:2095E000F80601200403012082010120E40201202DE9FC47A24D009004782F5D002FADF8C5 +:20960000047000F03B81DFF87C820D2C4FF000094ED0052C15D0072C08D00C2C1AD14068CA +:20962000C08A400A28BF4FF0010913E08678002E08BF07F11B000BD0807D242110FB0170D4 +:2096400006E08178012900F01981007CC0192430ADF80400BDF804001BF078FC071C1FD1DA +:209660000C2C40F00B8100984068002800F006811DF060F9064640460068009FD0F85413A9 +:20968000381D8847BDF804001BF060FC071C04D130461DF0CFFABDE8FC8730461DF0CAFAD3 +:2096A000072C20D02A5D009938461CF077FA18E045462868D0F8282401A953209047BDF89C +:2096C00004104FF6FE70884200F0D380BDF80410401C884200F0CD80009F3889002800F012 +:2096E000C880052C46D0072C55D1009908783870487878708878B870C878F8700A7ACE797E +:209700008D79487900EB026000EB064000EB05207860BE78E6B18E7D3E7266B1896951B189 +:20972000B20007F1100002EB46121CF037FA07F11000F86002E00020F86038720098806908 +:2097400048B318F097F9009800218161817522E01B223A72896907F110001CF01FFA07F1E3 +:209760001000009EF860B06918F084F900980021816110E0796807F11805242228461CF004 +:209780000DFA7D6079693A7C05F124001CF006FA7868243078613C48016819B13846884716 +:2097A00000285BD1DFF8E8A00D2C0DD00C2C2CD1009840781A2828D07E6836B3F08A400890 +:2097C00023D30EF000FF20E000984268117801F00203022B3FDA2D4B1B78C1F383018B427F +:2097E00039D1567836F03F0635D190F83000022831D10EF0E8FE0098418E4FF6FF728A426F +:2098000003D140688079022808DAB9F1010F25D050460078394616F0E5FF1FE0381C1AD064 +:2098200057F80C6CAEB910F8021CFF2911D15446217800F8021C17480A22394618F0F4FC7F +:20984000012808D120784FF4005115F001FCBDE8FC871BF081FC454628680BE00C2C0DD10C +:209860000098416851B145462968D1F85413001D03E02868D0F8541368468847BDE8FC87F5 +:209880008086020014010020D00A01208601012050010120E80A01202DE9F04FDFF84C9259 +:2098A00004460D460020ADF1440D01461F460D9016460E9183460F91D9F808A0CDF840B021 +:2098C00011F018FF262803D011F014FF252825D1308843F6070181420ED040F60201814262 +:2098E00006D0B0F5C15F19D1F07B022816DD43E0F07B022812DD3FE096F8240002280DDDCF +:20990000307C0F2838D13169C1F31421B1F5803F04D00F2830D1B1F5A02F2DD1002D2BD0CC +:2099200056B328784FF0010808FA00F01AEA000F22D0304659461DF00BF865606C4DA66096 +:20994000A86980B110A800900DA90EAA0FAB30460AF066FA0E980B214FF6FF7250231AF080 +:2099600003FFFF2808D01CF0E5FF82462878022804DB50461DF05EF95C46B3E000286DD1F0 +:2099800005F06CF85B495C4E086840F00200086009A8C9F800601CF02FFD584E58497078DD +:2099A00009AA0B9005F1E00016F0C2FA554905F58E7009AA16F0BCFA09A81CF0DDFC1921EC +:2099C00009AB3078504A0A9005F1600018F0B0FB4E4A05F17C001A2109AB18F0A9FB4C49B4 +:2099E0005A4605F5AC70134617F064FF49495A4605F5CE70134617F05DFF47480068C0F31E +:209A0000814030B1454A05F1340004215B461AF0E7FEB078012802D10E200DF0BBFC05F13A +:209A2000A0001CF0E1FA05F198001CF0DDFA594685F8241085F83010072085F84002A96032 +:209A4000E962374B1970E960052685F83110354A2E610420AA621BF001F9287805EB80012A +:209A6000401CC1F8B840C0B2287050461DF0E2F81FB901A81CF0FEFA01AF38684FF4FA76CA +:209A8000E6602060B8694146A062388A61766083F8692063786800280CBF40F6C41059467A +:209AA00020616061204E266266622176E661F86800B12062786900B16062B86800B1E061CF +:209AC000C82204F13800594612F088F904F1500059461AF05DFA15495A4604F1B800134604 +:209AE00017F0E8FE204611B0BDE8F08FCC21084068F2002000200940110000E08487020018 +:209B0000155C0200E9650100ADF00100F9DE01009951020031570200B44F00503108020009 +:209B2000661B0120B5460100734A0100BF6802002DE9F04F994E96F83D0096F83F10F37851 +:209B400096F83C800027ADF12C0D0918491E91FBF3F296F83D4077705A43891AC9B208917E +:209B6000810001EBC0018919B1F84C0096F83C10ADF81C00880000EBC1008019B0F84C5074 +:209B8000CDF8248006A818F09DFC70780A97A04500F0A180B946CB46BBF1010F00F09080C2 +:209BA000BDF81C10162966DD002840F09580BDF81C0001AAC01F81B2ADF81C1020460EF012 +:209BC000D1FFBDF81210BDF81C30884608F1070008F1100287B29A4246D89DF80E00962870 +:209BE00042D19DF80F00420839D2800837D3BDF81C0000230093A0EB08001FFA80FA9DF885 +:209C00000D20BDF81C002346401A80B219F038FAF8B9E819B0F5005F15DCF068C5F1885287 +:209C20000AEB443A3B46D21B514602F500521CF0ADFDED1909F10109ADB2B5F5005F08BF74 +:209C40004FF0010B0BE0BDF81C004FF0010BC01D2EE0BDF81C00401EADF81C0004E0BDF83E +:209C60001C00A0EB080023E0204607A914F014FC01281FD030E0F278B9F1000F07D0484B53 +:209C8000BDF81C70A10001EBC401C9188F830899A14220D04249641C94FBF2F05043241A7D +:209CA000E4B2A00000EBC4004018808B4FF00009ADF81C0009997078A1427FF46DAF0AE06D +:209CC000B9F1000F07D0364ABDF81C70A10001EBC40189188F8320B106981BF047FF10203E +:209CE00059E0DDF824804FF6F0704FF40051C5EA0040C5EA0141E1FA40F01FFAA0F283B2AE +:209D0000102102F18852404617F084F871780843707006981BF02AFFA0450FD1F278204FB8 +:209D20001019401E90FBF2F15143401AC4B2A00000EBC400C019808BADF81C00184FBDF8BA +:209D40001C00A6F840504FEA8801A6F8440001EBC80186F83E40C9198D83B6F9422096F8D3 +:209D60003D10012340461AF027FD96F83E10B6F94420022340461AF01FFDBDF81C001628EF +:209D8000DCBF01200A90B5F5005F03DB0A9840F002000A900A980BB0BDE8F08FC01900209E +:209DA000F01900202DE9F04F0546ADF1140D02911CF0C0FD8A4C012D039000F0D280A346FD +:209DC000DBF80000D0F838038047002800F0C58015F0D6FD002800F0C080DBF80410864CA0 +:209DE000896960680F783C30002F40F0B6807D4E0068357880477168F268AB00401AB0FB97 +:209E0000F3F7B0684FF00008C2469146534611464F4573EB0A0301DA884206D84146524689 +:209E200087428A4143DA024600E041461046EB172A46C01B71EB08011CF000F807466F48B2 +:209E400000688846418B00694018643081464FF00001B7EB090778EB0A08784271EB08015E +:209E600025DA1CF089FB024653464146384613F0D1FA884607464FF00001784271EB080125 +:209E800015DA1AF0C7FE054630691CF055FA10B130691CF049FD28461CF047F83069394648 +:209EA0001CF03EFD30691CF03DFD002000E001204D490870884698F8000000284DD1DBF8D6 +:209EC0000000D0F8940000780027394614F048FB00B101274FF0000A381C3CD1DBF8040067 +:209EE00080690078002836D16068404D436C286902216A4698479DF8000060B302984FF00A +:209F0000010901281ED03A4F6268286997F9001011F1020F05D0926B97F900109047626876 +:209F20002869344E96F9001011F1020F05D0926B96F900109047626828696FF001013170B7 +:209F4000397001E062682869DBF80410896981F80090D169884788F800A003981CF06AFE02 +:209F60003AE02068D0F894000078012114F0F8FA03981CF05FFE606880690078012811D11B +:209F80001BF0FAF960B1606880690178012909D10021029F0170012F04D01BF007FF01E05B +:209FA0000EF0F2FC1BF0E8F9B0B960680C30C1680978022909D101680F7837B12068D0F885 +:209FC0004C058047241D20680C3001680F781FB9C16808780228FCD005B0BDE8F08FC0461E +:209FE00014010020D8000020721B0120A4060120B00A0120B10A0120D4050120B40601202F +:20A00000F0B58E4D05F1320184788E4A0E782746ADF11C0D7F1E0B2F03D9FE3F00F0D680D3 +:20A0200008E1DFE817F0C000AC00A0008900F9007B004D003D00300021000C00E100002177 +:20A040008DF80A1010F8031F31F0030706D1521C1170512001211CF067FB02E002208DF8BC +:20A060000A000DF10A03E0E03EB100200146F9F709FF002808BF002000D001208DF80B002D +:20A080000DF10B03D1E0002210F8031F8DF80C2000290CBF101C01201CF010FB03ABC4E05C +:20A0A000C01C002110F8017B8DF80D1004211BF011FA002F0CBF6862A8620DF10D03B4E0D2 +:20A0C000C01C10F8016B002108220746684611F085FEEFB15A4900204870301C15D0401EBC +:20A0E0000ED0401E0AD0401E03D0401E10D101204870384669460CF073F80AE001204870AA +:20A10000384669460CF002FC03E016F05FFA00E002208DF80E000DF10E0386E0002210F8A2 +:20A12000031F8DF80F2000290CBF101C01201BF0A7FB0DF10F0378E0C01C002110F8012BC2 +:20A140008DF811100146521E00F1080004D0521E06D10CF045F801E00CF0D8FB8DF811000F +:20A160000DF1110361E0844600201CF8037F8DF8120007B101200DF11203107055E00021B3 +:20A180008DF8131010F8031F0E2906DCD21C1170532001211CF0C8FA02E002208DF8130066 +:20A1A0000DF1130341E000218DF8141010F8031F0E2906DC921C1170522001211CF0B4FAE0 +:20A1C00002E002208DF8140005AB2EE00025C01C04218DF808501BF07DF91B4948604D80C7 +:20A1E00010F0B4FF02AB20E00021C51C8DF8091028461CF015FA06460421A81C1BF06AF933 +:20A20000014630460DF0FCFD104A352028211CF08BFA0DF1090308E0014600208DF8100014 +:20A2200011F8030F03F0A2FF04AB21466F20012218F0EEF807B00020F0BDC04668060120A0 +:20A24000CCE80020E6040120100A0120300301202DE9F04F8F4E054696F84A00ADF11C0D74 +:20A2600008280CD004280AD0287800F00300012840F0088128690078062840F0038168887C +:20A280004FF6FE74844200F0FD80718F814206D1287F20B9284612F00BFA0446F3E01BF01D +:20A2A00073F9002840F0EC80287FDFF8ECA14FF000082746C34608B30AF12400007804212F +:20A2C00040EAC00010FB01F05FFA80F9698885F81C90FF2019F00CFF48B1E88A49F00103D1 +:20A2E0004FF00108671C2B7740F00400E8825046407830F0010008BF4FF0400B688817F09C +:20A3000059FB08B100206876A87E08B90F20A876287830F07F0008D1E87E50B996F82400C5 +:20A32000411C86F82410E87603E0287800F003002870287E012806D196F82F0018B92878CE +:20A3400008B9002028769AF8010030F0010020D196F8320080081CD3B8F1000F0AD168881F +:20A3600017F028FBA8B1287820B1286900781BF05BFF70B1E88AC00902D3A87E012804D027 +:20A3800028461AF081F820B97AE0E98AE01E0840E8822878012807D128690078022803D1CE +:20A3A000E88A40F04000E882E88AC0093CD2B8F1000F39D19AF8010030F0010034D196F8FF +:20A3C0003200800830D3687E6988AA1D5B4612F03FFB28B10020EB8A687643F02000E8823C +:20A3E000A87978B1698805F1080017F0C3FA07466888B84204BF0021A971E98A41F0400146 +:20A40000E98200E068882978012904D0A9885A460EF0CAFD6888A9885A460BF0B1FF18B197 +:20A42000E88A40F02000E882284606A904F04CFF8046BC4208BF6F88B8F1000F1DD00595D3 +:20A4400028788DF810006C8DADF812406B7D0093E88A019095F82C00029004AA0392728FCA +:20A460009DF81830394640460BF03EFC0446102C04D1404617F0FEFA00E0102420460CE778 +:20A48000112400E0C224284617F0F4FA204607B0BDE8F08F50010120E40401202DE9F04F4D +:20A4A00009AF00268B46ADF14C0D099034469BF80380BBF806100B93B8680A92854D0D903B +:20A4C00038790F964FF00E090C900CE014FB09F02A5C904505D140191AF0F6FB08B1761C70 +:20A4E000B6B2641CE4B2002CF0D0002E0E9600F0D7809BF81450F1B2182000EBC10084B225 +:20A50000281900B20FF05CFD051C06D00F99224611F064FC2E742819E860002D00F0BB8005 +:20A520009BF80340DDF83C80BBF806102046424616F090FD06466C71BBF80600E8809BF88D +:20A540001600688185F808809BF81420E868DBF81010CDF820801BF021FB4446109411948E +:20A56000B8896882387CDFF87091287555E008994FEAC80005EB000A4019817570780AF184 +:20A580001604012810D0B0788AF81D007088ADF81C0004218DF8101004A815F047FDBDF8A4 +:20A5A0001200AAF8180005E00120207001230F9370886080307920719BF80000C00903D32F +:20A5C000A07940F00200A0710F9ED6B9B9F83A006188884215D120798BF80200109E0096FD +:20A5E0000C9B01930D9A0292314603910A9B0999B9F8482058460DF059FCA07940F005003C +:20A60000A07108F101005FFA80F8BBF806109BF80300424616F01EFD064616B10E98404518 +:20A62000A5DC2E4C201D06681198314604E00E4620E00968401CC0B20029FAD1052813DBCE +:20A6400096B1334600E01B6813B99E4202D00BE09E42F8D1306801216060304614F0DEF8FB +:20A66000304617F007FA6668607828716078401C6070284616B131680029D8D11199002EA1 +:20A6800001600CBF606030600C9B00950B993A78584600F077FB0E98002818BF002D15D1F4 +:20A6A0009BF803009BF816708DF81300BBF806608DF814700E9DADF81660002D0CBFB9209A +:20A6C00010208DF8180004A81BF0FDFE13B0BDE8F08FC0462201002050010120EC0A012042 +:20A6E0002DE9F04F0746861CADF11C0D30461CF0D7F886490446182268460EF007FC7D7807 +:20A700000DF10B0031461CF0FBF84FF6FE794FF0000B02208DF816004FF00108ADF8149066 +:20A72000B87A8DF808B0810805D3B87A000934BF0326042603E000092CBF02264646744881 +:20A740000378002B08BF002D00F09680714890F84A10082940F093801BF0D6FD10B1012D7D +:20A7600000F08A80002C27D02079864218BF022D74D1042818BF032803D1042E10D0032ECB +:20A780000ED0022818BF012812D1022E08D0012E06D0022818BF01280AD11CF0DDF807E0F4 +:20A7A000208882461AF0BCF808B9ADF814A003E0B81C14F085FF5C46BDF81430994514D1B4 +:20A7C00019F05AFF70B95448008882462DB11AF0A7F8002808BF504601D01BF0FDFDADF87B +:20A7E000140003464846984235D0BA7A1846B91C2B4611F0F9F907F1020A002841D14648F8 +:20A80000801D016811B1BDF814008847BDF814005146324609F078FC04463E4800784FF408 +:20A82000803141F288321CF047F83A494046087174B1022D05D0012D07D1607940F0100065 +:20A8400002E0607940F0080060718DF816B011E0ADF8149015E04FF0C70812E020888DF88D +:20A8600016B0ADF814002279BDF81400B91C2B4611F0BAF9D84604E04FF0C30801E04FF0CF +:20A88000C208C5B1254803789BB9012D11D144B902208DF816003146012268460FF004FB2C +:20A8A00030E08DF816B00122684631460FF0FCFA04E02A46F8E7684616F0EAF806469CB19E +:20A8C00045B16079022D40F04000607104BF40F020006071B87AC00903D3607940F08000FB +:20A8E0006071A079401CA07156EA08000AD014B1B81C14F0E5FEBDF814104846884201D05D +:20A900001CF02AF807B0BDE8F08FC046A07C0200FC09012050010120EA020120E50401205B +:20A920002DE9FE4F824C00906068C06801910121017080484FF0000A80F800A07E4880F8DA +:20A9400000A02068403001680D681E46174615B9D0F80C0580477949DFF8E481DFF8E49108 +:20A96000886E4FF0E2450AEA0702354008BF002A40F089800D46B5F89E10082253463A40F4 +:20A9800013EA060708BF002A0BD118B14246508B401C50834A4692F90000401E10701D204F +:20A9A000ABE04A4692F90030DFF89CB142F201468E42A3F10103137002D0321D8A4216D163 +:20A9C00018B14246508B401C5083584600680199826C0098904750B1424602F11601008804 +:20A9E000B5F89E30098842F60147874233D15748411C0A78B5F86610B1F5105F12D0AF6E49 +:20AA000042F60600884206D0002FC8D04246508B401C5083C3E7002F71D04246508B401C26 +:20AA200050836CE0A96F5B460C3319604189062A0CD1427A022902F10102427206DB491ED6 +:20AA400089B24181062002F0FBFD58E016F068FE0EF00EFA53E0491C361D88B29E42D082E8 +:20AA600014BFE1201C200FF0DBFC99F9000020B199F90000002854DC48E02068D0F85824AF +:20AA8000514650464CE04A4692F900102768491E117007F1400118B14346588B401C588316 +:20AAA0000868006840680078800925D2284A1078832824D125484378032B1BD1042347795B +:20AAC000D1F8945013707B1CDBB2437195F8241099420DDB817895F831304D1CAB42C4BF2A +:20AAE000491CCBB28370832010701BF0EFF906E0E12002E0852051E7E9200FF091FC99F99E +:20AB0000000040B199F9000000280ADC2068D0F84C05804705E02068D0F8582450460146AE +:20AB200090476068C06880F800A0BDE8FE8FC04614010020B40A0120B30A01205800012093 +:20AB4000D8180120B60A0120D805012004180020741B01202DE9F04F7F4E7068416EADF1D2 +:20AB6000340D02A88847DFF8F4B19BF9000038B17B4890F90000002818BF002040F0E9801E +:20AB80001BF0D8FEDFF8DC910A9099F80000800806D27D2000210CF09FFB0025079001E014 +:20ABA0000025079502958DF80C50059503228DF818206D4CA4F8BE50C4F8C45094F8C80059 +:20ABC000012705F00F013B4620F00F00014384F8C810DFF898A10B9394F8C81063F3C711D0 +:20ABE00094F8D73084F8C81023F0010007F0010343EA000184F8D71094F8D70067F34100D0 +:20AC000084F8D70094F8D70065F3820084F8D70094F8D70065F3C30084F8D70094F8D7001D +:20AC200065F3041084F8D70094F8D70062F3461084F8D700DAF80000D0F8282404F1D80140 +:20AC4000F4209047DFF8288198F80030A3B94946706809788446890910D3C06B8047C4F898 +:20AC6000C40094F8C81021F00F0141F0020184F8C8108DF80C700290D6F804C03E4A3D48D1 +:20AC80004FF080738DE80C00DCF850703B4B006804F1BC01894602AAB8470028708006D560 +:20ACA000022041F2883113F0F1FC0B954DE02C49334F91F90000401C087097F90000401C88 +:20ACC00038709BF90000C6F808902946401C8BF80000022013F0DAFCDAF8001001F1AC0217 +:20ACE0001068077888F8005007B18025308F17684FF67F7303401D432843308794F8D42076 +:20AD0000387860F3C71284F8D420D1F8D400C28CA6F84620428D00F14403A6F844201A686D +:20AD200006F13B052A6058686860D1F8D400C18CA4F8EE10418D00F14407A4F8EC10396803 +:20AD400004F1E4063160786870600A981BF072FF0B980DB0BDE8F08FD4050120B80A012054 +:20AD6000B70A0120701B01205800012014010020B50A0120B4060120200043006D450000C7 +:20AD8000B60A01202DE9F04F0646ADF13C0D032700200A91189D0C93297C0B920CE005EBF3 +:20ADA000C002127F530805D3D30803D212093CBF7F1EFFB2401CC0B2814201DD002FEED19C +:20ADC000B9460124002010E005EBC002177FFB1109D07A0807D307F0040207F00807174359 +:20ADE00004BF641EE4B2401CC0B2814201DD002CEAD1A346B9F1000F08BF002000F0CC805D +:20AE00004FF00008BEE04FEAC8002A184019007F02F11604400880F0B180002760480D97C9 +:20AE2000077837F0010714D1277897B9108B1BF00AFD70B10079012818BF032809D1A0792B +:20AE4000BBF1000F40F08000A07100F0968001200D900C98002814BF2027002700210C2256 +:20AE6000684610F0BBFF237813BB0A9800280EBF4FF0080A47F040074FF00A0A60884FF61B +:20AE8000FE71814228D104208DF81800E379ADF8243006A815F0CAF84FF6FE7000210346DF +:20AEA000B0800A46ADF8003007A813F0CBFE15E03C480078012808D0608847F00C074FF05F +:20AEC0000C0AB0804FF6FF7006E06088FF2147F00807217141F2080AADF800008DF80270D1 +:20AEE000307D8DF8040001238DF80530684607F061FE9DF8141061BB0398417D6171A0F8A2 +:20AF000016A00B9F4776277817B126490978017769890185698A4185297D80F82C106979D8 +:20AF200080F83A10217980F83B10F188C1873189A0F84010717D80F84910B1888187406CE3 +:20AF4000327D31691AF02AFE684616F093FC9DF81410A07940F00100A07151B90D9818B1A7 +:20AF6000ABF101075FFA87FBA9F101075FFA87F903E0A07940F00800A071297C08F10100F3 +:20AF80005FFA80F8414503DDB9F1000F7FF43BAF2846002113F042FC0FB0BDE8F08FC046AB +:20AFA000E5040120DC0101202DE9F041064606F11600ADF1380D16F0DDFE7A48007806F1F4 +:20AFC0001607012818BF02282FD100200DF1320501A905AC8DF8320001220095601A83B25C +:20AFE00001A907A815F084FE98B16F4800680DF1330101AA10F074FEADF81C00BDF81C40E8 +:20B00000C82C12DA03A8394608221AF0C7FD214606E003A8394608221AF0C0FDBDF81C10E5 +:20B020000420142201AB18F033FA3846FF211AF0F6FC10B15D4901200870002402A83946EE +:20B040008DF804401BF05CFC1BF05EF948B901A812F04EFE012804D02046394608AA19F0CD +:20B0600005F83079534D012861D006285FD0691C0B7804282AD0032840F0918038460DF1BD +:20B080001E0119F055FA58B14FF6FE7039460DF11E0218F0EBFF214638460A4613F0D2FDE7 +:20B0A000BDF81E0006A918F0F7FF069838B906A818F0B6F818B9BDF81E0006990880B11D84 +:20B0C00038460EF06DFC12F0FFF868E0002B66D038460DA901AA10F003FE01469DF83400F9 +:20B0E00000285CD08DF8154020460290019001278DF81640142201AB8DF81470042018F07F +:20B10000C7F9B21D4FF4817010211BF007FB06F1060828B94FF48170102142461BF004FB51 +:20B120002D1F384603216C7118F094F837E0721D1021204612F8017F1FB9491E00F10100B8 +:20B14000F8D11B4F10280CD07179B01D18F042FE387808B12878D0B170790DF025FB2C707D +:20B1600015E0387898B9204662210DF1220211F01DFD0DF12200214618F02CFE20460DF097 +:20B1800013FB0DF122002146102210F027FE0A480178052903D1C079802113F059FF0EB003 +:20B1A000BDE8F081E5040120EC060120CFE80020B50101206C060120C40301202DE9FE4FD0 +:20B1C0009B461546894682461BF0B4FB7B49019008680CAF504508BF48687B4C6FF0010827 +:20B1E00028B1B8301BF0A8F8002840F0D68019F023FD061C00F0DB8004F5CE701BF094FBCE +:20B200000023B4F9B400C6F80C90401C86F832306FF31F30A4F8B400C6F808B0B4F8B4003D +:20B2200030866748C6F810A097E80C0020210027B8461940104006F1180383E80300424699 +:20B2400086F8332006F1200383E88001E8683064287C86F8440028687063287986F8380013 +:20B26000A868F0636869B064A869F064287F86F85000687F86F851002F7C27B9EF6817B14C +:20B28000012086F844002F795FB999F80C0000F00F00022805D1012086F83800D9F80800BF +:20B2A0007063484608274568002D18BF002F70D100886FF30900B0F5305F18BF022506D1E1 +:20B2C00096F83300082540F0100086F8330006F1180090E80C00414606F1180745EA02002E +:20B2E000194387E80300D4F8D800824507D194F8DC00410824BF00F0FE0084F8DC003148EA +:20B300000768002F39D004F1A0000090D4F8A810D4F8AC2004F198052B463046B84710F1CC +:20B32000030F10D0B6F93010B4F9B420914207D0B4F9B41001F6FF716FF31F31A4F8B41017 +:20B3400010F1020F1BD010F1030F18D096F83300B6F9308040F0800086F8330000278AF8CB +:20B36000FC702868864205D0F068007B00F00F0002281CD112F002FA19E06FF00200B4F946 +:20B38000B410804601F6FF716FF31F31A4F8B41005E07F1E2846FFB285E76FF0020894F8A8 +:20B3A000DC0040F0040084F8DC00C4F8D8A001981BF040FC4046BDE8FE8FC04620F3002020 +:20B3C000FFEFFF9F040B012068F200202DE9F04F8246DAF8185069782878EA7800EB0120F1 +:20B3E000A978ADF1240D034601EB0221069116F0E1FA012800F0D6804FF00008CDF8108082 +:20B400001846CDF8148016F0D5FA2D1D48B96F480088984205D06E480078022800F0C280DD +:20B42000D0E015F8014B5CB160000EF0C9FD049030B1049A204629461AF06AF8054600E053 +:20B44000444615F8017B5FEA07090AD078000EF0B7FD059028B1059A384629461AF058F828 +:20B4600000E0C1465B480568002D76D04646079608966868017800296CD0AA7B520869D332 +:20B48000AA68002A04BF8668DDF820B004D0012090474FF0010B0646002E5BD070880699C7 +:20B4A000814204D006984FF6FF7181424CD1F279B3680499204618F09EF838B9327B336961 +:20B4C0000599484618F097F800283DD009EB0400022110FB01F01430C0B219F037FD071C47 +:20B4E0002AD0D2203870BAF80200788087F80C90002C3C7104BF0798B86008D007F11400BA +:20B500000499B860620007F114001AF047FBB9F1000F04BF0898386108D0059907EB44005B +:20B520004FEA4902143038611AF038FB686840680078394615F056F93078274908F1010791 +:20B5400001F808005FFA87F8BBF1000F02D0304616F090FA2D68002D8BD1B8F1000F05D1D3 +:20B560009AF80C00A8B90023984600E00023174800880090CDF80480174F02979AF8100067 +:20B5800003909AF811100AF1020248F2060012F01BFD049808B116F06DFA059890B116F066 +:20B5A00069FA0FE000930020019002909AF8100003909AF811100AF10202802348F2060099 +:20B5C00012F002FD09B0BDE8F08FC046E0030120E5040120C00A012054050120FEB50E460D +:20B5E0001BF0A8F900257F4A7F4C517855708A080ED2C9081AD31BF01DFBA4F1080000F177 +:20B6000008048068D0F858242846014690470FE01BF010FB6068C068007828B92068D0F8C8 +:20B6200058242946012090471BF084F91BF002FBB00941D337E02168D1F898205060009861 +:20B64000D1F8401388472168D1F89800D1F85413001D884732E01BF06DF92168CA6B117B2C +:20B66000491E11731BF0E6FA216800983C31CB6D0278586000988DF8042047782FB1162ADC +:20B680000AD1D1F81813684601E0D1F80413884721689DF804203C31162A06D0C86DD1F8DA +:20B6A0001813001D884721683C310868001D18F04CFB00280090CED1300C08D32068D0F8E3 +:20B6C0009400007813F096FC00280090B3D1700907D327682E20D7F840138DF8040001A809 +:20B6E0008847700807D327682520D7F840138DF8040001A88847B00807D327682620D7F8FC +:20B7000040138DF8040001A88847F00807D327682720D7F840138DF8040001A888473009D1 +:20B7200007D327682920D7F840138DF8040001A88847F00909D32D2027688DF80400D7F82B +:20B7400040138DF8055001A88847300A09D3302027688DF80400D7F840138DF8055001A821 +:20B760008847700A09D3352027688DF80400D7F840138DF8055001A88847300B07D38DF829 +:20B78000055037208DF8040001A81BF037FA700B07D38DF8055038208DF8040001A81BF0CB +:20B7A0002DFA2068D0F898000068C8B11BF0C2F82168D1F898100A6800920D601BF03AFA2A +:20B7C00021680098D1F8982050600098D1F8401388472168D1F89800D1F85413001D88478E +:20B7E0002846FEBDD8000020140100207D492DE9F04F0A680646ADF11C0D0DF10E000260E5 +:20B8000049684160F08900280CBF08210221B569764A15F80180D0B973490F781046294621 +:20B820001AF0ACF880B937F001004FF6FE7434D128461BF035F800282FD00179012918BFF5 +:20B8400002292AD1048821E06948048825E069782878674F00EB01243888A0421CD0624973 +:20B860000878002530F0010017D120461AF0EBFF98B10179012910D18DF800504088ADF8B0 +:20B880000C00684614F0D2FB00B101ADB8F1000F18BF4FF0FF0800E015464FF6FE70A04219 +:20B8A00018BF002D03D1377B002F40F0988051494F68A0424FF00B0910D07DB138F00100CA +:20B8C00008D0307B012800F08A804FF0000B4FF0800A0DE04FF0000BDA4609E0F3894FF0B4 +:20B8E000000B4FF0810A002B0CBF441C0DF10E0507F801AB002D14BF291C0DF10E01384691 +:20B900001AF0FEFF0746384D07F8014B20123870287830F0010053D1B8F1010F50D13448EE +:20B920000088A0424CD1BAF1000F49D18DF816B00DF1160012F01AFD7F1C051C3CD0F489EF +:20B94000002C0CBF08210221B0699DF816404018427805EB4201A242A4BF58468DF81600DB +:20B960000ADA9DF81600801A8DF816009DF8160009EB40095FFA89F99DF8160007F8010B8A +:20B980003A709DF816407CB17F1E087807F8020F9DF8164031F8020B00127870601EC4B2A9 +:20B9A000002C8DF81640F0D1284616F063F809F102005FFA80F903E087F800B04FF00C09BC +:20B9C0000C49F28910204B46C87042F4004206F11100B11C12F060FB064880F803B007B0C4 +:20B9E000BDE8F08FE07B0200E50401201C030120E0030120280401202DE9F0470646F08919 +:20BA000017468946ADF1280DC01D80B205460DF00DFE7A4CFF280BD12846FCF715FF8542C0 +:20BA200004DD641C207800B90520E3E0012000E000206178D9B917B1022F18D1B8B1307AEB +:20BA40008DF80C00F788ADF80A70B588ADF8085000230093E18E94F8330001AA032304F0D4 +:20BA60004DFA9DF814003074BDF81070B78194F83310E58EE06806AA0423884649031AF040 +:20BA800085FE069800F0FF0100F0FF007E2806D140467C2117F08AFE069901F0FF017C2942 +:20BAA00040F0A580F08942F20102C11D8FB2E9198A4240F39A80F188327AC1F301238DF8C5 +:20BAC0001D10B18843EA82038DF81C308A1006468DF81E200423C0F3851201F0030142EA42 +:20BAE00081128DF81F2010FB03F1F21D01F0FC01731990B28DF820101FFA83FA0D282BDB9F +:20BB00004846314600221AF079FD0246052107A81AF074FD9DF82010334600F03F064A46E3 +:20BB200041EAA011B0008DF8201040F0020096268DF8210029468DF82260404615F06AF9CC +:20BB40000646514607AA07234046667015F062F9304360704DD135E004F1240049463246D5 +:20BB60000DF0D4F907A90A68301900F12409484609790260731D0171002204F1240099B278 +:20BB80001AF03CFD9DF82010962300F03F068DF8223041EAA011B0008DF820103B4640F0E6 +:20BBA000020007AE49468DF821003268B0790A60B288887140468A8004F12402294615F01A +:20BBC00029F96070E18EED194FEA8806AAB2C919E18606EBC8010919A1F84C2048B1404632 +:20BBE000514614F0D9FD607803E0052000E001206070C0B20AB0BDE8F087C046C0190020DC +:20BC00002DE9F04F09AF3D7AD7F804800E1C9A4693460446ADF12C0D26D0207A29098DF8C2 +:20BC2000260010D302281FD121881AF0C9FC884209D008460322012111F0F1FF002818BF41 +:20BC4000CD2040F0D580237A022B07D00F2B05D0032B0DD0012B0BD033B909E0208815F02E +:20BC6000A9FE18B90F2B03D10220C1E00F2323728DF80830032B1CBF2088ADF8000003D1CD +:20BC8000684621461AF03CFEA8081DD25A484FF000090368ADF8109043B15868864203D0C3 +:20BCA0001B68002BF9D101E09A681AB9B3688BB158880DE031780220904758B10188ADF859 +:20BCC000101015F0D7FE05E04FF6FF704FF00009ADF810006809ADF818900BD39DF808009B +:20BCE0000F2807D0012805D0BDF8180040F00400ADF8180035F07F0005D0BDF8180040F004 +:20BD00001000ADF81800E80938BF484606D3BDF8180040F00100ADF8180001208DF8250081 +:20BD2000E80805D3BDF8180040F04000ADF818008DF82490A80934BF012004208DF81B007F +:20BD400039680591ADF80EB0ADF812A03D7B8DF81C50637A8DF80B3098F800008DF81A007D +:20BD60006189ADF80C1030788DF80A0019F05EFD20B1016911B168468847637A19461AF0BD +:20BD80002DFD78B909A815F041F9504506DA1B480168A1B168468847074611E0684600F06C +:20BDA00031F9F9E716480068D0F80001C0892238C0B2504503DB684605F010FCECE70227B7 +:20BDC0009DF8080002280CD11AF0FAFBBDF80010884206D1307898F800105A463B4616F0EB +:20BDE00051FE27B998F80000401C88F8000038460BB0BDE8F08FC046C00A0120E80601204B +:20BE0000140100202DE9F84F0AAF97F80090984692460D46044615F0C7FC0746754800266D +:20BE2000B346002F38D1B9F1000F20D117F016FB071C00F0DC8031461C220FF0CFFF3C8062 +:20BE4000BAF1000F7D8106BF0120B87487F812A069485E300078012818BF072002D15046A0 +:20BE600019F0A7F8787406203874BDE8F88FB9F1010F0FD105466878B8F1000F52D030F071 +:20BE800001074FD15C49097889084BD3204617F035FD41E005463FE005466878B9F1000F97 +:20BEA00012D1B8F1000F0BD1B97851444910CBB2BB700BB90121B9707B780BB90321797071 +:20BEC000B97806292EDD2BE030F0010306D14B4920310B6813B1184680476878B8F1000F18 +:20BEE0001CD030F001031DD143490978890819D342482430026812B1414638469047387823 +:20BF00000D2809DA401CC0B20C28387004D1204617F0F4FC7E700126687803E03146397035 +:20BF20004FF0010B022825D1B9F1010F22D1B8F1000F1BD0B8F1EB0F18D0B8F1E10F19D039 +:20BF4000B8F1F10F16D0B8F11A0F13D0B8F1190F10D02A49AB7D0A79521CD2B29342C8BF80 +:20BF60000A7107DC002201260A7106E023490022091D0A7056EA0B0739D030F0010714D123 +:20BF80001D490978890810D320461AF05CFC58B1BBF1000F03D0417901F0FE01417136B3A2 +:20BFA000417941F001014171687806B3144E30F001000DD196F83200800809D3204619F055 +:20BFC0008CFD28B12146002017F0F6F8BDE8F88FF08FA0420BD12146012017F0EDF86878C6 +:20BFE000022804D14FF40050012103F0D7FCBDE8F88FC046E404012082010120E4020120E1 +:20C00000500101202DE9F04705467B4895F80B900078ADF1180D002808BFBA2000F0E980CE +:20C02000684600210C220FF0D9FE01264FF0000A298B8DF80560C8080AD39DF80220C810E3 +:20C040000B0942F040028DF8022038BF032602E09DF80220C8104B0928BF46F04006400821 +:20C060000FD342F0C00288098DF8022039BF9DF8030040F002009DF8030040F001008DF8A2 +:20C08000030001EA6100000A28BF46F00806287A5A4F002830D00F2828D0022822D0032833 +:20C0A00018D0012832D1387848B94FF6FD70ADF80000288842F00C0246F0040608E028889C +:20C0C00042F0080246F480564FF0FF09ADF80000824619E02846694617F0F0FA9DF80220A2 +:20C0E000298B13E02888ADF800000FE0288842F0080246F0040605E01AF062FA9DF8022027 +:20C1000042F00402ADF800008DF8022048081AD312F00C0F0DD1288813F08FFD002808BF35 +:20C12000BB2066D09DF80220298B42F020028DF80220480807D302F00C00042804BF42F03F +:20C1400020028DF80220A87C8DF80400684606F031FD9DF8140000284BD1039CE682E87E3D +:20C160006076287FA076287A012804BF38782077A87E2085288B6085E87F84F82C00288B32 +:20C1800000EA6000000A15D395F82000667D804617F0B2F9071C0DD03A7C002008E007EBAB +:20C1A000C001CB7E984504BFCE763A7C401CC0B28242F4DCA87A84F83A0084F83B90A4F8BE +:20C1C0003CA0E889E087288AA4F84000A87E84F84A00A87F84F84B00687F84F84900606CCB +:20C1E00069696A8A19F0DAFC684615F043FB9DF8140006B0BDE8F087E3060120DC01012026 +:20C200002DE9FE4F07462C200DF0DAFE0028386100F0E48000212C220FF0E0FD38694FF607 +:20C22000FF7585823C6938880DF1020111F03AFADFF8B4B158B30DF10200694619F0C8FB26 +:20C24000BDF80000854222D000200626BDF800102074BDF80020634B66828E00A28206EBBD +:20C26000C100C2181168A1611168491C11601E584FF47A74B6FBF4F06043361A07D1012031 +:20C280005E46107230784FF4006112F0E1FE39693888083111F006FA5448846880461AF057 +:20C2A00033F868B138690021418238696826868238690223037438698461621CC8F8082055 +:20C2C0004B48D0F800903869DFF828A10446A18A2E468E4254D104F10800494619F04EFB76 +:20C2E00048B919F02BFC0146484619F047FB10B91AF00AF860B13888396902F065FC00242E +:20C3000000B1012400200CB139698D823969087438690446A18A8E4232D15146303991F829 +:20C320002F303BBB91F86510012923D101200DF10A013A221AF0E3F8C8B901209DF80A5090 +:20C34000207400233A22A5755D466382D8F80410A2822878A161D8F80410491C0129C8F84B +:20C36000041005D14FF4007112F072FE00E0A5823C692046828A3146914204BFA121397512 +:20C38000818A8E4224D0017C01290ED0BE6856B919F0BAFF20B9B878400838BF052100D311 +:20C3A0000D21204602E00D2100E00E210177B87800F0030001281ABF51460878052039694F +:20C3C00048703C69607819F031FC6077BDE8FE8F15F050FB00203861BDE8FE8F10203875D1 +:20C3E000BDE8FE8FE0E80020CB030120100A0120EC060120800101202DE9F04785682A6878 +:20C40000D16944681162490832D3D4F8C01049BB2968486820F0020048602968486A20F07F +:20C4200003004862D4F8CC002A6941686F69096847EA0200C862D4F8CC006E6941682A692A +:20C44000096846EA0200C1F804052968486920F001004861286801210162284618F038FABE +:20C46000BDE8F08703220A7402F08AF9BDE8F087D4F8CC0041682A696F6909684FF0000907 +:20C480000226CA4647EA0200C1F80405D4F8C070002F00F0A880D4F8CC00D5F814E040682B +:20C4A000D4F8E0C0D0F80080BCF1000F04D1EA69A86904F1D80103E004F1DC016A6A286AEA +:20C4C000D8F8043513EA0E0F11D0806810F0070F0DD13868D4F8D030984208D17F6937B985 +:20C4E0002B68586A20F002005862C8F804E5906810F0070F74D10F68002F71D0D4F8D40098 +:20C50000BCF1000F3844C4F8D40014BF48462020C4F8E000C1F80090D4F8C010D4F8D02075 +:20C52000086890424BD8D4F8D420904247D881F81090D4F8C80004F1300730B9D4F8C01087 +:20C54000C4F8C810D4F8C80008E04369002B34D1D4F8C0104161D4F8C01040694969C4F8FE +:20C56000C010C0F814A0D4F8E00000280CBFD4F8D800D4F8DC00C4F8D000D4F8C000C4F8C0 +:20C58000D49088B12046294605F02AFB94F8FE0078B1D4F8CC00406801686869D1F80425F0 +:20C5A000024218BF886204E02968486A20F00300486238461AF0DEF912E01846C5E72046D1 +:20C5C000294605F00DFB94F8FE0048B1D4F8CC00406801686869D1F80425024218BF8862FB +:20C5E000761E7FF453AFBDE8F08770472DE9F84F0746714D714C28684030D0F89410267830 +:20C6000091F883B026B1D0F80C0580472868403001680E6816B9D0F80C058047A046694901 +:20C62000674C0120012F88F80000D1F8009067702AD9DFF894A1654EBF1E59D07F1E52D0BF +:20C640007F1E3DD07F1E73D07F1E34D12968096C096891F86D20628191F86E70002F06BFE3 +:20C66000E070071CE770686840683178007811FB00F0784381005046C16690F8701021F049 +:20C680000F0141F0030151E000202E686071306C0068D6F8D410C08AC00934BF91F8250033 +:20C6A00091F84E00A070B7B9CF78A7B10228C4BF0220A0700FE02868D0F84C05804737E02F +:20C6C0002868006C006890F86910617190F86A00A0700027A77109F0C7F92868006C0068C5 +:20C6E00030BBBDE8F88F0020607116F053F81FE030788700D9F83C00804771683C22401A4E +:20C70000B0FBF7F0B0FBF2F15143401AC0F1780086B2D9F83C00804707FB06015046C16610 +:20C7200090F8701021F00F0141F0020180F870102748007898B92868403001680F682FB9A4 +:20C74000D0F80C0580472868006C07687A686178107800F0200020719078E07100E06178D8 +:20C76000032903D0022918BF062923D11AF0E2F805466078022815D01648077817B9164973 +:20C780000F787FB10221BBF1010F88F8001004D10078832801D112F027FE28461AF04AFAC6 +:20C7A000BDE8F88F832088F8000028461AF042FA18F098FBBDE8F88F14010020741B0120CA +:20C7C00004180020D805012058000120D8000020641B01206F1B0120711B01202DE9F04F61 +:20C7E0000746ADF11C0D10980D460590287A99461646012818BF032805D127B1FF2F02D0DF +:20C80000032802D10EB90020CFE0694C237833BB0420684B8DF800001888ADF8020019F09A +:20C820008DF90DF104080146404619F053FE684606F0EAFC19F0B2FEBDF8021081420BD099 +:20C840004FF6FE71814207D0ADF80200404619F0FEFF684606F0D8FC01202070287A4FF04D +:20C86000040B02284FF000048DF800B015D003280AD001281CBF4FF6FE71ADF80C1017D1BC +:20C880002888ADF80C0012E001A8294619F022FE684611F02DFA38B109E02888ADF8020005 +:20C8A00068460FF0D5FA10B9684606F0ADFC287ABDF80C10012818BF049402D1012026467B +:20C8C00004904FF6FE7088426ED0DFF8EC8025460E2015E015FB00F318F80320BA420DD128 +:20C8E0004344DDF810C05A78624507D15A888A4204D11A79B24208BF1C1C04D06D1CEDB2B6 +:20C90000002DE7D02CB3B9F1000F4DD0DDF814A04F468146AAF1020A3AF8026F2046314672 +:20C9200018F0D2F990B984B1607904280DDA04EB4000C6806079294615FB09834A46401C75 +:20C940006071022016F0A4FD00E000247F1EE3D12AE02546824625E015FB0AF018F800206C +:20C96000FF2A1DD100EB080408F80070049860706180B9F1040F2671C8BFD94605994FEA1B +:20C980004902A01D84F8059019F008F92B01022029465246A3EB4503434416F079FD03E063 +:20C9A0006D1CEDB2002DD7D0204607B0BDE8F08F200901208A010120220100202DE9F04FAC +:20C9C000724C002704F19800ADF1140DB946B846056802978246CDF80C903DB3D4F8AC0092 +:20C9E000B84203D1D4F8A800B8421DD0D4F8A8600EB3D4F8A8102869096988421BD195F8AF +:20CA00003300400917D3D4F8AC60A6B90127D4F8A800C06840880028F9D0D4F8A800C06860 +:20CA200040880128F3D006E0012704E004F1E000022119F09DFF002D43D087F0010B03A845 +:20CA400002AA59460BF010FE5FEA000809D0012F07D0039929B104F5AC7019F071FA4D46BF +:20CA60002FE0002D2DD04A48066856B3B8F1000F27D0039828BBCDF800B002980190D4F8DB +:20CA8000A800D4F8AC100AF108035246B047401E02D0401E08D014E0029800B92846012194 +:20CAA0004B460091014605E001230093D4F8A800D4F8A8100069B1F930104A4604F056FC50 +:20CAC00060E0002F5ED0002D5CD060682969884252D1B8F1000F0BD0039848B1D4F8A8007E +:20CAE00030B9D4F8AC0018B9082016F0FDFA49E0082018F047FE95F8330004F1E006C0F3F3 +:20CB0000001028B9504618F010FAC4F8A80004E0504618F00AFAC4F8AC00A8691D49C043B0 +:20CB20000860A8694A6810434860E869C04341F8080CE86951F8042C104341F8040CEC6874 +:20CB40000820294618F08AF8204618F051F82088A0F6020040B141F21E01401A04D041F615 +:20CB6000E671401A012803D80120214618F076F84FF08041304603E004F1E0004FF48061B0 +:20CB800019F0F6FE05B0BDE8F08FC04668F20020080B0120101004402DE9F047ADF1200D8F +:20CBA000109C1D4682460E469046E811002110221FFA80F920460FF011F9C5F3C307D6B11E +:20CBC00004A82146102218F0E9FF20465146102218F0E4FF04A8214616F088F810262246CF +:20CBE00013781AF8011B761E81EA030102F8011BF6D18035ADB24846411E00281FFA81F9E0 +:20CC000040F09980002F72D00E2F28DA04A82146102218F0C3FF204600210E220FF0DEF880 +:20CC20003A462046414618F0B9FF2E128020E05521461022E5736846A67318F0AFFF04A898 +:20CC4000214616F053F810206B46227813F8011B401E81EA020104F8011BF6D187E004A8BC +:20CC60002146102218F09AFF2046002110220FF0B5F83A462046414618F090FF802021460A +:20CC80001022E055684618F089FF04A8214616F02DF8102721466B460A7813F8010B7F1E2C +:20CCA00080EA020001F8010BF6D104A82146102218F074FF204600210E220FF08FF8281205 +:20CCC000E57321461022A073684618F067FF04A8214616F00BF810206B46227813F8011B76 +:20CCE000401E81EA020104F8011BF6D13FE004A82146102218F052FF204600210E220FF016 +:20CD00006DF82F128020E573214620701022A773684618F043FF04A8214615F0E7FF10200C +:20CD20006B46227813F8011B401E81EA020104F8011BF6D11BE004A82146102218F02EFF61 +:20CD400020464146102218F029FF04A8214615F0CDFF22460021137818F8010B491C1029D2 +:20CD600080EA030002F8010BBFF645AFF3E708B0BDE8F0872DE9F8430646307B8946034689 +:20CD800018F0C4FD0125041C5ED1D6F8008077891C461C200DF014F950B100214173047312 +:20CDA000478101818173C173C0F8008041614160041C00F0C18000270781307C2074708A4C +:20CDC0006082337C23BB716911B30F460E200DF0F7F8E0B1394691F83820027091F8392092 +:20CDE000427091F83A20827091F83B20C270CA8F8280B1F84020C28091F84220027291F808 +:20CE00004A2002734A88428191F849104173074638466061308B20836189B07E4FF67F47FB +:20CE20002E46A07607EA0100C108608108D2454914310A78802707EBC2110843608104E021 +:20CE4000608940F08000F9E700266089DFF8F080B9F1000FC0F3C21224D10AB3810911D2A4 +:20CE6000410909D2C00838BF281C10D319F093FC00F02000801C0AE019F08DFC00F00F00E8 +:20CE80000A3004E019F087FC00F07F005F3020810420474660733878202112F0D9F817E00A +:20CEA000002515E0022060732068C089C00803D3404634300088208152B160894FF67F41F0 +:20CEC0004FF680770140618107EBC21001436181012E32D1667B27893CB3012E0AD0042E1C +:20CEE00002D0022E0BD020E0042017F07DFF142805DD1AE0012017F077FF202815DC6673E6 +:20CF000000202781104960600868002808BF0C6003D00146486830B94C60404600782021C7 +:20CF200012F096F809E00146F4E7606908B114F0A1FD204614F09EFD00252846BDE8F8837A +:20CF400050010120E5040120E40A01202DE9F0430E4680460E220021ADF11C0D03A80EF022 +:20CF60003DFFB06A417811F01F0F18BF002040F0CC80880924BF01208DF8180031F07F002E +:20CF80001CBF01208DF81700C80924BF01208DF816009DF816200024012A03D0307A00B141 +:20CFA000B46902E0F07900B1746934B10DF10E00214619F0A5FC9DF81620554DB189012AA7 +:20CFC0006F78ADF80C1020D1287F27F00102104300F09A80002F00F09780022F04D119F055 +:20CFE000DDFA884240F09080708914F0E3FC002840F08A804CB118F0A1FD01460DF10E001C +:20D0000018F0BCFC00287FD06F78DFF8089137F0010019D148460078800815D39DF816004F +:20D02000012811D0BDF80C1019F0B8FA88420BD09DF81700012807D0084618F05AFD18B193 +:20D04000BDF80C0015F0C4FB9DF81600012821D0BDF80C1019F0A2FA884211D19DF81700B8 +:20D06000012808D02C48007800F00700022807D101208DF818009DF818000AF055FB3EE0F7 +:20D080009DF817209DF8183008460DF10E0107F089FB34E000249DF818008DF81A4028BB6A +:20D0A0006978074631F0010003D0022908BF251C01E09DF8175019F0F6F8484618300078F8 +:20D0C000082818BF042811D14FF6FD70ADF8000018F034FD01908DF809408DF808708DF8CA +:20D0E0000A508DF80B4068460CF0EAFC9DF818000AF01AFB52200DF11A0114F05BFE074883 +:20D10000016809B103A88847404607B0BDE8F083E404012082010120501A01201C040120A4 +:20D120002DE9F043002507460C22ADF1340D294668468DF814500EF051FE6A4CDFF8A8811E +:20D14000B87804282DD001280BD0062809D0022805D003281CBFB3208DF8140024D11B20CA +:20D1600020E06078D8B919F097FA40B9B9684646082206F11C0018F011FD38883080E079EA +:20D1800002280CD1B8680BA906AA0EF0A9FD9DF8280010B99DF82C0008B9B1209FE02320C5 +:20D1A00000E022208DF804009DF81400002840F087803888BE7BADF800003B698DF8056090 +:20D1C0007A7B0293012A14BF012021208DF80200684605F0EFFC9DF81400002870D10398A3 +:20D1E000466C05233370B8787070796829B9B01C294610220EF0F2FD03E0B01C102218F09C +:20D20000CDFCB8781236012812BF0628F87806F8010BB968304619F05DF9B878083604289B +:20D2200006D0012804D006281CBF387B307004D1AB202946324613F017FA388814F0BAFBAB +:20D2400010B103980421C1829DF81400002837D1B878042809D0386918B9684614F00AFBD3 +:20D260002EE068460CF04EF92AE0B8680DF12D0106AA0EF035FD06469DF82D0018B94FF655 +:20D28000FF70B0421CD038694FF0010918B9684614F0F0FA02E068460CF034F9B96808A860 +:20D2A000082218F07BFC8DF8289028468DF8295031461422079006AB0690042016F0E8F887 +:20D2C000607850B919F0E8F938B946462946082206F11C000EF082FD35809DF814000DB0C2 +:20D2E000BDE8F083E4040120B4080120F8B5694C2168054614310868407F002800F0C88026 +:20D30000D1F8C000B5F84220C08C904240F0C080D1F8581305F128008847002800F0B88076 +:20D32000206840690026467721687031486E90F8290028B16068816A0220884721687031A1 +:20D34000086890F82B0018B16068816A01208847287C400908D36068816A1020884720683C +:20D36000D0F82813802088476068C16B202088472168C868D1F8FC1410308847686822683D +:20D3800041785269007800EB0120C0F30321517622685269C0F3003797762268526900F086 +:20D3A0000F03C0F3031793772068D0F8D40080F82C7022680C32D2F8C81091F84F000F28D3 +:20D3C00006D093689B7F984202DD6B68DF780FB19068807F4873106880F83060D2F8C800FB +:20D3E000417B0F290BD19068C07E022850D1D2F8580180472068D0F86C018047F8BDD2F8EF +:20D4000000252846904723680C339868C07E022815D1D3F8F014186888472268D2F8D40044 +:20D420001169467BD06831F81630D2F8F0244FF4707707FA06F1C91A904723680C33D3F8BB +:20D44000C8002A89D3F8A83190F82C1002209847206800F11401D1F8C020D0F8D400527B48 +:20D4600090F82C0082420FD00868D1F8E81488472268D2F87C015169886050694169D2F8B1 +:20D48000F024904721681431D1F8141310208847F8BDC046140100202DE9F047674CA368E9 +:20D4A000002589468046ADF1280D002B8DF8245000F0BC802F46FF264FF6FF7AB8F1030F7C +:20D4C00018BFB8F1020F04D193F84200904240F0AD80384617F0A8F8B8F1010F04BF8520A4 +:20D4E0008DF82400B8F1000F10D0B8F1030F0DD0B8F1020F08D1A068B9F1000F0CBF012112 +:20D50000022180F841100DE0A0680BE0A0680121B8F1030F80F8411004D1B9F1000F18BF2C +:20D520008DF82490B8F1000F4FF0020112D090F84120012A0ED190F8433033B990F84830FC +:20D5400013B15B1E80F8483004E090F84320521E80F8432090F843304BB990F8483083B151 +:20D56000A568C26C867B00F12007AD1D05E00746A568426C97F82E60263502EB430232F8CC +:20D5800002AC9DF824308DF8181043BB3FB390F84110012914BF212422247988254BADF8E0 +:20D5A00010101978032280F842100DF11A0029468DF8222019F0A4F9CDF800A00DF11A005A +:20D5C0000190029678780390BB7BBA1D04A920460DF040FE1848008817F026F826E0418868 +:20D5E000ADF8101009AF009740780190A06848F22002012304A914F02DF804F108052868DE +:20D6000090F8401002290FD1418CADF8101009AF009790F821000190286848F220020123FC +:20D6200004A9203014F016F811F09CFD0AB0BDE8F087C04628040120E40601203C050120AB +:20D640002DE9F047634F8046381D0068416EADF1280D02A888475B4D2A68403210680068C1 +:20D6600020B9D2F80C0580472A68403256484FF001096E6880F80090F068007830B9D2F8E3 +:20D6800018244846002190472A684032106801684C68088921788246C1F3401109F01CFE25 +:20D6A000079010F095FD494E746786F873A00024A6F8664019F03EF9059482463146B8F115 +:20D6C000010FA6F8664004BF4148C1F8B80038F001083E4654D1A1F89E4001F16400C1F8D9 +:20D6E000A00091F8A90002231A4602F00F0220F00F00024381F8A92091F8A80004F00F07EF +:20D7000020F00F0047EA000291F8B3708C6627F00F0081F8A82040F0040009F00F0291F8EB +:20D72000717081F8B30027F00F00024381F8712028684030006800684268127801F1640706 +:20D7400092090FD301F120028A66406891F87150807803F00F0381F82E0025F00F00034348 +:20D7600081F8713001F1100001F19C0242604A7F04F00F0322F00F0213434B77014601E029 +:20D7800064310F467068174A056D08238DE81800114B106802AAA84710490028088006D4EA +:20D7A0000F4991F90000B760401C087004E0484641F2883110F06AFF504619F03BFA0AB047 +:20D7C000BDE8F08714010020B30A012058000120801A0600D405012021A90000D40A01203E +:20D7E000B60A0120B40601202DE9F04FDFF898910646A9F1080000F108078068D0F8000179 +:20D80000807AADF12C0DC0000CF0DAFB0028089008BF1A2500F0B48019F08CF800244FF0CC +:20D82000FF0B25460A9027E0ADF800608DF80240D2F88823D02069469047D8B99DF80C00E9 +:20D84000012802D19DF80B1019B998B99DF8071081B1002814BF082304230DF103005B1E54 +:20D8600000F801BBFBD105703868D0F894246946D0209047641CE4B23A6802F58072106804 +:20D88000C07AA042D0DC4C462068D0F80001C0884FF6FF78AA461DE0089901EBC0018A888C +:20D8A00096421CBF401CC0B261D1C1F800A0A1F804803A68D42004A9904702E07F1CBFB237 +:20D8C00025E020682268D0F800016D1CEDB202F58072C088A842D8BF55464BDDADF80060C6 +:20D8E000ADF80250D2F88823D120694690470028E7D1BDF804008045E3D0ADF810002068F7 +:20D90000D0F8882404A9D420904790BB5746226802F580721068C088B84210DDADF8006014 +:20D92000ADF80270D2F88823D120694690470028C4D1BDF81000BDF804108842BED12068B8 +:20D94000D0F80001C088B842BBD1ADF81480ADF8168006A8594608220EF040FA2068D9F8B4 +:20D96000003000F29447D3F80001837A5046834292DC19250A9819F05DF9089814F07AF8C3 +:20D9800028460BB0BDE8F08F140100202DE9F04160485F4E614C604D70601030B06004F1FA +:20D9A0004400B0E88C1005F17C01A1E88C108DC881E88D00182204F1140705F13400394619 +:20D9C0000BF0A4FA1822394605F14C000BF09EFA05F164071822384604F12C010BF096FA5A +:20D9E00095F870003C2204F1840140F0800085F8700005F1BC000BF089FA95F8CB100120FC +:20DA0000024602F0010221F001010A4385F8CB2095F8CB1060F3820185F8CB1095F8CB1003 +:20DA200021F0200185F8CB1095F8CB1060F3C71185F8CB1004F16401B1E8085105F19C0291 +:20DA4000A2E8085191E80A5082E80A50C5F8A07095F8A81060F3C71185F8A81095F8A91094 +:20DA600021F00F0141F0020185F8A910042385F8AD30052185F8AC1095F8AE1000F01F02DF +:20DA800021F01F010A4385F8AE20032185F8B01095F8B31000F00F0221F00F010A4385F820 +:20DAA000B320B4E8841005F12001A1E8841014CC81E8140095F82C1060F3C71185F82C1025 +:20DAC00095F82F1003F00F0321F00F010B4385F82F3095F82F1060F3C71185F82F1095F8EA +:20DAE0002D1000F00F0021F00F01084385F82D004FF4586028630A48F0600A480068406949 +:20DB0000007808B10CF08AF90AF0BAFCBDE8F081A40601205817002058000120207B02001F +:20DB2000140B01201801002001282DE9F84F40F0B080DFF88491D9F83401012840F0A68015 +:20DB40000220C9F8340117F0C9FD012015F05EF85FEA000805D00120C9F8340117F0CCFD57 +:20DB600099E0112018F074FD00280CBF00250125102018F06DFD08B145F002050F2018F076 +:20DB800067FD08B145F00405444CA06A0068014601208847012805D099F83801012818BF29 +:20DBA000002703D1002004F045FD012718F04AFDDFF8ECA040080AD20026206A8068014637 +:20DBC000504688478346BBF1040FF6D000E00126304600214FF0FF3201F08EFF012E0ED0F9 +:20DBE000BBF1010F05D1206A4068012102465046904732496C39086840F0030008602068D7 +:20DC000040690146284688470B2018F021FD254E30B12068C06A3146091D02460888904734 +:20DC20000A2018F015FD28B12068C06A31460246088890471C4903200124C9F834011B4EE3 +:20DC40000C6000233360284612F05AFD0128FAD1174D2868042014F0D9FF064615480460E6 +:20DC60002868012F02D1204604F0E4FC18F0BAFC082014F0CBFF0746C9F8344117F03CFD60 +:20DC800057EA060018BF4FF0FF3804E06FF0040801E06FF001084046BDE8F88FB8010010DD +:20DCA000004003406A810200282008600C2008402C2009400C400940501800209022084024 +:20DCC000F8B5074661485F4C001DC26A0168B7F5C067C2F30722C4F81071C1F38441C4F821 +:20DCE0001421C069C4F81811C0F38120C4F8280100F0A38094F830616EB9C4F82C71D4F82C +:20DD00001801C4F82001D4F81461C4F81C61D4F82851C4F82451D4F82C01D4F814510028CB +:20DD200054BF02236FF0010304F59072116800EB4000C018431000EB937001EBA001116092 +:20DD4000D4F82011C4F81C5100291CDD1E293DDDD4F8240130B93429B4BF15391E21C4F827 +:20DD6000201125E02A29BABFD4F820010B381E20C4F82001D4F81C013E28D4BF401C3F20B9 +:20DD8000C4F81C011FE0D4F82401032812D011F10A0FA6BFD4F820010B300120C4F8200107 +:20DDA000D4F81C010028CCBF401E0020C4F81C01032009E011F1140FA6BFD4F820011530A8 +:20DDC0000120C4F820010020C4F824014FF08057D7F8A401B4F81C111B4D40684FF47F42CD +:20DDE00008230646009128463021B047D7F8A40101214FF40032112340680091064604217C +:20DE00002846B047D7F8A401B4F8201140684FF4F80212230646009104212846B047D7F8FC +:20DE2000A401B4F8241140684FF440620A230446009120212846A047F8BD002084F83001AF +:20DE4000F8BDC0465018002000A00C4000A00C402DE9F84F604B5879002840F0B88000201E +:20DE6000012117F0B9FA002800F0B1800668002E00F0AD800746594A408951789246C2099F +:20DE800070D231F001054FF6FE7465D1994699F83220920860D3326A51791579400B05EB6E +:20DEA00001252CBF402600263868B7F818800088834613F07FFD002840D15846032113F010 +:20DEC00095FC002838D15846002113F057F831460EF084FD061C2AD07079012804D003284C +:20DEE0001AD0042818D12AE0B179708811F0180F0DD0FF21A842317103D0404518BF844251 +:20DF000008D128464146224606F016FF02E099F838103171844208D17079022807D058463C +:20DF2000072113F063FC10B106E0834604E0584617F082F9044602E05846FBE7641CA542D0 +:20DF400002D0388BA04213D1386801880222002328460EF089FA0FE0022909D118F01EFBF2 +:20DF6000044605E038680088044613F023FD28B94FF6FE70A04203D1CD211EE04FF6FF74EF +:20DF800038680480204613F015FD00280CBF012000203968C8810F4938680AF055FC011C64 +:20DFA0000BD19AF8010002280CD19AF8000048B92020012101F0F2FC04E03868407B13F0D5 +:20DFC000FDF820B91FB138460121FEF7D3FEBDE8F88FC046452C020050010120E40401201D +:20DFE0002DE9FE4F5D4C5E4994F83C80B4F848500A68834601A8026049684160DFF868A16A +:20E0000001A80AF11409494617F0B8FC00280CBF01260026A76887B11EB93888854206D03A +:20E0200008E007F10C00494617F0A8FC10B1B878804502D0BF69002FEED1002F08BFCA203C +:20E0400000F0898039894FF6FE70884208BFC32000F0818018F0B4FA884208BFC2207AD07A +:20E060003888A84218BFA4F8480016F06DFCF87A4946401C84F85C0004F15D0018F040FC01 +:20E0800002208DF80100684616F0E6FF04F12405061C5BD03069062100F8011B94F8321032 +:20E0A00001704FF0010986F81E9017F047FD706286F81A904020F0823889708086F818B06C +:20E0C0003046FCF7C5F8061C41D1092084F84A003B89E38794F83C00804518BF84F83C802D +:20E0E00005F11A014B2013F065FE05F12401502013F060FE05F11801E12013F05BFE05F1F0 +:20E100001601532013F056FE0820494601F046FC4FF40050002101F041FC20784FF4806196 +:20E1200010F000FD0F484178022905D10078012808BF4FF4DC6203D008200FF005FD82006A +:20E1400020784FF4806118F0B7FB00E0102600208AF805003046BDE8FE8FC046500101206C +:20E16000987C0200E4040120C40301202DE9F04120F039055C4E5D4C96F82F00ADF1180D30 +:20E18000002840F08E803078042113F053FC002840F0878096F82F10777805F03F0541EA7B +:20E1A0000500012F41EA050186F82F1001466FD04FF0010806F132035520002186F80180AD +:20E1C0001F46424617F0ECFF387801285ED12078012818BF022842D1454804680021204603 +:20E1E00017F01DFC00283AD118F08EF8002836D1204605A96A460DF073FD04469DF81000EF +:20E20000FD282CD002282AD0C82C16DA6846002114220DF0E3FDFF20214614226B468DF801 +:20E220001000042015F034F93249A000002200EBC4000A5009184A604A720024552041468B +:20E240003A4686F8324018F06FFAFF20032114F0BDFDF4713078042110F0FAFE40E096F804 +:20E260002F00072440F01000F471284386F82F0000200146F5F706FE002831D0002015F0E2 +:20E28000E5FB20460021F9F777F929E096F82F103078002904BF0724F471F2D00021F17178 +:20E2A000D9E7307AE0B9217896F82F00022901D1810915D296F832706FB1A9080BD341096E +:20E2C00009D217F0C1FA04200121F9F755F996F82F0085F0020505F03F05054386F82F5066 +:20E2E00006B0BDE8F081C04668060120E5040120EC06012004E900202DE9F8435F4CDFF8C0 +:20E3000068815B4DD4F83C0100286ED0574E401E0AD0401E60D0401E1CD0401E53D0401E69 +:20E320001AD0401E33D02FE04E4801250221006884F83A51702204234068009100210746D5 +:20E340004046B847356004F1500018F0EBFA2846BDE8F883022100E003214FF08059D9F8D3 +:20E36000A40184F83A1140680025702204232946074600954046B847D9F8A401C0687022A5 +:20E38000294613460125DAE70320BDE8F88300262E606E6028688008FCD268688008FCD2FD +:20E3A000374834490127001D06600E200F6008F059FD022015F05AFAC4F83C6184F83B61DF +:20E3C0000220BDE8F8830520C4F83C010027376030688008FCD242E00320C4F83C010027CC +:20E3E000376030688008FCD239E0234F01260F202E6042F62A21C7F80B004FF08059C7F805 +:20E400000F10D9F8A40140684FF4C072072302218446404600910021E047D9F8A401C06836 +:20E4200000214FF4C072072384464046E0472E6028688008FCD394F83901C7F81B6018B95F +:20E44000032100200E4602E0002028630321C4F83C6147F8011C686068688008FCD20020B0 +:20E46000BDE8F883A401001000A00C4058600C4054600C4004800C4001400C4050180020F2 +:20E4800038500C402DE9F8430446DFF87C81A078471E53D07F1E40F0B480814600252C2060 +:20E4A0008DF8005016F052FD071C04BF01208DF80000E41CA078002818BF02283AD19DF8C5 +:20E4C0000000A8BB14F8010BB87014F8010BF87014F8010B387130B92046042116F0FAFFE5 +:20E4E0000C34B86007E0241D07F108000822214617F054FB083414F8010B387414F8010B9D +:20E50000387514F8010B10222146787507F11C0017F044FB042104F1100016F0DBFFB86133 +:20E520000820387046467D703078394612F05AF96B4661E002208DF80000F9E78146E41CD6 +:20E540000026607C8DF801600546183080B216F0FDFC071C04BF01208DF80100A078002842 +:20E5600018BF022843D19DF80100002842D114F8013B304603B10120B87014F8010BF8707A +:20E5800014F8010B387130B92046042116F0A2FF0C34B86007E0241D07F10800082221468E +:20E5A00017F0FCFA083414F8010B387414F8010B787414F8010B2A462146B87507F117002F +:20E5C00017F0ECFA641914F8010BB87414F8010B787514F8010B0525387520783D70F874E8 +:20E5E00043467E701878394612F0FCF802E002208DF801000DF1010375204946012213F0C9 +:20E6000007FF0020BDE8F883E80901202DE9F84F534D2968D1F8D40090F883A040310868EB +:20E62000006820B9D1F80C05804729684031886F4C4EDFF83491DFF834810078E8B918F01C +:20E6400079F9377883464FB949460F7837B9832041460870584618F0EDFA60E002214046AA +:20E66000BAF1010F017004D13078832801D110F0BBFE584618F0DEFA65E014F08BF83C48ED +:20E6800000683C4F016C38688847044618F052F9824630460778002F44D149460F78002FC8 +:20E6A00040D12868D0F8B800C16C002088472868D0F828246946F42090479DF90000A04267 +:20E6C0001EDC2D4CA079D8B9504618F0B3FA6078042803D02868D0F84C05804704204146E0 +:20E6E000A7792E680870781CA071D6F8B800C16C09B103208847032060810FF001FD22E0E5 +:20E70000832041460870002014F05AFE504618F091FA1A486968C01D09690078087016F03A +:20E72000E1FB10E0022241460A700078832801D110F05AFE504618F07DFA2868D0F8B80076 +:20E74000C16C042088476868C068007828B92868D0F85824002001469047BDE8F88FC04604 +:20E76000140100206F1B0120711B0120741B0120D8050120B406012004180020051800200A +:20E780002DE9F04106467468B56818F0D3F8D4F8C0108046002900F0A18094F8F80028B919 +:20E7A000087C032818BF042840F09D80287918F0C3F8D4F8CC0041686F690968CF6294F8AF +:20E7C000F90018B92968C8684009FCD22968486820F002004860D4F8CC0041682F69096852 +:20E7E000CF622968486A20F003004862D4F8CC002A6941686B69096843EA0200C1F80405DE +:20E800002968486920F001004861286801270762D4F8D400D4F8C0100860D4F8D87067B10B +:20E82000E8698068C0F30910401C874205D3D4F8C0201168C919091A1160D4F8DC7067B10B +:20E84000686A8068C0F30910401C874205D3D4F8C0201168C919091A1160304610F03AFDED +:20E86000287918F063F8287918F068F8D4F8C070386857B100230222397C03291CBF0429B7 +:20E880003A743B607F69002FF6D1D4F8C0100860D4F8C8100022002904BFD4F8C000C4F853 +:20E8A000C80004D04869B8B9D4F8C0004861C4F8D020C4F8D420C4F8D820C4F8DC20C4F8E1 +:20E8C000C020C4F8C420404618F0B4F904F1300018F050F8BDE8F0810146E3E729684868A0 +:20E8E00020F002004860404618F0A4F9BDE8F081F0B504466568267A00213422ADF1740D2B +:20E9000004A80DF06BFA8DF810606978287800EB012004A913F069FC02208DF811009DF805 +:20E920001000AD1C801E8DF82C00608E0E9504F12801ADF81E0019A817F03CFC9DF8120096 +:20E94000032840F0868017F035FE9DF8131088427FD19DF814109DF815009DF816709DF837 +:20E960002D609DF817509DF81830084347EA000146EA010045EA000153EA010069D111A822 +:20E9800000211C220DF02AFA0E9DBDF81E202846ADF84E209DF82C1010F8017B07F0030287 +:20E9A0008DF84470D21E1ED107F00C06082E14BF002301238DF850300C2E06D14678037897 +:20E9C000801C03EB0623ADF8483046780378801C03EB0623ADF84A300378467803EB06230C +:20E9E000ADF84C30801C1590401B081AC0B28DF85800091A8DF851105ABB07F00C0004289C +:20EA000027D007F0200127F07F00084321D1FE2794F94830104894F8466094F847508DF8B8 +:20EA200047709DF823208DF86230007800928DF860608DF8615000270197E16B0291039773 +:20EA4000B4F842208DF8460018AB11A819A909F02DFA1DB0F0BDC046C80A01202DE9F043C3 +:20EA6000584C94F84201ADF1140D002840F091804A484B4E4FF00108027B3368416884F84B +:20EA80004281814684F84121C3F38147C4F86C11BFB9D9F81000A0B156F8085C17F06CFD8B +:20EAA00064210246C5F306604143B1FBF2F23D49002304F1940012F0FDFE3B494FF0004025 +:20EAC000086001A817F053FE00252F4604F10C00029501AB8DF80470344903953A4612F05F +:20EAE000E9FE01A817F043FE04F150000822029501AB8DF804702E49039512F0DBFE2D4A32 +:20EB000004F1D80032213B4613F012FB2B4A2A4F04F1F4002C212B463D6013F009FB306873 +:20EB200099F80D30C0F381501BB1032803D184F8398103281FD002281DD001281BD14FF0FD +:20EB40008059D9F8A4011E4C406803214FF040521C230746009129462046B847D9F8A401F8 +:20EB6000406829464FF4007209230746CDF800802046B84706E0386840F0400038600220F6 +:20EB800014F08CFE56F8040CC00802D2284614F085FE05B00020BDE8F083C046308602004D +:20EBA000B44F0050555E020000A10C4003950100ED0E0200994902009022084081C80100A2 +:20EBC00000A00C40501800202DE9F0430E460024ADF1240DADF8160006F108078DF8144097 +:20EBE000384616F068FC50B905A80DF031F9A124012840F0938005A814F078FD8EE038460D +:20EC00000DF122016A460DF06BF805464FF6FF70A8427FD09DF82200DFF80C81002834D044 +:20EC2000404801789DF8100040B3401E1AD0401E04D0FB381DD0801E1BD051E0012915D0D8 +:20EC4000022913D039B9748240F20110B0829DF8127086F8287006F11E0002A9082216F02C +:20EC60009DFF3DE0012918BF022902D14FF4817001E040F20310B082748231E005219DF88E +:20EC80001300718200F07F0029E002A83946082216F084FF4FF001098DF81190FF208DF807 +:20ECA000100017F078FD274600F00F0000942946142201976B468DF81200042014F0E8FB38 +:20ECC000AF0007EBC507404621460C223F1838460DF084F8748287F8099040F20310B082D9 +:20ECE000A8003474414600EBC5000A58B2610F580A237F1CB7FBF3F20F505A43BF1A0DD19F +:20ED000040180121094F017238784FF4806110F09FF903E0748240F20310B082204609B0D3 +:20ED2000BDE8F083E504012004E90020CB0301202DE9F04F044608469A46ADF1240D2146B2 +:20ED400005908E680692129B04914C68756807935044854238BF6FF00304C0F093804B4D10 +:20ED600028684FF0FF3117F095FA4948328C079F48496368026083460B60780819D238462E +:20ED8000800813D3F768002F3AD03569002D37D000970195012002900599069A0498534648 +:20EDA0000DF036FA5FEA000813D114E04FF0000811E0A0683AEA00070AEA00021CBFB168A8 +:20EDC0000A4405990140049808F09CFB5FEA000801D0044652E034680598DDF818905746EA +:20EDE000241805E0BBF80010049817F02FFAA944AFB90798C00840D3F16809B1306910B91F +:20EE00006FF007043AE00091019000270297069A0599049853460DF0FBF980462DE00498B9 +:20EE200010F082FD38BB049814F048FA18BB04F0FF05C5F58075BD4288BF3D1C210C8DF8B3 +:20EE40000D1002208DF80F40230A8DF80C00BBF8001004988DF80E3017F0EFF903A8042100 +:20EE600011F09CFA7F1B641928B94846294611F095FA0028B6D04FF0FF3844460348006815 +:20EE800017F06EFD204609B0BDE8F08F141B0120101B01200C1B0120F0B50446207CADF1B0 +:20EEA0003C0D0F28C0F2A680656860690DF1260210F0F6FA9DF82600002840F09B80207C84 +:20EEC0000B28C0F29780287A022840F09380A88900F00F010F2940F08D80C0F303100F2884 +:20EEE00040F088809DF82860002E18BF022E40F08180414C414894F84A20022A3BD00068AC +:20EF0000062A39D010B18179012935D0082A18BF042A6FD16D8910B18079022827D0B4F8DA +:20EF20004800854266D1012E07D004F15D000DF12D0116F023FD00285CD120784FF4007140 +:20EF400012F078FD002855D1E06C029001268DF80D6002238DF80E3094F852708DF80C70BE +:20EF600002A80FF0AFFD10B114F008F842E0284615F06EF93EE0006840B900230093288896 +:20EF800069896A7CFCF73EFF9DF828602888ADF810006889ADF81200A87B8DF81400AF894B +:20EFA00000206FF30E0707B101208DF818608DF815009DF827408DF819409DF82C708DF8BA +:20EFC00017709DF82A009DF82B308DF81600687C0DF12D018DF81A009DF838608DF81B30B4 +:20EFE00008228DF81C600DF11D0016F0D7FD04A803F03EFC0FB0F0BD50010120000A01200F +:20F000002DE9F04380460E20ADF1340D15464FF001098DF80100B8F1000F8DF802305048A3 +:20F020008DF8005000F1010000788DF804900F468DF8030047D1112004A93A2217F05FFAE9 +:20F0400000283CD1444E0DF111007B199DF80320716803901C4642F02802481C7060581CBC +:20F06000227016F08FFD054616F068FD0146284617F046FC48460DF131013A2217F03FFA5E +:20F08000083500280CBF9DF831000020287016F055FD01460DF1210017F032FC7088401C7B +:20F0A00080B27080B0F57A7F02D8706801282FD12A4800784FF400710FF0CAFF28E0002027 +:20F0C0007C19039024E07C19ED19687B11F076F83A2808D03B280FD1112004A93B2217F058 +:20F0E0000EFA30B108E0112004A93A2217F007FA10B90DF1110000E0002003909DF80300FA +:20F10000217808432070611D0DF1210017F0F8FB0DF12900611C042216F040FD039E20789E +:20F12000002E8DF82D0008BFA12012D0404669460DF121023B4604F0EBF8054620780021D3 +:20F14000102200F0F80020700DF111000CF046FE28460DB0BDE8F083100A0120CB03012049 +:20F160007F0101202DE9F047564CA4F1080000F108058068D0F80001807AADF1280DC00026 +:20F180000AF01EFF0028089008BF1A2400F0958017F0D0FB8246286800F59162D0F80001B3 +:20F1A00000894FF6FF780026C14608E020682268D0F80001761CB6B202F591620089B042BB +:20F1C000D8BF002473DD2068D0F80001C07A0127002548E0ADF81480ADF8168006A8FF21E2 +:20F1E00008220CF0FBFD2068D0F8942404A9D42090472068ADF80480D0F894246946D120A0 +:20F2000090472068D0F800012268C0886D1CEDB202F5916230E0ADF800608DF8025012687C +:20F22000D02069469047A8B99DF80C00012810D19DF80B0068B90DF102020820002112F836 +:20F24000013FFF2B03D1401E01F10101F7D10829ACD0002720682268D0F800016D1CEDB27F +:20F2600002F59162C07AA842D5DC002F9ED12068D0F80001C0880025A84297DDADF8006010 +:20F28000ADF802501268D120694690470028B8D1BDF804008145B4D0ADF810002068D0F8CD +:20F2A000882404A9D4209047002893D01924504617F0C0FC089812F0DDFB20460AB0BDE8CA +:20F2C000F087C04614010020F8B50546687F0C4600280CBF08201020AF7F0FB10830C0B268 +:20F2E0002F7F0FB1401CC0B2AF7927B1297A00EB4100801CC0B22F7E6870002F0CBF002650 +:20F300000E2647494A78022A0AD10A7D012A07D12A78012A04D0CF78002F18BF012100D1F5 +:20F32000002185F834102F7E297D09188919217037B13C48007816F079FC2178081820709C +:20F340002078742869DC0AF03BFE071C66D017F031F90346A97F6A7F95F834002C7F41EA86 +:20F360004001A87942EA410240EA42012A7E002042EA410204B10120297840EA42006A7E4D +:20F3800041EA830102F0030241EA821141EA002188B2397000127870A878B8706888001296 +:20F3A000F87028793871A88800127871A87EB871E87EF871687F002808BF082405D0296AE8 +:20F3C00007F1080017F09CFA1024A87F28B1696A381917F095FA0834E4B2A87988B1287AD4 +:20F3E0003855697A631CD8B239542A7AE968431CDCB2E019520016F0D1FB287A04EB400433 +:20F40000E4B2287F00B13855687829692A7D8019C0B2C01916F0C2FB00E000273846F8BD77 +:20F42000E4040120800101202DE9F0470546A87A022840F09B804E4CAF7B5248DFF840A1DC +:20F44000A66A002F7CD12169F9B16769EFB1A769DFB1E768CFB114300078012815D1688852 +:20F460008847AE1C88B943490A6830889101A1EB820162699047012878D1A16930888847B6 +:20F48000E16830888847BDE8F0873B486D88006878B101680A88954208D1096A4A78097816 +:20F4A00001EB0221490A01D220B136E040680028EFD10020314933230027012401F60C72EF +:20F4C0001679FF2E02D01688B54206D05B1E02F124024FEA4404F3D100E0274601F1AC0869 +:20F4E00001F13C09002319F803208AB19E0058F8064027420CD0104616F008FA38B1417BC7 +:20F50000052904D1BC431E2348F8064000E000205B1CDBB21E2BE6DB68B1417B05290AD136 +:20F52000016801270D8056464773307820210FF08FFDBDE8F087284611F0D0FABDE8F08772 +:20F54000A6B1017D012911D1C07840080ED3042015F0FCFC011C09D06420087001274F706F +:20F56000688856464880307811F03CF9BDE8F087E4020120BC800200E40A012020010020A8 +:20F5800050010120E40401202DE9F0478A46071CADF1200D08BF002000F099804D480088D8 +:20F5A000B8420AD116F0CAFA0146504616F0E6F900280CBF0125002500E012254FF000094D +:20F5C000ADF8027068468DF800900CF041FC68B101AC204615F06FFF012807D1504621467B +:20F5E00016F0CCF900280CBF01254D46DFF8F0804146087830F0010044D1122D42D1504628 +:20F6000017F04EF928B101888F4202D00679052E03DBB9F1000F34D134E00780EEB1414688 +:20F62000491E0D79032E18DA2B493DB901EB8502126B01EB8501C261096B0AE001EB8501FB +:20F640000B6B9A01A2EB8302C2610A6B9101A1EB8201816180F8209003E06FF00101C161DE +:20F6600081614E46C6600125ADF8107051468DF80E500DF1120016F02DFF0DF10E0003F0E8 +:20F68000C3FD4D463846514610F028FF0A2818D0A02813D1114C142604F102084046514662 +:20F6A00016F06CF930B9761E04F11C0408F11C08F4D100E02780384612F07CFC012D01D0ED +:20F6C00004E001253846494614F0DEFB284608B0BDE8F0878A010120688002009C0400209E +:20F6E000E50401202DE9F041054603200C46ADF1300D8DF81E000DF1160017F001F916F060 +:20F700001DFA01460DF1160016F038F9002878D0217D032918BF012973D1207A00286ED0C1 +:20F72000FE286CDC032904D1A07D002867D0FE2865DC3E490A6809A80260496841603C4F8E +:20F74000082209A9384615F0F7FCC8B9AE1C394831880088884213D0608988B900208DF8CE +:20F7600008003946082203A816F018FA02A80EF0BFFA3088BDF80A10884218BF8D2042D1CC +:20F780002D48EB890768AE1C212B11D02B48076867B1207A6189A37D04F10C02B84728B999 +:20F7A00000208DF82C0012F0C5FA2EE088202AE08C2063898DF82C00ADF822302FB30DF1D7 +:20F7C00022000090A27D207A04F10C010123B847D8B100278DF82C7012F0ACFA207D032858 +:20F7E00013D104F10C0008A913F068FF04F10C0858B9394640460A460FF024FA05E08220F6 +:20F8000000E08420AE1C8DF82C000BA80090287C0190EA893146012305F1110042F40042E4 +:20F8200011F018FF0CB0BDE8F081C046E48702004C0501208A01012024090120F0060120E8 +:20F840002DE9F041524D2968F4310A68064692F84400ADF1180D82281ABF92F84400401C10 +:20F86000002082F84400086890F8441000EBE10090F82C104A1080F82C2048080AD22968F3 +:20F88000F4310A6892F84400401C82F84400C0B28128E8DB2A68F4321168DFF8F88091F802 +:20F8A0004400812824DB8878E8B944462168D1B10868C0B10F4615F0ADF98046386817F0D8 +:20F8C0008BF810B1386817F095F9384617F08EF9384612F0CFF8083C0020A060404616F06C +:20F8E00024FB2A68F4322A203070D2F84C1249E0D2F83C234431E12090472C684FF6FF7335 +:20F900000220ADF80830F43422688DF810009778BFB916F031FE4FF47A71B1FBF0F01E49C4 +:20F92000434600220AF092FB00282DD02868D0F8F4001A2141702A2737702868D0F8401395 +:20F9400020E0022F1CD0012F19BF07208321082080210027009749320192D4F8844202AAE4 +:20F96000A047DB2807D0E52805D0F32803D0DF2818BFE82808D12968D1F8F4104870DAE758 +:20F98000D4F874133046884706B0BDE8F081C046140100207C0A012091590100FEB5524DE4 +:20F9A0006A78022A04D12A78012A04BF4F4A10404F4CB4F8707000290CBF87430743F80BB9 +:20F9C000A4F87070C60308D001208DF8040001A9522012F0EFF9B4F87070B80B62D2F80BD4 +:20F9E0000026C30358D1002F5AD06B784FF0FF306E460090022B4AD12D78002D47D1780852 +:20FA000006D304F14C000168B1F1FF3F38BF061C380906D304F1500032680168914238BF3E +:20FA2000061C780906D304F1540032680168914238BF061CB80906D304F158003268016828 +:20FA4000914238BF061CF80B06D304F15C0032680168914238BF061C780B06D304F16000ED +:20FA600032680168914238BF061CB80806D304F1640032680168914238BF061CF80806D3DD +:20FA800004F1680032680168914238BF061C6846B04208BF002603E0F80B28BF04F15C0669 +:20FAA000374600E00027134D2878BFB1E66E1EB131683A68914215D03968E766012909D04B +:20FAC00001210FF02FF8E16E28780A68012116F0F0FEFEBD01210FF0BBFAFEBDE7660121AC +:20FAE0000FF020F8FEBDC046E4040120C0CFFFFFE4020120500101202DE9F0478246484E74 +:20FB00004E4C56F80C0C9046894680082AD245480068810D28D2051704F13400006800682A +:20FB200080476D1CC0F13E0110F1020F4FEAE101D8BF07218D42B8BF0D1C3B480068C0F38C +:20FB40000320401B102803DA0028D8BF012000E00F20364900F00F0040F0F00081F84D00BF +:20FB6000087801E03248306000203249324F256808603868A96927208847324D304805F154 +:20FB8000300211682B460840106003F17800006820F48070A8672068016B4FF480608847C4 +:20FBA0002068016B4FF4816088472068016B4FF4C0608847244901200860C5F880912860EC +:20FBC00056F80C0C800806D2B8F1FF3F14BF40464FF0404030603868E8698008FCD3072061 +:20FBE00010F0AAF80228FAD1BAF1010F13D0206A164E8168304688470428F8D0012804D1C2 +:20FC0000206A4268032130469047D5F8180220F00300C5F818022068806B8047BDE8F08718 +:20FC20001C000940B44F00500C1300500D620840FD0000400C4009402C200940B8010010B6 +:20FC4000FFFFFEFE0C2008402820086000400340F0B5524C06466078ADF1240D022803D1CF +:20FC60002078002800F097804D4D95F84A00082818BF042840F08F8030460DF10E0115F052 +:20FC800076F9607802280BD115F058FF04A915F075FE28B116F094FCBDF80E1088427AD040 +:20FCA0004FF6FF7012F086F9BDF80E0004AF3946FFF76AFC01286ED00DF11A0016F0C7FD75 +:20FCC0000DF11A00394615F059FE58B1BDF80E2016F064FC904205D005F13E014B200A800E +:20FCE00012F068F8607830F0010019D116F068FCB18A884214D004A816F0D2FD38B1007989 +:20FD0000012818BF022802D104A80FF0D9FC2548016829B1207D012802D1BDF80E0088478B +:20FD2000BDF80E00002114F0ABFFBDF80E0014F01FFE00248DF80040BDF80E00ADF80200FA +:20FD400068460CF085F898B10DF11A00214608220CF044F801AC0DF11A00214615F00EFE15 +:20FD600030B104A9204616F0B5FB684603F04CFA01A804A916F0AEFB68460DF0B9FF50B189 +:20FD8000BDF80E00BDF80210884204D0ADF80200684603F039FA09B0F0BDC046E40401204B +:20FDA00050010120F00201202DE9F04F00210225C41CADF1540D8DF84A1081788DF848504D +:20FDC0002046139116F02CFCA41CADF84000204616F026FCA41C8146204616F021FCA41CE8 +:20FDE00014F8018B8246B8F1110F0DDAB8F1000F0DD047466E46204616F012FCA41C7F1E46 +:20FE000026F8020BF7D102E080208DF84A002678112E63DA5EB1641C37460DF1200B2046E9 +:20FE200016F0FEFBA41C7F1E2BF8020BF7D19DF84A00002855D1304A53684746BC1948461C +:20FE4000514614FB05F4A41D5FFA84FCBCF1500F42DC9DF848400F2C18BF022C08D1BDF854 +:20FE600040504FF6FF74AC4204BFA41EADF840404FF6FF74844208BFA01E03F8010B001286 +:20FE800003F8010B03F8011B0D1203F8015B03F8017B67B168469B1E017803F8021F30F81B +:20FEA000021B7F1E4FEA21215970F5D19B1C1E705EB15B1E08A8017803F8021F30F8021B27 +:20FEC000761E4FEA21215970F5D1104610A9634606220EF0E1F802E0102000E080208DF8B6 +:20FEE0004A001399652001220DF14A0312F090FA15B0BDE8F08FC046280401202DE9F04FFC +:20FF000015460646287A0C4600F03F01E8886FF39F2040EA0130A988ADF1140D6FF39F2118 +:20FF200041EA003B49490E9FC8789A464FF0000988462EE09DF80B10C8080CD3BDF80E00B6 +:20FF4000844204DD241AA4B2162C13D931E02146304610F021FC0020F8F776FC98F83300E9 +:20FF600098F803204FF00009401C90FBF2F15143401AC6B298F803008119491E91FBF0F254 +:20FF80004243891ACEB2B10001EBC6014144B1F84C40484503DC0020A8810A2052E098F8FA +:20FFA000323009F10101B3421FFA81F9E4D0172CE2D3E41F30466A46A4B2214608F0D2FD02 +:20FFC0009DF80B108808B7D34808B5D22A7AEB881AF00F0018D0401E12D0401E07D0401E95 +:20FFE00018BF04202ED100985845A5D10CE09DF808009042A0D1BDF8060098429CD103E0AB +:020000040001F9 +:200000009DF80800904297D1AFB10AF0F000102811D1BA89BB68684600210EF0BDFF00288E +:2000200088D1F988B868BA884018396814F0CAFE00287FF47FAF68460EC80EC503C885E867 +:200040000300002005B0BDE8F08FC046C01900202DE9F84F504CD4F8A000D4F8A06000284C +:2000600000F095800546E86840F6030108274A1C02E040687F1EFFB260B15FB103889942B2 +:2000800018BF9A42F5D129692CC838312CC189C881E8890006F1280090E800034FF0000AE5 +:2000A00006F12807D34687E8000CB16821B357464FF0E24A07EA08001AEA090508BF002897 +:2000C00013D036A090E80C0002EA080213EA090308BF002A04D0B5683069B6F93010A8478B +:2000E000504607EA080800EA0909B5683069B6F930104B464246A84716F01CFC0546B4F9AA +:20010000B600401C6FF31F30A4F8B600214886F833B06FF00207378614F007FF284616F05D +:2001200089FDB4F9B400B4F9B61088422FD16068D4F8B860D4F8BC7090F8FC1000290CBF6F +:20014000052007200AF03CFF58462EB196F8FC5005B9306886F8FCB05E462FB197F8FC50E8 +:2001600005B93E6887F8FCB0864238BF061C66B1B6F1FF3F0BD016F0FFF9B6FBF0F104F5AF +:20018000CE7015F0DDFEBDE8F88F15F0D1FABDE8F88FC04608F3002068F20020F0FFFFFF91 +:2001A000FFFFFF8E2DE9F0478046D8F808603068076CD8F8045047646A6CA96B286C17F406 +:2001C000F06FA0EB020937D1F8091FD2780979D3B9B196F82100464A145C601E814294BFB6 +:2001E0000C1C641E4046214612F064FDA86B001BA863A86B002865D105F18800012116F0B5 +:20020000B7FB4046494613F05DF95BE00029F8D0404612F04FFD014695F82D00A96318B9E0 +:20022000A86B00284ED101E00020A86305F18800012116F09DFB45E0F80A21D24FF0000AB7 +:20024000544603E0A86B401EA863A96B91B14046012112F02FFD3068446814F00F04C0F866 +:2002600004A0EFD0296BAB6B686B491E2963401E6863EBB905F18800012116F079FB13E0D1 +:20028000306844680022202904F00F044260CCBF4FF0200A8A464046514612F00BFDCAF160 +:2002A00020008145C8BF81464946404613F00AF9EC77404610F02EFB706A18B1024621468B +:2002C00040469047B80910D3AF6A77B14046394612F060FDA862AD6A3DB996F82000054965 +:2002E000095C4046C9190FF037F9BDE8F087C0465C88020068880200F8B50546A869837804 +:2003000000242746002B2CD0FE2B2ADC427800784B494C4E00EB022009783288264682421E +:200320000DD031F0010306D115F0D7FB00280CBF8126892616E0022908BF802612E01846E6 +:2003400015F074FA50B18268002A04BF4068846804D00120194690470127044604B98326BB +:2003600000E08226384801685EB954B1227BE0790223801810FB03F00C30C3B2502B01DD35 +:2003800058E0042301F8016BA869007801F8010BA8694078042B01F8010B42DD181F01F8BF +:2003A000010B207801F8010BA07801F8010B6088001201F8010B207901F8010BA0880012A0 +:2003C00001F8010BA07900F00F0001F8010BE07901F8010BE67916B10020864214DC207B04 +:2003E0000870267BFEB1491C002086421BDD26694200965D0E702669925B12124A70267BB3 +:20040000401CC0B2891CF0E7A6684200965D0E70A668925B12124A70E679401CC0B2891C26 +:20042000DBE70020087005F11100A91C48F204020DF032FE1FB114B1204611F01BFBF8BD62 +:20044000E5040120E00301202C040120FEB5524C60692589A689E169806D2A4689190831C4 +:2004600008F054FD6269916D49199165E2697619B0B212180832127801A90A70444EE169E8 +:20048000401C80B20918097A721C401C117081B2E269A18152180832126868460260091DCB +:2004A000A181042115F016F863690090054615F04FFED863284615F0F1F9A3F84000EA206C +:2004C00012F030FF02213548324D017068684069007830B1307810B97078FF2801D0042014 +:2004E000E0706769E078397C084338749DF9040016F05EFA87F8460007F17406BE653989C4 +:200500009DF904007B6887F84800B7F85C000026401AC0187860B88987F84760800A0AD38E +:200520002868D0F80813384688476769786E10B1B7F8680010B397F8600050B12868D0F862 +:200540000C13384688476769F86C10B1B7F85000A0B12968B8310A68107838B1936C2BB1B2 +:2005600019463846884767692968B831D1F8A01138468847666115F0F3F9FEBD2868D0F8F3 +:20058000541204F11400884766610DF0EDFDFEBD2C1A002014010020B41801206F1B012081 +:2005A0002DE9F84F8146D9F80040D9F8047094F82360B4F814A0D4F810B090460D465EB18E +:2005C000A168434815F066FE002818BF6FF001007BD1012084F8260084F8218000262560E8 +:2005E0004A463C483C49E66114F005FD3978272016F0A8F951465846062205F081F8002883 +:2006000057D13749091F086820F00200086094F82000042806D133484C380068406901461A +:20062000272088472D4F4FF0020B4FF0805AC7F8FCB2DAF8FC0140680146062088470AF5A4 +:20064000FE7A38BB584613F029F9B8F1020F4FF0010005D0B8F1040F18BFB8F1060F01D17A +:20066000314600E00421C7F84C11E968C7F85011C7F8546184F82400DAF80000AA68E96828 +:20068000036968681C460B46A04748460DF0FCFABDE8F88F4020386080253D6094F82600EB +:2006A00020B10B4816F05CF984F82660C7F8FC6207E094F8260020B1054816F051F984F819 +:2006C00026604FF0FF30E061E069BDE8F88FC0464C160120AC19012061D501000444024040 +:2006E00088470240FC0100102DE9F04F00214FF00209C41CADF1540D8DF84A1081788DF8E0 +:2007000048902046139115F08BFFA41CADF84000204615F085FF0A34804614F8010B149014 +:20072000204615F07DFFA41C14F8015B8246102D0BDA6DB12F466E46204615F071FFA41CDE +:200740007F1E26F8020BF7D102E080208DF84A002678102E5DDA5EB1641C37460DF1200B70 +:20076000204615F05DFFA41C7F1E2BF8020BF7D19DF84A0000284FD12C4F381D0468AB1936 +:2007800013FB09F00F305FFA80FBBBF1500F3EDC15F016FF404538D184F800804FEA2820F5 +:2007A000607015F0CBF9A41C0146204616F0A8F804461498207084F801A04FEA2A23A37051 +:2007C000E570241D65B16846A41E017804F8021F30F8021B6D1E4FEA21216170F5D1A41CC5 +:2007E00026705EB1641E08A8017804F8021F30F8021B761E4FEA21216170F5D1384610A96A +:2008000020225B460DF048FC04E0484602E0102000E080208DF84A001399652001220DF18F +:200820004A0311F0F5FD15B0BDE8F08F280401202DE9FE4F8246DAF8180090F800900021F4 +:200840006A469D2005F034FD9DF80000814531DA9DF80000A0EB0900C4B20A2CC8BF0A2415 +:20086000E00009F0ADFB5FEA000821D0054624B300262746B34606EB09018B202A4605F0FC +:2008800017FD6879401E0AD0401E06D0401E02D00320687105E00220FBE70120F9E785F864 +:2008A00005B07F1E05F1080506F10106E3D104E0002402E04FF0000844469AF811000AF1D8 +:2008C000020A8DF801000527CDF804A014FB07F0001DC0B20646401C09F072FB4546071CA0 +:2008E00040D0791C0022084602709DF80020BA7087F803903C712CB3491C083D15F8082F06 +:2009000001F8032F2A8812124A706A7902F0070201F8022FAA7912F0180F0BD0D3082CBF27 +:2009200006230223520928BF43F001030A7842EAC3020A70AA784A706A88641E4FEA222236 +:200940008A70DBD10B4D2C1D514648F23202334620600DF101000DF09FFB384611F08AF8BB +:2009600009346C60B8F1000F02D0404611F082F8BDE8FE8F280401202DE9F0470646880F34 +:20098000C0F08E8000200EF0FDF8464815F014FD454C40F60A09A4F8009000256580207B37 +:2009A00005F00F0120F00F00014321736560607B4FF0010808F00F0720F00F0047EA0001F4 +:2009C0003046617306F06EFBD6F808A04A462146D01F574600F1010C00E027467C6834B161 +:2009E00023889A4203D0984218BF9C45F5D179607A7B2E4C05F00F0322F00F0213437B738F +:200A0000D4F8983033B1DA681288904223D06046904220D0338FF3B1F56306F13802558091 +:200A200096F8440005F00F0320F00F00034386F8443096F8450008F00F0320F00F00034344 +:200A400086F845304A60487B05F00F0620F00F0046EA00054D7315F021FB1548A06294F80C +:200A6000310080B91348006801684046884701280FD0787B08F00F0120F00F000143797339 +:200A80000D4EA66205E011F035F80028FBD010F051FA504615F090FC5146404614F0DEF884 +:200AA000BDE8F08701010E04601A012068F20020855C0000E001001035FE0100F8B53C4DB5 +:200AC000002428703B4E85F84A4040F20110308040F60C4009F074FA706028B17068214606 +:200AE00040F60C420BF07AF933483449344B364EC161344A03627778426237F0010718D159 +:200B0000317D012915D13149314F8162F3780761590802D2406B58B90BE02E4F47632E49ED +:200B2000C1622E4B43612E4AC2602E4B836138468047AC602C48046013F030F8707830F022 +:200B400001002FD115F0F0FB28494FF6FE70642721F8080F48800C714C717F1E8C71F7D161 +:200B60002349C82748804C704C607F1E01F8084BF8D120490827A1F1CA02508014727F1E4F +:200B800002F10A02F9D12A781E277F1E21F8080BFBD1194901200870104610214FF47A725F +:200BA00015F087FE03F0DCFF14480460F8BDC04650010120DC0A0120E40201203D3802006B +:200BC000C156020029DE0100E4040120ADA40100614B02001951020079D10100B9BF0100BB +:200BE0001D0102007D670100E40A0120C4060020EC09002044020020650F0120000A0120BC +:200C0000F0B5064631684889ADF1440D4008C0F092804A894FF6FE70104048810868036A04 +:200C2000C57F5978187800EB0120694611F0DDFAD878997801EB0021ADF80A105A791879EB +:200C400000EB0220ADF80C0098799DF807708DF81200D879002F8DF8130008BF082403D044 +:200C600003F10800102405909DF808701FB1181908340690E4B28DF801409DF8057037B181 +:200C8000185D641C8DF80500E4B28DF801409DF806C02A480027BCF1000F06D190F82F201B +:200CA00052B1428F8A4206D106E090F82F201AB99DF8022002B90127A7B9BCF1000F05D1A1 +:200CC0001B190A932D1B8DF81C500CE090F830001B190E330A9314F0A9FF2D1B281A0E38D8 +:200CE0008DF81C000A9B37BB1878042823D10DA800210E220BF072F8BDF80A000A9FADF894 +:200D000034007978880924BF01208DF83F0031F07F001CBF01208DF83E00C80934BF069993 +:200D200005990DF1360015F0EBFD30798DF840000DA80FF03BFE11B0F0BDC04650010120B3 +:200D40002DE9FF4105466E68AF680C4615F0F2FD3178012903D115F06DFF002080E0012105 +:200D6000317015F067FF207870706078B07060687060A068B060E068F06020693061207DF8 +:200D80003075607D7075A07DB075A069B061207F3077607F4FF0000843467077A07F3363FF +:200DA000C6F82080B0771C4674627463B462B46386F82C4086F82D4086F8A84186F8A941CE +:200DC000786806F0E7FA284606F040FB28460CF00BFD684615F0D0FA3A7B06F16C00B96895 +:200DE0000192214A00956B4611F0A2F9684615F003FB396902911D49009506F188006A4603 +:200E00000FF096F8B07830B906F1C400214613F0BFF817483061707830B906F58A7021463B +:200E200013F0B6F81348F060684615F0A0FC01948DF8004006F5B2700F4902950A226B46C4 +:200E400010F038FDB969FA6906F13C0015F019FA0A4A06F1580004212B4613F0C1FC284626 +:200E60000090BDE8FF81C046A501010043E901007F6802002D6802004D120200A9640200F3 +:200E80002DE9F84F80460D462868DFF824A1D8F80040D8F804700689D0F804B0E168914631 +:200EA000504615F0F7F90028CDF8009018BF6FF0010074D148464FF0000960723A496561BD +:200EC00042464B46C4F804903648A37014F093F83978272015F036FD31465846062204F028 +:200EE0000FFCA8B9334E4C3E306840690146272088472E4F4FF0020BC7F8FCB2F06C4068A3 +:200F000001460620884750B14020386080263E60504615F025FD4FF0FF30BDE8F88F584663 +:200F200012F0BCFCF06C95F82010C26928699047F26CDDF800C095F8200095F82110136872 +:200F4000BCF1010F4A4608BF01229847E869C7F85001C7F85491A869C7F85801A96959B131 +:200F6000F06C076968684A461346B847F06C806901461148401E8847207A042804D03068A9 +:200F80000069014627208847F06C0369E969EA68A8681C460B46A04740460DF0B5F9BDE89F +:200FA000F88FC046AC190120A5E90100044402404C160120FC01001003000080F0B50E4699 +:200FC0000746002406F10805ADF1240D28468DF81C4014F070FA18B9384629460CF062FBF9 +:200FE000284607A96A460AF07BFE414D01466878A127012818BF022812D19DF81C30BBB9D1 +:2010000005A8214608220AF0E9FE05A807A96A460AF066FE01464FF6FF70884204D16878CC +:201020009DF81C5025B907E001208DF81C0068784FF6FF728A4207D1002855D115F02CFB74 +:20104000002851D127463AE02A4B9DF810205D782746002A3BD0521E2DD0521E0AD0FB3A22 +:2010600008D0921E40D1012812BF0228012086F8260024E08A0002EBC102B169D218383242 +:2010800053688B4215D8491C012851601CD002281AD038B9748240F20110B0829DF8125049 +:2010A00086F8285006F11E0002A9082214F076FD1AE0A22718E0012806D0022804D040F2EF +:2010C00003107482B0820FE04FF48170F9E705209DF81330708203F07F00B08205B1012464 +:2010E00086F8264086F82740384609B0F0BDC046E4040120CCE800202DE9FC4706467568DE +:20110000D6F808802F780FB1AF6B1FB14FF0FF30BDE8FC8729630024EC77171C6C631BD092 +:2011200005F13C0915F006FC82466946484610F061FD002820D4504615F07CFD9DF8000045 +:20114000296B0870686B296B7F1E00F10100686301F101012963E5D169786A6B286B012919 +:20116000A0EB0200286305D1E868296B0346304698476A6B144659E0AF63D8F80010086B32 +:2011800040F400700863D8F80010886B40F4FA608863504615F04EFD05F5D47014F04CF987 +:2011A000687805F5D47768BB15F0C4FB95F82D1069B1696B59B1A96B49B1AC6315F03AFD08 +:2011C00005F5D47014F028F9686BBDE8FC8715F031FD696805F58A76304615F05BF80028BD +:2011E000F2D0AC633046214615F054F80028EBD0384614F011F91022696B286BEA77401A2D +:201200002863E1E715F096FB95F82D1061B1696B51B1A96B41B1AC6315F00CFD05F1880092 +:20122000012115F0A5FB01E015F004FD2046BDE8FC8770472DE9F04F05468846ADF1140D8E +:201240001C46D5F808B00E990092DBF80400019108EB0401884238BF6FF003047BD3404E0A +:2012600030684FF0FF3115F015F83E48019F01684FF0000978081CD23846CDF80C908008A9 +:2012800027D334B33046DBF800200099066823464244491E521E11F8010F12F8015F05406F +:2012A00085421CBF6FF00604301C52D15B1EF2D10FE034EA010701EA040202D02A480068C6 +:2012C000121801EA080128460DF0D6FF002803903CD1DBF800500FF0E1FE27464544DDF81C +:2012E00000A0029002E0BF1BB244AD1997B1082F8CBF08263E1C15F01DFB0490294632465A +:20130000504614F07BF98146049815F093FCB9F1000FE8D0029813F053FBB9F1000F12D1D0 +:201320000198C00812D38CB1DBF8000000994044491E401E10F8012F11F8013F9A4202D145 +:20134000641EF7D102E04FF0FF3003900448039C006815F005FB204605B0BDE8F08FC046C3 +:20136000001B0120081B0120041B01202DE9FE4F0CAF1D468B465FEA02083E78009014BFEF +:201380004FF0804A4FF0005A15F0D4FA0324DFF804910190BBF1FF3F14D1D9F8A8100098C4 +:2013A00015F012F858B9D9F8AC10009815F00CF800280CBFD9F89870D9F8AC7008E0D9F86D +:2013C000A87005E000985946002211F0B7F80746002F59D097F8330030F07F0053D04C464C +:2013E000D4F8A800B84219D0D4F8AC00B84215D000982A463346394608F0AAFB002842D068 +:2014000094F8240001283CD094F82400042838D0214904F1E00015F0ABFA32E0D4F8A80094 +:201420005346002211F0A8F8D4F8AC005346002211F0A2F8B8F1000F14BF1848184813F034 +:20144000D7FBB6B1D4F8A80000224FF0807311F093F8D4F8AC0000224FF0807311F08CF8AE +:201460003869C4F8D80094F8DC0040F0010084F8DC0035B1D4F8981000982A46334608F073 +:2014800067FB832400E00424019815F0D3FB2046BDE8FE8F68F20020020000400100020474 +:2014A000010001042DE9F04FADF1140D02921D460191DDF83CB00E9C009015F03BFA464AC4 +:2014C0006FF001084FF00109002392F840A2039009FA03F616EA0A0F6FD0B5F1FF3F18BF2A +:2014E000AB426AD1D8B214F0F7FD002865D0877A002F62D192F84012B14382F840124F4651 +:201500008772009D437292F842120560491C82F84212019E06722E4F4760017A07460129DD +:201520001ED0022924D140F20361018290F90930C17C5B1D21F00F0103F00F030B43C37462 +:201540006379817C63F3C7018174C17CA37963F34611C174C17CE37963F30411C17407E044 +:201560000A20388297F90900401DB874A0687861BBF1000F08BF002012D09BF801009BF8D9 +:20158000001097F90960134C4FF6FC75800040EA4110711D40EA012005EA000144EA01003A +:2015A000B861029800B17860506808B9386850600CF0E4F897F9098002E05B1C032B87D354 +:2015C000039815F037FB404605B0BDE8F08FC046734A01000100040668F200202DE9F0414A +:2015E00004464A480078ADF1280D18B9E17A15F0F5F808B9012085E06846002124220AF050 +:20160000EDFB208B00F0010100F00C00084301D1207A08B9B62075E00F288DF808004FF0A3 +:20162000000613D002284FF003050DD0032806D0012812D126884FF6FF700F2508E068463A +:20164000214615F05DF908E0208804E020880B2502218DF80810ADF8000005F00C07B7F167 +:201660000C080CBF03200120678A801DC1B27818C0B28DF81F0008F0A3FC071C40D0089737 +:20168000B81CB8F1000F00F8015B04D100F8016B311200F8011BA17B00F8011BE189091225 +:2016A00000F8011B217C00F8011B218A091200F8011B628A616914F071FA14F07BFF0326BF +:2016C0003A46810041F0030102F8011B80111070A0898DF80C60A37EADF80A0015F00C0FA3 +:2016E0008DF80D300CBF012000200021ADF80E00684607F0A9F80446384610F0BBF900E0A6 +:201700001024E0B20AB0BDE8F081C046C60A01202DE9F84306464FF6FC751C46174688465C +:20172000B54200F0848000210FF028FCDFF804910646B9F83A00B04201D1E00977D3214679 +:2017400030460BF04BF9C0B9A81C00210BF046F998B914F0180F0DD0374B0020997911F02E +:20176000180F03D1642805DA184606E0401C08336428F3DB0220BDE8F883AD1C06804545B3 +:2017800018BFA0F802808471610824BF44F004048471012F0CD04179012913D0817911F018 +:2017A000180F0CBF99F83710FF210171477109E001214171817911F0180F0CBF99F8381092 +:2017C000FF210171012F32D1B9F8481040460FF0EBFF60BB194C1A4F00204101A1EB800174 +:2017E000C919B1F87C6307F2AC52002364215588AE4205D0491E02F1080203F10103F6D11B +:20180000642B04D0401C1C341428E6DB0FE0204600211C220AF0E2FAA4F80080B9F848001D +:201820006081AA27A77401266674062525740020BDE8F88350010120CC0600209C040020B2 +:20184000200100202DE9F0479646464A88461E23002401460125204697782FB15B1E02F12D +:20186000080204F10104F7D11E2C79D03E4C3F4F814633264FF6FF7C82F8069037F824AFFF +:20188000D04510D0638F53450DD03B7933F0040A06D0012B07D14B899C4508BF284302E064 +:2018A00093795B1C9371761E4FEA4505E6D1304D1426ACF1010C35F81C3F98450DD09C454F +:2018C0000BD0B4F848306F89BB4206D16F7C27B1AF7C17B193795B1C9371761EEBD19779A0 +:2018E000082F01DC17B909E0082393718B7C012B04D094F826305B1C137101E082F8049019 +:2019000094F82B30937094F82570D7708E891680CD7C82F805E0D571B8B116491E2201F1E0 +:201920003B030D46494613F8017F37B1BE4504D0521E01F10101F6D107E01E2905DA83F88A +:2019400000E005EB8105C5F8AC002078402110F071F820B920784021642214F0AAFF012040 +:20196000BDE8F08744020020500101200810002080040020200100202DE9F84F8346DBF85D +:201980001800057800216A46A3200EF06DFEBDF800004FF00009854224DABDF80000401BE3 +:2019A00084B2042C01DA0CB91DE00324E00000EB041008F005FB5FEA00090FD007464FF069 +:2019C00000088CB146467119A2203A460EF04CFE761C1837F6B2B442F5DC05E04FF0B508F1 +:2019E000002401E04C46C8469BF81100E1B215278DF8020011FB07F0001DC0B2401C08F062 +:201A0000DFFA4E460BF1020B071C45D0781C82468AF800809DF80010E3B2B970FD700425C1 +:201A20003C7143B3001DE4B2314614F069FF317A00F8011BB17A00F8011B7189091200F862 +:201A4000011B317D00F8011B317D032906D0317B00F8011BB1890E35091205E006F10C01B7 +:201A600014F04EFFB17D1535641EEDB200F8011B06F11806D8D10C4E2B460DF10200594640 +:201A800048F23302341DC4F800A00CF005FB38460FF0F0FF09347460B9F1000F02D0484698 +:201AA0000FF0E8FFBDE8F88F2804012030B54B4C0546E079ADF12C0D012840F0878014F06C +:201AC00023FC002840F08280688800287ED1404905A8122207F01AFA20784FF480510DF008 +:201AE00021F8A96911F8010B0C784A788DF8140004EB0220ADF816009DF81400C8BB881C2B +:201B00009DF8181010F8012B10F8015B10F8014B01F0E00102F01F020A438DF8182010F825 +:201B2000013B8DF8195010F8012B10F8015B8DF81A4010F8014B8DF81B3010F8013B8DF817 +:201B40001C2042788DF81D5005788DF81E4005EB02218DF81F30841CADF8201014F8010BC9 +:201B60008DF8220014F8013B8DF8233025788DF82450BDF82000B0F5285F23D2154800684D +:201B80000DF126016A460AF0ABF80446C82C11DA9DF8100010B1FD208DF8100021461422F5 +:201BA0006B46042011F074FC0B4AA000012100EBC4001154002014F07BFD01200146F5F7C4 +:201BC000DBFC03E00120022111F044FB0BB030BDA6860200EC0601200DE900206806012039 +:201BE0002DE9F84FD0F8E8200023083A002AC8BF0123D0F8C0C0D0F8D020E346DBF8004042 +:201C000094420CD8DBF81470002FBC4678D001228CF81020D0F8C0B04FF0000E00E0964622 +:201C2000DCF80020A2EB0E02B2F5806F88BF4FF48062D0F8D8702FB9C0F8D820D1F81C8004 +:201C40008E6904E0C0F8DC20D1F824800E6ADCF804402CB92B4C9F00E55900F1F6040AE0EA +:201C6000294D9F00ED5903F1010A02FA03F90EFB0A444C44641EB56034600C6804F1080986 +:201C8000C6F80490B56843F6F07A1401103C0AEA04042543B560DCF8086026B9194BDD59A3 +:201CA00000F1F40308E0194DED595F1C02FA03F30EFB07669B195B1EC8F80850C8F804308C +:201CC000C8F80090D8F80830E34544EA0304C8F8084004D1D0F8D0309B18C0F8D03090F8B7 +:201CE000FE706FB90B685A6A42F003025A62D0F8CC004F6943680A69196847EA020088621C +:201D0000BDE8F88F24880200348802002C8802002DE9F04306467568B7680C46ADF1140DD3 +:201D200014F008FE95F8FD1021B96169102901D8042903D214F07EFF00206FE04FF001090E +:201D400085F8FD9014F076FF2069C5F8E4006069C5F8E800207B85F8F900207885F8F8004A +:201D60000020616885F8FC008046C5F8C080C5F8C480C5F8C8802B4AC5F8EC10217E12F861 +:201D8000211085F8FA10F989A5F8F610237B002B0CBF1021494685F8FE00C5F8F010387B27 +:201DA00005F0F8FA30460DF095FA97F83B0085F8FB00304609F090FA684614F0DDFA787985 +:201DC00000966B463979184A0190284610F0B0F9684614F011FBB96802911449009605F1A5 +:201DE00030006A460EF0A4F80EF0BAFD014633460F4AC5F8CC1005F11C00042112F0F0FCDD +:201E000095F8F80030B905F16C00414612F0C0F8084800E0A068C5F8BC00304605B0BDE830 +:201E2000F083C046E8850200F9C300003118020035670200776802002DE9F04FADF1140D20 +:201E400002A913F049FA5FEA000940F08380434F029C3E69218856B1B61F0322002036F83D +:201E6000063F994205D0521E00F10100F7D1C82601E080460026182008F0A2F8051C0ED0BF +:201E80000021182209F0AAFF608818212A4614F04BFC4FF6FF70608028460FF0EBFD4FF63B +:201EA000FE7A4FF0000BA4F800A0002E84F804B050D13869444668B3142008F081F85FEA71 +:201EC000000827D04C205946022203AB14F068F902255E463869B44207D0A9B24C20062299 +:201EE0006B4614F05DF9694603E0610001EB84010918A8B20622404413F050FE761CAD1D9F +:201F0000032EE7DB4C201421424614F00DFC40460FF0B0FD4C205946022203AB14F040F94C +:201F2000C0B93F695FB1610001EB8401BDF80C007A5A5646964204D138B1401E03E0BDF8E1 +:201F40000C00401C80B2ADF80C004C20022103AA14F0EAFB484605B0BDE8F08FCCE80020D6 +:201F6000F0B5ADF13C0D11F0A5FF454E96F84A00082807D0332086F8290086F827000127F7 +:201F80007765B76568460021242209F027FF3D4D2878012804D0012000278DF80A0002E035 +:201FA00000278DF80A700F2446208DF837400DF13701B4700FF0FEFE6D1E8DF82470A8794C +:201FC0008DF8250014F0F6FA8DF826008DF827708DF8287096F85C008DF82A700F28A8BFD8 +:201FE000201C06F15D018DF829000DF12B0014F087FC0DF13300FF21032209F0EFFE96F808 +:2020000096008DF8360009A80CF0D6FB06F1140145200FF0CFFE08F0CBFE8DF80C708DF86D +:20202000207096F850008DF8157096F851508DF80800B6F848308DF8095096F85320ADF8C2 +:20204000043096F83C408DF80B2006F13A018DF8064053200FF0AEFE06F13E014B200FF0D7 +:20206000A9FE96F82B203078642111FB02F2082114F022FC684605F0D1F80FB0F0BDC0468A +:2020800050010120E5040120FEB505462B7A33F001000BD0288804460FF08CFC30B9032B8A +:2020A00006D1284601A911F009FB18B90220FEBDADF80440688A443007F082FF071C08BFCD +:2020C00010206ED00021442209F088FEA87A0DF1060112F05DFF9DF8060087F83A009DF81E +:2020E0000700012187F83900384612F061FA242207F11000294613F051FD07F1440038643E +:20210000688AB88769696A8A386C13F047FDBDF804002449B8808878F8718878401C8870C2 +:2021200014F08CFD044614F027FA97F839604FF47A71FF236043B0FBF1F0388003FA06F051 +:2021400087F83700002487F83600288B8DF80040400834BF201C01208DF80100287A8DF833 +:20216000020068460EF052FF801EC1B2BE8FBD8F87F8341097F8342095FBF1F0C0B2387283 +:2021800096FBF2F15143761A1CBF401C3872064E388D40F008003885307801210CF058FF9B +:2021A0002046FEBDE0060120800A0120F0B50646B16948780D7805EB002543480088ADF136 +:2021C000140DA84271D1414C708802A90BF06AFAB71C241D01281DD19DF80F00042807D150 +:2021E0009DF80E00CF2803D19DF80D008C280BD09DF80F0054280DD19DF80E00EF2809D1AE +:202200009DF80D00442805D15F201123E0700020237102E00020E07020712A490A6802F861 +:20222000010B02F8015B2B1202F8013B2078C11001F0020300F0070001F00101194340EAFA +:20224000C10002F8010B607800F0F80100F00700084302F8010BA07802F8010BE07802F83E +:20226000010B207902F8010B607902F8010BA07902F8010BE07902F8010B207A02F8010BB6 +:202280002089001202F8010BA07A02F8010BE07A02F8010B207B10233946107048F20202F2 +:2022A00006F111000BF0F8FE0AE048F202000090307C0190707CB11C80222B4611F0C0FEA7 +:2022C00005B0F0BD2C040120E00301204C1A0120F8B5474C054620684030816F0F780023A3 +:2022E000B7B395F8987097B92521297501680968C98AC90939BFD0F8940090F82500D0F8E3 +:20230000940090F84E0085F86A00801C0EE01521297501680968C98AC90939BFD0F89400BB +:2023200090F82500D0F8940090F84E0085F86A00042085F8693005F1900185F86B000A68BC +:2023400005F170073A604E687E600889388101E001202875B5F89E0095F8A07095F82C2038 +:20236000E88295F8A160EF760F2A2E770CD02068B5F8A870D0F8046305F12C011A4607B987 +:2023800001222846B047034673B995F83C00FF2801D1A86D38B12068D0F8FC2205F13C01DF +:2023A0002846904703460BB11F461FE020680027D0F87463009795F89C10B5F89A3005F1E4 +:2023C00090022846B047071C10D1216801F5807108682A89C0899042A8BFD1F8781103DABE +:2023E000E5206870D1F86C1128468847F8B2F8BD140100202DE9FF47444D0C460646904688 +:20240000600831D230460EF0B9FD698F814205D03046022122460BF002FC08B9002072E06A +:2024200030464FF6FE7102222346FFF771F9002868D124F02004E0091ED2304602A912F0F0 +:20244000E6FA70B9B5F84810304611F02DFF071C12D0B81C13F02FF870B1B91C02A814F024 +:202460004FFA44F0200407E04FF6FC76A00834BF44F0080444F0100425486B8F90F800907B +:20248000012509F101010022C9B20170491E00951846C9B20AF016FBA0BB4FEA641AA00971 +:2024A00034BF06200E208DF8050001A812F0D4FD071C25D0BD7713F041FB78623869057054 +:2024C00004F07804447080F802903112C670002301715FEA5A01437103D3801D02A914F046 +:2024E0000FFA4FF6FC70B8F1000F788004D0B8F10F0FB8BF87F81A803846F7F7A9FE02E052 +:20250000102000E0C7200090BDE8FF8750010120640F01202DE9F041454C05462078002820 +:2025200000F08280B4F9B600B4F9B41088421DD004F1980128460E4611F035FC70B9D4F8A7 +:20254000A810284613F040FF28B906F10801284611F029FC01E0D4F8A80038B1B0F9301077 +:202560000A224FF0E043284603F0A6F914F0E2F9804604F1B8000168A94219BF0026466083 +:20258000002606602078401EC0B2207000283BD194F82400656002280ED1082010F0A4FD3C +:2025A000404614F047FB05F150004FF0FF3113F071FE14F0BFF9804604F1E00014F0D2F902 +:2025C00004F1600014F0B4F904F58E7014F0CAF904F17C0014F0ACF904F5AC7014F09AF971 +:2025E00004F5CE7014F096F9E16911B104F14800884704F1340012F0BFFD0C48007801281D +:2026000002D10E2004F02EFC606805F15007854208BF6660404614F00DFB384614F09EF987 +:2026200005F1B80014F076F9BDE8F0818687020068F200202DE9F843434D444C3E4EDFF806 +:20264000FC80DFF800910746012F44D139480068006801460120884701283CD096F8380180 +:20266000002838D108342068C0F38140C8B940460068B0B154F8080C000834BF4FF48050B3 +:202680004FF440502E4908600A2014F02DF94846006901460120884706F1940014F042F93C +:2026A00001E012F093FA0121206886F83811C0F3814010B94046006848B913F0C3FF8009BF +:2026C00005D28020A860286840F080002860032011F0E4F82BE057BB0BF03EFBA068C0F3A7 +:2026E0008140A8B94046006890B106F1940014F01BF92068000834BF4FF482514FF4415178 +:20270000134A48461160006910B101460020884796F8380158B12868802720F080002860DE +:202720000320AF6011F0A2F8002086F838010020BDE8F883E0010010501800204086020074 +:20274000A8A00C403086020090220840AC4F005028A10C402DE9F04105460024ADF1500D22 +:2027600028888DF84C400FF025F9002879D13E480078A0B9A87804280FD113F0C5FD60B9A8 +:20278000686813A901AA09F0ABFA80469DF84C0000280CBFAD26261C02E0B62600E0B3263E +:2027A0001E2012F0D3FB074666BB03209DF816108DF84D000FAA03A80CF030FD0DF14D0015 +:2027C00008210FAA0BAB0CF02DFBA8680BA9102212F0B2FCA8B106A80090414622461423DA +:2027E000042010F013F89DF82B0030F07F0003D00DF12B0011F092FA022006AB8DF8280042 +:2028000012E0AD269DF84C00012812D102949DF81700019430F07F0003D101208DF8150001 +:20282000FF248DF8144001AB04204146142210F02FFEB7B10920387028887880A8787E77EC +:20284000387169680822781D13F0A8F9A96807F10D00102213F0A2F90448007839460DF075 +:20286000C1FF14B0BDE8F081E5040120CB03012044492DE9F04105464C310868002877D149 +:202880003E4CA7683E1C0BD068883988884203D12979BA78914218D03E46BF69002FF4D1EC +:2028A0001C2007F08DFBD4F80880071C63D000211C2209F093FA4FF6FE70FF233881B8F197 +:2028C000000FFB720CBFA760B761687AB871287A78712879B87068883880287B3875287A99 +:2028E000012806D107F10C00FF21082209F076FA05E007F10C0005F10D0114F001F8A97A14 +:20290000062938DD6879012803D013F0CBFE002831D0B87A00231E46884202DAEA7A102AA4 +:2029200005DB884204D1F87AE97A884200DD01231348007830F0010203D0022808BFEE7957 +:2029400000E0AE791EB9E08F2988884206D12BB128883881A87AB872E87AF872E87908B161 +:2029600001203871A87908B10120F870BDE8F081096828468847BDE8F081C04650010120D8 +:20298000E5040120C40301202DE9F04F002788460646ADF1140D039713F0CCFF3A4D04906D +:2029A0006868384CC36C2069052103AA9847684613F06AFBDFF8E490CDF80880DFF8D0B054 +:2029C000DFF8D4A0DFF8CC80009629F0010926F00106B1451BD02D4820F00100B0420ED17B +:2029E0009BF900106B68206911F1020F24D059469A6B91F90010904781281BD015E04046AC +:202A00000068D0F84C0580476FF001071AE09AF900106B68206911F1020F0DD051469A6B82 +:202A200091F900109047812804D040460068D0F84C0580476B682069DB6A69463A4698472B +:202A4000071C04D540460068D0F84C058047B14507D00E4820F00100B04204BF58460770AE +:202A600001E05046077001206F6803902069FB6C052103AA9847049814F0DCF805B0BDE86D +:202A8000F08FC046A4060120D4050120B51E0200B10A012014010020B00A0120E9970100AA +:202AA0002DE9F0413C4F3B4C3C4D38696168ADF1300D58B921B92868D0F84C0580476168CB +:202AC000096A07F11C0088473548B8636069016929B12868D0F8D40090F853008847286895 +:202AE000D0F8D40090F942000CF0DCF8B0F1FF3F0A9008D00290000834BFBDF808004FF6BF +:202B0000FF7028490880DFF8A0800026A8F87E60C8F8806098F8890020F00F0040F00100A9 +:202B200088F8890098F88810012363F3C71188F888102868D0F8C403804730B91B49102097 +:202B40006B680870596814230B703869454650B9606804687968164805F17C0207F11C0384 +:202B6000A047386113E0304610F02AFC6068416E02A88847334660680593066D08228DE86B +:202B80000C0038697C35294602AAB047A5600CB0BDE8F081D4050120A406012014010020F4 +:202BA00054F10080E600012058000120D8000020680F0120BCB505460020E860012428616E +:202BC000A978287501F0030348081DD2C80801F00C0201D3042A04D1022B01D1480900D239 +:202BE00002240C2A04BFA41CE4B2022B01D148090AD2241D32F00807E4B203D00C2A18BF4C +:202C0000042A01D1641CE4B231F07F070BD0E878641C10F0030FE4B205D0641C8808E4B219 +:202C200024BF641CE4B213F0CBFC2A88641CE4B290420BD0880909D32148016828468847E0 +:202C4000286918B9A87800F0DF00A870287D002834D150202F6969792B798DF800008DF8A1 +:202C600002101819C0B227B17A7F397F89180918C8B28DF8010068460FF098FAC8B12988EB +:202C8000012747764180A97880F83810E97880F839102979036980F842101919416480F864 +:202CA00048402F691FB13A7F416C89184164E860BCBD284613F056FD10202875BCBDC046A7 +:202CC000B80801202DE9F0410F463E4C3E4904EBC00409782668D4F80480ADF1280D8142BE +:202CE0006BDD07B9394F96F85200002865D198F80100022826D1022086F852000EF0DEFB8B +:202D0000684613F0A3F900258DF800508DF808503968039598F80000019169460EF0CAFEBF +:202D200070607068002848D013F044FDF87998B13A68B979706864235143B1FBF3F113F053 +:202D400034FD09E002F06EF8012198F8000086F85210002586F8540006A813F008FD8DF83D +:202D6000185008941A480795294606AA0EF0C2FDB060B068E8B138683060B87986F8530082 +:202D8000F87988B1401E09D0401E10D1B8884FF6FF72411020460CF0FAFE08E096F8531099 +:202DA000204610F065F802E020460FF0F5FA204604E0706808B113F0F3FC00200AB0BDE8CE +:202DC000F081C046F88602006A83020004880200E3220200F0B50446A178606840182178B7 +:202DE000ADF1440D0546F9B9217F0D2914BF00230123227C617841EAC20141EA431100F81B +:202E0000011BA16912F0BEFE0646012B04D104F1080113F075FD0836207C04F1080101280D +:202E200004BFA07D307005E0297860780843287004F10801A7692E7804A813F061FD06A862 +:202E4000394612F09FFE0670A078237F8DF80000E7788DF8013066788DF80270608A8DF846 +:202E6000036060B9A18A40F201128A4207D194F8281004F11E000CAA0CF0D0F903E0A18A62 +:202E80000CAA09F093FE0CA8FF270390207C8DF84070022803D003280CD1022000E000208D +:202EA0008DF8400008210CAA08AB10A80BF0BAFF08A8039020786368694604AA00F028FA3A +:202EC000044628780021102200F0F800287008A808F084FF0CA80021102208F07FFF204627 +:202EE00011B0F0BD70B53248304E4FF08055B067D5F8D8012F4C036801210A46ADF1280D4B +:202F000020469847D5F8D801426801212046904713F056F8284906F124040822204612F04A +:202F20003DFE26490822204611F04CFF20B924492046082212F032FE2248A060224DE560E5 +:202F4000224B2361224A62612249A161224DE561224B2362224A62622249A16200252563F2 +:202F60006563E562204BA363204AE26320492164F06A10B1F16A2846884706F02BFA0DF069 +:202F8000E5FB684629462422082313F02BFE06F108048DF8185029466A46204613F01EFE03 +:202FA000746013F017FE28460AB070BDE8010120E368020000400340C87F0500EC87020035 +:202FC000F0120050517B0100CD000200B9AE0100DD90010045A60100F1BA0100FD7B01001C +:202FE0000DC8010019F70100555B020009D10100C1DD01002DE9F04104460D461646104628 +:203000000021342208F0EAFE082D5CDB61782078357000EB012031460FF0E7F800280CBF83 +:2030200001270027E178A078A2792379657900EB0120B274E179708103EB0520F174F579D8 +:20304000B081002D08BF082103D004F1080010217061357A084625B160180831B061C9B240 +:203060000846002386F82030757973622DB17070605C491C7071C9B20846757FFDB1481CBF +:20308000C2B2605C7270511C86F82000C9B27170A25C86F821208242A8BF737710DA0C28C7 +:2030A000C8BF0C20DFF85080450009192A46404612F074FD7078C6F824804019C1B27070F0 +:2030C0003078814202DD0020BDE8F081B379401A6418C5B2002B08BFB46209D007480E3D7C +:2030E0000E34EDB2B4620078357712F09FFD2D1A35773846BDE8F081440100208001012089 +:20310000B0B5C16891F838300A6903F0030535F0020702F8013B40D1D90803F00C0401D395 +:20312000042C08D1022D01D1590904D2C16891F83B1002F8011B0C2C09D1C16891F83C102A +:2031400002F8011BC168898F091202F8011B022D01D1590921D2C16891F83E1002F8011B7B +:20316000C168C98F091202F8011BC16891F8401002F8011BC168B1F8401034F008074FEAF7 +:20318000212102F8011B03D00C2C18BF042C04D1C16891F83A1002F8011BC46894F83910DD +:2031A00003F0020701F003010F430DD1618D090A0AD2144DA97884F84910A97802F8011B83 +:2031C000A978491CA97003E094F8491002F8011B33F07F0714D0C16891F839101170C16840 +:2031E00091F8394014F0030F0AD091F84B1002F8011F990804D3C06890F84C0002F8010F61 +:20320000B0BDC046E00601202DE9F04307464FF6FE754FF00008ADF11C0D391DBD8101A89B +:203220008DF8008013F056F968460AF061FD07F10409444601280BD1BDF80C00BDF8021015 +:203240007E88B8818E4218BF6E4602D1012441E046468DF80E807888ADF810000DF10E005B +:2032600008F0F6FD012808BF0DF10E043046012618BB74B97888854206D1484612F01BF984 +:20328000012818BF404602D138460CF0EDF906461FE0A089B881201D12F00DF9012807D083 +:2032A000484612F008F9012813D103213C460DE038460CF0D9F9064606E080893146B881A6 +:2032C00038460DF03BFD24B16580022120460DF035FD34463E78A6B1384611F0B9F90128E8 +:2032E0000FD10A48BD89001D0168AA0002EBC502501889180A78164203D116430E7013F0E1 +:203300002EF9204607B0BDE8F083C046DC0A01202DE9F04F0C46834661782078D4F80C90FB +:203320004018C6B2E0781D469246ADF13C0D0428A8BFA77803DAA07800278019C6B211F063 +:2033400069FC0E90E07812F071FC0D9049461022F01900EB050809A813F0CAF84FF0000986 +:203360000146BBF1000F25D1E078042847DB002946D1684613F05FFA09A8069621780797E1 +:20338000637800900D240D9E01951A46CDF810A0204FCDF8148058188DF8204052188DF86F +:2033A000216040195219039069463868029213F06EFA23E0E078042821DB09BB684613F0EF +:2033C0003AFA09A8069621780797637800900D240D9E01951A46CDF810A00E4FCDF81480CD +:2033E00058188DF8204052188DF8216040195219039069463868029212F05FFB014609B171 +:203400005FFA81F90E9812F090FD48460FB0BDE8F08FC0460CDC00202DE9F04780463D498C +:20342000D8F80460C86CD1F808A07F2500220124A946ADF1200DB0438446C86404FA02F035 +:203440001CEA000F10D05FEA0A074FF0000007D0BB789A4204BF401CC0B2BF69002FF7D148 +:203460008542C4BF051C9146521C1B2AE6DB002E0D4637D1284C5FEA0A0726D02168B5F813 +:2034800048004FF6FF72254B3E88B0421AD1BE78B14517D103F130063688B24208D113F04F +:2034A0001DFAA5F848003E88B0420ED057460AE0002485F84A4009B1C4208847204611F0F4 +:2034C000F3F924E0BF69002FDED185F83C90FEF747FDE0B10020216885F84A00B9B1C42025 +:2034E000884714E0EE64684600211C2208F076FC8DF8044000268DF80760D8F80400009001 +:2035000095F852708DF80570684608F009FE08B0BDE8F087500101200C0A0120E40401202F +:20352000FEB53F4C074694F84A00032803D0012818BF092870D13B4D7878384E69780028B3 +:2035400050D17888B91C608753200EF033FC94F84A00092801D011F0F7F90127422002A9F0 +:203560008DF808700EF026FC0420694684F84A004A2011F085F904F14000694613F0C0F90C +:2035800030780B2805D0B4F84800002107F020FE01E006203070687830F0010008D1E08F61 +:2035A0004FF6FE71814203D06946002200F0ACFD94F83200000934BF0020381C02A98DF8F9 +:2035C000080052200EF0F6FB6878022822D194F83200000934BF381C4FF400403946FCF782 +:2035E000DDF917E002290CD130780B2804BF0A2030700020E87020784FF480410BF092FAF3 +:203600007878B4F848200146104607F0E1FD002084F84A0011F0F0FEFEBDC046C4030120B6 +:2036200050010120E40401202DE9F04391460A68D9F800401678804600271D463846ADF172 +:20364000140D242E02F101020A6058D11678521C4C2E0A600ED1AA68E41C24F00304241D41 +:2036600054F8040C414613F0B1FA2968EF600127091A2960462E1AD1E41C24F00304241D4A +:2036800054F8040CE41C029024F00304241D54F8040C002741460390AA68ADF8047001A86F +:2036A00013F090FA2968EF600127091A2960532E25D1E41C24F00304241D54F8040CE86151 +:2036C000C9F80040288B0090A968EA69D8F800004B4613F073FAD8F80040002744B1A96834 +:2036E0008142D8BF481ED8F800100918C8F80010D9F800402968EF600127091A2960662EE0 +:203700000BD1298B012904D0E41D24F00704083403E0E41C24F00304241D1FB9E9690E70D8 +:203720000127EF60C9F8004005B0BDE8F08370472DE9F04105463E48401C0078ADF1280DCE +:2037400030F0010169D1374C04F13A0109880026A94228D0284613F076F8071C59D03879E4 +:20376000012818BF022854D18DF818607888ADF8240006A80CF05AFC00284AD038882849C1 +:2037800008800DF10B0007A913F0BAF812F024FE8DF81660ADF8140039790222684606F0E1 +:2037A00083FBFE6039E0002D33D030F001004FF001062ED10CF068FBADF82600BDF8260079 +:2037C0000DF12601608753200EF0F4FA1648BDF8264007680EF0AEFA1448007810210BF0F0 +:2037E00037FCA7B14FF0D6087868007860B1042011F0ACFB011C07D081F800804C80786853 +:20380000406800780CF0EEFF3F68002FECD10CF04DFD16B9284611F0ABF80AB0BDE8F08115 +:20382000EA02012050010120C00A0120CB030120E40401203F482DE9F04F001FADF1140D6C +:2038400000F1A80100F1980B8046029100F1AC0103914FF4804012F0EFFBE8B14FF0045094 +:20386000D0F89813D8F8046090F88503C3F38857C1F31501C0F38002C1F31501B805014332 +:20388000B06841EAC2716A4602F040FCD8F804008168012011F0E2F9002702260DF10409C0 +:2038A000234D049759F8044F236883B32068806912F0C2FB82462068002352460EF05CFE05 +:2038C0001AF00A0F08D1BAF1000F20D0206847F48047C8F8B0001AE020681449AB6880696D +:2038E000014023EA0100A8602068C1692A6822EA010028602168102011F0B0F921680BF1B0 +:20390000080011F097F8049847F002072060761EC8D127B108F1E000394613F029F804F03E +:20392000B9FCF9F74BF805B0BDE8F08FFDBFFFFF0C1004406CF200202DE9F8430446A06A89 +:203940000D464778C178807800EB0129207F042866D136480378DFF8DC80354901263846BE +:20396000022829D9C01E072846D90838012819D9801E02D0401E3FD03DE033F001033BD167 +:20398000414691F83200800836D391F84A00082802D14846FFF7CCFE48460CF077FDC52845 +:2039A0002AD122E033F0010026D108460078800822D30DF0A5FD1FE033F001001CD10846AF +:2039C0000078800818D34846002109F007F870B1817911F0180F0AD0A18900910288438828 +:2039E0006189104600220CF0C1FB002604E0484612F090FA00E00025608939464A4610F08C +:203A00006DFD60890DF0D6FF50B1A07C022807DBA18940463A300088884201D0012E02D01A +:203A20000020BDE8F8832846BDE8F883E504012082010120500101202DE9F04FDFF8E4A0E8 +:203A4000DFF8E88000244FF001096FF001064FF6FF7B2546ADF1240D01A80090294622464B +:203A6000102303200EF0D2FE00284BD1BDF804109DF80970A80000EB45102AF80010504459 +:203A800047719DF80A3083719DF80820027180F809900482BDF80610C4729DF80B70418012 +:203AA0000623C771049A0372AA278772B2F1FF3FC46015D1037983B11B4A1778032B0CDA25 +:203AC0002FB958F82720C26158F8272009E058F827309A01A2EB830202E0C661866103E09D +:203AE000C261826180F820408B450BD08DF81490ADF8201005A80CF099FA18B1BDF8040081 +:203B000010F036FF6D1C332DA6DB2046042110F0C7FD3328A4BF0648047007F049F909B045 +:203B2000BDE8F08F2C100020E804012098800200FD0901202DE9F8433A4C364D8146241D55 +:203B400054F8040C800807D254F8080C05F14D01000C40F0F000087033484FF001214FF045 +:203B600080531838DFF8A880C0F804140088D3F8F0012668016803F5F87730468847B00EAE +:203B800003D2700E24BF02202870386842683146484690470FF0CAFE38B12068810C2CBF5F +:203BA000002040F307200EF0D9FB2048BC300068C0F3053188F80010410A39BF402185F863 +:203BC00023104021E974800900F0380040F46050A8F85C0038688168304688470E490F4AE5 +:203BE0000AE0105C9478131D844299BF184410F8010C18444078086008684B689842FCD15E +:203C00000228EED1064901200860BDE8F883C0460EB00C400962084000600C40DC870200EF +:203C200094046042B04F005018A00C4050130050394AF8B52120742112F070FD0A2814BFCA +:203C4000002501250C2006F0BBF9071C14D0FF210C2208F0C3F8314E002407E02146012029 +:203C60000C223B460BF0E4FE641CA4B23088A042F4DC38460DF0FEFE294E707830F0010081 +:203C800015D1102006F09CF9071C10D0FF21102208F0A4F800240320214610223B460BF03E +:203CA000C7FE641C332CF6DB38460DF0E3FE1D48006820B180470A2808BF45F008050FF094 +:203CC0000DF90A2808BF45F01005142006F078F9071C1CD00021142208F080F84C20142189 +:203CE0003A4612F01BFD0446092C04D14C2014213A4612F019FD38460DF0BCFE06F1480227 +:203D00007120082112F00AFD04430A2C01D145F020052846F8BDC04674010120DC0A012071 +:203D2000E4040120300901202DE9F0413A4D04462868ADF1200D18B90FF0BCF9286840B3A5 +:203D400030490978A14224DD4FF0FF3112F0A2FA2D490C2014FB00146768A66838780128FD +:203D60002ED0B268511EC843B86028683368844619420BD17068824208D8B96801408142CC +:203D800004D1706930BB308B042804DB604612F0E7FD002431E0DFF8748058F82030A3B93C +:203DA000684612F0A3F900208DF80C00F1698DF80000307E049169460DF03CFF031C01D10C +:203DC000002417E0308B48F82030114A815C491C815400E003687B601048318C0D4B016017 +:203DE0007A681A60204611F087F90120387020460FF04AFA286812F0B3FD204608B0BDE809 +:203E0000F081C0465C830200A0850200B01A0120401B01200C1B0120141B0120101B0120D8 +:203E20002DE9F8431D463B4B089C1B68C3F340689B0E15D20388A3F6020343B141F21E06BF +:203E40009B1B04D000F11A030B60C06903E000F112030B604069106000202860206056E06B +:203E60000388A3F60203F3B141F21E069B1B17D041F6E6769B1B05D0876AC36A90F8246039 +:203E8000BC4603E0D0F820C0436A002600F11A070F60C1691160C5F800C02360007E0DE03B +:203EA000466A836A01E08669C36900F112070F60416911602E602360C67B007C00F0070709 +:203EC000286888B140F203714FF6FF72052310F04BFC8146B9F1050F06DA3046394609F0FB +:203EE000DBF8296841F82900206880B140F203714FF6FF72052310F037FC0546052D06DA2F +:203F00003046FF2109F0C8F8216841F825004046BDE8F88394120050F0B5014688890425A9 +:203F2000ADF1240DADF8140000248DF81F504A888DF81E40354EADF81C20081D897B069009 +:203F4000022923D10DF121016A4607F0C9FE07469DF82100012856D19DF81000022852D16F +:203F600068462146142207F039FFFF20BB008DF81000142203EBC700345031184C606B4643 +:203F80004C72284639460FF083FA3CE051B3032925D008A96A4607F0A3FE01469DF82000C4 +:203FA00001281AD19DF81000022816D1FF209DF812708DF810008A000194781C00946B4674 +:203FC00000F00F008DF8120002EBC100345082195460284614220FF05BFA012408E0102095 +:203FE000214601E0082001218DF81F008DF81E1005A800F04FFC30B9012C04D1BDF81C0034 +:20400000069906F0AFF809B0F0BDC04604E9002038B505461446480817D2880872D31C200F +:20402000002112F0A1F91D20002112F09DF91E20002112F099F91C20002110F081FB0021E0 +:204040001D2010F07DFB002159E01C20002112F08BF91D20002112F087F91E20002112F02D +:2040600083F9284606F032FB21460090C20F0888A0F6020068B141F21E03C01A09D041F6EC +:20408000E773C01A09D191F8240010F07F0F04D019E0C87B10F07F0F15D1012A0DD01C200F +:2040A000002110F04DFB1D20002110F049FB1E20002110F045FB1C2014E01C202F2110F09A +:2040C0003FFB3221BCE7012A10D01C20002110F037FB1D20002110F033FB1E20002110F02B +:2040E0002FFB1E20012112F03FF938BD1C20002110F026FB1D20322110F022FB2F211E204E +:2041000010F01EFB38BD7047F0B50E1C14460546ADF1140D04D0084612F0C2FB071C1ED1B4 +:20412000324F33203979FF2905D0401E07F12407F8D100274BE001208DF80000ADF80250C3 +:20414000314601A812F0C6F96846FFF75DF8BDF80C00002678802846BE7110F009FC0020E4 +:204160000122014614B1052CB8BF04213D803C71797106263E727A72AA25BD723882F87106 +:20418000F8728023F86087F82130E4B118480678032C18DA17483EB900EB8601096B00EB2F +:2041A0008600F961006B0AE000EB8600036B9901A1EB8301F961016B8801A0EB8100B861CD +:2041C00087F8202003E06FF00100F861B8610020042110F065FA332802DB074900200870A7 +:2041E00006F0E6FD384605B0F0BDC0462C100020E804012068800200FD0901202DE9F0433D +:2042000081463848384C07AFADF1240DADF81E300578ADF81C1094F84A009046042814BF62 +:204220000828C2205BD0BDF81E004FF6FE71814208BFC32053D0684600211C2207F0CEFD5B +:20424000032007A984F84A0050200DF0B3FD4B200DF11E010DF0AEFD84F83C80BDF81C006F +:20426000BDF81E6084F832504946A4F8480004F15D00E68712F044FB1C4805F0CE0646F037 +:20428000800504F1240600788DF81A5030F0010003D13878401C84F85C0002208DF816007D +:2042A0000F258DF80B80002284F85150BDF81E708DF80820BDF81C30ADF80E7006F12D0142 +:2042C000ADF8183054200DF075FD06F12C01472084F850500DF06EFD684603F031FB09B079 +:2042E000BDE8F083521A012050010120E5040120F0B5364D384C0028ADF1140D6978207297 +:204300005ED129B9207818B9082011F0CBFC697831F0010051D168460021102207F05EFDBB +:2043200011F0F2FF002848D0294D05F1240006463930074610F04EFE20B9284938461C3158 +:2043400012F0DEFA06F1160153200DF033FD95F83200000934BF0020012004A98DF8100097 +:2043600052200DF027FD082085F84A0006F020FD07F05EFE1A49486808B901204860E0795F +:204380004FF440710AF064FE68460FF02FFB684600210FF01FFD95F8650010B9002004F03D +:2043A00003FA68460021102207F018FD09480078012802D0012010F077FA01200FF046FB3C +:2043C000E07902210AF044FE05B0F0BDE4040120500101209A060120C403012000DC0020A3 +:2043E000100A01202DE9F84F06467068B6F80A80447800F1020B042C10D0012C07D0062CC9 +:2044000005D090F81A9000F1120500270AE090F8129000F1130700F11B0503E000F1120749 +:2044200000F11A054FF0010A5FB1384611F043F8012806D111F082FB0146384611F09EFA7C +:204440008246BAF1010F20D0204C607830F0010039D1B8F1000F36D1384669460FF02EF968 +:20446000012830D100217172BDF80000708194F8260020B170680078052808BF01213173DB +:2044800030460BF0C5F8BDE8F88F202010F05EFD071C18D004203870A7F80280594610225E +:2044A0003C71B81D87F8059011F078FB07F11600294612F00FF887F81E900548FC77007807 +:2044C00039460CF08FF9BDE8F88FC046E4040120CB030120DFF8E8C02DE9F04300260D466E +:2044E00080464FF0B3094FF00E0E3746ADF11C0D01E07F1CFFB2002F5ED1002422462346DC +:2045000001E05B1CDBB263B913FB0EF01CF80010FF29F6D011464A1C8F42D2B2F1D100EBBD +:204520000C04002CE5D061798919CEB2B045E0DA28460021182207F051FC6179A8EB06005F +:204540004018C0B204EB4000C088688111F0F6FA0146284612F0D4F96078012822D06088E1 +:20456000ADF80C0004218DF8001068460BF05EFDE0B103208DF8160001A90DF10E0012F0C5 +:20458000BFF99DF816709DF81600032F287518BFBDF80E0009D105F10C000DF10E0112F049 +:2045A000AFF903E0012028756088A8812078287220794FF00009A875484607B0BDE8F08314 +:2045C000220100202DE9F043374C0346354A2668364C108E2578012B9146ADF11C0D0746A2 +:2045E00018BF4FF000080CD14FF6F87402E012F0D2F801468C42FADD0029F8D08846B9F805 +:2046000030002B4CE6644FF6FF7184F852500F2684F85060B94284F851604FF0000584F88D +:20462000535004D1814201D112F0B5F80746A4F8487009F1500010F0CDFC09F15007012890 +:2046400004D104F15D00394612F05AF904F15D00074610F0BFFC18B9E220394610F010F9AA +:20466000A4F83A8084F85060E58784F85160052084F85C5029461C2284F84A00684607F0BA +:20468000ADFB8DF804508DF80750E06C009094F852708DF80570684607F042FD07B0BDE859 +:2046A000F083C046E4040120D0030120990601205001012070B5324C0D46A80850D2E8089A +:2046C0005DD30125042065700FF0E8F82D480068006B8047A060606804F198060146306863 +:2046E00070B10069064649B18E4207D0B16AC90803D3436A0421002298477576314661608B +:20470000486821490078086002200FF0C7F8112002F040FE1D48007884F8245010B90E209A +:2047200002F038FE60684168886808B9C86810B1174811F041FE174907200026086016492B +:20474000174B0E60154D4E600A68A36245EA020008601A2012F0F2F8192012F0EFF870BDF4 +:20476000FBF776FC204600F1A001096811B909F005F870BDE03045F0020112F0F9F870BD17 +:2047800068F200208C010010D021084086870200510007060000046014100440024000400E +:2047A000790901002DE9F04781461E46924688460846ADF1180DFDF73FFB404610F04CF84F +:2047C000324807684FB103208DF8080041460822684611F0E3F96846B8472D4C607830F0E6 +:2047E000010047D1ADF80290CDF8048002208DF808000025ADF80050404612F051F82EBB9D +:2048000028B9484641460BF069FEAA281ED111F07BFDD8B9AB20294603AA0BF025FF4046E9 +:2048200005A92A4607F05CFA94F82700012807D19DF8140020B98DF80950684607F08AFECC +:2048400001208DF80900684607F084FE404612F027F878B1007968B105280BDABAF1010F53 +:2048600003D0012818BF022801D112F075F840460AF026FF4846002110F002FA484610F01C +:2048800077F810F091FE06B0BDE8F0872C090120E40401202DE970410546DFF8D880A87A86 +:2048A0000024ADF11C0D60B9E87A400909D230480078012804D1404615300078012800D044 +:2048C000C824002C4DD12888696805AA0FF0CEFBA87A00282DD14046E97A00784A0902D2DA +:2048E000C8081BD321E000BB23480078E8B900208DF81600214858C8694658C109C881E874 +:20490000090068686A460DF1160107F0E9F99DF8160018B19DF81000022806D0E87A00099C +:2049200038BFAD2406D3002408E0284607F015FA04461CB168680FF08FFF94B9104E30689F +:2049400090B1288869680822ADF800000DF1020011F024F928893168ADF80A006846884732 +:2049600002E0284604F09AF9204607B0BDE87081CFE80020E6040120FC09012054850200CA +:2049800024040120F8B5134602465468956808464FF0FF31203856D0401E5FD0401E33D09E +:2049A000401E3FD0401E26D0401E1DD0401E52D1D4F8C070002F5AD094F8FE70002F56D0C6 +:2049C0002968486A40F003004862D4F8CC002A6941686F69096847EA02008862296848683C +:2049E00040F00200486026E0D4F8C070002F3ED10020014605E0D4F8C070002F37D10120FD +:204A0000002184F8FE0032E01E78FF2E15D094F8FB000FF00DFA84F8FB6094F8FB00696B82 +:204A20000FF08EFE94F8FB00FF2804D00FF000FAFF2084F8FB00002119E010462321002204 +:204A4000FFF7A0FF12E094F8F90001280FD1012084F8FC00EFE76FF0010108E094F8FB0002 +:204A600000210FF0FBF9002084F8FC0001460846F8BD7047B0B504462079ADF1580D042812 +:204A800069D136480078002865D011F03DFC002861D1AB20002113AA0BF0E6FD276813A824 +:204AA000874207D0002F56D013A8394610F066FF002850D038460DF1550106AA07F010F998 +:204AC0009DF85500002846D09DF82800012842D14FF48170002110220BAB11F061FB0320F8 +:204AE00008210BAA0FAB8DF8540015A80AF09AF9002568460C228DF81450294607F06EF944 +:204B000041208DF80200ADF8005001278DF805701A238DF804306846FEF74CF89DF8140010 +:204B2000C8B90398456C0F272F702079687011F005F80146082213A811F030F813A9A81C8F +:204B400011F0DEFE0FA9102205F10A0011F026F868460CF08FFE16B0B0BDC046E5040120F5 +:204B60002DE9F04711F017FE354C374D84F82400287C84F82B004FF0020884F836800F2731 +:204B800084F8287084F8507084F85170002684F82C6084F82D604FF0050984F83090E87B65 +:204BA00084F82500A87B84F82600012084F82F0084F890004FF6FE7A84F831002148A4F848 +:204BC0003AA0007884F83200E87AA086287B84F83C60082284F83700687BA4F83EA03146E1 +:204BE00084F8380004F1400007F0F8F804F15D0005F14001A4F848A011F082FEA87C84F8B7 +:204C00008E0084F86560314684F88A70687C84F88B90424684F88D00E87C84F88C6004F10B +:204C2000920384F88F00892011F0BAFA08B1A4F8926030460EF0BCF9A4F89460BDE8F0875A +:204C400050010120521A0120E40401202DE9FF41384D95F83C00012101AA044610F0EAFCAB +:204C60000221204602AA10F0E5FC9DF80A4095F83D10EA78002605F130074FF0100C10E065 +:204C80008C4214BF6346BDF80830880000EBC100491CC019838391FBF2F303FB02F0091AE1 +:204CA000C9B295F83E00401C90FBF2F35343C01A8842E5D195F83D40A84635E0A00000EB5A +:204CC000C400C119898B10291AD03A180421022320461C320CF09EF86870E86861036A46E1 +:204CE000042311F053FD009800F0FF007C2802D0FE280BD1FEE7204678210EF057FD05E022 +:204D0000204602F04FF8761CF6B26870E97898F83E30641C94FBF1F04843241A581CE4B2C0 +:204D200090FBF1F24A43801AA042C7D130460090BDE8FF81C01900202DE9F84F904689463E +:204D400000274FF6FE7B824601223946CDF800B00CE0012F08BF012106D011F01CFDC1B227 +:204D600091FBF7F07843091A00273A462A482B4C1423057834F81C0F834517D0824515D0EC +:204D8000814513D0804511D0667C7EB1082E0DDA072E0AD0012A05D07F1CFFB2B94205DC5F +:204DA000BDE8F88F7F1CFFB200E000905B1EE1D135F0010524D11A4B332433F8240F8345DE +:204DC0001CD082451AD0814518D0804516D05E7AA6B1082E12DA1D79012D0FD0022D0DD0DD +:204DE000072E0AD0012A05D07F1CFFB2B94205DCBDE8F88F7F1CFFB200E00090641EDCD165 +:204E00000FB10029A5D00099584688421CBF081C80B2BDE8F88FC046E50401208004002022 +:204E2000081000202DE9F047ADF1900D11F082FD2D4A1178002952D1114601240C7011F0ED +:204E4000F9FEF9F70BFE092002F0A4FA20A811F093FA4FF0FF302190254A2448102120AB5D +:204E60000DF066F92348244990F800800B7800274046054683421BD3DFF880A08600A14664 +:204E80000DEB0600041FDAF80000315821F0FF0044F8040F880807D2E8B201F0010111F040 +:204EA00063FA09FA05F007436D1C361D9D42EAD91549134C4FEA8800C0EB830201F1D00362 +:204EC000121D1F600DEB0001001904F01FF80D49086820F4F85040F40050086001E011F017 +:204EE000A9FE24B0BDE8F087B00B0120901901207D0002004B8302004C830200E8860200E5 +:204F00000010084000300940002002402DE9F04F044694F802A0FF210E22ADF1240D0DF174 +:204F20000E0006F05BFF4FF0FE09E41C14F8010B8DF81090FF25089014F8010B8DF81150D6 +:204F400003288DF80C0005D0204611F069FBADF8040003E001A8214611F0D2FC083414F842 +:204F600001BB2778002F3BD07E00304605F028F85FEA000834D0611C324610F00FFE08989C +:204F8000CDF8008001A95A463B46F7F727FCC0B1017842798DF80E1047788DF81320468863 +:204FA0008DF80F7005798DF8106005AB8DF8125031128DF811105200811D184610F0EEFDC1 +:204FC0000BE08DF80E508DF80F508DF810908DF811508DF812508DF8135040460CF04AFD7C +:204FE000672051460E220DF10E030DF011FA09B0BDE8F08F2DE9F04F09AF8046ADF11C0DD5 +:205000009B460491386805923D7A0690194640460EF0A8FF0828A8BF4FF6FE7905DA2E4E5E +:20502000410001EBC00136F801904FEA251A680934BF0820102069110391A90924BF0830B4 +:20504000C0B28DF80100684610F006F8061C40D00124B47710F072FD706201A948460FF0B2 +:20506000D6FC30B95FEA5A0006D3C14504D1069800E001A874773062346902202070657056 +:2050800084F802B084F803804FEA28232371049A62711012A07148460BF0F0FB05994018BD +:2050A000E0715FEA5A0038BF002005D3069904F1080011F025FC08200399490804D3796882 +:2050C0000019083011F01CFCA6F802903046F5F7BFF807B0BDE8F08F7E0100202DE9F04756 +:2050E000DFF8D890D9F81000ADF1280D002859D0074600244FF0FF0A2F4EB87A20B1401ED5 +:20510000C0B20028B87247D111F0C6FA5FEA000811D006AD8DF81440B91C0822284610F0C7 +:205120003DFD05A808F0E4FD28B1BDF816003A8829460FF0E8F9B81C0DF126016A4606F05B +:20514000CFFD054609A9B81C0EF00AFAB8F1010F1FD19DF81000E0B102281AD0B81C0FF0EA +:205160007BFB9DF82600012813D168462146142206F034FEA80000EBC5008DF810A01422BB +:20518000345031184C606B464C72042029460EF07FF938460AF0F6FEFF68002FADD1D9F8CD +:2051A000100028B999F800004FF4006109F0BAFC0AB0BDE8F087C04604E9002068060120A2 +:2051C000F8B5364DAC680746B0B9002C64D0207850B1152110FB01F02346401CC521C2B28B +:2051E00045200DF015F9AC68002C55D0A8680CF041FC0020A8604FE044B9FA2004F0E0FE51 +:205200000446002CAC6047D00020207020783978152610FB0640401C00F8011B3988091224 +:2052200000F8011BB97800F8011B7988091200F8011B397900F8011B797900F8011BB979E7 +:2052400000F8011BF97900F8011B397A00F8011B797A00F8011BB97A00F8011BF97A00F834 +:20526000011B397B07F10D03082200F8011B194610F094FC2078401CC0B20A2820700BDD19 +:2052800010FB06F0C5212346401CC2B245200DF0BFF8A968002008700020F8BD8C0A0120A0 +:2052A0002DE9F04116468846044611F043FB074631488325B8F1090F36D8DFE808F0554A59 +:2052C0004744402917053C37044694F82400E8B9D4F89800D0B9316804F1E00010F0BEFC9B +:2052E000316804F58E7010F0B9FC3FE0044694F8240058B9D4F8980040B93168192011F00F +:2053000021FB31681A2011F01DFB2FE000252DE0306828B1012807D180200DF0E5FE25E04D +:20532000802010F02FFA21E003251FE0202031460FF094FC1AE031781048017016E031683B +:205340001030016012E03088A0850FE0308860830CE0012026696369607606F1600020613D +:2053600003F16000606101E030682060384611F061FC2846BDE8F08168F20020A8F4002089 +:205380002DE9F84307467D68BE6890460C4611F0D1FA814630682B78026B02F4807203B165 +:2053A0001AB1484611F046FC56E005F5B27011F0BBFA2C620024EC776C623168086B40F426 +:2053C00080700863484611F035FC05F2A91010F033F8414638460DF0DDFC05F2A919A86239 +:2053E000A8B9384641460AF0B7F8A878D0B9A96805F1C40010F04EFFE8B1AC621020E877A7 +:205400003146284606F0B2F805F2A91022E011F091FA3268916B41F02001916311F00AFCE6 +:20542000A87810B12046BDE8F883A96805F1C40010F030FF10B9686ABDE8F883384641464B +:205440000AF08AF81020AC623146E877284606F08DF848460FF0E0FF4FF0FF30BDE8F883D9 +:205460002DE9F0410546ADF1400D681D06A90EF025F96E1D01285ED168880DF12A0108F06B +:2054800011F9012857D10DF11A002C4C029020788DF8320011F0D2FB074611F06DF84FF47C +:2054A0007A787843B0FBF8F08DF8330011F0C6FB074611F061F87843B0FBF8F0000A8DF8AE +:2054C000340010F03BFB014602220DF1350010F065FB0DF11A000DF1320240230090002007 +:2054E0000146F7F759FB039603278DF8067001238DF812308DF811308DF81030002605962E +:205500006988ADF804109DF81A00207001A8F7F707FE8DF810600DF12A040394BDF8180081 +:20552000ADF8040001A8F7F7FBFD0DF11A001022314606F053FC10B0BDE8F081100A01201C +:205540002DE9F041344C20780D46290C1ED2E80B38BF00205ED30FF05DFB304C804604F1AB +:205560000C00006858B107463E69384611F03EFB38460CF07FFA371CF6D10020E06040460F +:2055800010F0D3FC85F48040BDE8F08109F032FD071C3DD03878233801281CD9001F34D148 +:2055A00008200FF0D3FC061C11D0012030707878C01C04F005FD6478706040B17A78791C4B +:2055C000D21C10F0EBFA204631460BF00BF938460FF0C2FD19E00C200FF0B8FC061C14D002 +:2055E00000210C2206F0FAFB0520307000247470B8783071F8787071F87804F0E1FCB06031 +:2056000018B17968FA7810F0C9FA38460FF0A4FD85F40040BDE8F08128180020380A0120FB +:205620002DE9F04FADF1140D04900DF048F95FEA000861D0002427463D46B94623E008EBF9 +:20564000C500401C834611F02BF9D0B10179012918BF022915D190F82000012811D10C204F +:2056600004F0AEFC061C0CD0594611F049F9C6F80890002C0CBF341CCAF808607F1CB24652 +:20568000FFB26D1CEDB298F80000A842D7DC002F2FD00220049E8DF80C007088ADF80400E0 +:2056A000F80004F08DFC061C21D074B14D46A14606EBC500494611F023F9A46848460CF0CB +:2056C000D9F96D1CEDB2002CF1D148F21F00009004983A4601A93346113002F07FF830469A +:2056E0000CF0C8F905E02046A4680CF0C3F9002CF9D140460CF0BEF905B0BDE8F08F70471F +:205700002DE9F04788461546814600212022ADF1200D684606F062FB4046103808D0083837 +:2057200004D0083814BF0026032602E0022600E00126012404FA05F7274D4FF0805000F58B +:20574000D87A2F60D0F8B001416927208847C5F87C430321C5F88013C5F8FC42C5F88413F0 +:205760006868B04218BF6E60B8F1180F45F8047C1CBF41464E4606D168464946182203F0FE +:20578000C5FB6E46202130460DF02CFC204611F08AF8D5F88C036FF39D000028F6D0D5F8BA +:2057A0008C636FF39D06C5F88463DAF80000016A27208847DAF8000001692720884716F0A6 +:2057C000404F04D12868074218BF002000D1204608B0BDE8F087C046044402402DE9FC47A1 +:2057E00007460E1C14BF4FF0000A4FF0E80A002F5BD0BAF1000F5AD17868401E78603F2130 +:205800000170BD6D002D0CBF802000207968DFF8A4900225083E491E7960A8460870388975 +:20582000A7F85450801C388116F8080FFF2839D02A2834D1706890B3D9F80010D1F8B81097 +:205840008969884705467868401B78607168CA0809D2D9F80020D2F8B820D46900233A4630 +:20586000A04788B113E0D9F8040080680078D9F800408DF80000D4F8B8007168C4697868E0 +:205880003A466B46A04710B9EB20BDE8FC873889B7F85440401938816019A7F85400B8F1C9 +:2058A0000108C1D17868386501E04FF0E80A5046BDE8FC87140100202DE9F8430446994651 +:2058C00090460E1C44BF0020011C5CD411F04CF805463146802220460CF030FE071C04D028 +:2058E00097F8331031F07F0106D1284611F062F902200021BDE8F8834FF0E0400A2107F1AF +:20590000200640EA090941EA080896E8030008EA000019EA010608BF00281CD0284611F023 +:2059200049F907F1200003C804F1B00604F1B00508EA000809EA010986E8000395E80C00FC +:2059400007F1200696E8030007F120059943904385E8030014E00D48B968884203D0B96844 +:20596000C4F8A810B86004F1A00080E80003284611F020F904F150004FF0FF3110F08AFCD9 +:20598000B03494E80300BDE8F883C046E1E80100F8B52F4C334D6788BFB905F1080000683F +:2059A000D0F8F4002B4BC18F012606FA01F08102A1EB801118784FF47A7201F5707148438C +:2059C000B0FBF2F081B2A18000E0A1882078B9421ADD21480068214F016C3868884721789D +:2059E000C0B28142B8BF20706088401C608010F0C3FD4FF47A71B1FBF0F0194904F108036B +:205A0000002204F023FBF8BDA968D1F8F46040B20EF0B8FD96F84410B2695054A868D0F851 +:205A2000F40090F84420012700EBE20002F0070207FA02F1427900238A434271AE6863804B +:205A4000D6F8940023700078042109F001FBF8BD740A0120D8000020D8050120B40601209A +:205A6000915901000C010020F8B50020314C8DF8000010F0D1FEA41EA2782F4D0121914025 +:205A80004FF6FF72521802402868D0F8B81062810878002829D08A6B3AB342F21A00694621 +:205AA0009047204867790678CEB1C7B99DF80060AEB12868D0F8B800C06D80B18047074674 +:205AC0001E48017857B16868406866890078083010FB01F0B7FBF0F17018608167799DF85B +:205AE0000010608907FB01006081607810B904F0C5FB01E008F004FB2868006C006878B10F +:205B000009480B49007840B90848007828B98322084602700FF0E6F9F8BD022208460270EA +:205B2000F8BDC046641B01206F1B0120711B0120741B01200618002014010020D800002097 +:205B400010B504462088ADF1180D0BF033FF002859D110F0D9FB002855D1A0782B4958BB8B +:205B6000207A04284FD1084600686A4605A906F0B7F804469DF81400002844D09DF81000B2 +:205B8000012840D102209DF813308DF8100033F07F0003D00DF113000EF0C0F80420214675 +:205BA00014226B460DF074FC002010F081FD01200146F1F7E1FC26E0207A042823D10846B8 +:205BC00000686A4605A906F08BF801469DF81400C8B19DF81000012815D1002201929DF81F +:205BE0001300009230F07F0003D101208DF81100FF228DF8102004206B4614220DF048FCB4 +:205C000003490220087006B010BDC046EC0601207006012070B5334D06462868D0F83C03E3 +:205C2000ADF1300D8047002818BFFC2057D168463146112203F06AF9B47C707CF37C8DF8C1 +:205C400012402A688DF81100717D8DF81330D2F8D400B47D90F853008DF815108DF8140027 +:205C6000002104B10121347E8DF8161096F825208DF81840F07D8DF8252096F824308DF881 +:205C80001700F48C8DF8243006F119010B220DF11900ADF8264003F039F9707C002448B9FE +:205CA000812004F08DF90A9078B1FF21812206F095F80CE09DF815000A9440B1810001EB2E +:205CC000401004F07DF90A9008B91A2406E02A6802F55172126807206946904720460CB0F6 +:205CE00070BDC046140100202DE9F04F09AF9B4692468946ADF1240DBC8897F800800790EE +:205D0000242004F05DF91026002800904ED00021242206F063F827484078002530F00100C4 +:205D20000FD1484610F08FFD40B10079012818BF032803D1E00938BF44F48064E00A28BF33 +:205D400001251D49009809884181ADF818A080F81FB002230373079A02620372A0F80090EB +:205D60008DF80C8080F80D80F968ADF80A4006C904AB83E80600387A29468DF81A00684660 +:205D8000F6F7F8FF01280ED10A48407830F0010007D1012D05D140460FF0B8FD08B106F027 +:205DA000EBFA002602E000980BF064FE304609B0BDE8F08FE40401209801012070B506467A +:205DC00000210C22ADF1380D06A806F007F80EF090FE30F07F000CBF002501250024072062 +:205DE00021460C2206AB09F023FE30B92DB1072021460C2206AB0DF04BFB641C052CEEDB52 +:205E000007A8FF21082205F0E9FF641EA4B207200C2206AB214609F00BFE30B92DB1214637 +:205E200007200C2206AB0DF033FB68460021182205F0D4FF822018216A4610F06FFC30B981 +:205E4000012E04D1822018216A4610F06DFC09A80021112205F0C2FF3A20112109AA10F050 +:205E60005DFC30B9012E04D13A20112109AA10F05BFC3B20112109AA10F050FC30B9012EA2 +:205E800004D13B20112109AA10F04EFC0EB070BDB0B5314C04F124010878ADF1780D742283 +:205EA0006B46401C08702120002110F079F994F8240074216A468DF80000212010F034FC9E +:205EC000264DE8780027032805DA0BF0A1FB012808BF042000D00D200FF0E4FE618F4FF600 +:205EE000FE70884208BF0127B4F84810401C88422DD06FBB1A49487830F0010008D008788E +:205F0000012805D04FF400500121F9F747FD06E001208DF874001DA952200BF04BFFE878BD +:205F200003280DDA0BF074FB012809D1002028710120F8F755F8E978491C0746E97007E079 +:205F4000012028710020F8F74BF80021F5E7012738461EB0B0BDC046500101206806012050 +:205F6000E40401202DE9F04781463148006888464FF47A711E46ADF1280DB1FBF0F080B232 +:205F800002FB00F50EF046FE8246414648460FF0E3F90824071C37D1142004F011F8071C6A +:205FA0003CD0684600212422234610F0FFFD012E1ABF0020059005950120ADF810001B48CB +:205FC000069729466A46002310F0ECFD03461948083882683B609BB187F80490C7F80880E4 +:205FE00000243E73002A3C6108BF876004D0164633691BB937613B68184609E01E46F7E7F3 +:2060000038460BF037FD09E0386810F0F3FD3868294610F0C3FD386810F0BCFD50460FF09D +:2060200084FF20460AB0BDE8F087C046E1FA0100A0880200400A01207FB500242E482D4DE2 +:206040002F4E04702D482C7031680470D1F800016C70C089D1F850126C61103080B2884709 +:20606000286120B93068D0F84C058047286900908DF804409DF8051004F0030221F00301A4 +:206080000A438DF805209DF8051064F383018DF805109DF8051064F307118DF8051031689E +:2060A000D1F80011C9896A461031ADF80610296913680B6052684A60E8612C6202F0E0F98A +:2060C0007068C168087838B93068D0F858242046014690477068C1680A4804700A4D2C7034 +:2060E000087828B93068D0F8582420460146904700907FBDB41801206F1B0120711B0120CE +:2061000014010020741B0120641B0120F0B50E460021ADF1140D0191029103911446049179 +:2061200003AB02AA04A9009101A9FDF779FE8325310824D2E0B1039F87B10499C6F3150203 +:2061400071B1019840F22B21028038460EF0B1F90298049906F086FE039826E0C6F315023C +:2061600040B1019800884FF6FF71814202D132E0C6F31502019802806280102029E0002882 +:2061800029D00399A9B10499C6F3150699B101984FF6FF720280084632462B210EF089F9F2 +:2061A0000298049907F0C8F8049815212180606012E0C6F3150670B102982B2132460EF07B +:2061C00078F9FF2807D001984FF6FF71018066601420208000E00325284605B0F0BD704758 +:2061E0002DE9F04188463049074648780025ADF1180D8DF8145020B9C879002808BF012009 +:206200004ED0002F14BFB8F1000F022048D0404605A96A4605F064FD06464FF6FF70B04240 +:206220001BD09DF8140060B19DF8100048B99DF81310052010223B4601F07F010DF028F9F4 +:206240002DE02C460520214610223B4609F0F0FB092804D0641C282CF4DBB22020E002A878 +:20626000414608220FF09AFC44F08004284601953146009014228DF810006B468DF81340C1 +:2062800004200DF005F90948B70007EBC60429460C222418204605F0A1FD012060722846E8 +:2062A00006B0BDE8F081C046E404012004E90020F8B507462F48314B067814460A460021C0 +:2062C0003846803851D0C01F3CD0DFF8ACC0001F23D00D3843D0001F44D0401E0CD0401E04 +:2062E0003AD0812F45DBD82F43DC184636383F1817F85D0C014633E036F0010639D16046CC +:2063000064224FF6FE73083030F8085BAB421CBF491CC9B2521EF7D122E036F0010628D176 +:20632000604664234FF6FE7530F8086FB54203D08A4204D0491CC9B25B1EF5D1F8BD082271 +:20634000014605E010460DF0C5FF011C11D01C2220460FF023FCF8BD184600F1140319788E +:206360002170F8BD0EF052FDC4E71846123000882080F8BDE5040120C406002086010120C6 +:206380002DE9F8439146884607460BF013FB002818BF002058D1384600210AF0EFFD494655 +:2063A00006F01CFB0025041C19D138460EF044FF10F049FA002846D041794A0843D38908AE +:2063C0004FF0010606D340463946324608F0FAF880B938E0417941F0020141710AE0607983 +:2063E000032806D001282ED1608807210BF0FEF948BB02261CB1A07910F0180F19D14046CA +:2064000029460AF0BBFD11493A31098881420AD040463946324608F0D5F8A0B938464946C0 +:206420000EF02EFC0EE0384649460822FBF7E2FF08E0608839462A464FF6FE7300904046B1 +:2064400009F094FE01252846BDE8F883500101202DE9F043804600210822ADF1240D06A8B4 +:2064600005F0BCFC0021142201A805F0B7FC0025FF274FF001092E46274C8DF8147004201F +:206480002946142201AB09F0D3FA002837D1B8F1000F27D101A8009029463246142304208A +:2064A0000CF0B4F903A806A908220EF045FE58B90199A80000EBC500231883F809900B31E0 +:2064C00001912150029A5A6004202946142201AB0CF0DEFF01A83146142205F07FFC8DF8CA +:2064E00014700CE004202946142201AB0CF0D0FFA80000EBC50026502018466046726D1CFF +:20650000C82DBCDBB8F1000F02D030460DF006FC09B0BDE8F083C04604E900202DE9F04FB7 +:206520000546287B0E46ADF1240D80460CF0E4FF071C30D06C694EB3414608220DF0F6FE0A +:20654000031C27D03CB3A07893F800B0B3F802A097F80A9008900FF067FF5FEA000819D036 +:2065600008200EF0F3FC011C14D0FE2008704E70089B8B7081F8039081F804B0A1F806A09B +:20658000D8F8040000780AF02DF903E0414604220DF0CCFE0CB9002023E0A088ADF80A0079 +:2065A000E088ADF80C00207A8DF81800F8680590607B2E688DF81900306A4178007800EBD1 +:2065C0000120801110F0030F00F0030208BF0422237801A803F0400103F020030097F4F705 +:2065E000D1FB09B0BDE8F08F2DE9FE4FDFF8C08098F8410200284FD0002501212C4698F815 +:20660000412201FA04F0104203D1641C032CF6D342E098F841221020A040104218BF0D1C13 +:2066200010F088F998F841221121A1408A4388F8412210F0FFFAE0B20FF04EFD60B3877A3A +:2066400057B390F9099019490768012D446851F82960019710D0017A02290DD100F1100193 +:2066600091E8000C00274FF0805317EA0B0703EA0A0108BF002901D105F078FA012D04D026 +:20668000009600224FF0006303E000224FF00073009201984946A04798F8410220B108F5A7 +:2066A0008E70002110F064F9BDE8FE8F9430044068F200202F4870B534380468B4F1FF3F53 +:2066C00008BF00240EF08CFF04283CD10AF0B2FE142838DB28481C4E002510380560306CCC +:2066E000806C80471948006820B1194800682046FDF720FA174818490560184C0A686FF3B3 +:206700005B4244EA0200086015490868C0F30130012806D10A681348104040F400320A60A5 +:206720000860114D0124EC613068016A142088470E49086840F4E02008600D492C60086866 +:206740000028FCD170BDFEE7B001001080012843800520438C2108404820034000003901C3 +:2067600028000940EFFFFCFC00002443002009400C00684250130050940460422DE9FC41FC +:206780000646022568468DF801500EF065FC071C52D03869042260240270411C0C700124A3 +:2067A000BC76BC770FF0CAF978622449F87E7E8038B908462F3890F82420531C80F824304A +:2067C000FA76387E012806D10846007818B9387808B90020387638460DF10601F8F774FDDA +:2067E0005FEA000825D0242003F0EAFB061C1DD00021242205F0F2FA502001A90EF040F890 +:20680000BDF80400708135739DF8063035727888F3773080F481787DC6F82080084970739E +:20682000304602F011F830460BF024F940460BF021F938460BF01EF9BDE8FC817F0101206B +:20684000452C02002DE9F0410FF0C6FE4FF08058D8F8E801406880470FF0F4FE054605F04B +:206860000C000C283FD0E80822D20DF0B7FD234F3C680646012001460EF03BFE39687143DE +:20688000884215D21E4DF020B0FBF4F0311A284610F084F9284610F07DF900BF00BF012084 +:2068A000F7F742F900BF00BF284610F0A3F920E000BF00BF280918D208F5EC7420688068C1 +:2068C0000146104888470428F8D0690903D2002818BF002000D101200CF09EFB0A480121F5 +:2068E0000160006803E000BF00BF10F011F800BF00BF0FF077FEBDE8F081C046A08802002D +:206900005C180020004003402C2009402DE9F04389462F4907464878ADF1140D20B9C87955 +:20692000002808BF012050D0002F40D0B9F1000F3DD010224FF6FF7141F2210001F00106EF +:206940004B0824BF414089B2491016B141F4004189B2521EF2D17E1E10254FF6FF748046F2 +:2069600016F8010F08210EF0D7FC8446802004F40043610010EA0C0F8CB21CBF83F4004311 +:206980009BB213B188EA04018CB24010EFD16D1EE6D1204610210EF0BFFC4FF6FF71484052 +:2069A00084B207F110000FF03BFEA04201D002200BE001A800903A46902300200146F6F7E1 +:2069C000EBF801A84946FFF70BFC05B0BDE8F083E40401202DE9F84315468146287A9846D6 +:2069E0000E46012803D010460CF093FA00E028884FF6FE71814226D0264B00274FF00E0C7A +:206A000001E07F1CFFB2F7B917FB0CF1CC18595C8945F6D1297A012905D16278012A02D1E1 +:206A2000628882420AD00129EBD061780029E8D161888142E5D121798845E2D131462046D5 +:206A40000EF042F910B9B420BDE8F88365792746002D11D007F106010ED0201D30F8022F74 +:206A6000964205D17A79521ED3B27B7113B903E021F8022B6D1EF1D10FB1787930B96588CB +:206A800038460FF0F4FE28460AF074F80020BDE8F883C04622010020F8B5071C0C4604D034 +:206AA000387A022803D0032801D0E820F8BD384603F02AFCFF2818BF1E2046D1387A054687 +:206AC0000FF05CF901210246002001FA00F31A4202D0401C0528F8DB052804D1022D14BF5C +:206AE000032D1A2031D0022D07D01A4A7B68083202EBC00253603B4610E03A8826128DF852 +:206B00000020154D8DF802406B468DF8036012128DF8012005F1080202EB80021B680B4D7F +:206B20000B4C13603B7A022B19BF2A1C1268221C126801FA00F6022B42EA060214BF2A60AA +:206B400022603A7A0BF0D6F90020F8BD08180120041A012004180120001A0120F0B5054678 +:206B60002E4C6878ADF1140DF32850D0DF284ED0E8284CD0DB284AD02068D0F8FC11284688 +:206B80008847071C42D1687C00283FD095F8340000283BD12268B83210680078002835D14E +:206BA000D2F87C2105F1120109209047061C2DD02068D0F8302405F10B01E720904720683A +:206BC000D0F8302405F10801502090472068D0F8302405F10A01E12090474FF6FF720220FE +:206BE0002368ADF80420A97A8DF80C00D3F8C07100912B89304601A9B8470746F32F05D0E9 +:206C0000DF2F03D0E82F18BFDB2F05D16F702068D0F804122846884705B0F0BD14010020AC +:206C20002DE9F0412E4C2068E03081680D68002D54D001686A680968914206DAD0F86C04B5 +:206C400080472068D0F8E80005685DB10CF0D2FB6968884206D2083CA068D0F8D4048047CB +:206C6000BDE8F0812168D1F8E80000680AE02068D0F80015404688473846A8472168D1F8F9 +:206C8000E800006850B34668002E0BD5D1F84C05804721682068D1F8E810D0F8E800096811 +:206CA00000684E68077B856880460CF0A3FBB042DDD22168E0318868006840B1096840684A +:206CC0000968814203DD0BF055F9BDE8F0810FF079F82168D1F8E81000200860BDE8F081E9 +:206CE000140100202DE9F041244D0646287886423AD000283ED1224F3868D0F838038047D7 +:206D0000002837D00FF016FE1E4C8046207818B13868D0F84C0580471B48007818B13868DC +:206D2000D0F84C0580471948007800BB18480078E8B918480078D0B917480078B8B917485E +:206D40000078A0B91648007888B90CF01FFB267040460FF06FFF012E05D0022E03D0386805 +:206D6000D0F84C0580472E700020BDE8F08140460FF060FFE220BDE8F081C0466E1B0120B3 +:206D800014010020B50B0120B41801206F1B0120711B0120741B01206A1B0120701B012096 +:206DA000721B01202DE9FC412D4C05466069002710B1804700284CD0002F4AD1E068226A34 +:206DC00069030FF0D9FC002841D40C2004F1300815FB00F026184044173001783036FE29CE +:206DE000AEBF0121491CC9B20170009840F0FF0061F31F2019496A460423014300912846DD +:206E000039460AF007F8607038B9A800FF2100EBC50040448175032444762846FF214FF099 +:206E2000FF323B460DF0C8FC2846FF214FF0FF3201230DF0C1FC2846FF214FF0FF320223E0 +:206E40000DF0BAFC1020B083FF24347602E0012700E00B273846BDE8FC81C04600000F96E8 +:206E6000C01900202DE9B04304460FF063FD28498146621892F84A01401EC7B2002F82F860 +:206E80004A713ED1264800EB84000478408834F07F07804614D1E0090BD21E480068806935 +:206EA000014640468847404608F046FF0228FAD121E001EB8801D1F86011002088471AE0E5 +:206EC0004FF08055D5F8B801006A014640468847D5F8B801806A014640468847D5F8B80180 +:206EE000006B01464046884701210B4A0B48116001688908FCD304F03F00152801DAFFF746 +:206F0000B1FF48460FF096FE0020BDE8B083C04650180020B8010010282008602820084011 +:206F2000408102002DE9F84305462C684FF0FF36E6620FF0FFFCDFF89CC094F830E0814612 +:206F4000BEF1040F09D16246177837B1224903204860086820F003000860204A204F6369B0 +:206F60001168002090469F4204D019B96246177807B10120BEF1040F4FF0000703D111B16D +:206F8000624613780BB9384301D00DF02DF894F8320028B148460FF04DFE3046BDE8F88387 +:206FA00094F83000042804D0404621460DF042FD03E0404621460DF050FD012084F8320003 +:206FC00048460FF037FE02F021F9284609F046F9BDE8F883AD0B01200C8002400C0B01203E +:206FE00080A9030038B52B4C2068D0F8AC00007808B909F0FBF900F053FD2068D0F8B80097 +:20700000007820B1244808300168012088472348007810B91D48007818B12068D0F84C0537 +:2070200080470FF087FC1E490A78022A1FD10122174D0A706A78022A03D0032A18BF062AEC +:2070400001D183220A700FF0F5FD697831F0010018BF042902D1FEF707FD6978022903D09C +:20706000032918BF062904D10DF03CFF01E00FF0E1FD2168B8310A68107828B1506918B14C +:20708000D1F870121020884738BDC046711B01200418002014010020D80501206F1B0120E4 +:2070A000741B0120034630B50020ADF1140D019002460292039298685C7E42800188049256 +:2070C000A1F60201C9B141F21E05491B15D041F6E675491B012920D8417E012C62F3820121 +:2070E000417606D0018B21F47C7141F43471018313E0018B62F30911F9E7417C012C62F30A +:207100008201417405D0018A21F47C7141F4347102E0018A62F3091101825A7604A902AA73 +:2071200003AB009101A9FCF77BFE50B1019800884FF6FF71814204D10298049906F0FCF86A +:2071400003E00298049905F08DFE04481830016809B10298884705B030BDC04668F2002053 +:207160002DE9F0410646B469ADF1180D20460EF0A2F9DFF8A08038B10EF0E0FC0146204636 +:207180000EF0FCFB012805D141460F78002F3DD0002002E041460F782046022F029004D1A3 +:2071A0001D49B28B0988914230D1377B002F2DD1257AE90939BF0024211C012100248DF833 +:2071C0000C1035F07F050CBF271C01278DF80D708DF80E402FB920B94FF400500121F8F77A +:2071E000DDFB02A800F046FA8DF81000B11C48F23402012304A8009006F1110001940AF014 +:2072000029FA1DB9029808B90FF04DF806B0BDE8F081C046E50401208E010120F0B52C4E2B +:20722000054630680127ADF13C0D0DA9D0F830248DF83470522090470024342268466C750F +:20724000214685F8204004F0C9FD28680090A888ADF80400A8798DF80600287A8DF809005B +:20726000687A8DF80A00A87A214600B13946E87A8DF80B10214600B13946287B8DF80C1007 +:20728000214600B139468DF808400F208DF80740104B8DF8240043F6FF778DF80D101878AA +:2072A000ADF8267001280BD13068D0F83024291D502090473068D0F83024A91DE1209047FB +:2072C0003068D0F828126846884720460FB0F0BD14010020E5040120F8B52D4C064620688C +:2072E000D0F828240D4669464F2090472168D1F8D40090F85300D1F818148847234F0428CF +:207300002DD02168D1F8D40090F85300D1F818148847C0B9397806F10800400080B235B12A +:207320004FF47A7292FBF1F28018163080B29DF80030676801229A407B681B78521E0833EC +:2073400012FB030018E03978F000603080B2A5B14FF47A7292FBF1F2801898300CE03978D0 +:20736000700100F5867080B23DB14FF47A7292FBF1F2801800F5F67080B2122E8CBF2822F8 +:207380000C22801880B241438800F8BDD800002014010020F8B506460FF0CCFA264D074689 +:2073A000711991F84A01421C002881F84A213DD1224C04EB8604267806F03F00152801DA25 +:2073C000FFF7E8FF648836F07F0014D1F0090BD21B4800684069014620468847204609F035 +:2073E0008FF90128FAD121E005EB8405D5F86011012088471AE04FF08055D5F8B801C069AC +:20740000014620468847D5F8B801406A014620468847D5F8B801C06A0146204688470121F6 +:20742000084A0948116001688908FCD338460FF001FC0020F8BDC0465018002040810200CF +:20744000B80100102820086028200840FEB54FF0805684684568D6F8D0112068C96888478B +:20746000216822488A6B1040886340F2F2712068204B41641E4994F8210094F82020085C78 +:207480009A5C21681043486368460FF045FA1C4FDFF868E0D6F8D0112B7FDFF85CC06A7FC4 +:2074A000A87F496857F823705EF82260AA695CF820300D46206801993E433343A84721689F +:2074C000C86A40F01000C8622168086B40F001000863A07D0027FF2802D0E07DFF2800D1E6 +:2074E0001FB1086B40F440400863FEBD0DF8FFFF628802006E8802005886020044880200DA +:20750000088702002DE9FE4F0D4601900BF011FA174600284CD1019841688668254B002F1C +:207520004A6834682448318C1A602C4401603ED04FF6FF7980464FF0D80B4FF0200A0198D4 +:2075400008F0F2F938BB01980BF0B8FE18BBB94507D219EA040F04BF8DF800B04FF480355B +:2075600002D0B5688DF800A0210C8DF80110200A8DF80200B8F8001001988DF803400EF064 +:207580005CFE6846042108F009FF40B1B8F8001001980EF05BFE4FF0FF30BDE8FE8FB8F8CD +:2075A000001001980EF052FE64197F1BC7D10020BDE8FE8F0C1B0120101B01202A48016864 +:2075C000D1F8B020D1F888031060D1F89C03D1F8B0205060D1F8A003D1F8B0209060D1F8DF +:2075E0008002D1F8B020D060D1F8A403D1F8B0201061D1F87C02D1F8B0205061D1F88402E6 +:20760000D1F8B0209061D1F8B0200020D061D1F8B030D1F88C231A62D1F8B020134B5062B0 +:20762000D1F8B0209362124BD1F8B020D362D1F84824D1F8B4301A60D1F8A823D1F8B430F4 +:207640005A60D1F8AC23D1F8B4309A60D1F8B423D1F8B430DA60D1F8B023D1F8B4301A61E6 +:20766000D1F8AC100870704714010020EF680200B56902002DE9F04104460125ADF1200D26 +:20768000607926688DF8080020798DF80B50002E8DF80A0034D0234890F8008030460DF0D6 +:2076A0000AFF68B338F001004FF0000736D130460DF11A010BF054FFBDF81A004FF6FE71D0 +:2076C000814208BFC827A07930B92FB9BDF81A1020688DF809501AE08DF81650BDF81A004E +:2076E0008DF818706679ADF80C0021688DF817600DF10E000FF004F903A809F057F90DE07F +:2077000000208DF809000EF019FA4FF6FD7101906846ADF8001002F0D3F90746384608B0C2 +:20772000BDE8F081E5040120F8B50746012F14BF01200320254C012104F1090260728520DE +:207740000EF0F2FF41F288300DF0E6F9224E204D717831F001000AD128784FF4807107F0E5 +:20776000E1F928784FF4807106F0C8FE7178022904D14FF400500121F8F710F9012F04D005 +:2077800041F288300DF068FDF8BD022603202670012705F15D01607004F1140067710FF0DA +:2077A000AFF885F84A600BF0E9FB0A4C002704212078677007F0B6F92078042106F09EFE16 +:2077C000384684F82F70F6F7D1FCF8BDC40301205001012068060120E40401202DE9FE4F4C +:2077E000294E00900CAF0191301D097A3F8800689A4690460F2903D1019A4FF6FC71118096 +:2078000048F21F01B9421CBF4FF0000B012504D14FF0000B022500F801BB814689F8008006 +:2078200071785C46401C0AEBC1010FF069F871780835EDB2491CC9B2884505D1641C89F801 +:20784000004086F801B017E0641C71700A2CEADB0A24884589F800400EDD1F2F01D10DF0A2 +:207860000BFD48F21F00B84206D1084800784FF4804122460FF020F8009801993A462B4668 +:2078800006F00AFCBDE8FE8F28040120CB030120BCB5054669680C462078401F4AD0801EF0 +:2078A0002CD0801E42D0401F02D0801E3AD0BCBD481C01A90BF002FF093401283DD15020DC +:2078C00000238DF800002F7A8DF80230A7F109008DF8010068460AF069FC071C2DD0BDF897 +:2078E0000400788020783A7D87F83800386921460EF054F93846F2F7ABFCBCBD6D890C208A +:207900000DF024FB071C18D006203870611C08227D80381D0EF042F908480078394608F001 +:2079200061FFBCBD28460DF05FF8BCBD28460CF053FEBCBD2846FCF755FDBCBDCB030120E4 +:20794000B0B5002405462022ADF1200D21462C72684604F043FA0B22684629460EF01EF903 +:20796000E87A0A228DF80B00287B8DF80D4005F10E018DF80C000DF10E000EF00FF9AF7E9F +:2079800006220DF11A00214604F028FA780824BF01208DF81A00B80824BF01208DF81B00A3 +:2079A000F80824BF01208DF81C00380924BF01208DF81D00F80924BF01208DF81E0037F06C +:2079C0007F001CBF01208DF81F00288B074FADF8180038688DF80D40D0F8F4128DF80C40B1 +:2079E00068468847204608B0B0BDC04614010020B0B50546294C297D012905D0152903D069 +:207A0000252918BF35291FD1287E00091CD22268D432106890F8820080B168781B280DD112 +:207A20006068816A012088472068D0F82C134FF480608847002022686870D432D2F85C2252 +:207A4000697828469047B0BD287EC2091ED2012918BF152901D100090ED26F781B2F09D02E +:207A60001FB920683430026802E0206834304268895C04E0232100E031212068343029709C +:207A8000006E0078294608F0ADFEB0BD2068006D016809B168788847B0BDC0461401002012 +:207AA000FEB50EF047FF244CA16962698A4240D0224A1778002F3CD1214A177837F07F07D0 +:207AC00037D1204A1778002F33D161610FF0B2F860691D4E01907068416D20698847019FC4 +:207AE0001A4D0090F90FB1EBD07F16D02868D0F8D40090F8830001280FD00BF047FC706861 +:207B0000826D206939469047832803D02868D0F84C0580470EF026F9FEBD7068826D206981 +:207B200039469047832806D02868D0F84C058047FEBD0FF07FF8FEBDA4060120711B01209A +:207B4000741B01206A1B0120D405012014010020F0B5294C06462078ADF11C0D032848D197 +:207B600000256846182225700823657029460EF0E7FD684629460CF089F820613A2229462C +:207B800004F1300004F02AF904F13C00FF210A2204F024F90CF0BAF93146284609F082F913 +:207BA00004F11801E0600EF0ECFD226AE169B1FBF2F0C0B284F830000428A4BF032084F8E0 +:207BC0003000E070B2F5005F04D1E768B1EB403F00D317B9012020700CE084F83550FF2080 +:207BE00084F833004FF40050E086EEF7E3FC607800E0607007B0F0BDC019002003B42DE967 +:207C0000F04F09AFD7F808A0BC69D7F814903D8ABE894FF6FF709846ADF12C0DBAF1000F2D +:207C2000208009D0B8F1000F06D0B9F1000F03D016B1B5F5005F01DD04202DE019463846F5 +:207C400001AA04F07DF9174F034607F110000068002B18BFD8B21FD102F09CFBCDF818907E +:207C6000ADF81C60ADF81E508346CDF820A006A8009097F83300F98EADF8248001AA1223D2 +:207C8000F8F73CF9C6B216B9BDF8080020803869594605F073F830460BB0BDE8F04F02B0B5 +:207CA0007047C046C0190020F0B5294E05463068D0F8FC11ADF1140D28468847041C3FD10E +:207CC0003068D0F82C1128468847041C38D1687C002835D095F8340090BB3268B832106888 +:207CE000007868BBD2F87C2105F1120109209047071C25D03068D0F8302405F10B01E720A4 +:207D000090473068D0F8302405F10801502090473068D0F8302405F10A01E12090474FF6C0 +:207D2000FF7202203368ADF80420A97A8DF80C00D3F8C04100912B89384601A9A04705E093 +:207D400030686C70D0F844112846884705B0F0BD140100207CB50646284D96F830000328E3 +:207D60003FD196F83A0003283BD12C68D434216806F12800082216310DF024F878BBD4F827 +:207D80005C2306F128014A20904774682B6861782078D3F8302400EB0120ADF800006946A4 +:207DA00050209047A41C2B6861782078D3F8302400EB0120ADF8000069464B209047E41CF7 +:207DC0002B6861782078D3F8302400EB0120ADF800006946532090472C68002003E0EA2035 +:207DE00002E02C68E820D434216A48702A253570D4F86C12304688477CBDC04614010020C3 +:207E000098B5284B284A5C78022C3FD11F78002F3CD1D36E440806D302F14C0421609C4243 +:207E200004BF0023D366040906D302F1500421609C4204BF0023D366440906D302F1540407 +:207E400021609C4204BF0023D366840906D302F1580421609C4204BF0023D366840806D30C +:207E600002F1640421609C4204BF0023D366C40806D302F1680421609C4204BF0023D366A7 +:207E8000440B24BF4FF47A74146600E0D36EC00B06D302F15C000160984204BF0020D0669D +:207EA00098BDC046E4040120E40201202DE9F8430446207D1D46904689463830C0B20DF040 +:207EC00045F808AF061C40D00120307021461C2206F11C000DF062FEB01C49460A220DF022 +:207EE0005DFEA6F80C802878307495F90200B0746878002370743879F362F074B8687061C3 +:207F0000387830766089F081387B7076207D40B106F13800F0622169227D06F138000DF0B4 +:207F20003DFE0B48727F816A407812F0030F09D021B930460DF010F9BDE8F8833046884777 +:207F4000BDE8F883314608F04DFCBDE8F883C046E0060120B0B58478C01C0546083010F854 +:207F6000011B0278ADF1200D284606F06BFE01228DF8180006AB214665200AF049FA1E48D3 +:207F8000007830F0010034D128460EF089FC071C2FD0387901282CD10EF012FB8DF80000C9 +:207FA0008DF807005FFA90F18DF8011000248DF802408DF8034080228DF804208DF80540FD +:207FC0008DF806408DF808108DF809400DF10A0029460EF095FC397800F8011B39881522A8 +:207FE0006B46091200F8011BFF21047045200AF00FFA08B0B0BDC046E5040120F8B5284E4D +:20800000346810346568287EFF2840D0D4F8C47097F88310022927D0AB7E7BB102280DD135 +:20802000D4F8F404804771682C6949683A7909780546083112FB01F1084612E0D4F8F404DB +:2080400080476D69E76AD4F8C43022682D1A93F82C10388977682D1A32F81140D7F8B400F5 +:2080600080472D1B2D1A10E0D4F8F40480476969D4F8C460E76A2568081A96F82C203989D1 +:20808000401A35F81210A0EB0115002D01D50020F8BD4FF6FF70A842C8BFA8B2F8BDC04684 +:2080A0001401002070B5284C2068D0F8D4104D7B4069002141772068C16891F83000401CAE +:2080C00081F8300020680C30016891F83010042931D06068C16B202088472368D3F8D41096 +:2080E00091F84F600F2E0CD058694A7B807F824207DD4873D3F81415884723683546D3F8B3 +:20810000D4101A69D86832F8154090F830200126550006FA05F24E7B4FF47075624305FA59 +:2081200006F18C08944238BF221CA1EB4201D3F8F024904770BDD0F8580180472068D0F8BF +:208140006C01804770BDC04614010020D0B50446607D164601220BF055FE071C44D0002EA5 +:2081600042D1E07D97F8351081423DD197F839103B7A0A18934211DD207EFF2811D1FF20B2 +:20818000884087F8360087F8370097F83500401887F83500002687F8386007E0207EFF28F3 +:2081A00018D087F83700207E87F836000EF046FD04460EF0E1F997F83A600C4B4FF47A71BD +:2081C0006043B0FBF1F03880012118787E8006F03FFFD0BDB87E97F82A10FA8B33460AF050 +:2081E00051FC38460BF052FAD0BDC046800A01202DE9FF4101464C682078801F1AD0801E1F +:2082000002D0C01F33D040E065784E89022D08BFA41C0E200CF09AFE071C36D00720387066 +:208220007E80022D3D711CD1781D214608220DF0B5FC16E0A07A657AB1F80A80E67A05EB30 +:20824000002510200CF082FE071C1ED005203870611C0822A7F80280381DBD810DF09EFC7D +:20826000BE730B480078394608F0BCFA0DE04889ADF8000060788DF80200A71C019704F1C3 +:208280000A0602966846FAF765FA0090BDE8FF81CB0301202DE9F047254EDFF898900025B0 +:2082A00001244FF0020A4FF01108E8B20DF014FF071C38D0B87A012835D197F909001130E6 +:2082C00004FA00F0C14346F8041C31680843306097F9090004FA00F0C0B20DF053FA07F19F +:2082E000100000210BF028FE0146812909D1B86918B100210BF020FE0146812908BF87F806 +:208300000AA081290FD0A9F1040097F9091090F8412208FA01F1114380F84112002100F5CF +:208320008E700EF025FB6D1C032DBED3BDE8F0870C1004406CF200202648B0B5006880889A +:20834000ADF1200D0EF07FFA071C41D0224C04F126000078012806D1787900F0EF007871ED +:2083600040F00800787100258DF80C507888ADF8180003A807F05AFE04AB38880193ADF877 +:2083800000000EF01DF9ADF80800787900EA5001890928BF01258DF80A508DF80B0060780A +:2083A00030B10DF0B1FF18B9684601F095FE02E0684602F057FA20B9787900F0FB007871BB +:2083C00006E004AC20460CF047FA204607F078F908B0B0BDD4030120E40401202DE9F84F13 +:2083E00004460AAF207DD4F810A03D689946934688463030C0B20CF0A9FD061C3ED01A2058 +:208400003070A0887080E0885946B080B01D0CF073FFE078F07398F800003075207B7075C2 +:208420002878B0756878F07595F902003076387A7076F868F061387986F82000608BB08544 +:2084400060897082A6F81090207DB084387C86F82E00B08C002804BF0020B06208D006F1AA +:208460003000B062B28C514606F130000DF096FBD8F804000078314608F0B4F9BDE8F88F9C +:2084800025482649EE381831C0F8CC1024491E39C0F8D01090F8CB1041F0010180F8CB10B8 +:2084A00090F8CB20012161F3410280F8CB2090F8CB2061F3820280F8CB2090F8CB2022F0FA +:2084C000080280F8CB2090F8CB2061F3041280F8CB2090F8CB30002262F3451380F8CB302A +:2084E00090F8CB2061F3861280F8CB2090F8CB2061F3C712052180F8DA1080F8DB100449E2 +:20850000C0F8DC100349C0F8E01080F8CB20704704180120001A012046010120B8180120D8 +:208520001A0601202DE9F84F0AAF3C7BBD683E79994690468A468346002C0EBF02200420C4 +:2085400000EB46008DF8010068460CF085FD031C37D0A3F802B083F81A90A3F804A03878B1 +:20856000D876987F01280BD10EF02AF89988884206D0B8F1000F06BF00209877C3F82480A5 +:208580001969052001F8010BBCB1701C01F8010B66B13046891E2A7801F8022F35F8022BD7 +:2085A000401E4FEA22224A70F5D1891C0EF008F801F8010B0EF004F806120E701846F1F7E2 +:2085C00047FEBDE8F88F7047B0B58478ADF1280DC01C01A90DF0FCF98DF8060068BB1820E1 +:2085E00001F0EEFC071C2ED00097BDF804100620002218230AF00AF9B0B90DF107003946B2 +:2086000010220DF0CBFABDF80400164D830003EBC003E9580DF117000DF0B4FA5B195968E0 +:208620000DF11B000DF0AEFA38460021182203F0D5FB384609F01EFA05E00DF10700FF2147 +:20864000182203F0CBFB6720214619220DF1060309F0DEFE0DF106000021192203F0BEFB16 +:208660000AB0B0BDE0E80020DFF898C0F8B50B1C04464FF000050FD0DCF898702E466FB10B +:20868000F868007B00F00F00022803D03F68002FF6D103E03E4601E0DCF898606EB302B17E +:2086A0001660F168087B012500F00F00022824D1012B14D0098840F60300884205D0401C4F +:2086C00088421CBF3069016901D130694169408B9CF842321922091813FB021103E0316910 +:2086E000888DC9680918706B0CF08EF820600DF043FF2168B1FBF0F000E0002020602846F4 +:20870000F8BDC04668F200202DE9F84F0E46074630684FEA9009224848452CBF002503258D +:208720000EF008F900901F48D0F8BC1000F1B80AB94214BF00240124A10081F004015AF87C +:208740000180834627B107F1B8000DF0F5FDC8B9B8F1000F04D008F1B8000DF0EDFD88B972 +:208760003168A00000EBC40050448160317A01740DF002FFB9FBF0F107F1B8000DF0E0FB61 +:20878000832507E09BF8DC0040F002008BF8DC00CBF8D87000980EF04DFA2846BDE8F88FC8 +:2087A00040420F0068F20020D0B504461120ADF1180D01F005FC071C3FD03B200021112218 +:2087C0003B460DF0EDFC80BB387884422DD1112001F0F6FB061C28D03A200021112233462F +:2087E0000DF0DEFCC8B93A2011213A460DF09CFF13490120087013484468B4F1004F84BF4A +:20880000002444601122394668460DF0C7F9822018216A4605940DF087FF30460021112202 +:2088200003F0DCFA304609F025F938460021112203F0D4FA384609F01DF906B0D0BDC04679 +:20884000B5010120100A012030B50C4605463C220021ADF13C0D684603F0C0FA0A226846E9 +:2088600029460DF09BF96889ADF80A00287B8DF80C00687BE9898DF80D000DF10E000BF036 +:208880006CFE287C8DF81600687C8DF81700A87C8DF83700E87C8DF83800E87FADF828007A +:2088A00001F08EFB099070B1296AEA7F0DF076F94CB19DF828000999A04720B1099809F06E +:2088C000D9F81A200BE007480068D0F88812684688470446099808B109F0CCF820460FB086 +:2088E00030BDC04614010020F0B520480127F84201D008F065F9204D204F214EBD4206D298 +:2089000003CD0478A4003459401CA047F6E71D48002800D08047164D164FBD4202D210CD1E +:20892000A047FAE7F0BD03251BE0416808300A1C2A400BD11A1C2A40AB4305D0046804304F +:208940000C600431043BF9D1131C05D0047801300C700131013BF9D1021C2A4001D0A843C4 +:2089600004300368002BE0D17047C046FFFFFFFF0000000000000000A08D0200088E0200FC +:20898000408D020075F402102DE9F041204D6868416EADF1280D02A888476868C06B80474C +:2089A0001C4CA060217B21F00F0141F002012173029000260596668001208DF80C000DF0E2 +:2089C000B9FF1849091D0968896980460220087069680F6D31468DE803000F480F4B006840 +:2089E00002AA2146B847064640460EF023F9002E06D40B4991F90000AC60401C087004E0CF +:208A0000032041F2883105F041FE0AB0BDE8F081D405012058000120B4060120F5B8010047 +:208A2000B60A0120140100202DE9F0470F4606460EF0ACF8EFF311898246202080F3118800 +:208A4000D6F80880474533D01D481E4B0068002F05D49C690125BD4004EBC70401E01C18FC +:208A60000025307D01281AD130460EF08BF8306C0EF0D0F818B1F1685868884358601869D1 +:208A8000864204D0204631460EF0BCF804E020685C6131460DF05AFE586828435860B760BC +:208AA000F5603464002F44BF002058610120188189F3118850460EF061F84046BDE8F08760 +:208AC00090720200CCFF002070B5064600210C22ADF1180D684603F081F9308801211F4CC4 +:208AE0001F4DADF8000009208DF80400307A8DF80510012810D1212063788DF802006BB99E +:208B00000DF0CAFD50B9716805F11C0008220DF045F83088288001E08DF802106846FAF7C2 +:208B200049F89DF8140050B90398406C072101707168401C0DF0E4FE684608F09BFE607837 +:208B400050B90DF0A9FD38B905F11C000021082203F044F90020288006B070BDE404012037 +:208B6000B40801207CB506462448006814460D4607236A4605EB46310DF008FE9DF8000041 +:208B80009DF80010A58183109DF802209DF801009DF8045001F0030140EA012026749DF8D2 +:208BA0000310E080891141EA82019DF80320237240EA03309206120D42EAA502E2819DF8CE +:208BC00005509DF80420A18041EA003102F00302920142EAA50262729DF806509DF8052034 +:208BE0002160962DA57202F0030206BF42F00402101C42F00100E0727CBDC046CC19002031 +:208C00002DE9F04105462C686E680F460DF092FE94F8311019B91D490978012904D00EF0F4 +:208C200009F80020BDE8F081012184F831104FF0000884F832800DF0FDFF07B9144F94F801 +:208C40003000012806D1786820B9B868002808BF454618D0387884F83000F868206278688B +:208C6000E060B868A5602061B068010A04D00949814288BF011C00D80749616104F134008B +:208C800041460BF085F92846BDE8F081AC0B0120448602000100000180A9030030B505464E +:208CA0002989ADF1240D0DF08BFC884222D06868ADF8081005AA03900021AB2007F0D4FC71 +:208CC00005A807A9002203F00BF81A4827300078012808D19DF81C0028B900208DF81000A5 +:208CE00002A8FFF7F1FE01208DF8100002A8FFF7EBFE1DE000248DF804408DF80540686822 +:208D000000900DF0CDFD18B1017909B1052906DB0DF056FC298888420AD1009403E040791B +:208D2000000938BF01248DF806406846FEF7A2FC09B030BDE4040120B0B5244C2068B8300E +:208D400001680F781E4917B90F783FB909E00F7837F07F0702D11B490F7817B1D0F894046A +:208D600080470DF0E7FD6168174D09692A780978914207D116490978C90803D20DF05AFF02 +:208D80000120B0BD0DF056FF0AF000FB0DF0F4F9012811D12D7808F0C9F918B960680069A8 +:208DA000057009E06068006905702068D0F8D40090F942000CF0BEFF0CF0D4FFB0BDC046C5 +:208DC000741B01206A1B0120A406012014010020701B0120B0B5234C2068B83001680F785D +:208DE0001E4917B90F783FB909E00F7837F07F0702D11D490F7817B1D0F8940480470DF0F4 +:208E000099FD6168194D09692A780978914206D113490978C90802D20DF00CFF19E00DF0CE +:208E200009FF0AF0B3FA0DF0A7F9012811D12D7808F07CF918B960680069057009E06068A1 +:208E4000006905702068D0F8D40090F942000CF071FF0CF087FF0120B0BDC046741B012013 +:208E6000701B0120140100206A1B0120A406012070B5254C216840310868006828B9D1F88E +:208E80000C0580472068006C006840681B4D007800F0200028710DF04DFD194906460878F8 +:208EA000832826D12879D8B1216840310868006890F8780010B9D1F80C05804730460DF037 +:208EC000B9FE1048008842F20341401A0DD0401E18BFE9200AD101200BF08EF91B2005E070 +:208EE0008520087030460DF0A5FE002001F098FA70BD30460DF09EFE70BDC04604180020F1 +:208F0000741B01207A00012014010020002A4AD05FEA000C8B071CD1830722D1102A08D327 +:208F200070B4103A78C978C0103AFBD270BC103238D0042A2CD3082A05D30C2A24BF08C99C +:208F400008C008C908C008C908C092072AD0920F22E00B780370491C401C521E22D08B0736 +:208F6000F7D1C30714D18307D8D0121F12D308C903801B0C4380001D121FF8D20AE008C921 +:208F800003701B0A43701B0A83701B0AC370001D121FF4D2121D05D00B780370491C401C47 +:208FA000521EF9D160467047F0B516460C460546ADF1240D08F0FEFC002840D128460021F3 +:208FC00007F0DCFF314603F009FD071C37D0B879400834D320460CF08CFD012819D0B97976 +:208FE000C8082CD30DF0ECFAA0420BD1002000902146019005AA02900F2303902846FFF7EF +:2090000091FAB97988081AD2B87900F0FB00B87115E004208DF81000ADF8124004A802F08F +:2090200017FF01280BD1002000900127214605AA01900F23029028460397FFF773FA09B0AE +:20904000F0BD704770B52348234C1830E06000F5877020611C48ADF1280DA06008F094FAFB +:2090600068460CF013FE4FF4E130069003208DF81C0000258DF815508DF816508DF81D509B +:2090800001208DF800008DF801001048039010488DF8175069460490284608F02BFE202162 +:2090A0002A4660600DF09FFB0BF0B4FD0646202204F11401606825800DF09AFB30460CF034 +:2090C00034FF0AB070BDC04689240200C9BE01009950020004FC00208C07012003B410466D +:2090E000F0B51E1C05AFADF11C0D14BF0028042038D081B201AA384602F022FF1C4C0746CB +:2091000004F114000068002F2BD110B1804700B90B2720692FBB01F03DF9054600200090AB +:2091200094F83300E18E01AA0323F6F7E7FEC0B278B901A831460222F2F75EFC071C0CD134 +:20914000BDF8101049B19DF8140007F025FB677803E00A280CBF0A2701272069294603F07D +:209160000DFEF8B207B0BDE8F04002B07047C046C01900202DE9F84F8146002100200A4691 +:20918000C9F800006846FFF76FFADFF87C8000264FF0FF354FF0190A34460746E0B20CF0DE +:2091A0009BFFC8B1837ABBB1017A0126022917D04246516892F8423240694A8B09698918AF +:2091C00013FB0A110BF020FB83460DF0D5F9BBFBF0F0854288BF051C641C032CDED300E0B7 +:2091E00000251FB1012E04D0012F05D0012E04D005E00098854200D9009DC9F800503E4323 +:20920000F0B2BDE8F88FC04668F200202DE9F0410DF090FB204C80462078002650B11F48D9 +:209220000322083801688260480803D30AF096FB0AF0DAFE164D2868071C0ED008F03AFDD8 +:20924000B86A796A884207D8284639460BF018FC3046012687F832002868217801290ED0E5 +:2092600050B90F480DF060F948B90A4A4FF0FF30012105F0B7FC02E080680CF0FBFC404668 +:209280000DF0D8FC16B1B86808F0EDFFBDE8F0810C0B012080A90300AD0B0120108002400D +:2092A0007419012030B50546A96948780C7804EB002420480088ADF1240D4A1CA04222D16D +:2092C00050781028A8BF10208DF808009DF80820491C891C0DF109000CF060FC8120112171 +:2092E00002AA0DF021FA9DF80800134920B90846017901F0EF0103E00846017941F0100142 +:209300000171002000E084208DF819008DF81A408DF81B400DF119000090287CA91C48F290 +:2093200014020323019005F1110008F093F909B030BDC046E00301204C1A01209EB5477E86 +:2093400037F07F0743D0017D012903D0032918BF04293CD11E4C2168D1F89810098901F0AE +:20936000020201F00801114331D041684878C0F3810002288DF8080006D003280ED1491D00 +:2093800068460DF0BDFA09E08A79487940EA0220ADF800000879C97841EA00216068426F46 +:2093A000684690471E2809D040B16068006D8047FF280CD16068416D012007E06068006D65 +:2093C0008047FE2803D16068416D002088479EBD14010020F0B51F4D1D4C002124220823CB +:2093E000ADF1240D6846E5620DF0FCFB002604F15007384631466A468DF818600DF0EEFBBB +:209400003C2208236763314604F16C0738460DF0B1FB4FF44060C4F88C000521E5673A46D6 +:20942000334604F1840004F1A805016074300A49C4F8880028460DF099FB084825630849D4 +:209440000160084981600849C16009B0F0BDC046D4DB00200C020120019D01000C010020D1 +:20946000D4800200446C0200547A02008B4208BF824204D90B1C021C002100207047002B77 +:2094800008BF002A0BD10B1C021C00210020002B08BF002A1CBFC943C04307F064BFF0B5B4 +:2094A0001C4615460B46024600200021B4FA84F6202E04BFB5FA85F62036B3FA83F7202FE6 +:2094C00004BFB2FA82F72037F61BB6F1200727BF05FA07F400257F42B4403EBF25FA07F79A +:2094E0003C43B540A34208BFAA4201D3521BA341404149416D0845EAC4756408761EF1D58D +:20950000F0BD704730B501250446ADF11C0D8DF81450F9F7F5FD206918B11E480168204679 +:209520008847207D50BB684600210C2202F056FCA0688DF802500088E368ADF80000187D87 +:209540008DF8055009308DF804006846F9F732FB9DF8140090B90398456C0E232B70A16891 +:209560004968681C0DF0CCF9E2681169127D05F109000CF013FB684608F07CF9E06808B17C +:2095800008F078FA20460DF0EDF89DF8140007B0207530BDBC080120F0B585780221C41CAD +:2095A000ADF11C0D20468DF808100DF039F8A41CADF8000020460DF033F8A11C11F8012BCE +:2095C00006460DF10B008DF80A200CF0E7FA164F3046391D9DF80A400E68102CA8BF10244D +:2095E000102206F8010B001206F8010B202106F8014B304602F0F2FB0DF10B01304622464B +:209600000CF0CCFA142213236946384604F044FD01228DF81B000DF11B032946652008F0EF +:20962000F7FE07B0F0BDC046280401202DE9FC47224D81466D1E95F83340E8784FF0FF08BE +:20964000002642F2010A0AE0204678210AF0AEF8E878641C94FBF0F14143641AE4B2B04242 +:2096600028DD95F83200761CA042B6B2F0D0E86861036A4604230DF089F8009800F0FF00FA +:209680007828E5D005F13007FF2818BF7E2803D120467C210AF08AF8A00085F8334000EBD6 +:2096A000C400C019818BE986808B48448245CBDD95F833804046BDE8FC87C046C11900209E +:2096C00070B50546A96948780C7804EB00241F480088ADF1200DA0422BD181200021112224 +:2096E00002AB0CF05DFD20BB687C194E9DF808108DF81900301D00680023221200F8013BB6 +:20970000091D00F8014BCEB200F8012B9DF8081000F8011B9DF808200DF109010CF03EFA81 +:20972000A91C0DF1190048F21102334604F0B4FC0AE048F211000090287C0190687CA91C40 +:20974000842223460AF07CFC08B070BDE0030120280401202DE9FE4F0CAF3E793C888DF834 +:2097600000001D469246894606F10A00C0B20190401C00F025FC5FEA00082ED008F1010025 +:20978000834651468BF80090401C0CF0FBF900F8015B291200F8011B00F8014B231200F8F6 +:2097A000013B067026B1B968401C32460CF0F6F90B4C0C49C4F804B0E51C48F23802387BFC +:2097C000019B2870684604F067FC404608F052F905F10A0666600020E070BDE8FE8FC04613 +:2097E000280401203C0701202DE9F0411D4F7868C068012101701C496FF0010008701B48CA +:209800000068C06B80471A4C054621786068A2688B002E1AB6FBF3F05843361A880015499A +:2098200002FB03F8B1FBF0F0904203D23868D0F84C058047AD1B1048656008EB0501F9F7AF +:20984000A3F83868D0F8E40480470DF073F80DF0F1F90BF093FA7968C96800200870BDE830 +:20986000F081C04614010020B00A0120D8050120D8000020FFF6C2FFE99701002DE9F041ED +:2098800006467468B5680DF055F88046A06A58B928688169090907D2006B400A04D24046E2 +:2098A0000DF0C8F9BDE8F08104F5B2700DF03CF800274046A7620DF0BDF9A97D3846FF2953 +:2098C00002D0E97DFF2900D118B12046294601F04DFE0DF02FF82A68916B21F020019163A5 +:2098E0002A68116B21F4807111630DF0A3F904F2A9100BF091FD616A206A2769626A401A04 +:209900002062216A3B4630469847BDE8F08170B50C4621780646ADF1180D01F00C0531F00C +:209920007F0018BF45F0800501F0030045F00205012808BF45F01005880928BF45F02005DB +:209940000C226846002102F049FA8DF80250ADF8006060788DF80300012568468DF80550EB +:20996000F9F728F99DF81400C0B903984576A17880F83A10E17880F83B10E188C18721890C +:20998000A0F84010617D80F84910217E80F84C10E17D80F84B10684607F06CFF06B070BD99 +:2099A000FEB50C4601A90AF0C3FD00283CD11F4D2869002838D0871F00210320BDF8042019 +:2099C00037F8063F9A4204D0401E01F10101F5D1FEBD7980182000F0F3FA061C24D00096D6 +:2099E000798806200022182308F010FF3046214610220CF0D3F80024746134617988062051 +:209A00001822334609F044FD30461822214602F0E5F9304608F02EF879881435880000EB21 +:209A2000C1002C5040194460FEBDC046CCE8002038B5224C083CE068D0F8880080470CF05D +:209A400079FF0546E068C06D8047E068416AA068D0F8D40090F942008847E068816CA06899 +:209A6000D0F8AC0000788847E068016EA068D0F8D400C08C8847E068A368416ED3F8D40014 +:209A8000408D8847E068A368816ED3F8D4004430884728460DF0CEF8E068A568016BD5F847 +:209AA000D40090F843008847A268D2F8D410D2F8302452202931904738BDC046140100208F +:209AC00098B5044602208DF8010068460BF0C4FA071C3BD038690422411C02700020087084 +:209AE000227A012A04BF40F020000870607A012803D1087840F040000870A07A01281CBFB7 +:209B00000123BB7604D10878012340F080000870607A012804D1606808B17B7760683862A2 +:209B2000E07A012808BFFB82208807F043FF18B1F88A40F00400F882BB770BF0FFFF78627F +:209B4000208878803846F0F783FB98BD102098BD2DE9FE4F0190214800F19806376899463E +:209B600092460D460024804600E03F6897B3BD42FBD1D7F800B0019839460CF025FC18B3B5 +:209B8000384600224FF0805308F0F6FC06F10800B9F1000F00900ED0384600224FF0807331 +:209BA00008F0EAFC286998F8DC30C8F8D80043F0010088F8DC00304639460AF061FF00988B +:209BC00039460AF037FF641CBAF1000F18BF5FEA0B07CED12046BDE8FE8FC04668F20020B3 +:209BE000F8B515460C460CF0A5FE84461E491D488326A4B1641E2CD0641E22D0A41E19D03B +:209C0000641E15D110300768002F0CBF0021F96829604768002F0CBF0021F9680FE007689F +:209C2000002F08BF802617D0D1F8A800018E12E0032611E0D1F8B8002860D1F8BC1069602E +:209C40000AE0843800780021022808BF0121297002E006480178298060460CF0EBFF3046C5 +:209C6000F8BDC04610F3002068F20020A8F40020F0B50546ADF1340D0CF05CFE1F4C0746F3 +:209C800008342068D0F8080100686968836B102209A89847061C28D12068D0F8080100686A +:209CA000016968468847AE682B8B019609A80693EA680090A98B02926E8B0392731A0793B1 +:209CC0006B698DF82110701A0493801805900D2325688DF82030D5F80811D5F804010968F1 +:209CE00000688A6969469047064638460CF0A2FF002E14BFE42000200DB0F0BD0C01002060 +:209D00002DE9F041E9F79CF91E4C1D49207808704FF4804048601C4800684FF0FF310CF0C5 +:209D200075FF0026DFF86480606B4FF0FF310CF06DFF606C35460A21001F50F8042F1768A1 +:209D40001FB9491E05F10105F7D10A2DECDA0AF061FF616CAF0079580D680E600CF0E5F8A0 +:209D600058F8072030462946904705460AF052FF616C79580A6815430D600CF0D6F8D3E7C1 +:209D8000380A0120D4DB0020EC0101201883020010B50446207AADF1300D04283CD10CF02D +:209DA000B3FA002838D1A07838B960680BA906AA01F096FF9DF82C0070B3002168460C2229 +:209DC0008DF8141002F00AF89DF8140020BB2088A378ADF80000002B0CBF612041208DF89D +:209DE00002000B238DF8043001208DF805006846F8F7E0FE9DF8140070B90398406C10210A +:209E00000170A1784170217A81706168C01C0CF077FD684607F02EFD0CB010BD1CB51E4BD3 +:209E200003F1D4042078012202F0010120F001000143217093F8D40062F3820083F8D4003C +:209E400093F8D40062F3041083F8D40093F8D40062F3861083F8D40010480068406903F1F5 +:209E6000D401027042F20200ADF8000009880DF10200018003F1D601097801A80170B3F89D +:209E8000BE00022806D107480068054C426A2068694690471CBDC0465800012018010020B0 +:209EA000B4060120D80501202DE9F84304460420904689468DF8010068460BF0CDF81C4D08 +:209EC000071C2ED03869072100F8011B217D00F8011BA18A091200F8011BA17D01700126C2 +:209EE0007E7704F10B033B62BE770BF027FE7862B9F1030FBE7604D0B9F1010F18BF4020E9 +:209F000001D14FF48860F8822C46A01D0088B8F1010F788004BF002038763846F0F798F9DB +:209F200000E010204FF6FE71E980BDE8F883C046E4020120002030B50146ADF1240D0CF0B0 +:209F400011FE184C2061002001460CF00BFE002124220823606168460CF044FE04F1280540 +:209F6000012128466A460CF039FEA5610CF0F6FDA16904F11C0203F08BFF20700A49087084 +:209F80000A490B4808600AF045FE0B4904460948C1600A490161FFF755F820460BF0C5FF49 +:209FA00009B030BD70F70020651B01206C0A012035E4010004FC0020A963020099C7010093 +:209FC000F8B5041D14F003001CBF241A241D0AF021FE1D4A054697685560112C28BFD76870 +:209FE000386800231E46010821D226B9844209D93B4601261EE0196809188C42196019D837 +:20A000001F460846DFB11169001B032807D83868091A1161386840F00040386005E0385113 +:20A0200044F000403860091B11613F1D07E080F0004000263F1838680028D4D1002728460C +:20A040000BF073FF3846F8BD501A00202DE9F04114460D4680461E1CADF1280D08BF022026 +:20A0600034D03768EFB90C20FFF7AAFF071C14D068460021242208230CF098FD0023069732 +:20A0800041466A4605931348ADF810300CF08AFD38607D60BC60386808B9082016E0376087 +:20A0A0000CE00AF0B7FD044638680CF095FC10B138680CF09FFD20460BF037FF38684146D8 +:20A0C0000CF06CFD38680CF065FD00200AB0BDE8F081C0462D66020030B50188ADF11C0D5D +:20A0E000ADF802100024ADF800404168C27A019132F07F010AD1D10905D3807A012814BF04 +:20A100000320201C0BE00125284609E0D10905D3807A012814BF0720042000E0052001255A +:20A120008DF80800214603AAAB2006F09DFA03A805A9224601F0D4FD09480078012807D1D9 +:20A140009DF8140020B98DF80940684602F002FA8DF80950684602F0FDF907B030BDC046F5 +:20A160000B0501202DE9F04105464FF6FE708846A84238D01D4C2769B8F1000F33D06FB9CD +:20A180001020FFF71DFF206168B320784FF400614FF47A720CF08DFB20690EE094F834605B +:20A1A000B91C404608220AF0C7FFD8B9F86888B91020FFF705FFF860A8B1002194F83470FC +:20A1C000C1600822877241460580801C0BF0E6FCBDE8F0810746811C082240460AF0ACFF61 +:20A1E0000028E3D0BE72BDE8F081C04668060120F0B50546ADF1340D0CF09CFB1E4C074690 +:20A2000008342068D0F8080100686968836B102209A89847061C26D12068D0F808010068E6 +:20A22000016968468847AE6801962B8B0693698B0791EA68029209A803926E6900900D23EC +:20A240000496297F8DF820302A698DF8211026680592D6F80811D6F80401096800684A6933 +:20A2600069469047064638460CF0E4FC002E14BFE42000200DB0F0BD0C01002070B51E4C67 +:20A280002068D0F85C0280471C490B781C490D7818B91C2000F0C4F870BD0021194E22687F +:20A2A000A6F8AA10D2F8D42092F8314086F8AC4092F8242086F8AD2096F8AE2042F020025A +:20A2C00086F8AE2096F8AE206843800022F01F0242F0020286F8AE2096F8AE20C6F8B80024 +:20A2E00061F3871286F8AE2086F8B03086F8AF1086F8B11070BDC0461401002006180020A5 +:20A30000D8000020580001202DE9FF47067A022E1CBF804608240DD100880F128DF80A10CD +:20A320000DF108088DF8080004248DF80B7000128DF80900DFF85490154F00254FF0010A2C +:20A3400030460BF01BFD0AFA05F1014216D0022E19BF09F1080101EBC50107F1080101EBA7 +:20A36000850122466846FEF7D1FD4046694622460AF0E2FE012808BF281C03D06D1C052D45 +:20A38000DEDBFF200090BDE8FF87C04604180120001A01202DE9F043054620480068ADF1AA +:20A3A000140D05EB00090CF0D9FB071C16D00CF015FB06460CF0EAFB80466868012807D1DA +:20A3C00000246C60EF604046AE600CF0D7FB21E0E868874204D140460CF0D0FB01201AE085 +:20A3E00038460BF0CEFD02970024C7F818D0484669463246039409F030F9E8680CF0EEFA13 +:20A40000B04203DAE8683146FEF70EFB40460CF0B5FBBC61204605B0BDE8F0837C88020020 +:20A42000B0B5074600251D481D4C05701E4805704FB92068006C0068C08AC00803D20CF0E0 +:20A44000FDFB184908602268AC32D168087808B1496C61B91068007808B905F0C7FFFDF732 +:20A460001FFB2068D0F87012384688470BE0384688476068C068007828B92068D0F8582456 +:20A480002846014690472068006C006810B1007D352801D00BF066FCB0BDC046641B0120F8 +:20A4A00014010020940B0120741B01202DE9FF411D4D1F4F1D4C33264FF001082B79002BF0 +:20A4C0002AD0032B28DAE9696269F1B982B13868022B4FEA8011A1EB800107D12888904755 +:20A4E000012805D1A1692888884701E0288890478DF800806888ADF80C00684605F096FD90 +:20A5000050B101A805F0DCF806E0A86910F1020F02D0E869401EE861761E05F12405CDD1A4 +:20A520000090BDE8FF81C0462C100020E4020120BC80020070B5C821ADF1180D8DF8141045 +:20A540001C4986780978C01C39BB0DF115016A4601F0C6FB05469DF8150010B316499DF825 +:20A560001330A800002400EBC50038310C504018446033F07F0003D00DF1130009F0CEFB13 +:20A5800068462146142201F029FC0420294614226B4608F07DFF204601E0F7F74DFC8DF869 +:20A5A000140065203146012205AB07F031FF06B070BDC046E5040120CCE80020F8B51C4EB3 +:20A5C000D6F8600101680120884701282ED0D6F82401184DC4683C21012200232846A04750 +:20A5E000002808BF002022D02F8817F0010704D14FF00120C5F80404288830688047012F5B +:20A6000004BF4FF08070C5F804040D4A0A480B4F936901681069D161A0EB9000C91A07FB70 +:20A6200001F3190C814228BF081C10610120F8BD8000001000A00C403020094040420F0046 +:20A64000D808012003B40021F0B505AF3846ADF11C0D01AA01F074FC1B4C054604F11400BC +:20A6600000682DB910B1804700B90B2520690DB1E8B224E0FFF78EFE002506460095E18E3F +:20A6800094F8330001AA0323F5F738FCC7B28FB99DF81400BDF8101006F07EF8009594F83E +:20A6A0003300E18E01AA0323F5F728FC0A2814BF012767782069314602F060FB384607B089 +:20A6C000BDE8F04002B07047C019002030B5204D45EA0401ADF11C0DC1F315040021019176 +:20A6E00002910391049104A90091806802AA03AB01A9F9F795FB0146019802884FF6FF70D6 +:20A7000090421DD101B3039808B1049840B9D9B102982B2105AA0BF019F8FF2806D113E0C0 +:20A720002B2105AA0BF012F8FF280DD0C4F38850059C80056FF39F54044344F0004403E069 +:20A74000A805204042EA0004204607B030BDC046FFFF3F00F8B5204C0D46280C34D2680859 +:20A7600038BF002037D3607805F050FD071C0BD001208DF800006946522007F01BFB0020AC +:20A780000BF004FD0020A07002200AF0DFFB011C05D0332008704F70E07806F023F885F03D +:20A7A0000100F8BD317820790C2905D00D2908D13046F4F79DF804E0B2787378114608F04A +:20A7C00061F930460AF0C8FC207804F013FC061CE8D185F40040F8BDC40A01208CB5014690 +:20A7E0008A695078137803EB00231B480088984214BF0027194F1A48001D006857B948F2AA +:20A8000003000090087C0190487C8022891C09F017FC8CBD002200F8012B00F8013B1A128A +:20A8200000F8012B3A6802F0F00302F00F021A4300F8012B3A68120A02F0F00302F00F0243 +:20A840001A430523027001F1110048F20302891C03F022FC8CBDC046E00301204C1A01202F +:20A8600028040120B0B50446A07AADF1180D48BB606805A96A4601F033FA0146E07A4009CE +:20A8800020D29DF8140001281CD19DF81000022818D1FF208A009DF81270134D8DF810009A +:20A8A00002EBC102781C531900F00F008DF8120000275F6001970097AF5004206B46142233 +:20A8C00008F0E6FD2046F9F7E5FF071C09D1A07A38B9E07A400904D20BF072FE6168FFF7B8 +:20A8E00041FC384606B0B0BD04E9002030B50446ADF1440D601D0AA908F0E0FE012802D04E +:20A900002079022834D060880DF13A0102F0CAFE01282DD10DF12A0001900DF1420105AAC5 +:20A920000DF13A0001F0DCF99DF8420000B39DF82610019A07A804F071FC01208DF80E0065 +:20A940008DF80D008DF80C00002504956188ADF8001004238DF802300DF13A016846029120 +:20A96000F2F7DEFB0DF12A001022294601F036FA11B030BDF8B51F4CA0F5C060D4F81011C3 +:20A98000C4F82C010029B8BF49420028B8BF404281422BDA4FF08057D7F8A401B4F814115F +:20A9A000154D40684FF47F4208230646009128463021B047D7F8A401B4F8181140684FF497 +:20A9C000F80212230646009104212846B047D7F8A401B4F8281140684FF440620A23064682 +:20A9E000009120212846B047012000E0002084F83001F8BD5018002000A00C407CB5204C8C +:20AA00003C3CE06B00680146042088471B4D02281AD0032818D001282FD1206840680321C5 +:20AA20004FF040521C230646009128460021B0472068406801214FF4007209230446009195 +:20AA400028460021A0477CBD2068406803214FF040521C230646009128460021B0472068F8 +:20AA6000406801214FF4007209230446009128460021A047022008F0F9FE7CBD00A00C40A4 +:20AA8000E0010010B0B505461E484268184C9269217817783FBB174B8A00B3FBF2F2AA421A +:20AAA00004D20068D0F84C0580472178164B042011FB00F001B2181D00686768C06B05FB14 +:20AAC00001748047211AA1F54871090806D30A4A011B891A090828BF00F548740748214654 +:20AAE000F7F752FFB0BD064901200870B0BDC046D8000020FFF6C2FF00093D00E9970100DA +:20AB0000721B012014010020D40501207FB51F4C4FF47000E0600025A560656065701C489E +:20AB200005700AF077F80646206940B10BF004FC10B120690BF0F8FE20690BF016FD6846F6 +:20AB40000BF015FE8DF800500E48019501216A4606F0D0FE0C4D206120B92868D0F84C0534 +:20AB6000804720690BF0DEFE30460BF0DEF92868D0F814150F208847E06800F07BFE0090A6 +:20AB80007FBDC0460D3B020014010020D8000020721B01201B49B0B509684BF2F52250432D +:20ABA0000027040A01F44021B1F5802F03D116480068800C00D38FB14FF08055D5F8EC01AE +:20ABC0000068804706F016FFD5F8E011C96888472111C01000B2484304EBE0340B48007870 +:20ABE00030B90B48006820F07F402418640802E0084880F8407108480460210C4160012735 +:20AC00008760B0BDB44F00508C1300509019002010200940501800207C600C402DE9F04165 +:20AC200085780221C41CADF1280D20468DF818100BF0F6FCA41C2646083414F8018BADF89C +:20AC4000100020460BF0ECFCA41C074614F8010B03288DF8220005D020460BF0E1FCADF8EC +:20AC60001A0004E00DF11A0021460BF049FE00970DF11A00019014F8080F002704A9324666 +:20AC8000434602902120039700F0E4FA8DF824002946012209AB652007F0BAFB0AB0BDE871 +:20ACA000F0812DE9F04185780221C41CADF1280D20468DF818100BF0B3FCA41C26460834E4 +:20ACC00014F8018BADF8100020460BF0A9FCA41C074614F8010B03288DF8220005D02046EF +:20ACE0000BF09EFCADF81A0004E00DF11A0021460BF006FE00970DF11A00019014F8080F3B +:20AD0000002704A93246434602902220039700F0A1FA8DF824002946012209AB652007F0FA +:20AD200077FB0AB0BDE8F081F8B506AF3E7894468E46002E3AD0002735461B1F4FF6FF7142 +:20AD40003C4633F8042F91422BD017B13F88B84201DD824205DC6D1E1F4604F10104F0D18E +:20AD6000F8BDA6421A4608DD361B121F32F8044FA14202D0761EF9D1121D934203D2D11A1B +:20AD8000C91C8F1000E0012732F8041C12F8026C118012F8015C96707F1ED570A2F10402EC +:20ADA000F2D1188083F802C083F803E0F8BDFEE71F4830B5ADF1140D94386A4614300546ED +:20ADC00004F06EFB002404218DF8044020468DF8064009F065FC332807DA09F04DFC20B922 +:20ADE00001208DF804008DF80600684603F0E4FC4520294606F0DEFF9DF8060010B99DF8FD +:20AE0000040000B101248DF8134008499DF8132008784978104001408DF8131041200DF18E +:20AE2000130106F0C7FF05B030BDC046FC090120E4010120F8B50D46074609F0EBFE0646F3 +:20AE40000BF0D6FB68BBB5F5877FDCBF0021081C05DDA5F5877007F587714FF48775134C6E +:20AE600061612A463946E08004F59370FEF74EF801211048A580A7680170781CA06009F0DE +:20AE8000C9FE0B4C07462A462169606865800BF0B4FCB0F1FF3F04BF0020608038460BF0DA +:20AEA00044F830460BF041F8F8BDC04604FC00208C070120B60B012003B41046F0B51E1C4F +:20AEC00005AFADF11C0D14BF002804202FD081B201AA384601F034F8174C074604F11400A7 +:20AEE00000681FBB10B1804700B90B272069EFB9FFF750FA05460020009094F83300E18E03 +:20AF000001AA0323F4F7FAFFC0B250B10A2806D101A831460122F0F76FFD071C02D001274D +:20AF200000E00D272069294601F028FFF8B207B0BDE8F04002B07047C01900202DE9F0410E +:20AF40001D4C804620684FF0FF310BF0A3F9D8F808601A4DD8F80470144A308C736979687A +:20AF600028601160B3B9124A318B89180A78521ED3B20A7073B9404604F0D6FC404609F0CB +:20AF8000F9F878680BF020FC0022318B094B286843F8212081B24046F9F7B5F8002038706D +:20AFA00020680BF0DDFCBDE8F081C0460C1B0120401B0120B01A0120141B0120101B0120CE +:20AFC000F8B505460BF0B6FC1D4C064604F1DC010878A84304F1B80508702868002808BF31 +:20AFE000002706D02868B8300BF0A6F9002700B10127686838B1B8300BF09EF9002538436F +:20B0000018BF01252F4694F8DC00A0B9012F12D0D4F8D80078B1816A89080CD3456A30469E +:20B020000BF008FED4F8D80002210022A8470020C4F8D800F8BD30460BF0FCFDF8BDC046A9 +:20B0400068F20020F8B507460024081C08BF0124002302B90123002F33D01AB197F8446016 +:20B06000002E2ED080B190F844606EB17D6B016CAD08A5EB910539460BF04FFA2D1AB5F148 +:20B08000704F04DB002D02DC012C01D019E00124BAB1D068007B00F00F00022811D1516B06 +:20B0A000386C8D081146A5EB900538460BF035FA01262D1AB5F1704F02DB002DD8BF002699 +:20B0C00033431C40E0B2F8BD70B50646B5681D48296874688A6B10408863002020703046A1 +:20B0E000FEF7CCFB304605F015FC2968C86A20F01000C862296814480A6B10400863304678 +:20B1000007F058FA6868FBF7ADFE04F16C000BF00FFC04F188000BF025FCA07818B904F19B +:20B12000C4000BF01BFC607818B904F58A700BF015FC04F5B2700BF0EDFB04F158000AF04C +:20B140001BF870BD0DF8FFFFFEFCFFFF70B53A2000211122ADF1280D01AB0BF021F81B4DE6 +:20B1600010B9A81C006806908220182101AA0BF0DBFA154E002407A80090214600220C2370 +:20B18000072007F043FB08A93046082209F0D4FF48B9641C052CEEDB08A8FF21082200F0D1 +:20B1A0001DFE641EA4B2069821460C2207AB0790072008F06DF9002101A81822298000F0FE +:20B1C0000DFE0AB070BDC046AD010120120A0120FEB51D4D1D4C0E462E721EBB1C48401C58 +:20B1E0000078022819D108F0D9FC08F037F9071C13D000211C2200F0F1FDE08F04F14001E6 +:20B200003880B81C0BF07CFBB4F848007881AA23BB7406223A7401217974287810B90320D6 +:20B220000AF040FD5035296849B18DF80060608FADF80200E78FADF804706846884702201E +:20B24000002108F0BBFBFEBDC403012050010120E40401202DE9F84F99461E4B82460AAFDB +:20B2600098467C6858683E88237A8B46032B04D0012B0CBF0E250C2500E0152511460BF04F +:20B280003FFB00F8019B00F8016B311200F8011B217A00F8011B217A032907D001290AD1D3 +:20B2A000217800F8011B2188091203E021460BF027FB397A0170102088F8030052465946A8 +:20B2C0002B46404602F0E8FE002188F80310BDE8F88FC0462804012070B506467568B46802 +:20B2E00095F8F900012816D094F83800A16A09F027FA94F83900E16A09F022FA94F83A00E5 +:20B30000216B09F01DFA95F8FB00FF2823D0616B09F016FA70BD94F83800E16A09F010FADB +:20B3200094F83900A16A09F00BFA94F83A00216B09F006FA95F8FB00FF280CD0616B09F0A4 +:20B34000FFF995F8FB0004490AF0ECFB95F8FB0031460BF001F870BD05DA0100B0B507468D +:20B360001A4C1B4D207818B12868D0F84C0580472868D4300168194BCA8C991C0A800FB376 +:20B38000032F1BD0052F06D0012F04D0022F02D0D0F87804804702202070FDF771F82868D5 +:20B3A000D0F8D4104FF6FF72CA84D0F8D400094FC18C094C3980C08C2080B0BDFDF760F8E9 +:20B3C000032000E001202070B0BDC046B4180120140100201A06012046010120A4060120B0 +:20B3E000F8B51F4C2068D0F8E800002505602068D83001680F68A7B181687A68096891429C +:20B400000FDD07F0F7FF2168D8310A6812685368984202DD5060086802680869026020687C +:20B42000D83041680F684FB101690E681EB172687B689A4202DD0F602068D83001690F68DD +:20B440003FB1806879680068884202DD06F092FDF8BD0AF0B7FC2068D0F8E8000560F8BDE9 +:20B460001401002038B51D4C054694F83200000906D21B49086B18B14878082103F0E8FDF6 +:20B480006B78E12B07D0F12B05D01A2B03D0192B18BF002007D1E07918B907F031F86B789D +:20B4A000E07980F00100E0710E48417802290AD1007840B9EB2B18BFE92B04D130200021A4 +:20B4C000F4F76CFA6B7801200090B4F84810E08F0022F0F797FCF2F7BBFC38BD5001012071 +:20B4E000E0060120E40401202DE9F0411D4CC668E76C00210125ADF1200DA04605FA01F221 +:20B500003A4209D0735C0BF04FF8984204DAE06C9043E064D8F84C70491C1B29EEDB47B9AC +:20B52000114F0020396884F84A00C1B1C420884715E0684600211C2200F050FC8DF80450E8 +:20B5400000268DF80760E06C009094F852708DF80570684600F0E4FD062084F84A0008B092 +:20B56000BDE8F081500101200C0A012070B50C4606460BF0DFF92268916B21F020019163CA +:20B580000BF058FB184D207D2946491E02F0C0F8A07D294602F0BCF830468178012906D03A +:20B5A000C4304FF0FF310AF075FE206803E0206881690909FCD20D4D85420CBF10211421AC +:20B5C000207D09F0BDF8A07D0021FF2802D0E27DFF2A00D131B121688D4214BF152111211B +:20B5E00009F0AEF870BDC046026000200010004010B5044600210C22ADF1180D68468DF853 +:20B60000141000F0EBFB6078012809D0042807D002281CBFB3208DF8140004D10A2000E003 +:20B6200002208DF804009DF8140000BB2078ADF8000021238DF8023001228DF80520684648 +:20B64000F7F7B8FA9DF8140088B90398406C08210170617841706178022903D16168801CB8 +:20B660000BF04EF9684606F005F99DF8140006B010BD2DE9F04F1D4690466A68834600266B +:20B680008A464FF0010909AF3046ADF1140D09FA00F10A421CBF761CF6B2401C1B28F6DBDF +:20B6A000A6B13046FEF78CFC041C10D0002001466A6809FA01F3134204D04A19127A431C99 +:20B6C0002254D8B2491C1B29F2DB00E00024CDF800800196029438780390A9786A685346AF +:20B6E0005846FEF737F814B1204606F0C3F905B0BDE8F08FC8B509F073FF01461C480368D4 +:20B700000429C3F34062C3F3C056C3F300674FF0FF302BD1C3F30331491F1BD0C91E24D039 +:20B72000491E1DD0891F21D1180E0ED2980E07D3580E03D2980E03D30F20C8BD1120C8BD74 +:20B74000002F14BF10200B20C8BD002A14BF0E200D20C8BD56B1002A14BF26202520C8BD16 +:20B76000002A14BF0A200920C8BD0C20C8BDC04694120050F8B51C4D0446286818B904F092 +:20B780002FFB286818B116490978A14201DC002423E0144A0C2114FB01246668A7684FF084 +:20B7A000FF310AF077FD114831780268012908BF28680CD039682868531E0B4207D10C4906 +:20B7C0007B6809689A4202D81940994201D0002401E0012131700BF0C3F82046F8BDC046BB +:20B7E0005C830200A0850200001B0120041B0120081B0120BCB51C4DE86848B307460124EA +:20B8000003206C720AF04EFAB87907F0BBFCF87A00903988BA783B8907F10C00F8F7EEFC70 +:20B8200070B913480078000904D210480078D0B9082001E04FF400402146F4F7AFF8BCBDD6 +:20B84000E8688DF8044008F0E9F8214601AB06E00020012168720DF105038DF805000A4601 +:20B86000032006F0E7FABCBD68060120C5030120521A01201D4998B54A68926917783FBB67 +:20B88000154B1A78154F5B68042412FB04F424B2920000FB0434B7FBF2F2824203D2086828 +:20B8A000D0F84C05804712480068C06B8047211AA1F54871090806D3094A011B891A09085D +:20B8C00028BF00F5487407482146F7F75DF898BD05490120087098BDD8000020FFF6C2FF98 +:20B8E00000093D00B51E0200721B012014010020D8050120F8B51D4D6868C06801210170AA +:20B900006868806900781E461746022803D02868D0F84C058047002402204FF0807304EA62 +:20B92000070104EA0602384033400143134308BF00290CD14FF0805304EA0700334008BF76 +:20B94000002804D12868D0F84C05804709E008496F6891F90000401E0870B86904700AF07A +:20B9600025FA6868C0680470F8BDC04614010020B60A0120BFB509F0C9FF002835D0417B4D +:20B98000062932D101680A7A44898DF808200988ADF8001005F060F9200B26D3BDF8001091 +:20B9A000002008F06BFC00BB114CB4F84810684608F055FD0020014608F060FC071C11D035 +:20B9C0004FF6FF75386801888D420ED0B4F84810FBF762F81A2808D03846002108F04EFC8D +:20B9E000071CEFD108460AF0C7FF0090BFBDC046500101202DE9F8438146EFF311882020FF +:20BA000080F311880124164E164DF461164F6C60F86A016A14208847D9F81000810C14BF97 +:20BA2000000C0420A861386802682321002090470E480068C6F8804200280CBF211C0321F6 +:20BA40000B4807680FB141F00401286820F4E02040EA01402860346088F31188BDE8F883CF +:20BA6000000024430020094084010010CC7202002C730200B0B51B4C054620784FF48061AD +:20BA800003F050F8092084F84A0018484178022904BF0021C1700AF051F80146686909F0CF +:20BAA0006DFF01281CD1102009F050FA071C17D002203870A86A8178407800EB01207880F6 +:20BAC000A86AC0787870A9694A2006F073F9A87910B90549052008702078394604F082FEF6 +:20BAE000B0BDC04650010120C4030120E404012003B42DE9F04307AFBD681E469046ADF1BD +:20BB00001C0D002D14BF002E042027D01946384601AA00F015FA144C04F11001096800282D +:20BB200018BF071C19D10846FEF734FC81460020009094F83300E18E01AA0323F4F7DEF976 +:20BB4000C7B237B94146324601A82B4603F024FA07462069494601F011F9F8B207B0BDE8EC +:20BB6000F04302B07047C046C0190020F8B507460AF0E0FE044677B3B87A60B397F90920E6 +:20BB800009F03AFB012303FA02F1CDB240B1144E30681132934098433060DA4346F8042CED +:20BBA0000020B8610346BB723B7207F110063B60024686E80C000B4A7B6002F5107003789C +:20BBC0001943017092F8420210B1401E82F84202284607F089FA20460BF02CF8F8BDC046C5 +:20BBE0000C10044068F20020F8B51D4C0546E07904211E4605F01EFF002818BF01202DD1F8 +:20BC000006F098F836F0010018BF022E25D10820FEF7D6F907462069002F08BF10201DD0A5 +:20BC200010B9276104E0084601680029FBD10760E079402105F0FEFE002180B23960C0F570 +:20BC40001670BD8080B2B0F5167FF88005D1E07940214FF416720AF02FFE0020F8BDC046E0 +:20BC6000C40301202DE9FC470646884691469A461A487168184DB2684B681468118C0360C9 +:20BC80003046296003F050FE07464046241807BB03218DF80010200C8DF80340220A8DF835 +:20BCA000010029888DF8022030460AF0C6FA6846042104F073FB002818BF4FF0FF3704D17D +:20BCC0004846514608F06CFA0746298830460AF0BDFA3846BDE8FC87101B01200C1B012082 +:20BCE000F0B50F46014616464FF6FF70002FADF1240DADF818002ED000292CD0002401AA46 +:20BD00003C7003A80091801A83B201A908221D4606A804F0EDFF002804BF012038700ED015 +:20BD20000DF11A002146082200F058F80DF11A002B4601A90822009006A804F0D9FFBDF8FE +:20BD40001800C82805DA26B1304601A9142209F025FFBDF8180009B0F0BD30B504462088A8 +:20BD60000125ADF1340D3A22ADF8080060688DF80A5007A9049011200AF0C1FB20B107A863 +:20BD80000021112200F02AF80DF11D038DF815509DF81C00039321898DF80B000AF010FCAE +:20BDA000884207D08DF81650ADF8001060680190684602E000208DF81600069002A8F1F776 +:20BDC000AFF904460021112207A800F007F820460DB030BD002213460A46194671B510F01F +:20BDE000030F0BD0002A82BF00F8011BB2F1010210F0030FF6D1002A08BF71BD11F0FF0138 +:20BE000041EA0121042A18D341EA0141082A0FD30E46102A08D30C460D46B2F10F0312F076 +:20BE20000F0272C0103BFCD812F0080F18BF42C012F0040F18BF40F8041B12F0020F18BF81 +:20BE400020F8021B12F0010F18BF017071BD70472DE9F04705460021281D0AF03BFB05F14A +:20BE600004094FF6FE7100206A88A981914227D014490F884E68044688461FE0A10001EBAD +:20BE8000C401725C12F00F0F16D071186B884A889A4211D101F1040A504609F00CFB01283E +:20BEA00007D1484651460AF015FBB8F80070D8F80460AC8101203C46641CA4B2A742DDDCDF +:20BEC000BDE8F087DC0A01202DE9F041174608F0A1FE1A4C80462FB904F108052A68002636 +:20BEE0000C351BE02188E368002604F114053046B1F5877F09DA2A5C5A542E544A1C401C61 +:20BF000091B2C0B287422180F2D8A268B84205D042B161884FF487709047A26812B1B8B23B +:20BF20003146904726806068294620220AF060FC404609F0FAFFBDE8F081C0468C070120F6 +:20BF400010B5B1F5805FA8BF052031DA0378402BA8BF09202CDA4388B3F5806FA8BF072094 +:20BF600026DA8388B3F5806FA8BF082020DA114B5B1E1B78032B08BF032019D0D181017862 +:20BF800001F03F04418800236FF39F2141EA0431848893816FF39F2444EA013414608188DA +:20BFA00091804488D4800178117296249472184610BDC046C1190020FEB5044602208DF8C5 +:20BFC000080019480D460188ADF800406846FAF763FD1A281DD01549FF2600224FF6FF77A9 +:20BFE000091D081F30F8043F9F4203D1FF2E08BF161C01E09C4211D0521C052AF2DB052A75 +:20C000000DD1FF2E07D10748B0F84810684608F026FA0020FEBDB0000C5240184580012001 +:20C02000FEBDC04650010120980101202C010020BFB519490EC901A880E80E00174D002472 +:20C04000274601A8009021463A460C23072006F0DDFB02A92846082209F06EF838B9641C1C +:20C06000052CEEDB019808B90FB912E004240C49887970B9012088710A4D01990C2201F2DF +:20C08000E240019001AB68602146072007F000FA6F800090BFBDC04654870200AD0101204D +:20C0A000C4030120100A012010B500211822ADF1300D6846FFF792FE822018216A460AF0A9 +:20C0C00033FB0021112206A8FFF788FE3A20112106AA0AF029FB3B20112106AA0AF024FB04 +:20C0E0000C49002008700C480078012818BF02280DD10A4A4FF48170102114460AF00EFB69 +:20C1000028B94FF48170102122460AF00DFB0CB010BDC046B5010120E504012088800200F5 +:20C1200030B5002405462822ADF12C0D2146AC716846FFF753FE0B220DF1190005F10B01CB +:20C1400009F02CFD124829680160684609F01AFD28798DF8110068798DF81200E8798DF81E +:20C160001500287A8DF81600687A8DF81700A87A8DF81800074800688DF81440D0F87C1448 +:20C180008DF813406846884720460BB030BDC0464C1B01201401002038B51A491A4C097842 +:20C1A000E06802292DD120B107F038FCE0680028FAD109F021F9E079082805D0012812BF6C +:20C1C000A072012000211AD00825E5710F4C012084F84A000A2009F065FD2078022102F02A +:20C1E000A1FC4FF480400021F3F7D8FB0024522069468DF8004005F0DDFD28462146EBF731 +:20C20000BBF938BDE504012068060120500101202DE9F84F0AAF7C6897F808803E688146EC +:20C22000184692468B46234658B3074600259C4207D10BEB050148463246FFF713FD00BB98 +:20C240000023B8F1010F05EB0A0103EB060005D00278097800208A4208D006E009780078A0 +:20C2600001EA000200208A4200D00120002818BF6FF0060006D17F1E03F1010305F1010528 +:20C28000D5D10020BDE8F88F2DE9F04104460AF051FB194D29688046D1F8EC00D1F8E010AA +:20C2A00050F8240008602968D1F8E410134C08601048083C00682678C06B80476768B10081 +:20C2C000B0FBF1F177B92868D0F8E0000068884208D2B1FBF0F10427484316FB07F109B256 +:20C2E0004143616007F09EFF40460AF0A3FCBDE8F081C046D805012014010020E0000020F7 +:20C3000038B51B4D28684069012444772868A830C16A497B0F2927D0006804706868016C10 +:20C32000202088472B681349D868816103F1D400D96802681B69527B91F8305033F81230A3 +:20C340006D00AC404FF470755C43034605FA02F08008A04238BF041CD3F81C2401F11000F5 +:20C360004B346100904738BDD0F8BC00804738BD14010020A5800100B0B51B4903680F68CB +:20C380001C8800210A466FB17D7B052D07D13D682D88521CD2B2AC4204BF491CC9B27F68A2 +:20C3A000002FF1D1032905DA2D2A03DA0F493431098800E00121018105214173418941F4A2 +:20C3C0000061418118884FF6FF77874206D0054801881846FAF760FB1A2802D101200AF090 +:20C3E000CBFAB0BD98010120E40A012050010120F8B50B4601464C69601E024218BF221CFF +:20C40000651E184610EA05071CBF2044C01B834213D8CF6801F10C0C7FB1531E796803EABB +:20C42000070613EA070518BF561B84198C4206D9BC46DCF80070002FF0D10020F8BD091A26 +:20C44000BA198D1B3EB98E4204BF3868674608D03968674602E07E6025B1396810180160A4 +:20C46000456038601046F8BD2DE9FF4105460420984616460C468DF80100684608F0ECFD0E +:20C48000071C28D0B8F1000F08D00120BC800023B8773878FB7640F0800038703969032202 +:20C4A0000A70481C0670447021128170284605F081FA48B9284601A908F0A9FA20B10120CC +:20C4C000787701AE3E6201E0002078777D803846EDF7BEFE00E001200090BDE8FF8180B528 +:20C4E00003460F1C30D038783A88B97803F8010B10127A8803F8010B101203F8011B397908 +:20C5000003F8010B7A7903F8011BB97903F8012BFA7903F8011B397A03F8012B7A7A03F85E +:20C52000011BB97A03F8012BFA7A03F8011BF96803F8012B184609F025FB1878398A001D8B +:20C540001870387C091201E0FE20FF2103F8010B197080BD30B5044600210C22ADF11C0D53 +:20C560006846FFF73BFC20880121ADF800000C208DF80400607A8DF8051000280CBF081C31 +:20C5800021208DF802006846F6F714FB9DF8141099B90398456C06232B706168681C0AF0C7 +:20C5A000AFF9A078687260880012A872207AE872684605F05FF99DF81410207A002814BF90 +:20C5C000081C002007B030BD1B4930B5044600201222ADF1140D8DF812006846FCF796FC03 +:20C5E000E41C14F8015B20460AF01AF8ADF80000A07810288DF8020003DA9DF8020018B9A0 +:20C6000009E00F208DF802009DF802200DF10300E11C09F0C3FA28466946012200F03AFBAB +:20C620008DF812004B2101220DF11203652005F0EFFE05B030BDC0469486020010B51A4C6B +:20C64000608FADF1180D8DF8000000128DF80100164800788DF80200B4F848008DF8030032 +:20C6600000128DF80400E08F082204F15D018DF8050000128DF806000DF1070009F08EFA86 +:20C6800008220DF10F0004F1400109F087FA94F83C00502118226B468DF81700652005F079 +:20C6A000B7FE06B010BDC04650010120C40301201B4910B504463422ADF1380D6846FCF795 +:20C6C00025FCA088ADF80C006088ADF80A00207D8DF81C0020690A90207F8DF80500208D92 +:20C6E000ADF81000207E8DF80600607E8DF80400608DADF82E0094F82C0000228DF83000A6 +:20C70000FF208DF834000DA98DF835004FF0FF308DF836006846E9F715FD00200EB010BD5D +:20C72000DC82020070B505F09FFF04F0FDF91648007830F0010001D109F0F6FD134C60681B +:20C7400028B1606805F096F9002020806060104D2C687CB120686668006A05F08BF9206855 +:20C7600005F088F9606905F085F9204605F082F9341CEFD10020286008F03EFE0548007880 +:20C78000F4F79CF970BDC046E5040120DC0A0120E40A01205001012070B5054608F06CFC84 +:20C7A000184CC0F5877081B26088A94229DDAEB23118B1F5877F0EDD0319C0F587711A1D1D +:20C7C0008EB2C0F5877399B2104606F0D7FFAD1BAEB20020608000193146001D06F0CEFF65 +:20C7E0006088094D4FF48772801980B290FBF2F15143401A02216080A86929810AF012FAD4 +:20C8000070BDFEE738FE002070F7002003B41046F0B51E1C05AFADF1140D14BF00280420AB +:20C8200027D0114638466A46FFF78AFB134D044605F114000068DCB910B1804700B90B24E0 +:20C840002869ACB9FDF7A6FD0746314600226846EFF7D2F8041C07D1BDF80C1021B19DF8D7 +:20C86000100003F099FF6C782869394600F086FAE0B205B0BDE8F04002B07047C01900203B +:20C8800038B51B4C184A0023164994F83A01136020B3012817D0022807D003281ED151F8DF +:20C8A000350CFEF767F8062016E051F8355C2846F1F706FA40F2FE50A84202D2001DA84252 +:20C8C000F1D8042008E051F8350CFEF763F9074800780028E7D00220C4F83C0109F0C0FB33 +:20C8E00038BDC0463D400C403C500C403E86020050180020F8B50D4606460AF01BF80446AB +:20C90000E8B209F0E9FB8025071C23D0B87A08B3386886421ED11349486891F824100229AD +:20C9200006D03846FFF722F900F028FF812511E097F909100A4E4FF4A06202EB012202F498 +:20C940007F4246EA0201002206F0E8FB05463846FFF70CF920460AF06DF92846F8BDC04635 +:20C960000100080468F2002070B5054609F0E2FF194C06464FF0FF30E06205F1B80009F0DE +:20C98000D3FFB4F9B400B4F9B61088420FD194F8240002280BD094F8DC0040B130460AF0C9 +:20C9A00049F90720FEF70CFB09F0C4FF0646B4F9B400B4F9B61088421CBF012085F8FC00F7 +:20C9C00006D104F5CE7009F0AFFF082006F08CFB30460AF02FF970BD68F20020F8B51B4CAA +:20C9E00001F0400C002264264FF6FE75A4F1080737F8081F884208D185420AD0BB790CF028 +:20CA0000400103F04003994203D0761E02F10102EED11646642E12D1854210D12146642242 +:20CA20000026087928B1521E01F1080106F10106F7D1642E08DA0888614608F021F9642EF6 +:20CA4000B8BF04EBC60000DB0020F8BDCC0600207CB502281E4614460D4612D0042818BFB7 +:20CA6000012829D108461A46012101F0D8F818B33CB1284602F048FBC828BCBF012020708B +:20CA80001ADB28460021FFF7A9FF78B1817911F0180F0BD04FF6FE710091094E028843885D +:20CAA00031881046002203F061FB07E0284631460822F5F79FFC08B100207CBD01207CBD0D +:20CAC0008A0101202DE9F84308AF3F7899461446064607F047FADFF858800D46082816DB0B +:20CAE0004FF6FE70002107F03DFA082808BF02201CD0D7B14100424601EBC000FF231554A7 +:20CB000011184E800B4F8B71387808720AE04100424601EBC0008118C879A042D8BF0320C9 +:20CB200004DD17B1CC71A1F804900020BDE8F8837A01002087010120F0B5024691694878B7 +:20CB4000097801EB002117480768ADF1140D09F037FD154C88421CBF0020802314D13B465E +:20CB6000002002E01B68401CC0B2002BFAD1401E0023C0B247B1A4467D682E780EB10CF849 +:20CB8000016B3F68002FF7D1009101900294107C0390517C48F20500921C01F015FA05B045 +:20CBA000F0BDC046C00A01205405012008B513460A4618BB3A2A14BF3B2A012114D0174922 +:20CBC00040F20310904205D120311846102208F0E5FF08BD10480078682A0AD0B2F5817F03 +:20CBE00018BF622A16D100211046102209F0D8FA08BD0128E9D002280CD1E6E7052808BF08 +:20CC0000052002D0062805D1062000930022102305F0FCFD08BDC046E5040120688002005E +:20CC200070B5ADF1280DADF8002001248DF802400D468DF8035006460196002002904FF646 +:20CC4000FF718DF80E409142049014D0CB1E934211D0891E91420ED002208DF81400ADF8EF +:20CC6000162005A8FFF7F4F8012818BF201C07D106A8029020468DF80D006846F0F750FAC4 +:20CC800004462946304607F0A5F805F053F820460AB070BD2DE9F0470D46298890460446D3 +:20CCA00007F026FA002818BFB82028D109F02AF8002818BFB22022D11820FDF781F9DFF831 +:20CCC0004490D9F80060071C08BF102017D04FF0000AC7F800A0B81D294612223C7108F089 +:20CCE0005DFF16B94E4603E0064630680028FBD1B8F1000F376001D005F07CF85046BDE8F6 +:20CD0000F087C04664F2002090B51B4C22687032116891F82B70ADF1140D57BB516E8F7814 +:20CD20003FB3037AC168D2F8182118469047071C1FD02068016F91F82B0040F0040081F8B8 +:20CD40002B002068D0F85C1302A888476068816A01208847012024680090206F2030019020 +:20CD6000D4F8D400C38CD4F87843394602AA0520A04705B090BDC04614010020F8B50446D2 +:20CD80001A480068251809F0E9FE0B46071C2BD009F0FCFE064623BB384609F01FFEA16883 +:20CDA000884203DDA1683846FBF73EFE284609F031FFA0B9284609F031FF8168E160084615 +:20CDC00009F00CFEEFF31187A060202080F311880846394609F0BEFE87F3118801E00120F3 +:20CDE0006060304609F0CAFEF8BDC0467C880200F8B51B4C103C2578064607F00BFF844667 +:20CE00001648037800278BB1001D10F8181F8E4202D05B1EF9D109E08068074630B13878E6 +:20CE2000D12803D057F80C7C002FF8D1604609F07CF8381C10D1022008F088F80146E079D5 +:20CE400031B1D12008704D70304603F0CBFCF8BD102102F0FDF8F8BD4570F8BD501A002024 +:20CE6000D4030120002980B534D00F0E202F1BD0212F08BF022218D0A02F08BF032214D03F +:20CE800087B1102F08BF05220FD0112F08BF06220BD0402F08BF072207D0502F0CBF08229A +:20CEA000092202E0042200E00122C1F39701090241EA02110268B2F1FF3F41F00F0106D045 +:20CEC000914204D050F8042FB2F1FF3FF8D14FF0FF31016080BDF8B520220D46064608F0F3 +:20CEE0005DFE002401277461A87CF46178B1022110FB01F000B2FDF763F87061002808BF34 +:20CF0000271C04D0AA7C6969520008F047FE287E78B1022110FB01F000B2FDF751F8F06145 +:20CF2000002808BF271C05D02A7EE969520008F035FE3FB9706908B104F09CFDF06908B14A +:20CF400004F098FD3846F8BD1FB504681748617A012913D000686169806891F82110024672 +:20CF6000684690476069416990F82120684605F0C0F810B96FF00200606006E00068616993 +:20CF80008268486991F821109047094840210160802404600021C0F8FC12022006F066FCE9 +:20CFA000044809F0DDFC00901FBDC046FC010010044402404C160120B0B50446E16891F846 +:20CFC000380000F00300012810D12069077C77B9496C0A78052A0AD14978012904D00629B1 +:20CFE0001CBF0321017402D102210174206900210170E068216990F848008870E0682169CB +:20D0000090F84200C870E068216900694860256908F094FD014605F1080009F071FC2069E0 +:20D02000F5F7D8FE2075B0BD2DE9F04380460E464FF6F870ADF1140DB04202DCB8F1000FD5 +:20D0400024D0144C332500F1070901272079FF2818D0B8F1000F05D1B14513D02088B04252 +:20D060000ED00FE08DF800706088ADF80C00684602F0DCFF30B101A9404608F07FFC08B19D +:20D08000204604E06D1E04F12404DFD1002005B0BDE8F0832C100020062809DC062814D080 +:20D0A000C8B1801E14D0801E0FD0401E0AD007E00A3807D0801E08D0C01E03D00F3801D081 +:20D0C00000200AE041F2011007E04FF2011004E04FF4817001E040F20250FF2904BF40F031 +:20D0E000C00121F480610AD031B149082CBF40F0100040F0200001E040F03000014640F237 +:20D10000037040EA01407047F8B51A4C6069002510B1804700B90B2520694DBBFDF73AF950 +:20D1200065780026074606E03046F9F73BFE761CF6B205436570E178B142F5DC002084F80A +:20D140003100491E84F832100C2684F8330010FB0641B1F84C10E1867E2106F027FB94F897 +:20D160003200FE2106F022FB20693946FFF706FE2846F8BDC01900202DE9FE43184D052646 +:20D180004FF6FF790A274FF00208164C35F8040F814521D06B888BB15B1E9BB293FBF7F095 +:20D1A0006B8078431B1A17D128888DF808802188ADF800006846F9F76FFC0DE028888DF876 +:20D1C00008802188ADF80000684607F048F92846FF210422FEF702FE761ED7D1BDE8FE8388 +:20D1E0002C0100209801012010B509F0A3FB154991F82420022A1ED091F8241004291AD0B3 +:20D2000009F018FD10480068006B80470F4A002308F014FE0E4C4FF090531B1820684FF012 +:20D220007A044FEA000244EB010400215B1844EB0204241C04E0074990390C6809F0FAFC98 +:20D24000204610BD68F200208C01001000093D00701A012094300440184930B58422ADF101 +:20D26000BC0D02A8FBF752FE15490EC92CA880E80E0002A800902CA8019004208DF88C00A6 +:20D2800002F0CEFA684623A9FBF7BAFC051C10D00C4928A8142209F024F9284628A906F00B +:20D2A00075FB0446284608F03FFF002C08BF002001D04FF0FF302FB030BDC046A87D0200C5 +:20D2C00060870200741A01202DE9FC410020ADF800001420FCF774FE071C28D0154810304D +:20D2E000006808B38046032402254FF6FE76A8B241460622C01908F051FC38F8060B86420E +:20D3000004D0BDF80000401CADF80000641E05F10605ECD138466946022208F03FFC4C2053 +:20D3200014213A4609F000FA384604F0A3FBBDE8FC81C046CCE80020002980B532D00F0EBC +:20D34000202F1BD0212F08BF022218D0A02F08BF032214D087B1102F08BF05220FD0112F4D +:20D3600008BF06220BD0402F08BF072207D0502F0CBF0822092202E0042200E00122C1F34F +:20D380009701090241EA02110268B2F1FF3F41F00F0106D0914204D050F8042FB2F1FF3F47 +:20D3A000F8D1016080BD98B504466FF002001F688DF800003A462046FDF744FE10B1012004 +:20D3C0008DF800009DF9000010F1030F13D1E068007B00F00F0002280DD167B13A68204651 +:20D3E0003946FDF72FFE18B9002A1746F6D102E002208DF800009DF9000010F1030F04D167 +:20D40000E06B10B104208DF80000059807609DF9000098BD002B08BF002A0FD10B1C021C27 +:20D42000002908BF002807BF0020002100204FF00041C4BFC043C94303F095BF10B55C082B +:20D4400094EA610404D55FF0000E40426EEB010113F0004F04D05FF0000E52426EEB030360 +:20D46000FCF704F8241C04D55FF0000E52426EEB0303640004D55FF0000E40426EEB0101DD +:20D4800010BD70472DE9F8430024002B16460F468046254606D5002FC3F1000302D57F422D +:20D4A000761E2D2599463846494604F0A3FD0CA0405CB7FBF9F7002F04F1010408F8010DE5 +:20D4C000F1D1A64205DD3021301B401E08F8011DFBD10DB108F8015D4046BDE8F883C04614 +:20D4E0003031323334353637383961626364656600007047F8B505462C680F4609F01AFA25 +:20D5000016490978012902D194F8221019B109F091FB0020F8BD012684F8226009F08AFBA9 +:20D5200007B90D4F387884F82000786860603878022814BF0021B96884F82360002084F859 +:20D540002400A16084F8250084F826000B20F9F721FF2846F8BDC046D8860200930B0120E0 +:20D5600070B50646356809F0E5F9002195F8212085F82410032A1CBF042A85F8251009F045 +:20D5800059FB0F4800F108010968090824BF4FF0FF31E9610B490160304605F0D5FC95F84A +:20D5A0002000022807D06C68E9692A6895F821303046A04770BD044809F0D2F970BDC046E7 +:20D5C00088470240010000809C16012010B504466089ADF1200D05A900F064F805A807A9CC +:20D5E0006A46FEF77DFB9DF81C0070B19DF81000FD2818BF002808D10D48007828B9607A12 +:20D6000048B96068007806280FD0607A18B960680078072809D0207B18B9606800780528F0 +:20D6200003D1044801682046884708B010BDC0460D050120C80801201CB50C46217F05298C +:20D6400007D104F1080100F02DF8002808BFC82024D004F10800694608F0BAF9BDF8000008 +:20D660004FF6FF71814218D02078012810D1BDF800100B4B880000EBC10003F10801401804 +:20D68000A16902688A4288BFA22007D8491C0160BDF80000A08200201CBDA1201CBDC0462C +:20D6A000DCE80020D0B50746184800880C46012687421ED008F072FF874216D0384607F00F +:20D6C000A6F906460F480078C8B908F0E5FFB0B9AEB90D490888B84211D187B11C312046B6 +:20D6E000082208F05BFA012609E0084609F0AFF805E008F023FA0146204609F001F93046A5 +:20D70000D0BDC046E5040120B40801208A0101202DE9F041174D804605EB880528680C4613 +:20D72000660824F0FF0186F0010606F0010610F0FF0F0AD109F0FEF8210A6970270CAF70BF +:20D74000210EE97009F076FA00E02960002706B1012727B1404604F0010108F005FE09F021 +:20D76000E9F8054941EA88010F6009F063FA0020BDE8F08100100840001A4442194838B585 +:20D7800090F82410022928D0044694F82400012826D094F82400042822D009F0CBF80546BC +:20D7A0006846FBF7E7FC80B1009949B904F5AC7009F0BAF804F1E000042109F0D9F808E0AE +:20D7C00004F5AC7008F0BCFB03E004F5AC7009F0ABF8284609F02EFA38BD192009F0B0F893 +:20D7E00038BDC04668F2002038B58568184C287DFF2807D02868844214BF14211021287D9F +:20D8000006F09EFF687DFF2806D029688C4214BF13210F2106F094FFA87D0021FF2802D035 +:20D82000EA7DFF2A00D191B1FF2806D029688C4214BF1521112106F083FFE87DFF2806D0D4 +:20D8400029688C4214BF1621122106F079FF38BD00100040F8B50446A07C0C28B2BF00269B +:20D86000A069C67AF01D4000FCF7AAFB071C25D0A46925783D700DBB641C381D214609F00E +:20D880003FF8083461782078002500EB012078803D739EB1A41C14F8010B387314F8010BE1 +:20D8A00007F10E01787362782078761EF6B2A41C002E00EB022021F8020BF4D13846F8BDAF +:20D8C0007FB50646B0690578FF2D08BFFE251448144C0570A4F13E000078802101F022F9F3 +:20D8E00002F0E8FE00248DF8084008F00DFD10B1284608F0EFF90C48007810B9284608F053 +:20D90000E9F9307B50B902A80090B11C48F236020123019406F1110003F09CFE00907FBDDE +:20D92000FE0901208E010120E50401202DE9F8438046174808AF174C00783D88401CC6B264 +:20D940006068914608F01EF9B9F1060F214600F8019B13DBB9F1FE0F18BFB9F1FF0F0BD14F +:20D960000670B9F1FF0F18BF062409D1401C2B12082400F8015B02E0052401E006240370FC +:20D98000084638222346414600F086FBBDE8F883E6010120280401202DE9F0410746387AC3 +:20D9A000012804D0384605F0B4FA064600E03E884FF6FE70B04221D0DFF8448000240E25CF +:20D9C00017E0397A012907D114FB05804278012A02D14288964208D0012908D014FB05803F +:20D9E000437823B941888E4201D108F040FF641CE4B2002CE5D0304603F0BCF8BDE8F081C4 +:20DA00002201002070B5064608F09EFC05466C68304607F0D7FDA0B908F08CFF0546D4F86D +:20DA2000C00040B994F8FB00002106F017FA012084F8FC0001E001210174284609F0FAF814 +:20DA400070BD08F077FF064694F8FB00002106F005FA0121D4F8C00084F8FC1008B104212E +:20DA60000174304609F0E6F82846F0F789FE70BDF8B5194C6068C06800780E4628B92068A4 +:20DA8000D0F8582400210120904708F053FF054608F098F904F04EFA07462068D0F8EC1036 +:20DAA00051F82610D0F8E00001602068D0F8E400016006F0B7FB2268D2F8D8000168D2F842 +:20DAC000E024384690472068D0F8D4048047284609F0B0F8F8BDC04614010020194898B551 +:20DAE00001684969FF220A76016814310B68DC7E012C0CD0D1F8C0104A7B91F82C108A42F7 +:20DB00001ED04068406C804707F038F998BD0020D876886AC77A9FB1D1F8C00090F843300A +:20DB20008DF8003090F852308DF8013090F853008DF80320D1F8C0138DF80200684688474D +:20DB400098BDC046140100201949420824BF081C4C3021D2020924BF081C50301CD2420948 +:20DB600024BF081C543017D2820924BF081C583012D2420B24BF081C60300DD2820824BF03 +:20DB8000081C643008D2C20824BF081C683003D2C20B03D308465C3000687047C11300F451 +:20DBA0000050C903084314BF00204FF0FF307047E402012010B5044600210C22ADF1180DBE +:20DBC0006846FEF70BF92088E178ADF8000001294FF002008DF804004FF001008DF805003A +:20DBE00008BF21208DF802006846F4F7E3FF9DF8140090B90398406C0922411C0270A078D0 +:20DC00000870208803F0D6FE10B103980421C182684603F02FFE9DF8140006B010BDF8B5B2 +:20DC20000C46174605464FF6FE76012C03D1032103F0DCFD20BB2846002103F09FF93946CC +:20DC4000FEF7CCFE012C17D110B14179012903D0F80938BF2E1C00E046884FF6FE74B442DB +:20DC600010D03046032103F0C1FD48B9B54209D0AC422E46F5D105E020B14079844201D179 +:20DC80000020F8BD0120F8BD70B505462C6894F8200004280AD0022818BF00261FD11348B1 +:20DCA0004FF0FF3108F0F6FAE66918E00D480068806901460C488847000824BF4FF0FF305D +:20DCC000E061E669002094F8211084F8240003291CBF042984F82500284605F035F930465B +:20DCE00070BDC046FC010010010000809C1601202DE9F04706464FF6FE70708006F1040A4F +:20DD0000B081504607F0D7FB4FF0000801281DD110480788D0F80490C7B14446A50005EB3B +:20DD2000C4054D44287810F00F0F0BD0291D504607F024FE012805D16888B4814FF001088F +:20DD40003C467080641CA4B2A742E7DC4046BDE8F087C046DC0A0120B0B5154DD5F860012B +:20DD60004268002101209047D5F8600101680120884788B10F4C278817F0010704D14FF0F3 +:20DD80000120C4F80404208828688047012F04BF4FF08070C4F804040748084CD5F86C716C +:20DDA0000068183C6061386880472062B0BDC0468000001000A00C4030200940F00801205C +:20DDC000F8B5184D0C3DE97895F8334000273E4624E095F83200761CA042B6B217D0E86806 +:20DDE00061036A46042308F0D1FC009800F0FF00FF2803D07E2818BF7C2808D1A00000EB1D +:20DE0000C4004019B0F84C003F1A07F50057E978641C94FBF1F04843241AE4B2B142D8DCEE +:20DE20003846F8BDCC190020E1291CB528D10189154C491C89B20181E9B112480078F8B1B4 +:20DE4000943CB4F8941088421ADA002000F0F4F9B4F894206421414391FBF2F11A290FDBE2 +:20DE60000A49091F096859B1ADF80200ADF80020684688471CBD00202080012000F0DCF944 +:20DE80001CBDC04612050120E401012030070120F8B5184B1C780F2C25DA1F78E50005EBC3 +:20DEA0000415ED182C77FD0005EB07151F7803F11C06AD196860F80000EB071080191F7833 +:20DEC000C1601978F800CD0000EB071000278019876005EB01101D7880190774E80000EBA5 +:20DEE000051080194261641CE0B21870401EC0B2F8BDC046501A0020F8B5184C1548D4F8E8 +:20DF0000A86008F049FA1449054608680F6800F02000284007F460270DD066B10300C4F882 +:20DF2000B0600022304604F027FB04F1E0004FF4804108F01DFD17EA05000AD094F8411279 +:20DF400041EA504084F84102002104F58E7008F00FFDF8BD20000E000C10044068F200206E +:20DF6000F0B5184C00250526ADF1140D5D3401A80090294600220C23072004F047FC02AFF0 +:20DF800020460822394607F0D7F848B93846002107F045FD18B96D1C052DE8DB00E02E4630 +:20DFA000052E0CDA02A82146082207F0F7FD002031460C2201AB0190072005F069FA05B0EC +:20DFC000F0BDC046500101202DE9F843DFF85C900446904608AF8DF8001009F104003A79EB +:20DFE0003988006848F20605A5420CBF1025002500F8013B00F8011B0E1200F8016B002AB1 +:20E00000027008BF042605D0111DCEB2B968401C07F0C4FD4F462246684641463346FD70CD +:20E0200000F03AF80020F870BDE8F88328040120F8B5844640F6FF741CF8013B002210E047 +:20E04000481B401E10F8015B7F1E01F8015BF9D103E01CF8010B01F8010B521C5B08082AD4 +:20E06000EADA5808F5D21CF8010B1CF8015B05F00F07FF1CC5F30315122F45EA001508D1D1 +:20E080001CF8016B300A24BF1CF8010B60F3DF16BF19AC42D4D1F8BDF0B50E4617460446BB +:20E0A0001D4600210C22ADF11C0D04A8FDF796FE00208DF81900307A0F498DF8180030889E +:20E0C0004A68ADF81000207802F8010C48686B1C401E3A460090881C0190C878074902903E +:20E0E0000F20039004A8EDF78BFD10B92178491C217007B0F0BDC04628040120F40301201F +:20E100001649174A00200968A2F8AA00D1F8D41091F8313082F8AC3091F8241082F8AD1089 +:20E1200092F8AE1021F0200182F8AE1092F8AE1021F01F0141F0010182F8AE1092F8AE1001 +:20E1400060F3871182F8AE1082F8AF00054982F8B100097882F8B0107047C046140100204D +:20E16000580001200618002070B5154E154C706928B12068D0F8541206F11400884708F0C5 +:20E18000D9FBF1690A68002515710968F16108F051FD0D4A0D49107810B90846007870B146 +:20E1A000157008460570F8F71DFF6068C068007828B92068D0F8582428460146904770BD3E +:20E1C000B4180120140100206F1B0120711B0120F8B508F0AFFB164D164C2E782978012940 +:20E1E0000ED001272F7008F025FD6068C068007840B92068D0F8582400213846904701E0DC +:20E2000008F018FDECF7A6FC074608F093FB07B92E7008F00FFD6068C068007828B9206866 +:20E22000D0F858240020014690473846F8BDC046B20A01201401002002461648F8B507783F +:20E24000002137F0010710D1144833230C460579FF2D06D0078A27B1002A06BF0F44B9B2F3 +:20E2600004825B1E00F12400F1D10B4814234FF6FE75002430F81C6FB54206D0078B27B178 +:20E28000002A06BF0F44B9B204835B1EF2D10846F8BDC046E5040120800400202C100020FB +:20E2A000B0B54778144D17BB082095F85C4085F84A0034B91148016809B13846884706F043 +:20E2C00043FB104C601C0078012802D1384606F0E9FC0B48006868B1207D01280AD1287846 +:20E2E0004FF480414FF47A7208F0E3FAB0BD00204A352870B0BDC046500101200C0A012056 +:20E300000C030120E404012038B505462C6801206070207A042809D0022805D111484FF0D0 +:20E32000FF3107F0B7FF15E0002038BD0A480068806901460C48801E8847000824BF4FF021 +:20E34000FF306060002106486170044908602846FEF7FAFD606838BDFC01001088470240A4 +:20E36000030000809C160120030000802DE9F041DFF858803321044600274246107918B12F +:20E380000328BCBF7F1CFFB2491E02F12402F5D1B7B1022017FB00F000B2FBF711FE051CE5 +:20E3A0000FD0034633214046067926B1032EBCBF028823F8022B491E00F12400F4D101E065 +:20E3C0000025002727702846BDE8F0812C100020F8B50446A178032000EB4100C0B205465E +:20E3E000FBF7EEFD071C23D00146207801F8010B2088001201F8010BA0780870666876B102 +:20E40000491C002008E032780A7036F8022B401CC0B212124A70891CA2788242F3DC4520AD +:20E42000C4212A463B4603F0F3FF384603F022FB0020F8BD2DE9F041054690460C460C20D8 +:20E44000FBF7BEFD06460820FBF7BAFD0746FEB1F7B17C607D80B8F1000FB7600FD10020A6 +:20E460000C4C38706069314608F0CCFBE06940F00800E061A06908F0D5FBBDE8F08120468E +:20E4800006F06AFE384603F0F5FA304603F0F2FABDE8F08170F700202DE9F0410E46348875 +:20E4A000ADF1200D162C22DDDFF84C804703362CDABFA4F1160085B22025D8F800006A46C1 +:20E4C000641B2B46A4B2391908F060F90DEB050010F8011D962904D16419A0B230800120FC +:20E4E00006E06D1EADB2002DF2D1162CDFDC002008B0BDE8F081C046CC1900202DE9F04719 +:20E50000164E074630788A4600244FF01808B14603E099F80000641CE4B2A0421CDDFF2FC5 +:20E5200007D006F11C0114FB08F04518085C874209D0FF2FEDD108F011FB14FB08651C35C9 +:20E5400069688842E5D106F065FB6A69116821EA0A01116007F0E9FCBDE8F087501A0020BF +:20E56000F8B5174C2678002786B1221D12F8183F984203D1002301B101231374157C00230D +:20E580002F4318BF0123761E1F46EFD1A0784FB198B9012005F082F9022005F07FF9A078B4 +:20E5A000401C09E0012808D1012005F05FF9022005F05CF9A078401EA0703846F8BDC0467B +:20E5C000501A0020F8B5174C064604F13A0000880F46B04208BF012504D030460023FDF709 +:20E5E00043FF05463046002102F0C8FC618F814216D138460021FEF7F1F970B1817911F00D +:20E60000180F0AD04FF6FE71009102884388618F1046002201F0AAFD02E0384607F07AFC92 +:20E620002846F8BD500101200246F8B5084611464D68203822D0401E1DD0401E18BF6FF0CD +:20E6400001001FD18C6808F075F90F4E074630680069014620688847B0F1FF3FF7D100245B +:20E660006C64EC64286CAC63401EA864384608F0E1FA2046F8BD0021084601E0012100206F +:20E6800085F82D10F8BDC046D001001070B50E46054606F0BFFA044607F06EFF012DB6FB24 +:20E6A000F0F00ED0022D07D00B4B18B9186807F0C3FF0DE0094908E0094B0028F6D009497B +:20E6C00003E0094B0028F1D008490022FBF7BEFC204607F02AFC70BDF4050120B95802001E +:20E6E000F00501204D5D0200EC050120F55D020098B5174C2268D2F8DC00D2F8D8100768F1 +:20E70000D2F8E00009680068D2F8E024404290475FB12168E0310868026878688242DCBF8C +:20E72000801A78603F68002FF5D1226802F1E4000168D2F8E02009681368994204D011602B +:20E7400005F070FD2068E430D0F8F003804798BD140100202DE9F041164E0D460446002146 +:20E7600070682160C068007820B93068D0F858240120904708F0DEF880462946204607F093 +:20E78000B7F82F682A463FB161687868884203DC3A463F68002FF8D1146027602868844211 +:20E7A00003D13068D0F8D4048047404608F042FABDE8F08114010020F8B5174E054606F12D +:20E7C00014042878A978207068780822707540EA011070752979E878B778B07540EA8100C0 +:20E7E000C0B26979B07540EAC100C0B2A979B07540EAC110E91DB07506F1170007F0CEF90A +:20E80000032205F10F0106F11F0007F0C7F90E2FC4BFA87CA073F8BD50010120FEB5057CAE +:20E82000012300221C460EE000EBC206367F770806D316F00C0F03D0F60828BF002300E0A6 +:20E840000024521CD2B29542EEDC077AAFB9012C18BF012911D141798DF80310012404721B +:20E860008DF80830C788ADF80670817A8DF80410684607F028FE2046FEBD0020FEBD10B551 +:20E88000044600211322ADF1180D6846FDF7A6FAE01C10F8014B07F0C3FE0146204605F029 +:20E8A00027FC002804BF01208DF8000010D0002104888DF8001082788DF8014001AB8DF891 +:20E8C000032021128DF80210C11C184607F066F965204A2113226B4603F09AFD06B010BDD7 +:20E8E0002DE9F0410446D4F8A8501F461646884605B1A84704F1A00003C806400F4008BFD3 +:20E90000002E1CD041462046802203F017FE04F1B00181E8C00058B100F1200106C900F19C +:20E920002003BA43B14383E80600D4F8A81081600020C4F8A80004F1500008F011F8BDE87E +:20E94000F081F8B5044608F011F80746A6686068790805460CD300F5D47006F05DFD696B23 +:20E96000286BEB686A6B401A2863296B20469847B80816D305F2A91006F04EFD3168886BF8 +:20E9800020F0200088633168086B20F480700863286A696A2B696A6A401A2862296A204637 +:20E9A0009847F8BD70B50646356807F0C3FFA978F9B90021697008F03DF90F4800F10801B0 +:20E9C0000968090824BF4FF0FF3169600B4901603046FEF7B9FA287A022806D02C696968BF +:20E9E0006A696B7A3046A04770BD054807F0B8FF70BD08F01FF970BD8847024003000080DC +:20EA00009C1601207FB507F095FF114C06462078012818D0684607F0AFFC00254FF0FF302F +:20EA200027216B4601900C4A0A488DF8085003F07FFB0B48012105F0ABFA0848294605F097 +:20EA4000A7FA01202070304608F0F4F800907FBDBA0A0120AC190120AFAD01009C16012043 +:20EA60004C16012070B5154C054694F84A000E46ADF1200D042814BF0828C2201BD0E56408 +:20EA8000684600211C2284F85260FDF7A7F901208DF804000223009500218DF805600848E8 +:20EAA00084F84A3042788DF80710022A08BFC1706846FDF735FB08B070BDC04650010120B7 +:20EAC000E404012030B5164C05466068ADF11C0D18BB0820FBF774FA6060002808BF1020D2 +:20EAE0001CD0296801602979017169794171A9791C22817168460021FDF770F900228DF86B +:20EB00000720286800902C798DF805406B798DF804306846FDF704FB00E0012007B030BD5C +:20EB2000FC090120F8B50D46064606F073F804462946304606F010FC071C08BF022519D0D7 +:20EB4000386808F057F8384608F050F80C4901F108000068B84207D000E0084601698F421F +:20EB6000FBD13969016101E038698860384602F081FF0025204607F0D8F92846F8BDC046EF +:20EB8000380A01202DE9F0418046154800684068124F46688568C468B8F1000F0AD0002DB1 +:20EBA00008BF002C03D03846503007F005FC36B1F4F7BDFD1EB1B8F1010F00D0B047002D91 +:20EBC00008BF002C08D007F069FA05B1A84704B1A047384606F00CF8BDE8F0810100070633 +:20EBE0006CF20020F8B507461248012416460D4604700820F8F7CEFB022004F04FFE312067 +:20EC0000394607F09FFE0C490320012D486019BF086820F00300086840F00300074A0860DC +:20EC2000106800683146034600200246984704480460F8BDAD0B01200C800240CC01001004 +:20EC4000A80250422DE9FF41154D8046281D066811480F461446414606F090FE002804BF49 +:20EC60000F214FF6FD7002D00C48022100888DF80810ADF800004146304607F041FE6946BD +:20EC8000002200F8017B0A2304702846FFF704FA0090BDE8FF81C0461C030120E0030120DC +:20ECA0002804012098B5154CE768014697B11448001D006800693B78007883420ADC7A7869 +:20ECC000D218824206DD7A68C01AC0B210568842B8BF011C07480068026EA068904700901B +:20ECE000054A00996FF39F518A4214BFA0614FF0FF3098BDD8050120FFFF3F00A406012071 +:20ED00001401002070B5164C05466068C068007828B92068D0F8582400210120904707F0C7 +:20ED200009FE2268D2F8D810D2F8F82406462846904730B92268D2F8DC10D2F8F82428469C +:20ED400090472068D0F8E8000068A84203D104F003FBFCF745FB304607F06CFF70BDC0464E +:20ED60001401002098B5164C2068D0F8E800002101602068D83001680F68A7B181687A6862 +:20ED8000096891420FDD04F035FB2168D8310A6812685368984202DD506008680268086932 +:20EDA00002602068D83041680F683FB10169086818B140687A68904200DD0F6098BDC046AB +:20EDC0001401002015492DE9F041804691F8270000280CBF00200120114F81F8280017E0B7 +:20EDE0007D887E6820462946324607F097FC70B9B8F1000F06D120462A460021334607F032 +:20EE0000CFF904E020462946324607F08DFC08373C88002CE4D1BDE8F081C046E404012070 +:20EE200064750200F0B514461D4610270246ADF1240D264601AB16F8010B7F1E80F03600D2 +:20EE400003F8010BF7D10B46009501A80121EDF7A3FE05A82946102206F0A0FE102001AAF0 +:20EE600014F8011B401E81F05C0102F8011BF7D1009501A8012105AA8023EDF78DFE09B086 +:20EE8000F0BD03B480B502AF39780020012908BF01207978012908BF40F00400B9780129D4 +:20EEA00008BF40F00800F978012908BF40F010003979012908BF40F020007979012908BFDB +:20EEC00040F04000B979012908BF40F08000F979012908BF40F48070BDE8804002B070479A +:20EEE0002DE9FC4180461348457990F820400E4603208DF80100684606F0AEF8071C16D0A8 +:20EF000038690B2100F8011B00F8015B04700125BD7706F013FE7862A7F802807D773E6258 +:20EF20000548BD76002101703846EBF791F9BDE8FC81C046E4040120E4020120F8B50546A5 +:20EF40000820FBF73DF8071C21D02878C01CC0B20446801C05F0FAFF786020B9384602F06B +:20EF600089FD002713E07868FE210170786822462946401CF9F7CAFF7E682146701C06F0E6 +:20EF800051FFA119487000263E70A31C7B80284606F0E2F83846F8BD2DE9F8431446884637 +:20EFA000064600229946F189B0890092727A337C401A80B2054604F063F8071C14D10C48A2 +:20EFC000B28900684544A9B20B199A4205DAF089A042ACBF0627052706E0327C234601EBC3 +:20EFE00042314A4607F0D2FB3846BDE8F883C046CC1900202DE9F047144D80462878002766 +:20F000004FF018093C4605F11C0A19E014FB09A63178884512D106F1080004F096FE07460E +:20F02000B06828B920464FF40041FFF767FA04E020464FF4004100F00BF82878641CE4B21F +:20F04000A042E3DC3846BDE8F087C046501A0020154A2DE9F84F0F461178804600244FF022 +:20F06000180A032002F11C06914618E014FB0AF5725D904511D105F0CDFD83467119486910 +:20F0800002683A430260C86808B107F0CBFD584606F04BFF99F800100020641CE4B2A142E7 +:20F0A000E4DCBDE8F88FC046501A002038B54FF0FF3006F0C1FF05460F4C1049A06A8142F7 +:20F0C0000FD10F4904F16000002205F094FF022084F8240003F082FC18B9F9F7DBF8EDF74E +:20F0E0006DFC0848284205D004F1E0004FF0005107F03EFC38BDC04668F20020855C00002C +:20F100003538010002000040B0B5154C0146C820002522465388994205D0401E02F10802D7 +:20F1200005F10105F6D1C82D17D14FF6FE70884213D1083CC821002514F8087F27B1491EAA +:20F1400005F10105F8D10834C82D06DA6080606818B102F08FFC002060602846B0BDC0462A +:20F16000EC09002010B5154CA06830B3C16C19B1084602F07FFCA068416C19B1084602F0F8 +:20F1800079FCA068416919B1084602F073FCA068C16919B1084602F06DFCA068416B19B1AC +:20F1A000084602F067FCA068C06B08B102F062FCA06802F05FFC0020A06010BD3C050120CC +:20F1C0003EB5154D044628464368197041684A70207A022818BF0F2816D121884FF6FF7075 +:20F1E000884205D0C21E8A4202D0801E88420BD102238DF8083007F0E3F969463622ADF84D +:20F2000000002846FEF748FF2846214636220223FEF742FF3EBDC04628040120DFB5171CA7 +:20F220000C46064626D02EB340F20110002110226B4606F0B5FF04F00F0438460DEB0401E6 +:20F24000C4F1100206F0AAFC381B69462246103006F0A4FC7F1E3046082617F8012F017812 +:20F260003C7A5140397010F8011B761E81EA04013972F2D10090DFBD2DE9F84384680D464C +:20F2800003F02EFA174600BB246801F007FF64198046002F08BF00250FD00D4E07F04AFBE4 +:20F2A0008146204606F0B8F90546484607F0C2FC1DB930683F1A0444F0D1404605F080FB26 +:20F2C000002D14BF4FF0FF300020BDE8F883C046041B012030B584684568ADF1140D204697 +:20F2E00005F0F6FA2168486820F0020048602168486920F00F00486120680321016202A87B +:20F3000007F00AFB09480068D5F8E42001680092D5F8E8000190206895F8F93095F8FA2041 +:20F320000C460399A04705B030BDC046C4010010B0B5124C0546802D03DD2068D0F84C053F +:20F34000804707F0F7FA0F4927680D70D7F8B8100F780B4917B90F783FB90AE00F7837F041 +:20F360007F0702D108490F781FB107F063FC0120B0BD07F05FFCF9F7DFFCB0BD14010020E9 +:20F38000741B0120A40601206A1B0120B0B5124C0546802D03DD2068D0F84C05804707F052 +:20F3A000C9FA0E4927680D70D7F8B8100F780C4917B90F783FB90AE00F7837F07F0702D174 +:20F3C00008490F781FB107F035FC0120B0BD07F031FCF9F7FFFCB0BD14010020A406012053 +:20F3E000741B01206A1B0120154838B508300168D1F8D40090F85300D1F818148847042864 +:20F4000014BF40F6387443F66C4405F003FC054607F0B2F8074A084B127821464A430749FC +:20F42000B2FBF0F00022FAF711FE284606F07DFD38BDC046D8000020F8050120B953020020 +:20F440000C0100201CB50E21F8288DF8001023D1124CA268D432116891F8840050B991F94F +:20F4600042000E2815D0D2F85C23E02069469047A2680DE014208DF8000091F942001428A8 +:20F4800007D0D2F85C23E0206946904708342268D432D2F8F80280471CBDC0460C01002063 +:20F4A00038B5044614F8010B15462870207800F00F00687014F8010B0011A870207800F0D2 +:20F4C0000300E8702078C0F3800028712078C0F3C300687114F8010B08222146C011A871F3 +:20F4E000E81D06F05BFB0834032205F10F00214606F054FB14F8030FA87438BD154808B560 +:20F500004178022922D1007800BB4FF6FF700021F0F744FA012040F6B831F8F771FC082023 +:20F520004FF4DC71F8F76CFC10206421F8F768FC2020F8F765FC4FF480504FF47A71F8F71C +:20F540005FFC034A3520282107F0EEF808BDC04630030120E40401202DE9F0474468894698 +:20F5600004F5B27007F0E0F9DFF844A0677F257FA66907F001F8804606F0FEFFED19ED1D93 +:20F5800004F5B2744946AAB251430AFB01F1B1FBF6F164314144491EB1FBF0F1491C20466A +:20F5A00007F0BEF9204607F0BDF9BDE8F087C04640420F00154909681E280ADC1E2819D0AD +:20F5C0000C380FD00A380FD0001F0FD0C01E0FD01AE0243810D0001F10D0401E10D0801E1B +:20F5E00010D011E0086870474868704788687047C8687047086970474869704788697047E6 +:20F60000C8697047086A7047002070477CFF002010B5044600210C22ADF1180D6846FCF7A5 +:20F62000DDFB6089ADF80000207A8DF80400207B8DF80500607A012814BF012021208DF85F +:20F6400002006846F3F7B6FA9DF8140050B903986168227A406C06F0A1FA684602F00AF9CE +:20F660009DF8140006B010BDF8B507464FF6FE703E78B881002006B3104E328875680446AA +:20F6800019E0A10001EBC4016B5C13F00F0F10D13878685478886D18391D6880281D06F0EC +:20F6A00019FFBC81284606F05AFF3288756801201446641CA4B2A242E3DCF8BDDC0A0120F1 +:20F6C00090B5ADF1140D07F0EBF8071C08BF002410D001248DF800407888FF212422ADF869 +:20F6E0000C003846FCF77AFB802087F82100684603F0FCFF0020042104F0D2FF332805DAF8 +:20F7000004480121401C0170FBF752FB204605B090BDC046FC09012003B40021F0B505AFAA +:20F720003846ADF11C0D01AAFCF70AFC002818BF002015D10D4C2069FAF72CFE002506466D +:20F740000095E18E94F8330001AA0323F0F7D6FB08B9BDF8125020693146FDF70FFB284619 +:20F7600007B0BDE8F04002B07047C046C019002038B5134D95F83901002410B911480078C3 +:20F7800060B107F0D7F895F83B11002906BF012185F83B11012407F04DFA0CB1002038BDAB +:20F7A000022004F07BF80E20F7F7F4FD05F09EFA01280EBF0120002085F83A0138BDC0463C +:20F7C000501800203E860200144BB0B511F1800F43EA0202C2F3150208BF071C19D090F92D +:20F7E000004000277F2C0FD00546D5F801406FF39F54A34208D095F90040A14204DB15F90F +:20F80000054F7F1C7F2CF0D137B107EB87077F1F3F18D7F80100B0BD1046B0BDFFFF3F00F3 +:20F8200038B507F087F80E4C05462078012813D00C480D4A3121002302F07AFC0B480C49EC +:20F840000422082306F05CFC0A4A4FF0FF300121FFF7C8F901202070284607F0EBF938BD7F +:20F86000AC0B0120581901200D920100741901204009012080A903003EB515460C4602AAEE +:20F8800004F0F4FB002818BF012020D1BDF80800694604F001FC009850B9684603F0C0FC19 +:20F8A000002818BF112012D1BDF808000099088020462946FAF774F8204601A905F00CFD17 +:20F8C00010B9019801210171FDF7FEFC00203EBD4EF68851CEF2000108684FF0F00340EA7F +:20F8E000034008600C4885460C4885446F4607208743BD460A486F4607600A48002803D0BD +:20F900007946491D8E460047F8F7EEFF06F0EEF907F01CF9FEE7C046003A01200006000096 +:20F920009C0B0120E1690200FEB506461248B5680078124C8DF8000003E0686A08B106F07E +:20F9400049FB2188304606F078FC6846012100F025FD01A8012104F023FC218807463046AE +:20F9600006F074FC002F18BF381C04D19DF804004008E2D20020FEBD66800200101B01204E +:20F9800010480078A0B91048007888B90F48007870B90F48007858B90E48007840B9064840 +:20F9A000007828B90548007810B90548007808B10020704701207047B20A0120B30A012078 +:20F9C000B40A01206F1B0120711B0120741B01206A1B0120701B012038B5044612480078E5 +:20F9E0000D4640B1114960893A310988814203D101F086FD38BD60890021FCF7EFFF60B188 +:20FA0000807910F0180F08D0688E00906189627F2B8DA08900F0AAFB38BDA08961890022FD +:20FA2000FEF7D0FD38BDC046F504012050010120FEB5144C154604F12C0217681E46FFB159 +:20FA40003A69EAB101228DF80020BA6AADF80200002AADF8041008BF002003D09DE80300B0 +:20FA60009047E76A854208BF00200AD03C699DE803002A463346A047012808BF0A2000D0EF +:20FA80000920FEBDD4DB00202DE9FE43134C06462068984617460D4607F054F88146294622 +:20FAA0003A463046FCF7A4FC07462068494607F045F85FB90848006800900196054C029546 +:20FAC00021880022DD23404607F034F83846BDE8FE83C0466473020028750200007302001B +:20FAE00098B50446A1682079FFF7B2FA207B00BB206807F07FF80F498868A04207D000E0FE +:20FB0000104602699442FBD12269026101E020698860C86800222261CF6817B9CC6004E056 +:20FB200010460269002AFBD1046108784968FFF78FFA98BD380A012038B5054600211420B4 +:20FB400006F012FC00240A20002106F00DFCC4F1070045FA00F1092001F0010106F004FC35 +:20FB60000A20012106F000FC082006F09CFE641C082CE8DB0A20002106F0F6FB1420012190 +:20FB800006F0F2FB4FF42F7006F08DFE38BDD0B504680E1C174622D00FB302F0FDFBA0680C +:20FBA00006F0C2FE4FF6FF70B84205D0B7F5004FA8BF47F6FF777800A4F85800701005F016 +:20FBC000D4FCA4F85600A068B4F8561006F0A8FEA06806F0A7FE022084F85000D0BD05F09A +:20FBE00093F9D0BD7FB506460020029008981D46009002A801903046FDF7D5FB0446012C3B +:20FC000003D12846314604F028FF022C0CD102980268006820B92846314604F00BFF03E0FA +:20FC20002846314604F006FC042C03D12846314604F000FF204600907FBD1FB5044600219C +:20FC4000AB200DF1060200F00FFD05F077FF01460DF1060005F092FEA8B120460DF10601D8 +:20FC600004F0D5FE88B10DF10600694605F034FB18B90098007930B907E00DF1060001A94D +:20FC800004F056FC08B9012000E0002000901FBDB0B505462C680F4606F04CFE104909781D +:20FCA000012901D1217819B106F0C4FF0020B0BD0121217006F0BEFF07B9084F38782072E0 +:20FCC000786820613878022814BF0020B868E0600B20F7F75FFB2846B0BDC046C8860200F2 +:20FCE000BB0A012010B503F019FD114C14202146491CFDF70DFD0A202146FDF709FD092041 +:20FD00002146FDF705FD0B490820FDF701FDB920FFF712FF142004F08BF80A2004F088F8EF +:20FD2000092004F085F8082004F082F810BDC04600620020022000200246134898B570306C +:20FD40000168476D01F00103002007F004071F4318BF0120930802EA000006D301F00204BE +:20FD60000023204318BF01231846D20806D301F004010022084318BF01221046002814BF43 +:20FD80000120022098BDC046D02008402DE9F043171C0D464FF00009ADF1240D19D0DFF8E7 +:20FDA0003C804603202FACBF20243C1C4046006871196A46234606F0E9FC484669462246D7 +:20FDC00005F0BAFA3F1B2D19BFB2ADB28146002FE8D1484609B0BDE8F083C046CC190020F1 +:20FDE00010B510481249104A006800F00F0083025C1E08461360E1430160012004F0DEF89A +:20FE0000044606F097FD094A116831B106F012FF34B1204606F028FC10BD146006F00AFFB4 +:20FE200010BDC04630240340041B0120001B0120081B0120084608B500F0005100F0040058 +:20FE4000084316D00B480068016801208847012808D006F091FB3221B1FBF0F1064806F0B6 +:20FE60006FF808BD0549064828310860054806F0A3FA08BDE0010010C0F3002068F2002016 +:20FE8000855C0000601A0120F0B5134E00274FF6FE75ADF1140D06F07EFC0446301D0088B3 +:20FEA000A042F8D006F07AFBA042F4D0204601F081FD0028EFD1002CEDD08DF80070ADF847 +:20FEC00002406846FBF7C4FF0028E4D1A542E2D0204605B0F0BDC04686010120F8B50D4691 +:20FEE000044606F027FD06466768A0682946874205D1304606F09EFE4FF0FF30F8BDE568F5 +:20FF0000A26923686D1CB5FBF7F078432D1A05FB0230F8F7FBFFA0686169E560401CA0609B +:20FF2000814238BF6061304606F084FEA068F8BDB0B5171C0C460546ADF1280D19D0104852 +:20FF4000B9680068884204D8B1F1FF3F18BF002014D1684600212822082306F0E7FDFA6836 +:20FF60000792386804907B680593B96806916A4600E000222846214605F01CFD0AB0B0BDC5 +:20FF8000D07302002DE9F041124D04462869082204F102084146801C05F0CEF818B12C6936 +:20FFA000E068286111E02F69002657B1FD6841460822A81C05F0C0F810B92F1CF6D100E077 +:20FFC0003E462EB1F068C068F060204601F052FDBDE8F0816806012070B50646B568296884 +:20FFE0007468486820F002004860204606F0A0FCD4F8CC0002F057FF04F1300006F0B2FC1A +:020000040002F8 +:2000000094F8F80018B904F16C0006F0A7FC304602F08CFD287BF6F725FF04F11C0005F0E6 +:20002000ABF8002084F8FD0070BD7047F8B506464FF6FE7000217080301D06F04BFA3046E5 +:2000400004F006FB351D0746012F13D1B0890A4B840004EBC004181D006824186088708082 +:20006000241D204605F027FA012803D12846214606F030FA3846F8BDDC0A012011482DE928 +:20008000F041076800260760B7B1DFF83C800124D8F80410B7FA87F0C0F11F0082008D58D0 +:2000A00004FA00F39F43002D08BF1E4302D08958C0B28847002FEBD116B1304600BF00BF7E +:2000C000BDE8F081E0200240E8860200F8B5124C06466069002710B1804700B90B27206915 +:2000E000BFB9FAF757F927780546381C0DD1E08EC0F5005000B2864203DC002E18BF04272F +:2001000003D10020E8F7A0FB677820692946FCF735FE3846F8BDC046C01900203EB5044605 +:20012000104800224FF6FF75052130F8043F9D4201D09C4204D0491E02F10102F5D13EBD7B +:20014000052A0DDAFF210422FBF748FE064D0220ADF8004029888DF80800684604F07FF959 +:200160003EBDC0462C010020980101202DE9F041044698460D46101C06AF17D1084600217D +:20018000FCF72CFC061C17D0B079400814D3388841462246F4F7D0FD4FF6FE7181420BD02A +:2001A000708028460C222546044600E00B22204629460023FCF758F9BDE8F0811CB5044684 +:2001C0003A220120694606F09AF9E0B99DF80000A04216D001200DF101013B2206F08FF978 +:2001E00088B99DF80100A0420DD19DF800009DF801108842A8BF3B2007DA9DF80100F8F73B +:20020000D3FA3A201CBD4FF6FF701CBD08B58DF80000022004F0E8FDC8B90E480068D0F80D +:200220003403804798B1E120694601F0C3FD01200DF101018DF80100522001F0BBFD064806 +:2002400000220270104605F0A1FF104608BD012008BDC04614010020C60A012038B5046899 +:2002600094F83000042808BF0F4D17D0022805D001280CBF00204FF0FF3038BD216A04F196 +:20028000340006F007F80DE0012006F00CFB281F006810F0030FF7D0F8F7B8FFA06A616A27 +:2002A0008842F1D8E06A38BD0C8002401CB5002004F032FC06F084F9044605F03FFC014657 +:2002C0000C4802780023204602F0C0FB002004F023FC0948417802290AD1007D012807D159 +:2002E000684606F0B4FA06F059F96946FEF7F8FD1CBDC046521A0120E4040120F8B5124C4B +:20030000074604F1080005680E46281C09D001798F4202D1C1888E4213D0054600680028C0 +:20032000F5D10820F9F74CFE002808BF102009D00771C68000210160A16800290CBFA06060 +:2003400028600020F8BDC04628040120114910B50446887808B1886A10B900208870486A46 +:2003600005F080FA0C484178C06B38B9012C14BF052003200021E7F7FFF810BD012903D1DC +:20038000012C18BF012100D100216420E3F77AFD10BDC04668060120E4040120F0B5124C02 +:2003A000074600250E46ADF11C0D2068029577B90121009106AB01933A788DF8182069464B +:2003C00006F007FA48B1761E0AD07F1C206800960197694606F0FDF910B94FF0FF3000E0BC +:2003E000284607B0F0BDC0460C1B012098B506F0A1FA04460D48007898B90D490F78012099 +:2004000037F07F0707D10B490F7837F07F0702D109490F781FB180F00100C0B208B102F0C5 +:20042000B5FF204606F006FC98BDC046701B01206F1B0120741B01206A1B012038B5124C57 +:2004400022680546D2F8EC0050F82100D2F8E01008602168D1F8E41008600A480068A84234 +:2004600003D82068D0F84C058047280803D32068D0F84C05804706F05DFA06F0DBFB03F0BF +:20048000D1FE38BDE000002014010020124AB0B5032311464C88A04208BFC52015D05B1E65 +:2004A00001F10401F6D1114603234FF6FE754C88A54208D05B1E01F10401F8D1111F032228 +:2004C00011F8047F27B94880002004220A70B0BD521EF5D1C720B0BD240301202DE9F0479C +:2004E000114E00258A460746A846B8F1000F18D16C01A4EB8504A01900F10209484604F010 +:20050000DAFF58B1305B874208BF48F00A085146484605F033FA08B148F0A0086D1C142DEA +:20052000E3DB4046BDE8F0879C040020F8B5124C607801281CD004F5C27600204FF4405778 +:2005400031467F1E41F8040BFBD1E82131604BF6FC75A851A5F1E801C6F8E81006F1E80119 +:20056000A160F9F72DFDE060A6600120607025614BF6BE20F8BDC046501A00207CB5124CB0 +:200580000346E06A16460025E0B18269D2B101228DF80020826AADF80230ADF8041082B1D1 +:2005A0009DE80300904760B1864208D1E06A82699DE803009047012808BF0A2502E00C2564 +:2005C00000E0092528467CBDD4DB002030B500240822ADF1240D214605A88DF81C40FBF7AE +:2005E000FDFB05A807A96A46FBF77AFB05469DF81C0078B1684621461422FBF7EFFBFF2024 +:20060000294614226B468DF81000042002F040FF204600E0012009B030BD98B5437B0A4632 +:200620000021042B1ED1077CE7B94769D7B1387810F0030F16D150687C7B437DA34211D141 +:2006400012887B899A420DD1C288BB889A4209D18278BB789A4204D0007800F00C00042882 +:2006600000D10121084698BD38B5104C15466269E368A488A13816D0401E0AD0401E02D0D7 +:2006800008380BD038BD0A48006868B18047044609E04AB108462946904738BD284619462C +:2006A00006F02EF938BD2C8038BDC046E00601202809012010B5104CA41EA07898B10120C3 +:2006C000207004F0E9FDA178FF2910D000200B4BA070A3F13E0000784FF47A724A43802162 +:2006E00006F0EAF803E00020207004F0D5FD4120214601F05FFB10BDFE0901208E01012011 +:200700001149C8B570310A684E6D410806D302F0010106F0040600270E4300D00127810825 +:2007200005D3002117B1930828BF01210F46C00805D3002017B1D10828BF01200746002F1A +:2007400014BF01200220C8BDD020084030B5104CDD214FF4806204F19405ADF13C0D28467F +:20076000FBF73CFB00213C220823684606F002FA4FF480600023074908906A460795042068 +:20078000069004F1440006F0F1F90FB030BDC04670F70020D18D000038B5491D04468DB237 +:2007A000294604F099FC20F0020029460246204604F04EFF0A480C21493014FB0105287824 +:2007C00060B12046022104F087FC20F0030002210246204604F03CFF0020287038BDC04642 +:2007E000C0190020F8B505460F1C08BF05201CD00E4C2078C0B1241D14F8181F8D4211D16D +:2008000004F008FA0646394604F1080003F0B4FA28464FF40041FEF71BFC304605F085FB90 +:200820000020F8BD401EE7D10320F8BD501A0020042870B51ED1104D05F5AC70064605F077 +:200840007BFDB8B105F098FE0446304606F066F86043B0F5967F0DD2304606F065F80520EE +:2008600003F01CF82846012180F831100421E03006F07EF8002070BD68F2002098B5114C16 +:200880000146323C94F82C000727C0B90846B4F8481000F089FF011C11D094F83100012896 +:2008A00007D1887804F085FB49788142A8BF081C02E0887804F07DFB071C08BF07273846F9 +:2008C00098BDC0468201012070B50E46044606F031F8A16805463046B1B1A26923692168EB +:2008E00002FB0311F8F712FB2069A1686368401C491EB0FBF3F2A1605A43801A2061284614 +:2009000006F098F9A06870BD284606F093F94FF0FF3070BDF8B505466C68AE6806F00AF8B6 +:2009200031680746886B20F4FA60886304F5D47004F072FDA06B18B9384606F07BF9F8BD6C +:200940000022616B206BA263401A2063384606F071F9E068216B626B034628469847F8BD72 +:20096000FEB5104D6C682079F6F714FD05F0E2FF2E680746307880B9684605F0FDFCA079AD +:20098000094A0190617900956B46301D01F0D0FB01203070284604F003FF384606F04AF96E +:2009A0002846FEBD1C8802000568020038B5044605F0C4F80146A01C04F0E0FFA51C012851 +:2009C0000BD00B48007830F0010010D12088A27AE37A2946F3F7E6FE38BD064854300168E1 +:2009E00011B12046884710B9E07AF6F79DFE38BDE5040120C40301203EB50546AC690421F6 +:200A0000204604F067FD241D009014F8010B01218DF8040022788DF805108DF80610084865 +:200A2000C1700271022180F82E106988C184697C81706846FEF746F808B102F09FFA3EBD0D +:200A4000C4030120BCB501468A695078177807EB00270D480088074015D0487C0B4D8DF8E9 +:200A60000000686800243A12032300F8014B891C00F8017B1027027048F215026846EF70AC +:200A8000FDF70AFBEC70BCBD581A01202804012010B5002104461822ADF1180D217268463A +:200AA000FBF79CF90B226846214605F077F808220DF10B0004F10B0105F070F8A08AADF8A9 +:200AC0001400A07D8DF8160003480068D0F81C126846884706B010BD1401002030B505463C +:200AE00010484830048800213C22ADF13C0D6846FBF774F902208DF80C00ADF800508DF8FA +:200B000008003121ADF80A400DF10E0003F025FD03480068D0F88812684688470FB030BD2D +:200B200014010020500101200EB510200DF102018DF802005A2001F03DF94FF4FA70694696 +:200B4000ADF80000552001F035F903200DF103018DF80300592001F02DF909208DF804006D +:200B600003480068D0F8302401A9E02090470EBD140100204FF6FE7190B58142ADF1140DAA +:200B80001AD00E4900270E2201E07F1CFFB24FB917FB02146378012BF7D0002BF5D16388B6 +:200BA0009842F2D1012F07D1ADF80C00042168468DF8001002F09AFD05B090BD22010020A9 +:200BC000F8B506460F4D104F7388002417E0A20002EBC402921951689068D26852B9AF4264 +:200BE0000BD00A7855F822200346491C08461946904701E0F8F78AF97388641CA4B2A342CE +:200C0000E5DCF8BD408D02004C8D020010B505F091FE0C49097879B90B49097861B90B4920 +:200C2000097849B90A49097831B90A49097831F0020108BF012400D0002405F0FBFF204646 +:200C400010BDC0466F1B0120711B0120741B01206A1B0120701B0120114980B50B68071C42 +:200C60001DD0181C0DD00022874204D0024640680028F9D105E0834219BF40685060406853 +:200C800008603868006A00F0F5FE386800F0F2FE786908B100F0EEFE384600F0EBFE80BD75 +:200CA000E40A0120F8B503F0B5FF104900252F463E462C46CB68486012E0110809D21FB94F +:200CC00014461D4601270AE02968A4188918296005E082F000420027B44288BF261C9B18DC +:200CE0001A68002AE9D105F020F9F8BD501A002090B5114C2468ADF1240DBCB1276AAFB1E6 +:200D000001248DF818400424ADF81A400024ADF81C400091019202930C9A039206AB04904C +:200D200093E8030022461423B84708B10A2000E0204609B090BDC04600DC002010B5838995 +:200D40009A0002EBC3020E4B1B1D1B6801291A44144618BF02290AD14288022962800BD1C1 +:200D6000001D04F0A8FB08B90020207004E0121D011D104605F0AEFB204605F0F0FB10BD16 +:200D8000DC0A01200E49086820F0020040F4087008600C48032140F8041C41F2300181604A +:200DA000012101605022826001604FF4CA62826001604FF486528260016003480160704788 +:200DC000000004605860044000410440F8B505466C68082004F0BAF8071C12D001203870C6 +:200DE0002078C01CF9F7ECF809490E68786040B122782146D21CF8F789F8F0B23946FFF7A4 +:200E0000F1FC686804F0A8F9284600F033FEF8BD7CF700202DE9FC470F4C8046606900273F +:200E20001D4692460E46B94608B1804758B157B904200090E06806EB48312B46524605F027 +:200E400065FB814600E00B27B9F1000F48BF01273846BDE8FC87C046C01900202DE9F04185 +:200E60000746B86840681C460D4690462919884238BF6FF0030010D3094E30684FF0FF312C +:200E800005F008FA3846294642462346FAF7EAFE0446306805F064FD2046BDE8F081C046EA +:200EA000141B01200E4A98B512780F460446012A01D003F02BF80B480078A0420CDD07B9AC +:200EC000064F09480C2114FB01F140588069394602462046904798BD002098BD78880200ED +:200EE000B10B01205C830200A08502000F49A1F1240000688008FAD30D48001F006801283D +:200F000019BF0122111C20210122074840F8251C002340F83D3C0823C0F8FB3FC0F8FF3F96 +:200F200040F83D2C7047C0463D400C407C600C409019002098B505F0FDFC0446F9F73EFBEB +:200F40000D480021001D0170032002F08FFC204605F070FE074CA068014602208847074644 +:200F6000102001F053FE1FB1A06801460320884798BDC046308602008419002010B504460F +:200F8000C8090FD20E48007830F0010008D1204605F059FC20B1007901280CD002280AD0D4 +:200FA000204610BD2146FF2003F0A2F8002808BF4FF6FE7001D00148008810BD8A0101202E +:200FC000E50401202DE9F84307468C4616469E460020B7B1DFF83090044676B10CEB440587 +:200FE000F046324638F8021B2B88994203D129F81010401CC0B2521EF4D17F1E04F10104B9 +:20100000EBD1BDE8F883C0465405012038B50178012914BF00250825411C8078012814BF6E +:20102000082009200B78C0F16C00C4B22BB1052004F0FCFD241A0D3CE4B20548007820B1A8 +:2010400004F0F4FD241A0E3CE4B2641BE0B238BD800101202DE9F84F0F4E00249046824669 +:201060004FF00E0B274603E0641CE4B27F1CFFB2002F18BF00200DD117FB0BF5705D8245BC +:20108000F4D1AD19284603F01FFE0028EED0A045EADC2846BDE8F88F22010020B0B54FF035 +:2010A0008054D4F8D8010E4D80680146284688472A1D116804F5EC74C7B241F0300111608B +:2010C00067B1206840680021024628469047206880680146284688470028F8D13846B0BD4A +:2010E00000400340BCB50546FEF71EFC002818BF4FF0FF3017D10C4CC72021888DF80000E0 +:20110000284605F09AF868460121FFF747F921880746284605F09AF8002F18BF381C02D1BC +:201120002846FEF701FCBCBD101B0120104A98B5D768C7B10D48006800690078FF2810D087 +:201140003B7883420DDC7978C918814209DD79681778C01AC0B20C56F81AC0B208568442ED +:2011600001D0012098BD002098BDC04618010020A406012070B5054605F0DCFB0E4C226889 +:20118000D2F8D810D2F8F82406462846904730B92268D2F8DC10D2F8F8242846904720684A +:2011A000E83001680968A94202D1D0F8F0038047304605F03FFD70BD1401002038B50446BD +:2011C0000D46142003F0C2FE011C0BD00C2008708C7000248C730A4B4D701878FFF702FB85 +:2011E000204638BD204604F091FB38B106214173007B02F06BFB2046FAF7BCFB102038BDE4 +:201200005001012098B505F095FB0446F9F7D6F90028FBD0032002F029FB0A49002008706A +:20122000204605F007FD084CA0680146022088470746102001F0EAFC1FB1A0680146032025 +:20124000884798BD881900203086020038B58168096844688969080916D305F08DF94FF454 +:20126000FA75B5FBF0F0012898BF012103D905F083F9B5FBF0F104F5B274204605F050FB2A +:20128000204605F04FFB38BD04F18800022105F06FFB38BD70B50D46044605F04BFB6668F5 +:2012A000A1682B468E4204D105F0C4FC4FF0FF3070BDE1682568491CB1FBF6F27243891A98 +:2012C0004B55A2686369E160521CA260934238BF626105F0AFFCA06870BD38B50546297DA5 +:2012E000032905D002291AD1808905F0ACFA03E005F10C0005F0D4FA041C10D0687860B19A +:20130000F12818BFE12804D1A079012801D105F023FBA07918B1401E00E00020A07138BD92 +:2013200090B50F1C4FF00004ADF1340D18D00168086AA8B1C97F6A46F1F75CFE7888BDF810 +:201340000C1088420CD19DF80200012808D10A980178012904D139788078814208BF0124BF +:2013600020460DB090BD70472DE9FC410E4E00254FF00E082C4611E014FB08F7B819214674 +:20138000002243460090022001F040FA20B9F05DFF281CBF6D1CADB2641CE4B2002CEBD0B8 +:2013A0002846BDE8FC81C046220100200E4870B50168D8310868006810B94868006888B175 +:2013C00005F0B8FA06460948001D056802F012F80446304605F02EFC641CA5428CBF281B6F +:2013E000012070BD002070BD14010020E000002010B504460E48ADF1180D047005F092FBFF +:20140000002115226846FAF7E9FC152102A22346684604F055FBFEE75B41737365727420E9 +:20142000526561736F6E5D2030782530325800C0E80101200F4908B5D1F878020B68020F9A +:2014400003F0FF037F2B88BF002304F0C9F801464FF0FF3004290CD11146012908D9891E06 +:2014600003D0491E05D1153300E00B3358B208BD0A2008BDA01000502DE9F0418768786822 +:201480001D460C4690466119884238BF6FF003000FD3094E30684FF0FF3104F0FBFE396856 +:2014A00040462A460919F7F731FD306805F058FA0020BDE8F081C046001B0120B0B505F047 +:2014C00039FA05460B48017801290FD00A49024601230878137048B1084C074620688068ED +:2014E0000146204688470C347F1EF7D1284605F0A1FBB0BDB20B0120000000000000000081 +:2015000010B50E4C20784FF4805100F093FA88B90B48C27C407E012814BF03210121002091 +:20152000F0F768FF20784FF4805141F2883205F0C3F910BD0120E07010BDC0465001012090 +:20154000E4040120B0B505F0F5F905460B48017801290FD00A49024601230878137048B15F +:20156000084C0746206880680146204688470C347F1EF7D1284605F05DFBB0BDB30B012032 +:201580006083020090870200B0B505F0D3F905460B48017801290FD00A49024601230878C8 +:2015A000137048B1084C0746206880680146204688470C347F1EF7D1284605F03BFBB0BD77 +:2015C000B40B0120648302009C87020000B500211122ADF1140D6846FAF700FC81201121E7 +:2015E0006A4605F09BF870B98120002111226B4604F0D6FD38B99DF8000020B103490879F9 +:2016000040F01000087105B000BDC0464C1A012010B5ADF1280DFAF70BFD00248220182281 +:2016200021466B4604F0BCFD88B906A821461022FAF7D4FB0DF1010006A9102203F07CFD51 +:2016400028B9684621461822FAF7C8FB012420460AB010BDF8B50F4C06AF6568D7F800E05B +:201660008446184603E01EF8016B05F8016B0646701E002EC0B2F6D13F79002F07BF002561 +:20168000281C40200025E0706046FCF705FDE570F8BDC0462804012010B50446207804F09E +:2016A000C5F8002818BF022014D11420F8F788FC60B1094A516801604460506000238360E8 +:2016C00032210173012444738473036100280CBF1020002010BDC046BC0A012098B50E4C68 +:2016E000071C03D12068D0F84C05804705F022F90A4A1178B943117005F09CFAFEF776FE2D +:201700006068C068007828B92068D0F8582400200146904798BDC04614010020701B01203A +:2017200098B50E4C083CA06800F1400319680F6837B9D0F84C058047A3684033186807684D +:20174000074810300068044604F002FDF860204604F0A4F819680968088298BD1401002001 +:20176000D405012010B504462168086AADF1380DA8B1C97F01AAF1F73DFC0A48BDF80E10F0 +:201780003A30008888420AD0206800889DF821200090BDF810004FF6FE73FEF7E7FC0EB02C +:2017A00010BDC0465001012038B505460D4800780C4630F001000BD10B480E300088A04295 +:2017C00006D1284605F03FF8002818BF083007D12846214602F068FD002814BF1030002002 +:2017E00038BDC046E50401208A01012038B50F4C0D463A3CB4F84810FFF7D6FF011C10D05B +:20180000887803F0D6FB497859B150B194F83120012A02D18142B8BF011C081C01D085424A +:2018200001DA002038BD012038BDC0468A010120F8B507467D68002616E06069C5F8C800A7 +:201840006068666110F0704F06D128B1062002F00DF8042002F00AF8022002F007F8D5F875 +:20186000BC20384621469047D5F8C840002CE4D1F8BD704710B50446207DA0B92046F1F75B +:201880003FFC206918B10A48016820468847207D20B9E068E8F7DCFC207504E0E06800F0A5 +:2018A000E9F80020E060204604F05CFF10BDC046BC080120F0B515460E4604461F1CADF103 +:2018C000240D08BF00230DD0684600212422082305F06CF93B78ADF81030B86806907A6846 +:2018E00005926B46204631462A4605F017F9204609B0F0BDB0B50C460546171CADF1280D7A +:2019000008BF00220DD0684600212422082305F04DF9B8683B7806907968ADF810306A46A7 +:201920000591034B2846214605F03CF90AB0B0BD800901201FB5044620880822A11C8DF8C1 +:20194000000000128DF801000DF1020004F026F9A07A8DF80A00E07A8DF80B00207BC921C4 +:201960000D226B468DF80C00452000F051FD002000901FBD38B504460D460846FDF7C4FB3C +:20198000C828A8BF4FF6FE7011DA094901EBC001487849686160207030B1421E01EB400123 +:2019A000627031F8020C38BD00206070284638BDEC0900204FF6F87280B50021801A0328F7 +:2019C0000BD9001F07D0401E03D0801E0ED1012704E0022702E0042700E00827044800786A +:2019E000074202D107B1012100E00221084680BDE50201200E4938B58A68CD681B3800FBA2 +:201A000000F482FB04234443C5FB04234C68C4FB002312091807024308681B11C11780189F +:201A20004FEA104041EB03010904084338BDC046D808012070B50C46064603F0EBF80546B5 +:201A40002146304603F088FC002808BF00240AD0006802F04BF9064909684FF47A72B2FB0B +:201A6000F1F1B0FBF1F4284604F05FFA204670BDA0880200B0B5071C19D003F0CBF80C4900 +:201A800048604C690B6957F8042C15080BD322F000428D6847F8042C9B183F1F0B61AF42D5 +:201AA00038BF8F6001E0641C4C6104F03EFAB0BD501A0020C8B50E4601460A480778002006 +:201AC00077B1094A12788A420ADD06B9074E084A0C2011FB00200168C9680A463146904758 +:201AE000C8BDC046B20B012000000000B88502000000000070B504F01DFF06460C48001D4C +:201B0000007850B108480068C0680546074800243C2101222346A84700B10124304605F095 +:201B200089F8204670BDC046A401001000A00C408419002070B504460C4806680C48006840 +:201B40002568006B8047801B000B2060A84202D240194008206040F6C411814204D3B0F577 +:201B6000967F02D24FF49671216070BD70F200208C01001070B500260D460D4B467134463E +:201B80001E202A7B13F8011F8A4204D0401E04F10104F7D102E02846FAF7EEFB1E2C06D12C +:201BA00006202C686873607B3146FFF707FB70BD5B010020F8B504F0BDFE0D490B4FCA685F +:201BC0000C684B680D698E6882EA92024C60ED19CE6082EA42028B6082EA04120D61544073 +:201BE0000C6005F027F828460019F8BDC5870500741A0120B0B50D46044604F09BFEA7688B +:201C0000294697B1226923689A5C0A7021696568A268491C521EB1FBF5F3A2606B43C91A2A +:201C2000216105F007F8A068B0BD05F003F84FF0FF30B0BDC8B50E4601460A4807780020E5 +:201C400077B1094A12788A420ADD06B9074E084A0C2011FB00200168C9680A4631469047D6 +:201C6000C8BDC046B30B012060830200EC8402009087020008B5014608780D2804D00C28C9 +:201C800014D14868C83000E0486878B1027802F00302032A0AD1807800F00300032805D199 +:201CA00003480078FEF79EFD012008BD002008BDC40A01203EB505460EE06A6AAC6AA41A43 +:201CC000082C28BF0824E869694680182246F7F71DF9686A00196862A86A696A884206D976 +:201CE00003486946FEF7F0FDB0F1FF3FE5D13EBD74190120C8B50E4601460A4807780020C1 +:201D000077B1094A12788A420ADD06B9074E084A0C2011FB00200168C9680A463146904715 +:201D2000C8BDC046B40B012064830200848402009C8702000C480E49007802280ED030F0D5 +:201D4000010003D109480078800807D30846007840F6C4124FF4807104F0AEBD0846007858 +:201D60004FF48071FDF774B9E504012082010120CB0301203EB504460C486D46016840681C +:201D80002960002C686014BF201C684604F0C4FA04B12546064C2946204604F0B1FD7120DD +:201DA0000821224604F0C0FC3EBDC0464C8502002C05012038B505460C46E22D02D10A48FE +:201DC00004F09EFD522D05D1207818B908482638007838B105480068D0F830242146284601 +:201DE000904738BD012038BD1CDC002014010020120501200E4830B50468ADF1140DA4B1C1 +:201E000000252079A11D12228DF800000DF1020003F0C4FE2946082014226B4601F038FB36 +:201E200024686B1CDDB2002CEBD105B030BDC04664F200202DE9F84306460D4890F80090F0 +:201E40005FEA030814460D4610D0A01CC0B203F07DF8071C0AD0B81C2246414603F09EFEBC +:201E60003E70484639467D70FEF7BCFCBDE8F883680601207CB50E4C0125032601288DF8D6 +:201E80000050A17984F82E600BD0032904DBE06801F0C4FD002001E0491CC8B2A07129468E +:201EA00000E0002130462A466B46FFF7C3FF7CBD6806012010B56FF001000C490C4C0870C0 +:201EC0002068D0F8E800006878B16068C068012101702068D0F8DC04804704F02BFD04F0AF +:201EE000A9FE6168C9680020087010BDB10A01201401002008B50346104603F03FFF012914 +:201F000007D00121022A01FA03F120EA010007D109E00121022A01FA03F141EA000002D0A7 +:201F20000249086008BD0249086008BD04180120001A012038B50D480D4C01680A48083C9F +:201F4000056860682A1A2078800092FBF0F0D1F8D420527BD1F8EC1051F8221000F04AF887 +:201F60000846656038BDC0460806012014010020E00000200E4870B50068E830016809681A +:201F80000A4C4D6804F108010968A94202D8D0F86404804704F0CEFC0646E5602846F9F75E +:201FA00069FC304604F046FE70BDC046D8000020140100202DE9F0410D4C4FF6FF77054608 +:201FC0001426A7F101081C3C34F81C0F854203D0AF4208D1804506D0A01C03F06CFA10B99A +:201FE000204603F05DFD761EEED1BDE8F081C0469C0400201CB50A1C17D000230124E407EE +:20200000A04238BF041C944201D95200FBE790425B41904228BF801A914201D25208F6E745 +:20202000191C021C081C111C1CBD00B1C843FFF79AF91CBD98B50C4604F0CEFA002700B1D2 +:2020400001270B4A18329069211AB1F1004F08D8011B891DC90F05D1801DA04288BF041C5E +:2020600000E0841D14600FB904F0BCFA98BDC04600200940F8B504F04DFD002808BF00203B +:2020800013D00A480768002F0DDD0948046800250020294604F0A2F80646B068A0476D1CB0 +:2020A0007F1E7060F4D14FF0FF30F8BD8088020098880200F8B50646346817460D4604F066 +:2020C00039FC94F8251021B104F0B4FD4FF0FF30F8BD012184F8251004F0ACFD28680FC899 +:2020E0000C3484E80F003A4630462946EEF758FAF8BD9EB50090171C01914FF000008DF868 +:20210000080010D00346009A01999C5C595C9DF808207F1E03F1010381EA040142EA0102BC +:202120008DF80820EFD19DF8087007B901209EBDF0B514460D4606461F1CADF1340D08BF6A +:2021400000230DD0684600213022082304F0DEFC7B680893386805903A7AADF818206B4670 +:2021600030462946224600F06FFB0DB0F0BDB0B5046860680D4608B1642D01D90020B0BDB1 +:20218000216864226943B1FBF2F7394604F00DFB3946002806BF84F853500120002000297F +:2021A0000CBF0021012184F85110B0BD98B50446617820784018F7F703FF071C13D02278D7 +:2021C0000021F9F70BFE4FF6FE70788004F0F8F9B8802078C01938616078387502F0D2FCCE +:2021E0007875A0783876384698BD00F003028A70C0F38302CA70C0F381120A71C0F3402222 +:202200008A71C0F300224A71C0F380224A77C0F3C022CA71C0F300320A72C0F3403281F84E +:2022200031208013C0B270472DE9F84316468846044602F0EFFC27688146002005462FB14E +:2022400000E0401C57F80C7C002FFAD1864204D92046414601F090FD0125484603F065FE57 +:202260002846BDE8F88398B503680021D9629F690FB10221397093F8301002290DD001292B +:202280000FD19A692AB91C69D96ADA699B6AA04798BDDC68D96AA04798BD03F1340004F04D +:2022A0005FFB98BDB0B500F00AFB071C18D0002410E007EBC400401C054604F0F1FA38B1D1 +:2022C0000079012818BF022802D12846FDF7F8F9641CE4B23878A042EBDC3846FFF7CAFB8D +:2022E000B0BD38B505462C68B4F85610A06804F017FBA06804F016FB284603F076FBB4F8FA +:2023000058004FF6FF71814209D040B1401EA4F85800B4F8580010B9284602F0F5FD38BDBD +:2023200038B50C4C2169054699B1606988B1A06978B16888884760B907490A6868889101E9 +:20234000A1EB820162699047012802D1A1696888884738BDE4020120BC80020010F1240F99 +:2023600000F1240103DB1C28A8BF3F2100E00021032001F00F030F22A0EB2110C3F10F0186 +:2023800002414FF6FF7343FA01F0024B40EA02401860704718A00C4070B50468002584F8F7 +:2023A000515094F85210012907D094F853602946FFF7DDFE84F8536005E094F854002946AB +:2023C00003F0D2FF012094F85010022918BF84F8505070BD38B50B4C207888B10A4D2878D5 +:2023E00060B1022806D0012804D008480068D0F84C0580470020287003F0B4FC002020702C +:2024000038BDC0466E1B0120B50B0120140100202DE9F0411646054698460C46F01C02F0E5 +:2024200095FD071C0DD03E707D70BC7026B1F81C32464146F6F76AFD034800783946FEF7CE +:20244000D1F9BDE8F081C046651B012030B58578C41CADF1240D204603F02DF800280CBFF3 +:202460000020201C627A217A01EB0221FAF7DCFD01466846FAF733F8672024226B462946B2 +:20248000FFF7C6FF09B030BDB0B50C4C002520800F46658010B1216901B1884747B1E26811 +:2024A0000748E188057022B121B9114638468847E18811B16069F8F7BDFCB0BD04FC002075 +:2024C000B60B0120F8B54FF08057064607F5EC7420680A4D81682846884700F00300306027 +:2024E000D7F8D801426800212846904720688168284688470028F9D1F8BDC0460040034046 +:2025000000B500211822ADF11C0D6846F9F766FC02208DF808000848C18FADF80010B0F838 +:202520004800ADF80A0000208DF81400684600F07DF807B000BDC046500101200D4B70B56F +:202540000D4606460824B3F9300085420BD13046194603F039FF30B11AB193F83300024283 +:2025600001D0184670BD641E03F15803EBD1002070BDC046B0F40020F8B51C4615460746A4 +:2025800004F0D8F99FB107F1280106C907F1280307F120062943224383E8060096E806002F +:2025A00007F120030D4344EA020683E8600004F041FBF8BD10B58468207DFF2801D001F093 +:2025C00037FC607DFF2801D001F032FCA07D0021FF2802D0E27DFF2A00D141B1FF2801D05A +:2025E00001F026FCE07DFF2801D001F021FC10BD30B5054600211822ADF11C0D6846F9F7A8 +:20260000EDFB00240620214618226B46FDF710FA38B9012D05D10620214618226B4600F0DB +:2026200037FF641C032CEDDB07B030BD30B5002405461822ADF11C0D21462C756846F9F74E +:20264000CDFB0A226846294603F0A8FA6889ADF80A0004480068D0F8F812684688472046CB +:2026600007B030BD1401002038B50D4C083CA068D0F8C81301208847054600208DF800006C +:20268000A068D0F83024694656209047A0680349D0F83024E2209047284638BD1CDC002056 +:2026A0001401002008B5002101288DF800100FD00A4A907840B1506A30B1917003F0D2F8C4 +:2026C000322003F07BF808BD0320E4F755FF08BD032001226B46FFF7ADFB08BD680601207D +:2026E0000D4B10B51B6801EA03048C4218BF6FF0040010D180684068884298BF6FF003004C +:2027000009D98918884202D31340934202D06FF0050010BD002010BD081B01200D480021C5 +:20272000001F01700748084900680988D0F8D420D184D0F8D400054AC18C11800449C08CFD +:202740000880704714010020A60601201A06012046010120B8180120F8B50F1C044616D096 +:202760000B4E0025786831680019E83178600A681268BA4202D1002848BF7D607868002889 +:2027800002D5D1F8640480473F68002FEAD1F8BD1401002098B50D4CA168D1F8B800077840 +:2027A0009FB1C7698FB1086C0268D06D28B102210023B847A168086C0268106E28B1D1F819 +:2027C000B810CC6900230821A04798BD0C010020F8B504460C480768AFB10026062538683C +:2027E00001888C420CD13E817989C90803D3387B01F06CF838687D73407BF021FEF7DEFC0A +:202800007F68002FEBD1F8BDE40A012030B50D4C2468ADF1140D94B1E46984B101258DF827 +:202820000850ADF80A00ADF80C10089D009502AD95E80300A047012818BF002000D10A2065 +:2028400005B030BD00DC0020F8B507460A480B4C0668E0698D00285886420AD108480090F0 +:20286000384604F04FF9E0692858864218BF381C00D10020F8BDC046C87302001C000120BC +:20288000800901201FB5044620880822A11C8DF8000000128DF801000DF1020003F07EF95A +:2028A0006089CA210C226B468DF80A0000128DF80B004520FFF7ACFD002000901FBDF8B5F7 +:2028C0008469C08948F21F01814208BF641C2778F800401CF7F774FB061C0BD0751C3770D9 +:2028E00047B1641C2846214604F00AF8083408357F1EF7D13046F8BD10B50024ADF1180DE0 +:2029000013E001A800902146002214230820FFF77DFF40B99DF80400FF2804D00DF106019F +:202920000022FAF7B7F9641CA4B2002CE9D006B010BD10B543689B6801EA03048C4218BF8C +:202940006FF0040011D180684068884298BF6FF003000AD98918884203D302EA030090423A +:2029600002D06FF0050010BD002010BD0EB50346042003F051FD18788DF8000058888DF87C +:20298000010000128DF802009888C62105228DF803006B4600128DF804004520FFF738FD0B +:2029A00000200EBD7CB50C4D0646002401E0641CE4B2E878A042D8BFFF200BDDE8686103A7 +:2029C0006A46042303F0E2FE009800F0FF008642EDD120467CBDC046C01900200C4880B519 +:2029E0000168886800E0384647681FB101F13802BA42F8D1407B10F00F0006D1498F40F601 +:202A00000900884208BF012000D0002080BDC0466CF20020B0B50446242002F097FA074687 +:202A2000094805787FB1322038702078B87060687860A1681B2207F1080003F0AFF82846F0 +:202A40003946FDF7CFFEB0BD1C0701203EB515460F220B4C8DF808204FF6FD72ADF8002089 +:202A60006268107000125070901C03F049FF606813220B23694685722046FBF70DFB3EBD27 +:202A8000280401202DE9F0411D4616468846044603F0CAFC071C0FD0062002F057FA011C8A +:202AA0000AD0FD2008704D708C708E8081F8038078680078FDF796FEBDE8F081C8B5FE294A +:202AC0004FF0000608BF0126094A17686FB1FA88904207D1002E18BF387907D13A798A4298 +:202AE00008BF01263F68002FF1D1FE20C8BDC04664F200201CB500200B4C8DF80000042040 +:202B00008DF80100012060716846F8F771FD20784FF48051FCF706F820784FF4805141F2B6 +:202B2000883203F0C9FE1CBD6806012038B58468456894F8380001F07BF994F8390001F054 +:202B400077F994F83A0001F073F995F8F900012803D095F8FB00FF2803D095F8FB0001F065 +:202B600067F938BD38B50C46054600F043FC0A49A04204D2084602682046DC3205E00846DD +:202B80000268DC3250680068001968601168D2F810242846904738BD140100200C48083842 +:202BA0008268D2F8D820002111608268D2F8DC2011608268D2F8E0204FF4700313608268EF +:202BC000D2F8E42013608068D0F8E8000160704714010020094908B5012008700A48863817 +:202BE000006818B10649088B401C0883F02000F099FB04480078E9F7F9FC08BD641B012049 +:202C0000D8180120051800204601012098B504460B48006888B10746B86804420AD0F86886 +:202C20003A690021034620469847002818BF4FF0FF3003D13F68002FEED1002098BDC046F1 +:202C40005018002010B50C1CADF1380D13D001466A462046F0F7CEF99DF8060058B19DF8F5 +:202C600001209DF81C300020214602F0EBFF002818BFA42000D100200EB010BD38B50B4C6C +:202C80000D4694F8961081420EDA00F091F908482146058091F82B200878642313FB02F271 +:202CA0004FF4007103F008FE38BDC04650010120EC020120F8B50C4E446885680F4608E00E +:202CC000216B0870606B216B7F1E401C6063491C21633FB130680069014628688847B0F1BC +:202CE000FF3FEDD13846F8BDD001001010B50C4601461022ADF1200D684603F0F9FB04A828 +:202D000003F09DFD10200790CDF810D004A9044805940068069403F0C0FD08B010BDC046EB +:202D200010DC00202DE9F0410F46044603F04CFA04F1280292E8600033462A46F6F796FB08 +:202D400080460B4642462846314603F077F817B1303484E803004046BDE8F0811CB50C4C2D +:202D6000A06838B9684603F04DFA01206946EFF7A9FFA0602178012909D040B1E178012904 +:202D800002D0FFF709FB1CBD642100F071F81CBDCCE80020F8B5446885680F1C11D00A4E59 +:202DA0003068216A826909782868904748B1216A606A7F1E01F10101216200F10100606207 +:202DC000EED13846F8BDC046D001001038B50C4605460021012203206B468DF8001003F0F0 +:202DE000DFF970B9FF2D19BF9DF80000A0439DF80000204301216A468DF80000032003F0F1 +:202E000093FC38BD0246107800280CBF00200120517809B140F00200917809B140F004007E +:202E2000D17809B140F00800117909B140F04000517909B140F08000704738B50E20F7F7AF +:202E4000BFF8041C12D0FF210E22F8F7C7FF002507E0294602200E222346FCF7E9FD6D1C1C +:202E6000EDB2002DF5D02046FEF704FE002038BD10B5046894F85220012A03D0FFF777F9BC +:202E800030B910BD94F85400012103F06DFA012094F8501002291CBF012184F850100121ED +:202EA00084F8511010BDF8B54568066803F042FD0746307870B1287903F0CAFB012806D1FF +:202EC000286800244460301D03F032FD34702879F3F7C8FF384603F0ADFEF8BD10B5FF217F +:202EE0001422ADF1180D6846F8F778FF002401E0641CE4B2002C18BF002008D1214608201F +:202F000014226B46FCF794FD0A28F1D10A2006B010BD014600B50420ADF1140D8DF8000041 +:202F2000087A022806D001A803F0D4FA6846FAF7DFFE05E00888ADF802006846F8F788FFE9 +:202F4000BDF80C0005B000BD0A4938B5402205680A60802008600024C1F8FC4295F82600EF +:202F600020B1054803F0FCFC85F82640022000F07DFC38BD044402404C16012010B50A4CBD +:202F8000606820B16068FEF775FD0020606002F033FA064C206B30B141682163FEF76AFD23 +:202FA000206B0028F8D110BDFC090120E402012030B50B4C0546ADF1140D84F896506A4643 +:202FC00014342046FCF76CFA68468DF81250FBF7F3FB45202146FEF7EDFE05B030BDC04621 +:202FE000500101200A46014610B5101C0ED069B1074A0323C2F88437D2F88C3713F0030F51 +:20300000FAD1044C012323601160906010BDC046044002400000484210B50A4941F8980CB5 +:2030200008684FF0805440F003000860D4F8B80181692020884704480068D4F8B801806BD0 +:20304000804710BD242208402C20094084460B4838B5028881B1051D4FF48774AB5C521C1E +:20306000491E0CF8013B92B292FBF4F303FB04F3A2EB0302F2D1028038BDC04638FE0020D4 +:2030800038B514460546042211FB02F21846091D02F0FC028DF800208AB22946FCF776FE4D +:2030A00002460121684603F0A9FA84420CBF0020022038BD10B5FEF745FA012000F07EFF13 +:2030C000044603F037FC074A116831B103F0B2FD34B1204603F0C8FA10BD146003F0AAFD57 +:2030E00010BDC046141B012038B5044603F022FC084905460878A04308700878000904D28F +:2031000005480821E03003F033FC284603F092FD38BDC046661B012068F20020F8B51646F7 +:203120000F46044603F006FC05460848001D0068A04205D13846314600F0FEFE044600E018 +:203140000324284603F076FD2046F8BD68F200200C2838B512DA002808BF00240CD0921E33 +:203160000346002403F02CFA32F8025FA84203D05B1E04F10104F5D1A14201D0002038BD7F +:20318000012038BD0B49891F8A7992080ED3084A127882420AD00846017901F0F80141F042 +:2031A000020101710C21817101F0FEBC7047C046EA040120521A01200B4908B509780229BA +:2031C0000FD101280DD10748007850B900F0E6FC03F068FA18B90020FEF74CFE08BDF8F72D +:2031E000DBFF08BDCF030120E50401203EB50225ADF80000094B8DF808505C6804F8010B77 +:20320000001204F8010B184604F8011B0423694622700122FAF740FF3EBDC0462804012015 +:203220000B4A98B50021283A176801606FB1BF1F03224FF6FE7437F8063F9C4203D1076022 +:203240000846387198BD521EF5D1C82098BDC04604E900201CB50B4C21722178012803D04C +:2032600000200121607107E008464FF48051FBF759FC002184F8371001206B460246FEF7B8 +:20328000D9FD1CBD68060120BCB50B4C0546AB2021888DF80000284602F0CFFF01216846E6 +:2032A000FDF77CF821880746284602F0CFFF17B92846FCF739FBBCBD101B01207CB50546DC +:2032C00009480A4C007821888DF80000284602F0B4FF01216846FDF761F82188064628460E +:2032E00002F0B4FF30467CBD67800200101B012080280BDC012803D0032818BF802801D13E +:2033000001207047022805D1022070478428B8BF042006DB842801DB862801DB00207047EB +:203320000320704738B50546EA2D12DBF42D10DA084C083CA068D0F82824694628469047C4 +:203340000098A368401C0090D3F8302469462846904738BD1401002010B5094C94F90000FA +:2033600010F1020F0BD00848064B4238006894F90010826B186890476FF00100207010BD3F +:20338000B10A0120B40601201A0601200A4808B50068D0F8B800007800280CBF0120002092 +:2033A00000F00EF8054991F9000018B191F90000401E087008BDC04614010020B80A012033 +:2033C00038B5054603F0B6FA044600210220FBF75DF9074800688369044800684FF0FF3177 +:2033E0002A469847204603F025FC38BDB4060120D805012038B503F09DFA054608480068BC +:20340000084CC06B8047083C6168401A21788900B0FBF1F4284603F00DFC204638BDC04682 +:20342000D8050120E00000200A4908B5888B401C888303F07FFA08490A78862A02D003F050 +:20344000F9FB08BD87220A7003F0F4FBE920F6F7E7FF08BD04180020741B01204FF6FE706E +:2034600038B5411C00F020FF011C0DD1074C1425A07C08B1607C18B9208800F03FFA2146B2 +:203480006D1E04F11C04F3D1084638BD9C040020BCB50B4D2F68002487B17F6977B10125D3 +:2034A0008DF80050ADF80200ADF804109DE80300B84718B10A280CBF09240A242046BCBD50 +:2034C00000DC0020F8B50B4E456884680F4606E005F13C02C1B21046FDF7DCFE7F1E3FB1BE +:2034E00030680069014620688847B0F1FF3FEFD1F8BDC046D00100100B4910B5096849B16E +:203500000B7C002201E0521CD2B2934204DC09680029F5D1002010BD01EBC204E47EA04237 +:20352000F1D1084610BDC046F00A012038B5B1F1FF3F044608BF05212020EFF3118580F35E +:2035400011880120054B61618840A061586903F0D5FAA06285F3118838BDC046B0FF002076 +:2035600030B50D4601460024ADF1140D01A88DF8004002F0AFFF6846FAF7BAFBBDF80210C0 +:203580004FF6FE72204629808A4218BF012005B030BD1FB504460822208861688DF80000C3 +:2035A00000128DF801000DF1020002F0F7FA217A0B226B4601704520C821FEF729FF00201B +:2035C00000901FBD70B516460C46054601F022FB2968A14219BF54F80C1C46F80C1C54F8E1 +:2035E0000C1C2960002144F80C1CFF2104F8021C02F09BFC70BDF8B58C46071C164611D0C6 +:2036000000245EB13CF814109A1E304632F8025F8D4208BF012006D0401EF7D17F1E04F121 +:203620000104EED10020F8BD70B5044604F128020CCA0846002102F001FC04F1300292E88E +:2036400060002D1846EB0106290C30040143FEF7F1FC383484E8600070BD10B5044603F097 +:2036600049FA034603E0184603F040FA03469C4208D0986803F0B2F99042F4DA184603F0C2 +:2036800065F810BD204603F0BDFA10BD0A4980B50A1D1768874209D057B1F968884202D04E +:2036A0000F1CFAD104E0C168F96001E0FA684A60FEF7E0F980BDC046800A012038B50C46C6 +:2036C000054602F03BFA0146284602F057F9012804D028462146FFF743FF38BD02480088B0 +:2036E0002080012038BDC0468A01012038B5044600F0AEFF0546012D0CD10748A289036853 +:203700002478910001EBC2015A5CC818A2435A5402F025FF284638BDE00A01200A4908B510 +:203720001420F9F7F5FF1420002102F01DFE012003F0B9F81420012102F016FE4FF40C702F +:2037400003F0B1F808BDC0460162002008B503460948007801280BD006481978007809B993 +:2037600008B905E020B94520CB210122FEF750FE002008BDFC0901208C0A012070B50346E3 +:203780000E4601F099FCB04202DA01F095FC0646054C65881846324661191831F5F7B6FB3F +:2037A000AD19A8B2608070BD04FC002038B50A460C460546002101F04BFF07490C39487831 +:2037C00040B97C2C08BF81F833500C2015FB001080F8464038BDC046CC190020F8B50A4C38 +:2037E000054620680E4617464FF0FF3102F052FD284631463A46FBF73FFD0546206803F03C +:20380000AFF82846F8BDC046001B0120F8B50A4C054620680E4617464FF0FF3102F03AFD7D +:20382000284631463A46F3F76DFE0546206803F097F82846F8BDC046141B01200EB50949EB +:203840000A68917969B913680749C268096831B10193029240788DF8000068468847FFF7AA +:203860008DFB0EBD000A01203007012010B5044603F060F8084B1A1992F84311491EC9B2D2 +:2038800082F8431121B99A680121A1408A439A6003F0D0F9002010BD5018002038B504464C +:2038A00003F048F8084A02F108031D680121A140A4182943196094F84311491C84F8431147 +:2038C00003F0B8F9002038BD501800200A4938B500221E230C4614F8015FA84204D05B1E0F +:2038E00002F10102F7D138BD002308462370713040F8223038BDC0465B0100200A4938B52F +:20390000642203254FF6FE748B795B0807D24B88984204D14B79012B04BF4D714C80521ED3 +:2039200001F10801F0D138BDCC06002007480068400909D20748064B074A016803EA912011 +:20394000824208BF012000D000207047B04F0050F1FF0F0050130050F00107001CB54FF00B +:203960008054D4F8CC014068014602208847D4F8CC110090486801460120884701900248FF +:203980006946FCF7ABFA1CBD74190120C8B50F46016887B17E6876B13A78042A0BD1BE68F7 +:2039A0004EB100224A628F617A68CA61BA688A62F3F7B8FAC8BD6FF00200C8BDF8B5044631 +:2039C000094805780E46022001F0C0FA071C09D01EB13146022202F0E1F83C70284639462E +:2039E000FCF700FFF8BDC046CB03012010B504461022ADF1200D04A9684602F072FD064815 +:203A000000686946FFF7C2FF01991022204602F0C5F808B010BDC04614DC00200A4A10B543 +:203A2000D3680146181C0ED0814204D0044680690028F9D110BD834219BF8169A1619969DE +:203A4000D160FEF717F810BD680601200A4A323A92F83210884202D1517801290AD00128B6 +:203A60001CBF002182F82F10323210700121552002F05ABE7047C0469A06012080B5071C36 +:203A800014BF80210021074B188F4FF67F7202401143054A08431887117867F3C711117057 +:203AA00080BDC046D40501202C010120094810B500240470FFF76AFCFAF756FB0649486830 +:203AC000C068007828B90868D0F8582420460146904710BD701B01201401002010B50A4C64 +:203AE0006068C068007828B92068D0F8582400210120904702F01EFF03F09CF82068D0F8B2 +:203B0000B800806E804710BD1401002008B502F011FF084A517841F00201517003F08AF8F2 +:203B200005480068D0F8940000780021FBF790FA08BDC046D80000201401002038B5044630 +:203B400009480068D0F8D85002F0F4FE296831B1A14208BF012403D009680029F8D100243C +:203B600003F068F8204638BD14010020F8B5061C0D464FF000040CD0074807684FB13846E5 +:203B80002946B047012803D07F68002FF7D100E03C462046F8BDC046E40A012038B5094D10 +:203BA0001424284601F07CFF1C35641EF9D106494FF6FE72002303204A80401E01F8043BAC +:203BC000FAD138BD9C0400202403012010B502F089FF02F0DBFF032002F080FF06481030F0 +:203BE000006830B1034C204602F04AFD204602F04DFD10BD439001008CFF002008B502F0F1 +:203C000089FF012801D002F065FF074802F05EFF01F00EF902F056FF02F050FF02F04AFF73 +:203C200002F044FF08BDC046CD3B0200084910B5002008600120C861064C2060216844F8FB +:203C4000280C05480068016A14208847206810BD000024432C200940B001001030B50025F1 +:203C6000ADF1240D0848009502AA01930B46294602F018FF041C03D002A902F003F9254690 +:203C8000284609B030BDC0460C85020030B503460025ADF1240D0848009502AA01912946C3 +:203CA00002F000FF041C03D002A902F0EBF82546284609B030BDC0460C85020030B500257E +:203CC000ADF1240D0848009502AA01930B46294602F0E8FE041C03D002A902F0DFF8254686 +:203CE000284609B030BDC0462C85020038B50446EFF31185202080F31188A08A012809D1CF +:203D000002F09CFFE168A368081A834203D22169814200D2002085F3118838BD10B5041CDC +:203D200009D10024052021461022FCF727FC641C282CF7DB10BD21780520102201F07F01DD +:203D4000FCF71CFC0020207010BD98B5044600F061FF2168002908BF002709D051F80C2CFA +:203D6000002322600F4641F80C3CFF2401F8024C02F0DBF8384698BD38B50C46054600F04C +:203D800049FF6CB1002144F80C1C296811B92C6006E0114651F80C2C002AFAD141F80C4C0E +:203DA00002F0C3F838BD38B50C46054602F0C2FD22680346002442B12846114602F004FB86 +:203DC00000B114461268002AF6D1184602F032FF204638BD00B51022ADF1140D8DF8001056 +:203DE00001460DF1010001F0D9FE3B2011216A4602F09AFC002111226846F7F7EFFF05B05D +:203E000000BD70470346094810B5001D006858B1C479A34205D18488A14202D18479A242A6 +:203E200003D0C0680028F3D1002010BD800A012010B5044601F06AFE07480838006850F85C +:203E400024102046F9F764FC0021204601F06AFE204602F081FA10BDF086020038B50C4641 +:203E6000054602F067FD0749891C01EB85010A78C4F3024322F007021A430A7002F0DAFE00 +:203E800038BDC0460010084038B50446084800780D4630F0010009D12046EFF749FC21468A +:203EA0002B464FF6FD700D22F8F7DEFA38BDC046E504012070B5094D95F88A4064B102F00B +:203EC0006AFC4FF47A7600F07F0016FB040228784FF4807102F0EDFC70BDC046500101206F +:203EE00010B5202918BF6FF0010009D141688368044A4C681B8C146003490B60FDF7F2F85D +:203F000010BDC0460C1B0120101B0120074898B5007838B1064C074654F80C0B006980470B +:203F20007F1EF9D103490120087098BD5C830200A0850200B10B012010B50C46084924313E +:203F40000978022918BF012009D100F051FE04B1206000F0FF0001280CBF8120022010BDFC +:203F600068F20020094A38B50346082400205A325588AB4202D11578A94205D0641E02F107 +:203F80000A0200F10100F3D138BDC0462001002030B50D460446242208230021ADF1240D40 +:203FA000684602F01FFE012029466A468DF81800204602F013FE204609B030BD10B50446E3 +:203FC000002124220823ADF1280D684602F00AFE044A012069468DF81800204602F05EFD66 +:203FE0000AB010BD80090120074810B5002407490460032008600220FFF738FC0820F2F7BC +:2040000031FF0348047010BDA802504210800240AD0B012038B5094C0146E07850B1C878DB +:2040200040B9487830B90448002505800120FAF703F9E57038BDC046E40101201C07012040 +:204040008CB58DF800000848001D0068027004AF43701A1282700022C2703A8804236846E4 +:20406000FAF71AF88CBDC046280401201FB514460222ADF8020001A88DF8002002F02AFA44 +:204080006846EFF7C1F8012814BFC8200020BDF80C10218000901FBD98B5094B00221F68A7 +:2040A0000A6057B1BF1F032337F8064FA04204BF0F60101C02D05B1EF6D1C82098BDC04671 +:2040C000DCE8002010B5074C207838B9064807494FF4B472F4F71AFF0120207001F027FA8D +:2040E00010BDC046B70B01204C400021F4760200094A10B512686AB11379984218BFFF28E0 +:2041000005D1931D1C88A14208BF181C03D01268002AF1D1002010BD64F2002010B5FF2116 +:204120001422ADF1180D6846F7F758FE002407E02146082014226B46FFF7AAF9641CE4B264 +:20414000002CF5D006B010BD38B5094B00200E2401460AE011FB04F29D5CFF2D03D0D21843 +:204160005279121890B2491CC9B20029F2D038BD2201002038B5094C0546B92021888DF871 +:204180000000284602F059F801216846FCF706F92188284602F05AF838BDC046101B01200A +:2041A000094A10B5ADF1180D009100240290114608680194694602F00CFB002814BF201CA2 +:2041C0004FF0FF3006B010BD0C1B012080B5071C04D107480068D0F84C05804702F0AAFB4B +:2041E000044A1178B943117002F024FD80BDC04614010020701B012010B5041C04D107482B +:204200000068D0F84C05804702F094FB044A11780C43147002F00EFD10BDC0461401002026 +:20422000701B0120084838B50068D0F8E000046802F080FB0546054804602046F6F722FC3F +:20424000284602F0F7FC38BD14010020E000002038B5094C0546206B28B101888D420AD0BE +:2042600040680028F9D10820F5F7AAFE216B10B105804160206338BDE402012080B5071C9E +:2042800012BF78680748006850B14289120B04D339B102681288914203D040680028F4D1CD +:2042A000002080BDE40A0120094A38B514234FF6FF7532F81C4FA04205D15489A14214BF82 +:2042C0008D42101C02D05B1EF3D1002038BDC046800400200246094838B5002114234FF6F2 +:2042E000FE7430F81C5FAC4203D08A4204D0491CC9B25B1EF5D1002038BDC046800400206A +:204300000EB5094909680346002061B18A6A52B101218DF80010ADF80200ADF804309DE8E9 +:204320000300904780B20EBD00DC0020F8B5057C002301E05B1CDBB29D42D8BF00200ADDF7 +:20434000DE0084191B342778B942F3D1617880190A4316306270F8BD027A0B7A93420CD1F6 +:204360005AB1022A07D1098800880022814208BF012210467047032A01D00020704701F073 +:20438000FDBA704708602E2088800020888102A0886008467047C0467B756E6B6E6F776EA8 +:2043A0002D696E7374616E63652D6E616D657D000860322088800020888102A0886008466D +:2043C0007047C0467B756E6B6E6F776E2D696E7374616E63652D6E616D657D0038B520209B +:2043E000EFF3118580F31188064CA068002102F051FB6169081AA169814238BF002085F338 +:20440000118838BD4CFF002010B5094C034600E00834208850B18342FAD16088814205D16A +:2044200060680B4611461A4601F0B8FB10BDC04664750200F8B516460D46044602F07AFA4E +:20444000024629463046086043684B60476807B9274639604160104602F0ECFBF8BD10B5B2 +:20446000041C0FD0207A022818BF03280AD12046F5F74AFFFF2805D0227A0021FDF73AFD1D +:20448000002010BDE82010BD00B5817EADF1340D8DF81210C27E8DF813204188ADF80A10A0 +:2044A0008188427DADF80C106846EDF7CBF90DB000BD70B514460E460546002201F046F933 +:2044C000FF280AD02B2E19BF40F22B2141EA8421A10241F02B0145F8201070BD10B51446A3 +:2044E000024602F06DF802F06BF890420AD10B2908D12046002100F0C3FB204600211E2212 +:20450000EDF778FF10BD0EB54FF6FE73834203D0002918BF934201D101200EBDADF800002A +:204520000191ADF808206846F4F7B8FB00200EBD1FB50C46014602208DF8000001A801F037 +:20454000C9FF6846F9F7D4FB012814BFC8200020BDF80C10218000901FBD4A0824BF0122EC +:204560000270CA0824BF012242704A0924BF0122C2708A0924BF01220271490A24BF012150 +:20458000C171704710F15A0F05DB10F1140FC8BF6FF0130001E06FF05900332141F2EE12AB +:2045A0000E2310FB012191FBF3F0C0B27047FEE7C8B507460748466857B116B9476004E0F7 +:2045C0000646F0680028FBD1F760B9710020F860C8BDC046800A012038B5458940684478F5 +:2045E000062000F0B3FC01460448007829B108220A704D800C71FCF7F5F838BDCB0301205F +:20460000044805494160054981600549C160054901617047B408012001C20000B9CF010031 +:204620000D690200158B0000074A517828B90020106208460121FAF775BA044B1362024639 +:204640000846012102F038B9E00601200F6802000146084B89891A8800208A4208DD8A00DE +:2046600002EBC1025968895C11F00F0F18BF01207047C046DC0A01200849091F088850B1FF +:2046800049680C3911F80C2F12F00F0F08BF002002D0401EF6D101207047C046E00A0120F9 +:2046A00038B5084C002233232579A84203DCA942A4BF521CD2B25B1E04F12404F4D11046E9 +:2046C00038BDC0462C100020084933220B79052B05DA002808BF081C06D0401E80B2521E61 +:2046E00001F12401F2D100207047C0462C1000201FB5FF210E226846F7F770FB002407E071 +:20470000214602200E226B46FEF7C2FE641CE4B2002CF5D000901FBD70B5084E00240E2535 +:2047200008E0214614FB056302202A46FEF7B0FE641CE4B2002CF4D070BDC0462201002002 +:2047400070B5084C04EB800425680E4602F0F2F805F0FF053146A94218BF217002F06AFA97 +:2047600070BDC0460010084038B50C4601466BB1091F002051F8045FB5F1FF3F06D0154009 +:20478000AC4204D05B1E00F10100F3D1FF2038BD084910B5087860B139310246002311F88F +:2047A0000C4FFE2C08BF181C03D0521E03F10103F5D110BDC31900201CB55B1C8DF80210D0 +:2047C0009624ADF8002099008DF803406A46042389B2FCF71FFB014908701CBDC119002045 +:2047E00010B5044610460A46211C08D038B1C8608A6004480B6100F01DF9002010BD6FF0EA +:20480000020010BD5018002038B50D460446F8F7EBFC05F57A71241AA008814234BFB0F1BF +:20482000405F002003D2401B012898BF012038BD10B50446062000F089FB011C09D0312003 +:204840000870208848806088024B88801878FBF7C9FF10BD1C07012000B5ADF1140D0DF166 +:204860000E01FFF765FE48B902208DF80000BDF80E30ADF80C306846FEF738FF05B000BD08 +:20488000E22808B505D1064A0846114602F038F808BD044A1268D2F82824904708BDC0461F +:2048A0001CDC00201401002001280AD00749887828B1486A18B100208870FBF747BD0021D5 +:2048C00000E001210520E2F757BEC046680601200168084603E0D1F88C0006E08268C26845 +:2048E000D208FBD20222C0F88020C8684008F2D30020C1F88000704710B5041C04D1064840 +:204900000068D0F84C058047044801780C430470F9F75EFC10BDC04614010020701B0120C9 +:20492000084A014603235088814204D11078002818BF012004D15B1E02F10402F3D1002075 +:204940007047C0462403012070B50748074C142506886089864202D0204601F0A1F86D1EC6 +:2049600004F11C04F5D170BD980101209C04002038B50446074801882046FFF795FC0D4666 +:2049800038B101F08DF820462946FFF78DFC0028F7D138BD9801012038B5084D69682C681E +:2049A00024EA010028600C40E00901D3F6F726F8200A01D3FCF726FCAC6038BD902208403E +:2049C00010B5084C38B1064800684068012102462046001F9047206820F03000206010BD9C +:2049E000D8010010044003400EB5014648894A68ADF8000050788DF8020092788DF808200F +:204A000008B9487A10B16846F1F79AF80EBD1FB50C460021ADF8020068468DF80010F7F740 +:204A200017FA01A9204601F055FD204600F043FD00901FBD38B50D46044601F07BFF0021FA +:204A40002A462346116059685160596801B921460A605A6002F0EEF838BD38B50C4605463D +:204A600001F068FF00212B4622461C6851601460196801B929464A601A6002F0DBF838BDB3 +:204A800038B50D46044601F055FF2A46116801B9214653684B60516801B9214612680A6019 +:204AA00002F0C8F838BD10B58478C078ADF1280DFFF70AFE01466846F7F711FD67202422C7 +:204AC0006B462146FDF7A4FC0AB010BD10B50446022001F0A1FC032001F09EFC0020F0F72F +:204AE0006FFB4520C72101222346FDF791FC002010BD1CB50024032001216A468DF8004056 +:204B000001F00CFE28B90320214601226B4601F047FB9DF800001CBD074A517828B901209E +:204B2000D07008460221F9F7FDBF0023D37002460846022101F0C0BEE0060120428913099C +:204B40000CD3920808D3427B062A05D0E92903D0CD2918BFF02901D1F1F7E0BC0020704747 +:204B600008B501F070FE002808BF002009D0017931B1032904DA8169C161012380F82030D3 +:204B8000012008BD38B5074B9C782546681CC4B29C70284600F0BAFE0028F6D1002DF4D075 +:204BA000284638BDE40201200648017808092CBF03200120890828BF40F004000249087015 +:204BC0007047C046521A0120E5020120054808B50068426801200146904703480349006829 +:204BE000086008BDE001001030200940F008012007490246083908680028FCD10023CB6158 +:204C00000A60C8690028FCD0CB6148687047C0460810044010B501F0B9FF064980B200041D +:204C20002140040C0C4301F085FE80B260F31F44204610BD0000FFFF0749082291F83300F1 +:204C400030F07F0008BF081C04D0521E01F15801F4D100207047C046B0F400200A46064936 +:204C600010B54B683BB18968084204D003490C6801462046984710BD848702006CF200201D +:204C800010B50C460021FCF779F92146F7F7A6FE38B14FF6FE710180418000240471447151 +:204CA000847110BD10B5074CE41F207220B9207810B9062000F0F6FFE0792021FAF7C8F9F4 +:204CC00010BDC046CB03012010B530B14379002201E0521CD2B2934201DC002010BD00EB31 +:204CE0004204E488A142F4D1012010BD064A1068002818BF012006D1044940200860012374 +:204D000048600020D361704704800C4038500C40064902680B390A6042684A6004490268CA +:204D20000A390A60406848607047C0461A060120460101200649002008700648001D006856 +:204D40000069FF2202704FF0FF30886148617047A40601201401002010B504460B2C01DB7E +:204D60001A2C04DD04480068D0F84C0580470148047010BD22010120140100200649487866 +:204D800040F00400487005480068D0F8940000780021FAF75DB9C046D80000201401002043 +:204DA00038B50D460446FEF725FB4019606004480268D2F8D810D2F8EC242046904738BDC7 +:204DC0001401002010B50346002A08BF00200AD05B1E491E11F8014F13F8010F844201D1B9 +:204DE000521EF7D1001B10BD024607480168002041B14B7B9A4212BFFF2A401CC0B2496866 +:204E00000029F6D17047C046E40A0120074910B5142200204FF6FE731C3131F81C4BA342F3 +:204E20001CBF401C80B2521EF7D110BD80040020074808B51030006828B1034801F020FC7B +:204E4000024801F023FC08BD595402006D5E02008CFF0020074810B51030006830B1044C1F +:204E6000204601F00DFC204601F010FC10BDC046731802008CFF0020074908B5283090E887 +:204E80000C000020F4F7F2FA002908BFB0F1FF3F88BF4FF0FF3008BD907E000038B5054680 +:204EA0000024064A0448009429684FF0FF3301F0EDFD2C6038BDC0460C85020049640200F8 +:204EC00038B505460024064A0448009429684FF0FF3301F0DBFD2C6038BDC0462C85020041 +:204EE0005964020007480078022807D0062803D0052806D000F0EABF062000E00220E8F787 +:204F00009FBB70470518002038B505462C6894F85000022808D1A06801F006FD2846FDF73A +:204F20003BFA002084F8500038BD38B5054601F001FD2C6834B121682960216801B92946F7 +:204F400000224A6001F076FE204638BD10B5041C04D004F10C00F5F733F808B9002010BD46 +:204F6000002101600481FF2383720C3010BD38B584690D466178207800EB0120A41C2880F8 +:204F80002146A81C01F0BCFC14F8080FA87238BD08B50B4600F04AFC20B9322018700122F1 +:204FA0005A7008BD00F10C010222184600F0F6FD08BD0C28C8BF01200BDC0628C8BF03209F +:204FC00007DC0228C8BF052003DC002814BF0720002070473EB50546002108226846F6F71C +:204FE000FDFE2846694600F0C9FC0024012818BF012420463EBDF8B516460D46044601F0A3 +:2050000091FD074629463246204601F07CFC384601F010FEF8BD7047012814BF00200120D9 +:20502000044B03491A78087060F345121A7070472C1A00202C01012038B5044614F8030FD7 +:205040000D462870601C01F0EBFA6880E01C01F0E7FAA880601D38BD38B5382101700125E6 +:205060008570FDF7A3F8041C04D02570A57700F065FD6062204638BD0648018840884FF4B6 +:205080008772401A00F5877090FBF2F15143401A80B2704738FE002010B5FFF7BBFD044679 +:2050A0000448826812B1418800209047204600F03CFF10BD8C0701200648418800884FF443 +:2050C0008772401A00F5877090FBF2F15143401A80B2704704FC0020064A08B5126801EBB9 +:2050E0004031012310466A4601F050FB9DF8000008BDC046CC19002010B54FF6FF700C46A9 +:20510000A04205D0EFF78EFE0249E0B2F8F700FB10BDC0460160002038B5064D05242D1D98 +:205120002846FF210422F6F759FE2D1D641EF7D138BDC0462C01002010B5401E491E4AB116 +:2051400011F8013F10F8014FA34218BF002002D1521EF5D1012010BD08B5002808BF05200A +:2051600009D010F8021CFF2918BF042003D10C38FCF780FC002008BD38B5054601F0DAFBA3 +:20518000044604482946FFF77BFC204601F052FD38BDC046501800200648054A816A8A4220 +:2051A00003D0E030042101F0E3BBF8F7E7BAC046855C000068F2002008B54FF0FF3000F04C +:2051C0003BFF800805D303484FF40061E03001F0CFFB08BD68F20020064A92F8241000200E +:2051E000022906D1D2F8A81019B9D2F8AC1001B90120704768F2002005480068400838BFD3 +:20520000002003D303480068C0F3C0107047C04640210840000004403EB50446A0686A46C3 +:20522000F0F774FF0546832D04D1694620460022FDF774FF28463EBD10B5044600F04DFCF5 +:2052400040B9204601F0FFFA08B1007910B14FF6FE7010BD204610BD38B5064C0546E0797C +:205260000421FCF7E7FB20B9E0792A46042101F023FB38BDC403012008B501F08CFA42F219 +:20528000107210401218034800784FF4804101F013FB08BDCB030120054808B500788DF891 +:2052A00000000448016809B16846884708BDC046FE090120200401200EB54188ADF8001089 +:2052C000417F8DF80210411D019100798DF808006846F4F75DFD0EBD1CB50C4600212160FE +:2052E0006946FFF725F928B9BDF800002146FEF7D3FE1CBDC8201CBD10B50446087A20726B +:20530000087A03281CBF0888208002D1204601F0F7FA0020608110BD491E012202FA01F174 +:205320008BB211460022034218BF0A4349005B1089B2F8D1104670470346104610B51A46C5 +:2053400030B1044B11F8014B62409A5C401EF9D1104610BD5C78020002460648006800E031 +:20536000006928B103799A42FAD183689942F7D17047C046400A012005480EB50068436CEB +:205380000448006802216A4698479DF800000EBDD8050120B4060120054808B5001D0068DF +:2053A000016C0448103000688847FFF7EBF808BDD4050120A406012005490878832805D10B +:2053C0000020087003490870F1F70CBE7047C0466F1B0120711B0120002812BF40680548BC +:2053E000006828B1427B914203D040680028F9D100207047E40A012038B5064C04F108004D +:20540000006820B18569FCF735FB281CFAD10020A06038BD5001012038B5044601F08AFA00 +:205420000546207820B10220FEF720FA00202070284601F0FFFB38BD38B5044601F07AFAED +:205440000546207820B90220FEF728FA01202070284601F0EFFB38BD10B5064C206901F0D7 +:2054600011FB0146A06800B9E160A068401CA06010BDC0468CFF0020054808B541680548F5 +:2054800001220838026048698969884708BDC046500001200C20094041680978491F07D0BB +:2054A000091F03D0C91F05D1FFF79EBAFFF794B8EEF798BF7047011C4FF0000308D01A4619 +:2054C000885C08B101230822521CD2B2082AF7DB18467047022908BF017806D0C2780178E2 +:2054E000837801EB026101EB0341407801EB0020704702294FF0000204D0012808BF4FF444 +:205500007A7203E0012808BF40F2EE221046704780B5074608464FB1437801787F1E00F1EB +:20552000020001EB032122F8021BF5D180BD4FF00451002081F82004012081F860040220AE +:2055400081F86A04032081F878047047402807DB6528B8BF403806DBE02801DBF92801DB0D +:20556000FF2070474530C0B2704710B5041C08BF002008D001F000F84FF47A716143B1FBAC +:20558000F0F000B9012010BD08B50420FFF72CFC142804DCFF20FFF727FC302801DD0120DA +:2055A00008BD002008BD7047054808B500784FF48071FCF73FFA08B9FCF7BCFB08BDC04672 +:2055C000CB0301200549C0310968012303FA00F200200A4218BF181C7047C0460020024083 +:2055E000054800684BF641310001B1EB104F14BF4FF0FF30042070471813005008B5044BA4 +:205600001B689B699847034A0021116008BDC046A801001084046042044908B5096849696A +:205620008847034A0021116008BDC046A801001084046042034605480068491C890089B2E7 +:2056400001EB4331042301F0A1B8C046CC19002008B501238DF800206A46FBF7DBFB024925 +:20566000491C087008BDC046C0190020806802680A604068034A4860106800F00F00800237 +:205680008860704730240340054808B5006800F001FE002814BF6FF00200002008BDC0462C +:2056A000001B0120054808B5006800F0F3FD002814BF6FF00200002008BDC046141B0120C5 +:2056C0000549B1F89400401CA1F8940080B210B90120F8F7B1BD70475001012008B501F066 +:2056E00055FA0349086001F0FDF90249086008BD481B0120441B0120044808B5006801F0E2 +:2057000059FA0348006801F039FA08BD441B0120481B01204FF0FF3181600022026002714F +:205720000274027742771146C1604161816170470548B0F9B610B0F9B400814202D1082037 +:20574000FDF7D2BC7047C04668F2002038B514460546502340F2FF32FFF706F81CB155F81A +:205760002010890A216038BD054908B56A46FDF7D5FC81280CBF9DF902006FF07F0008BDC1 +:205780000100030410B5044601F0D4F803490A7814430C7001F04EFA10BDC046661B0120E6 +:2057A00040684FF0FF330168034ACB6201688A6000680121416070470018002005490978B1 +:2057C00018B908460121F9F743BC02460846012101F072B8CB030120054808B500784FF412 +:2057E0008071FCF727F908B9FCF7A4FA08BDC046CB0301200EB5ADF80000044801910168EA +:205800008DF8082009B1684688470EBD080401200346054810B544682170091261701946C9 +:205820000223F8F739FC10BD2804012001460548006830B142681278914202D000680028BF +:20584000F8D17047C00A01200EB54FF6FC70B4210122ADF800000F208DF808006846F9F772 +:20586000AFFC0EBD044A05493B3210600C3108608420042100F058BFE5040120C4030120D2 +:2058800004490128087014BF01200220024908707047C0469B060120EB04012005494A68B2 +:2058A0000978801A8A00B0FBF2F15143401A80B27047C046D8000020054991F900004FF0C9 +:2058C0008073401C0870002002460146F6F712B8B60A01200448002101700448007808B957 +:2058E000F1F780BB7047C046711B01206F1B01200A684AB1904203D11068086001207047A5 +:2059000011461268002AF5D10020704701460548006828B1027B914203D040680028F9D15D +:2059200000207047E40A012040B1054B33F8022F914208BF012002D0401EF7D1002070475A +:2059400042010020054808300068D0F8B800007808B900F005B8F8F707BCC0460C010020AC +:205960000448002101700448007808B9F1F73ABB7047C0466F1B0120711B012010B50822E3 +:2059800011F8013B10F8014BA34218BF002002D1521EF5D1012010BD0F2808D9044B1038EC +:2059A000012100F01F024009914043F82010704780E200E0054B10B5044601F05FF8A06887 +:2059C00000280CBF0020201C10BDC046800901201CB50C466946FFF77FFC002806BF009932 +:2059E00049884FF6FF7121801CBD026892F85110012904D029B992F85310FDF739BAFCF7AB +:205A0000CBBC70470EB500908DF8041000208DF805008DF806006846F9F754F80EBD28B199 +:205A2000401E082210F8013F994201D000207047521EF7D101207047801E08B506D0401E74 +:205A400000D0FEE700F00CFB002008BDF9F790FE08BD08B58DF801000021032201206B4617 +:205A60008DF800000A20FCF7E5F908BD38B10628B8BF012006DB802801DB8A2801DB00201F +:205A800070470220704710B503460C4650080021C0184FF0000341EB0401F3F7E7FC10BDB8 +:205AA00010B5041C08D000211C22F6F797F94FF6FE702080401C608110BD0222EBF7E0B951 +:205AC0000CB480B502AF3A6827F003031B1D00F08BFFBDE8804002B0704708B500F0B3FE83 +:205AE00028B1007918B10528B8BF012000DB002008BD08B500F0A7FE28B1007918B103286E +:205B0000B8BF012000DB002008BD70470449891C01EB8000017801F0FB0101707047C04684 +:205B200000100840044A121F126802EB80000268914218BF01607047F086020010B5044CEE +:205B4000E22038342146FEF79BFE204610BDC046E402012010B5002430B1C01D80B2F3F7DF +:205B600065FDFF2808BF0124204610BD0146034808B5006842680248904708BDD80100104D +:205B80000040034000F8011B0A0A00F8012B0A0C00F8012B090E00F8011B7047034610467B +:205BA0001A4628B111F8013B401E02F8013BF9D11046704738B50C460546FFF72BF82968C8 +:205BC00044F80C1C2C6000F0B0F938BD044908B591F8410118B1D1F86C0100B1804708BD36 +:205BE000501800201CB5C2F3800302F001040093C2F340032246EBF7B9FB1CBD70B515463B +:205C00000C460646FAF711FA214630462A46EEF7FFF970BD10B5044C00F0A8FE0146A26A95 +:205C20006068904710BDC04668F20020044908B51031096809B1884708BD002008BDC04683 +:205C4000100A012010B5044C0C3424680CB1A04710BD012010BDC046100A0120044A1268C0 +:205C60008A4202D8B1F1FF3F01D1FDF75FBC7047D07302000268406892F83030007800212C +:205C8000042B18BF01215269F8F7ACBF044910B51CC91CC01CC91CC00EC980E80E0010BD19 +:205CA0008484020004490A78904204D00870C8791021F9F7CDB97047C40301200449B1F870 +:205CC0009220904203D0A1F89200FFF785BD70475001012000280CBF002001200249C8702A +:205CE0000871FDF73BB8C046CCE800200449B1F1FF3F07BF0021081C0868091DEDF7F2B80E +:205D0000FFFFFFFF04480168002002E00968401CC0B20029FAD1704764F200200349891E7D +:205D200008800349891E08807047C0461A0601204601012008B5F8F7B5FFB0F1FF3F08BFF4 +:205D4000E82002D0F1F7ACFE002008BD044808B50068D0F82C134FF48050884708BDC046CD +:205D60001401002004480078002808BF002001D0F8F72EBA7047C046701B0120022819BF08 +:205D800002480068024800687047C04604180120001A0120044808B50068D0F82C134FF4AF +:205DA0000070884708BDC0461401002010B5044CA06820B1F4F766FEE068F5F75BFD10BD0E +:205DC000D800002008B500F0B5FD034908398A68CA6000F02FFF08BDE00000200449096822 +:205DE000D1F8EC2052F82000D1F8E4100860704714010020044808B50068D0F82C134FF498 +:205E00000060884708BDC04614010020401E082110F8012FFF2A18BF002002D1491EF7D172 +:205E20000120704702460846002128B112F8013B401E83EA0101F9D10846704730B502FB36 +:205E400001F403FB00444FF00005E2FB00542146284630BD044808B54021A8300160FEF73C +:205E6000B5FEFBF7CFF908BD00A00C4004498868401E886003D10869C96800F0FBBD7047AC +:205E80008CFF00200121044A41600021C16012688160801800F0EABD7C88020010B5044665 +:205EA000086903490968A0608847606010BDC046888802002022EFF3118382F31188426ACE +:205EC0001143416283F3118800F0CCBD04480078012802D9C11E012901D8E7F7B1BB704798 +:205EE0000518002030B10449814203D000212022F5F774BF7047C04680090120044800B5B7 +:205F000002680A21ADF12C0D684690470BB000BDDC74020010B500210446FEF7B1FE0021D1 +:205F200008222046ECF766FA10BD08B50090BDF8020000F07FFEBDF8000000F01FFE08BDC9 +:205F400010B50129044698BF012100F0E9FC204600F0E8FC10BD0A7A02720A7A022A02D039 +:205F60000822FFF71BBE09880180704710B50446FEF770FF032000F0B1FD204600F0E6FDF2 +:205F800010BD10B52021EFF3118481F3118800F065FD84F3118810BD08B5F8F733FD024954 +:205FA0000120087008BDC046BB0A012008B5F8F729FD02490120087008BDC046930B012057 +:205FC00008B5E8F74BFDEEF72DFFF9F78BFEE6F70CFB08BD0349096800EB5100B0FBF1F025 +:205FE00000F038BDA088020010B5044600F0A2FC00216160216000F01DFE10BD03480078F7 +:20600000002814BFFE20FF207047C0462C1A0020692803D06B2818BF6A2801D1022070471A +:206020000020704708B5812101228DF800006B464120FCF7EDF908BD034908310A6810408B +:20604000C2430A607047C04608100440034910B51CC91CC00EC980E80E0010BDB88502008D +:2060600008B5E8F749F90028FBD0401E012800D9FEE708BD034938B53CC93CC01EC980E8BC +:206080001E0038BDCC84020010B500210C220446F5F7A4FE4FF0FF30207110BD0349103156 +:2060A00008680028FCD00020086070470C10044008B5C2F3800302F0010200930123EBF75A +:2060C00055F908BD0EB50091019291F904300A680121EBF7E7F90EBD0328BABF024901EB0C +:2060E000401000207047C04648F40020034938B53CC93CC01EC980E81E0038BDEC84020009 +:206100000160426083610021816001614161521EC2607047034910B51CC91CC006C980E840 +:20612000060010BD4486020010B5046804F1340000F014FC002084F8310010BD034991F8F7 +:20614000D40040F0040081F8D400704758000120034A5168401A11788900B0FBF1F0704705 +:20616000D800002002490880024908807047C0461A06012046010120034808B50078FEF7A6 +:20618000EBFD012008BDC046A406012000280CBF00200120014908707047C0465501012036 +:2061A0001CB514460A460146009300202346FCF72DFB1CBD0A7A032A02721CBF09880180FB +:2061C00001D100F09DBB7047034808B508300068006B804708BDC0468401001000B90348B0 +:2061E0008A0002EBC10108187047C046A40A012008B500F02BFC0248006800F033FC08BD50 +:2062000058FF00204FF47A7101606422827100218180C171704701460A780020012A02D10D +:20622000498801B90120704701460120042903D00A291CBF0329002070474FF6FF70884204 +:2062400003D0C8B2002100F08FB870474FF6FF70884203D0C8B2012100F086B870474FF0D1 +:20626000FF3280680A6042684A6080688860704708B58022FCF762F9002814BFC0680020D0 +:2062800008BD016042600021816001614161521EC260704708B500F0B9FC002814BF00206A +:2062A0004FF0FF3008BD08B50020FDF7CFFBFF200321FCF78BFD08BD024910B51EC980E82E +:2062C0001E0010BDC8860200024A02EBC000F9F7DFBCC046F4870200024910B51EC980E81D +:2062E0001E0010BDD8860200024A02EBC000F7F701B9C046FC870200014602480078FAF72D +:2063000071BAC046800A012002480068FF21FFF786BBC046EC06012001460248006800F096 +:20632000EFBAC046EC0601200248FF2140F22C72F5F754BD2C10002008B500F04DFB0021F2 +:2063400000B10121084608BD0249096851F820007047C046F0860200024A126842F82010CD +:206360007047C046F0860200024A01F0010111547047C04600200240002101604FF0FF3134 +:2063800041600121017270470248002153300170EBF7E6BD50010120024A11680840C143A9 +:2063A0001160704708100440024804218180806900F038BC70F70020024900220C39CA61B8 +:2063C000086070470C10044021B10969884208BF012000D00020704710B5F9F755FD044650 +:2063E000F4F7E6FC204610BD00F00300022101FA00F000F01C007047002101604FF0FF32E7 +:2064000082604160C1607047024A02EBC000F2F7F7BBC04614880200024A002142F8201012 +:206420007047C0460404012008B5FFF7FFF9002814BF4068002008BD0F2802D9014910389F +:206440000860704700EF00E002490968401800F0F9BAC0467C88020008B50249406809686A +:20646000884708BD8C88020008B5024B40681B68984708BD8488020008B5024B40681B6856 +:20648000984708BD9088020008B5024A40681268904708BD9488020008B502494068096838 +:2064A000884708BD9C880200042808B502D11046F0F7CCFF002008BD0068002180F8221046 +:2064C0000B20F0F7CFBC03461979DA88D8781B7AFCF7D8BA19B900210822F5F77FBC00F044 +:2064E0000FBA416004238260002103700846704741600223826000210370084670471346F6 +:20650000024618460B460021FFF74ABE38B50468049D646A0095A04738BD0969006981428E +:206520000CBF0020C8687047416882680020914208BF01207047D0F80320C31D08461946EC +:20654000F2F7E4BC08B5FFF73FFE000C0904084308BD0068002101700B20F0F783BC0178D5 +:2065600041F080010170FFF71FB808B50090684600F03CFB08BD0000014800687047C046D6 +:20658000A0880200014800787047C0466E1B0120014800787047C046671B01200148001D22 +:2065A000008870478A010120014800787047C046E7020120014800787047C0468601012042 +:2065C000014800887047C0468A010120014908707047C046E7020120EFF3108072B67047A7 +:2065E00000207047EFF3108062B6704700207047014800787047C046B60B012013460A46A3 +:2066000001461846FEF798BE0148006800F0A8B9001B01200148006800F0A2B9141B012000 +:2066200008B50221FEF756FF80B208BD08B5014688684968884708BD18B1006808B100F026 +:20664000D9BA704701480830006870475018002001491231085C7047881900200149097894 +:2066600008407047661B012008B50090684600F0E5F908BD014A42F8201070470404012056 +:206680000149091F08607047F80A0120014908607047C046F80A0120014800787047C04636 +:2066A0009D060120014800787047C0469A06012001493631087070476806012001490870A6 +:2066C0007047C0469D060120D0F8032008460021F5F784BB08B5FCF721F8F4F717FA08BD2A +:2066E00008B5EFF7A9FCECF7DBF908BD01480021017070476E1B012001490C3108607047F4 +:20670000D4050120014800787047C046B818012001480830006870475001012013460A4655 +:2067200001460020F9F784B913460A4601460020FCF7AEBE08B51046F8F7CCFD002008BDA6 +:2067400001B9014900F076B918860200426808604A60116041607047014880687047C04603 +:20676000B0FF0020006908B1FBF784B970470021816001704160704708B503689B6898476D +:2067800008BD08B50268D268904708BD10B50468E469A04710BD08B5FBF70CFA80B208BD59 +:2067A00008B501680968884708BD08B502681269904708BD08B50168C969884708BD4068DC +:2067C000002180F8FD10704708B501680968884708BD08B502681269904708BD0020FE29AC +:2067E00008BF0120704708B503685B68984708BD08B503681B69984708BD08B50368DB69AF +:20680000984708BD406800680121C1647047012085210022E6F740BE08B5FBF7CBF9C0B21D +:2068200008BD0A4601460020F9F7A8BE406800F58A7000F095B800212422F5F7CFBA0021B5 +:206840001022F5F7CBBA01460020F6F7EDBB01464A20FEF715B84068002101707047002114 +:206860000222F5F7BBBA4068002101707047FF210E22F5F7B3BA40686C3000F071B84068F4 +:20688000C43000F06DB84FF0FF30906070470122EAF7F6BA0222FBF70DBC0122FBF70ABC6C +:2068A0000021F6F7C1BB401EFDD170476FF0010070470123EFF756BB0023EFF753BB0720FB +:2068C000F4F77EBB0022FCF729BC0022FCF726BC4FF0FF3070474FF0FF307047401C80B2CB +:2068E00070470320FAF784BDC000FFF7DCBFE920F3F796BD0846F3F763BB0846FBF7BAB8ED +:206900000822FFF74BB98160426070470120704730BF704700F08AB800F084B8FDF7E6B9AA +:2069200000F03CB900F036B900F064B9FFF734B800F074B800F0F6B800F06CB800F066B8C8 +:20694000FFF77ABD00F05EB800207047002070470020704700207047F4F72ABA00F04EB8E3 +:2069600000F060B900F046B800F0BCB8FFF7F4BEFFF7A0BA00F076B8FEF74EBB00207047D1 +:20698000002070470020704700207047F32070470020704700207047DC207047DD20704793 +:2069A000002070470020704700207047C2207047FDF7E8BDFFF7D6B90020704700207047ED +:2069C000002070470020704700207047012070470120704700207047808A7047806870474B +:2069E000EFF768BE0120704700F000B8DFF800F0B9F80210DFF800F0BDE80210DFF800F03C +:206A0000FDE60210DFF800F019E90210DFF800F01DD90210DFF800F0D9D80210DFF800F086 +:206A200075E40210DFF800F0FDE90210DFF800F049E60210DFF800F0C9F40210DFF800F0C7 +:206A4000DBEC0210DFF800F09DE80210DFF800F0D7DB0210DFF800F001CE0210DFF800F005 +:206A6000B1D70210DFF800F091D80210DFF800F0E5DE0210DFF800F07BEC0210DFF800F097 +:206A800019D70210DFF800F077EC0210DFF800F067F30210DFF800F0C5EA0210DFF800F036 +:206AA00049DC0210DFF800F0F9F20210DFF800F0EBEC0210DFF800F06BEC0210DFF800F034 +:206AC00031EC0210DFF800F0F1DC0210DFF800F059F50210DFF800F01BD00210DFF800F02F +:206AE00011EA0210DFF800F025EA0210DFF800F0D7EC0210DFF800F0D3EC0210DFF800F0A6 +:206B00007DE80210DFF800F021D40210DFF800F049EB0210DFF800F0E5F80210DFF800F0A6 +:206B20008DDD0210DFF800F055EB0210DFF800F0F1EB0210DFF800F039F70210DFF800F03B +:206B4000AFEC0210DFF800F0ABEC0210DFF800F0B1F70210DFF800F0B9DC0210DFF800F062 +:206B6000F5EA0210DFF800F015DF0210DFF800F0D9D50210DFF800F009EC0210DFF800F03B +:206B800045DF0210DFF800F02FEB0210DFF800F04DEA0210DFF800F0E7E90210DFF800F04C +:206BA000C3EC0210DFF800F025DB0210DFF800F09DEB0210DFF800F061DB0210DFF800F0FE +:206BC000F1EC0210DFF800F05DF10210DFF800F0C5F30210DFF800F0A5EA0210DFF800F0DF +:206BE000C1DD0210DFF800F0E5EB0210DFF800F0BBEC0210DFF800F0C5E20210DFF800F075 +:206C00001D870310DFF800F0D9EB0210DFF800F0B1BF0210DFF800F021EB0210DFF800F02B +:206C2000CDEB0210DFF800F021CD0210DFF800F011F70210DFF800F047EC0210DFF800F00F +:046C400011DC021051 +:206C4400301B01202C170120C01A0120A01701200000000018190120381B0120C8190120C5 +:206C6400D01A012034180120A482020028870200CA8702004487020036870200E01A0120C5 +:206C8400F4070120F8070120FC0701200008012004080120080801200C080120100801209B +:206CA40014080120F01A012068170120881A0120601801209E7E02002C7E0200107F020011 +:206CC400827F0200F47F020000860200788702006C870200731B0120181B0120240A012068 +:206CE400E4190120FC0801206B1B01206C1B0120D41701209C1A012058030120180801205E +:206D0400207D02005C790200000000000000000018870200F4130120601B01205C1B0120FC +:206D24001C08012020080120541B012024820200341A0120F81501200000000000000000EC +:206D4400580A012000000000000000000000000000000000C007012068110120980B012066 +:206D6400014A031049480310D549031015470310A97C01005D49031081470310A1460310B9 +:206D84009548031045450310254A031021440310ED47031099490310E14803102149031073 +:206DA4005553031089520310CD520310655003108D4E0310A580010001C30100DDDA01009B +:206DC4000000000059510310ED50031009CD0100CD4B03102952031011530310A95503108A +:206DE4007555031069530310DD55031035550310FD7F010021540310855C03100D56031092 +:206E04004D5D0310A9640310B55B03106D570310E5610310095E0310C5580310856003109C +:206E240071610310B16203109963031055630310FD600310B15E03105D6B0100D55A0310CC +:206E4400D559031009630310D963031019640310555F0310C56403104D62031071640310E2 +:206E64008D64031055640310E16403102975031079720310A16B0310F57203109D7403107A +:206E8400797403102D74031061730310FD7303105574031015750310D96C0310FD7403107B +:206EA400D1220100E17403103D750310F1790100F9640310CD6803102D710310C174031091 +:206EC400F56E0310B973031029670310056E0310C56F03103D930100A1770310797D031084 +:206EE4003D7E031049750310157E0310357D031099760310997C0310257B0310717803108B +:206F0400B57D0310ED7C0310857E03102D790310B97A0310917B0310B1790310ED7B0310C0 +:206F2400E97D0310617E0310357A0310D57E0310457C0310A57E0310BD7E0310DD5701002D +:206F4400D9800310E97E031049830310898403108D8103107D820310E58403102B840310D7 +:206F6400C5830310918703106188031045880310F1850310B18803107D880310C98803105A +:206F84001D870310A186031001850310E188031099880310F9870310BD750100359C031009 +:206FA400819D0310E99A0310359B0310C19B0310419A0310F18803101D8C0310618F03107B +:206FC400F1940310919E0310C19E03103D9E0310699E0310259E0310619D03100D9E0310B4 +:206FE400819B0310ED93031055990310C9970310D9980310BD950310959C0310C19D0310B9 +:20700400A59E03107D9E0310C9910310319A0100699C0310DD9D031095900310FD9B031027 +:20702400CD990310158E0310019D0310E19C0310219D0310419D0310BD9C0310F59D031009 +:20704400A19D031055980310E1920310999A0310B99E0310559E0310F13202006D5A0200B1 +:2070640039A203104D55020069A1031075A20310C59E0310B9A10310F9A1031015A10310DA +:207084009DA20310ED6602004FBE0100E56C0100D523020085650200A59D000031A90310D0 +:2070A400ADA2031041F80000B9A8031099A50310557D010039A803106DA90310155C01000A +:2070C4006DAC031099B1031009AF031059B1031001B103109DA90310A16902009D69020009 +:2070E4008D6902008169020095690200996902008569020091690200A5690200A969020094 +:2071040089690200F1B9031075BA031081BB03109D2B0200E1B3010065ED0100216C0100E9 +:2071240059270200F1E601003D3B020055E70100652B0200A14D0200F158020005ED01007A +:2071440075110200F53302003D04020071DA0100DD5D020089C20100AD1302000D5E020033 +:20716400BD690200C5690200E9D7000065F10000E9C60310C1690200F19500004D69020071 +:20718400052E0200575F020083EE0100E3680200875A020049690200AD69020045F4010056 +:2071A400F1A10100719C010001000000000000000000000000000000FFFFFFFF5C0B0120A5 +:2071C4000400000000000000000000001400000030FD0210180000004C8802006C72020086 +:2071E400340B01200400000000000000000000002400000018FD021018000000FD5E020067 +:20720400080000005C73020020720200C1C8021001BB021091EB0210DDE5021081E00210BF +:20722400B9E5021071E50210310000000100000001000000A488020000000000FFFFFFFFD5 +:20724400540B012004000000000000000000000028000000B8FC0210240000001E00000076 +:207264001800000000000000D4740200807202009BEC021025E2021005EB021025DE0210EB +:20728400FDE10210E1E402102F000000340000002400280000000000D0090120FFFFFFFF7E +:2072A4007C0B0120040000000000000000000000380000006CFC0210280000000100000043 +:2072C400100000000000000000000000F7F1021000001A001000000003000000B487020036 +:2072E400528702000800000036000000600901205408012009001D00A755020054070120CA +:207304000100000000001200FFFFFFFF6C0B012004000000000000000000000010000000AE +:2073240048FD0210180000000000000000001300FFFFFFFF840B0120040000000000000017 +:207344000000000054000000A0FB02103C000000000001002D000000B07102001750020032 +:2073640030000000000000005C7302008473020089FA0100D9DB021059EC0210CDD60210B9 +:2073840085DE02104DE5021029E5021030000000000016000000000000000000FF7F00004C +:2073A40088050120FFFFFFFF640B012004000000000000000000000058000000DCFB02104A +:2073C4003400000039FB021001002F00060000000000000020000000010000001BF80210B3 +:2073E40028000000D4740200FC73020093EC02106DEB02104DEC021029E00210BDE4021092 +:2074040099E402102D000000000000003C0B01200400000000000000000000001000000030 +:2074240040FC02102C000000000000000000030000000F003C000000000000000000000080 +:207444002FF9021010000000080000006C860200FFFFFFFF740B0120040000000000000042 +:20746400000000001C000000DCFC021024000000E8730200240B012004000000000000002D +:20748400000000000C00000000FD0210180000000B5B020000000000000000000800000045 +:2074A400010000000400000000000000000014000000000094810200000019000000180067 +:2074C40024000000E56902000040000000020000B07102000000100055F002100C0000005C +:2074E40029360100000000001C0B01200400000000000000000000002000000010FC02109E +:2075040030000000AC8102000100000087680200AF45020000000000000017000002000007 +:20752400310000000000230000001500010000006C7302004C0B0120040000000000000080 +:20754400000000002000000094FC021024000000C4810200A40A0120200000005C84020029 +:207564008F0001001105012087000100E5040120350028003003012028000100F9040120B6 +:2075840029000100FA040120840004002005012086000100990601202A000100EA0401204F +:2075A4002B000100EF0401202C000100F10401202D000800240501202E000100F20401207F +:2075C4002F000100F304012030000100F404012032000100F504012033000100F604012079 +:2075E40034000100F704012036000100FD04012038000100FE04012039000100F004012032 +:207604008300020014050120630001000A05012065000100FB0401206D0001000C050120ED +:20762400710008002C050120660001000B05012043000100050501204400020016050120F2 +:2076440045000100060501204600020018050120470008003405012048000100070501200F +:207664004B0001000805012004000100900B0120A1000100920B012037000100910B012076 +:2076840088000100120501203C000100FF0401203D00010000050120490002008E0B01205B +:2076A400670001000D0501204D0002001A0501204E000100090501204F0002001C0501208B +:2076C4003E000100F804012051000100E704012052000100E804012053000100E90401202A +:2076E400540001000405012000000000000000005D40002189400021954000213B410021CC +:20770400074C657900F009F861796940490703D50121044A8903116070BD70B5024908473F +:2077240080030021081104402D59000000F00AF800480047577F000000F00AF800480047E6 +:207744001B880000806B0C490007000F48717047094A0A4918235079CB56497EC01881428F +:2077640001DD084602E00F2800DD0F20D189090909010143D1817047E00200218800002145 +:207784000122274B02212548184710B5254880472548406A00280DD124490A20085600282E +:2077A40009DA401C07D008462038406A2049884200D1804710BDFFF7E3FF10BD00211E4B98 +:2077C4001C4A0846184701201C49400208601C48FB220178114001701248EC38004710B51C +:2077E4001849884711492039012807D0020404D50020088514484862012010BD4A6A094B1A +:20780400EC3B9A4201D1114A05E007494A6A104B9A42F2D10F4A4A6210BD00000608000071 +:207824009F060000A1920200080100215401002163920200E7400021B5B4020080E100E0DF +:2078440080030021F7960200DD4000212341002169950200194100210097B92EE5725CCBB7 +:207864005DCAE473B82F0196BA2D03945FC8E671E7705EC90295BB2CE3745ACD0691BF2814 +:20788400BE2907905BCCE27559CEE077BC2B05920493BD2AE17658CF51C6E87FB4230D9AF4 +:2078A4000C9BB522E97E50C7EB7C52C50E99B720B6210F9853C4EA7DB2250B9C57C0EE79D4 +:2078C400EF7856C10A9DB324089FB126ED7A54C355C2EC7BB027099EA2351B8C47D0FE69B4 +:2078E400FF6846D11A8DA334188FA136FD6A44D345D2FC6BA037198E41D6F86FA4331D8A94 +:207904001C8BA532F96E40D7FB6C42D51E89A730A6311F8843D4FA6DF3644ADD1681AF3873 +:20792400AE3917804BDCF26549DEF067AC3B15821483AD3AF16648DF1087A93EF5624CDB53 +:207944004DDAF463A83F1186AA3D13844FD8F661F7604ED91285AB3C0001363601010001BF +:20796400020100010301000104010606080400000C0100340D01000F10040101140100FF55 +:207984001608000020020000220100FF23010001240100FE250100082602000028010001B9 +:2079A400290100012A0200002C01000F2E0200003001000131010008320200FF3401000725 +:2079C400350102FF360100003701000138010001390100FF3A01000F3C0200FF3E01010FB3 +:2079E4003F0100014001041F41010001420100FF43010080440800004E0100084F01000F93 +:207A040050010001510100FF520100005301000054010001580400005C04000060040000A2 +:207A240064040000680400006C0400007004000074040000780400007C040000800100FF96 +:207A4400810100018201000183010202840100011E060120751B0120761B01201D06012021 +:207A64006D1B01201F0601201C060120F9660200EDC50000355D0200F9410200CD410200DD +:207A840031F301008DF30100ED030200DD160200F9480200AD3A02007D3A020019680200ED +:207AA400FD5F02001950020025330200354D0200656102001D5D0200114D0200DD3A02005E +:207AC4000DAB0100996A01005F44020081F90100A5EC0100D5660200E166020000000000AD +:207AE4009953020083D401005DB301001D270200000000005933020005670200D52B0200E7 +:207B0400955D020000000000000000000DE60000795302001D9E01000D0C0200032C0000A6 +:207B24000000000000000000000000000000000003080000000000000000000000016509C7 +:207B44000000000000000000012C000000000000000000000001001E0000000000000000D5 +:207B6400020800000000000000000000000101000800FFFF980A0120B8090120A009012080 +:207B8400022C000000000000000000000000000000000000000000000000000000000000B3 +:207BA4000128000000000000000000000001003000000000000000000003FF1864000000E9 +:207BC40000000000000000007856341200000000BAAB00000000000100000000FFFFFFFF2B +:207BE400FFFFFFFF1300000051FC00001F000000215601001F800000A52202000000000026 +:207C0400EDB7000001000000EDB7000002000000AD21010002800000FF560100030000006B +:207C2400DDA7010004000000F902010004800000DF6101000500000039CB010006000000E6 +:207C4400CDB3000030000000F9090200310000005D820000320000003108010033000000BD +:207C640079190100340000006171010036000000C1D8010011000000C19601001400000019 +:207C8400A592010015000000450A0200FFFF000000000000FFFFFFFFFFFFFFFF000000004C +:207CA400000000000000000000000000000000000000000001000000E1A600000600000032 +:207CC400F3D4010008000000A1E201000B000000DB1202001000000029F400000A0000001B +:207CE40065B4010002000000213501000500000099EE000007000000618500000C00000088 +:207D0400459300000D0000006D0B00006400000021230200FF000000000000003600010022 +:207D24000600000000000000000F000000000000000000000000000000000300FFFF000029 +:207D44000403FFFF0000FFFF0F00E8030005401F0310000100000000FF3F0F000800050B45 +:207D640000000000000000000300010F0000000000000000000000000000000000000000EC +:207D840000000000000000000000000000000000000000000000000000000000AD00000230 +:207DA4000000000000000000000000000000000000000000000000000000000000000000BF +:207DC40000000000000000000000000000000000000000000000000000000000000000009F +:207DE40000000000000000000000000000000000000000000000000000000000000000007F +:207E040000000000000000000000000000000000000000000000000000000000000000005E +:207E24000000000000000000010171010101010111010101310101010101800100011001E9 +:207E440061013B001400630173017201620143010001130106013D013500040112010001D3 +:207E640000010001000104010401330133013C014401320136000001000165010001350000 +:207E8400810100010501820183010001660100010001080109010A010B0103007100300115 +:207EA40060001100700031022003500480000700100061000000140063007300720062007D +:207EC4004300000013000600000000000400120000000000000000000400040037003700B6 +:207EE4003C02440000000000000000006500000035008100000005000000830000006600F3 +:207F040000000000080009000A000B0003027102300160021102700201020202020280021A +:207F24000002100261023A00410063027302720262024302000213023800000200020402FB +:207F44001202000200020002000204020402370037003C024402000239000002000265025D +:207F640000023502810200020502820283020002660200020002080209020A020B0201038F +:207F8400710301030103010301030103220302030103000310030003000300030003000302 +:207FA400000300034203000324030603000300030403120325032303250323030403040373 +:207FC4000003000300034403000300032303000365032100350381030003050300030003C8 +:207FE4000003000325032303080309030A030B03030471040204600411047004020402047C +:2080040001040204000410046104000414046304730472046204430400041304060400048E +:208024000004040412040004000400040004510464000004000400044404000400040004F1 +:208044000004650400043504810464000504000483040004660400040004080409040A0458 +:208064000B040506D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF0000000000000000000000006A +:20808400000000005A6967426565416C6C69616E636530390A000000020000000400000014 +:2080A4000800000010000000200000004000000080000000000100000002000000040000BD +:2080C40000080000001000000020000000400000154C02002B5F0200C19F0100751A020043 +:2080E400395102000D8F0100DDBD01004D4F0200595102004B3D0200793D020029220200DF +:20810400C5350200B55B0200F5EF0100E507020061E5010051F00100DBFD0210C54D0200F3 +:2081240011DC02104DA001003966020059430200B5610200016902007D5902008F00000024 +:208144008F0001008F0002008F000300900000018F00010190000002900000038F0001048D +:208164008F0000058F0008048F0000048A000006510000007F0001003F0004003F00020054 +:208184003F0001007F0002008F0002048F0001027B7374617469632D696E7374616E63656E +:2081A4002D6E616D657D00C07B656D7074792D696E7374616E63652D6E616D657D00C04633 +:2081C4007B756E6B6E6F776E2D696E7374616E63652D6E616D657D00B5F501001FF902106E +:2081E40045F8021059F802106DF8021081F8021095F80210F5B901002D3C020035200200B7 +:2082040029360200794E0200C961020079540200252D020045650200E55E020085D4010096 +:20822400C003000080070000000F0000001E0000003C00000078000000F0000000E001003E +:2082440000C003000080070000000F0000001E0000003C00000078000000F0000000F0000F +:208264000000004017FF0000000000000400FFFF08000000100000004018002030180020AA +:20828400401A0020301A00200A000000090000000C0000000B00000009080AFF0A000000A8 +:2082A4000000000002000000020000000A00000002000000020001000000000000000000A7 +:2082C40000000000000000000000000000000000000000000E00000000000000000000008C +:2082E40000000000000000000000000000000000000000000000000000000000000000007A +:20830400000000000000000000000000FFFFFFFFFFFFFFFF81570000DDB500008115000061 +:20832400D1710000E56D0000B91E0000457F000055A70100F169000041550100010001001A +:2083440001000100010001051E0D0C1C1D1E0F0E0607140A08090001020001000100010023 +:20836400010001020001024057680200AD680200DD3702006D560200E1FD0100895602003F +:2083840075B701007914020009660200351201003DAF0100E13E02000D3802005F6202004C +:2083A400B5300200A5560200293D01005D0E02001566020031ED0000C9B0010029E60100DC +:2083C40067680200410D0100F9100100D16802001509020081530100D76802007D980100E8 +:2083E400000000000060250000100000EC16012040000000000000000000000000093D003B +:2084040014000000640000005C7302002484020069640200796402009964020089640200C9 +:20842400BD3C0200C14E0200B143020032000000001000400600000015000000FF0000009A +:20844400000000000D0CFFFFF818012020000000010300000000000015F9021001E6021093 +:208464002DDA021045E7021041D10210C9D30210A5DF02102DE4021061EA02107520020022 +:2084840000000000FFFFFFFFFFFFFFFF00000000000000000101010100C201000300000016 +:2084A40000000000D4740200BC840200D169020095A301007DCD01005D3C02009D4E0200E4 +:2084C400854302002E000000FFFFFFFF0000000000000000000000003A013A01000000002E +:2084E400000000000000000000000000FFFFFFFF000000000000000040420F0008000000E3 +:208504000000000000000000A88402002C0B012004000000000000000000000020000000AD +:2085240018860200180000000C840200440B01200400000000000000000000001400000065 +:20854400848502001C000000FFFFFFFFFFFFFFFF00000000000000000000000000000000F8 +:208564000000000000000000000000000000000000000000000000000000000000000000F7 +:208584001C0000000000000000000000988502000000000008000000000000006C830200A3 +:2085A400581B01203C88020094830200241B0120E48302000100000040420F0001000000E8 +:2085C400000000000000000000000000D9FF010085490100BF670200111D0100097C000013 +:2085E40081E7000000000000020000000100000003000000100000002000000000000500D4 +:20860400BD00B700B100BC001C003000380008003801020018000000000000000000000096 +:208624002886020008000000000000000000000045680100395A0200010101000000000038 +:20864400020000000000000000000000FFFFFFFF0000000000000000060000000200000010 +:208664008600000082000000010000000000000000000000000001000000010000161000C5 +:208684000018151002000224145800001000002000000000000000000000000000000000D5 +:2086A4000000000000000000000000000000000000000000000000000000000000000000B6 +:2086C400000000000200000000000000FFFFFFFF000000000200000000000000FFFFFFFF9A +:2086E4000000000068020120001501207C150120FFFFFFFF3C1301207488020098130120CD +:20870400768802000000000020000000400000006000000088B2240088130000100000008C +:208724000000000100A6AAACA4A9A9A399B19ABCB6A8313118191A22311C1E203131343180 +:20874400313117191A21241B1D1F313133310000000000000000000000000000FF00000008 +:2087640000000000000100000C0E020B040B0A070800110F000120181A18182C34041E0080 +:20878400FF000100FD5B020007000000D08502006810012064820200BC830200B80D012075 +:2087A40034840200FF0000000000000080A9030025DD021031C8021075DF0210020102073F +:2087C400013B893401000204020101010109020000BE040A00BE02080102000302000103E4 +:2087E400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1C1A01206B8302008C180120938602005E +:20880400E80300000000640000080004000200017C140120A88702003819012054880200C4 +:20882400038000CC038000DD0380000C0380005D038000C0038000D5000005000060000016 +:2088440000000000080000000000000000000000000002400A29FF0010040810181C100028 +:208864000810182004040810181C0000010203040601070100000000100000000100000026 +:20888400F5680200D5690200033E0200FB680200A50C02002D050200CD6902000A00000064 +:0488A400CD5B0200A6 +:2088A8009998000015250100000000000000000000000000E55B0200B160020069C90100BC +:2088C80075600200CB680200C5680200C5600200000000005F680200F5C80100E9D10100EC +:2088E80069570200E19B010071620200A1520100BDB10000CDA60100195202000000000019 +:20890800C9F701001557020009870100995F0200C962020053650200B962020037680200F0 +:208928008F680200BB5A0200AD5F0200E9620200B9640200D96202003F6802009B680200BA +:0C89480095680200F1640200E364020084 +:20895800003D00000F05D41B002001BF06017FFFFFDEFFEFA79C01000003FFE38813FCFFD0 +:20897800EFE11FFF2FF50C200601205408C7012001FFE00031FFE96009B301200031FFEDE3 +:20899800FF7FFFE46CFBDC02FFE57007012003FEFFE4FD3B02006D5F028404FEFFE1240621 +:2089B800B0FFE106B9077984CC01F4FFE9A80B083508B10120A9080036FFEBAE0270A00246 +:2089D800B0A4AA02F53A0BB0060E63010E0064C9120CBF000FF10104891080010CD2FFE722 +:2089F800800C4F02FFEFB7010FFFEFEF013514FF0200A88802001489B62CA38DD9FFEF04F9 +:208A18000260004100E120003100B0007200B4000220220174400034013100380102750084 +:208A38003F05F300030570003500001000D700FEFFFFEFD00104FFEF17CB0364483F001DB8 +:208A58007F0F04033F20FFEF1E494CFFE7DF6D37000041FFE41952B6FFEF0C01A0FFEF042E +:208A780085E4519201FF0808020101010307FF0D1E02051E01640AE700020300F00131099E +:208A980003009F030201020A5AA34D3001FFFFFFF401803EE803FD0554B523456789ABCD19 +:208AB80095EFFFEF02FF2558FF0004FFEF22888705012000315C791CD66110B88E5AF43930 +:208AD800EC022CB00FBCFFEF4501DB003064BEC5A7FFE3F1610E6A650100D06D3001750225 +:208AF8007D0177085F4F1568001531032CA054916FF50C6F2BE6FFEF5D6C727C267FF4010D +:208B18000068887CB0003101BF02847E700031FFEF62EDFDD2FFEF05C046C00000F052FF85 +:208B3800E0F085F286312C0034340034153C00344400344C00348FB18FF1033DC52AB749EB +:208B5800912B8D037189F58A31558C00349400349C0034A4003479AC0034FFEF9A0170FF31 +:208B780000200031E6A0BDA3DF3C7342DF0E2BD4D7FFFD0307C201838703FF00C306020172 +:208B9800A86001EE46722B5EC84CD0320583AB870001710501700447B979BB540233B2FF5B +:208BB8000014319F2F9E4D7E2CF7827F2DB7FFE914000A7F130F14201400320010E4AB1049 +:208BD800A2607DFFEF07794F0683880F6F00D388F355320C84B12386B4F1FEFEAE3F007DE8 +:208BF800807DBC0A3F04053B0003B8E24390010032FFE5BFE5FB010055693B370B3E82D025 +:208C1800480A01201CB2300031552400342C00343400343C0034554400344C0034540034E0 +:208C38005C0034556400346C00347400347C0034FD84003400C0FEFF0A0101E061FF070DD5 +:208C5800E9FFF00077063C00000FA72CC54002FFE6FFECC6040000EEC806EF0000F1CA0082 +:208C780040F4CC0A6F0000F6CF0040F7D00090FFFAD4100000FBD612DF0000FD9318FFE0E1 +:208C98005328EF000001560040025932FF0000035D38000004FF634E000005177200FF0056 +:208CB800062A4F1480075FFF281480085A331080FF095F3F10800A664FFF10800BCB213098 +:208CD800800CFFCC273F800DCDC33FFF800ED6271B800FDAFF2F1B8010DE391B80FF11E5D5 +:208CF8004F1B8012E047FF308013E2613F8014FFF5753F807FFFFF3F000690FFEF19FFF0F1 +:208D180000E500000FA1020100BF0514BF027D69023F0035260100C9007016B10503170563 +:208D380020179F54FFF0000031E0010037650200C96602000000000002000000100000000F +:208D580002000000100000000200000010000000020000001000000002000000BF0F0000F5 +:208D7800000100000F15FFF00200000010000000000FAC710200FFF0000FDC810200FFF03B +:208D9800000F4CFF0020FFF058890200501A00205B8C020020010020188D0200501800208C +:208DB800508D0200301A0020588D020030180020608D0200401A0020688D0200401800202B +:208DD800708D0200B80B0120788D0200D8000020808D02000C010020888D02000001002025 +:108DF800908D020004010020988D020008010020D7 +:020000040005F5 +:207FA800000080011000C0FFFDFF58003AC1F9F1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40 +:207FC800FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC508FEC5FFFFFFFF00FFFFFF00C5C5FF97 +:187FE800000000FF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92 +:00000001FF diff --git a/tools/fw_SonoffZigbeeBridgePro_cc2652/Sonoff_ZBPro.autoconf b/tools/fw_SonoffZigbeeBridgePro_cc2652/Sonoff_ZBPro.autoconf new file mode 100644 index 000000000..342c3d5aa Binary files /dev/null and b/tools/fw_SonoffZigbeeBridgePro_cc2652/Sonoff_ZBPro.autoconf differ
) bool no_label = false; for (uint32_t i = 0; i < count; i++) { - WSContentSend_P(PSTR("%s%s%s%s{e}")); // Last column is units ({e} =
, {m} = , {e} =
, {m} = , {e} =