From c55445697bb18fbaafc5ba425e64b7acd66fe9c7 Mon Sep 17 00:00:00 2001 From: Khoi Hoang <57012152+khoih-prog@users.noreply.github.com> Date: Sun, 25 Apr 2021 02:19:29 -0400 Subject: [PATCH] v1.4.0 to enable scan of WiFi networks ### Major Release v1.4.0 1. Enable scan of WiFi networks for selection in Configuration Portal. Check [PR for v1.3.0 - Enable scan of WiFi networks #10](https://github.com/khoih-prog/WiFiManager_NINA_Lite/pull/10). Now you can select optional **SCAN_WIFI_NETWORKS**, **MANUAL_SSID_INPUT_ALLOWED** to be able to manually input SSID, not only from a scanned SSID lists and **MAX_SSID_IN_LIST** (from 2-15) 2. Fix invalid "blank" Config Data treated as Valid. 3. Permit optionally inputting one set of WiFi SSID/PWD by using `REQUIRE_ONE_SET_SSID_PW == true` 4. Enforce WiFi PWD minimum length of 8 chars 5. Minor enhancement to not display garbage when data is invalid --- README.md | 349 +++++++++++++- .../AM2315_ESP32_SSL/AM2315_ESP32_SSL.ino | 3 +- examples/AM2315_ESP32_SSL/defines.h | 13 + examples/AM2315_ESP8266/AM2315_ESP8266.ino | 3 +- examples/AM2315_ESP8266/defines.h | 13 + .../Blynk_WM_Template/Blynk_WM_Template.ino | 14 +- examples/DHT11ESP32/DHT11ESP32.ino | 3 +- examples/DHT11ESP32/defines.h | 12 + examples/DHT11ESP32_SSL/DHT11ESP32_SSL.ino | 3 +- examples/DHT11ESP32_SSL/defines.h | 13 + examples/DHT11ESP8266/DHT11ESP8266.ino | 3 +- examples/DHT11ESP8266/defines.h | 12 + .../DHT11ESP8266_Debug/DHT11ESP8266_Debug.ino | 3 +- examples/DHT11ESP8266_Debug/defines.h | 13 + .../DHT11ESP8266_SSL/DHT11ESP8266_SSL.ino | 3 +- examples/DHT11ESP8266_SSL/defines.h | 13 + examples/ESP32WM_Config/ESP32WM_Config.ino | 3 +- examples/ESP32WM_Config/defines.h | 13 + .../ESP32WM_ForcedConfig.ino | 3 +- examples/ESP32WM_ForcedConfig/defines.h | 13 + .../ESP32WM_MRD_Config/ESP32WM_MRD_Config.ino | 3 +- examples/ESP32WM_MRD_Config/defines.h | 13 + .../ESP32WM_MRD_ForcedConfig.ino | 3 +- examples/ESP32WM_MRD_ForcedConfig/defines.h | 13 + .../ESP8266WM_Config/ESP8266WM_Config.ino | 3 +- examples/ESP8266WM_Config/defines.h | 13 + .../ESP8266WM_ForcedConfig.ino | 3 +- examples/ESP8266WM_ForcedConfig/defines.h | 13 + .../ESP8266WM_MRD_Config.ino | 3 +- examples/ESP8266WM_MRD_Config/defines.h | 13 + .../ESP8266WM_MRD_ForcedConfig.ino | 3 +- examples/ESP8266WM_MRD_ForcedConfig/defines.h | 13 + library.json | 6 +- library.properties | 4 +- pics/Input_With_Scan.png | Bin 0 -> 31402 bytes pics/Main.png | Bin 29966 -> 29047 bytes pics/Saved.png | Bin 0 -> 35300 bytes src/BlynkSimpleEsp32_SSL_WM.h | 415 ++++++++++++++-- src/BlynkSimpleEsp32_WM.h | 397 +++++++++++++++- src/BlynkSimpleEsp8266_SSL_WM.h | 396 +++++++++++++++- src/BlynkSimpleEsp8266_WM.h | 448 ++++++++++++++++-- 41 files changed, 2090 insertions(+), 177 deletions(-) create mode 100644 pics/Input_With_Scan.png create mode 100644 pics/Saved.png diff --git a/README.md b/README.md index cf454cb..44e7678 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ * [Features](#features) * [Currently supported Boards](#currently-supported-boards) * [Changelog](#changelog) + * [Major Releases v1.4.0](#major-releases-v140) * [Releases v1.3.1](#releases-v131) * [Major Releases v1.3.0](#major-releases-v130) * [Major Releases v1.2.0](#major-releases-v120) @@ -67,6 +68,13 @@ * [ 6. To use custom HTML Style](#6-to-use-custom-html-style) * [ 7. To use custom Head Elements](#7-to-use-custom-head-elements) * [ 8. To use CORS Header](#8-to-use-cors-header) + * [ 9. To use and input only one set of WiFi SSID and PWD](#9-to-use-and-input-only-one-set-of-wifi-ssid-and-pwd) + * [ 9.1 If you need to use and input only one set of WiFi SSID/PWD](#91-if-you-need-to-use-and-input-only-one-set-of-wifi-ssidpwd) + * [ 9.2 If you need to use both sets of WiFi SSID/PWD](#92-if-you-need-to-use-both-sets-of-wifi-ssidpwd) + * [10. To enable auto-scan of WiFi networks for selection in Configuration Portal](#10-to-enable-auto-scan-of-wifi-networks-for-selection-in-configuration-portal) + * [10.1 Enable auto-scan of WiFi networks for selection in Configuration Portal](#101-enable-auto-scan-of-wifi-networks-for-selection-in-configuration-portal) + * [10.2 Disable manually input SSIDs](#102-disable-manually-input-ssids) + * [10.3 Select maximum number of SSIDs in the list](#103-select-maximum-number-of-ssids-in-the-list) * [Important Notes for using Dynamic Parameters' ids](#important-notes-for-using-dynamic-parameters-ids) * [Important Notes](#important-notes) * [Why using this Blynk_WiFiManager with MultiWiFi-MultiBlynk features](#why-using-this-blynk_wifimanager-with-multiwifi-multiblynk-features) @@ -112,6 +120,9 @@ * [6.2. Enter persistent ConfigPortal](#62-enter-persistent-configportal) * [7. ESP8266WM_MRD_ForcedConfig using LITTLEFS with SSL on ESP8266_NODEMCU](#7-esp8266wm_mrd_forcedconfig-using-littlefs-with-ssl-on-esp8266_nodemcu) * [8. ESP32WM_MRD_Config using LITTLEFS with SSL on ESP32S2_DEV](#8-esp32wm_mrd_config-using-littlefs-with-ssl-on-esp32s2_dev) + * [9. ESP32WM_MRD_ForcedConfig using LITTLEFS with SSL on ESP32_DEV to demo WiFi Scan](#9-esp32wm_mrd_forcedconfig-using-littlefs-with-ssl-on-esp32_dev-to-demo-wifi-scan) + * [9.1 MRD/DRD => Open Config Portal](#91-mrddrd--open-config-portal) + * [9.2 Config Data Saved => Connection to Blynk](#92-config-data-saved--connection-to-blynk) * [Debug](#debug) * [Troubleshooting](#troubleshooting) * [Releases](#releases) @@ -189,6 +200,14 @@ This [**BlynkESP32_BT_WF** library](https://github.com/khoih-prog/BlynkESP32_BT_ ## Changelog +### Major Release v1.4.0 + +1. Enable scan of WiFi networks for selection in Configuration Portal. Check [PR for v1.3.0 - Enable scan of WiFi networks #10](https://github.com/khoih-prog/WiFiManager_NINA_Lite/pull/10). Now you can select optional **SCAN_WIFI_NETWORKS**, **MANUAL_SSID_INPUT_ALLOWED** to be able to manually input SSID, not only from a scanned SSID lists and **MAX_SSID_IN_LIST** (from 2-15) +2. Fix invalid "blank" Config Data treated as Valid. +3. Permit optionally inputting one set of WiFi SSID/PWD by using `REQUIRE_ONE_SET_SSID_PW == true` +4. Enforce WiFi PWD minimum length of 8 chars +5. Minor enhancement to not display garbage when data is invalid + ### Releases v1.3.1 1. Fix issue of custom Blynk port (different from 8080 or 9443) not working on ESP32. Check [Custom Blynk port not working for BlynkSimpleEsp32_Async_WM.h #4](https://github.com/khoih-prog/Blynk_Async_WM/issues/4) @@ -286,7 +305,7 @@ Thanks to [Thor Johnson](https://github.com/thorathome) to test, suggest and enc 5. [`ESP8266 Core 2.7.4+`](https://github.com/esp8266/Arduino) for ESP8266-based boards. [![Latest release](https://img.shields.io/github/release/esp8266/Arduino.svg)](https://github.com/esp8266/Arduino/releases/latest/). To use ESP8266 core 2.7.1+ for LittleFS. 6. [`ESP_DoubleResetDetector library 1.1.1+`](https://github.com/khoih-prog/ESP_DoubleResetDetector) to use DRD feature. To install, check [![arduino-library-badge](https://www.ardu-badge.com/badge/ESP_DoubleResetDetector.svg?)](https://www.ardu-badge.com/ESP_DoubleResetDetector). 7. [`ESP_MultiResetDetector library 1.1.1+`](https://github.com/khoih-prog/ESP_MultiResetDetector) to use MRD feature. To install, check [![arduino-library-badge](https://www.ardu-badge.com/badge/ESP_MultiResetDetector.svg?)](https://www.ardu-badge.com/ESP_MultiResetDetector). -8. [`LittleFS_esp32 v1.0.6+`](https://github.com/lorol/LITTLEFS) for ESP32-based boards using LittleFS. To install, check [![arduino-library-badge](https://www.ardu-badge.com/badge/LittleFS_esp32.svg?)](https://www.ardu-badge.com/LittleFS_esp32). +8. [`LittleFS_esp32 v1.0.6+`](https://github.com/lorol/LITTLEFS) for ESP32-based boards using LittleFS. To install, check [![arduino-library-badge](https://www.ardu-badge.com/badge/LittleFS_esp32.svg?)](https://www.ardu-badge.com/LittleFS_esp32). **Notice**: This [`LittleFS_esp32 library`](https://github.com/lorol/LITTLEFS) has been integrated to Arduino [esp32 core v1.0.6](https://github.com/espressif/arduino-esp32/tree/master/libraries/LITTLEFS). --- @@ -843,6 +862,56 @@ Blynk.setCORSHeader("Your Access-Control-Allow-Origin"); ``` +#### 9. To use and input only one set of WiFi SSID and PWD + +#### 9.1 If you need to use and input only one set of WiFi SSID/PWD + +``` +// Permit input only one set of WiFi SSID/PWD. The other can be "NULL or "blank" +// Default is false (if not defined) => must input 2 sets of SSID/PWD +#define REQUIRE_ONE_SET_SSID_PW true +``` +But it's always advisable to use and input both sets for reliability. + +#### 9.2 If you need to use both sets of WiFi SSID/PWD + +``` +// Permit input only one set of WiFi SSID/PWD. The other can be "NULL or "blank" +// Default is false (if not defined) => must input 2 sets of SSID/PWD +#define REQUIRE_ONE_SET_SSID_PW false +``` + +#### 10. To enable auto-scan of WiFi networks for selection in Configuration Portal + +#### 10.1 Enable auto-scan of WiFi networks for selection in Configuration Portal + + +``` +#define SCAN_WIFI_NETWORKS true +``` + +The manual input of SSIDs is default enabled, so that users can input arbitrary SSID, not only from the scanned list. This is for the sample use-cases in which users can input the known SSIDs of another place, then send the boards to that place. The boards can connect to WiFi without users entering Config Portal to re-configure. + +#### 10.2 Disable manually input SSIDs + +``` +// To disable manually input SSID, only from a scanned SSID lists +#define MANUAL_SSID_INPUT_ALLOWED false +``` + +This is for normal use-cases in which users can only select an SSID from a scanned list of SSIDs to avoid typo mistakes and/or security. + +#### 10.3 Select maximum number of SSIDs in the list + +The maximum number of SSIDs in the list is seletable from 2 to 15. If invalid number of SSIDs is selected, the default number of 10 will be used. + + +``` +// From 2-15 +#define MAX_SSID_IN_LIST 8 +``` + + --- --- @@ -962,14 +1031,31 @@ After you connected, please, go to http://192.168.4.1 or the configured AP IP. T
+ Enter your WiFi and Blynk Credentials: +### 1. Without SCAN_WIFI_NETWORKS + ++ +### 2. With SCAN_WIFI_NETWORKS + + +
+ +
+ + Then click **Save**. The system will auto-restart. You will see the board's built-in LED turned OFF. That means, it's already connected to your Blynk server successfully. ++ +
+ --- --- @@ -1533,7 +1619,7 @@ The following is the sample terminal output when running example [ESP8266WM_MRD_ ``` Starting ESP8266WM_MRD_Config using LittleFS with SSL on ESP8266_NODEMCU -Blynk_WM SSL for ESP8266 v1.3.1 +Blynk_WM SSL for ESP8266 v1.4.0 ESP_MultiResetDetector v1.1.1 LittleFS Flag read = 0xFFFD0002 multiResetDetectorFlag = 0xFFFD0002 @@ -1613,7 +1699,7 @@ BBBBBB ``` Starting ESP8266WM_MRD_Config using LittleFS with SSL on ESP8266_NODEMCU -Blynk_WM SSL for ESP8266 v1.3.1 +Blynk_WM SSL for ESP8266 v1.4.0 ESP_MultiResetDetector v1.1.1 LittleFS Flag read = 0xFFFC0003 multiResetDetectorFlag = 0xFFFC0003 @@ -1675,7 +1761,7 @@ The following is the sample terminal output when running example [DHT11ESP8266_S ``` Starting DHT11ESP8266_SSL using LittleFS with SSL on ESP8266_NODEMCU -Blynk_WM SSL for ESP8266 v1.3.1 +Blynk_WM SSL for ESP8266 v1.4.0 ESP_DoubleResetDetector v1.1.1 [293] Hostname=ESP8266-DHT11-SSL [316] LoadCfgFile @@ -1733,7 +1819,7 @@ The following is the sample terminal output when running example [ESP32WM_MRD_Co ``` Starting ESP32WM_MRD_Config using LITTLEFS without SSL on ESP32_DEV -Blynk_WM for ESP32 v1.3.1 +Blynk_WM for ESP32 v1.4.0 ESP_MultiResetDetector v1.1.1 LittleFS Flag read = 0xFFFE0001 multiResetDetectorFlag = 0xFFFE0001 @@ -1810,7 +1896,7 @@ BBBBBB ``` Starting ESP32WM_MRD_Config using LITTLEFS without SSL on ESP32_DEV -Blynk_WM for ESP32 v1.3.1 +Blynk_WM for ESP32 v1.4.0 ESP_MultiResetDetector v1.1.1 LittleFS Flag read = 0xFFFC0003 multiResetDetectorFlag = 0xFFFC0003 @@ -1868,7 +1954,7 @@ ets Jun 8 2016 00:22:57 ``` Starting ESP32WM_MRD_Config using LITTLEFS without SSL on ESP32_DEV -Blynk_WM for ESP32 v1.3.1 +Blynk_WM for ESP32 v1.4.0 ESP_MultiResetDetector v1.1.1 LittleFS Flag read = 0xFFFE0001 multiResetDetectorFlag = 0xFFFE0001 @@ -1992,7 +2078,7 @@ The following is the sample terminal output when running example [DHT11ESP8266_S ``` Starting DHT11ESP32_SSL using LITTLEFS with SSL on ESP32_DEV -Blynk_WM SSL for ESP32 v1.3.1 +Blynk_WM SSL for ESP32 v1.4.0 ESP_DoubleResetDetector v1.1.1 [346] Hostname=ESP32-DHT11-SSL [385] LoadCfgFile @@ -2056,7 +2142,7 @@ Blynk.resetAndEnterConfigPortal(); ``` Starting ESP8266WM_MRD_ForcedConfig using LittleFS without SSL on ESP8266_NODEMCU -Blynk_WM for ESP8266 v1.3.1 +Blynk_WM for ESP8266 v1.4.0 ESP_MultiResetDetector v1.1.1 LittleFS Flag read = 0xFFFE0001 multiResetDetectorFlag = 0xFFFE0001 @@ -2142,7 +2228,7 @@ Non-Persistent CP will be removed after first reset, even you didn't enter the C ``` Starting ESP8266WM_MRD_ForcedConfig using LittleFS without SSL on ESP8266_NODEMCU -Blynk_WM for ESP8266 v1.3.1 +Blynk_WM for ESP8266 v1.4.0 ESP_MultiResetDetector v1.1.1 LittleFS Flag read = 0xFFFE0001 multiResetDetectorFlag = 0xFFFE0001 @@ -2224,7 +2310,7 @@ Blynk.resetAndEnterConfigPortalPersistent(); ``` Starting ESP8266WM_MRD_ForcedConfig using LittleFS without SSL on ESP8266_NODEMCU -Blynk_WM for ESP8266 v1.3.1 +Blynk_WM for ESP8266 v1.4.0 ESP_MultiResetDetector v1.1.1 LittleFS Flag read = 0xFFFE0001 multiResetDetectorFlag = 0xFFFE0001 @@ -2311,7 +2397,7 @@ Persistent CP will remain after resets. The only way to get rid of Config Portal ``` Starting ESP8266WM_MRD_ForcedConfig using LittleFS without SSL on ESP8266_NODEMCU -Blynk_WM for ESP8266 v1.3.1 +Blynk_WM for ESP8266 v1.4.0 ESP_MultiResetDetector v1.1.1 LittleFS Flag read = 0xFFFE0001 multiResetDetectorFlag = 0xFFFE0001 @@ -2379,7 +2465,7 @@ The following is the sample terminal output when running example [ESP8266WM_MRD_ ``` Starting ESP8266WM_MRD_ForcedConfig using LittleFS with SSL on ESP8266_NODEMCU -Blynk_WM SSL for ESP8266 v1.3.1 +Blynk_WM SSL for ESP8266 v1.4.0 ESP_MultiResetDetector v1.1.1 [267] Set CustomsStyle to : [289] Set CustomsHeadElement to : @@ -2467,7 +2553,7 @@ The following is the sample terminal output when running example [ESP32WM_MRD_Co ``` Starting ESP32WM_MRD_Config using LITTLEFS with SSL on ESP32S2_DEV -Blynk_WM SSL for ESP32 v1.3.1 +Blynk_WM SSL for ESP32 v1.4.0 ESP_MultiResetDetector v1.1.1 [134394] Set CustomsStyle to : [134417] Set CustomsHeadElement to : @@ -2546,6 +2632,220 @@ Subs Topics = default-mqtt-SubTopic Pubs Topics = default-mqtt-PubTopic ``` +--- + +--- + +### 9. ESP32WM_MRD_ForcedConfig using LITTLEFS with SSL on ESP32_DEV to demo WiFi Scan + +The following is the sample terminal output when running example [ESP32WM_MRD_ForcedConfig](examples/ESP32WM_MRD_ForcedConfig) on **ESP32_DEV** with WiFi Scan for selection in Configuration Portal. + +#### 9.1 MRD/DRD => Open Config Portal + +``` +Starting ESP32WM_MRD_ForcedConfig using LITTLEFS with SSL on ESP32_DEV +Blynk_WM SSL for ESP32 v1.4.0 +ESP_MultiResetDetector v1.1.1 +[228] Set CustomsStyle to : +[250] Set CustomsHeadElement to : +[257] Set CORS Header to : Your Access-Control-Allow-Origin +LittleFS Flag read = 0xFFFC0003 +multiResetDetectorFlag = 0xFFFC0003 +lowerBytes = 0x0003, upperBytes = 0x0003 +multiResetDetected, number of times = 3 +Saving config file... +Saving config file OK +[332] Multi or Double Reset Detected +[488] Hostname=ESP32-Master-Controller +[558] LoadCfgFile +[571] OK +[571] ======= Start Stored Config Data ======= +[571] Hdr=SSL_ESP32,BrdName=ESP8266 +[571] SSID=HueNet1,PW=password +[571] SSID1=HueNet2,PW1=password +[574] Server=blynk-cloud.com,Token=token +[577] Server1=blynk-cloud.com,Token1=token2 +[581] Port=9443 +[583] ======= End Config Data ======= +[586] CCSum=0x2185,RCSum=0x2185 +[620] LoadCredFile +[632] CrR:pdata=default-mqtt-server,len=34 +[632] CrR:pdata=1883,len=6 +[632] CrR:pdata=default-mqtt-username,len=34 +[632] CrR:pdata=default-mqtt-password,len=34 +[635] CrR:pdata=default-mqtt-SubTopic,len=34 +[639] CrR:pdata=default-mqtt-PubTopic,len=34 +[643] OK +[644] CrCCsum=0x29a6,CrRCsum=0x29a6 +[647] Valid Stored Dynamic Data +[650] Hdr=SSL_ESP32,BrdName=ESP8266 +[653] SSID=HueNet1,PW=password +[656] SSID1=HueNet2,PW1=password +[659] Server=blynk-cloud.com,Token=token +[663] Server1=blynk-cloud.com,Token1=token2 +[667] Port=9443 +[668] ======= End Config Data ======= +[671] Check if isForcedCP +[702] LoadCPFile +[713] OK +[713] bg: isForcedConfigPortal = false +[713] bg:Stay forever in CP:DRD/MRD +[713] clearForcedCP +[746] SaveCPFile +[758] OK +[790] SaveBkUpCPFile +[802] OK +[802] Scanning Network +[6310] scanWifiNetworks: Done, Scanned Networks n = 11 +[6310] Sorting +[6310] Removing Dup +[6311] WiFi networks found: +[6312] 1: HueNet, -26dB +[6312] 2: HueNet1, -30dB +[6314] 3: HueNetTek, -32dB +[6316] 4: dragino-1ed63c, -35dB +[6319] 5: HueNet2, -57dB +[6322] 6: bacau, -68dB +[6324] 7: guest_24, -69dB +[6326] 8: rogers786, -87dB +[6328] 9: Rogers 786, -87dB +[6331] 10: Access 2.0, -92dB +[6334] 11: Family Room speaker.o, -96dB +[7197] +stConf:SSID=TestPortal-ESP32,PW=TestPortalPass +[7197] IP=192.168.4.1,ch=6 +[7299] s:millis() = 7299, configTimeout = 127299 +F +Your stored Credentials : +MQTT Server = default-mqtt-server +Port = 1883 +MQTT UserName = default-mqtt-username +MQTT PWD = default-mqtt-password +Subs Topics = default-mqtt-SubTopic +Pubs Topics = default-mqtt-PubTopic +[19720] h: Init menuItemUpdated +[19863] h:mqtt=default-mqtt-server +[19863] h2:myMenuItems[0]=default-mqtt-server +[19877] h:mqpt=1883 +[19877] h2:myMenuItems[1]=1883 +[19891] h:user=default-mqtt-username +[19891] h2:myMenuItems[2]=default-mqtt-username +[19911] h:mqpw=default-mqtt-password +[19911] h2:myMenuItems[3]=default-mqtt-password +[19925] h:subs=default-mqtt-SubTopic +[19925] h2:myMenuItems[4]=default-mqtt-SubTopic +[19939] h:pubs=default-mqtt-PubTopic +[19939] h2:myMenuItems[5]=default-mqtt-PubTopic +[19942] h:Updating LittleFS:/wmssl_conf.dat +[19982] SaveCfgFile +[19982] WCSum=0x34ef +[19996] OK +[20173] SaveBkUpCfgFile +[20184] OK +[20217] SaveCredFile +[20217] CW1:pdata=default-mqtt-server,len=34 +[20228] CW1:pdata=1883,len=6 +[20228] CW1:pdata=default-mqtt-username,len=34 +[20228] CW1:pdata=default-mqtt-password,len=34 +[20228] CW1:pdata=default-mqtt-SubTopic,len=34 +[20232] CW1:pdata=default-mqtt-PubTopic,len=34 +[20237] OK +[20237] CrWCSum=0x29a6 +[20275] SaveBkUpCredFile +[20276] CW2:pdata=default-mqtt-server,len=34 +[20288] CW2:pdata=1883,len=6 +[20288] CW2:pdata=default-mqtt-username,len=34 +[20288] CW2:pdata=default-mqtt-password,len=34 +[20288] CW2:pdata=default-mqtt-SubTopic,len=34 +[20292] CW2:pdata=default-mqtt-PubTopic,len=34 +[20297] OK +[20297] h:Rst +``` + +#### 9.2 Config Data Saved => Connection to Blynk + + +``` +Starting ESP32WM_MRD_ForcedConfig using LITTLEFS with SSL on ESP32_DEV +Blynk_WM SSL for ESP32 v1.4.0 +ESP_MultiResetDetector v1.1.1 +[227] Set CustomsStyle to : +[249] Set CustomsHeadElement to : +[256] Set CORS Header to : Your Access-Control-Allow-Origin +LittleFS Flag read = 0xFFFE0001 +multiResetDetectorFlag = 0xFFFE0001 +lowerBytes = 0x0001, upperBytes = 0x0001 +No multiResetDetected, number of times = 1 +LittleFS Flag read = 0xFFFE0001 +Saving config file... +Saving config file OK +[635] Hostname=ESP32-Master-Controller +[704] LoadCfgFile +[716] OK +[717] ======= Start Stored Config Data ======= +[717] Hdr=SSL_ESP32,BrdName=ESP32-SSL +[717] SSID=HueNet,PW=password +[717] SSID1=HueNet1,PW1=password +[719] Server=account.duckdns.org,Token=token +[726] Server1=account.duckdns.org,Token1=token1 +[732] Port=9443 +[733] ======= End Config Data ======= +[737] CCSum=0x34ef,RCSum=0x34ef +[768] LoadCredFile +[779] CrR:pdata=default-mqtt-server,len=34 +[779] CrR:pdata=1883,len=6 +[779] CrR:pdata=default-mqtt-username,len=34 +[780] CrR:pdata=default-mqtt-password,len=34 +[783] CrR:pdata=default-mqtt-SubTopic,len=34 +[787] CrR:pdata=default-mqtt-PubTopic,len=34 +[791] OK +[791] CrCCsum=0x29a6,CrRCsum=0x29a6 +[795] Valid Stored Dynamic Data +[797] Hdr=SSL_ESP32,BrdName=ESP32-SSL +[801] SSID=HueNet,PW=password +[804] SSID1=HueNet1,PW1=password +[806] Server=account.duckdns.org,Token=token +[813] Server1=account.duckdns.org,Token1=token1 +[819] Port=9443 +[820] ======= End Config Data ======= +[824] Check if isForcedCP +[858] LoadCPFile +[871] OK +[871] bg: noConfigPortal = true +[871] Connecting MultiWifi... +[19266] WiFi connected after time: 1 +[19266] SSID: HueNet, RSSI = -29 +[19266] Channel: 10, IP address: 192.168.2.45 +[19267] bg: WiFi OK. Try Blynk +[19268] + ___ __ __ + / _ )/ /_ _____ / /__ + / _ / / // / _ \/ '_/ + /____/_/\_, /_//_/_/\_\ + /___/ v0.6.1 on ESP32 + +[20282] NTP time: Sun Apr 25 04:52:35 2021 +[20282] BlynkArduinoClient.connect: Connecting to account.duckdns.org:9443 +[22407] Certificate OK +[22412] Ready (ping: 4ms). +[22480] Connected to Blynk Server = account.duckdns.org, Token = token +[22480] bg: WiFi+Blynk OK + +Blynk ESP32 using LittleFS connected +Board Name : ESP32-SSL +Stop multiResetDetecting +Saving config file... +Saving config file OK +B +Your stored Credentials : +MQTT Server = default-mqtt-server +Port = 1883 +MQTT UserName = default-mqtt-username +MQTT PWD = default-mqtt-password +Subs Topics = default-mqtt-SubTopic +Pubs Topics = default-mqtt-PubTopic +RBRBRBRBRBRBRBRB +``` --- --- @@ -2585,6 +2885,14 @@ Sometimes, the library will only work if you update the board core to the latest ## Releases +### Major Release v1.4.0 + +1. Enable scan of WiFi networks for selection in Configuration Portal. Check [PR for v1.3.0 - Enable scan of WiFi networks #10](https://github.com/khoih-prog/WiFiManager_NINA_Lite/pull/10). Now you can select optional **SCAN_WIFI_NETWORKS**, **MANUAL_SSID_INPUT_ALLOWED** to be able to manually input SSID, not only from a scanned SSID lists and **MAX_SSID_IN_LIST** (from 2-15) +2. Fix invalid "blank" Config Data treated as Valid. +3. Permit optionally inputting one set of WiFi SSID/PWD by using `REQUIRE_ONE_SET_SSID_PW == true` +4. Enforce WiFi PWD minimum length of 8 chars +5. Minor enhancement to not display garbage when data is invalid + ### Releases v1.3.1 1. Fix issue of custom Blynk port (different from 8080 or 9443) not working on ESP32. Check [Custom Blynk port not working for BlynkSimpleEsp32_Async_WM.h #4](https://github.com/khoih-prog/Blynk_Async_WM/issues/4) @@ -2751,7 +3059,7 @@ Submit issues to: [Blynk_WM issues](https://github.com/khoih-prog/Blynk_WM/issue ## TO DO 1. Fix bug. Add enhancement -2. Add support to **ESP32-S2 (ESP32-S2 Saola, AI-Thinker ESP-12K, etc.) using LittleFS and SPIFFS** + ## DONE @@ -2786,6 +3094,9 @@ Submit issues to: [Blynk_WM issues](https://github.com/khoih-prog/Blynk_WM/issue 28. Configurable **Customs HTML Headers**, including Customs Style, Customs Head Elements, CORS Header 29. Add support to **ESP32-C3 using EEPROM and SPIFFS** 30. Fix SSL issue with Blynk Cloud Server by using SSL in unsecured mode. +30. Permit optionally inputting one set of WiFi SSID/PWD by using `REQUIRE_ONE_SET_SSID_PW == true` +31. Enforce WiFi PWD minimum length of 8 chars +32. Enable **scan of WiFi networks** for selection in Configuration Portal --- --- @@ -2801,6 +3112,9 @@ Submit issues to: [Blynk_WM issues](https://github.com/khoih-prog/Blynk_WM/issue * [Good new feature: Blynk.resetAndEnterConfigPortal() Thanks & question #27](https://github.com/khoih-prog/Blynk_WM/issues/27) 5. Thanks to [Thor Johnson](https://github.com/thorathome) and [kevinleberge](https://github.com/kevinleberge) to help locate the bugs, discuss the USE_DEFAULT_CONFIG_DATA solution leading to release v1.0.16. See [Can’t load defaults](https://github.com/khoih-prog/Blynk_WM/issues/15) and [Setting "#define USE_DYNAMIC_PARAMETERS false" on Blynk_WM_Template.ino results in compile error](https://github.com/khoih-prog/Blynk_WM/issues/16) 6. Thanks to [komaneko](https://github.com/jjskaife) to report bugs in [Custom Blynk port not working for BlynkSimpleEsp32_Async_WM.h #4](https://github.com/khoih-prog/Blynk_Async_WM/issues/4) leading to v1.3.1 +7. Thanks to [Michael H. "bizprof"](https://github.com/bizprof). With the impressive new feature : + - `Enable scan of WiFi networks for selection in Configuration Portal`. Check [PR for v1.3.0 - Enable scan of WiFi networks #10](https://github.com/khoih-prog/WiFiManager_NINA_Lite/pull/10) leading to v1.4.0 +⭐️ Thor Johnson |
kevinleberge |
komaneko |
-
⭐️⭐️ Michael H. "bizprof" |
+
DjX24^+bab3x^kKCb8RyUx%#@>=KePurjqC@Q&U@R9E_#U zbUV7*GAi-&^{JTmt35b??e^&ZC7W+)YkmIUj=m8ox1`61qvMsYbM9Y*jrZNz(Xnsb_PT4_j5qR@ z3DapX{xi$$*)W; 3i|}Waa_53QD1 DbC_gWtuE zjK2${GSwXPPje`)EAkev-t}6pLd--nTD?O*pUxc$>?` zdy7*MY2vo=tQ^iBa|DW(>UoBb_hHLSAd(+(1eSMNDVY}fk9tx0*sxgorwPA5n&fxn zmEA{VT8L5m825UPlQyI+PG{j=3%* q@6J6ftXAW^n z12yTtcD(=8r1;}7E7TgC6}1*P*|Kx}z K$2?r>SNpHEJdkYTAL-VZY%n~e3^nGs^H)%~mF;BSEME<0UeEOpzf&HDA^S0$BZ}8h{+s~$+^A(r1wM>E? zmLKm@tl(7}qTC5a<=oBcZyQbgXJMH{H!$NCME6?6xk~qUYg8uYtM)_ntU5L}XC1#F zD M(5nU z{WQ**Qh=MAllfs|0Q;AWo(8+UXGoEKPta+;HtQo%dXisoiR4oYCMw2i4m~O<8G0Fp zPBT6y=#AVOLLMmJ>3Q}!g6&Jr>vXzi$)`SFCUlbJe<(V&OGl{Ge7M)IQ=v^pqw>A4 z|MK)G^Ej2j^y`vZFa87*kFO^0kRg4$XLRJz`WAOMX}Dn>)kSwJmE6h@ohsZz`+bk` zUsU7n7t986@N|w2(QW*ytnEo-YV2UXpW7*`oFA|sV2 Jfy)mg4pko3BxHKP;`FmAvpX+7IB~PY_$}2k?^_>~ye{{+u#e?e zj8Dq+7w=(_B38S0(4P8zx-4ovDvbEkn;P3pwdDLN>eZw>iv115l>{<1atY?Y6!ZUM z`|6*hrdT#q{gW-ZWqE6X6O=bK@2R+uiHnaU^%aD%-wC|`x1F+@;G%{CM#W-}s_R%+ z_HQhtORi+0HoBD-pSuzxkO*w9{=3bb5&?GF1M9{50u>RO>@R|bOMNED44t8@zw$E1 z{crXmPTpQ3WOCViUA >~UaV?l@iG zQR PjSM8F;@ZrL|7^JTOz9UWP_9TUno59&S&YX&6ZvyS+lD5}3`SX1tNN9eVH zQDY_g9v3SCT^#)x3bWBGtTdwwq96RMa_zf(!wv)ys8aPZK?eP~(&*2aRexdT%G+#I zR|ND_jGWHVBJ5{8X6sjCVx#Gm>1tDgX;9~dYv&vHi=~y!QFa7^8GUdv)S}g&J AyS~apXNrzTqM>A5Z!UH{cJe;V)%VIr+pw)1Rbxi8jt=zE zT45x8!Z&GCZ+eJ2l~0AkVerIKD<)TLWJwtAV??aWku(0FexmZI=kWd~EvANiUhVbH zNC*Dm9iBgyGT+c#2^9r%bLo2v*~3z=j#I{|3_d5{c!hAQ^gz&& zm&Q}4f+?d z<_SH|w-@=83njPi++}xl+d5bhB;j`^!0IlPt`ACQc#P`udqZQ(=UNHZ=r-c^2drZdiJpZM~3hT-sktFz+x#`kC%a<;>McE<`}tI Z_ zrp?;HhU Qk_fVIN8M)(mJy7utQ#nmcaP7kJWEuROp+f4~H!<2$+84MxxV*OG!w0 zKXvUTBE(>-tvVLJrQjSl8q!OsLXU#z`y|SO3^K4f@Yq)NM2*0m?)J?FpE&L}ACJ#1 zdw<3iXxDrz${6cj9GjwK5vOXT$QTmZ)BSp7CU2S TnP)R!SL?u^_2 zt1XK7N7+@aH5#@@+q%lX%(1@iNdC_I{3D3iO7b2Qjl@@hC^z`kvo1=eT#vRf8&h *dv*a`1*_)oSkaa6#_1k3E?7?6MyZq!MxyNGt zeD#7Ae##d=1ns-cUVCd0uDzgY5l5#1BS4GS7>4fDgy@ia-2J}VTD!iObIm@f+W4Tz zH %u{&@7&)bww{#p4w=lCD) zv`;wk`+WQQh4|;efmu^ZVlMk>A(e*{Lq!O)$wNz@i`o}Mqszl3OjypUa>%6E5(@0w zl5J7cJ~_qtc{hnAUV5+mkkib}q`kwR@X03i(sg!S?&Kp0=dMY=p8EGMFVskG`&Rn4 z=e*fdp`W+O8z*jA*Abm~+04mvb79zE-!6&Q^XlT}J|P;T%2SNuuSJEg!b@!SODom# z(~k1{n#o>CL7DJ zHD Cjl26X3W4d3?NU(AGl#PhZh#$=%l zg5_cVBpU~2gg;vhyt}m2+Bc~1W4~YRxYl+ZGUZ(6+QBxJnRtLJenVSIg)_97!c0U3 zE1h>E9lwK7P5Ju)V^G*VoKN&;Y>DO$%?pYiiiA>F8sVAY-^(Sx<9}A54l?GDK^6CA z#K5L`W+o4d0S{FCUe-r{i~Lf4IXaE^{Tf^5_z$bvJbo&RiPDLrnTq5Jp1mtJ`o^z# z>X?Kc6evqIbg_$F`d6k+23qXz-)Don9OJI5ZlQ-fdnhiK8F9WeJ~)MZEVX{(s$7p^ z%t$y0WV|h0;uAXB;bxNlbCsc|%?$JexQr7svQ*|7jK6DC0&!@au#2;X2NSr1vD%;z zitbAG_l_q1Pn(puw6ERjwb*znc_p){9OK *kPj R4Hw1-<=FFcYE%!*{p6WNelt1C0qqb*%?8g+25QeyQ zb$2 !f%|?xqGB#{JVXcBXk=hjnSQ0345*u-Vp%> zDCK#4#Z`VU%&sk7-9$oMXMI(6wYvBpBq!q3(|_tqB!4V>&J%CE|5HM)ehj^Q zO7MPXse58En+x0mwsv-g*WM{$Mwfg1c&_{JZG8Z7>}+jCj_yaxezzfi$9=+PO`ffi zi{B-!V+$UMwZUxQ)kG&;-S#|V2t_$L0Oj5sf Eo&Q1u^y{B35mcsP)Hu6NLOhA?3+=b7&_9 zS|Irj8mgPQn@D3(5gP-8q^_=8PuxQ|9+)fQkq84Nah?cLe9u1j+TFD#?*I$-;laT~ z4 P9*7Pb@XKN&54eed4MOtC6C81Q#>oB^Je0=~^lb>YTEq)tMhho-MpbZlC}vmg z^A!Il)A^M|BpC^)5ekarP|M)mByhC*$YycI%X^6-z!8Xt3^v!ypR4vYyGd2a*ivw+ z;6ZN`LT+g)pJ92l5*;@8k;!PDPLDmM0gS!Q|;`#0V1^{qH-gNMfVMsH^#n zMOh9n*%EngMj&d^s8%18Z8v^GxT)?Y^8d#YVb=WXxP^hi3@)A2=1ij~HT4SswZQFS zP?7@va`-9t3@bBpf~aSMudk$u34=J06DHfgtHFJ0JtkJ!{T_Vi1L+d~W+>g--Y&|` zC84Cey1DWCFp?guE&!eZ>j=~YjSu({AsS%Z=SsX34-`a*n3 zA9g5}=+VK!=fO3=0f&G6a@kvydGTTv48A_1rrKp@&j8;1(7ZaFKk9D|aaRMu17K7= zxM%00&d$zaHf$UmOujyc?Fu-(KtfjL`}du|Bo2JhL#+LS1Aq>J-y5rUbrdwnMuu%! zX+y&~z*;@ew|FT-U%h Bz{)fdK(Ns@jDeV6+5;GF0@6_~A>RjEs4(PXkbr zn3zb0i<@3t+-Se1;xhn#;kg$dtfsNiJHP`1?sg{CzfMd7A|kNj()xfYa(-a}pfz_u zA^ mo=n!e9>b;i-0LVD85|pX4i++H<))SW!h! 8-)&9wCh{JGi++0g z%E*)MhG-Rg@eedH>|crsBE$^H#F!40j*gDNS+jsm-#!zos Vf-HuH{H30!+J+B+33K)fSV)WSO954*iJ!IfUgT|#Nb{|PD mEm-0!JuY3av9TlQu_=Z4fFkw0z8oDIIsn=VJssemBJJ{ZaLNyUQJ5?@ zClbGZ|9)pv(=4P-GM~*n&>~>q2Xj2wcIjwo(Y?*|`4KbORA#DrddWbd_!$B+1@Io! z)M2a-sJHK;qd;`r@OuCKC5;a$85s!{s<;_c1DG6i8o-R9E>in|vHf11(-_cp{#Yb? z2WzTe4xban;jtJ)_!GKaV~tHt@*2Eo>F9U`LGst}Uhh&4SOoBG<>e0f-G+E5xOjMU z5XtQ9*WK)m546550=vRZ3K@w-!)@4t;sebCjQe0mFD@>A#TgIZ1Kb322Il(vtgO-D z;aZS1Ix^2y|HBIazzH0_WCdx~HN+Qqo|n_4{I>MsW`HJxn;q=jZX%w;dFs8b1Xfl% zKs*Ff3ZM0hULWl5w{loO;_6gbR70!*ESJ!TLWBMi*du(5zd-K|uURlw!$v%Sd8EQF z_F`f{NdG0C_m;Z*Q$_oiY_Bhm4ftx(T!Vc9(F1_K9GvT3fJTt>4Zth`huPxjXk}#u zroUx=fKuR0Id~w}uy5a%L eR#P?6vRM%Kzt#?J;W54-<}qyXff$9Mdu?ux zS$tav2wjNPrk^)ws;SJffN6jc2@MKbwB`e%5O63+bIU%N>_I?seXf%M(`fMWLJ~JS z-kt(8b>sDwV6?0x`m@}j#~)CqY8)_W@TsVvS;0XX^YZdqTEzcRtwi6YTOewRs7?T& zNwfkc;TlRm3=c%sD0~IZLP_+p?DgQ6P}W+gkq~`=k-+RLDfI(Y0>QyS90Xi7wGXhL zK<5by3Awqs`FP^(A0C=;5JRr)@9vttdBe%UVYY7-kFeK6ogfb&CMCr{<6+(UUA^DR ze;W(y>gs$aMiqRFBAd^>KYY+p1a=EIMGSd>0`QrCRyAVBzh0+eLf$uBe|k)`p?`gE zyWsW>MEk$K>wnu 3qTE9UG5{7RCkVcV_$hCJ5o`9b kc=0D*;s+}V^J$TU*c)4N =enKwp7+frm-R%Y%irV{#JcSZLsYabRi^ _ zmFaIUc5`>frVuED8UWN3;K0>2HAOm=Y|PAEZEf@bbJ3I;b%gv)BSAq|$RA+;0ICA= zHS(U)H25h#d_b;4_Er?3QdU(3kX-;y%gBf>v6qlX)khilyMh9XZvMZjtHJHGdPCHC zkKR{29vD{uJfSnf%fsUe$UC4SuXY-*Nl8f7*47}wEXPU=p&vsJVG{pH{qZIyAzN-KVWCRM%D(xTAqhtZE*X#`V!!C9D0plH zbd#2$p{Uk5^c9O0B?1KJ?h>%{ia1Z;wpT^PyZttqNJe;u2hXENw{}FFcEt<~u8kzu zMg2M!F8}e=0>(&wr`;C<$wff;F)~(|{iM~@90lQ4nWP0oHpr>(-zA^l(^XKgTpdV< zYZkDceIFErMeeW*LbAs5TI54B2M>?_H)BwKxBOe-Yi>co-$wy(aZT1b7N@4B!dXa4 zeuoJG)|pn91B}*OT&hl)fU%*|u*JGAbrJXsfS6-cO6f7?obibkuXfnbfVlw)1Z*h) ztN@TzR2+dOf#LijA0LsJ*u7+HZf@>d=mt-B0IV%4B0?M;9zBAFf&xVg+9Ql~O exeVve-aK}y7xYAU8f+echF;7nn MoYnRW2g7(iW( zjg0{)hZ5lec>tvuUenXl=rq#O(sQ?cl>hVL7VvO^k&7pgD3B$v`ug_G7U}@BBbEmb z-~lr50%ZJmjRQ-vB0Mg|Q$ZoPzWx&G6HMCQA?Jlqg Y#3I!UIIq z)zruV2!@&kf*7K^#qsiQpB8f31t|kp4l@i-jDUAx-MQm&aq=*=U({y44UP}`RYybP z=<9G_JeM@!YJ7ZE!}cPnRQUL1u$sEQ-0{4+x`Jc2guz2WYHMp#L6e_UQgU&X8n*fs z>eo+ 5X`Y6NmbpRLx?wQ8o8&v9EAk-7(WMp8W3J8Bv zuPNr_#w&og#Lz*gLZSO<#?8-P4XX?&3Ge_LJUl#~0eI93JR4*3N)}WwER(LclAWL9 zcN`t}V _x#Aw#?i_1L>Y+}r)sm6r|0PEr?cSx`wYgnv!@s8gL>+EQ|dECs>15o z71PyruK-hpF##n=W$*&XZQz{|O%TrT;0Qp_jy$iAJq x(bu1bvIJ? adi`%FX4!+J;DhrB{h_eN6>`+mi6IvMLs%zR$*n`W}J>R+GT;BmX5O-o4`? ziSJ&5wpsN56nEwUHLq*m|5b*FW| 3!u>-rAY{k<1lnl^np z2Oy`5Lhrx*Las`X<-_uFYt0siiw4Kc)m`-?Ip 0I9gQ Rs=y06DLfd?+}zQuz!EX8E(C~ z?K+0K2;FAKt1Z|MD1xYQy8qW-r)-kpAFz9(OWwM>(l9LD<>W#ZU)|hJu!g~ay6Vo3 z=5LZA2M^xz;B7S~B 5E;^Zt@SxOEBgx93aA0mu8z}gKDhB%y8JG6|Wsk@?{vOzhWOL9eO zTG~fc0**T?2BGy-K6%ntS-D^T{&aDPkwWB-0dSY0y-vgPXt(S{p#RbE@W_Y==`K40 z0s `+pKtgXMA<9 zo;^kWHZk_0)|S6Mptvkrw20p1ZujC>tKUi^yf u#EEhp6&7O8 zE|S~L)wQ*)V(bSG9!y`LA+mA#D#G_|9-tp-C@(KB2xmj31it6`=H~gtYZ)3|PDzmv zh=gHFhgvK5>vxV7Ebs-8E;eaWYl)rN)ZXe2D{ZSDKR$Zulpig9W9{8*O_i%)4a8n$ zWVDFS{o6&29yaWXU;9Lbv6`ASv~aVIZ@(rC-mM;%q}DGNZbe=9xO1$l!0|LbEpKne z5gmdPc!6=xB_ DH~=rio80D}PT(0Wb|(B^@bh56H^u;0H{cG)W>lHMNxQ zHzz0h$`waV#RL2IBQUZ2o?hEJUQch1rXpz??M+YCktX42QdIi3J4e3AU1@A6R4ZAY znqKYqgrjPcCzA}-K|BIamfo-J+(JGTVHe6hhpMaR mM)avYz@~*J%7{+v$fF=CN1vzvdNfeDivtU0Z6;UFyqaH2$%b|J$zo z^OE}WUbZ_Kd&w{0UM>5zvpKty!U2WJyH3FbTyd0~TnJE1TbnPLS#fhKOG{Ii6{`RV zqodUcN}^Lr1q25d1AO>MfD#0QrEYGV9*?nKfk4Xomv~-qU?53%;|&aY$;qKN5MTBE zo`1*Z3eTvD%1YCV-U!^!F0YzTnW(tri6)u|LFZt0p>443wzDB3Gc%X({Z5$q`;qqr z2-NaJ?ELoaTY~eog(Je#Qd3bzP;!)F!PR963&t84%w4cxc(@Inm{*Mb@Q}i*-VGuJ zPYR3W^T#g!Lv>T&A|F1iZuBJm=1U5wclwMOu<3T06`{j(c pa-(psM@$7ew! zIGvE-`!cTwDo0Y*_nrd9DjjL*vGdjgfgbDD`9t;4&dI2&r~!rZTG|L0JN}JR)~xU? z2p;6Mkv+xYF&H~G{=$X!m%+LnUz7Z&YbuTiC%#TjQ1fqV(9Le!(DrS;nVFfWjsPlO z-^{EmKc2dq+e^==ZDrNfNpW!toSi=scUN9s^umh{GEBK= Si<=6al3)Tmc z$i=?)bLMD>;LgF8XS#a?M|V^0#c_CRO$aZgW2hWpf%qSk9eJ|}gNR~KXjtnf>eah9 zigD4LE0!XO06G!55DcIbvcng)5qS>yNfeftDMnoX?aY}Ca2>&V#*DEXuxf0iiX6M* zztufW+OO}+qeqS)nny%NBAXCaBquAY(x(r>PjlzZ wm-QyQf1kwh!jsEgDW7FG*sCVw!P3lF#?W4btXojZ0 zF1!6m@oU8-|1OcDG L77(K_XHG*!-J@2p50ATKe6{bd z{6^Y)e7uY>NLG8)sF}l*p{498t7+4KE(C>*q7#8N0BiB_#rgR|b#xLanCH$7n>cZR zP)1}_7eSr;x%l{znwpkP* 5C2uz& zAww2<@#P~Njdn^SIcY3$gd~9>j-y@k@E$*YeB;JT))f8(B0iZ|$n%>?B#Vr!K$Ax} zFM0ALJ~2^MK|ya-S;G8z0t=CJAf4gEeV_>j1_u29Bf2hr1a*3D$@hFHmztig2J=H@ zM!2K(=Q)|NHR@mFvMJec+Otjs9yov><#wq8=fvVP;=$)aHUCT&6_ix%NFBj728M e8zf;{uIo*GN)l zladgbsdkWY|8Fn43xVh#y?fueb&JeJ2MdcE@l`!Y_yopp`T1ua-g=`GEJ1Q8I|oaB z%l{(99}!Q9fGs5BNeSoT<5#U&1GCmVmhfR=f4ts_Cr^cil~h&TuKgU;^xe|Y$w?{z z la}=K>at-&C1PgDc(q4d952rozYPV8z}*=C$Td yXUT7xM)*HTMI;=wE`)o z+Y 5Hmt9T7%7 {a^1bFH3UBlvCD8(*|6cm zSzq+hi6@_xmk$fIX0rxq`r90tMnDqQGI~=+6%wnR>pXG`fnfjOfb#45ip
cH`_H8N07SZ^*PByJ#;>iq;+DS;Pp2Zr?A4rk^ZY*F86PC)0+Zm){Stn> z^?g$Itb~IDa!GGIf2{KC+wQ5CFYhG&Pf`*-AYBL9nKpGQD!jvpaB|qbwX}qqWL>?w zl~}j+>%}>$Z2MKK;z6RwFmOlc3XFL5-Co^ti;G9<>e~JE)7Q{^R%g(G19-G-fxH+tis7$l6(!TP0cD6qt=h(4I{8{*B z52?3H2#PHzEcB;)vZE=eNf*04+xYWf-$NBsPTL!nK8nikGd!g2jm>D2$bO{i9o>9) z(B9me_wE&5SQ@J;F6g&c(#2+q<<&I#9kwFppcV_tA}_}Z=_aXvaz*3#h5-73!-DcX z>R~@gU5V&7*-2W=GXKZWR9DY#&AKv3E3`LzkgOH;(WqaaK0i4+MjSruMtst|c}Jq6 zh)rUUf@o%7_nC9&2sEl80I#KSnc%g4ea0_e&r_u-M@VHr8Hn555p{&EW^J1!RAp`3 z%2Ol0v#P3%a37`=_+V;&-(Dc{qg6;mpE+{_+BG5^ZE3{#@y#xs-yb6t1wO5P^5lt= zlM~PTvv%XB;LH)m7p^V9xylA45NfPsM%X1L4QWxM!fkLTKGfCGK7t$&tEsL12Mjo$ zknlH~7`|3s_HlnJe6={!J2Y_Y(t=(h^{c_Fum^YxG4^kPtJf&gadUs)T(?j}j%;8? zhL5MG_MF2wLPZ5fZDI(2Qc+Ri-Cmh7{NtVPy_!AR!L4Ax9(zwyg6o@_v<^m1+On3i zeb&ih>( $I4s-*b2=zeovAVi)0)90RMmqKk3liqk zKP(S`O=x6tvV8R~MPmoa-3BJ{Q!%80V7{g#K5*%H>%M@06SzOgYF(8_xN%6mG70QrVQT@$yF@1}SBj%sxe`L<8~olaN0H0Dic zT%9eW*RNNQC7E)Dq-HfnQ=}PAhw(Oq<-P#*5-{1hyRGiS2U5HUSF+4{OPh7nDZ>nq z$a(Ull@dF2ap0|oY&URGcI(Hhj<1U@eIGq{;llIL(XPZr%gej2U5jw(NXW;72XhuI zpb`3D#vn$B2OQ|V1_p?uyR69x2k$A2F*NKdY&Wk*yO+vAN+psz?%X-+ybpi;aRu2N zYPfOZ*td;p0)5tb;X<48g|=FkE?hWJpXx_z d0VlAn8k1#MOt*F4j`5qdnsimd(q#13r zv8640Q3N&ve7_>6c&E8~PTU~fU47HEU0ht$LJCo(eap2P<<62q{Am%Z{8~f7z>5-H zeC7@K_BJ*OW-yQq2S|52zE*Z`*pVYz$~`f%SWaYyqYwPuRylFv#3Jg@qerh_zEo6E zA*ha*^5DU}1;UcGC51!b;q>D^ii+ZFL1%g%3x-jGEt@vM5)l>A!-GLuk+!NKebv+m zW?aWe2JtIz--_k9R}H^x-5L}?kYP%SUg$l1X~t=0#g>5e5)u-q MZ)Prl#cJO)xdhN=ut33SC`wWsb9R7An)kiN}gxlX1&lRuGJhjb{=34!}BfYILYI zi!}Gf4W1c>el#9SY{{#aFK^`L7AE~>u9ZHjl$<|&ee5uH8%$bZT|51QQ5SOMphe81 zh{lbZ#}2#W!I%Qz4^L0b8Hr?9vTbld6T$&v3v5J~z38X|^G5x^R}hDhiGr{@<>c<& zzO8xW>tAq`guURNqNJ!;zIxo=+!pkS!oE5@d0NW&@#Mog%sV722m?goI|9z8q@)0g zV`7GCYa=uPCP+_JaL9u}EjJL4lOQH-A<`XYhxdEz7(+-m`R|b^1@Y3hwe1z0Ptb2Y z{FLO_>9+kXf3r5jeqFP4>8~Uw3((`P0hFM!vNE{unVZKVA`XQzwL%0AOPOs!Dp}=w zr6s^D0fLCdNk%eYjkQ7uDliUZTX_EF%`_do;}PT-!^h;eLu5$w*6X@-Ouwtt&$QK% zq})LVfRPmNDHawiEdq0S(nR=`J$y*1_=- IPaj69zCErKc9trV-P-mp{>K zC7L-NX52*pfAAG84L%`i7xV^)NGrX`a@287cD+szBNGhOo&;&{-W?i>|I7PaVNeOQ zdgl9i=6?$4t4MlXx^znBr<<3%%zYP?J|)$oLVv$FHqz1*sqP|f_FzWpUda@=>ysG7 z!eDCW=<(z6XU-fxd9v>9+lu@5i4GsB7(|XW<++RG^_Tg<;LoH*8EA&;q1NtE`yF+< z2^%=)mVjEY+v2*)gsBFuOO~MEJ$UkDq`Wk^Pr?=a#vZzJ=Z F^8=+H%+_-UlfHh5T-c2<3rkVgYD+r0+1or*oV#wGm)nityxn?T9shr-(ftw z8yU9U@P2}PA U2O-+ukuj%{BaSdoLyNS6a< z-ob;X2%?P~>-o&Ta~p;RiSsO_Y)T-@mDwMLgw|!Xh&h3<90G;$hkPOmEn+#|yJwfS zvGq%d9pgnT2G5l%M?Bf0aj$pJ6@u}8(B=5?>3`PwmF&i3;s+ogUG%)Cx>_kL5G}*x zO(t#l-)a7~gTxLI_H047?MvPMsVRCH*UvAfuP9xJvpN*}@SSs_UW3DM`5n=tcKtsD z|G!9!hdgr}j!#;=V1W H-Q8)W{13z%N%J{# z6pj|JfeP8!*w39?b!}^Uc=%6LQ69d8`Sj^4_J3MNO!A*i3E(yNg1`~b*~M+%*n75) z%DVDojR_Mf%FB(I^cWFtqp1ku19Tt{nnq %w3hTLJ;N_b)2#+a@5u!pf*0inudUr~*lKa5EeTn84X=|sW*URo*%1B^B z!iP_v{F#cPePCfJ_ @025RHsxSw?OBNpF1-+wZ>-Y_w;6hJ->nU;O=}PpLE*{C$vi ri&SyYS8QZuSh4{?)l(zq@ w@Q?boqaMG#~5c)3xSPt4-0|3STKmI5?F2 z@N7txyTg_w!JIwkm9gmbY!XYA`u2TXRppCzfbNaPqO c2;qc z7EbL98AWx8n|tigp#a0ZImK_5zF+ptUx+-vYwzC9ZT+A7YSjGH-7w(KPMh)A^3|Ky zuKg%ww|mbXmV@}B3jHu{%RrSEhz+dy+~S`x1{}^edQoBl8V}jp+!s-nxOgi7z55%l zmd4ivdsYnLTZdV)ugc1f@E`Q+CA)X*dOezHLEEH*ndZ*r{_Y42#;Qrl$@NQ)7nvQR zr(|!OgHn0hW2ls-INBTY{9#E6G75Qp43f>XwGEse7ot2tfL*3kd|<(v&eEfYsE*ar z4>GLB%-IHK<{RMoSk8FqWdug%79O?;2#H8#FE1~gj+;MT^f!nMGmHfFiY?%&Q+caG zGNYOzL12)KzvL6tv>6MoDUMWZF2$iiVx;iF)7L(A1LJ9h6~4+ZEM!g>Mu<@WnIL+$ z(K{0%K@?45Hy72^j2$y38r&_NTU3O>48AycuXgL!t!Sq5YZmi#ot&;RRLSrs+Z7|d zskvFr{}W%mwVmBjYfT^u?~l*$BcR__%w$rL{?HZIzbartjA@ Xd`b>Pt6h (-q+my?r?NNXNf829V;ckfmb?aXIEYsFiT zH0S%GI=Z?>qbh;P+~-S@ob2< Ut zuLy1>D}+p_)n)n?(2n~9H-HCS {0l=?J%otn_4dv__}KvUu3*>V0h#~gFjo%S@y&r=dG zqsB(wMquShQ8~~$V>V4}r?g$HJFL?qa%{NG;HXQMqR?%!d24PxlU-m v0etaUv7Gv_ z(LBrugy?3};g|=c^oHH6;X0_%TkziHM((8K1CD%rCI~obr<9>;>QX4=mZoG2gQuBL zz`3(Hog5RhyZH4xAmxY=tYBOgWSzq -FR+6c>ZAwz=z( zD(bd$DRbaZoQB4<%a={Oo(m^uX-i?-h@N~DkNmuPMbC2fZ~w|Sg15RO*}kp49hXr$ zSVj;})ZVxOY6j8QVj;gdgI~jl`O{3FOV*nD$l0GihgoZqf&U#PhTARHaLWMBFl O0e)#eEa+S3l{UHJHVfL!J| zIbG=;2yTDw4FAU&jDJD0Mq>l!|6v(S;B#>TCiyG+T7!Zq*3ymjwYh(M`qcdOE7PmV z+_A*X7okI}_^T4DwFW4=J+>T_ZhY)Lan*7fBot%qvrNRRg^VFSuu@x`(nu{NTw`62iPDEQKnWkHF2s06{ex7 zY4oU3T?07iz=cKk@54XNo;!DCYx7zR6b306hn5Ur < z3)NsGMB3~P(0fR8iFgu{%SNct2UShpafOzF!I$gZ)c}gNhnL@S0AXsG{}bBGRmQ zklERtToc1&6(ZcUZz)&lRnw>Ucu|u<2tC>&EDPM#G{huOqo`z%Qgy~gvA0q9YOt}l z*N)}fctBT3=fXFD0s~r{&e7`UF?*Qujifs6`f )a_4sunAa{vAr zTr4MN`t5mWZjUZL#|C)QV9}h@)>S8-J}n{enKz9XQOtBA;>wfCN_>1AO$27s>tm*j z2;XNZ67!AF%PTo@FkY;T#hyC#41N4&6dkV>{#)%+dlD5?;(b3K)wKJ6{IMMM12&Au zKYjjfG$Zlz+1F vOXbejS z4^jGD>if}DEvv0@2JfmWQPRg=t3G2=WZQv#mS;E?0q I!O>bko}S=J9~yNx3; zBjzEVcEW@%&g0BB>VEE!Dw;d=-)mmRQ~ozl>oC8Ncc$NOKWvK86|1RJO}tjsFciTI zSdl897dlC;u-wpX=j4wszmNHWw8jRCkyfYFzmV3z ^`i7{3zgv4@82Ikbt;R=Tn?*QXo5j`j9e{|cV-Z$O8A7&pSxn9i|WlK1aq_l zu#W2HCU%n;r!nISrC3*WMeogOC}MCvE!xDVu?7=U@8nf(LK!p03vR*IKm0VrR7=Z) zO$T(Rd@#{e@W$xp@BhM40$X9YxJg}3OJhz+ab{Uw-md+tmo1wbTSBckcKmpYujvEl zC~3FuJ^%scJh(p*RgAZboy1WUq+7vj ~2@+~Mq#M9vQxb}7>>fLfSTcVW_`tK#EBi?1F@zQRymvFjMY zl^;;968pDqXYGei=o2!gIp3`Th0Re%MNgy*j7o_J#J#)iaf#J2|H49qdn--NFf%V# z-uz$3N2BdKKa?peD;L%0?isY}Q5ON|#i|`rD5ZHZ*zD%vLlYe0N*gAyOe$*4tA6`X zcWC!n`#5*+<;%}yXS?vIoobX*cK?5XPja^{=ge6T%H_HuFRw#wl^YQVu>(S_H!(7@ z;fzrbw|>C+JUtl|9W`uNa%!sP?O5=t0I*HIbZLkiaOU1I!{A{{Ftid5?6UptXYS-Q ziN94>H)jB*pFD)%zuJf%d;YIBqQZkc*8O_zIeL_#fm7$tzZ(+F@i4CZD0WL>^8_AE zrwm|av4#3OrY?WbWkOML@w&>?o7L4~A1C>W0C+di(cwfS+w>Ru$I`?9Mx+vjW_Emk z&p6Omx(zFgjz_Jqv1FWN3tCQJ7vIzI@mIx~)Ir@{v1xwKmz^40$mG)J&n~59DXdpK z4Rjoxw6xf}%-^V9TBz-47SO3QWVy^WNuwXH%yaSRnM<|nZyg9y_=h*)^XTt$s Arh4 sKpPl#gV{zWLq zoGB1@@m!H{Wj4p 82 ztA?+uYaOH}($6q-{rt>DO-{Y2wA)|l{Xaom;|Pmft9o0#&b^x!?6UMc=pG%i;c~$D z;_NsJ-(lr)nG dIk7%__l2}w> z^K*H9VaKyQvmU;)n4l4GGO5%zye4>e>b7|XPt#)#Mp-w+o$02fbWP|{ka~UAt@BZN zJ<@kYwP}_~3IQ4cSA0^Pg#kiW*G;?5bh$4XeO}|I?t;)Ne>3U$IpMjY=&sXnZ9!f_ zxy$U%l>Re^4^pxlF-#aD#8?fBv8t&tzq|bOm(Lzcz6@$vB0N!ldpIO-$WE`%J;O(6 z#|YLEHg-j$%5| >1Z0--&!^H^8#y%VwXh!~2-;uv0M{v!HzQ9AAwi3!N+_ z1ihS3*>fg34O=G+yEgRlXO+&v!{d6IOC-0}s;z6@x9x8;2hI63GoyOeoS;3=p3G`_ zc&x0Y^XiAkvxVg{Ge`G)756E2-^`O|-|=zwn-6dAy XQMzCOY*;nOsmHh&8z>DKMjr_R)vnmK*#g8i0{%|!|h z0}^LvjrpyIgm?CA+h?&K-URLG9{pYCYqR~kO*2+_4n^_ypT14owyL9Z @R6(q3{Ce9zleyKg&j`EOSa_KN&amFkm}nK|e$qoaQ{;DvglP9<9T%;&MP tleH#=bVT)=d|$=le?0CT*|W{8`<5e)(rcw6xNTaPK6RF5qJ`^@{{Sp+MWz4% literal 0 HcmV?d00001 diff --git a/pics/Main.png b/pics/Main.png index 0d682625fe15b4f0b1e33d19f388c5f8bbf7b9eb..1a03bfb768943430388269d58f92834f1a720168 100644 GIT binary patch literal 29047 zcmb@uc_5W-yEnWHv65LCQsyXxR5B|GnWaLRQxs*0D8njal8}%T2}zTrGEd2rWU450 z$UKvo@3*@5e)jV```LSc`+eW_$9)&Eu614Kc^tp#I71BdG#KbM(-8;+hQpd_NAUkO z0)grfkrIDWXewmG|EMmi9zIGW5?j0VyYN?Lw?igwMowqkJgi+$6O8QL-P}&Qp7N_- zPayCS4yzqF>iJ`&-AnP#;F`*WLj|W@ LT^rffBW^ _#l)lb>@ChTrP>!*4gQ;XyD*un?5(45$Eu7 z=~8}1v)RS=-E%(e0UaF{)Fm1r#C(GH8_n|a@>d)sl_6KHIY-tJ1bGR3D}?=v6jx`c z2!phQMkYcEFF{j l BZc^0hOz;1u;-20c*MtZusx_WxI3JMDR{mWFwmM$wMWM=MC |ckdn*71iM2 z;3=*-?Zb!9+S`}tQ5!8X)OU0!$IP&Ws99TExA QA3Oxm~;%FLVBco15F2GiOv){gRUSRiC7!d}wLONlxyWpX^y#SrHHr zxN_x+cC18LNJ#bP&zD?Xe@=SNjd$v6Y2649Z*FSJdi%EAIMll38Wn9yN{Xh?kwb?L z+1UJ?xP3DFLT+yER;4RPU#V(nRK9!n?%uu4A|h$Wo*h4s?`K#VR9#h7qHevmy0Y|p zw6)-JR&nv#Gvf@ro1444sW^L(b!uv=C23`^#ZGDI+ts$NvRin 8Dk z{ga-Hi;LdMq$+JuQPInnFRQFAPY*X|6wm(*Wzp_XS64r?vN)Tbo?f4RZBAi~iIH*j zcdL`TyL z!j)iKy)lU0%oj%<5FgSM1XLe}Q8!^w~9^YNNb}=x7 zmG-NNo9BJ$>{QvYqq?KRx8f$(@#Du?Sy?+eIu5cQH8!4`nQ^qYw?BV=t4l2|^YG!r z^fYCkKYwm$Fg$tE%d@)m-P5;kj~zR<>BlCW84qP4*0T#!ec4W(-@bl5cJ$~TY3WBz zgZOoV$B!Eu@7ud~t3^U$;@Zgf-32wx4Gk>p>^v4z?-;sVb4kmS!C6_m$=Bwyc70@Y zG*N|gOXZS_OZW5wkzY8<)ZAQGh_$oe^7KH1AdUZISE+yC1`bBwkaC;uShlL_>O&eD z!^6XKb90g=ul652=wH@NzXNLx3%L2E`O;L4 sK) zkGgEJ%I@7w6%{m>816PMFE88J*a% RxE&ryDbTrP9ZUfL}-W z&;Rz{O29vTBVx6>z=bnt7w658< xr$|{d=cKP_O4DcJRc`C(_}nvjBQz8x zfV4Q6_UhHE2MQjS+}xg97W?*8gt^IY<^S^S+wY&{8v^RH?CQQ{SSChCyDv %+QzU39ay!^eIK1K_YhsVA^RW43W&(-DJjEwQP-FENJx8ecs{aEX@viP>J(C6~y z1(n6LfPjGaWn~Hq3jACVs~&P*za3AUIDt!0Q~Q9muB)T-SU+*Bw|C>_%|Ecz`aeI| zdGehU=S}=Rfq*ARhX$L{SXA+dK7Rbz={;Th`gDz^(CxG|J7;I-BS(&4jj5`>@0uO& zDD?XJ^w@5@&x&5ZM}C%vwzst%J$7ujwDg3r*q>Kt=H;nBFKWte-W4NPS65U7Mtb@H z+x?53fq&{|WOZ**kup#CzWHsZPoJjow?1>G!b%EtQHownQnJ{!k1n?6{JC@Y@GcR@ zA~l61B{O<^Z4a!EuayuN|1jP!AtqLHCW}Q?N7(52arTV*2J&l{t&*fg0g;}5xi8jI z#;HS5O6n?ep3l;y{rgMiI!WQyCI=22P*qjc)U0wUUisG1aRIxEm$%q=W%1|FpAR2C zOeC$!DJgB`pBYR`{Pyizk?+dp_midEOVMGarKPpCwfmepP;CXHs{LFgVo#cx6`cDj zN_ox7!67~&;exHLt%CzDD#Nl^FRkhP`SZaUy2p;aO-(&C@#fvTv| zX(X$!Cf38v?Nj`|y0*50q$KOPv37^%m&XhZ@q;0up*6V|`+t3k>*?;kR$Ms|megR6 zM-aiJxmJbswCB%@hQp%BTMl=wuCA`CipX#4 jsfWO-M#B5BnOwTIV|;rr3$ zQ~lv8t0hv76C%+C1 #}*7OANPyW=lTY}&YSX13X~ zN1uV79+mk+d3j)9pz(7PLko+Sj~~nY^gAl*UVCq^Um8|kVPWBX4{n-nqViV#A*`hd z)wAT+AitQQu`y|JX0Y{Lm}(MvZ}okQKKK#u^RuT1mD_b@z_1`CJKI=Gi|##z&zgOM z{Tq}{S|*++>FMj$`#tBJoSecvo-i^p`c0S@UWu;htEi~3;r!Onkd%_r+uhA?g0}Q5 zHFaH?6y>#7*p+M|dfrpjBIs!r78ag?b;?VQ^D@-y)&&Ly{rdF_t>s5+YxbKrM~@%> zSW}aoo!w-=$H=H@v^5(=@nLRmoO<%xH*XZZ=j%&Kx^OccW%A#?{fatlsc&Qy_41`e zKu=jPLsVqsHC;-txv|>MpA+Vbz0h2@DqOO%x-mUFyV5EjHP c-3Ll$V#^y?Zx5e`$R^Gyl;eM{FD&+Zq~Nmggr|SAAJnSd^3s zQ?+9&K76pXvr~|hoAfMLnj06{wynIfa(HlX{e`Yu|2yo$ACREzvzeX!-RYVbevdaa zR$CfLzeh|ZVq05UI9XUSPgOEHIgJCiY$`syn5+@Led9-LO54+?*Hil?CMMp!%Ne33 zz#78N&JK)_kdQ!3Iuy#je!~W*&Y}lui{oeRL`N5TPW}Y?BJwW>jg)B@Ee?tC^C#i$ zLatx$68kXDS79q1D{1*MCB^pKxgSkUyH8cn+gnXos4I)JYwPIT)DfPWot^Yl+_fun zn|2J|nLl84d0Jm4-rUqQgn4Li5O-xg9i6<#SX);)pe4#_Vjb_)?Hf0=EG# ~7TWjk~ ze0X4~1ILcdetl+K|FUc4miJ$^XCjI5!eC?S>gp=s%kSU6cc1wLNPjybg45U72scn) zzYg#T6_=&i(bo3PojV__q((+Ywrt({_U+r?*n;!VPMkc6{*z>0sz&NRC=eMVY3Yj= zX>M)~oGK_NDE~l$pMRGPx~Ds~TX)~W!a`kwQdz$D)~#Eut-HIoIkgfbVwWm;NwNwG z2lM^rTIa&6IyzPtru*klad2=bCx-Lh1VCa7`G6X)cxC2#sg zquEzR;TGH6r#}Cyjcc@fh0UAy_t@A4nRtdB3kK^)zh~KL8tUqXJ%0SFQ=-~R3eDy6 zSeqO=pLCqri4*6XoI3044GavNXNQilu|=T~V8d_b=GF$%fBUx3cjbh-`Y-$vUteFW zujuG#fDVQbwLF)e3Luf;p&=bzUF@>h8YKW3Gqd}Jg)0%ooNR1@0s@boKOY$%?`&*z zU0uGsckf=npN8c`5FH>AfOtUb1zI1fNYCYY7xamB>(*6${Nf6Lze((PK}HeaZx+6c zpTizPyO!CtD^A%bFDl9i&(zCn2~h2w xoH0K{RY^Y{F4;y>%;-mAu5H@=y*ubK-^#`MJ4RC0kW| z%?!F5Q? jH`07*9WCv?efvNQ znrdsqbc8p2%r(2<;xhU4*fS!v--{RLuUyFkNqX^OXM8Q-l>7rdJo>FgGRKa6jfsiz zSk4_9I=6i4! s45Cv`%v2mBZuXK({xZKX)`TVoR*! zC?J0(eC^WciLF~7_|r1o))WG>ZEB)2y%t&5Y4Y~mF$078W=m3-%3dj{f#G2`lq+_2 zi%gqC;Gg&I{kXp2Ncxw(4&Mq+E$ P)2H%3J$|yq`Z5Mb z;d-K?s9sPCt3xRPT)>C 8OxRJrZ9YR7!&CC?NKkE`I z9z1{k9K|y@xUwsRYVE;{e!NWBe!hU9Aib9Rj0EB@xA{2@W#ET;o-RS9p>_Yd%ltD6 zTn(JbG7;Y#Mw3sYW3Hc|7#SPOtGyVaW`mpQ?!I?KO={CIW8<{PkB0^Zme1=_23a4x zamCBasXg!5@#8=QH2JJLa$u0)2!H7!<1gjjf87b-TwF{VYs+=kmyp_&X(FzisB*7{ zq%p9RepEEP^5iS4YmXlbk7!BtVeR+!_Ey!@D9Fk#_Y@^o_Hc1?ADk)On3|q0CnXh; zkf0osY_Vg<4h9B>mJlngVhTX`%G AjeB%)w$5d7Q)tX}bg|25JBP0Zepn z?omu|lu>|^p`g%OT^&+;M& 57BH;!r3;j*LgVuEf8YSm#<$hU%4U>;JY{|A{sr^-*0DQbHvPSIXkrO zzMPSnnYX80khR9GExDvMWz{E-AD`LM|CFZ7C(L`mEe}Pt>#VkRXliO-x>1@G{f71H zA<*Tx4K_~o)i7<5o%m{O+4t)g-ML@Ay-*9>E?xSm4@esjpoT_${``x_j~`>7sp6xL zd |tpssj813Rf$_=ox4z!UOatDM jMw%@+_{4Sp4woKDx}~s z_NAdA7X%CKkwq0f`6UP%6BBR2=M5YZA1W&|PQ2B!w1h^Mo|&16O%Fc1ZCfA22N@YM zyv2p$XM~xF0Dwe( Ogl#0#l_{C49$4zxbYup?Ph2w zZV`TGw`;Cn?3OKCUT0;Y`hW=2NDAQT&99f2k@;QfPkZoNdP>ShE-up}M+8Jg@7=$z zlh$M^{tW qm|t2Hif$i7L-3pwP}PKR^XZcgIvOwr z=r^ExXJ=<^?fHqHbaZsn{dIHG(@TFEJ-Q*9CCaKsI8UI0!_~Q^2l^HkJjzp0@9 IMAvS22Vej+vHp52@cMB{9r!XGUy%aUTaAhu1L3NKIpdTyFE zVL~NU`j;5k(PKE?3J{c hS$4XQnqW-_jWnuZns{JEm1Q8=#(WGZ)H#b3Y9oIh`FY|O#J((v_b z>XRp&tgHgtw#}9?sSFGb?&751v?&^j9_r5BavL}tcoYn*R6c9OyE>1PlTV#Eu{pf5 ztmhW<5hxCkk?BvLsuCf=y)esV<%bN-%gyaI(N!7{KwYX}S9xnI*xJD$eUvh^;9T#8 z*N`7kSSH@1G`F<0fElA={GORHNdMB!U1lYv_dwnqRryrqE$AHdzUdIvQc{GrZQHhE z#~>gO5IQh34-XGk9m@H SUC*w`2_pSYM<{H{~#-rfc8-d)1d{jjc4MH&|dNF7iQ zRKcrsMQA$;3{d112M4jx^7s8Tqk7=ofiT+RVE^8A^ZqcCRW_uilC7 zGS6;&M@L5o2peS%3<8TU*hvS_3Fghsn>TZE<^h)FY#-oiY^6=r)rI%&jV|kU^YDm| zi{lS)JbxbV8(@9+`Ezk!_6PUxx1}Ze-eA7B>l96VZBWksMGfH`I>?iBAOIg@cb>ci zO_h7!1>)jtce9x9>{nwb9Qe{fqT%+9_#j|GpxOM8Ik@i4&d$zLDJM#rFqcV@bx`ro z*RD|%m^uIM=nCVSx}%o{`p;m|T2ex|wx2I@Re^6yty)XhDSed(P!|V@Nz2RL%LfS} zJ9oZ-!kBsl(%Iy@)7Yv2oK20518!H~tf1JrxMX7EMMfH4x+K#P8ypze9gTMmy>X+X z;IhB9$(b{c0nY( lv(x910w3INEY;&d2;{liV9=p8OxsF3 nOJGcNV3e5=&4{#P*h05{-m1 eqyVS3L$wTFR#kStTy$FzH45*U-EKt_UzlYq3Anx7uA-9 z0$oUlBc~^>@y=5I1#L=b701GF-0-WpR7xE$-aLD2=`rEIwhsRuE&TQK%2!S)mMuUo z0M$8n?i^M}7W6`6 0nqN2J|VX}dG!e {iRomo^|{Jsil6 h3_6*U$)l^vDKJ_I=<6a4BH+ zyOEJ(XzjD;hCW?tw{FBoDo{fi3Y;l+MEKpa?+P{CnRf #vRH+3=uSe^_msQk>{ppCwlQUy zURy6?dM0ag-|`CKrXXFQG^A3_g{$ElDZGDY3#**N4i@aFRa8-dgyu;v);sBmrUIw0 zUeoGz+FC=hMo*6E&Ye43-<|irs8Z^+SJ^JtF#QW)3v3LyJ)qTpU;c?hYU=6&0e~!r z(wcDHmA2BSZEgMh{ZVy`zzcnRd}#dnMMa?;?U0c0g_`2!<;5C8y^~tlt8;v0L|jB9 zHX@?_#}8;LUNZv?K)eYFJfhJzjAdPZs##j{uC`9VvsqbQhR5?*H+~{p?bNB{`1sZk zHWAz@a06yl)L>^12dTY_zSmHTL1el_7F%0e6P3J k;hT~@@;%e|op|g|@ z_i&WLta$S5nP32@b-7LE!(%0PbX34<6)U7}R`&1*0PAF*Z@q+u0^xjO!CN}cd-CTY z%4;S4)2%;#FslMu`^Wknr!dl@pbq-?EWpT mJRj~7Z(>X36Hq+CR5iz&9#15I4g6Vp`oEme+o%0wDq!A?!({Ki&E3j zRFs!zejkAuH#6gAXV>3JT3bOq_md&4#bjExQ}%oMg+T96`FK&Wdx-rX>_pz|%(Wl* z-0O_r`eTi}JjXkyOF>Xq{#S8<|GeiR)9qiZe8;K0s~V6MZ2$r~M3$wYuVVCNz6*V^ zyl`Kg$Rq*Vcw}shXZ47d)<@iR{Ri?WYFHMPeTm-iIha(IBN7vtMj2?hdlpt;jr^Se zo#?w5qLsS1un>3m?nVxdwb7qg_V@#@1+?) FNAY)oV+ns-8)B^k+WZ zr3ho_sHqCpOLI7Tc74LTH*ZW%oJf#&rz?9E5fOn7iO|4K%cA9yYgCp#v&Sx6c=_;* zo}L~clAWE%>Ye?3_!In(uiw7mVTf+u&KH1Zs&`+u8`4W#+x@?3NCWl!R8; AnVnuR{ _Vi;FwSKn#lc zo3l-ipFV~4# y+d75XN14lb<|k`Tkwb^N1Sm4bbA^(o*a9?}g{nCnlUJuaOnk z1BXeZHGDW0RfInPL-1H|$8qWCr4X<$T)5!RVQgS 1ip*D--`9Ha0lid*0iZOb#5yL)1if?6{1#fYc74Zf0%{p;AalXyTv= zjeo Z~p}97+6MO zK>_F>9>vpV&$#F-KyLa!#rZRXE;b=&fY1$#Du4`B0~iqy13+|9VPUoJk&^0~^h7-X ztdWzGgYq>0rjhV)?KFF<2U#xrM?#^#J9N}5ch_ =oA7!1A7uBnx|x|7807o>wObs2Zzt^m0WNgy`)Gd- zAcXG1MWri%gJ8||jf6#C!m2}?@91VuP9hy0K3db)ukCLgI4rR42YPxg!toC C? zAD3)qM^)QObKZn>gnPJNS;=>KQUi6WG?5=d6*579cZhNTLHkX?9s#nQTJSz~st4N$ zh>L?G7F@9)&G`6n1PuysJzxP4s({2m?P#5b(A`0j^#mfpbe_L>0f8MW1A!J4>4U1O zi2eA^chdqs()cGmdL(`E*Qd&G-Yk>nIXOAlZU<~0j`LDPRinG=KpLC$^lW2M#g+&8 z1~(-pK|8`S6bQgV#8YMBQM?-w!ROgO(vn$*s6o}l;LKnX7&siS-?Oty?n4_bTK-eR zlJ`D^1O?~?)`|yy63@6)5=Jq=D6S5z>Vc9MssNg9OIexV-o0NxexzHI$W2eLZf{@d zt&Rd)fU|_1-u&$wVnqIAeEt|ptBnovJGriXU@O#pATH2xoz9;>ooNEJK;*~13aH0A zrsjBiU-9x3woF+#8*E=tVir{hJHbr66&uj6kxCJel+@>AMmC05*<0586f9n3Do{G$ zUKcM<)$k9$dHq@-sv7qM{ALSdT7G`(r%&|!$OSARG(%s8r!ko|069u|WyUC={wCM% z7Dt&sM5pxFbu|G))KY^Y$M3HphqUFm9IVe^Dz=z}G%vk-H@>t*^}1>jS~Fg#Lqx2x zm(@=*GAen|SWEplgJ6o5HlGKz?&|Z)nxk?06p`j8UkLs^@dHXE_;$!lCk1~bF<3of zwfJCK(`0Bpocu{9iu(X}F){4XTIQKH<*hNO ;_y8zCahAYj)K9lu_DB^Rwq$u-`h&dZDCZlDV2Jjo6A)u zB`BEO)@CLVTVs<6iv>!GsDy+CSsDe0D5kMYqUn0#@djkAr>6%+1rHwU9CF|~No-hm z50By{X)!bhNX;utb0WgRbaeY1TV6SJDuYoQ8a8xwSuMAxK782K)01_+RYoEfHbC}; zc6nHUV8OY0d1z3a+}whHaLI-Cp|LTEZQBBQr+&}Pp?YGa-Hne&d~0o@jETr^X=w@a zJuxwXgcn>d;99s@RUax(jr7ljPl@m23HLx#J9x0nV+LsPh`0Ch_BvPY+J%*IAA{ka zKO5WH#OKejU1f6aotA;T_$s!P*7wVXe{<}3CvsFoMd>73*ReUiHfvTGi>D;q^d|f* z;`cuod-DTfll1+7JqV7V&yY35#>OM&=7mq6o}1V< 0w5B4`1$Xz z`$8p)t_D#=?OQ<~*hqKi$dRdvFm7xIV2Fcbd3r*u{k8GNCr-$J+=Lh-04>+ 1p zsEE*2d_6sL($fbAR0Ig~b4#n;76qQy>W*phF=N-k6J}9G3I=hON|o&cZt_vp(4RnE zzjUQrW69>4NxY%H`+g80Rz}%KImjAjFjy;498i{7;T3l)D=T&Npr=oVP@AxH*ClRx zHCMWkXQ8dg2eFJ WW;$!PFy@bhsAu;xZC GcbWlPtlioD)Ojm8XCHQrXdle=<<^~u}&na8cbG*ndq%t{Ne=zzmT}NqUVkP z0|$p^+1Yb|-w1nc2%{EWGL#Ha`{^u;w?+a1MXyv!92rJ(sw(B>OIT)geXd!rU!yTV zO2&O;Rt16LcB!D{3GeUk&%Qi;=DPCT&4UP`))lX ?=dj8U{UPT(;9aRWcM;yOdGc2Hx^KAO zvtHQZPc@nhcy{t1N{V+|#i|2Tfd9h?K!h){J3U;V|K0E)#{l D zK&1VdGoX6ua4&xSqVd||Z7?XgeS1l;Qg?SZLMMo?{CIc%q_uStl2XBCE*>7^!@~-$ zy+k!${7WZCN5xAcCdf)EAL75ZpP7~Qy$S;;@ua*hS(+`oMZ oRg=@DeUwytp|`J-Okoj_~T) zSERL7w1t))t0~SU@plBBGg43!#?SwUjNrGhRQe(Lzly3R$3#c>b#=YEGCO3HrpF+G zC^llQf5lS{J#0iYBpSx_A>bQG))qj+q)c=F`Qo}WK&@v0<1iiEiWU>@6K z{|1b|bT332>i)Hj8#lr~N=-@GqT)*?ZDtZ2Kd5vHXFy1X2L_<}u!g8zyf_V$C%^#C zgPYq7X?2?Sz+0?(fN;C=8=K~v5M|mb=NdpZqIIzE1XzNst>_+GqP+kurl*ILbpyfx ztn&xJy8Yem(OG+U7ga`C&m`!&pPwI$f2#x1arYx4UO}rxXVz4?dwUSp&lEhQ$w`-s z7XgBC?@=PoUAVCNE8dCP9i=nNZSct6y>Izzu3Wy1EZ!^(D~R4fzX@z1dn6p-&j7@L zCetdv2Er{uk`m@ABB}tKcvag@^;CvKvCvOcZf|N5M1A6823D1#hpL%?N1T~C3FU>J zp8nzCk}uk8ziQ*5kU 7SZT? zcki~KxI |Mz!3x;$d~|Nfa&Bg;2!Or=6P=*W}*5}Q 3`#`CK8!?p1 z%m2ovoUSxh?w~*s?6}fx6ciNxv?~Y<)ze$i{Y_p(