From 8ddb9a6be04cd6e8ec1bf62a0c07a792ffe0a738 Mon Sep 17 00:00:00 2001
From: Khoi Hoang <57012152+khoih-prog@users.noreply.github.com>
Date: Mon, 26 Apr 2021 16:33:27 -0400
Subject: [PATCH] Major release v1.2.0
### Major Releases v1.2.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
6. 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)
7. To permit auto-reset after configurable timeout if DRD/MRD or non-persistent forced-CP. Check [**Good new feature: Blynk.resetAndEnterConfigPortal() Thanks & question #27**](https://github.com/khoih-prog/Blynk_WM/issues/27)
8. Fix rare Config Portal bug not updating Config and dynamic Params data successfully in very noisy or weak WiFi situation
9. Tested with [**Latest ESP32 Core 1.0.6**](https://github.com/espressif/arduino-esp32) for ESP32-based boards.
10. Update examples
---
CONTRIBUTING.md | 6 +-
README.md | 338 +-
examples/ESP32_BLE_WF/ESP32_BLE_WF.ino | 73 +-
examples/ESP32_BLE_WF/defines.h | 25 +-
examples/ESP32_BT_WF/ESP32_BT_WF.ino | 74 +-
examples/ESP32_BT_WF/defines.h | 14 +
.../Geiger_Counter_BLE/Geiger_Counter_BLE.ino | 70 +-
examples/Geiger_Counter_BLE/defines.h | 14 +
.../Geiger_Counter_BT/Geiger_Counter_BT.ino | 74 +-
examples/Geiger_Counter_BT/defines.h | 14 +
.../Geiger_Counter_OLED.ino | 70 +-
examples/Geiger_Counter_OLED/defines.h | 14 +
.../Geiger_Counter_OLED_BT_BLE_WF.ino | 72 +-
.../Geiger_Counter_OLED_BT_BLE_WF/defines.h | 14 +
.../Geiger_Counter_OLED_BT_WF.ino | 60 +-
examples/Geiger_Counter_OLED_BT_WF/defines.h | 14 +
examples/PET_Check/PET_Check.ino | 26 +-
examples/PET_Check/defines.h | 14 +
library.json | 4 +-
library.properties | 2 +-
src/BlynkSimpleEsp32_Async_BLE_WF.h | 244 ++
src/BlynkSimpleEsp32_Async_BT_WF.h | 293 ++
src/BlynkSimpleEsp32_Async_WF.h | 144 +
src/BlynkSimpleEsp32_Async_WFM.h | 2885 +++++++++++++++++
src/BlynkSimpleEsp32_WFM.h | 5 +-
25 files changed, 4360 insertions(+), 203 deletions(-)
create mode 100644 src/BlynkSimpleEsp32_Async_BLE_WF.h
create mode 100644 src/BlynkSimpleEsp32_Async_BT_WF.h
create mode 100644 src/BlynkSimpleEsp32_Async_WF.h
create mode 100644 src/BlynkSimpleEsp32_Async_WFM.h
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ed2922d..4098912 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -15,7 +15,7 @@ If you don't find anything, please [open a new issue](https://github.com/khoih-p
Please ensure to specify the following:
* Arduino IDE version (e.g. 1.8.13) or Platform.io version
-* `ESP32` Core Version (e.g. ESP32 core v1.0.4)
+* `ESP32` Core Version (e.g. ESP32 core v1.0.6)
* Contextual information (e.g. what you were trying to achieve)
* Simplest possible steps to reproduce
* Anything that might be relevant in your opinion, such as:
@@ -27,9 +27,9 @@ Please ensure to specify the following:
```
Arduino IDE version: 1.8.13
-ESP32 Core Version 1.0.4
+ESP32 Core Version 1.0.6
OS: Ubuntu 20.04 LTS
-Linux xy-Inspiron-3593 5.4.0-64-generic #72-Ubuntu SMP Fri Jan 15 10:27:54 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
+Linux xy-Inspiron-3593 5.4.0-72-generic #80-Ubuntu SMP Mon Apr 12 17:35:00 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
Context:
The board couldn't autoreconnect to Local Blynk Server after router power recycling.
diff --git a/README.md b/README.md
index cad8176..2eebf2a 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,7 @@
* [Features](#features)
* [Currently supported Boards](#currently-supported-boards)
* [Changelog](#changelog)
+ * [Major Releases v1.2.0](#major-releases-v120)
* [Releases v1.1.1](#releases-v111)
* [Major Releases v1.1.0](#major-releases-v110)
* [Major Releases v1.0.6](#major-releases-v106)
@@ -31,6 +32,7 @@
* [Use Arduino Library Manager](#use-arduino-library-manager)
* [Manual Install](#manual-install)
* [VS Code & PlatformIO](#vs-code--platformio)
+* [Note for Platform IO using ESP32 LittleFS](#note-for-platform-io-using-esp32-littlefs)
* [HOWTO Use analogRead() with ESP32 running WiFi and/or BlueTooth (BT/BLE)](#howto-use-analogread-with-esp32-running-wifi-andor-bluetooth-btble)
* [1. ESP32 has 2 ADCs, named ADC1 and ADC2](#1--esp32-has-2-adcs-named-adc1-and-adc2)
* [2. ESP32 ADCs functions](#2-esp32-adcs-functions)
@@ -42,6 +44,16 @@
* [ 3. Example of Default Credentials](#3-example-of-default-credentials)
* [ 4. How to add dynamic parameters from sketch](#4-how-to-add-dynamic-parameters-from-sketch)
* [ 5. If you don't need to add dynamic parameters](#5-if-you-dont-need-to-add-dynamic-parameters)
+ * [ 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)
* [Why using this BlynkESP32_BT_WF with MultiWiFi-MultiBlynk features](#why-using-this-blynkesp32_bt_wf-with-multiwifi-multiblynk-features)
* [Important Notes for using Dynamic Parameters' ids](#important-notes-for-using-dynamic-parameters-ids)
* [Examples](#examples)
@@ -54,6 +66,8 @@
* [ 7. Geiger_Counter_OLED_BT_BLE_WF](examples/Geiger_Counter_OLED_BT_BLE_WF)
* [ 8. PET_Check](examples/PET_Check)
* [So, how it works?](#so-how-it-works)
+ * [ 1. Without SCAN_WIFI_NETWORKS](#1-without-scan_wifi_networks)
+ * [ 2. With SCAN_WIFI_NETWORKS](#2-with-scan_wifi_networks)
* [Example ESP32_BLE_WF](#example-esp32_ble_wf)
* [1. File ESP32_BLE_WF.ino](#1-file-esp32_ble_wfino)
* [2. File defines.h](#2-file-definesh)
@@ -121,12 +135,30 @@ Now from Version 1.0.2, you can eliminate `hardcoding` your Wifi and Blynk crede
This [**BlynkESP32_BT_WF** library](https://github.com/khoih-prog/BlynkESP32_BT_WF) currently supports these following boards:
1. **ESP32-based boards using EEPROM, SPIFFS or LittleFS**.
+
+#### Not yet supported Boards
+
+
+ 1. **ESP32-S2 and ESP32-C3**
---
---
## Changelog
+### Major Releases v1.2.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
+ 6. 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)
+ 7. To permit auto-reset after configurable timeout if DRD/MRD or non-persistent forced-CP. Check [**Good new feature: Blynk.resetAndEnterConfigPortal() Thanks & question #27**](https://github.com/khoih-prog/Blynk_WM/issues/27)
+ 8. Fix rare Config Portal bug not updating Config and dynamic Params data successfully in very noisy or weak WiFi situation
+ 9. Tested with [**Latest ESP32 Core 1.0.6**](https://github.com/espressif/arduino-esp32) for ESP32-based boards.
+10. Update examples
+
### Releases v1.1.1
1. Add functions to control Config Portal from software or Virtual Switches. Check [How to trigger a Config Portal from code #25](https://github.com/khoih-prog/Blynk_WM/issues/25)
@@ -189,9 +221,10 @@ With this libraries modifications, we now can compile with both options, then se
## Prerequisites
1. [`Arduino IDE 1.8.13+` for Arduino](https://www.arduino.cc/en/Main/Software)
-2. [`Blynk library 0.6.1+`](https://github.com/blynkkk/blynk-library/releases)
-3. [`ESP32 core 1.0.4+`](https://github.com/espressif/arduino-esp32/releases) for ESP32 boards
+2. [`Blynk library 0.6.1+`](https://github.com/blynkkk/blynk-library/releases). Never use the **beta versions** or your request for support will be ignored..
+3. [`ESP32 Core 1.0.6+`](https://github.com/espressif/arduino-esp32) for ESP32-based boards. [![Latest release](https://img.shields.io/github/release/espressif/arduino-esp32.svg)](https://github.com/espressif/arduino-esp32/releases/latest/)
4. [`ESP_DoubleResetDetector v1.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).
+5. [`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).
---
@@ -218,6 +251,33 @@ The best and easiest way is to use `Arduino Library Manager`. Search for `BlynkE
---
---
+### Note for Platform IO using ESP32 LittleFS
+
+#### Necessary only for esp32 core v1.0.6-
+
+From esp32 core v1.0.6+, [`LittleFS_esp32 v1.0.6`](https://github.com/lorol/LITTLEFS) has been included and this step is not necessary anymore.
+
+In Platform IO, to fix the error when using [`LittleFS_esp32 v1.0`](https://github.com/lorol/LITTLEFS) for ESP32-based boards with ESP32 core v1.0.4- (ESP-IDF v3.2-), uncomment the following line
+
+from
+
+```
+//#define CONFIG_LITTLEFS_FOR_IDF_3_2 /* For old IDF - like in release 1.0.4 */
+```
+
+to
+
+```
+#define CONFIG_LITTLEFS_FOR_IDF_3_2 /* For old IDF - like in release 1.0.4 */
+```
+
+It's advisable to use the latest [`LittleFS_esp32 v1.0.5+`](https://github.com/lorol/LITTLEFS) to avoid the issue.
+
+Thanks to [Roshan](https://github.com/solroshan) to report the issue in [Error esp_littlefs.c 'utime_p'](https://github.com/khoih-prog/ESPAsync_WiFiManager/issues/28)
+
+---
+---
+
### HOWTO Use analogRead() with ESP32 running WiFi and/or BlueTooth (BT/BLE)
Please have a look at [**ESP_WiFiManager Issue 39: Not able to read analog port when using the autoconnect example**](https://github.com/khoih-prog/ESP_WiFiManager/issues/39) to have more detailed description and solution of the issue.
@@ -461,7 +521,82 @@ uint16_t NUM_MENU_ITEMS = 0;
```
+#### 6. To use custom HTML Style
+
+```
+const char NewCustomsStyle[] /*PROGMEM*/ = "";
+
+...
+
+Blynk.setCustomsStyle(NewCustomsStyle);
+```
+
+#### 7. To use custom Head Elements
+
+
+```
+Blynk.setCustomsHeadElement("");
+```
+
+#### 8. To use CORS Header
+
+```
+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
+```
+
---
+---
+
### Why using this [BlynkESP32_BT_WF](https://github.com/khoih-prog/BlynkESP32_BT_WF) with MultiWiFi-MultiBlynk features
@@ -578,12 +713,30 @@ After you connected, please, go to http://192.168.4.1 or the configured AP IP. T
Enter your WiFi and Blynk Credentials (Server, Port, WiFi/BT/BLE tokens)
+
+### 1. Without SCAN_WIFI_NETWORKS
+
+
+
+### 2. With SCAN_WIFI_NETWORKS
+
+
+
+
+
+
+
Then click `Save`. After you restarted, you will see your built-in LED turned OFF. That means, it connected to your Blynk server successfully.
+
+
+
+
+
---
---
@@ -592,6 +745,18 @@ Then click `Save`. After you restarted, you will see your built-in LED turned OF
#### 1. File [ESP32_BLE_WF.ino](examples/ESP32_BLE_WF/ESP32_BLE_WF.ino)
```cpp
+/****************************************************************************************************************************
+ Important Notes:
+ 1) Sketch is ~0.9MB of code because only 1 instance of Blynk if #define BLYNK_USE_BT_ONLY => true
+ 2) Sketch is very large (~1.3MB code) because 2 instances of Blynk if #define BLYNK_USE_BT_ONLY => false
+ 3) To conmpile, use Partition Scheem with large APP size, such as
+ a) 8MB Flash (3MB APP, 1.5MB FAT) if use EEPROM
+ b) No OTA (2MB APP, 2MB SPIFFS)
+ c) No OTA (2MB APP, 2MB FATFS) if use EEPROM
+ d) Huge APP (3MB No OTA, 1MB SPIFFS) <===== Preferable if use SPIFFS
+ e) Minimal SPIFFS (1.9MB APP with OTA, 190KB SPIFFS)
+ *****************************************************************************************************************************/
+
#include "defines.h"
#include "Credentials.h"
#include "dynamicParams.h"
@@ -693,6 +858,11 @@ void checkStatus()
char BLE_Device_Name[] = "GeigerCounter-BLE";
+#if USING_CUSTOMS_STYLE
+const char NewCustomsStyle[] /*PROGMEM*/ = "";
+#endif
+
void setup()
{
Serial.begin(115200);
@@ -756,6 +926,23 @@ void setup()
//Blynk.setSTAStaticIPConfig(IPAddress(192, 168, 2, 232), IPAddress(192, 168, 2, 1), IPAddress(255, 255, 255, 0),
// IPAddress(4, 4, 4, 4), IPAddress(8, 8, 8, 8));
+
+ //////////////////////////////////////////////
+
+ #if USING_CUSTOMS_STYLE
+ Blynk.setCustomsStyle(NewCustomsStyle);
+ #endif
+
+ #if USING_CUSTOMS_HEAD_ELEMENT
+ Blynk.setCustomsHeadElement("");
+ #endif
+
+ #if USING_CORS_FEATURE
+ Blynk.setCORSHeader("Your Access-Control-Allow-Origin");
+ #endif
+
+ //////////////////////////////////////////////
+
// Use this to default DHCP hostname to ESP8266-XXXXXX or ESP32-XXXXXX
//Blynk.begin();
// Use this to personalize DHCP hostname (RFC952 conformed)
@@ -824,23 +1011,9 @@ void displayCredentials()
Serial.println(myMenuItems[i].pdata);
}
}
-#endif
-void loop()
+void displayCredentialsInLoop()
{
-#if BLYNK_USE_BLE_ONLY
- Blynk_BLE.run();
-#else
- if (USE_BLE)
- Blynk_BLE.run();
- else
- Blynk_WF.run();
-#endif
-
- timer.run();
- checkStatus();
-
-#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
static bool displayedCredentials = false;
if (!displayedCredentials)
@@ -859,7 +1032,27 @@ void loop()
}
}
}
-#endif
+}
+
+#endif
+
+void loop()
+{
+#if BLYNK_USE_BLE_ONLY
+ Blynk_BLE.run();
+#else
+ if (USE_BLE)
+ Blynk_BLE.run();
+ else
+ Blynk_WF.run();
+#endif
+
+ timer.run();
+ checkStatus();
+
+#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
+ displayCredentialsInLoop();
+#endif
}
```
@@ -878,7 +1071,7 @@ void loop()
#define ESP32_BLE_WF_DEBUG true
#define DOUBLERESETDETECTOR_DEBUG true
-#define BLYNK_WM_DEBUG 3
+#define BLYNK_WM_DEBUG 1
// Not use #define USE_LITTLEFS and #define USE_SPIFFS => using SPIFFS for configuration data in WiFiManager
// (USE_LITTLEFS == false) and (USE_SPIFFS == false) => using EEPROM for configuration data in WiFiManager
@@ -898,6 +1091,15 @@ void loop()
#define EEPROM_START 0
#endif
+/////////////////////////////////////////////
+
+// Add customs headers from v1.2.0
+#define USING_CUSTOMS_STYLE true
+#define USING_CUSTOMS_HEAD_ELEMENT true
+#define USING_CORS_FEATURE true
+
+/////////////////////////////////////////////
+
// Force some params in Blynk, only valid for library version 1.0.1 and later
#define TIMEOUT_RECONNECT_WIFI 10000L
#define RESET_IF_CONFIG_TIMEOUT true
@@ -918,6 +1120,20 @@ void loop()
#if !BLYNK_USE_BLE_ONLY
#if USE_BLYNK_WM
#define USE_DYNAMIC_PARAMETERS true
+
+ /////////////////////////////////////////////
+
+ #define REQUIRE_ONE_SET_SSID_PW false
+
+ #define SCAN_WIFI_NETWORKS true
+
+ // To be able to manually input SSID, not from a scanned SSID lists
+ #define MANUAL_SSID_INPUT_ALLOWED true
+
+ // From 2-15
+ #define MAX_SSID_IN_LIST 8
+
+ /////////////////////////////////////////////
#warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP)
#include
@@ -1125,7 +1341,7 @@ The following is the sample terminal output when running example [ESP32_BLE_WF](
```
Starting ESP32_BLE_WF using SPIFFS without SSL on ESP32_DEV
-BlynkESP32_BT_WF v1.1.1
+BlynkESP32_BT_WF v1.2.0
ESP_DoubleResetDetector v1.1.1
GPIO14 HIGH, Use WiFi
USE_BLYNK_WM: Blynk_WF begin
@@ -1183,7 +1399,7 @@ FF[9799112] id: = HueNet1
```
Starting ESP32_BLE_WF using SPIFFS without SSL on ESP32_DEV
-BlynkESP32_BT_WF v1.1.1
+BlynkESP32_BT_WF v1.2.0
ESP_DoubleResetDetector v1.1.1
GPIO14 HIGH, Use WiFi
USE_BLYNK_WM: Blynk_WF begin
@@ -1261,7 +1477,7 @@ FFFFF
```
Starting ESP32_BLE_WF using SPIFFS without SSL on ESP32_DEV
-BlynkESP32_BT_WF v1.1.1
+BlynkESP32_BT_WF v1.2.0
ESP_DoubleResetDetector v1.1.1
GPIO14 HIGH, Use WiFi
USE_BLYNK_WM: Blynk_WF begin
@@ -1347,7 +1563,7 @@ CP Button Hit. Rebooting
ets Jun 8 2016 00:22:57
Starting ESP32_BLE_WF using LITTLEFS without SSL on ESP32_DEV
-BlynkESP32_BT_WF v1.1.1
+BlynkESP32_BT_WF v1.2.0
ESP_DoubleResetDetector v1.1.1
GPIO14 HIGH, Use WiFi
USE_BLYNK_WM: Blynk_WF begin
@@ -1428,7 +1644,7 @@ Persistent CP Button Hit. Rebooting
ets Jun 8 2016 00:22:57
Starting ESP32_BLE_WF using LITTLEFS without SSL on ESP32_DEV
-BlynkESP32_BT_WF v1.1.1
+BlynkESP32_BT_WF v1.2.0
ESP_DoubleResetDetector v1.1.1
GPIO14 HIGH, Use WiFi
USE_BLYNK_WM: Blynk_WF begin
@@ -1519,6 +1735,19 @@ Sometimes, the library will only work if you update the board core to the latest
## Releases
+### Major Releases v1.2.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
+ 6. 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)
+ 7. To permit auto-reset after configurable timeout if DRD/MRD or non-persistent forced-CP. Check [**Good new feature: Blynk.resetAndEnterConfigPortal() Thanks & question #27**](https://github.com/khoih-prog/Blynk_WM/issues/27)
+ 8. Fix rare Config Portal bug not updating Config and dynamic Params data successfully in very noisy or weak WiFi situation
+ 9. Tested with [**Latest ESP32 Core 1.0.6**](https://github.com/espressif/arduino-esp32) for ESP32-based boards.
+10. Update examples
+
### Releases v1.1.1
1. Add functions to control Config Portal from software or Virtual Switches. Check [How to trigger a Config Portal from code #25](https://github.com/khoih-prog/Blynk_WM/issues/25)
@@ -1593,29 +1822,34 @@ Submit issues to: [BlynkESP32_BT_WF issues](https://github.com/khoih-prog/BlynkE
## DONE
- 1. Permit EEPROM size and location configurable to avoid conflict with others.
- 2. More flexible to configure reconnection timeout.
- 3. For fresh config data, don't need to wait for connecting timeout before entering config portal.
- 4. If the config data not entered completely (SSID, password, Server and Blynk tokens), entering config portal
- 5. Correct the operation of BUILTIN_LED
- 6. Reduce EEPROM size to 2K from 4K to avoid ESP_ERR_NVS_NOT_ENOUGH_SPACE error.
- 7. Add RFC952 hostname
- 8. Add configurable Config Portal IP, SSID and Password
- 9. Add configurable Static IP, GW, Subnet Mask and 2 DNS Servers' IP Addresses.
- 10. Use dynamically alocated Config Portal WebServer
- 11. Fix BT/BLE login timeout
- 12. Add checksum for config data integrity
- 13. Add clearConfigData() to enable forcing into ConfigPortal Mode when necessary
- 14. Add MultiWiFi feature to enable reconnect to the best / available WiFi AP.
- 15. Add MultiBlynk feature to enable reconnect to the best / available Blynk Server.
- 16. WiFi Password max length is 63, as in WPA2 standards
- 17. Permit to input special chars such as **%** and **#** into data fields.
- 18. Add Dynamic Custom Parameters with checksum
- 19. Add function to configure AP Channel (fixed or random) to avoid channel conflict.
- 20. Default Credentials and dynamic parameters
- 21. **DoubleDetectDetector** to force Config Portal when double reset is detected within predetermined time, default 10s.
- 22. Configurable Config Portal Title
- 23. Re-structure all examples to separate Credentials / Defines / Dynamic Params / Code so that you can change Credentials / Dynamic Params quickly for each device.
+ 1. Permit EEPROM size and location configurable to avoid conflict with others.
+ 2. More flexible to configure reconnection timeout.
+ 3. For fresh config data, don't need to wait for connecting timeout before entering config portal.
+ 4. If the config data not entered completely (SSID, password, Server and Blynk tokens), entering config portal
+ 5. Correct the operation of BUILTIN_LED
+ 6. Reduce EEPROM size to 2K from 4K to avoid ESP_ERR_NVS_NOT_ENOUGH_SPACE error.
+ 7. Add RFC952 hostname
+ 8. Add configurable Config Portal IP, SSID and Password
+ 9. Add configurable Static IP, GW, Subnet Mask and 2 DNS Servers' IP Addresses.
+10. Use dynamically alocated Config Portal WebServer
+11. Fix BT/BLE login timeout
+12. Add checksum for config data integrity
+13. Add clearConfigData() to enable forcing into ConfigPortal Mode when necessary
+14. Add MultiWiFi feature to enable reconnect to the best / available WiFi AP.
+15. Add MultiBlynk feature to enable reconnect to the best / available Blynk Server.
+16. WiFi Password max length is 63, as in WPA2 standards
+17. Permit to input special chars such as **%** and **#** into data fields.
+18. Add Dynamic Custom Parameters with checksum
+19. Add function to configure AP Channel (fixed or random) to avoid channel conflict.
+20. Default Credentials and dynamic parameters
+21. **DoubleDetectDetector** to force Config Portal when double reset is detected within predetermined time, default 10s.
+22. Configurable Config Portal Title
+23. Re-structure all examples to separate Credentials / Defines / Dynamic Params / Code so that you can change Credentials / Dynamic Params quickly for each device.
+24. Add functions to control Config Portal from software or **Virtual Switches**.
+25. Configurable **Customs HTML Headers**, including Customs Style, Customs Head Elements, CORS Header
+26. Permit optionally inputting one set of WiFi SSID/PWD by using `REQUIRE_ONE_SET_SSID_PW == true`
+27. Enforce WiFi PWD minimum length of 8 chars
+28. Enable **scan of WiFi networks** for selection in Configuration Portal
---
---
@@ -1624,11 +1858,19 @@ Submit issues to: [BlynkESP32_BT_WF issues](https://github.com/khoih-prog/BlynkE
1. Thanks to [Crosswalkersam](https://community.blynk.cc/u/Crosswalkersam) for the original code and request to inspire the work. See [Select connection Type via Switch](https://community.blynk.cc/t/select-connection-type-via-switch/43176)
2. Thanks to [Miguel Alexandre Wisintainer](https://github.com/tcpipchip) for working with, developing, debugging, testing and contributing example [PET_Check](examples/PET_Check). See also [nina-w102-ble-detector-presenca-de-pet](https://nina-b302-scanner-presenca.blogspot.com/2020/06/nina-w102-ble-detector-presenca-de-pet.html)
+3. Thanks to [Thor Johnson](https://github.com/thorathome) and [Thor Johnson in Blynk](https://community.blynk.cc/u/thorathome) to test, find bug, suggest and encourage to add those new features in [Blynk_WiFiManager library](https://github.com/khoih-prog/Blynk_WM) v1.0.13, such as Default Credentials/Dynamic Parms, Configurable Config Portal Title, DRD. The powerful [Async_Blynk_WM_Template](examples/Async_Blynk_WM_Template) is written by [Thor Johnson](https://github.com/thorathome) and is included in the examples with his permission.
+Check these new features thanks to his direct contribution and/or enhancement requests :
+ * [How to trigger a Config Portal from code #25](https://github.com/khoih-prog/Blynk_WM/issues/25)
+ * [Good new feature: Blynk.resetAndEnterConfigPortal() Thanks & question #27](https://github.com/khoih-prog/Blynk_WM/issues/27)
+4. 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.2.0
diff --git a/examples/ESP32_BLE_WF/ESP32_BLE_WF.ino b/examples/ESP32_BLE_WF/ESP32_BLE_WF.ino
index 804cb75..aec40c4 100644
--- a/examples/ESP32_BLE_WF/ESP32_BLE_WF.ino
+++ b/examples/ESP32_BLE_WF/ESP32_BLE_WF.ino
@@ -1,12 +1,12 @@
/****************************************************************************************************************************
ESP32_BLE_WF.ino
- For ESP32 using WiFiManager and WiFi along with BlueTooth / BLE
-
+ For ESP32 using WiFi along with BlueTooth BLE
+
BlynkESP32_BT_WF is a library for inclusion of both ESP32 Blynk BT/BLE and WiFi libraries.
Then select either one or both at runtime.
-
+
Based on and modified from Blynk library v0.6.1 https://github.com/blynkkk/blynk-library/releases
- Built by Khoi Hoang https://github.com/khoih-prog/BlynkGSM_ESPManager
+ Built by Khoi Hoang https://github.com/khoih-prog/BlynkESP32_BT_WF
Licensed under MIT license
Original Blynk Library author:
@@ -17,7 +17,7 @@
@date Oct 2016
@brief
- Version: 1.1.1
+ Version: 1.2.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -32,7 +32,8 @@
Auto format SPIFFS. Update examples.
1.1.0 K Hoang 30/12/2020 Add support to LittleFS. Remove possible compiler warnings. Update examples
1.1.1 K Hoang 31/01/2021 Add functions to control Config Portal (CP) from software or Virtual Switches
- Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ 1.2.0 K Hoang 24/04/2021 Enable scan of WiFi networks for selection in Configuration Portal and many new features.
*****************************************************************************************************************************/
/****************************************************************************************************************************
Important Notes:
@@ -147,6 +148,11 @@ void checkStatus()
char BLE_Device_Name[] = "GeigerCounter-BLE";
+#if USING_CUSTOMS_STYLE
+const char NewCustomsStyle[] /*PROGMEM*/ = "";
+#endif
+
void setup()
{
Serial.begin(115200);
@@ -210,6 +216,23 @@ void setup()
//Blynk.setSTAStaticIPConfig(IPAddress(192, 168, 2, 232), IPAddress(192, 168, 2, 1), IPAddress(255, 255, 255, 0),
// IPAddress(4, 4, 4, 4), IPAddress(8, 8, 8, 8));
+
+ //////////////////////////////////////////////
+
+ #if USING_CUSTOMS_STYLE
+ Blynk.setCustomsStyle(NewCustomsStyle);
+ #endif
+
+ #if USING_CUSTOMS_HEAD_ELEMENT
+ Blynk.setCustomsHeadElement("");
+ #endif
+
+ #if USING_CORS_FEATURE
+ Blynk.setCORSHeader("Your Access-Control-Allow-Origin");
+ #endif
+
+ //////////////////////////////////////////////
+
// Use this to default DHCP hostname to ESP8266-XXXXXX or ESP32-XXXXXX
//Blynk.begin();
// Use this to personalize DHCP hostname (RFC952 conformed)
@@ -278,23 +301,9 @@ void displayCredentials()
Serial.println(myMenuItems[i].pdata);
}
}
-#endif
-void loop()
+void displayCredentialsInLoop()
{
-#if BLYNK_USE_BLE_ONLY
- Blynk_BLE.run();
-#else
- if (USE_BLE)
- Blynk_BLE.run();
- else
- Blynk_WF.run();
-#endif
-
- timer.run();
- checkStatus();
-
-#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
static bool displayedCredentials = false;
if (!displayedCredentials)
@@ -313,5 +322,25 @@ void loop()
}
}
}
-#endif
+}
+
+#endif
+
+void loop()
+{
+#if BLYNK_USE_BLE_ONLY
+ Blynk_BLE.run();
+#else
+ if (USE_BLE)
+ Blynk_BLE.run();
+ else
+ Blynk_WF.run();
+#endif
+
+ timer.run();
+ checkStatus();
+
+#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
+ displayCredentialsInLoop();
+#endif
}
diff --git a/examples/ESP32_BLE_WF/defines.h b/examples/ESP32_BLE_WF/defines.h
index 8146ec6..3b06e0a 100644
--- a/examples/ESP32_BLE_WF/defines.h
+++ b/examples/ESP32_BLE_WF/defines.h
@@ -22,7 +22,7 @@
#define ESP32_BLE_WF_DEBUG true
#define DOUBLERESETDETECTOR_DEBUG true
-#define BLYNK_WM_DEBUG 3
+#define BLYNK_WM_DEBUG 1
// Not use #define USE_LITTLEFS and #define USE_SPIFFS => using SPIFFS for configuration data in WiFiManager
// (USE_LITTLEFS == false) and (USE_SPIFFS == false) => using EEPROM for configuration data in WiFiManager
@@ -42,6 +42,15 @@
#define EEPROM_START 0
#endif
+/////////////////////////////////////////////
+
+// Add customs headers from v1.2.0
+#define USING_CUSTOMS_STYLE true
+#define USING_CUSTOMS_HEAD_ELEMENT true
+#define USING_CORS_FEATURE true
+
+/////////////////////////////////////////////
+
// Force some params in Blynk, only valid for library version 1.0.1 and later
#define TIMEOUT_RECONNECT_WIFI 10000L
#define RESET_IF_CONFIG_TIMEOUT true
@@ -62,6 +71,20 @@
#if !BLYNK_USE_BLE_ONLY
#if USE_BLYNK_WM
#define USE_DYNAMIC_PARAMETERS true
+
+ /////////////////////////////////////////////
+
+ #define REQUIRE_ONE_SET_SSID_PW false
+
+ #define SCAN_WIFI_NETWORKS true
+
+ // To be able to manually input SSID, not from a scanned SSID lists
+ #define MANUAL_SSID_INPUT_ALLOWED true
+
+ // From 2-15
+ #define MAX_SSID_IN_LIST 8
+
+ /////////////////////////////////////////////
#warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP)
#include
diff --git a/examples/ESP32_BT_WF/ESP32_BT_WF.ino b/examples/ESP32_BT_WF/ESP32_BT_WF.ino
index 34cd0db..7124f03 100644
--- a/examples/ESP32_BT_WF/ESP32_BT_WF.ino
+++ b/examples/ESP32_BT_WF/ESP32_BT_WF.ino
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/BlynkESP32_BT_WF
Licensed under MIT license
- Version: 1.1.1
+ Version: 1.2.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -24,7 +24,8 @@
Auto format SPIFFS. Update examples.
1.1.0 K Hoang 30/12/2020 Add support to LittleFS. Remove possible compiler warnings. Update examples
1.1.1 K Hoang 31/01/2021 Add functions to control Config Portal (CP) from software or Virtual Switches
- Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ 1.2.0 K Hoang 24/04/2021 Enable scan of WiFi networks for selection in Configuration Portal and many new features.
*****************************************************************************************************************************/
/****************************************************************************************************************************
Important Notes:
@@ -139,6 +140,11 @@ void checkStatus()
char BT_Device_Name[] = "GeigerCounter-BT";
+#if USING_CUSTOMS_STYLE
+const char NewCustomsStyle[] /*PROGMEM*/ = "";
+#endif
+
void setup()
{
Serial.begin(115200);
@@ -199,6 +205,22 @@ void setup()
//Blynk.setSTAStaticIPConfig(IPAddress(192, 168, 2, 232), IPAddress(192, 168, 2, 1), IPAddress(255, 255, 255, 0),
// IPAddress(4, 4, 4, 4), IPAddress(8, 8, 8, 8));
+ //////////////////////////////////////////////
+
+ #if USING_CUSTOMS_STYLE
+ Blynk.setCustomsStyle(NewCustomsStyle);
+ #endif
+
+ #if USING_CUSTOMS_HEAD_ELEMENT
+ Blynk.setCustomsHeadElement("");
+ #endif
+
+ #if USING_CORS_FEATURE
+ Blynk.setCORSHeader("Your Access-Control-Allow-Origin");
+ #endif
+
+ //////////////////////////////////////////////
+
// Use this to default DHCP hostname to ESP8266-XXXXXX or ESP32-XXXXXX
//Blynk.begin();
// Use this to personalize DHCP hostname (RFC952 conformed)
@@ -256,37 +278,25 @@ void setup()
}
#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
-void displayCredentials(void)
+void displayCredentials()
{
Serial.println(F("\nYour stored Credentials :"));
- for (int i = 0; i < NUM_MENU_ITEMS; i++)
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
{
- Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata);
+ Serial.print(myMenuItems[i].displayName);
+ Serial.print(F(" = "));
+ Serial.println(myMenuItems[i].pdata);
}
}
-#endif
-void loop()
+void displayCredentialsInLoop()
{
-#if BLYNK_USE_BT_ONLY
- Blynk_BT.run();
-#else
- if (USE_BT)
- Blynk_BT.run();
- else
- Blynk_WF.run();
-#endif
-
- timer.run();
- checkStatus();
-
-#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
static bool displayedCredentials = false;
if (!displayedCredentials)
{
- for (int i = 0; i < NUM_MENU_ITEMS; i++)
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
{
if (!strlen(myMenuItems[i].pdata))
{
@@ -300,5 +310,25 @@ void loop()
}
}
}
-#endif
+}
+
+#endif
+
+void loop()
+{
+#if BLYNK_USE_BT_ONLY
+ Blynk_BT.run();
+#else
+ if (USE_BT)
+ Blynk_BT.run();
+ else
+ Blynk_WF.run();
+#endif
+
+ timer.run();
+ checkStatus();
+
+#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
+ displayCredentialsInLoop();
+#endif
}
diff --git a/examples/ESP32_BT_WF/defines.h b/examples/ESP32_BT_WF/defines.h
index 194765c..4523d69 100644
--- a/examples/ESP32_BT_WF/defines.h
+++ b/examples/ESP32_BT_WF/defines.h
@@ -60,6 +60,20 @@
#if !BLYNK_USE_BT_ONLY
#if USE_BLYNK_WM
#define USE_DYNAMIC_PARAMETERS true
+
+ /////////////////////////////////////////////
+
+ #define REQUIRE_ONE_SET_SSID_PW false
+
+ #define SCAN_WIFI_NETWORKS true
+
+ // To be able to manually input SSID, not from a scanned SSID lists
+ #define MANUAL_SSID_INPUT_ALLOWED true
+
+ // From 2-15
+ #define MAX_SSID_IN_LIST 8
+
+ /////////////////////////////////////////////
#warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP)
#include
diff --git a/examples/Geiger_Counter_BLE/Geiger_Counter_BLE.ino b/examples/Geiger_Counter_BLE/Geiger_Counter_BLE.ino
index 3ccf66f..b29ac55 100644
--- a/examples/Geiger_Counter_BLE/Geiger_Counter_BLE.ino
+++ b/examples/Geiger_Counter_BLE/Geiger_Counter_BLE.ino
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/BlynkESP32_BT_WF
Licensed under MIT license
- Version: 1.1.1
+ Version: 1.2.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -24,7 +24,8 @@
Auto format SPIFFS. Update examples.
1.1.0 K Hoang 30/12/2020 Add support to LittleFS. Remove possible compiler warnings. Update examples
1.1.1 K Hoang 31/01/2021 Add functions to control Config Portal (CP) from software or Virtual Switches
- Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ 1.2.0 K Hoang 24/04/2021 Enable scan of WiFi networks for selection in Configuration Portal and many new features.
*****************************************************************************************************************************/
/****************************************************************************************************************************
Important Notes:
@@ -230,6 +231,11 @@ void checkStatus()
char BLE_Device_Name[] = "GeigerCounter-BLE";
+#if USING_CUSTOMS_STYLE
+const char NewCustomsStyle[] /*PROGMEM*/ = "";
+#endif
+
void setup()
{
Serial.begin(115200);
@@ -283,6 +289,22 @@ void setup()
//Blynk.setSTAStaticIPConfig(IPAddress(192, 168, 2, 232), IPAddress(192, 168, 2, 1), IPAddress(255, 255, 255, 0),
// IPAddress(4, 4, 4, 4), IPAddress(8, 8, 8, 8));
+ //////////////////////////////////////////////
+
+ #if USING_CUSTOMS_STYLE
+ Blynk.setCustomsStyle(NewCustomsStyle);
+ #endif
+
+ #if USING_CUSTOMS_HEAD_ELEMENT
+ Blynk.setCustomsHeadElement("");
+ #endif
+
+ #if USING_CORS_FEATURE
+ Blynk.setCORSHeader("Your Access-Control-Allow-Origin");
+ #endif
+
+ //////////////////////////////////////////////
+
// Use this to default DHCP hostname to ESP8266-XXXXXX or ESP32-XXXXXX
//Blynk.begin();
// Use this to personalize DHCP hostname (RFC952 conformed)
@@ -325,32 +347,20 @@ void setup()
}
#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
-void displayCredentials(void)
+void displayCredentials()
{
Serial.println(F("\nYour stored Credentials :"));
for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
{
- Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata);
+ Serial.print(myMenuItems[i].displayName);
+ Serial.print(F(" = "));
+ Serial.println(myMenuItems[i].pdata);
}
}
-#endif
-void loop()
+void displayCredentialsInLoop()
{
-#if BLYNK_USE_BLE_ONLY
- Blynk_BLE.run();
-#else
- if (USE_BLE)
- Blynk_BLE.run();
- else
- Blynk_WF.run();
-#endif
-
- timer.run();
- checkStatus();
-
-#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
static bool displayedCredentials = false;
if (!displayedCredentials)
@@ -369,5 +379,25 @@ void loop()
}
}
}
-#endif
+}
+
+#endif
+
+void loop()
+{
+#if BLYNK_USE_BLE_ONLY
+ Blynk_BLE.run();
+#else
+ if (USE_BLE)
+ Blynk_BLE.run();
+ else
+ Blynk_WF.run();
+#endif
+
+ timer.run();
+ checkStatus();
+
+#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
+ displayCredentialsInLoop();
+#endif
}
diff --git a/examples/Geiger_Counter_BLE/defines.h b/examples/Geiger_Counter_BLE/defines.h
index 1e41b96..989199b 100644
--- a/examples/Geiger_Counter_BLE/defines.h
+++ b/examples/Geiger_Counter_BLE/defines.h
@@ -62,6 +62,20 @@
#if !BLYNK_USE_BLE_ONLY
#if USE_BLYNK_WM
#define USE_DYNAMIC_PARAMETERS true
+
+ /////////////////////////////////////////////
+
+ #define REQUIRE_ONE_SET_SSID_PW false
+
+ #define SCAN_WIFI_NETWORKS true
+
+ // To be able to manually input SSID, not from a scanned SSID lists
+ #define MANUAL_SSID_INPUT_ALLOWED true
+
+ // From 2-15
+ #define MAX_SSID_IN_LIST 8
+
+ /////////////////////////////////////////////
#warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP)
#include
diff --git a/examples/Geiger_Counter_BT/Geiger_Counter_BT.ino b/examples/Geiger_Counter_BT/Geiger_Counter_BT.ino
index 2f1cde5..64a52dd 100644
--- a/examples/Geiger_Counter_BT/Geiger_Counter_BT.ino
+++ b/examples/Geiger_Counter_BT/Geiger_Counter_BT.ino
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/BlynkESP32_BT_WF
Licensed under MIT license
- Version: 1.1.1
+ Version: 1.2.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -24,7 +24,8 @@
Auto format SPIFFS. Update examples.
1.1.0 K Hoang 30/12/2020 Add support to LittleFS. Remove possible compiler warnings. Update examples
1.1.1 K Hoang 31/01/2021 Add functions to control Config Portal (CP) from software or Virtual Switches
- Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ 1.2.0 K Hoang 24/04/2021 Enable scan of WiFi networks for selection in Configuration Portal and many new features.
*****************************************************************************************************************************/
/****************************************************************************************************************************
Important Notes:
@@ -230,6 +231,11 @@ void checkStatus()
char BT_Device_Name[] = "GeigerCounter-BT";
+#if USING_CUSTOMS_STYLE
+const char NewCustomsStyle[] /*PROGMEM*/ = "";
+#endif
+
void setup()
{
Serial.begin(115200);
@@ -283,6 +289,22 @@ void setup()
//Blynk.setSTAStaticIPConfig(IPAddress(192, 168, 2, 232), IPAddress(192, 168, 2, 1), IPAddress(255, 255, 255, 0),
// IPAddress(4, 4, 4, 4), IPAddress(8, 8, 8, 8));
+ //////////////////////////////////////////////
+
+ #if USING_CUSTOMS_STYLE
+ Blynk.setCustomsStyle(NewCustomsStyle);
+ #endif
+
+ #if USING_CUSTOMS_HEAD_ELEMENT
+ Blynk.setCustomsHeadElement("");
+ #endif
+
+ #if USING_CORS_FEATURE
+ Blynk.setCORSHeader("Your Access-Control-Allow-Origin");
+ #endif
+
+ //////////////////////////////////////////////
+
// Use this to default DHCP hostname to ESP8266-XXXXXX or ESP32-XXXXXX
//Blynk.begin();
// Use this to personalize DHCP hostname (RFC952 conformed)
@@ -325,37 +347,25 @@ void setup()
}
#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
-void displayCredentials(void)
+void displayCredentials()
{
Serial.println(F("\nYour stored Credentials :"));
- for (int i = 0; i < NUM_MENU_ITEMS; i++)
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
{
- Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata);
+ Serial.print(myMenuItems[i].displayName);
+ Serial.print(F(" = "));
+ Serial.println(myMenuItems[i].pdata);
}
}
-#endif
-void loop()
+void displayCredentialsInLoop()
{
-#if BLYNK_USE_BT_ONLY
- Blynk_BT.run();
-#else
- if (USE_BT)
- Blynk_BT.run();
- else
- Blynk_WF.run();
-#endif
-
- timer.run();
- checkStatus();
-
-#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
static bool displayedCredentials = false;
if (!displayedCredentials)
{
- for (int i = 0; i < NUM_MENU_ITEMS; i++)
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
{
if (!strlen(myMenuItems[i].pdata))
{
@@ -369,5 +379,25 @@ void loop()
}
}
}
-#endif
+}
+
+#endif
+
+void loop()
+{
+#if BLYNK_USE_BT_ONLY
+ Blynk_BT.run();
+#else
+ if (USE_BT)
+ Blynk_BT.run();
+ else
+ Blynk_WF.run();
+#endif
+
+ timer.run();
+ checkStatus();
+
+#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
+ displayCredentialsInLoop();
+#endif
}
diff --git a/examples/Geiger_Counter_BT/defines.h b/examples/Geiger_Counter_BT/defines.h
index 6244cdd..6f2690f 100644
--- a/examples/Geiger_Counter_BT/defines.h
+++ b/examples/Geiger_Counter_BT/defines.h
@@ -60,6 +60,20 @@
#if !BLYNK_USE_BT_ONLY
#if USE_BLYNK_WM
#define USE_DYNAMIC_PARAMETERS true
+
+ /////////////////////////////////////////////
+
+ #define REQUIRE_ONE_SET_SSID_PW false
+
+ #define SCAN_WIFI_NETWORKS true
+
+ // To be able to manually input SSID, not from a scanned SSID lists
+ #define MANUAL_SSID_INPUT_ALLOWED true
+
+ // From 2-15
+ #define MAX_SSID_IN_LIST 8
+
+ /////////////////////////////////////////////
#warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP)
#include
diff --git a/examples/Geiger_Counter_OLED/Geiger_Counter_OLED.ino b/examples/Geiger_Counter_OLED/Geiger_Counter_OLED.ino
index 3105989..fecb7a8 100644
--- a/examples/Geiger_Counter_OLED/Geiger_Counter_OLED.ino
+++ b/examples/Geiger_Counter_OLED/Geiger_Counter_OLED.ino
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/BlynkESP32_BT_WF
Licensed under MIT license
- Version: 1.1.1
+ Version: 1.2.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -24,7 +24,8 @@
Auto format SPIFFS. Update examples.
1.1.0 K Hoang 30/12/2020 Add support to LittleFS. Remove possible compiler warnings. Update examples
1.1.1 K Hoang 31/01/2021 Add functions to control Config Portal (CP) from software or Virtual Switches
- Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ 1.2.0 K Hoang 24/04/2021 Enable scan of WiFi networks for selection in Configuration Portal and many new features.
*****************************************************************************************************************************/
/****************************************************************************************************************************
Important Notes:
@@ -266,6 +267,11 @@ void checkStatus()
char BT_Device_Name[] = "GeigerCounter-BT";
+#if USING_CUSTOMS_STYLE
+const char NewCustomsStyle[] /*PROGMEM*/ = "";
+#endif
+
void setup()
{
Serial.begin(115200);
@@ -327,6 +333,22 @@ void setup()
//Blynk.setSTAStaticIPConfig(IPAddress(192, 168, 2, 232), IPAddress(192, 168, 2, 1), IPAddress(255, 255, 255, 0),
// IPAddress(4, 4, 4, 4), IPAddress(8, 8, 8, 8));
+ //////////////////////////////////////////////
+
+ #if USING_CUSTOMS_STYLE
+ Blynk.setCustomsStyle(NewCustomsStyle);
+ #endif
+
+ #if USING_CUSTOMS_HEAD_ELEMENT
+ Blynk.setCustomsHeadElement("");
+ #endif
+
+ #if USING_CORS_FEATURE
+ Blynk.setCORSHeader("Your Access-Control-Allow-Origin");
+ #endif
+
+ //////////////////////////////////////////////
+
// Use this to default DHCP hostname to ESP8266-XXXXXX or ESP32-XXXXXX
//Blynk.begin();
// Use this to personalize DHCP hostname (RFC952 conformed)
@@ -369,32 +391,20 @@ void setup()
}
#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
-void displayCredentials(void)
+void displayCredentials()
{
Serial.println(F("\nYour stored Credentials :"));
for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
{
- Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata);
+ Serial.print(myMenuItems[i].displayName);
+ Serial.print(F(" = "));
+ Serial.println(myMenuItems[i].pdata);
}
}
-#endif
-void loop()
+void displayCredentialsInLoop()
{
-#if BLYNK_USE_BT_ONLY
- Blynk_BT.run();
-#else
- if (USE_BT)
- Blynk_BT.run();
- else
- Blynk_WF.run();
-#endif
-
- timer.run();
- checkStatus();
-
-#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
static bool displayedCredentials = false;
if (!displayedCredentials)
@@ -413,5 +423,25 @@ void loop()
}
}
}
-#endif
+}
+
+#endif
+
+void loop()
+{
+#if BLYNK_USE_BT_ONLY
+ Blynk_BT.run();
+#else
+ if (USE_BT)
+ Blynk_BT.run();
+ else
+ Blynk_WF.run();
+#endif
+
+ timer.run();
+ checkStatus();
+
+#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
+ displayCredentialsInLoop();
+#endif
}
diff --git a/examples/Geiger_Counter_OLED/defines.h b/examples/Geiger_Counter_OLED/defines.h
index 194765c..4523d69 100644
--- a/examples/Geiger_Counter_OLED/defines.h
+++ b/examples/Geiger_Counter_OLED/defines.h
@@ -60,6 +60,20 @@
#if !BLYNK_USE_BT_ONLY
#if USE_BLYNK_WM
#define USE_DYNAMIC_PARAMETERS true
+
+ /////////////////////////////////////////////
+
+ #define REQUIRE_ONE_SET_SSID_PW false
+
+ #define SCAN_WIFI_NETWORKS true
+
+ // To be able to manually input SSID, not from a scanned SSID lists
+ #define MANUAL_SSID_INPUT_ALLOWED true
+
+ // From 2-15
+ #define MAX_SSID_IN_LIST 8
+
+ /////////////////////////////////////////////
#warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP)
#include
diff --git a/examples/Geiger_Counter_OLED_BT_BLE_WF/Geiger_Counter_OLED_BT_BLE_WF.ino b/examples/Geiger_Counter_OLED_BT_BLE_WF/Geiger_Counter_OLED_BT_BLE_WF.ino
index 2048c04..bd391a2 100644
--- a/examples/Geiger_Counter_OLED_BT_BLE_WF/Geiger_Counter_OLED_BT_BLE_WF.ino
+++ b/examples/Geiger_Counter_OLED_BT_BLE_WF/Geiger_Counter_OLED_BT_BLE_WF.ino
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/BlynkESP32_BT_WF
Licensed under MIT license
- Version: 1.1.1
+ Version: 1.2.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -24,7 +24,8 @@
Auto format SPIFFS. Update examples.
1.1.0 K Hoang 30/12/2020 Add support to LittleFS. Remove possible compiler warnings. Update examples
1.1.1 K Hoang 31/01/2021 Add functions to control Config Portal (CP) from software or Virtual Switches
- Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ 1.2.0 K Hoang 24/04/2021 Enable scan of WiFi networks for selection in Configuration Portal and many new features.
*****************************************************************************************************************************/
/****************************************************************************************************************************
Important Notes:
@@ -266,6 +267,11 @@ bool valid_BT_BLE_token = false;
char BLE_Device_Name[] = "GeigerCounter-BLE";
char BT_Device_Name[] = "GeigerCounter-BT";
+#if USING_CUSTOMS_STYLE
+const char NewCustomsStyle[] /*PROGMEM*/ = "";
+#endif
+
void setup()
{
Serial.begin(115200);
@@ -321,6 +327,22 @@ void setup()
//Blynk.setSTAStaticIPConfig(IPAddress(192, 168, 2, 232), IPAddress(192, 168, 2, 1), IPAddress(255, 255, 255, 0),
// IPAddress(4, 4, 4, 4), IPAddress(8, 8, 8, 8));
+ //////////////////////////////////////////////
+
+ #if USING_CUSTOMS_STYLE
+ Blynk.setCustomsStyle(NewCustomsStyle);
+ #endif
+
+ #if USING_CUSTOMS_HEAD_ELEMENT
+ Blynk.setCustomsHeadElement("");
+ #endif
+
+ #if USING_CORS_FEATURE
+ Blynk.setCORSHeader("Your Access-Control-Allow-Origin");
+ #endif
+
+ //////////////////////////////////////////////
+
// Use this to default DHCP hostname to ESP8266-XXXXXX or ESP32-XXXXXX
//Blynk.begin();
// Use this to personalize DHCP hostname (RFC952 conformed)
@@ -387,33 +409,20 @@ void setup()
}
#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
-void displayCredentials(void)
+void displayCredentials()
{
Serial.println(F("\nYour stored Credentials :"));
for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
{
- Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata);
+ Serial.print(myMenuItems[i].displayName);
+ Serial.print(F(" = "));
+ Serial.println(myMenuItems[i].pdata);
}
}
-#endif
-void loop()
+void displayCredentialsInLoop()
{
- if (valid_BT_BLE_token)
- {
-#if USE_BLE_NOT_BT
- Blynk_BLE.run();
-#else
- Blynk_BT.run();
-#endif
- }
-
- Blynk_WF.run();
- timer.run();
- checkStatus();
-
-#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
static bool displayedCredentials = false;
if (!displayedCredentials)
@@ -432,5 +441,26 @@ void loop()
}
}
}
-#endif
+}
+
+#endif
+
+void loop()
+{
+ if (valid_BT_BLE_token)
+ {
+#if USE_BLE_NOT_BT
+ Blynk_BLE.run();
+#else
+ Blynk_BT.run();
+#endif
+ }
+
+ Blynk_WF.run();
+ timer.run();
+ checkStatus();
+
+#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
+ displayCredentialsInLoop();
+#endif
}
diff --git a/examples/Geiger_Counter_OLED_BT_BLE_WF/defines.h b/examples/Geiger_Counter_OLED_BT_BLE_WF/defines.h
index 8d0a187..4c45dba 100644
--- a/examples/Geiger_Counter_OLED_BT_BLE_WF/defines.h
+++ b/examples/Geiger_Counter_OLED_BT_BLE_WF/defines.h
@@ -59,6 +59,20 @@
#if USE_BLYNK_WM
#define USE_DYNAMIC_PARAMETERS true
+
+ /////////////////////////////////////////////
+
+ #define REQUIRE_ONE_SET_SSID_PW false
+
+ #define SCAN_WIFI_NETWORKS true
+
+ // To be able to manually input SSID, not from a scanned SSID lists
+ #define MANUAL_SSID_INPUT_ALLOWED true
+
+ // From 2-15
+ #define MAX_SSID_IN_LIST 8
+
+ /////////////////////////////////////////////
#warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP)
#include
diff --git a/examples/Geiger_Counter_OLED_BT_WF/Geiger_Counter_OLED_BT_WF.ino b/examples/Geiger_Counter_OLED_BT_WF/Geiger_Counter_OLED_BT_WF.ino
index ef63a33..09f6f41 100644
--- a/examples/Geiger_Counter_OLED_BT_WF/Geiger_Counter_OLED_BT_WF.ino
+++ b/examples/Geiger_Counter_OLED_BT_WF/Geiger_Counter_OLED_BT_WF.ino
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/BlynkESP32_BT_WF
Licensed under MIT license
- Version: 1.1.1
+ Version: 1.2.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -24,7 +24,8 @@
Auto format SPIFFS. Update examples.
1.1.0 K Hoang 30/12/2020 Add support to LittleFS. Remove possible compiler warnings. Update examples
1.1.1 K Hoang 31/01/2021 Add functions to control Config Portal (CP) from software or Virtual Switches
- Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ 1.2.0 K Hoang 24/04/2021 Enable scan of WiFi networks for selection in Configuration Portal and many new features.
*****************************************************************************************************************************/
/****************************************************************************************************************************
Important Notes:
@@ -257,6 +258,11 @@ bool valid_BT_token = false;
char BT_Device_Name[] = "GeigerCounter-BT";
+#if USING_CUSTOMS_STYLE
+const char NewCustomsStyle[] /*PROGMEM*/ = "";
+#endif
+
void setup()
{
Serial.begin(115200);
@@ -312,6 +318,22 @@ void setup()
//Blynk.setSTAStaticIPConfig(IPAddress(192, 168, 2, 232), IPAddress(192, 168, 2, 1), IPAddress(255, 255, 255, 0),
// IPAddress(4, 4, 4, 4), IPAddress(8, 8, 8, 8));
+ //////////////////////////////////////////////
+
+ #if USING_CUSTOMS_STYLE
+ Blynk.setCustomsStyle(NewCustomsStyle);
+ #endif
+
+ #if USING_CUSTOMS_HEAD_ELEMENT
+ Blynk.setCustomsHeadElement("");
+ #endif
+
+ #if USING_CORS_FEATURE
+ Blynk.setCORSHeader("Your Access-Control-Allow-Origin");
+ #endif
+
+ //////////////////////////////////////////////
+
// Use this to default DHCP hostname to ESP8266-XXXXXX or ESP32-XXXXXX
//Blynk.begin();
// Use this to personalize DHCP hostname (RFC952 conformed)
@@ -351,27 +373,20 @@ void setup()
}
#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
-void displayCredentials(void)
+void displayCredentials()
{
Serial.println(F("\nYour stored Credentials :"));
for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
{
- Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata);
+ Serial.print(myMenuItems[i].displayName);
+ Serial.print(F(" = "));
+ Serial.println(myMenuItems[i].pdata);
}
}
-#endif
-void loop()
+void displayCredentialsInLoop()
{
- if (valid_BT_token)
- Blynk_BT.run();
-
- Blynk_WF.run();
- timer.run();
- checkStatus();
-
-#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
static bool displayedCredentials = false;
if (!displayedCredentials)
@@ -390,5 +405,20 @@ void loop()
}
}
}
-#endif
+}
+
+#endif
+
+void loop()
+{
+ if (valid_BT_token)
+ Blynk_BT.run();
+
+ Blynk_WF.run();
+ timer.run();
+ checkStatus();
+
+#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS)
+ displayCredentialsInLoop();
+#endif
}
diff --git a/examples/Geiger_Counter_OLED_BT_WF/defines.h b/examples/Geiger_Counter_OLED_BT_WF/defines.h
index 8d0a187..4c45dba 100644
--- a/examples/Geiger_Counter_OLED_BT_WF/defines.h
+++ b/examples/Geiger_Counter_OLED_BT_WF/defines.h
@@ -59,6 +59,20 @@
#if USE_BLYNK_WM
#define USE_DYNAMIC_PARAMETERS true
+
+ /////////////////////////////////////////////
+
+ #define REQUIRE_ONE_SET_SSID_PW false
+
+ #define SCAN_WIFI_NETWORKS true
+
+ // To be able to manually input SSID, not from a scanned SSID lists
+ #define MANUAL_SSID_INPUT_ALLOWED true
+
+ // From 2-15
+ #define MAX_SSID_IN_LIST 8
+
+ /////////////////////////////////////////////
#warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP)
#include
diff --git a/examples/PET_Check/PET_Check.ino b/examples/PET_Check/PET_Check.ino
index 2608bb6..27c9650 100644
--- a/examples/PET_Check/PET_Check.ino
+++ b/examples/PET_Check/PET_Check.ino
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/BlynkESP32_BT_WF
Licensed under MIT license
- Version: 1.1.1
+ Version: 1.2.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -24,7 +24,8 @@
Auto format SPIFFS. Update examples.
1.1.0 K Hoang 30/12/2020 Add support to LittleFS. Remove possible compiler warnings. Update examples
1.1.1 K Hoang 31/01/2021 Add functions to control Config Portal (CP) from software or Virtual Switches
- Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ 1.2.0 K Hoang 24/04/2021 Enable scan of WiFi networks for selection in Configuration Portal and many new features.
*****************************************************************************************************************************/
/****************************************************************************************************************************
Example Created by Miguel Alexandre Wisintainer
@@ -180,6 +181,11 @@ void checkPet(void)
pBLEScan->clearResults();
}
+#if USING_CUSTOMS_STYLE
+const char NewCustomsStyle[] /*PROGMEM*/ = "";
+#endif
+
void setup()
{
Serial.begin(115200);
@@ -221,6 +227,22 @@ void setup()
// Set config portal channel, defalut = 1. Use 0 => random channel from 1-13 to avoid conflict
Blynk_WF.setConfigPortalChannel(0);
+ //////////////////////////////////////////////
+
+ #if USING_CUSTOMS_STYLE
+ Blynk.setCustomsStyle(NewCustomsStyle);
+ #endif
+
+ #if USING_CUSTOMS_HEAD_ELEMENT
+ Blynk.setCustomsHeadElement("");
+ #endif
+
+ #if USING_CORS_FEATURE
+ Blynk.setCORSHeader("Your Access-Control-Allow-Origin");
+ #endif
+
+ //////////////////////////////////////////////
+
Blynk_WF.begin(BLE_Device_Name);
#else
//Blynk_WF.begin(auth, ssid, pass);
diff --git a/examples/PET_Check/defines.h b/examples/PET_Check/defines.h
index 8c145f7..5fe566e 100644
--- a/examples/PET_Check/defines.h
+++ b/examples/PET_Check/defines.h
@@ -62,6 +62,20 @@
#if USE_BLYNK_WM
#define USE_DYNAMIC_PARAMETERS true
+
+ /////////////////////////////////////////////
+
+ #define REQUIRE_ONE_SET_SSID_PW false
+
+ #define SCAN_WIFI_NETWORKS true
+
+ // To be able to manually input SSID, not from a scanned SSID lists
+ #define MANUAL_SSID_INPUT_ALLOWED true
+
+ // From 2-15
+ #define MAX_SSID_IN_LIST 8
+
+ /////////////////////////////////////////////
#warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP)
#include
diff --git a/library.json b/library.json
index 4b6c432..1e1ba50 100644
--- a/library.json
+++ b/library.json
@@ -1,8 +1,8 @@
{
"name": "BlynkESP32_BT_WF",
- "version": "1.1.1",
+ "version": "1.2.0",
"description": "By design, Blynk user can run ESP32 boards with either WiFi or BT/BLE by using different sketches, and have to upload / update firmware to change. This library enables user to include both Blynk BT / BLE and WiFi libraries in one sketch, run both WiFi and BT/BLE simultaneously, or select one to use at runtime after reboot. This library also supports (auto)connection to MultiWiFi and MultiBlynk, dynamic custom as well as static parameters in Config Portal. Eliminate hardcoding your Wifi and Blynk credentials and configuration data saved in either LittlFS, SPIFFS or EEPROM. Optional default Credentials to be autoloaded into Config Portal to use or change instead of manually input. Static STA IP and DHCP Hostname as well as Config Portal AP channel, IP, SSID, Password can be configured. DoubleDetectDetector feature permits entering Config Portal as requested.",
- "keywords": "sensors, control, device, smartphone, mobile, app, web, cloud, communication, protocol, iot, m2m, wifi, ble, bt-ble, bluetooth, ethernet, usb, serial, gsm, gprs, 3g, data, esp8266, http, drd, mrd, double-reset, multi-reset, multi-wifi, multi-blynk, littlefs, spiffs, eeprom, webserver, configportal, portal, credentials",
+ "keywords": "sensors, control, device, communication, wifi, ble, bt-ble, bluetooth, drd, mrd, double-reset, multi-reset, multi-wifi, multi-blynk, littlefs, spiffs, eeprom, webserver, config-portal, credentials, protocol, iot, m2m, smartphone, mobile, app, web, cloud, ethernet, usb, serial, gsm, gprs, 3g, data, esp8266, http, portal",
"authors":
{
"name": "Khoi Hoang",
diff --git a/library.properties b/library.properties
index ce6d9fd..8a2294e 100644
--- a/library.properties
+++ b/library.properties
@@ -1,5 +1,5 @@
name=BlynkESP32_BT_WF
-version=1.1.1
+version=1.2.0
author=Khoi Hoang
license=MIT
maintainer=Khoi Hoang
diff --git a/src/BlynkSimpleEsp32_Async_BLE_WF.h b/src/BlynkSimpleEsp32_Async_BLE_WF.h
new file mode 100644
index 0000000..7c7b0cc
--- /dev/null
+++ b/src/BlynkSimpleEsp32_Async_BLE_WF.h
@@ -0,0 +1,244 @@
+/****************************************************************************************************************************
+ BlynkSimpleEsp32_Async_BLE_WF.h
+ For ESP32 using WiFiManager and WiFi along with BlueTooth / BLE
+
+ Blynk_Async_ESP32_BT_WF is a library, using AsyncWebServer instead of (ESP8266)WebServer for inclusion of both ESP32
+ Blynk BT/BLE and WiFi libraries. Then select either one or both at runtime.
+
+ Based on and modified from Blynk library v0.6.1 https://github.com/blynkkk/blynk-library/releases
+ Built by Khoi Hoang https://github.com/khoih-prog/Blynk_Async_ESP32_BT_WF
+ Licensed under MIT license
+
+ Original Blynk Library author:
+ @file BlynkSimpleESP32.h
+ @author Volodymyr Shymanskyy
+ @license This project is released under the MIT License (MIT)
+ @copyright Copyright (c) 2015 Volodymyr Shymanskyy
+ @date Oct 2016
+ @brief
+
+ Version: 1.2.0
+
+ Version Modified By Date Comments
+ ------- ----------- ---------- -----------
+ 1.0.6 K Hoang 25/08/2020 Initial coding to use (ESP)AsyncWebServer instead of (ESP8266)WebServer.
+ Bump up to v1.0.6 to sync with BlynkESP32_BT_WF v1.0.6.
+ 1.1.0 K Hoang 30/12/2020 Add support to LittleFS. Remove possible compiler warnings. Update examples
+ 1.1.1 K Hoang 31/01/2021 Add functions to control Config Portal (CP) from software or Virtual Switches
+ Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ 1.2.0 K Hoang 24/04/2021 Enable scan of WiFi networks for selection in Configuration Portal and many new features.
+ *****************************************************************************************************************************/
+
+#pragma once
+
+#ifndef BlynkSimpleEsp32_BLE_WF_h
+#define BlynkSimpleEsp32_BLE_WF_h
+
+#if !( defined(ESP32) )
+ #error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting.
+#elif ( ARDUINO_ESP32S2_DEV || ARDUINO_FEATHERS2 || ARDUINO_ESP32S2_THING_PLUS || ARDUINO_MICROS2 || \
+ ARDUINO_METRO_ESP32S2 || ARDUINO_MAGTAG29_ESP32S2 || ARDUINO_FUNHOUSE_ESP32S2 || \
+ ARDUINO_ADAFRUIT_FEATHER_ESP32S2_NOPSRAM )
+ #define BOARD_TYPE "ESP32-S2"
+ #error ESP32-S2 is not supporteed yet. Please check later.
+#elif ( ARDUINO_ESP32C3_DEV )
+ #define BOARD_TYPE "ESP32-C3"
+ #error ESP32-C3 is not supporteed yet. Please check later.
+#else
+ #define BOARD_TYPE "ESP32"
+#endif
+
+#define BLYNK_ASYNC_ESP32_BT_WF_VERSION "Blynk_Async_ESP32_BT_WF v1.2.0"
+
+#ifndef BLYNK_INFO_CONNECTION
+#define BLYNK_INFO_CONNECTION "Esp32_BLE"
+#endif
+
+#define BLYNK_SEND_ATOMIC
+#define BLYNK_SEND_CHUNK 20
+//#define BLYNK_SEND_THROTTLE 20
+
+// KH
+#define BLYNK_TIMEOUT_MS 30000UL
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#define SERVICE_UUID "713D0000-503E-4C75-BA94-3148F18D941E"
+#define CHARACTERISTIC_UUID_RX "713D0003-503E-4C75-BA94-3148F18D941E"
+#define CHARACTERISTIC_UUID_TX "713D0002-503E-4C75-BA94-3148F18D941E"
+
+class BlynkTransportEsp32_BLE :
+ public BLEServerCallbacks,
+ public BLECharacteristicCallbacks
+{
+
+ public:
+ BlynkTransportEsp32_BLE()
+ : mConn (false)
+ , mName ("Blynk")
+ {}
+
+ void setDeviceName(const char* name) {
+ mName = name;
+ }
+
+ // IP redirect not available
+ void begin(char BLYNK_UNUSED *h, uint16_t BLYNK_UNUSED p) {}
+
+ void begin() {
+ // Create the BLE Device
+ BLEDevice::init(mName);
+
+ // Create the BLE Server
+ pServer = BLEDevice::createServer();
+ pServer->setCallbacks(this);
+
+ // Create the BLE Service
+ pService = pServer->createService(SERVICE_UUID);
+
+ // Create a BLE Characteristic
+ pCharacteristicTX = pService->createCharacteristic(
+ CHARACTERISTIC_UUID_TX,
+ BLECharacteristic::PROPERTY_NOTIFY
+ );
+
+ pCharacteristicTX->addDescriptor(new BLE2902());
+
+ pCharacteristicRX = pService->createCharacteristic(
+ CHARACTERISTIC_UUID_RX,
+ BLECharacteristic::PROPERTY_WRITE
+ );
+
+ pCharacteristicRX->setCallbacks(this);
+
+ // Start the service
+ pService->start();
+
+ // Start advertising
+ pServer->getAdvertising()->addServiceUUID(pService->getUUID());
+ pServer->getAdvertising()->start();
+ }
+
+ bool connect() {
+ mBuffRX.clear();
+ return mConn = true;
+ }
+
+ void disconnect() {
+ mConn = false;
+ }
+
+ bool connected() {
+ return mConn;
+ }
+
+ size_t read(void* buf, size_t len) {
+ millis_time_t start = BlynkMillis();
+ while (BlynkMillis() - start < BLYNK_TIMEOUT_MS) {
+ if (available() < len) {
+ delay(1);
+ } else {
+ break;
+ }
+ }
+ size_t res = mBuffRX.get((uint8_t*)buf, len);
+ return res;
+ }
+
+ size_t write(const void* buf, size_t len) {
+ pCharacteristicTX->setValue((uint8_t*)buf, len);
+ pCharacteristicTX->notify();
+ return len;
+ }
+
+ size_t available() {
+ size_t rxSize = mBuffRX.size();
+ return rxSize;
+ }
+
+ private:
+
+ void onConnect(BLEServer* pServer);
+ void onDisconnect(BLEServer* pServer);
+
+ void onWrite(BLECharacteristic *pCharacteristic) {
+ std::string rxValue = pCharacteristic->getValue();
+
+ if (rxValue.length() > 0) {
+ uint8_t* data = (uint8_t*)rxValue.data();
+ size_t len = rxValue.length();
+
+ BLYNK_DBG_DUMP(">> ", data, len);
+ mBuffRX.put(data, len);
+ }
+ }
+
+ private:
+ bool mConn;
+ const char* mName;
+
+ BLEServer *pServer;
+ BLEService *pService;
+ BLECharacteristic *pCharacteristicTX;
+ BLECharacteristic *pCharacteristicRX;
+
+ BlynkFifo mBuffRX;
+};
+
+class BlynkEsp32_BLE
+ : public BlynkProtocol
+{
+ typedef BlynkProtocol Base;
+ public:
+ BlynkEsp32_BLE(BlynkTransportEsp32_BLE& transp)
+ : Base(transp)
+
+ {}
+
+ void begin(const char* auth)
+ {
+ Base::begin(auth);
+ state = DISCONNECTED;
+ conn.begin();
+ }
+
+ void setDeviceName(const char* name) {
+ conn.setDeviceName(name);
+ }
+
+};
+
+
+static BlynkTransportEsp32_BLE _blynkTransportBLE;
+
+// KH
+BlynkEsp32_BLE Blynk_BLE(_blynkTransportBLE);
+
+#define Blynk Blynk_BLE
+
+inline
+void BlynkTransportEsp32_BLE::onConnect(BLEServer* pServer) {
+ BLYNK_LOG1(BLYNK_F("BLECon"));
+ connect();
+ Blynk_BLE.startSession();
+};
+
+inline
+void BlynkTransportEsp32_BLE::onDisconnect(BLEServer* pServer) {
+ BLYNK_LOG1(BLYNK_F("BLEDisCon"));
+ Blynk_BLE.disconnect();
+ disconnect();
+}
+//
+
+
+#include
+
+#endif
diff --git a/src/BlynkSimpleEsp32_Async_BT_WF.h b/src/BlynkSimpleEsp32_Async_BT_WF.h
new file mode 100644
index 0000000..031c533
--- /dev/null
+++ b/src/BlynkSimpleEsp32_Async_BT_WF.h
@@ -0,0 +1,293 @@
+/****************************************************************************************************************************
+ BlynkSimpleEsp32_Async_BT_WF.h
+ For ESP32 using WiFiManager and WiFi along with BlueTooth / BLE
+
+ Blynk_Async_ESP32_BT_WF is a library, using AsyncWebServer instead of (ESP8266)WebServer for inclusion of both ESP32
+ Blynk BT/BLE and WiFi libraries. Then select either one or both at runtime.
+
+ Based on and modified from Blynk library v0.6.1 https://github.com/blynkkk/blynk-library/releases
+ Built by Khoi Hoang https://github.com/khoih-prog/Blynk_Async_ESP32_BT_WF
+ Licensed under MIT license
+
+ Original Blynk Library author:
+ @file BlynkSimpleESP32.h
+ @author Volodymyr Shymanskyy
+ @license This project is released under the MIT License (MIT)
+ @copyright Copyright (c) 2015 Volodymyr Shymanskyy
+ @date Oct 2016
+ @brief
+
+ Version: 1.2.0
+
+ Version Modified By Date Comments
+ ------- ----------- ---------- -----------
+ 1.0.6 K Hoang 25/08/2020 Initial coding to use (ESP)AsyncWebServer instead of (ESP8266)WebServer.
+ Bump up to v1.0.6 to sync with BlynkESP32_BT_WF v1.0.6.
+ 1.1.0 K Hoang 30/12/2020 Add support to LittleFS. Remove possible compiler warnings. Update examples
+ 1.1.1 K Hoang 31/01/2021 Add functions to control Config Portal (CP) from software or Virtual Switches
+ Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ 1.2.0 K Hoang 24/04/2021 Enable scan of WiFi networks for selection in Configuration Portal and many new features.
+ *****************************************************************************************************************************/
+
+#pragma once
+
+#ifndef BlynkSimpleEsp32_BT_WF_h
+#define BlynkSimpleEsp32_BT_WF_h
+
+#if !( defined(ESP32) )
+ #error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting.
+#elif ( ARDUINO_ESP32S2_DEV || ARDUINO_FEATHERS2 || ARDUINO_ESP32S2_THING_PLUS || ARDUINO_MICROS2 || \
+ ARDUINO_METRO_ESP32S2 || ARDUINO_MAGTAG29_ESP32S2 || ARDUINO_FUNHOUSE_ESP32S2 || \
+ ARDUINO_ADAFRUIT_FEATHER_ESP32S2_NOPSRAM )
+ #define BOARD_TYPE "ESP32-S2"
+ #error ESP32-S2 is not supporteed yet. Please check later.
+#elif ( ARDUINO_ESP32C3_DEV )
+ #define BOARD_TYPE "ESP32-C3"
+ #error ESP32-C3 is not supporteed yet. Please check later.
+#else
+ #define BOARD_TYPE "ESP32"
+#endif
+
+#define BLYNK_ASYNC_ESP32_BT_WF_VERSION "Blynk_Async_ESP32_BT_WF v1.2.0"
+
+#ifndef BLYNK_INFO_CONNECTION
+#define BLYNK_INFO_CONNECTION "ESP32_BT"
+#endif
+
+#define BLYNK_SEND_ATOMIC
+#define BLYNK_SEND_CHUNK 40
+
+// KH
+#define BLYNK_TIMEOUT_MS 30000UL
+
+#include "sdkconfig.h"
+
+#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BLUEDROID_ENABLED)
+
+#ifdef ARDUINO_ARCH_ESP32
+#include "esp32-hal-log.h"
+#endif
+
+#include "esp_bt.h"
+#include "esp_bt_main.h"
+#include "esp_gap_bt_api.h"
+#include "esp_bt_device.h"
+#include "esp_spp_api.h"
+
+#include
+#include
+#include
+
+class BlynkTransportEsp32_BT
+{
+ public:
+ BlynkTransportEsp32_BT()
+ : mConn (false)
+ , mName ("Blynk")
+ {}
+
+ void setDeviceName(const char* name) {
+ mName = name;
+ }
+
+ // IP redirect not available
+ void begin(char BLYNK_UNUSED *h, uint16_t BLYNK_UNUSED p) {}
+
+ void begin() {
+ instance = this;
+
+ if (!btStarted() && !btStart()) {
+ BLYNK_LOG1(BLYNK_F("BTStartFailed"));
+ return;
+ }
+
+ esp_bluedroid_status_t bt_state = esp_bluedroid_get_status();
+ if (bt_state == ESP_BLUEDROID_STATUS_UNINITIALIZED) {
+ if (esp_bluedroid_init()) {
+ BLYNK_LOG1(BLYNK_F("BTInitFailed"));
+ return;
+ }
+ }
+
+ if (bt_state != ESP_BLUEDROID_STATUS_ENABLED) {
+ if (esp_bluedroid_enable()) {
+ BLYNK_LOG1(BLYNK_F("BTEnableFailed"));
+ return;
+ }
+ }
+
+ if (esp_spp_register_callback(esp_spp_cb) != ESP_OK) {
+ BLYNK_LOG1(BLYNK_F("RegCBFailed"));
+ return;
+ }
+
+ if (esp_spp_init(ESP_SPP_MODE_CB) != ESP_OK) {
+ BLYNK_LOG1(BLYNK_F("SPPInitFailed"));
+ return;
+ }
+
+ if (esp_bredr_tx_power_set(ESP_PWR_LVL_N2, ESP_PWR_LVL_P7) != ESP_OK)
+ {
+ BLYNK_LOG1(BLYNK_F("TXPwrSetFailed"));
+ };
+
+ if (esp_bt_dev_set_device_name(mName) != ESP_OK)
+ {
+ BLYNK_LOG1(BLYNK_F("BESetNameFailed"));
+ }
+ }
+
+ bool connect() {
+ mBuffRX.clear();
+ return mConn = true;
+ }
+
+ void disconnect() {
+ mConn = false;
+ }
+
+ bool connected() {
+ return mConn;
+ }
+
+ size_t read(void* buf, size_t len) {
+ millis_time_t start = BlynkMillis();
+ while (BlynkMillis() - start < BLYNK_TIMEOUT_MS) {
+ if (available() < len) {
+ delay(1);
+ } else {
+ break;
+ }
+ }
+ size_t res = mBuffRX.get((uint8_t*)buf, len);
+ return res;
+ }
+
+ size_t write(const void* buf, size_t len) {
+ if (!spp_handle) {
+ return 0;
+ }
+
+ esp_err_t err = esp_spp_write(spp_handle, len, (uint8_t *)buf);
+ return (err == ESP_OK) ? len : 0;
+ }
+
+ size_t available() {
+ size_t rxSize = mBuffRX.size();
+ return rxSize;
+ }
+
+
+ static
+ void putData(uint8_t* data, uint16_t len) {
+ if (instance)
+ {
+ // BLYNK_DBG_DUMP(">> ", data, len);
+ instance->mBuffRX.put(data, len);
+ }
+ }
+
+ private:
+ static BlynkTransportEsp32_BT* instance;
+ static uint32_t spp_handle;
+
+ static void onConnect();
+ static void onDisconnect();
+
+ bool mConn;
+ const char* mName;
+
+ BlynkFifo mBuffRX;
+
+ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
+ {
+ switch (event)
+ {
+ case ESP_SPP_INIT_EVT: // Once the SPP callback has been registered, ESP_SPP_INIT_EVT is triggered
+ esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+ esp_spp_start_srv(ESP_SPP_SEC_NONE, ESP_SPP_ROLE_SLAVE, 0, "SPP_SERVER");
+ break;
+
+ case ESP_SPP_CLOSE_EVT:// After the SPP disconnection, ESP_SPP_CLOSE_EVT is triggered.
+ spp_handle = 0;
+ onDisconnect();
+ break;
+
+ case ESP_SPP_DATA_IND_EVT:// Data received
+ if (param->data_ind.len > 0)
+ {
+ instance->putData((uint8_t*)param->data_ind.data, param->data_ind.len);
+ }
+ else
+ {
+ BLYNK_LOG1(BLYNK_F("SPP_DATA_ERROR"));
+ }
+ break;
+
+ case ESP_SPP_CONG_EVT: // SPP connection congestion status changed
+ BLYNK_LOG1(BLYNK_F("SPP_CONG_EVT"));
+ break;
+
+ case ESP_SPP_SRV_OPEN_EVT://Server connection open
+ spp_handle = param->open.handle;
+ onConnect();
+ break;
+
+ default:
+ break;
+ }
+ }
+};
+
+class BlynkEsp32_BT
+ : public BlynkProtocol
+{
+ typedef BlynkProtocol Base;
+ public:
+ BlynkEsp32_BT(BlynkTransportEsp32_BT& transp)
+ : Base(transp)
+ {}
+
+ void begin(const char* auth)
+ {
+ Base::begin(auth);
+ state = DISCONNECTED;
+ conn.begin();
+ }
+
+ // KH
+ void begin(const char* auth, char* ssid, char* pass)
+ {
+ begin(auth);
+ }
+
+ void setDeviceName(const char* name) {
+ conn.setDeviceName(name);
+ }
+
+};
+
+BlynkTransportEsp32_BT* BlynkTransportEsp32_BT::instance = NULL;
+uint32_t BlynkTransportEsp32_BT::spp_handle = 0;
+
+// KH
+static BlynkTransportEsp32_BT _blynkTransport_BT;
+BlynkEsp32_BT Blynk_BT(_blynkTransport_BT);
+
+#define Blynk Blynk_BT
+
+void BlynkTransportEsp32_BT::onConnect() {
+ BLYNK_LOG1(BLYNK_F("BTCon"));
+ Blynk_BT.startSession();
+};
+
+void BlynkTransportEsp32_BT::onDisconnect() {
+ BLYNK_LOG1(BLYNK_F("BTDisCon"));
+ Blynk_BT.disconnect();
+}
+//
+
+#include
+
+#endif
+#endif
diff --git a/src/BlynkSimpleEsp32_Async_WF.h b/src/BlynkSimpleEsp32_Async_WF.h
new file mode 100644
index 0000000..51277f2
--- /dev/null
+++ b/src/BlynkSimpleEsp32_Async_WF.h
@@ -0,0 +1,144 @@
+/****************************************************************************************************************************
+ BlynkSimpleESP32_Async_WF.h
+ For ESP32 using WiFiManager and WiFi along with BlueTooth / BLE
+
+ Blynk_Async_ESP32_BT_WF is a library, using AsyncWebServer instead of (ESP8266)WebServer for inclusion of both ESP32
+ Blynk BT/BLE and WiFi libraries. Then select either one or both at runtime.
+
+ Based on and modified from Blynk library v0.6.1 https://github.com/blynkkk/blynk-library/releases
+ Built by Khoi Hoang https://github.com/khoih-prog/Blynk_Async_ESP32_BT_WF
+ Licensed under MIT license
+
+ Original Blynk Library author:
+ @file BlynkSimpleESP32.h
+ @author Volodymyr Shymanskyy
+ @license This project is released under the MIT License (MIT)
+ @copyright Copyright (c) 2015 Volodymyr Shymanskyy
+ @date Oct 2016
+ @brief
+
+ Version: 1.2.0
+
+ Version Modified By Date Comments
+ ------- ----------- ---------- -----------
+ 1.0.6 K Hoang 25/08/2020 Initial coding to use (ESP)AsyncWebServer instead of (ESP8266)WebServer.
+ Bump up to v1.0.6 to sync with BlynkESP32_BT_WF v1.0.6.
+ 1.1.0 K Hoang 30/12/2020 Add support to LittleFS. Remove possible compiler warnings. Update examples
+ 1.1.1 K Hoang 31/01/2021 Add functions to control Config Portal (CP) from software or Virtual Switches
+ Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ 1.2.0 K Hoang 24/04/2021 Enable scan of WiFi networks for selection in Configuration Portal and many new features.
+ *****************************************************************************************************************************/
+
+#pragma once
+
+#ifndef BlynkSimpleEsp32_WF_h
+#define BlynkSimpleEsp32_WF_h
+
+#if !( defined(ESP32) )
+ #error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting.
+#elif ( ARDUINO_ESP32S2_DEV || ARDUINO_FEATHERS2 || ARDUINO_ESP32S2_THING_PLUS || ARDUINO_MICROS2 || \
+ ARDUINO_METRO_ESP32S2 || ARDUINO_MAGTAG29_ESP32S2 || ARDUINO_FUNHOUSE_ESP32S2 || \
+ ARDUINO_ADAFRUIT_FEATHER_ESP32S2_NOPSRAM )
+ #define BOARD_TYPE "ESP32-S2"
+ #error ESP32-S2 is not supporteed yet. Please check later.
+#elif ( ARDUINO_ESP32C3_DEV )
+ #define BOARD_TYPE "ESP32-C3"
+ #error ESP32-C3 is not supporteed yet. Please check later.
+#else
+ #define BOARD_TYPE "ESP32"
+#endif
+
+#define BLYNK_ASYNC_ESP32_BT_WF_VERSION "Blynk_Async_ESP32_BT_WF v1.2.0"
+
+#define BLYNK_SEND_ATOMIC
+
+// KH
+#define BLYNK_TIMEOUT_MS 30000UL
+
+#include
+#include
+#include
+#include
+
+class BlynkWifi
+ : public BlynkProtocol
+{
+ typedef BlynkProtocol Base;
+ public:
+ BlynkWifi(BlynkArduinoClient& transp)
+ : Base(transp)
+ {}
+
+ void connectWiFi(const char* ssid, const char* pass)
+ {
+ BLYNK_LOG2(BLYNK_F("Con2:"), ssid);
+ WiFi.mode(WIFI_STA);
+ if (pass && strlen(pass)) {
+ WiFi.begin(ssid, pass);
+ } else {
+ WiFi.begin(ssid);
+ }
+ while (WiFi.status() != WL_CONNECTED) {
+ BlynkDelay(500);
+ }
+ BLYNK_LOG1(BLYNK_F("Con2WiFi"));
+
+ IPAddress myip = WiFi.localIP();
+ BLYNK_LOG_IP("IP:", myip);
+ }
+
+ void config(const char* auth,
+ const char* domain = BLYNK_DEFAULT_DOMAIN,
+ uint16_t port = BLYNK_DEFAULT_PORT)
+ {
+ Base::begin(auth);
+ this->conn.begin(domain, port);
+ }
+
+ void config(const char* auth,
+ IPAddress ip,
+ uint16_t port = BLYNK_DEFAULT_PORT)
+ {
+ Base::begin(auth);
+ this->conn.begin(ip, port);
+ }
+
+ void begin(const char* auth,
+ const char* ssid,
+ const char* pass,
+ const char* domain = BLYNK_DEFAULT_DOMAIN,
+ uint16_t port = BLYNK_DEFAULT_PORT)
+ {
+ connectWiFi(ssid, pass);
+ config(auth, domain, port);
+ while (this->connect() != true) {}
+ }
+
+ void begin(const char* auth,
+ const char* ssid,
+ const char* pass,
+ IPAddress ip,
+ uint16_t port = BLYNK_DEFAULT_PORT)
+ {
+ connectWiFi(ssid, pass);
+ config(auth, ip, port);
+ while (this->connect() != true) {}
+ }
+
+};
+
+static WiFiClient _blynkWifiClient;
+static BlynkArduinoClient _blynkTransport(_blynkWifiClient);
+
+// KH
+BlynkWifi Blynk_WF(_blynkTransport);
+
+#if defined(Blynk)
+#undef Blynk
+#define Blynk Blynk_WF
+#endif
+//
+
+#include
+
+#endif
diff --git a/src/BlynkSimpleEsp32_Async_WFM.h b/src/BlynkSimpleEsp32_Async_WFM.h
new file mode 100644
index 0000000..fa4fdc8
--- /dev/null
+++ b/src/BlynkSimpleEsp32_Async_WFM.h
@@ -0,0 +1,2885 @@
+/****************************************************************************************************************************
+ BlynkSimpleESP32_Async_WFM.h
+ For ESP32 using WiFiManager and WiFi along with BlueTooth / BLE
+
+ Blynk_Async_ESP32_BT_WF is a library, using AsyncWebServer instead of (ESP8266)WebServer for inclusion of both ESP32
+ Blynk BT/BLE and WiFi libraries. Then select either one or both at runtime.
+
+ Based on and modified from Blynk library v0.6.1 https://github.com/blynkkk/blynk-library/releases
+ Built by Khoi Hoang https://github.com/khoih-prog/Blynk_Async_ESP32_BT_WF
+ Licensed under MIT license
+
+ Original Blynk Library author:
+ @file BlynkSimpleESP32.h
+ @author Volodymyr Shymanskyy
+ @license This project is released under the MIT License (MIT)
+ @copyright Copyright (c) 2015 Volodymyr Shymanskyy
+ @date Oct 2016
+ @brief
+
+ Version: 1.2.0
+
+ Version Modified By Date Comments
+ ------- ----------- ---------- -----------
+ 1.0.6 K Hoang 25/08/2020 Initial coding to use (ESP)AsyncWebServer instead of (ESP8266)WebServer.
+ Bump up to v1.0.6 to sync with BlynkESP32_BT_WF v1.0.6.
+ 1.1.0 K Hoang 30/12/2020 Add support to LittleFS. Remove possible compiler warnings. Update examples
+ 1.1.1 K Hoang 31/01/2021 Add functions to control Config Portal (CP) from software or Virtual Switches
+ Fix CP and Dynamic Params bugs. To permit autoreset after timeout if DRD/MRD or forced CP
+ 1.2.0 K Hoang 24/04/2021 Enable scan of WiFi networks for selection in Configuration Portal and many new features.
+ *****************************************************************************************************************************/
+
+#pragma once
+
+#ifndef BlynkSimpleEsp32_WFM_h
+#define BlynkSimpleEsp32_WFM_h
+
+#if !( defined(ESP32) )
+ #error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting.
+#elif ( ARDUINO_ESP32S2_DEV || ARDUINO_FEATHERS2 || ARDUINO_ESP32S2_THING_PLUS || ARDUINO_MICROS2 || \
+ ARDUINO_METRO_ESP32S2 || ARDUINO_MAGTAG29_ESP32S2 || ARDUINO_FUNHOUSE_ESP32S2 || \
+ ARDUINO_ADAFRUIT_FEATHER_ESP32S2_NOPSRAM )
+ #define BOARD_TYPE "ESP32-S2"
+ #error ESP32-S2 is not supporteed yet. Please check later.
+#elif ( ARDUINO_ESP32C3_DEV )
+ #define BOARD_TYPE "ESP32-C3"
+ #error ESP32-C3 is not supporteed yet. Please check later.
+#else
+ #define BOARD_TYPE "ESP32"
+#endif
+
+#define BLYNK_ASYNC_ESP32_BT_WF_VERSION "Blynk_Async_ESP32_BT_WF v1.2.0"
+
+#define BLYNK_SEND_ATOMIC
+
+// KH
+#define BLYNK_TIMEOUT_MS 30000UL
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+
+#define HTTP_PORT 80
+
+// LittleFS has higher priority than SPIFFS.
+// But if not specified any, use SPIFFS to not forcing user to install LITTLEFS library
+#if ! (defined(USE_LITTLEFS) || defined(USE_SPIFFS) )
+ #define USE_SPIFFS true
+#endif
+
+#if USE_LITTLEFS
+ // Use LittleFS
+ #include "FS.h"
+
+ // The library will be depreciated after being merged to future major Arduino esp32 core release 2.x
+ // At that time, just remove this library inclusion
+ #include // https://github.com/lorol/LITTLEFS
+
+ FS* filesystem = &LITTLEFS;
+ #define FileFS LITTLEFS
+ #warning Using LittleFS in BlynkSimpleESP32_WFM.h
+#elif USE_SPIFFS
+ #include "FS.h"
+ #include
+ FS* filesystem = &SPIFFS;
+ #define FileFS SPIFFS
+ #warning Using SPIFFS in BlynkSimpleESP32_WFM.h
+#else
+ #include
+ #warning Using EEPROM in BlynkSimpleESP32_WFM.h
+#endif
+
+//////////////////////////////////////////////
+
+// New from v1.4.0
+// KH, Some minor simplification
+#if !defined(SCAN_WIFI_NETWORKS)
+ #define SCAN_WIFI_NETWORKS true //false
+#endif
+
+#if SCAN_WIFI_NETWORKS
+ #warning Using SCAN_WIFI_NETWORKS
+
+ #if !defined(MANUAL_SSID_INPUT_ALLOWED)
+ #define MANUAL_SSID_INPUT_ALLOWED true
+ #endif
+
+ #if !defined(MAX_SSID_IN_LIST)
+ #define MAX_SSID_IN_LIST 10
+ #elif (MAX_SSID_IN_LIST < 2)
+ #warning Parameter MAX_SSID_IN_LIST defined must be >= 2 - Reset to 10
+ #undef MAX_SSID_IN_LIST
+ #define MAX_SSID_IN_LIST 10
+ #elif (MAX_SSID_IN_LIST > 15)
+ #warning Parameter MAX_SSID_IN_LIST defined must be <= 15 - Reset to 10
+ #undef MAX_SSID_IN_LIST
+ #define MAX_SSID_IN_LIST 10
+ #endif
+#else
+ #warning SCAN_WIFI_NETWORKS disabled
+#endif
+
+///////// NEW for DRD /////////////
+// These defines must be put before #include
+// to select where to store DoubleResetDetector's variable.
+// For ESP32, You must select one to be true (EEPROM or SPIFFS/LittleFS)
+// For ESP8266, You must select one to be true (RTC, EEPROM or SPIFFS/LittleFS)
+// Otherwise, library will use default EEPROM storage
+#define ESP8266_DRD_USE_RTC false //true
+
+#if USE_LITTLEFS
+ #define ESP_DRD_USE_LITTLEFS true
+ #define ESP_DRD_USE_SPIFFS false
+ #define ESP_DRD_USE_EEPROM false
+#elif USE_SPIFFS
+ #define ESP_DRD_USE_LITTLEFS false
+ #define ESP_DRD_USE_SPIFFS true
+ #define ESP_DRD_USE_EEPROM false
+#else
+ #define ESP_DRD_USE_LITTLEFS false
+ #define ESP_DRD_USE_SPIFFS false
+ #define ESP_DRD_USE_EEPROM true
+#endif
+
+#ifndef DOUBLERESETDETECTOR_DEBUG
+#define DOUBLERESETDETECTOR_DEBUG false
+#endif
+
+#include //https://github.com/khoih-prog/ESP_DoubleResetDetector
+
+// Number of seconds after reset during which a
+// subseqent reset will be considered a double reset.
+#define DRD_TIMEOUT 10
+
+// RTC Memory Address for the DoubleResetDetector to use
+#define DRD_ADDRESS 0
+
+//DoubleResetDetector drd(DRD_TIMEOUT, DRD_ADDRESS);
+DoubleResetDetector* drd;
+
+///////// NEW for DRD /////////////
+
+#include
+#define ESP_getChipId() ((uint32_t)ESP.getEfuseMac())
+
+//NEW
+#define MAX_ID_LEN 5
+#define MAX_DISPLAY_NAME_LEN 16
+
+typedef struct
+{
+ char id [MAX_ID_LEN + 1];
+ char displayName [MAX_DISPLAY_NAME_LEN + 1];
+ char *pdata;
+ uint8_t maxlen;
+} MenuItem;
+//
+
+#if USE_DYNAMIC_PARAMETERS
+ extern uint16_t NUM_MENU_ITEMS;
+ extern MenuItem myMenuItems [];
+ bool *menuItemUpdated = NULL;
+#endif
+
+#define SSID_MAX_LEN 32
+//From v1.0.5, WPA2 passwords can be up to 63 characters long.
+#define PASS_MAX_LEN 64
+
+typedef struct
+{
+ char wifi_ssid[SSID_MAX_LEN];
+ char wifi_pw [PASS_MAX_LEN];
+} WiFi_Credentials;
+
+#define HEADER_MAX_LEN 16
+
+#define BLYNK_SERVER_MAX_LEN 32
+#define BLYNK_TOKEN_MAX_LEN 36
+
+#define BOARD_NAME_MAX_LEN 24
+
+typedef struct
+{
+ char blynk_server[BLYNK_SERVER_MAX_LEN];
+ char blynk_token [BLYNK_TOKEN_MAX_LEN];
+} Blynk_Credentials;
+
+#define NUM_WIFI_CREDENTIALS 2
+#define NUM_BLYNK_CREDENTIALS 2
+
+// Configurable items excluding fixed Header and checkSum. Currently 12
+#define NUM_CONFIGURABLE_ITEMS ( 4 + (2 * NUM_WIFI_CREDENTIALS) + (2 * NUM_BLYNK_CREDENTIALS) )
+typedef struct Configuration
+{
+ char header [HEADER_MAX_LEN];
+ WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS];
+ Blynk_Credentials Blynk_Creds [NUM_BLYNK_CREDENTIALS];
+ int blynk_port;
+ char blynk_bt_tk [BLYNK_TOKEN_MAX_LEN];
+ char blynk_ble_tk [BLYNK_TOKEN_MAX_LEN];
+ char board_name [BOARD_NAME_MAX_LEN];
+ int checkSum;
+} Blynk_WM_Configuration;
+// Currently CONFIG_DATA_SIZE = ( 120 + (96 * NUM_WIFI_CREDENTIALS) + (68 * NUM_BLYNK_CREDENTIALS) ) = 448
+
+// Currently CONFIG_DATA_SIZE = 448
+uint16_t CONFIG_DATA_SIZE = sizeof(Blynk_WM_Configuration);
+
+extern bool LOAD_DEFAULT_CONFIG_DATA;
+extern Blynk_WM_Configuration defaultConfig;
+
+// Permit special chars such as # and %
+
+// -- HTML page fragments
+#if 1
+
+const char BLYNK_WM_HTML_HEAD_START[] /*PROGMEM*/ = "Blynk_Esp32_BT_BLE_WF ";
+
+const char BLYNK_WM_HTML_HEAD_STYLE[] /*PROGMEM*/ = "";
+
+const char BLYNK_WM_HTML_HEAD_END[] /*PROGMEM*/ = "\
+
\
+\
+\
+ \
+
\
+\
+\
+\
+ \
+
\
+ \
+
"; // DO NOT CHANGE THIS STRING EVER!!!!
+
+const char BLYNK_WM_HTML_INPUT_ID[] /*PROGMEM*/ = "
";
+const char BLYNK_WM_HTML_INPUT_ID1[] /*PROGMEM*/ = "
";
+
+#else
+
+const char BLYNK_WM_HTML_HEAD[] /*PROGMEM*/ = "
Blynk_Esp32_BT_BLE_WF \
+
\
+\
+\
+ \
+
\
+\
+\
+\
+ \
+
\
+ \
+
";
+
+#endif
+
+
+const char BLYNK_WM_FLDSET_START[] /*PROGMEM*/ = "
";
+const char BLYNK_WM_FLDSET_END[] /*PROGMEM*/ = " ";
+const char BLYNK_WM_HTML_PARAM[] /*PROGMEM*/ = "
";
+const char BLYNK_WM_HTML_BUTTON[] /*PROGMEM*/ = "
Save ";
+const char BLYNK_WM_HTML_SCRIPT[] /*PROGMEM*/ = "";
+const char BLYNK_WM_HTML_END[] /*PROGMEM*/ = "";
+
+//////////////////////////////////////////
+
+#if SCAN_WIFI_NETWORKS
+const char BLYNK_WM_SELECT_START[] /*PROGMEM*/ = "
";
+const char BLYNK_WM_DATALIST_START[] /*PROGMEM*/ = "";
+const char BLYNK_WM_OPTION_START[] /*PROGMEM*/ = "";
+const char BLYNK_WM_OPTION_END[] /*PROGMEM*/ = ""; // " "; is not required
+const char BLYNK_WM_NO_NETWORKS_FOUND[] /*PROGMEM*/ = "No suitable WiFi networks available!";
+#endif
+
+//////////////////////////////////////////
+
+//KH Add repeatedly used const
+//KH, from v1.2.0
+const char WM_HTTP_HEAD_CL[] PROGMEM = "Content-Length";
+const char WM_HTTP_HEAD_TEXT_HTML[] PROGMEM = "text/html";
+const char WM_HTTP_HEAD_TEXT_PLAIN[] PROGMEM = "text/plain";
+
+const char WM_HTTP_CACHE_CONTROL[] PROGMEM = "Cache-Control";
+const char WM_HTTP_NO_STORE[] PROGMEM = "no-cache, no-store, must-revalidate";
+const char WM_HTTP_PRAGMA[] PROGMEM = "Pragma";
+const char WM_HTTP_NO_CACHE[] PROGMEM = "no-cache";
+const char WM_HTTP_EXPIRES[] PROGMEM = "Expires";
+const char WM_HTTP_CORS[] PROGMEM = "Access-Control-Allow-Origin";
+const char WM_HTTP_CORS_ALLOW_ALL[] PROGMEM = "*";
+
+//////////////////////////////////////////
+
+#define BLYNK_SERVER_HARDWARE_PORT 8080
+
+#define BLYNK_BOARD_TYPE "ESP32_WFM"
+#define NO_CONFIG "blank"
+
+class BlynkWifi
+ : public BlynkProtocol
+{
+ typedef BlynkProtocol Base;
+ public:
+ BlynkWifi(BlynkArduinoClient& transp)
+ : Base(transp)
+ {}
+
+ void connectWiFi(const char* ssid, const char* pass)
+ {
+ BLYNK_LOG2(BLYNK_F("Con2:"), ssid);
+ WiFi.mode(WIFI_STA);
+
+ if (static_IP != IPAddress(0, 0, 0, 0))
+ {
+ BLYNK_LOG1(BLYNK_F("UseStatIP"));
+ WiFi.config(static_IP, static_GW, static_SN, static_DNS1, static_DNS2);
+ }
+
+ setHostname();
+
+ if (WiFi.status() != WL_CONNECTED)
+ {
+ if (pass && strlen(pass))
+ {
+ WiFi.begin(ssid, pass);
+ } else
+ {
+ WiFi.begin(ssid);
+ }
+ }
+ while (WiFi.status() != WL_CONNECTED)
+ {
+ BlynkDelay(500);
+ }
+
+ BLYNK_LOG1(BLYNK_F("Conn2WiFi"));
+ displayWiFiData();
+ }
+
+ void config(const char* auth,
+ const char* domain = BLYNK_DEFAULT_DOMAIN,
+ uint16_t port = BLYNK_DEFAULT_PORT)
+ {
+ Base::begin(auth);
+ this->conn.begin(domain, port);
+ }
+
+ void config(const char* auth,
+ IPAddress ip,
+ uint16_t port = BLYNK_DEFAULT_PORT)
+ {
+ Base::begin(auth);
+ this->conn.begin(ip, port);
+ }
+
+ void begin(const char* auth,
+ const char* ssid,
+ const char* pass,
+ const char* domain = BLYNK_DEFAULT_DOMAIN,
+ uint16_t port = BLYNK_DEFAULT_PORT)
+ {
+ connectWiFi(ssid, pass);
+ config(auth, domain, port);
+ while (this->connect() != true) {}
+ }
+
+ void begin(const char* auth,
+ const char* ssid,
+ const char* pass,
+ IPAddress ip,
+ uint16_t port = BLYNK_DEFAULT_PORT)
+ {
+ connectWiFi(ssid, pass);
+ config(auth, ip, port);
+ while (this->connect() != true) {}
+ }
+
+#ifndef LED_BUILTIN
+ #define LED_BUILTIN 2 // Pin D2 mapped to pin GPIO2/ADC12 of ESP32, control on-board LED
+#endif
+
+// For ESP32
+#define LED_OFF LOW
+#define LED_ON HIGH
+
+// New from v1.2.0
+#if !defined(REQUIRE_ONE_SET_SSID_PW)
+ #define REQUIRE_ONE_SET_SSID_PW false
+#endif
+
+#define PASSWORD_MIN_LEN 8
+
+ //////////////////////////////////////////////
+
+ void begin(const char *iHostname = "")
+ {
+#define TIMEOUT_CONNECT_WIFI 30000
+
+ //Turn OFF
+ pinMode(LED_BUILTIN, OUTPUT);
+ digitalWrite(LED_BUILTIN, LED_OFF);
+
+ //// New DRD ////
+ drd = new DoubleResetDetector(DRD_TIMEOUT, DRD_ADDRESS);
+ bool noConfigPortal = true;
+
+ if (drd->detectDoubleReset())
+ {
+#if ( BLYNK_WM_DEBUG > 1)
+ BLYNK_LOG1(BLYNK_F("Double Reset Detected"));
+#endif
+ noConfigPortal = false;
+ }
+ //// New DRD ////
+
+#if ( BLYNK_WM_DEBUG > 2)
+ if (LOAD_DEFAULT_CONFIG_DATA)
+ {
+ BLYNK_LOG1(BLYNK_F("======= Start Default Config Data ======="));
+ displayConfigData(defaultConfig);
+ }
+#endif
+
+ WiFi.mode(WIFI_STA);
+
+ if (iHostname[0] == 0)
+ {
+ String _hostname = "ESP32-" + String((uint32_t)ESP.getEfuseMac(), HEX);
+ _hostname.toUpperCase();
+
+ getRFC952_hostname(_hostname.c_str());
+
+ }
+ else
+ {
+ // Prepare and store the hostname only not NULL
+ getRFC952_hostname(iHostname);
+ }
+
+ BLYNK_LOG2(BLYNK_F("Hostname="), RFC952_hostname);
+
+ hadConfigData = getConfigData();
+
+ isForcedConfigPortal = isForcedCP();
+
+ //// New DRD/MRD ////
+ // noConfigPortal when getConfigData() OK and no MRD/DRD'ed
+ //if (getConfigData() && noConfigPortal)
+ if (hadConfigData && noConfigPortal && (!isForcedConfigPortal) )
+ {
+ hadConfigData = true;
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG1(noConfigPortal? BLYNK_F("bg: noConfigPortal = true") : BLYNK_F("bg: noConfigPortal = false"));
+#endif
+
+ for (uint16_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
+ {
+ wifiMulti.addAP(BlynkESP32_WM_config.WiFi_Creds[i].wifi_ssid, BlynkESP32_WM_config.WiFi_Creds[i].wifi_pw);
+ }
+
+ //Base::begin(BlynkESP32_WM_config.blynk_token);
+ //this->conn.begin(BlynkESP32_WM_config.blynk_server, BlynkESP32_WM_config.blynk_port);
+
+ if (connectMultiWiFi() == WL_CONNECTED)
+ {
+ BLYNK_LOG1(BLYNK_F("bg: WiFi OK. Try Blynk"));
+
+ int i = 0;
+ while ( (i++ < 10) && !connectMultiBlynk() )
+ {
+ }
+
+ if (connected())
+ {
+ BLYNK_LOG1(BLYNK_F("bg: WiFi+Blynk OK"));
+ }
+ else
+ {
+ BLYNK_LOG1(BLYNK_F("bg: WiFi OK, Blynk not"));
+ // failed to connect to Blynk server, will start configuration mode
+ startConfigurationMode();
+ }
+ }
+ else
+ {
+ BLYNK_LOG1(BLYNK_F("bg: Fail2connect WiFi+Blynk"));
+ // failed to connect to Blynk server, will start configuration mode
+ startConfigurationMode();
+ }
+ }
+ else
+ {
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG1(isForcedConfigPortal? BLYNK_F("bg: isForcedConfigPortal = true") : BLYNK_F("bg: isForcedConfigPortal = false"));
+#endif
+
+ // If not persistent => clear the flag so that after reset. no more CP, even CP not entered and saved
+ if (persForcedConfigPortal)
+ {
+ BLYNK_LOG2(BLYNK_F("bg:Stay forever in CP:"), isForcedConfigPortal ? BLYNK_F("Forced-Persistent") : (noConfigPortal ? BLYNK_F("No ConfigDat") : BLYNK_F("DRD/MRD")));
+ }
+ else
+ {
+ BLYNK_LOG2(BLYNK_F("bg:Stay forever in CP:"), isForcedConfigPortal ? BLYNK_F("Forced-non-Persistent") : (noConfigPortal ? BLYNK_F("No ConfigDat") : BLYNK_F("DRD/MRD")));
+ clearForcedCP();
+ }
+
+
+ hadConfigData = isForcedConfigPortal ? true : (noConfigPortal ? false : true);
+
+ // failed to connect to Blynk server, will start configuration mode
+ startConfigurationMode();
+ }
+ }
+
+#ifndef TIMEOUT_RECONNECT_WIFI
+ #define TIMEOUT_RECONNECT_WIFI 10000L
+#else
+ // Force range of user-defined TIMEOUT_RECONNECT_WIFI between 10-60s
+ #if (TIMEOUT_RECONNECT_WIFI < 10000L)
+ #warning TIMEOUT_RECONNECT_WIFI too low. Reseting to 10000
+ #undef TIMEOUT_RECONNECT_WIFI
+ #define TIMEOUT_RECONNECT_WIFI 10000L
+ #elif (TIMEOUT_RECONNECT_WIFI > 60000L)
+ #warning TIMEOUT_RECONNECT_WIFI too high. Reseting to 60000
+ #undef TIMEOUT_RECONNECT_WIFI
+ #define TIMEOUT_RECONNECT_WIFI 60000L
+ #endif
+#endif
+
+#ifndef RESET_IF_CONFIG_TIMEOUT
+ #define RESET_IF_CONFIG_TIMEOUT true
+#endif
+
+#ifndef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET
+ #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 10
+#else
+ // Force range of user-defined TIMES_BEFORE_RESET between 2-100
+ #if (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET < 2)
+ #warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too low. Reseting to 2
+ #undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET
+ #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 2
+ #elif (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET > 100)
+ #warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too high. Reseting to 100
+ #undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET
+ #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 100
+ #endif
+#endif
+
+ void run()
+ {
+ static int retryTimes = 0;
+
+ //// New DRD ////
+ // Call the double reset detector loop method every so often,
+ // so that it can recognise when the timeout expires.
+ // You can also call drd.stop() when you wish to no longer
+ // consider the next reset as a double reset.
+ drd->loop();
+ //// New DRD ////
+
+ // Lost connection in running. Give chance to reconfig.
+ if ( WiFi.status() != WL_CONNECTED || !connected() )
+ {
+ // If configTimeout but user hasn't connected to configWeb => try to reconnect WiFi / Blynk.
+ // But if user has connected to configWeb, stay there until done, then reset hardware
+ if ( configuration_mode && ( configTimeout == 0 || millis() < configTimeout ) )
+ {
+ retryTimes = 0;
+
+ return;
+ }
+ else
+ {
+#if RESET_IF_CONFIG_TIMEOUT
+ // If we're here but still in configuration_mode, permit running TIMES_BEFORE_RESET times before reset hardware
+ // to permit user another chance to config.
+ if ( configuration_mode && (configTimeout != 0) )
+ {
+ if (++retryTimes <= CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET)
+ {
+ BLYNK_LOG2(BLYNK_F("r:Wlost&TOut.ConW+B.Retry#"), retryTimes);
+ }
+ else
+ {
+ ESP.restart();
+ }
+ }
+#endif
+
+ // Not in config mode, try reconnecting before force to config mode
+ if ( WiFi.status() != WL_CONNECTED )
+ {
+ BLYNK_LOG1(BLYNK_F("r:Wlost.ReconW+B"));
+
+ if (connectMultiWiFi() == WL_CONNECTED)
+ {
+ // turn the LED_BUILTIN OFF to tell us we exit configuration mode.
+ digitalWrite(LED_BUILTIN, LED_OFF);
+
+ BLYNK_LOG1(BLYNK_F("r:WOK.TryB"));
+
+ if (connectMultiBlynk())
+ {
+ BLYNK_LOG1(BLYNK_F("r:W+BOK"));
+ }
+ }
+ }
+ else
+ {
+ BLYNK_LOG1(BLYNK_F("r:Blost.TryB"));
+
+ if (connectMultiBlynk())
+ {
+ // turn the LED_BUILTIN OFF to tell us we exit configuration mode.
+ digitalWrite(LED_BUILTIN, LED_OFF);
+
+ BLYNK_LOG1(BLYNK_F("r:BOK"));
+ }
+ }
+
+ //BLYNK_LOG1(BLYNK_F("run: Lost connection => configMode"));
+ //startConfigurationMode();
+ }
+ }
+ else if (configuration_mode)
+ {
+ configuration_mode = false;
+ BLYNK_LOG1(BLYNK_F("r:gotW+Bback"));
+ // Turn the LED_BUILTIN OFF when out of configuration mode. ESP32 LED_BUILDIN is correct polarity, LOW to turn OFF
+ digitalWrite(LED_BUILTIN, LED_OFF);
+ }
+
+ Base::run();
+ }
+
+ void setHostname(void)
+ {
+ if (RFC952_hostname[0] != 0)
+ {
+ // See https://github.com/espressif/arduino-esp32/issues/2537
+ WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
+ WiFi.setHostname(RFC952_hostname);
+ }
+ }
+
+ void setConfigPortalIP(IPAddress portalIP = IPAddress(192, 168, 4, 1))
+ {
+ portal_apIP = portalIP;
+ }
+
+ void setConfigPortal(String ssid = "", String pass = "")
+ {
+ portal_ssid = ssid;
+ portal_pass = pass;
+ }
+
+#define MIN_WIFI_CHANNEL 1
+#define MAX_WIFI_CHANNEL 11
+
+ int setConfigPortalChannel(int channel = 1)
+ {
+ // If channel < MIN_WIFI_CHANNEL - 1 or channel > MAX_WIFI_CHANNEL => channel = 1
+ // If channel == 0 => will use random channel from MIN_WIFI_CHANNEL to MAX_WIFI_CHANNEL
+ // If (MIN_WIFI_CHANNEL <= channel <= MAX_WIFI_CHANNEL) => use it
+ if ( (channel < MIN_WIFI_CHANNEL - 1) || (channel > MAX_WIFI_CHANNEL) )
+ WiFiAPChannel = 1;
+ else if ( (channel >= MIN_WIFI_CHANNEL - 1) && (channel <= MAX_WIFI_CHANNEL) )
+ WiFiAPChannel = channel;
+
+ return WiFiAPChannel;
+ }
+
+ void setSTAStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn = IPAddress(255, 255, 255, 0),
+ IPAddress dns_address_1 = IPAddress(0, 0, 0, 0),
+ IPAddress dns_address_2 = IPAddress(0, 0, 0, 0))
+ {
+ static_IP = ip;
+ static_GW = gw;
+ static_SN = sn;
+
+ // Default to local GW
+ if (dns_address_1 == IPAddress(0, 0, 0, 0))
+ static_DNS1 = gw;
+ else
+ static_DNS1 = dns_address_1;
+
+ // Default to Google DNS (8, 8, 8, 8)
+ if (dns_address_2 == IPAddress(0, 0, 0, 0))
+ static_DNS2 = IPAddress(8, 8, 8, 8);
+ else
+ static_DNS2 = dns_address_2;
+ }
+
+ String getWiFiSSID(uint8_t index)
+ {
+ if (index >= NUM_WIFI_CREDENTIALS)
+ return String("");
+
+ if (!hadConfigData)
+ getConfigData();
+
+ return (String(BlynkESP32_WM_config.WiFi_Creds[index].wifi_ssid));
+ }
+
+ String getWiFiPW(uint8_t index)
+ {
+ if (index >= NUM_WIFI_CREDENTIALS)
+ return String("");
+
+ if (!hadConfigData)
+ getConfigData();
+
+ return (String(BlynkESP32_WM_config.WiFi_Creds[index].wifi_pw));
+ }
+
+ String getServerName(uint8_t index)
+ {
+ if (index >= NUM_BLYNK_CREDENTIALS)
+ return String("");
+
+ if (!hadConfigData)
+ getConfigData();
+
+ return (String(BlynkESP32_WM_config.Blynk_Creds[index].blynk_server));
+ }
+
+ String getToken(uint8_t index)
+ {
+ if (index >= NUM_BLYNK_CREDENTIALS)
+ return String("");
+
+ if (!hadConfigData)
+ getConfigData();
+
+ return (String(BlynkESP32_WM_config.Blynk_Creds[index].blynk_token));
+ }
+
+ String getBlynkBTToken(void)
+ {
+ if (!hadConfigData)
+ getConfigData();
+
+ return (String(BlynkESP32_WM_config.blynk_bt_tk));
+ }
+
+ String getBlynkBLEToken(void)
+ {
+ if (!hadConfigData)
+ getConfigData();
+
+ return (String(BlynkESP32_WM_config.blynk_ble_tk));
+ }
+
+ String getBoardName()
+ {
+ if (!hadConfigData)
+ getConfigData();
+
+ return (String(BlynkESP32_WM_config.board_name));
+ }
+
+ int getHWPort()
+ {
+ if (!hadConfigData)
+ getConfigData();
+
+ return (BlynkESP32_WM_config.blynk_port);
+ }
+
+
+ Blynk_WM_Configuration* getFullConfigData(Blynk_WM_Configuration *configData)
+ {
+ if (!hadConfigData)
+ getConfigData();
+
+ // Check if NULL pointer
+ if (configData)
+ memcpy(configData, &BlynkESP32_WM_config, sizeof(Blynk_WM_Configuration));
+
+ return (configData);
+ }
+
+ void clearConfigData()
+ {
+ memset(&BlynkESP32_WM_config, 0, sizeof(BlynkESP32_WM_config));
+ saveConfigData();
+ }
+
+ // Forced CP => Flag = 0xBEEFBEEF. Else => No forced CP
+ // Flag to be stored at (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE)
+ // to avoid corruption to current data
+ //#define FORCED_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xDEADBEEF)
+ //#define FORCED_PERS_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xBEEFDEAD)
+
+ const uint32_t FORCED_CONFIG_PORTAL_FLAG_DATA = 0xDEADBEEF;
+ const uint32_t FORCED_PERS_CONFIG_PORTAL_FLAG_DATA = 0xBEEFDEAD;
+
+ #define FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE 4
+
+ void resetAndEnterConfigPortal()
+ {
+ persForcedConfigPortal = false;
+
+ setForcedCP(false);
+
+ // Delay then reset the ESP32 after save data
+ delay(1000);
+ ESP.restart();
+ }
+
+ // This will keep CP forever, until you successfully enter CP, and Save data to clear the flag.
+ void resetAndEnterConfigPortalPersistent()
+ {
+ persForcedConfigPortal = true;
+
+ setForcedCP(true);
+
+ // Delay then reset the ESP32 after save data
+ delay(1000);
+ ESP.restart();
+ }
+
+ //////////////////////////////////////
+
+ // Add customs headers from v1.2.0
+
+ // New from v1.2.0, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*"
+
+#if USING_CUSTOMS_STYLE
+ //sets a custom style, such as color
+ // "";
+ void setCustomsStyle(const char* CustomsStyle = BLYNK_WM_HTML_HEAD_STYLE)
+ {
+ BLYNK_WM_HTML_HEAD_CUSTOMS_STYLE = CustomsStyle;
+ BLYNK_LOG2(F("Set CustomsStyle to : "), BLYNK_WM_HTML_HEAD_CUSTOMS_STYLE);
+ }
+
+ //////////////////////////////////////
+
+ const char* getCustomsStyle()
+ {
+ BLYNK_LOG2(F("Get CustomsStyle = "), BLYNK_WM_HTML_HEAD_CUSTOMS_STYLE);
+ return BLYNK_WM_HTML_HEAD_CUSTOMS_STYLE;
+ }
+#endif
+
+ //////////////////////////////////////
+
+#if USING_CUSTOMS_HEAD_ELEMENT
+ //sets a custom element to add to head, like a new style tag
+ void setCustomsHeadElement(const char* CustomsHeadElement = NULL)
+ {
+ _CustomsHeadElement = CustomsHeadElement;
+ BLYNK_LOG2(F("Set CustomsHeadElement to : "), _CustomsHeadElement);
+ }
+
+ //////////////////////////////////////
+
+ const char* getCustomsHeadElement()
+ {
+ BLYNK_LOG2(F("Get CustomsHeadElement = "), _CustomsHeadElement);
+ return _CustomsHeadElement;
+ }
+#endif
+
+ //////////////////////////////////////
+
+#if USING_CORS_FEATURE
+ void setCORSHeader(const char* CORSHeaders = NULL)
+ {
+ _CORS_Header = CORSHeaders;
+
+ BLYNK_LOG2(F("Set CORS Header to : "), _CORS_Header);
+ }
+
+ //////////////////////////////////////
+
+ const char* getCORSHeader()
+ {
+ BLYNK_LOG2(F("Get CORS Header = "), _CORS_Header);
+ return _CORS_Header;
+ }
+#endif
+
+ //////////////////////////////////////
+
+ private:
+ AsyncWebServer *server;
+ bool configuration_mode = false;
+
+ WiFiMulti wifiMulti;
+
+ unsigned long configTimeout;
+ bool hadConfigData = false;
+
+ bool isForcedConfigPortal = false;
+ bool persForcedConfigPortal = false;
+
+ // default to channel 1
+ int WiFiAPChannel = 1;
+
+ uint16_t totalDataSize = 0;
+
+ Blynk_WM_Configuration BlynkESP32_WM_config;
+
+ // For Config Portal
+ IPAddress portal_apIP = IPAddress(192, 168, 4, 1);
+
+ String portal_ssid = "";
+ String portal_pass = "";
+
+ // For static IP
+ IPAddress static_IP = IPAddress(0, 0, 0, 0);
+ IPAddress static_GW = IPAddress(0, 0, 0, 0);
+ IPAddress static_SN = IPAddress(255, 255, 255, 0);
+ IPAddress static_DNS1 = IPAddress(0, 0, 0, 0);
+ IPAddress static_DNS2 = IPAddress(0, 0, 0, 0);
+
+ /////////////////////////////////////
+
+ // Add customs headers from v1.2.0
+
+#if USING_CUSTOMS_STYLE
+ const char* BLYNK_WM_HTML_HEAD_CUSTOMS_STYLE = NULL;
+#endif
+
+#if USING_CUSTOMS_HEAD_ELEMENT
+ const char* _CustomsHeadElement = NULL;
+#endif
+
+#if USING_CORS_FEATURE
+ const char* _CORS_Header = WM_HTTP_CORS_ALLOW_ALL; //"*";
+#endif
+
+ //////////////////////////////////////
+ // Add WiFi Scan from v1.2.0
+
+#if SCAN_WIFI_NETWORKS
+ int WiFiNetworksFound = 0; // Number of SSIDs found by WiFi scan, including low quality and duplicates
+ int *indices; // WiFi network data, filled by scan (SSID, BSSID)
+ String ListOfSSIDs = ""; // List of SSIDs found by scan, in HTML format
+#endif
+
+ //////////////////////////////////////
+
+#define RFC952_HOSTNAME_MAXLEN 24
+
+ char RFC952_hostname[RFC952_HOSTNAME_MAXLEN + 1];
+
+ char* getRFC952_hostname(const char* iHostname)
+ {
+ memset(RFC952_hostname, 0, sizeof(RFC952_hostname));
+
+ size_t len = ( RFC952_HOSTNAME_MAXLEN < strlen(iHostname) ) ? RFC952_HOSTNAME_MAXLEN : strlen(iHostname);
+
+ size_t j = 0;
+
+ for (size_t i = 0; i < len - 1; i++)
+ {
+ if ( isalnum(iHostname[i]) || iHostname[i] == '-' )
+ {
+ RFC952_hostname[j] = iHostname[i];
+ j++;
+ }
+ }
+ // no '-' as last char
+ if ( isalnum(iHostname[len - 1]) || (iHostname[len - 1] != '-') )
+ RFC952_hostname[j] = iHostname[len - 1];
+
+ return RFC952_hostname;
+ }
+
+ //////////////////////////////////////////////
+
+ void displayConfigData(Blynk_WM_Configuration configData)
+ {
+ BLYNK_LOG4(BLYNK_F("Hdr="), BlynkESP32_WM_config.header,
+ BLYNK_F(",BrdName="), BlynkESP32_WM_config.board_name);
+ BLYNK_LOG4(BLYNK_F("SSID="), BlynkESP32_WM_config.WiFi_Creds[0].wifi_ssid,
+ BLYNK_F(",PW="), BlynkESP32_WM_config.WiFi_Creds[0].wifi_pw);
+ BLYNK_LOG4(BLYNK_F("SSID1="), BlynkESP32_WM_config.WiFi_Creds[1].wifi_ssid,
+ BLYNK_F(",PW1="), BlynkESP32_WM_config.WiFi_Creds[1].wifi_pw);
+ BLYNK_LOG4(BLYNK_F("Server="), BlynkESP32_WM_config.Blynk_Creds[0].blynk_server,
+ BLYNK_F(",Token="), BlynkESP32_WM_config.Blynk_Creds[0].blynk_token);
+ BLYNK_LOG4(BLYNK_F("Server1="), BlynkESP32_WM_config.Blynk_Creds[1].blynk_server,
+ BLYNK_F(",Token1="), BlynkESP32_WM_config.Blynk_Creds[1].blynk_token);
+ BLYNK_LOG4(BLYNK_F("BT-Token="), BlynkESP32_WM_config.blynk_bt_tk,
+ BLYNK_F(",BLE-Token="), BlynkESP32_WM_config.blynk_ble_tk);
+ BLYNK_LOG2(BLYNK_F("Port="), BlynkESP32_WM_config.blynk_port);
+ BLYNK_LOG1(BLYNK_F("======= End Config Data ======="));
+ }
+
+ //////////////////////////////////////////////
+
+ void displayWiFiData(void)
+ {
+ BLYNK_LOG6(BLYNK_F("IP="), WiFi.localIP().toString(), BLYNK_F(",GW="), WiFi.gatewayIP().toString(),
+ BLYNK_F(",SN="), WiFi.subnetMask().toString());
+ BLYNK_LOG4(BLYNK_F("DNS1="), WiFi.dnsIP(0).toString(), BLYNK_F(",DNS2="), WiFi.dnsIP(1).toString());
+ }
+
+ //////////////////////////////////////////////
+
+ int calcChecksum()
+ {
+ int checkSum = 0;
+ for (uint16_t index = 0; index < (sizeof(BlynkESP32_WM_config) - sizeof(BlynkESP32_WM_config.checkSum)); index++)
+ {
+ checkSum += * ( ( (byte*) &BlynkESP32_WM_config ) + index);
+ }
+
+ return checkSum;
+ }
+
+ //////////////////////////////////////////////
+
+ bool isWiFiConfigValid()
+ {
+ #if REQUIRE_ONE_SET_SSID_PW
+ // If SSID ="blank" or NULL, or PWD length < 8 (as required by standard) => return false
+ // Only need 1 set of valid SSID/PWD
+ if (!( ( ( strncmp(BlynkESP32_WM_config.WiFi_Creds[0].wifi_ssid, NO_CONFIG, strlen(NO_CONFIG)) && strlen(BlynkESP32_WM_config.WiFi_Creds[0].wifi_ssid) > 0 ) &&
+ ( strlen(BlynkESP32_WM_config.WiFi_Creds[0].wifi_pw) >= PASSWORD_MIN_LEN ) ) ||
+ ( ( strncmp(BlynkESP32_WM_config.WiFi_Creds[1].wifi_ssid, NO_CONFIG, strlen(NO_CONFIG)) && strlen(BlynkESP32_WM_config.WiFi_Creds[1].wifi_ssid) > 0 ) &&
+ ( strlen(BlynkESP32_WM_config.WiFi_Creds[1].wifi_pw) >= PASSWORD_MIN_LEN ) ) ))
+ #else
+ // If SSID ="blank" or NULL, or PWD length < 8 (as required by standard) => invalid set
+ // Need both sets of valid SSID/PWD
+ if ( !strncmp(BlynkESP32_WM_config.WiFi_Creds[0].wifi_ssid, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.WiFi_Creds[0].wifi_pw, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.WiFi_Creds[1].wifi_ssid, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.WiFi_Creds[1].wifi_pw, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ ( strlen(BlynkESP32_WM_config.WiFi_Creds[0].wifi_ssid) == 0 ) ||
+ ( strlen(BlynkESP32_WM_config.WiFi_Creds[1].wifi_ssid) == 0 ) ||
+ ( strlen(BlynkESP32_WM_config.WiFi_Creds[0].wifi_pw) < PASSWORD_MIN_LEN ) ||
+ ( strlen(BlynkESP32_WM_config.WiFi_Creds[1].wifi_pw) < PASSWORD_MIN_LEN ) )
+ #endif
+ {
+ // If SSID, PW ="blank" or NULL, set the flag
+ BLYNK_LOG1(BLYNK_F("Invalid Stored WiFi Config Data"));
+
+ // Nullify the invalid data to avoid displaying garbage
+ memset(&BlynkESP32_WM_config, 0, sizeof(BlynkESP32_WM_config));
+
+ hadConfigData = false;
+
+ return false;
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////
+
+#if ( USE_LITTLEFS || USE_SPIFFS )
+
+ #define CONFIG_FILENAME BLYNK_F("/wfm_config.dat")
+ #define CONFIG_FILENAME_BACKUP BLYNK_F("/wfm_config.bak")
+
+ #define CREDENTIALS_FILENAME BLYNK_F("/wm_cred.dat")
+ #define CREDENTIALS_FILENAME_BACKUP BLYNK_F("/wm_cred.bak")
+
+ #define CONFIG_PORTAL_FILENAME BLYNK_F("/wm_cp.dat")
+ #define CONFIG_PORTAL_FILENAME_BACKUP BLYNK_F("/wm_cp.bak")
+
+ //////////////////////////////////////////////
+
+ void saveForcedCP(uint32_t value)
+ {
+ File file = FileFS.open(CONFIG_PORTAL_FILENAME, "w");
+
+ BLYNK_LOG1(BLYNK_F("SaveCPFile "));
+
+ if (file)
+ {
+ file.write((uint8_t*) &value, sizeof(value));
+ file.close();
+ BLYNK_LOG1(BLYNK_F("OK"));
+ }
+ else
+ {
+ BLYNK_LOG1(BLYNK_F("failed"));
+ }
+
+ // Trying open redundant CP file
+ file = FileFS.open(CONFIG_PORTAL_FILENAME_BACKUP, "w");
+
+ BLYNK_LOG1(BLYNK_F("SaveBkUpCPFile "));
+
+ if (file)
+ {
+ file.write((uint8_t *) &value, sizeof(value));
+ file.close();
+ BLYNK_LOG1(BLYNK_F("OK"));
+ }
+ else
+ {
+ BLYNK_LOG1(BLYNK_F("failed"));
+ }
+ }
+
+ //////////////////////////////////////////////
+
+ void setForcedCP(bool isPersistent)
+ {
+ uint32_t readForcedConfigPortalFlag = isPersistent? FORCED_PERS_CONFIG_PORTAL_FLAG_DATA : FORCED_CONFIG_PORTAL_FLAG_DATA;
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG1(isPersistent ? BLYNK_F("setForcedCP Persistent") : BLYNK_F("setForcedCP non-Persistent"));
+#endif
+
+ saveForcedCP(readForcedConfigPortalFlag);
+ }
+
+ //////////////////////////////////////////////
+
+ void clearForcedCP()
+ {
+ uint32_t readForcedConfigPortalFlag = 0;
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG1(BLYNK_F("clearForcedCP"));
+#endif
+
+ saveForcedCP(readForcedConfigPortalFlag);
+ }
+
+ //////////////////////////////////////////////
+
+ bool isForcedCP()
+ {
+ uint32_t readForcedConfigPortalFlag;
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG1(BLYNK_F("Check if isForcedCP"));
+#endif
+
+ File file = FileFS.open(CONFIG_PORTAL_FILENAME, "r");
+ BLYNK_LOG1(BLYNK_F("LoadCPFile "));
+
+ if (!file)
+ {
+ BLYNK_LOG1(BLYNK_F("failed"));
+
+ // Trying open redundant config file
+ file = FileFS.open(CONFIG_PORTAL_FILENAME_BACKUP, "r");
+ BLYNK_LOG1(BLYNK_F("LoadBkUpCPFile "));
+
+ if (!file)
+ {
+ BLYNK_LOG1(BLYNK_F("failed"));
+ return false;
+ }
+ }
+
+ file.readBytes((char *) &readForcedConfigPortalFlag, sizeof(readForcedConfigPortalFlag));
+
+ BLYNK_LOG1(BLYNK_F("OK"));
+ file.close();
+
+ // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE)
+ // => set flag noForcedConfigPortal = false
+ if (readForcedConfigPortalFlag == FORCED_CONFIG_PORTAL_FLAG_DATA)
+ {
+ persForcedConfigPortal = false;
+ return true;
+ }
+ else if (readForcedConfigPortalFlag == FORCED_PERS_CONFIG_PORTAL_FLAG_DATA)
+ {
+ persForcedConfigPortal = true;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ //////////////////////////////////////////////
+
+#if USE_DYNAMIC_PARAMETERS
+
+ bool checkDynamicData(void)
+ {
+ int checkSum = 0;
+ int readCheckSum;
+ char* readBuffer;
+
+ File file = FileFS.open(CREDENTIALS_FILENAME, "r");
+ BLYNK_LOG1(BLYNK_F("LoadCredFile "));
+
+ if (!file)
+ {
+ BLYNK_LOG1(BLYNK_F("failed"));
+
+ // Trying open redundant config file
+ file = FileFS.open(CREDENTIALS_FILENAME_BACKUP, "r");
+ BLYNK_LOG1(BLYNK_F("LoadBkUpCredFile "));
+
+ if (!file)
+ {
+ BLYNK_LOG1(BLYNK_F("failed"));
+ return false;
+ }
+ }
+
+ // Find the longest pdata, then dynamically allocate buffer. Remember to free when done
+ // This is used to store tempo data to calculate checksum to see of data is valid
+ // We dont like to destroy myMenuItems[i].pdata with invalid data
+
+ uint16_t maxBufferLength = 0;
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ if (myMenuItems[i].maxlen > maxBufferLength)
+ maxBufferLength = myMenuItems[i].maxlen;
+ }
+
+ if (maxBufferLength > 0)
+ {
+ readBuffer = new char[ maxBufferLength + 1 ];
+
+ // check to see NULL => stop and return false
+ if (readBuffer == NULL)
+ {
+ BLYNK_LOG1(BLYNK_F("ChkCrR: Error can't allocate buffer."));
+ return false;
+ }
+#if ( BLYNK_WM_DEBUG > 2)
+ else
+ {
+ BLYNK_LOG2(BLYNK_F("ChkCrR: Buffer allocated, sz="), maxBufferLength + 1);
+ }
+#endif
+ }
+
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ char* _pointer = readBuffer;
+
+ // Actual size of pdata is [maxlen + 1]
+ memset(readBuffer, 0, myMenuItems[i].maxlen + 1);
+
+ file.readBytes(_pointer, myMenuItems[i].maxlen);
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG4(F("ChkCrR:pdata="), readBuffer, F(",len="), myMenuItems[i].maxlen);
+#endif
+
+ for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++)
+ {
+ checkSum += *_pointer;
+ }
+ }
+
+ file.readBytes((char *) &readCheckSum, sizeof(readCheckSum));
+
+ BLYNK_LOG1(BLYNK_F("OK"));
+ file.close();
+
+ BLYNK_LOG4(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX));
+
+ // Free buffer
+ if (readBuffer != NULL)
+ {
+ free(readBuffer);
+ BLYNK_LOG1(BLYNK_F("Buffer freed"));
+ }
+
+ if ( checkSum != readCheckSum)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////
+
+ bool loadDynamicData(void)
+ {
+ int checkSum = 0;
+ int readCheckSum;
+ totalDataSize = sizeof(BlynkESP32_WM_config) + sizeof(readCheckSum);
+
+ File file = FileFS.open(CREDENTIALS_FILENAME, "r");
+ BLYNK_LOG1(BLYNK_F("LoadCredFile "));
+
+ if (!file)
+ {
+ BLYNK_LOG1(BLYNK_F("failed"));
+
+ // Trying open redundant config file
+ file = FileFS.open(CREDENTIALS_FILENAME_BACKUP, "r");
+ BLYNK_LOG1(BLYNK_F("LoadBkUpCredFile "));
+
+ if (!file)
+ {
+ BLYNK_LOG1(BLYNK_F("failed"));
+ return false;
+ }
+ }
+
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ char* _pointer = myMenuItems[i].pdata;
+ totalDataSize += myMenuItems[i].maxlen;
+
+ // Actual size of pdata is [maxlen + 1]
+ memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1);
+
+ file.readBytes(_pointer, myMenuItems[i].maxlen);
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG4(F("CrR:pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen);
+#endif
+
+ for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++)
+ {
+ checkSum += *_pointer;
+ }
+ }
+
+ file.readBytes((char *) &readCheckSum, sizeof(readCheckSum));
+
+ BLYNK_LOG1(BLYNK_F("OK"));
+ file.close();
+
+ BLYNK_LOG4(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX));
+
+ if ( checkSum != readCheckSum)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////
+
+ void saveDynamicData(void)
+ {
+ int checkSum = 0;
+
+ File file = FileFS.open(CREDENTIALS_FILENAME, "w");
+ BLYNK_LOG1(BLYNK_F("SaveCredFile "));
+
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ char* _pointer = myMenuItems[i].pdata;
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG4(F("CW1:pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen);
+#endif
+
+ if (file)
+ {
+ file.write((uint8_t*) _pointer, myMenuItems[i].maxlen);
+ }
+ else
+ {
+ BLYNK_LOG1(BLYNK_F("failed"));
+ }
+
+ for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++)
+ {
+ checkSum += *_pointer;
+ }
+ }
+
+ if (file)
+ {
+ file.write((uint8_t*) &checkSum, sizeof(checkSum));
+ file.close();
+ BLYNK_LOG1(BLYNK_F("OK"));
+ }
+ else
+ {
+ BLYNK_LOG1(BLYNK_F("failed"));
+ }
+
+ BLYNK_LOG2(F("CrWCSum=0x"), String(checkSum, HEX));
+
+ // Trying open redundant Auth file
+ file = FileFS.open(CREDENTIALS_FILENAME_BACKUP, "w");
+ BLYNK_LOG1(BLYNK_F("SaveBkUpCredFile "));
+
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ char* _pointer = myMenuItems[i].pdata;
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG4(F("CW2:pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen);
+#endif
+
+ if (file)
+ {
+ file.write((uint8_t*) _pointer, myMenuItems[i].maxlen);
+ }
+ else
+ {
+ BLYNK_LOG1(BLYNK_F("failed"));
+ }
+
+ for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++)
+ {
+ checkSum += *_pointer;
+ }
+ }
+
+ if (file)
+ {
+ file.write((uint8_t*) &checkSum, sizeof(checkSum));
+ file.close();
+ BLYNK_LOG1(BLYNK_F("OK"));
+ }
+ else
+ {
+ BLYNK_LOG1(BLYNK_F("failed"));
+ }
+ }
+#endif
+
+ //////////////////////////////////////////////
+
+ bool loadConfigData()
+ {
+ File file = FileFS.open(CONFIG_FILENAME, "r");
+ BLYNK_LOG1(BLYNK_F("LoadCfgFile "));
+
+ if (!file)
+ {
+ BLYNK_LOG1(BLYNK_F("failed"));
+
+ // Trying open redundant config file
+ file = FileFS.open(CONFIG_FILENAME_BACKUP, "r");
+ BLYNK_LOG1(BLYNK_F("LoadBkUpCfgFile "));
+
+ if (!file)
+ {
+ BLYNK_LOG1(BLYNK_F("failed"));
+ return false;
+ }
+ }
+
+ file.readBytes((char *) &BlynkESP32_WM_config, sizeof(BlynkESP32_WM_config));
+
+ BLYNK_LOG1(BLYNK_F("OK"));
+ file.close();
+
+ return isWiFiConfigValid();
+ }
+
+ //////////////////////////////////////////////
+
+ void saveConfigData(void)
+ {
+ File file = FileFS.open(CONFIG_FILENAME, "w");
+ BLYNK_LOG1(BLYNK_F("SaveCfgFile "));
+
+ int calChecksum = calcChecksum();
+ BlynkESP32_WM_config.checkSum = calChecksum;
+ BLYNK_LOG2(BLYNK_F("WCSum=0x"), String(calChecksum, HEX));
+
+ if (file)
+ {
+ file.write((uint8_t*) &BlynkESP32_WM_config, sizeof(BlynkESP32_WM_config));
+ file.close();
+ BLYNK_LOG1(BLYNK_F("OK"));
+ }
+ else
+ {
+ BLYNK_LOG1(BLYNK_F("failed"));
+ }
+
+ // Trying open redundant Auth file
+ file = FileFS.open(CONFIG_FILENAME_BACKUP, "w");
+ BLYNK_LOG1(BLYNK_F("SaveBkUpCfgFile "));
+
+ if (file)
+ {
+ file.write((uint8_t *) &BlynkESP32_WM_config, sizeof(BlynkESP32_WM_config));
+ file.close();
+ BLYNK_LOG1(BLYNK_F("OK"));
+ }
+ else
+ {
+ BLYNK_LOG1(BLYNK_F("failed"));
+ }
+ }
+
+ //////////////////////////////////////////////
+
+ void saveAllConfigData(void)
+ {
+ saveConfigData();
+
+#if USE_DYNAMIC_PARAMETERS
+ saveDynamicData();
+#endif
+ }
+
+ //////////////////////////////////////////////
+
+ // Return false if init new EEPROM or SPIFFS/LittleFS. No more need trying to connect. Go directly to config mode
+ bool getConfigData()
+ {
+ bool dynamicDataValid = true;
+ int calChecksum;
+
+ hadConfigData = false;
+
+ // Format SPIFFS/LittleFS if not yet
+ if (!FileFS.begin(true))
+ {
+ BLYNK_LOG1(BLYNK_F("SPIFFS/LittleFS failed! Formatting."));
+
+ if (!FileFS.begin())
+ {
+ BLYNK_LOG1(BLYNK_F("SPIFFS/LittleFS failed! Pls use EEPROM."));
+ return false;
+ }
+ }
+
+ if (LOAD_DEFAULT_CONFIG_DATA)
+ {
+ // Load Config Data from Sketch
+ memcpy(&BlynkESP32_WM_config, &defaultConfig, sizeof(BlynkESP32_WM_config));
+ strcpy(BlynkESP32_WM_config.header, BLYNK_BOARD_TYPE);
+
+ // Including config and dynamic data, and assume valid
+ saveAllConfigData();
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG1(BLYNK_F("======= Start Loaded Config Data ======="));
+ displayConfigData(BlynkESP32_WM_config);
+#endif
+
+ // Don't need Config Portal anymore
+ return true;
+ }
+#if USE_DYNAMIC_PARAMETERS
+ else if ( ( FileFS.exists(CONFIG_FILENAME) || FileFS.exists(CONFIG_FILENAME_BACKUP) ) &&
+ ( FileFS.exists(CREDENTIALS_FILENAME) || FileFS.exists(CREDENTIALS_FILENAME_BACKUP) ) )
+#else
+ else if ( FileFS.exists(CONFIG_FILENAME) || FileFS.exists(CONFIG_FILENAME_BACKUP) )
+#endif
+ {
+ // if config file exists, load
+ // Get config data. If "blank" or NULL, set false flag and exit
+ if (!loadConfigData())
+ {
+ return false;
+ }
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG1(BLYNK_F("======= Start Stored Config Data ======="));
+ displayConfigData(BlynkESP32_WM_config);
+#endif
+
+ calChecksum = calcChecksum();
+
+ BLYNK_LOG4(BLYNK_F("CCSum=0x"), String(calChecksum, HEX),
+ BLYNK_F(",RCSum=0x"), String(BlynkESP32_WM_config.checkSum, HEX));
+
+#if USE_DYNAMIC_PARAMETERS
+ // Load dynamic data
+ dynamicDataValid = loadDynamicData();
+
+ if (dynamicDataValid)
+ {
+ #if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG1(BLYNK_F("Valid Stored Dynamic Data"));
+ #endif
+ }
+ #if ( BLYNK_WM_DEBUG > 2)
+ else
+ {
+ BLYNK_LOG1(BLYNK_F("Invalid Stored Dynamic Data. Ignored"));
+ }
+ #endif
+#endif
+ }
+ else
+ {
+ // Not loading Default config data, but having no config file => Config Portal
+ return false;
+ }
+
+ if ( (strncmp(BlynkESP32_WM_config.header, BLYNK_BOARD_TYPE, strlen(BLYNK_BOARD_TYPE)) != 0) ||
+ (calChecksum != BlynkESP32_WM_config.checkSum) || !dynamicDataValid )
+
+ {
+ // Including Credentials CSum
+ BLYNK_LOG2(BLYNK_F("InitCfgFile,sz="), sizeof(BlynkESP32_WM_config));
+
+ // doesn't have any configuration
+ if (LOAD_DEFAULT_CONFIG_DATA)
+ {
+ memcpy(&BlynkESP32_WM_config, &defaultConfig, sizeof(BlynkESP32_WM_config));
+ }
+ else
+ {
+ memset(&BlynkESP32_WM_config, 0, sizeof(BlynkESP32_WM_config));
+
+ strcpy(BlynkESP32_WM_config.WiFi_Creds[0].wifi_ssid, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.WiFi_Creds[0].wifi_pw, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.WiFi_Creds[1].wifi_ssid, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.WiFi_Creds[1].wifi_pw, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.Blynk_Creds[0].blynk_server, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.Blynk_Creds[0].blynk_token, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.Blynk_Creds[1].blynk_server, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.Blynk_Creds[1].blynk_token, NO_CONFIG);
+ BlynkESP32_WM_config.blynk_port = BLYNK_SERVER_HARDWARE_PORT;
+ strcpy(BlynkESP32_WM_config.blynk_bt_tk, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.blynk_ble_tk, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.board_name, NO_CONFIG);
+
+#if USE_DYNAMIC_PARAMETERS
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ // Actual size of pdata is [maxlen + 1]
+ memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1);
+ strncpy(myMenuItems[i].pdata, NO_CONFIG, myMenuItems[i].maxlen);
+ }
+#endif
+ }
+
+ strcpy(BlynkESP32_WM_config.header, BLYNK_BOARD_TYPE);
+
+ #if (USE_DYNAMIC_PARAMETERS && ( BLYNK_WM_DEBUG > 2) )
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ BLYNK_LOG4(BLYNK_F("g:myMenuItems["), i, BLYNK_F("]="), myMenuItems[i].pdata );
+ }
+ #endif
+
+ // Don't need
+ BlynkESP32_WM_config.checkSum = 0;
+
+ saveAllConfigData();
+
+ return false;
+ }
+ else if ( !strncmp(BlynkESP32_WM_config.WiFi_Creds[0].wifi_ssid, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.WiFi_Creds[0].wifi_pw, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.WiFi_Creds[1].wifi_ssid, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.WiFi_Creds[1].wifi_pw, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.Blynk_Creds[0].blynk_server, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.Blynk_Creds[0].blynk_token, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.Blynk_Creds[1].blynk_server, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.Blynk_Creds[1].blynk_token, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.blynk_bt_tk, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.blynk_ble_tk, NO_CONFIG, strlen(NO_CONFIG) ) )
+ {
+ // If SSID, PW, Server,Token ="nothing", stay in config mode forever until having config Data.
+ return false;
+ }
+ else
+ {
+ displayConfigData(BlynkESP32_WM_config);
+ }
+
+ return true;
+ }
+
+
+#else
+
+ #ifndef EEPROM_SIZE
+ #define EEPROM_SIZE 2048
+ #else
+ #if (EEPROM_SIZE > 4096)
+ #warning EEPROM_SIZE must be <= 4096. Reset to 4096
+ #undef EEPROM_SIZE
+ #define EEPROM_SIZE 4096
+ #endif
+
+ // FLAG_DATA_SIZE is 4, to store DRD flag
+ #if (EEPROM_SIZE < FLAG_DATA_SIZE + CONFIG_DATA_SIZE)
+ #warning EEPROM_SIZE must be > CONFIG_DATA_SIZE. Reset to 512
+ #undef EEPROM_SIZE
+ #define EEPROM_SIZE 4096
+ #endif
+ #endif
+
+ #ifndef EEPROM_START
+ #define EEPROM_START 0 //define 256 in DRD/MRD
+ #else
+ #if (EEPROM_START + FLAG_DATA_SIZE + CONFIG_DATA_SIZE + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE > EEPROM_SIZE)
+ #error EPROM_START + FLAG_DATA_SIZE + CONFIG_DATA_SIZE + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE > EEPROM_SIZE. Please adjust.
+ #endif
+ #endif
+
+// Stating positon to store Blynk8266_WM_config
+#define BLYNK_EEPROM_START (EEPROM_START + FLAG_DATA_SIZE)
+
+ //////////////////////////////////////////////
+
+ void setForcedCP(bool isPersistent)
+ {
+ uint32_t readForcedConfigPortalFlag = isPersistent? FORCED_PERS_CONFIG_PORTAL_FLAG_DATA : FORCED_CONFIG_PORTAL_FLAG_DATA;
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG1(BLYNK_F("setForcedCP"));
+#endif
+
+ EEPROM.put(BLYNK_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag);
+ EEPROM.commit();
+ }
+ //////////////////////////////////////////////
+
+ void clearForcedCP()
+ {
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG1(BLYNK_F("clearForcedCP"));
+#endif
+
+ EEPROM.put(BLYNK_EEPROM_START + CONFIG_DATA_SIZE, 0);
+ EEPROM.commit();
+ }
+
+ //////////////////////////////////////////////
+
+ bool isForcedCP()
+ {
+ uint32_t readForcedConfigPortalFlag;
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG1(BLYNK_F("Check if isForcedCP"));
+#endif
+
+ // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE)
+ // => set flag noForcedConfigPortal = false
+ EEPROM.get(BLYNK_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag);
+
+ // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE)
+ // => set flag noForcedConfigPortal = false
+ if (readForcedConfigPortalFlag == FORCED_CONFIG_PORTAL_FLAG_DATA)
+ {
+ persForcedConfigPortal = false;
+ return true;
+ }
+ else if (readForcedConfigPortalFlag == FORCED_PERS_CONFIG_PORTAL_FLAG_DATA)
+ {
+ persForcedConfigPortal = true;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ //////////////////////////////////////////////
+
+#if USE_DYNAMIC_PARAMETERS
+
+ bool checkDynamicData()
+ {
+ int checkSum = 0;
+ int readCheckSum;
+
+ #define BUFFER_LEN 128
+ char readBuffer[BUFFER_LEN + 1];
+
+ uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkESP32_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE;
+
+ // Find the longest pdata, then dynamically allocate buffer. Remember to free when done
+ // This is used to store tempo data to calculate checksum to see of data is valid
+ // We dont like to destroy myMenuItems[i].pdata with invalid data
+
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ if (myMenuItems[i].maxlen > BUFFER_LEN)
+ {
+ // Size too large, abort and flag false
+ BLYNK_LOG1(BLYNK_F("ChkCrR: Error Small Buffer."));
+ return false;
+ }
+ }
+
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ char* _pointer = readBuffer;
+
+ // Prepare buffer, more than enough
+ memset(readBuffer, 0, sizeof(readBuffer));
+
+ // Read more than necessary, but OK and easier to code
+ EEPROM.get(offset, readBuffer);
+ // NULL terminated
+ readBuffer[myMenuItems[i].maxlen] = 0;
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG4(F("ChkCrR:pdata="), readBuffer, F(",len="), myMenuItems[i].maxlen);
+#endif
+
+ for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++)
+ {
+ checkSum += *_pointer;
+ }
+
+ offset += myMenuItems[i].maxlen;
+ }
+
+ EEPROM.get(offset, readCheckSum);
+
+ BLYNK_LOG4(F("ChkCrR:CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX));
+
+ if ( checkSum != readCheckSum)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////
+
+ bool EEPROM_getDynamicData()
+ {
+ int readCheckSum;
+ int checkSum = 0;
+ uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkESP32_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE;
+
+ totalDataSize = sizeof(BlynkESP32_WM_config) + sizeof(readCheckSum);
+
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ char* _pointer = myMenuItems[i].pdata;
+ totalDataSize += myMenuItems[i].maxlen;
+
+ // Actual size of pdata is [maxlen + 1]
+ memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1);
+
+ for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++,offset++)
+ {
+ *_pointer = EEPROM.read(offset);
+
+ checkSum += *_pointer;
+ }
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG4(F("CR:pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen);
+#endif
+ }
+
+ EEPROM.get(offset, readCheckSum);
+
+ BLYNK_LOG4(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX));
+
+ if ( checkSum != readCheckSum)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////
+
+ void EEPROM_putDynamicData()
+ {
+ int checkSum = 0;
+ uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkESP32_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE;
+
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ char* _pointer = myMenuItems[i].pdata;
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG4(F("CW:pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen);
+#endif
+
+ for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++,offset++)
+ {
+ EEPROM.write(offset, *_pointer);
+
+ checkSum += *_pointer;
+ }
+ }
+
+ EEPROM.put(offset, checkSum);
+ //EEPROM.commit();
+
+ BLYNK_LOG2(F("CrWCSum=0x"), String(checkSum, HEX));
+ }
+#endif
+
+ //////////////////////////////////////////////
+
+ // Return false if init new EEPROM or SPIFFS/LittleFS. No more need trying to connect. Go directly to config mode
+ bool getConfigData()
+ {
+ bool dynamicDataValid = true;
+ int calChecksum;
+
+ hadConfigData = false;
+
+ EEPROM.begin(EEPROM_SIZE);
+ BLYNK_LOG2(BLYNK_F("EEPROMsz:"), EEPROM_SIZE);
+
+ if (LOAD_DEFAULT_CONFIG_DATA)
+ {
+ // Load Config Data from Sketch
+ memcpy(&BlynkESP32_WM_config, &defaultConfig, sizeof(BlynkESP32_WM_config));
+ strcpy(BlynkESP32_WM_config.header, BLYNK_BOARD_TYPE);
+
+ // Including config and dynamic data, and assume valid
+ saveAllConfigData();
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG1(BLYNK_F("======= Start Loaded Config Data ======="));
+ displayConfigData(BlynkESP32_WM_config);
+#endif
+
+ // Don't need Config Portal anymore
+ return true;
+ }
+ else
+ {
+ // Load data from EEPROM
+ EEPROM.get(BLYNK_EEPROM_START, BlynkESP32_WM_config);
+
+ // If "blank" or NULL, set false flag and exit
+ if (!isWiFiConfigValid())
+ {
+ return false;
+ }
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG1(BLYNK_F("======= Start Stored Config Data ======="));
+ displayConfigData(BlynkESP32_WM_config);
+#endif
+
+ calChecksum = calcChecksum();
+
+ BLYNK_LOG4(BLYNK_F("CCSum=0x"), String(calChecksum, HEX),
+ BLYNK_F(",RCSum=0x"), String(BlynkESP32_WM_config.checkSum, HEX));
+
+#if USE_DYNAMIC_PARAMETERS
+
+ // Load dynamic data from EEPROM
+ dynamicDataValid = EEPROM_getDynamicData();
+
+ if (dynamicDataValid)
+ {
+ #if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG1(BLYNK_F("Valid Stored Dynamic Data"));
+ #endif
+ }
+ #if ( BLYNK_WM_DEBUG > 2)
+ else
+ {
+ BLYNK_LOG1(BLYNK_F("Invalid Stored Dynamic Data. Ignored"));
+ }
+ #endif
+#endif
+ }
+
+ if ( (strncmp(BlynkESP32_WM_config.header, BLYNK_BOARD_TYPE, strlen(BLYNK_BOARD_TYPE)) != 0) ||
+ (calChecksum != BlynkESP32_WM_config.checkSum) || !dynamicDataValid )
+ {
+ // Including Credentials CSum
+ BLYNK_LOG4(F("InitEEPROM,sz="), EEPROM_SIZE, F(",DataSz="), totalDataSize);
+
+ // doesn't have any configuration
+ if (LOAD_DEFAULT_CONFIG_DATA)
+ {
+ memcpy(&BlynkESP32_WM_config, &defaultConfig, sizeof(BlynkESP32_WM_config));
+ }
+ else
+ {
+ memset(&BlynkESP32_WM_config, 0, sizeof(BlynkESP32_WM_config));
+
+ strcpy(BlynkESP32_WM_config.WiFi_Creds[0].wifi_ssid, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.WiFi_Creds[0].wifi_pw, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.WiFi_Creds[1].wifi_ssid, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.WiFi_Creds[1].wifi_pw, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.Blynk_Creds[0].blynk_server, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.Blynk_Creds[0].blynk_token, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.Blynk_Creds[1].blynk_server, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.Blynk_Creds[1].blynk_token, NO_CONFIG);
+ BlynkESP32_WM_config.blynk_port = BLYNK_SERVER_HARDWARE_PORT;
+ strcpy(BlynkESP32_WM_config.blynk_bt_tk, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.blynk_ble_tk, NO_CONFIG);
+ strcpy(BlynkESP32_WM_config.board_name, NO_CONFIG);
+
+#if USE_DYNAMIC_PARAMETERS
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ // Actual size of pdata is [maxlen + 1]
+ memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1);
+ strncpy(myMenuItems[i].pdata, NO_CONFIG, myMenuItems[i].maxlen);
+ }
+#endif
+ }
+
+ strcpy(BlynkESP32_WM_config.header, BLYNK_BOARD_TYPE);
+
+ #if ( USE_DYNAMIC_PARAMETERS && ( BLYNK_WM_DEBUG > 2) )
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ BLYNK_LOG4(BLYNK_F("g:myMenuItems["), i, BLYNK_F("]="), myMenuItems[i].pdata );
+ }
+ #endif
+
+ // Don't need
+ BlynkESP32_WM_config.checkSum = 0;
+
+ saveAllConfigData();
+
+ return false;
+ }
+ else if ( !strncmp(BlynkESP32_WM_config.WiFi_Creds[0].wifi_ssid, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.WiFi_Creds[0].wifi_pw, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.WiFi_Creds[1].wifi_ssid, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.WiFi_Creds[1].wifi_pw, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.Blynk_Creds[0].blynk_server, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.Blynk_Creds[0].blynk_token, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.Blynk_Creds[1].blynk_server, NO_CONFIG, strlen(NO_CONFIG) ) ||
+ !strncmp(BlynkESP32_WM_config.Blynk_Creds[1].blynk_token, NO_CONFIG, strlen(NO_CONFIG) ) )
+ {
+ // If SSID, PW, Server,Token ="nothing", stay in config mode forever until having config Data.
+ return false;
+ }
+ else
+ {
+ displayConfigData(BlynkESP32_WM_config);
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////
+
+ void saveConfigData()
+ {
+ int calChecksum = calcChecksum();
+ BlynkESP32_WM_config.checkSum = calChecksum;
+ BLYNK_LOG4(BLYNK_F("SaveEEPROM,sz="), EEPROM_SIZE, BLYNK_F(",CSum=0x"), String(calChecksum, HEX))
+
+ EEPROM.put(BLYNK_EEPROM_START, BlynkESP32_WM_config);
+
+ EEPROM.commit();
+ }
+
+ //////////////////////////////////////////////
+
+ void saveAllConfigData(void)
+ {
+ int calChecksum = calcChecksum();
+ BlynkESP32_WM_config.checkSum = calChecksum;
+ BLYNK_LOG4(BLYNK_F("SaveEEPROM,sz="), EEPROM_SIZE, BLYNK_F(",CSum=0x"), String(calChecksum, HEX))
+
+ EEPROM.put(BLYNK_EEPROM_START, BlynkESP32_WM_config);
+ EEPROM_putDynamicData();
+
+ EEPROM.commit();
+ }
+
+#endif
+
+ //////////////////////////////////////////////
+
+ bool connectMultiBlynk(void)
+ {
+#define BLYNK_CONNECT_TIMEOUT_MS 10000L
+
+ for (uint16_t i = 0; i < NUM_BLYNK_CREDENTIALS; i++)
+ {
+ config(BlynkESP32_WM_config.Blynk_Creds[i].blynk_token,
+ BlynkESP32_WM_config.Blynk_Creds[i].blynk_server, BlynkESP32_WM_config.blynk_port);
+
+ if (connect(BLYNK_CONNECT_TIMEOUT_MS) )
+ {
+ BLYNK_LOG4(BLYNK_F("Connected to Blynk Server = "), BlynkESP32_WM_config.Blynk_Creds[i].blynk_server,
+ BLYNK_F(", Token = "), BlynkESP32_WM_config.Blynk_Creds[i].blynk_token);
+ return true;
+ }
+ }
+
+ BLYNK_LOG1(BLYNK_F("Blynk not connected"));
+
+ return false;
+
+ }
+
+ uint8_t connectMultiWiFi(void)
+ {
+ // For ESP32, this better be 2000 to enable connect the 1st time
+#define WIFI_MULTI_CONNECT_WAITING_MS 2000L
+
+ uint8_t status;
+ BLYNK_LOG1(BLYNK_F("Connecting MultiWifi..."));
+
+ WiFi.mode(WIFI_STA);
+
+ setHostname();
+
+ int i = 0;
+ status = wifiMulti.run();
+ delay(WIFI_MULTI_CONNECT_WAITING_MS);
+
+ while ( ( i++ < 10 ) && ( status != WL_CONNECTED ) )
+ {
+ status = wifiMulti.run();
+
+ if ( status == WL_CONNECTED )
+ break;
+ else
+ delay(WIFI_MULTI_CONNECT_WAITING_MS);
+ }
+
+ if ( status == WL_CONNECTED )
+ {
+ BLYNK_LOG2(BLYNK_F("WiFi connected after time: "), i);
+ BLYNK_LOG4(BLYNK_F("SSID:"), WiFi.SSID(), BLYNK_F(",RSSI="), WiFi.RSSI());
+ BLYNK_LOG4(BLYNK_F("Channel:"), WiFi.channel(), BLYNK_F(",IP address:"), WiFi.localIP() );
+ }
+ else
+ BLYNK_LOG1(BLYNK_F("WiFi not connected"));
+
+ return status;
+ }
+
+ //////////////////////////////////////////////
+
+ void createHTML(String& root_html_template)
+ {
+ String pitem;
+
+ root_html_template = BLYNK_WM_HTML_HEAD_START;
+
+ #if USING_CUSTOMS_STYLE
+ // Using Customs style when not NULL
+ if (BLYNK_WM_HTML_HEAD_CUSTOMS_STYLE)
+ root_html_template += BLYNK_WM_HTML_HEAD_CUSTOMS_STYLE;
+ else
+ root_html_template += BLYNK_WM_HTML_HEAD_STYLE;
+ #else
+ root_html_template += BLYNK_WM_HTML_HEAD_STYLE;
+ #endif
+
+ #if USING_CUSTOMS_HEAD_ELEMENT
+ if (_CustomsHeadElement)
+ root_html_template += _CustomsHeadElement;
+ #endif
+
+#if SCAN_WIFI_NETWORKS
+
+ // Replace HTML with , based on WiFi network scan in startConfigurationMode()
+
+ ListOfSSIDs = "";
+
+ for (int i = 0, list_items = 0; (i < WiFiNetworksFound) && (list_items < MAX_SSID_IN_LIST); i++)
+ {
+ if (indices[i] == -1)
+ continue; // skip duplicates and those that are below the required quality
+
+ ListOfSSIDs += BLYNK_WM_OPTION_START + String(WiFi.SSID(indices[i])) + BLYNK_WM_OPTION_END;
+ list_items++; // Count number of suitable, distinct SSIDs to be included in list
+ }
+
+ #if ( BLYNK_WM_DEBUG > 3)
+ BLYNK_LOG2(WiFiNetworksFound, BLYNK_F(" SSIDs found, generating HTML now"));
+ BLYNK_LOG1(ListOfSSIDs);
+ #endif
+
+ if (ListOfSSIDs == "") // No SSID found or none was good enough
+ ListOfSSIDs = BLYNK_WM_OPTION_START + String(BLYNK_WM_NO_NETWORKS_FOUND) + BLYNK_WM_OPTION_END;
+
+ pitem = String(BLYNK_WM_HTML_HEAD_END);
+
+#if MANUAL_SSID_INPUT_ALLOWED
+ pitem.replace("[[input_id]]", " " + String(BLYNK_WM_DATALIST_START) + "'SSIDs'>" + ListOfSSIDs + BLYNK_WM_DATALIST_END);
+
+ pitem.replace("[[input_id1]]", " " + String(BLYNK_WM_DATALIST_START) + "'SSIDs'>" + ListOfSSIDs + BLYNK_WM_DATALIST_END);
+
+ #if ( BLYNK_WM_DEBUG > 3)
+ BLYNK_LOG2(BLYNK_F("pitem:"), pitem);
+ BLYNK_LOG2(BLYNK_F("pitem:"), pitem);
+ #endif
+
+#else
+ pitem.replace("[[input_id]]", "" + ListOfSSIDs + BLYNK_WM_SELECT_END);
+ pitem.replace("[[input_id1]]", "" + ListOfSSIDs + BLYNK_WM_SELECT_END);
+#endif
+
+ root_html_template += pitem + BLYNK_WM_FLDSET_START;
+
+#else
+
+ pitem = String(BLYNK_WM_HTML_HEAD_END);
+ pitem.replace("[[input_id]]", BLYNK_WM_HTML_INPUT_ID);
+ pitem.replace("[[input_id1]]", BLYNK_WM_HTML_INPUT_ID1);
+ root_html_template += pitem + BLYNK_WM_FLDSET_START;
+
+#endif // SCAN_WIFI_NETWORKS
+
+#if USE_DYNAMIC_PARAMETERS
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ pitem = String(BLYNK_WM_HTML_PARAM);
+
+ pitem.replace("{b}", myMenuItems[i].displayName);
+ pitem.replace("{v}", myMenuItems[i].id);
+ pitem.replace("{i}", myMenuItems[i].id);
+
+ root_html_template += pitem;
+ }
+#endif
+
+ root_html_template += String(BLYNK_WM_FLDSET_END) + BLYNK_WM_HTML_BUTTON + BLYNK_WM_HTML_SCRIPT;
+
+#if USE_DYNAMIC_PARAMETERS
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ pitem = String(BLYNK_WM_HTML_SCRIPT_ITEM);
+
+ pitem.replace("{d}", myMenuItems[i].id);
+
+ root_html_template += pitem;
+ }
+#endif
+
+ root_html_template += String(BLYNK_WM_HTML_SCRIPT_END) + BLYNK_WM_HTML_END;
+
+ return;
+ }
+
+ //////////////////////////////////////////////
+
+ void serverSendHeaders()
+ {
+ BLYNK_LOG4(F("serverSendHeaders:WM_HTTP_CACHE_CONTROL:"), WM_HTTP_CACHE_CONTROL, "=", WM_HTTP_NO_STORE);
+ server->sendHeader(WM_HTTP_CACHE_CONTROL, WM_HTTP_NO_STORE);
+
+#if USING_CORS_FEATURE
+ // New from v1.2.0, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*"
+ BLYNK_LOG4(F("serverSendHeaders:WM_HTTP_CORS:"), WM_HTTP_CORS, " : ", _CORS_Header);
+ server->sendHeader(WM_HTTP_CORS, _CORS_Header);
+#endif
+
+ BLYNK_LOG4(F("serverSendHeaders:WM_HTTP_PRAGMA:"), WM_HTTP_PRAGMA, " : ", WM_HTTP_NO_CACHE);
+ server->sendHeader(WM_HTTP_PRAGMA, WM_HTTP_NO_CACHE);
+
+ BLYNK_LOG4(F("serverSendHeaders:WM_HTTP_EXPIRES:"), WM_HTTP_EXPIRES, " : ", "-1");
+ server->sendHeader(WM_HTTP_EXPIRES, "-1");
+ }
+
+ //////////////////////////////////////////////
+
+ void handleRequest(AsyncWebServerRequest *request)
+ {
+ if (server)
+ {
+ String key = request->arg("key");
+ String value = request->arg("value");
+
+ static int number_items_Updated = 0;
+
+ if (key == "" && value == "")
+ {
+ String result;
+ createHTML(result);
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG1(BLYNK_F("h:repl"));
+#endif
+
+ // Reset configTimeout to stay here until finished.
+ configTimeout = 0;
+
+ if ( RFC952_hostname[0] != 0 )
+ {
+ // Replace only if Hostname is valid
+ result.replace("Blynk_Async_Esp32_WFM", RFC952_hostname);
+ }
+ else if ( BlynkESP32_WM_config.board_name[0] != 0 )
+ {
+ // Or replace only if board_name is valid. Otherwise, keep intact
+ result.replace("Blynk_Async_Esp32_WFM", BlynkESP32_WM_config.board_name);
+ }
+
+ if (!hadConfigData)
+ {
+ // Nullify the invalid data to avoid displaying garbage
+ memset(&BlynkESP32_WM_config, 0, sizeof(BlynkESP32_WM_config));
+ BlynkESP32_WM_config.blynk_port = BLYNK_SERVER_HARDWARE_PORT;
+ }
+
+ result.replace("[[id]]", BlynkESP32_WM_config.WiFi_Creds[0].wifi_ssid);
+ result.replace("[[pw]]", BlynkESP32_WM_config.WiFi_Creds[0].wifi_pw);
+ result.replace("[[id1]]", BlynkESP32_WM_config.WiFi_Creds[1].wifi_ssid);
+ result.replace("[[pw1]]", BlynkESP32_WM_config.WiFi_Creds[1].wifi_pw);
+ result.replace("[[sv]]", BlynkESP32_WM_config.Blynk_Creds[0].blynk_server);
+ result.replace("[[tk]]", BlynkESP32_WM_config.Blynk_Creds[0].blynk_token);
+ result.replace("[[sv1]]", BlynkESP32_WM_config.Blynk_Creds[1].blynk_server);
+ result.replace("[[tk1]]", BlynkESP32_WM_config.Blynk_Creds[1].blynk_token);
+ result.replace("[[pt]]", String(BlynkESP32_WM_config.blynk_port));
+ result.replace("[[bttk]]", BlynkESP32_WM_config.blynk_bt_tk);
+ result.replace("[[bltk]]", BlynkESP32_WM_config.blynk_ble_tk);
+ result.replace("[[nm]]", BlynkESP32_WM_config.board_name);
+
+#if USE_DYNAMIC_PARAMETERS
+ // Load default configuration
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ String toChange = String("[[") + myMenuItems[i].id + "]]";
+ result.replace(toChange, myMenuItems[i].pdata);
+ #if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG4(BLYNK_F("h1:myMenuItems["), i, BLYNK_F("]="), myMenuItems[i].pdata )
+ #endif
+ }
+#endif
+
+ request->send(200, "text/html", result);
+
+ return;
+ }
+
+ if (number_items_Updated == 0)
+ {
+ memset(&BlynkESP32_WM_config, 0, sizeof(BlynkESP32_WM_config));
+ strcpy(BlynkESP32_WM_config.header, BLYNK_BOARD_TYPE);
+ }
+
+#if USE_DYNAMIC_PARAMETERS
+ if (!menuItemUpdated)
+ {
+ // Don't need to free
+ menuItemUpdated = new bool[NUM_MENU_ITEMS];
+
+ if (menuItemUpdated)
+ {
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ // To flag item is not yet updated
+ menuItemUpdated[i] = false;
+ }
+ #if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG1(BLYNK_F("h: Init menuItemUpdated" ));
+ #endif
+ }
+ else
+ {
+ BLYNK_LOG1(BLYNK_F("h: Error can't alloc memory for menuItemUpdated" ));
+ }
+ }
+#endif
+
+ static bool id_Updated = false;
+ static bool pw_Updated = false;
+ static bool id1_Updated = false;
+ static bool pw1_Updated = false;
+ static bool sv_Updated = false;
+ static bool tk_Updated = false;
+ static bool sv1_Updated = false;
+ static bool tk1_Updated = false;
+ static bool pt_Updated = false;
+ static bool bttk_Updated = false;
+ static bool bltk_Updated = false;
+ static bool nm_Updated = false;
+
+ if (key == String("id"))
+ {
+ if (!id_Updated)
+ {
+ id_Updated = true;
+ number_items_Updated++;
+ }
+
+ if (strlen(value.c_str()) < sizeof(BlynkESP32_WM_config.WiFi_Creds[0].wifi_ssid) - 1)
+ strcpy(BlynkESP32_WM_config.WiFi_Creds[0].wifi_ssid, value.c_str());
+ else
+ strncpy(BlynkESP32_WM_config.WiFi_Creds[0].wifi_ssid, value.c_str(), sizeof(BlynkESP32_WM_config.WiFi_Creds[0].wifi_ssid) - 1);
+ }
+ else if (key == String("pw"))
+ {
+ if (!pw_Updated)
+ {
+ pw_Updated = true;
+ number_items_Updated++;
+ }
+
+ if (strlen(value.c_str()) < sizeof(BlynkESP32_WM_config.WiFi_Creds[0].wifi_pw) - 1)
+ strcpy(BlynkESP32_WM_config.WiFi_Creds[0].wifi_pw, value.c_str());
+ else
+ strncpy(BlynkESP32_WM_config.WiFi_Creds[0].wifi_pw, value.c_str(), sizeof(BlynkESP32_WM_config.WiFi_Creds[0].wifi_pw) - 1);
+ }
+ else if (key == String("id1"))
+ {
+ if (!id1_Updated)
+ {
+ id1_Updated = true;
+ number_items_Updated++;
+ }
+
+ if (strlen(value.c_str()) < sizeof(BlynkESP32_WM_config.WiFi_Creds[1].wifi_ssid) - 1)
+ strcpy(BlynkESP32_WM_config.WiFi_Creds[1].wifi_ssid, value.c_str());
+ else
+ strncpy(BlynkESP32_WM_config.WiFi_Creds[1].wifi_ssid, value.c_str(), sizeof(BlynkESP32_WM_config.WiFi_Creds[1].wifi_ssid) - 1);
+ }
+ else if (key == String("pw1"))
+ {
+ if (!pw1_Updated)
+ {
+ pw1_Updated = true;
+ number_items_Updated++;
+ }
+
+ if (strlen(value.c_str()) < sizeof(BlynkESP32_WM_config.WiFi_Creds[1].wifi_pw) - 1)
+ strcpy(BlynkESP32_WM_config.WiFi_Creds[1].wifi_pw, value.c_str());
+ else
+ strncpy(BlynkESP32_WM_config.WiFi_Creds[1].wifi_pw, value.c_str(), sizeof(BlynkESP32_WM_config.WiFi_Creds[1].wifi_pw) - 1);
+ }
+ else if (key == String("sv"))
+ {
+ if (!sv_Updated)
+ {
+ sv_Updated = true;
+ number_items_Updated++;
+ }
+
+ if (strlen(value.c_str()) < sizeof(BlynkESP32_WM_config.Blynk_Creds[0].blynk_server) - 1)
+ strcpy(BlynkESP32_WM_config.Blynk_Creds[0].blynk_server, value.c_str());
+ else
+ strncpy(BlynkESP32_WM_config.Blynk_Creds[0].blynk_server, value.c_str(), sizeof(BlynkESP32_WM_config.Blynk_Creds[0].blynk_server) - 1);
+ }
+ else if (key == String("tk"))
+ {
+ if (!tk_Updated)
+ {
+ tk_Updated = true;
+ number_items_Updated++;
+ }
+
+ if (strlen(value.c_str()) < sizeof(BlynkESP32_WM_config.Blynk_Creds[0].blynk_token) - 1)
+ strcpy(BlynkESP32_WM_config.Blynk_Creds[0].blynk_token, value.c_str());
+ else
+ strncpy(BlynkESP32_WM_config.Blynk_Creds[0].blynk_token, value.c_str(), sizeof(BlynkESP32_WM_config.Blynk_Creds[0].blynk_token) - 1);
+ }
+ else if (key == String("sv1"))
+ {
+ if (!sv1_Updated)
+ {
+ sv1_Updated = true;
+ number_items_Updated++;
+ }
+
+ if (strlen(value.c_str()) < sizeof(BlynkESP32_WM_config.Blynk_Creds[1].blynk_server) - 1)
+ strcpy(BlynkESP32_WM_config.Blynk_Creds[1].blynk_server, value.c_str());
+ else
+ strncpy(BlynkESP32_WM_config.Blynk_Creds[1].blynk_server, value.c_str(), sizeof(BlynkESP32_WM_config.Blynk_Creds[1].blynk_server) - 1);
+ }
+ else if (key == String("tk1"))
+ {
+ if (!tk1_Updated)
+ {
+ tk1_Updated = true;
+ number_items_Updated++;
+ }
+
+ if (strlen(value.c_str()) < sizeof(BlynkESP32_WM_config.Blynk_Creds[1].blynk_token) - 1)
+ strcpy(BlynkESP32_WM_config.Blynk_Creds[1].blynk_token, value.c_str());
+ else
+ strncpy(BlynkESP32_WM_config.Blynk_Creds[1].blynk_token, value.c_str(), sizeof(BlynkESP32_WM_config.Blynk_Creds[1].blynk_token) - 1);
+ }
+ else if (key == String("pt"))
+ {
+ if (!pt_Updated)
+ {
+ pt_Updated = true;
+ number_items_Updated++;
+ }
+
+ BlynkESP32_WM_config.blynk_port = value.toInt();
+ }
+ else if (key == String("bttk"))
+ {
+ if (!bttk_Updated)
+ {
+ bttk_Updated = true;
+ number_items_Updated++;
+ }
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG2(BLYNK_F("bttk: = "), value.c_str());
+#endif
+
+ if (strlen(value.c_str()) < sizeof(BlynkESP32_WM_config.blynk_bt_tk) - 1)
+ strcpy(BlynkESP32_WM_config.blynk_bt_tk, value.c_str());
+ else
+ strncpy(BlynkESP32_WM_config.blynk_bt_tk, value.c_str(), sizeof(BlynkESP32_WM_config.blynk_bt_tk) - 1);
+ }
+ else if (key == String("bltk"))
+ {
+ if (!bltk_Updated)
+ {
+ bltk_Updated = true;
+ number_items_Updated++;
+ }
+
+#if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG2(BLYNK_F("bltk: = "), value.c_str());
+#endif
+
+ if (strlen(value.c_str()) < sizeof(BlynkESP32_WM_config.blynk_ble_tk) - 1)
+ strcpy(BlynkESP32_WM_config.blynk_ble_tk, value.c_str());
+ else
+ strncpy(BlynkESP32_WM_config.blynk_ble_tk, value.c_str(), sizeof(BlynkESP32_WM_config.blynk_ble_tk) - 1);
+ }
+ else if (key == String("nm"))
+ {
+ if (!nm_Updated)
+ {
+ nm_Updated = true;
+ number_items_Updated++;
+ }
+
+ if (strlen(value.c_str()) < sizeof(BlynkESP32_WM_config.board_name) - 1)
+ strcpy(BlynkESP32_WM_config.board_name, value.c_str());
+ else
+ strncpy(BlynkESP32_WM_config.board_name, value.c_str(), sizeof(BlynkESP32_WM_config.board_name) - 1);
+ }
+
+#if USE_DYNAMIC_PARAMETERS
+ else
+ {
+ for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++)
+ {
+ if ( !menuItemUpdated[i] && (key == myMenuItems[i].id) )
+ {
+ BLYNK_LOG4(BLYNK_F("h:"), myMenuItems[i].id, BLYNK_F("="), value.c_str() );
+
+ menuItemUpdated[i] = true;
+
+ number_items_Updated++;
+
+ // Actual size of pdata is [maxlen + 1]
+ memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1);
+
+ if ((int) strlen(value.c_str()) < myMenuItems[i].maxlen)
+ strcpy(myMenuItems[i].pdata, value.c_str());
+ else
+ strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen);
+ #if ( BLYNK_WM_DEBUG > 2)
+ BLYNK_LOG4(BLYNK_F("h2:myMenuItems["), i, BLYNK_F("]="), myMenuItems[i].pdata );
+ #endif
+ }
+ }
+ }
+#endif
+
+ request->send(200, "text/html", "OK");
+
+#if USE_DYNAMIC_PARAMETERS
+ if (number_items_Updated == NUM_CONFIGURABLE_ITEMS + NUM_MENU_ITEMS)
+#else
+ if (number_items_Updated == NUM_CONFIGURABLE_ITEMS)
+#endif
+ {
+#if USE_LITTLEFS
+ BLYNK_LOG2(BLYNK_F("h:Updating LittleFS:"), CONFIG_FILENAME);
+#elif USE_SPIFFS
+ BLYNK_LOG2(BLYNK_F("h:Updating SPIFFS:"), CONFIG_FILENAME);
+#else
+ BLYNK_LOG1(BLYNK_F("h:Updating EEPROM. Please wait for reset"));
+#endif
+
+ saveAllConfigData();
+
+ // Done with CP, Clear CP Flag here if forced
+ if (isForcedConfigPortal)
+ {
+ clearForcedCP();
+ }
+
+ BLYNK_LOG1(BLYNK_F("h:Rst"));
+
+ // Delay then reset the ESP8266 after save data
+ delay(1000);
+ ESP.restart();
+ }
+ } // if (server)
+ }
+
+ void startConfigurationMode()
+ {
+#define CONFIG_TIMEOUT 60000L
+
+ // turn the LED_BUILTIN ON to tell us we are in configuration mode.
+ digitalWrite(LED_BUILTIN, LED_ON);
+
+#if SCAN_WIFI_NETWORKS
+ configTimeout = 0; // To allow user input in CP
+
+ WiFiNetworksFound = scanWifiNetworks(&indices);
+#endif
+
+ if ( (portal_ssid == "") || portal_pass == "" )
+ {
+ String chipID = String(ESP_getChipId(), HEX);
+ chipID.toUpperCase();
+
+ portal_ssid = "ESP_" + chipID;
+
+ portal_pass = "MyESP_" + chipID;
+ }
+
+ WiFi.mode(WIFI_AP);
+
+ // New
+ delay(100);
+
+ static int channel;
+ // Use random channel if WiFiAPChannel == 0
+ if (WiFiAPChannel == 0)
+ {
+ //channel = random(MAX_WIFI_CHANNEL) + 1;
+ channel = (millis() % MAX_WIFI_CHANNEL) + 1;
+ }
+ else
+ channel = WiFiAPChannel;
+
+ WiFi.softAP(portal_ssid.c_str(), portal_pass.c_str(), channel);
+
+ BLYNK_LOG4(BLYNK_F("stConf:SSID="), portal_ssid, BLYNK_F(",PW="), portal_pass);
+ BLYNK_LOG4(BLYNK_F("IP="), portal_apIP.toString(), ",ch=", channel);
+
+ delay(100); // ref: https://github.com/espressif/arduino-esp32/issues/985#issuecomment-359157428
+ WiFi.softAPConfig(portal_apIP, portal_apIP, IPAddress(255, 255, 255, 0));
+
+ if (!server)
+ {
+ server = new AsyncWebServer(HTTP_PORT);
+ }
+
+ //See https://stackoverflow.com/questions/39803135/c-unresolved-overloaded-function-type?rq=1
+ if (server)
+ {
+ server->on("/", HTTP_GET, [this](AsyncWebServerRequest * request) { handleRequest(request); });
+ server->begin();
+ }
+
+ // If there is no saved config Data, stay in config mode forever until having config Data.
+ if (hadConfigData)
+ configTimeout = millis() + CONFIG_TIMEOUT;
+ else
+ configTimeout = 0;
+
+ configuration_mode = true;
+ }
+
+#if SCAN_WIFI_NETWORKS
+
+ // Source code adapted from https://github.com/khoih-prog/ESP_WiFiManager/blob/master/src/ESP_WiFiManager-Impl.h
+
+ int _paramsCount = 0;
+ int _minimumQuality = -1;
+ bool _removeDuplicateAPs = true;
+
+ //////////////////////////////////////////
+
+ void swap(int *thisOne, int *thatOne)
+ {
+ int tempo;
+
+ tempo = *thatOne;
+ *thatOne = *thisOne;
+ *thisOne = tempo;
+ }
+
+ //////////////////////////////////////////
+
+ void setMinimumSignalQuality(int quality)
+ {
+ _minimumQuality = quality;
+ }
+
+ //////////////////////////////////////////
+
+ //if this is true, remove duplicate Access Points - default true
+ void setRemoveDuplicateAPs(bool removeDuplicates)
+ {
+ _removeDuplicateAPs = removeDuplicates;
+ }
+
+ //////////////////////////////////////////
+
+ //Scan for WiFiNetworks in range and sort by signal strength
+ //space for indices array allocated on the heap and should be freed when no longer required
+ int scanWifiNetworks(int **indicesptr)
+ {
+ BLYNK_LOG1(BLYNK_F("Scanning Network"));
+
+ int n = WiFi.scanNetworks();
+
+ BLYNK_LOG2(BLYNK_F("scanWifiNetworks: Done, Scanned Networks n = "), n);
+
+ //KH, Terrible bug here. WiFi.scanNetworks() returns n < 0 => malloc( negative == very big ) => crash!!!
+ //In .../esp32/libraries/WiFi/src/WiFiType.h
+ //#define WIFI_SCAN_RUNNING (-1)
+ //#define WIFI_SCAN_FAILED (-2)
+ //if (n == 0)
+ if (n <= 0)
+ {
+ BLYNK_LOG1(BLYNK_F("No network found"));
+ return (0);
+ }
+ else
+ {
+ // Allocate space off the heap for indices array.
+ // This space should be freed when no longer required.
+ // Don't need to free as whenever CP is done, the system is reset
+ int* indices = (int *)malloc(n * sizeof(int));
+
+ if (indices == NULL)
+ {
+ BLYNK_LOG1(BLYNK_F("ERROR: Out of memory"));
+ *indicesptr = NULL;
+ return (0);
+ }
+
+ *indicesptr = indices;
+
+ //sort networks
+ for (int i = 0; i < n; i++)
+ {
+ indices[i] = i;
+ }
+
+ BLYNK_LOG(BLYNK_F("Sorting"));
+
+ // RSSI SORT
+ // old sort
+ for (int i = 0; i < n; i++)
+ {
+ for (int j = i + 1; j < n; j++)
+ {
+ if (WiFi.RSSI(indices[j]) > WiFi.RSSI(indices[i]))
+ {
+ //std::swap(indices[i], indices[j]);
+ // Using locally defined swap()
+ swap(&indices[i], &indices[j]);
+ }
+ }
+ }
+
+ BLYNK_LOG1(BLYNK_F("Removing Dup"));
+
+ // remove duplicates ( must be RSSI sorted )
+ if (_removeDuplicateAPs)
+ {
+ String cssid;
+
+ for (int i = 0; i < n; i++)
+ {
+ if (indices[i] == -1)
+ continue;
+
+ cssid = WiFi.SSID(indices[i]);
+
+ for (int j = i + 1; j < n; j++)
+ {
+ if (cssid == WiFi.SSID(indices[j]))
+ {
+ BLYNK_LOG2("DUP AP:", WiFi.SSID(indices[j]));
+ indices[j] = -1; // set dup aps to index -1
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ if (indices[i] == -1)
+ continue; // skip dups
+
+ int quality = getRSSIasQuality(WiFi.RSSI(indices[i]));
+
+ if (!(_minimumQuality == -1 || _minimumQuality < quality))
+ {
+ indices[i] = -1;
+ BLYNK_LOG1(BLYNK_F("Skipping low quality"));
+ }
+ }
+
+ BLYNK_LOG1(BLYNK_F("WiFi networks found:"));
+
+ for (int i = 0; i < n; i++)
+ {
+ if (indices[i] == -1)
+ continue; // skip dups
+ else
+ BLYNK_LOG6(i+1,": ",WiFi.SSID(indices[i]), ", ", WiFi.RSSI(i), "dB");
+ }
+
+ return (n);
+ }
+ }
+
+ //////////////////////////////////////////
+
+ int getRSSIasQuality(int RSSI)
+ {
+ int quality = 0;
+
+ if (RSSI <= -100)
+ {
+ quality = 0;
+ }
+ else if (RSSI >= -50)
+ {
+ quality = 100;
+ }
+ else
+ {
+ quality = 2 * (RSSI + 100);
+ }
+
+ return quality;
+ }
+
+ //////////////////////////////////////////
+
+#endif
+};
+
+static WiFiClient _blynkWifiClient;
+static BlynkArduinoClient _blynkTransport(_blynkWifiClient);
+
+// KH
+BlynkWifi Blynk_WF(_blynkTransport);
+
+#if defined(Blynk)
+#undef Blynk
+#define Blynk Blynk_WF
+#endif
+//
+
+#include
+
+#endif
diff --git a/src/BlynkSimpleEsp32_WFM.h b/src/BlynkSimpleEsp32_WFM.h
index b779fa3..2724832 100644
--- a/src/BlynkSimpleEsp32_WFM.h
+++ b/src/BlynkSimpleEsp32_WFM.h
@@ -569,10 +569,7 @@ class BlynkWifi
digitalWrite(LED_BUILTIN, LED_OFF);
}
- //if (connected())
- {
- Base::run();
- }
+ Base::run();
}
void setHostname(void)