diff --git a/README.md b/README.md index 3a52d7c..6a7f726 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,16 @@ [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](#Contributing) [![GitHub issues](https://img.shields.io/github/issues/khoih-prog/BlynkESP32_BT_WF.svg)](http://github.com/khoih-prog/BlynkESP32_BT_WF/issues) +### Major Releases v1.0.5 + +1. ***Multiple WiFi Credentials (SSID, Password)*** and system will autoconnect to the best and available WiFi SSID. +2. ***Multiple Blynk Credentials (Server, Token)*** and system will autoconnect to the available Blynk Servers. +3. New ***powerful-yet-simple-to-use feature to enable adding dynamic custom parameters*** from sketch and input using the same Config Portal. Config Portal will be auto-adjusted to match the number of dynamic parameters. +4. Dynamic custom parameters to be saved ***automatically in EEPROM, or SPIFFS***. +5. WiFi Password max length increased to 63 from 31, according to WPA2 standard. +6. Permit to input special chars such as ***%*** and ***#*** into data fields. +7. Config Portal AP Channel is configurable (either static or random channel) to avoid channel conflict to other APs. + ### Releases v1.0.4 1. Enhance Config Portal GUI. @@ -13,6 +23,8 @@ 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 SPIFFS or EEPROM. + Now from Version 1.0.2, you can eliminate `hardcoding` your Wifi and Blynk credentials, thanks to the `Smart Config Portal`, and have Credentials (WiFi SID/PW, Blynk WiFi/BT/BLE Tokens/ Hardware Port) saved in either SPIFFS or EEPROM. ## Prerequisite @@ -58,6 +70,78 @@ In your code, replace or 7. `Blynk.run();` with `Blynk_BLE.run()` for BLE related function calls +### How to add dynamic parameters from sketch + +- To add custom parameters, just modify from the example below + +```cpp +#define USE_DYNAMIC_PARAMETERS true + +/////////////// Start dynamic Credentials /////////////// + +//Defined in +/************************************** + #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 + +#define MAX_MQTT_SERVER_LEN 34 +char MQTT_Server [MAX_MQTT_SERVER_LEN + 1] = ""; + +#define MAX_MQTT_PORT_LEN 6 +char MQTT_Port [MAX_MQTT_PORT_LEN + 1] = ""; + +#define MAX_MQTT_USERNAME_LEN 34 +char MQTT_UserName [MAX_MQTT_USERNAME_LEN + 1] = ""; + +#define MAX_MQTT_PW_LEN 34 +char MQTT_PW [MAX_MQTT_PW_LEN + 1] = ""; + +#define MAX_MQTT_SUBS_TOPIC_LEN 34 +char MQTT_SubsTopic [MAX_MQTT_SUBS_TOPIC_LEN + 1] = ""; + +#define MAX_MQTT_PUB_TOPIC_LEN 34 +char MQTT_PubTopic [MAX_MQTT_PUB_TOPIC_LEN + 1] = ""; + +MenuItem myMenuItems [] = +{ + { "mqtt", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, + { "mqpt", "Port", MQTT_Port, MAX_MQTT_PORT_LEN }, + { "user", "MQTT UserName", MQTT_UserName, MAX_MQTT_USERNAME_LEN }, + { "mqpw", "MQTT PWD", MQTT_PW, MAX_MQTT_PW_LEN }, + { "subs", "Subs Topics", MQTT_SubsTopic, MAX_MQTT_SUBS_TOPIC_LEN }, + { "pubs", "Pubs Topics", MQTT_PubTopic, MAX_MQTT_PUB_TOPIC_LEN }, +}; + +uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; + +#else + +MenuItem myMenuItems [] = {}; + +uint16_t NUM_MENU_ITEMS = 0; +#endif + + +/////// // End dynamic Credentials /////////// + +``` +- If you don't need to add dynamic parameters, just use the following in sketch + +```cpp +#define USE_DYNAMIC_PARAMETERS false +``` + That's it. @@ -111,21 +195,30 @@ Enter your WiFi and Blynk Credentials (Server, Port, WiFi/BT/BLE tokens) Then click `Save`. After you restarted, you will see your built-in LED turned OFF. That means, it connected to your Blynk server successfully. -## Sample code -``` +## Example [ESP32_BLE_WF](examples/ESP32_BLE_WF) + +Please take a look at examples, as well. + +```cpp +#ifndef ESP32 +#error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting. +#endif + #define BLYNK_PRINT Serial +#define ESP32_BLE_WF_DEBUG true + #define USE_BLYNK_WM true //#define USE_BLYNK_WM false -#define USE_SPIFFS true -//#define USE_SPIFFS false +//#define USE_SPIFFS true +#define USE_SPIFFS false #if (!USE_SPIFFS) - // EEPROM_SIZE must be <= 2048 and >= CONFIG_DATA_SIZE - #define EEPROM_SIZE (2 * 1024) - // EEPROM_START + CONFIG_DATA_SIZE must be <= EEPROM_SIZE - #define EEPROM_START 768 +// EEPROM_SIZE must be <= 2048 and >= CONFIG_DATA_SIZE +#define EEPROM_SIZE (2 * 1024) +// EEPROM_START + CONFIG_DATA_SIZE must be <= EEPROM_SIZE +#define EEPROM_START 0 #endif // Force some params in Blynk, only valid for library version 1.0.1 and later @@ -142,74 +235,241 @@ Then click `Save`. After you restarted, you will see your built-in LED turned OF #include #if !BLYNK_USE_BLE_ONLY - #if USE_BLYNK_WM - #warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP) - #include - #else - #include - - String cloudBlynkServer = "account.duckdns.org"; - //String cloudBlynkServer = "192.168.2.110"; - #define BLYNK_SERVER_HARDWARE_PORT 8080 - char ssid[] = "SSID"; - char pass[] = "PASS"; - #endif +#if USE_BLYNK_WM +#warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP) +#include + +#define USE_DYNAMIC_PARAMETERS true + +/////////////// Start dynamic Credentials /////////////// + +//Defined in +/************************************** + #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 + +#define MAX_MQTT_SERVER_LEN 34 +char MQTT_Server [MAX_MQTT_SERVER_LEN + 1] = ""; + +#define MAX_MQTT_PORT_LEN 6 +char MQTT_Port [MAX_MQTT_PORT_LEN + 1] = ""; + +#define MAX_MQTT_USERNAME_LEN 34 +char MQTT_UserName [MAX_MQTT_USERNAME_LEN + 1] = ""; + +#define MAX_MQTT_PW_LEN 34 +char MQTT_PW [MAX_MQTT_PW_LEN + 1] = ""; + +#define MAX_MQTT_SUBS_TOPIC_LEN 34 +char MQTT_SubsTopic [MAX_MQTT_SUBS_TOPIC_LEN + 1] = ""; + +#define MAX_MQTT_PUB_TOPIC_LEN 34 +char MQTT_PubTopic [MAX_MQTT_PUB_TOPIC_LEN + 1] = ""; + +MenuItem myMenuItems [] = +{ + { "mqtt", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, + { "mqpt", "Port", MQTT_Port, MAX_MQTT_PORT_LEN }, + { "user", "MQTT UserName", MQTT_UserName, MAX_MQTT_USERNAME_LEN }, + { "mqpw", "MQTT PWD", MQTT_PW, MAX_MQTT_PW_LEN }, + { "subs", "Subs Topics", MQTT_SubsTopic, MAX_MQTT_SUBS_TOPIC_LEN }, + { "pubs", "Pubs Topics", MQTT_PubTopic, MAX_MQTT_PUB_TOPIC_LEN }, +}; + +#else + +MenuItem myMenuItems [] = {}; + +#endif + +uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; +/////// // End dynamic Credentials /////////// + +#else +#include + +String cloudBlynkServer = "account.duckdns.org"; +//String cloudBlynkServer = "192.168.2.110"; +#define BLYNK_SERVER_HARDWARE_PORT 8080 +char ssid[] = "SSID"; +char pass[] = "PASS"; +#endif #endif #if (BLYNK_USE_BLE_ONLY || !USE_BLYNK_WM) - // Blynk token shared between BLE and WiFi - char auth[] = "****"; +// Blynk token shared between BLE and WiFi +char auth[] = "****"; #endif bool USE_BLE = true; +long timePreviousMeassure = 0; + +#define WIFI_BLE_SELECTION_PIN 14 //Pin D14 mapped to pin GPIO14/HSPI_SCK/ADC16/TOUCH6/TMS of ESP32 + +BlynkTimer timer; + +#include +Ticker led_ticker; + +void set_led(byte status) +{ + digitalWrite(LED_BUILTIN, status); +} + +void noticeAlive(void) +{ + if (USE_BLE) + Blynk_BLE.virtualWrite(V0, F("OK")); + else + Blynk_WF.virtualWrite(V0, F("OK")); +} + +void heartBeatPrint(void) +{ + static int num = 1; + + if (Blynk.connected()) + { + set_led(HIGH); + led_ticker.once_ms(111, set_led, (byte) LOW); + Serial.print("B"); + } + else + { + Serial.print("F"); + } + + if (num == 80) + { + Serial.println(); + num = 1; + } + else if (num++ % 10 == 0) + { + Serial.print(" "); + } +} + +void checkStatus() +{ + static unsigned long checkstatus_timeout = 0; + +#define STATUS_CHECK_INTERVAL 60000L + + // Send status report every STATUS_REPORT_INTERVAL (60) seconds: we don't need to send updates frequently if there is no status change. + if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0)) + { + if (!USE_BLE) + { + // report Blynk connection + heartBeatPrint(); + } + + checkstatus_timeout = millis() + STATUS_CHECK_INTERVAL; + } +} + +char BLE_Device_Name[] = "GeigerCounter-BLE"; void setup() { Serial.begin(115200); Serial.println(F("\nStarting ESP32_BLE_WF")); - pinMode(WIFI_BLE_SELECTION_PIN, INPUT); - + pinMode(WIFI_BLE_SELECTION_PIN, INPUT_PULLUP); + #if BLYNK_USE_BLE_ONLY Blynk_BLE.setDeviceName(BLE_Device_Name); + + #if ESP32_BLE_WF_DEBUG + Serial.println(F("Blynk_BLE begin")); +#endif + Blynk_BLE.begin(auth); #else if (digitalRead(WIFI_BLE_SELECTION_PIN) == HIGH) { USE_BLE = false; Serial.println(F("GPIO14 HIGH, Use WiFi")); - #if USE_BLYNK_WM - Blynk_WF.begin(BLE_Device_Name); - #else - Blynk_WF.begin(auth, ssid, pass, cloudBlynkServer.c_str(), BLYNK_SERVER_HARDWARE_PORT); - #endif +#if USE_BLYNK_WM +#if ESP32_BLE_WF_DEBUG + Serial.println(F("USE_BLYNK_WM: Blynk_WF begin")); +#endif + // Set config portal channel, defalut = 1. Use 0 => random channel from 1-13 to avoid conflict + Blynk_WF.setConfigPortalChannel(0); + + Blynk_WF.begin(BLE_Device_Name); +#else + //Blynk_WF.begin(auth, ssid, pass); +#if ESP32_BLE_WF_DEBUG + Serial.println(F("Not USE_BLYNK_WM: Blynk_WF begin")); +#endif + Blynk_WF.begin(auth, ssid, pass, cloudBlynkServer.c_str(), BLYNK_SERVER_HARDWARE_PORT); +#endif } else { USE_BLE = true; Serial.println(F("GPIO14 LOW, Use BLE")); Blynk_BLE.setDeviceName(BLE_Device_Name); - #if USE_BLYNK_WM - if (Blynk_WF.getBlynkBLEToken() == String("nothing")) - { - Serial.println(F("No valid stored BLE auth. Have to run WiFi then enter config portal")); - USE_BLE = false; - Blynk_WF.begin(BLE_Device_Name); - } - String BLE_auth = Blynk_WF.getBlynkBLEToken(); - #else - String BLE_auth = auth; - #endif +#if USE_BLYNK_WM + if (Blynk_WF.getBlynkBLEToken() == NO_CONFIG) //String("blank")) + { + Serial.println(F("No valid stored BLE auth. Have to run WiFi then enter config portal")); + USE_BLE = false; + +#if ESP32_BLE_WF_DEBUG + Serial.println(F("USE_BLYNK_WM: No BLE Token. Blynk_WF begin")); +#endif + + Blynk_WF.begin(BLE_Device_Name); + } + String BLE_auth = Blynk_WF.getBlynkBLEToken(); +#else + String BLE_auth = auth; +#endif if (USE_BLE) { Serial.print(F("Connecting Blynk via BLE, using auth = ")); Serial.println(BLE_auth); + +#if ESP32_BLE_WF_DEBUG + Serial.println(F("USE_BLE: Blynk_BLE begin")); +#endif + Blynk_BLE.begin(BLE_auth.c_str()); } } #endif + + // Important, need to keep constant communication to Blynk Server at least once per ~25s + // Or Blynk will lost and have to (auto)reconnect + timer.setInterval(10000L, noticeAlive); +} + +#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS) +void displayCredentials(void) +{ + Serial.println("\nYour stored Credentials :"); + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata); + } } +#endif void loop() { @@ -221,40 +481,112 @@ void loop() 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++) + { + if (!strlen(myMenuItems[i].pdata)) + { + break; + } + + if ( i == (NUM_MENU_ITEMS - 1) ) + { + displayedCredentials = true; + displayCredentials(); + } + } + } +#endif } ``` -and this is the terminal debug output when running both WiFi and BT at the same time using example [Geiger_Counter_OLED_BT_BLE_WF](examples/Geiger_Counter_OLED_BT_BLE_WF) +The following is the sample terminal output when running example [Geiger_Counter_OLED_BT_BLE_WF](examples/Geiger_Counter_OLED_BT_BLE_WF) + +1. No Config Data => Config Portal + +``` +Starting Geiger-Counter-OLED-BT-BLE-WF +Use WiFi to connect Blynk +[346] Hostname=GeigerCounter-WiFi +[352] CCSum=0xbedc,RCSum=0xffffffff +[352] CrCCSum=0xaf50,CrRCSum=0xffffffff +[352] InitEEPROM,sz=2048,Datasz=628 +[352] pdata=blank,len=34 +[353] pdata=blank,len=6 +[355] pdata=blank,len=34 +[357] pdata=blank,len=34 +[360] pdata=blank,len=34 +[362] pdata=blank,len=34 +[364] CrCCSum=0xc30 +[439] b:Nodat.Stay +[1285] stConf:SSID=ESP_1CA4AE30,PW=MyESP_1CA4AE30 +[1285] IP=192.168.4.1,ch=7 +Use BLE to connect Blynk +[1392] CCSum=0x199d,RCSum=0x0 +[1392] CrCCSum=0xc30,CrRCSum=0xc30 +[1392] InitEEPROM,sz=2048,Datasz=628 +[1392] pdata=blank,len=34 +[1392] pdata=blank,len=6 +[1395] pdata=blank,len=34 +[1397] pdata=blank,len=34 +[1399] pdata=blank,len=34 +[1402] pdata=blank,len=34 +[1404] CrCCSum=0xc30 +BLE_auth = blank +No valid stored BLE auth. Have to run WiFi then enter config portal +Your stored Credentials : +MQTT Server = blank +Port = blank +MQTT UserName = blank +MQTT PWD = blank +Subs Topics = blank +Pubs Topics = blank +FFFFF ``` +2. Input valid credentials => reboot +``` Starting Geiger-Counter-OLED-BT-BLE-WF Use WiFi to connect Blynk -[328] Hostname=GeigerCounter-WiFi -[333] CCSum=0x3998,RCSum=0x3998 -[334] Hdr=ESP32_WFM,SSID=****,PW=**** -[334] Server=****.duckdns.org,Port=8080,Token=**** -[336] BT-Token=****,BLE-Token=**** -[344] BoardName=Geiger_Counter_OLED_BT -[348] +[347] Hostname=GeigerCounter-WiFi +[353] CCSum=0x4c8e,RCSum=0x4c8e +[353] CrCCSum=0x1ef9,CrRCSum=0x1ef9 +[353] Hdr=ESP32_WFM,BrdName=ESP32_BLE_BT_WM-TTGO +[353] SSID=HueNet1,PW=**** +[355] SSID1=HueNet,PW1=**** +[358] Server=account.ddns.net,Token=**** +[364] Server1=account.duckdns.org,Token1=**** +[370] BT-Token=****,BLE-Token=**** +[378] Port=8080 +[380] Connecting MultiWifi... +[4994] WiFi connected after time: 1 +[4994] SSID:HueNet,RSSI=-38 +[4994] Channel:10,IP=192.168.2.69 +[4994] b:WOK.TryB +[4994] ___ __ __ / _ )/ /_ _____ / /__ / _ / / // / _ \/ '_/ /____/_/\_, /_//_/_/\_\ /___/ v0.6.1 on ESP32 -[365] con2WF:start -[1866] con2WF:conOK -[1866] IP=192.168.2.92,GW=192.168.2.1,SN=255.255.0.0 -[1866] DNS1=192.168.2.1,DNS2=0.0.0.0 -[1866] b:WOK.TryB -[1866] BlynkArduinoClient.connect: Connecting to ****.duckdns.org:8080 -[2016] Ready (ping: 9ms). -[2086] b:WBOK +[5006] BlynkArduinoClient.connect: Connecting to account.ddns.net:8080 +[5040] Ready (ping: 12ms). +[5111] Conn2BlynkServer=account.ddns.net,Token=**** +[5111] b:WBOK Use BLE to connect Blynk BLE_auth = **** -[2086] +[5114] ___ __ __ / _ )/ /_ _____ / /__ / _ / / // / _ \/ '_/ @@ -262,9 +594,16 @@ BLE_auth = **** /___/ v0.6.1 on ESP32 -[14199] BLE connect -[15191] Ready +Your stored Credentials : +MQTT Server = mqtt.ddns.net +Port = 1883 +MQTT UserName = mqtt-user +MQTT PWD = mqtt-password +Subs Topics = SubTopic_ESP32_BLE_BT_WM +Pubs Topics = PubTopic_ESP32_BLE_BT_WM cpm = 0 - RadiationValue = 0.000 uSv/h - Equivalent RadiationDose = 0.0000 uSv +B[27863] BLECon +[29155] Ready cpm = 30 - RadiationValue = 0.197 uSv/h - Equivalent RadiationDose = 0.0008 uSv cpm = 60 - RadiationValue = 0.395 uSv/h - Equivalent RadiationDose = 0.0025 uSv cpm = 90 - RadiationValue = 0.592 uSv/h - Equivalent RadiationDose = 0.0049 uSv @@ -274,7 +613,7 @@ cpm = 180 - RadiationValue = 1.184 uSv/h - Equivalent RadiationDose = 0.0173 uS cpm = 210 - RadiationValue = 1.382 uSv/h - Equivalent RadiationDose = 0.0230 uSv cpm = 240 - RadiationValue = 1.579 uSv/h - Equivalent RadiationDose = 0.0296 uSv cpm = 270 - RadiationValue = 1.777 uSv/h - Equivalent RadiationDose = 0.0370 uSv -cpm = 300 - RadiationValue = 1.974 uSv/h - Equivalent RadiationDose = 0.0452 uSv + cpm = 300 - RadiationValue = 1.974 uSv/h - Equivalent RadiationDose = 0.0452 uSv cpm = 330 - RadiationValue = 2.171 uSv/h - Equivalent RadiationDose = 0.0543 uSv cpm = 360 - RadiationValue = 2.369 uSv/h - Equivalent RadiationDose = 0.0642 uSv cpm = 390 - RadiationValue = 2.566 uSv/h - Equivalent RadiationDose = 0.0748 uSv @@ -285,8 +624,6 @@ cpm = 510 - RadiationValue = 3.356 uSv/h - Equivalent RadiationDose = 0.1258 uS cpm = 540 - RadiationValue = 3.553 uSv/h - Equivalent RadiationDose = 0.1406 uSv cpm = 570 - RadiationValue = 3.751 uSv/h - Equivalent RadiationDose = 0.1563 uSv cpm = 600 - RadiationValue = 3.948 uSv/h - Equivalent RadiationDose = 0.1727 uSv -cpm = 630 - RadiationValue = 4.145 uSv/h - Equivalent RadiationDose = 0.1900 uSv - ``` @@ -305,6 +642,24 @@ cpm = 630 - RadiationValue = 4.145 uSv/h - Equivalent RadiationDose = 0.1900 uS 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 to avoid channel conflict. + +### Major Releases v1.0.5 + +***Why this version*** + +1. ***Multiple WiFi Credentials (SSID, Password)*** and system will autoconnect to the best and available WiFi SSID. +2. ***Multiple Blynk Credentials (Server, Token)*** and system will autoconnect to the available Blynk Servers. +3. New ***powerful-yet-simple-to-use feature to enable adding dynamic custom parameters*** from sketch and input using the same Config Portal. Config Portal will be auto-adjusted to match the number of dynamic parameters. +4. Dynamic custom parameters to be saved ***automatically in EEPROM, or SPIFFS***. +5. WiFi Password max length increased to 63 from 31, according to WPA2 standard. +6. Permit to input special chars such as ***%*** and ***#*** into data fields. +7. Config Portal AP Channel is configurable (either static or random channel) to avoid channel conflict to other APs. ### Releases v1.0.4 diff --git a/examples/ESP32_BLE_WF/ESP32_BLE_WF.ino b/examples/ESP32_BLE_WF/ESP32_BLE_WF.ino index c98cf26..f60f295 100644 --- a/examples/ESP32_BLE_WF/ESP32_BLE_WF.ino +++ b/examples/ESP32_BLE_WF/ESP32_BLE_WF.ino @@ -6,7 +6,7 @@ Forked from Blynk library v0.6.1 https://github.com/blynkkk/blynk-library/releases Built by Khoi Hoang https://github.com/khoih-prog/BlynkGSM_ESPManager Licensed under MIT license - Version: 1.0.4 + Version: 1.0.5 Based on orignal code by Crosswalkersam (https://community.blynk.cc/u/Crosswalkersam) posted in https://community.blynk.cc/t/select-connection-type-via-switch/43176 @@ -20,25 +20,39 @@ 1.0.2 K Hoang 04/02/2020 Add Blynk WiFiManager support similar to Blynk_WM library 1.0.3 K Hoang 24/02/2020 Add checksum, clearConfigData() 1.0.4 K Hoang 14/03/2020 Enhance GUI. Reduce code size. + 1.0.5 K Hoang 18/04/2020 MultiWiFi/Blynk. Dynamic custom parameters. SSID password maxlen is 63 now. + Permit special chars # and % in input data. *****************************************************************************************************************************/ - +/**************************************************************************************************************************** + 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) + *****************************************************************************************************************************/ #ifndef ESP32 #error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting. #endif #define BLYNK_PRINT Serial +#define ESP32_BLE_WF_DEBUG true + #define USE_BLYNK_WM true //#define USE_BLYNK_WM false -#define USE_SPIFFS true -//#define USE_SPIFFS false +//#define USE_SPIFFS true +#define USE_SPIFFS false #if (!USE_SPIFFS) // EEPROM_SIZE must be <= 2048 and >= CONFIG_DATA_SIZE #define EEPROM_SIZE (2 * 1024) // EEPROM_START + CONFIG_DATA_SIZE must be <= EEPROM_SIZE -#define EEPROM_START 768 +#define EEPROM_START 0 #endif // Force some params in Blynk, only valid for library version 1.0.1 and later @@ -58,6 +72,64 @@ #if USE_BLYNK_WM #warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP) #include + +#define USE_DYNAMIC_PARAMETERS true + +/////////////// Start dynamic Credentials /////////////// + +//Defined in +/************************************** + #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 + +#define MAX_MQTT_SERVER_LEN 34 +char MQTT_Server [MAX_MQTT_SERVER_LEN + 1] = ""; + +#define MAX_MQTT_PORT_LEN 6 +char MQTT_Port [MAX_MQTT_PORT_LEN + 1] = ""; + +#define MAX_MQTT_USERNAME_LEN 34 +char MQTT_UserName [MAX_MQTT_USERNAME_LEN + 1] = ""; + +#define MAX_MQTT_PW_LEN 34 +char MQTT_PW [MAX_MQTT_PW_LEN + 1] = ""; + +#define MAX_MQTT_SUBS_TOPIC_LEN 34 +char MQTT_SubsTopic [MAX_MQTT_SUBS_TOPIC_LEN + 1] = ""; + +#define MAX_MQTT_PUB_TOPIC_LEN 34 +char MQTT_PubTopic [MAX_MQTT_PUB_TOPIC_LEN + 1] = ""; + +MenuItem myMenuItems [] = +{ + { "mqtt", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, + { "mqpt", "Port", MQTT_Port, MAX_MQTT_PORT_LEN }, + { "user", "MQTT UserName", MQTT_UserName, MAX_MQTT_USERNAME_LEN }, + { "mqpw", "MQTT PWD", MQTT_PW, MAX_MQTT_PW_LEN }, + { "subs", "Subs Topics", MQTT_SubsTopic, MAX_MQTT_SUBS_TOPIC_LEN }, + { "pubs", "Pubs Topics", MQTT_PubTopic, MAX_MQTT_PUB_TOPIC_LEN }, +}; + +#else + +MenuItem myMenuItems [] = {}; + +#endif + +uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; +/////// // End dynamic Credentials /////////// + #else #include @@ -77,23 +149,68 @@ char auth[] = "****"; bool USE_BLE = true; long timePreviousMeassure = 0; -#define MEASURE_INTERVAL_MS 20000L - #define WIFI_BLE_SELECTION_PIN 14 //Pin D14 mapped to pin GPIO14/HSPI_SCK/ADC16/TOUCH6/TMS of ESP32 -void checkStatus() +BlynkTimer timer; + +#include +Ticker led_ticker; + +void set_led(byte status) { - if (millis() - timePreviousMeassure > MEASURE_INTERVAL_MS) + digitalWrite(LED_BUILTIN, status); +} + +void noticeAlive(void) +{ + if (USE_BLE) + Blynk_BLE.virtualWrite(V0, F("OK")); + else + Blynk_WF.virtualWrite(V0, F("OK")); +} + +void heartBeatPrint(void) +{ + static int num = 1; + + if (Blynk.connected()) { + set_led(HIGH); + led_ticker.once_ms(111, set_led, (byte) LOW); + Serial.print("B"); + } + else + { + Serial.print("F"); + } + + if (num == 80) + { + Serial.println(); + num = 1; + } + else if (num++ % 10 == 0) + { + Serial.print(" "); + } +} + +void checkStatus() +{ + static unsigned long checkstatus_timeout = 0; + +#define STATUS_CHECK_INTERVAL 60000L + + // Send status report every STATUS_REPORT_INTERVAL (60) seconds: we don't need to send updates frequently if there is no status change. + if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0)) + { if (!USE_BLE) { - if (Blynk.connected()) - Serial.println(F("B")); - else - Serial.println(F("F")); + // report Blynk connection + heartBeatPrint(); } - timePreviousMeassure = millis(); + checkstatus_timeout = millis() + STATUS_CHECK_INTERVAL; } } @@ -104,10 +221,15 @@ void setup() Serial.begin(115200); Serial.println(F("\nStarting ESP32_BLE_WF")); - pinMode(WIFI_BLE_SELECTION_PIN, INPUT); + pinMode(WIFI_BLE_SELECTION_PIN, INPUT_PULLUP); #if BLYNK_USE_BLE_ONLY Blynk_BLE.setDeviceName(BLE_Device_Name); + + #if ESP32_BLE_WF_DEBUG + Serial.println(F("Blynk_BLE begin")); +#endif + Blynk_BLE.begin(auth); #else if (digitalRead(WIFI_BLE_SELECTION_PIN) == HIGH) @@ -115,8 +237,18 @@ void setup() USE_BLE = false; Serial.println(F("GPIO14 HIGH, Use WiFi")); #if USE_BLYNK_WM +#if ESP32_BLE_WF_DEBUG + Serial.println(F("USE_BLYNK_WM: Blynk_WF begin")); +#endif + // Set config portal channel, defalut = 1. Use 0 => random channel from 1-13 to avoid conflict + Blynk_WF.setConfigPortalChannel(0); + Blynk_WF.begin(BLE_Device_Name); #else + //Blynk_WF.begin(auth, ssid, pass); +#if ESP32_BLE_WF_DEBUG + Serial.println(F("Not USE_BLYNK_WM: Blynk_WF begin")); +#endif Blynk_WF.begin(auth, ssid, pass, cloudBlynkServer.c_str(), BLYNK_SERVER_HARDWARE_PORT); #endif } @@ -126,10 +258,15 @@ void setup() Serial.println(F("GPIO14 LOW, Use BLE")); Blynk_BLE.setDeviceName(BLE_Device_Name); #if USE_BLYNK_WM - if (Blynk_WF.getBlynkBLEToken() == String("nothing")) + if (Blynk_WF.getBlynkBLEToken() == NO_CONFIG) //String("blank")) { Serial.println(F("No valid stored BLE auth. Have to run WiFi then enter config portal")); USE_BLE = false; + +#if ESP32_BLE_WF_DEBUG + Serial.println(F("USE_BLYNK_WM: No BLE Token. Blynk_WF begin")); +#endif + Blynk_WF.begin(BLE_Device_Name); } String BLE_auth = Blynk_WF.getBlynkBLEToken(); @@ -141,11 +278,32 @@ void setup() { Serial.print(F("Connecting Blynk via BLE, using auth = ")); Serial.println(BLE_auth); + +#if ESP32_BLE_WF_DEBUG + Serial.println(F("USE_BLE: Blynk_BLE begin")); +#endif + Blynk_BLE.begin(BLE_auth.c_str()); } } #endif + + // Important, need to keep constant communication to Blynk Server at least once per ~25s + // Or Blynk will lost and have to (auto)reconnect + timer.setInterval(10000L, noticeAlive); +} + +#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS) +void displayCredentials(void) +{ + Serial.println("\nYour stored Credentials :"); + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata); + } } +#endif void loop() { @@ -158,5 +316,27 @@ void loop() 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++) + { + if (!strlen(myMenuItems[i].pdata)) + { + break; + } + + if ( i == (NUM_MENU_ITEMS - 1) ) + { + displayedCredentials = true; + displayCredentials(); + } + } + } +#endif } diff --git a/examples/ESP32_BT_WF/ESP32_BT_WF.ino b/examples/ESP32_BT_WF/ESP32_BT_WF.ino index 7472d05..0d69d13 100644 --- a/examples/ESP32_BT_WF/ESP32_BT_WF.ino +++ b/examples/ESP32_BT_WF/ESP32_BT_WF.ino @@ -6,7 +6,7 @@ Forked from Blynk library v0.6.1 https://github.com/blynkkk/blynk-library/releases Built by Khoi Hoang https://github.com/khoih-prog/BlynkGSM_ESPManager Licensed under MIT license - Version: 1.0.4 + Version: 1.0.5 Based on orignal code by Crosswalkersam (https://community.blynk.cc/u/Crosswalkersam) posted in https://community.blynk.cc/t/select-connection-type-via-switch/43176 @@ -20,7 +20,20 @@ 1.0.2 K Hoang 04/02/2020 Add Blynk WiFiManager support similar to Blynk_WM library 1.0.3 K Hoang 24/02/2020 Add checksum, clearConfigData() 1.0.4 K Hoang 14/03/2020 Enhance GUI. Reduce code size. + 1.0.5 K Hoang 18/04/2020 MultiWiFi/Blynk. Dynamic custom parameters. SSID password maxlen is 63 now. + Permit special chars # and % in input data. *****************************************************************************************************************************/ +/**************************************************************************************************************************** + 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) + *****************************************************************************************************************************/ #ifndef ESP32 #error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting. @@ -28,17 +41,19 @@ #define BLYNK_PRINT Serial +#define ESP32_BT_WF_DEBUG true + #define USE_BLYNK_WM true //#define USE_BLYNK_WM false -#define USE_SPIFFS true -//#define USE_SPIFFS false +//#define USE_SPIFFS true +#define USE_SPIFFS false #if (!USE_SPIFFS) // EEPROM_SIZE must be <= 2048 and >= CONFIG_DATA_SIZE #define EEPROM_SIZE (2 * 1024) // EEPROM_START + CONFIG_DATA_SIZE must be <= EEPROM_SIZE -#define EEPROM_START 512 +#define EEPROM_START 0 #endif // Force some params in Blynk, only valid for library version 1.0.1 and later @@ -57,6 +72,65 @@ #if USE_BLYNK_WM #warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP) #include + +#define USE_DYNAMIC_PARAMETERS true + +/////////////// Start dynamic Credentials /////////////// + +//Defined in +/************************************** + #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 + +#define MAX_MQTT_SERVER_LEN 34 +char MQTT_Server [MAX_MQTT_SERVER_LEN + 1] = ""; + +#define MAX_MQTT_PORT_LEN 6 +char MQTT_Port [MAX_MQTT_PORT_LEN + 1] = ""; + +#define MAX_MQTT_USERNAME_LEN 34 +char MQTT_UserName [MAX_MQTT_USERNAME_LEN + 1] = ""; + +#define MAX_MQTT_PW_LEN 34 +char MQTT_PW [MAX_MQTT_PW_LEN + 1] = ""; + +#define MAX_MQTT_SUBS_TOPIC_LEN 34 +char MQTT_SubsTopic [MAX_MQTT_SUBS_TOPIC_LEN + 1] = ""; + +#define MAX_MQTT_PUB_TOPIC_LEN 34 +char MQTT_PubTopic [MAX_MQTT_PUB_TOPIC_LEN + 1] = ""; + +MenuItem myMenuItems [] = +{ + { "mqtt", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, + { "mqpt", "Port", MQTT_Port, MAX_MQTT_PORT_LEN }, + { "user", "MQTT UserName", MQTT_UserName, MAX_MQTT_USERNAME_LEN }, + { "mqpw", "MQTT PWD", MQTT_PW, MAX_MQTT_PW_LEN }, + { "subs", "Subs Topics", MQTT_SubsTopic, MAX_MQTT_SUBS_TOPIC_LEN }, + { "pubs", "Pubs Topics", MQTT_PubTopic, MAX_MQTT_PUB_TOPIC_LEN }, +}; + +#else + +MenuItem myMenuItems [] = {}; + +#endif + +uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; +/////// // End dynamic Credentials /////////// + + #else #include @@ -78,21 +152,66 @@ long timePreviousMeassure = 0; #define WIFI_BT_SELECTION_PIN 14 //Pin D14 mapped to pin GPIO14/HSPI_SCK/ADC16/TOUCH6/TMS of ESP32 -#define MEASURE_INTERVAL_MS 20000L +BlynkTimer timer; + +#include +Ticker led_ticker; + +void set_led(byte status) +{ + digitalWrite(LED_BUILTIN, status); +} + +void noticeAlive(void) +{ + if (USE_BT) + Blynk_BT.virtualWrite(V0, F("OK")); + else + Blynk_WF.virtualWrite(V0, F("OK")); +} + +void heartBeatPrint(void) +{ + static int num = 1; + + if (Blynk.connected()) + { + set_led(HIGH); + led_ticker.once_ms(111, set_led, (byte) LOW); + Serial.print("B"); + } + else + { + Serial.print("F"); + } + + if (num == 80) + { + Serial.println(); + num = 1; + } + else if (num++ % 10 == 0) + { + Serial.print(" "); + } +} void checkStatus() { - if (millis() - timePreviousMeassure > MEASURE_INTERVAL_MS) + static unsigned long checkstatus_timeout = 0; + +#define STATUS_CHECK_INTERVAL 60000L + + // Send status report every STATUS_REPORT_INTERVAL (60) seconds: we don't need to send updates frequently if there is no status change. + if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0)) { if (!USE_BT) { - if (Blynk.connected()) - Serial.println(F("B")); - else - Serial.println(F("F")); + // report Blynk connection + heartBeatPrint(); } - timePreviousMeassure = millis(); + checkstatus_timeout = millis() + STATUS_CHECK_INTERVAL; } } @@ -101,12 +220,17 @@ char BT_Device_Name[] = "GeigerCounter-BT"; void setup() { Serial.begin(115200); - Serial.println(F("\nStarting Geiger-Counter")); + Serial.println(F("\nStarting ESP32_BT_WF")); - pinMode(WIFI_BT_SELECTION_PIN, INPUT); + pinMode(WIFI_BT_SELECTION_PIN, INPUT_PULLUP); #if BLYNK_USE_BT_ONLY Blynk_BT.setDeviceName(BT_Device_Name); + +#if ESP32_BT_WF_DEBUG + Serial.println(F("Blynk_BT begin")); +#endif + Blynk_BT.begin(auth); #else if (digitalRead(WIFI_BT_SELECTION_PIN) == HIGH) @@ -114,9 +238,18 @@ void setup() USE_BT = false; Serial.println(F("GPIO14 HIGH, Use WiFi")); #if USE_BLYNK_WM +#if ESP32_BT_WF_DEBUG + Serial.println(F("USE_BLYNK_WM: Blynk_WF begin")); +#endif + // Set config portal channel, defalut = 1. Use 0 => random channel from 1-13 to avoid conflict + Blynk_WF.setConfigPortalChannel(0); + Blynk_WF.begin(BT_Device_Name); #else //Blynk_WF.begin(auth, ssid, pass); +#if ESP32_BT_WF_DEBUG + Serial.println(F("Not USE_BLYNK_WM: Blynk_WF begin")); +#endif Blynk_WF.begin(auth, ssid, pass, cloudBlynkServer.c_str(), BLYNK_SERVER_HARDWARE_PORT); #endif } @@ -126,10 +259,15 @@ void setup() Serial.println(F("GPIO14 LOW, Use BT")); Blynk_BT.setDeviceName(BT_Device_Name); #if USE_BLYNK_WM - if (Blynk_WF.getBlynkBTToken() == String("nothing")) + if (Blynk_WF.getBlynkBTToken() == NO_CONFIG) //String("blank")) { Serial.println(F("No valid stored BT auth. Have to run WiFi then enter config portal")); USE_BT = false; + +#if ESP32_BT_WF_DEBUG + Serial.println(F("USE_BLYNK_WM: No BT Token. Blynk_WF begin")); +#endif + Blynk_WF.begin(BT_Device_Name); } String BT_auth = Blynk_WF.getBlynkBTToken(); @@ -141,11 +279,32 @@ void setup() { Serial.print(F("Connecting Blynk via BT, using auth = ")); Serial.println(BT_auth); + +#if ESP32_BT_WF_DEBUG + Serial.println(F("USE_BT: Blynk_BT begin")); +#endif + Blynk_BT.begin(BT_auth.c_str()); } } #endif + + // Important, need to keep constant communication to Blynk Server at least once per ~25s + // Or Blynk will lost and have to (auto)reconnect + timer.setInterval(10000L, noticeAlive); +} + +#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS) +void displayCredentials(void) +{ + Serial.println("\nYour stored Credentials :"); + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata); + } } +#endif void loop() { @@ -158,5 +317,27 @@ void loop() 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++) + { + if (!strlen(myMenuItems[i].pdata)) + { + break; + } + + if ( i == (NUM_MENU_ITEMS - 1) ) + { + displayedCredentials = true; + displayCredentials(); + } + } + } +#endif } diff --git a/examples/Geiger_Counter_BLE/Geiger_Counter_BLE.ino b/examples/Geiger_Counter_BLE/Geiger_Counter_BLE.ino index e7f31c4..37ddfa5 100644 --- a/examples/Geiger_Counter_BLE/Geiger_Counter_BLE.ino +++ b/examples/Geiger_Counter_BLE/Geiger_Counter_BLE.ino @@ -6,7 +6,7 @@ Forked from Blynk library v0.6.1 https://github.com/blynkkk/blynk-library/releases Built by Khoi Hoang https://github.com/khoih-prog/BlynkGSM_ESPManager Licensed under MIT license - Version: 1.0.4 + Version: 1.0.5 Based on orignal code by Crosswalkersam (https://community.blynk.cc/u/Crosswalkersam) posted in https://community.blynk.cc/t/select-connection-type-via-switch/43176 @@ -20,7 +20,20 @@ 1.0.2 K Hoang 04/02/2020 Add Blynk WiFiManager support similar to Blynk_WM library 1.0.3 K Hoang 24/02/2020 Add checksum, clearConfigData() 1.0.4 K Hoang 14/03/2020 Enhance GUI. Reduce code size. + 1.0.5 K Hoang 18/04/2020 MultiWiFi/Blynk. Dynamic custom parameters. SSID password maxlen is 63 now. + Permit special chars # and % in input data. *****************************************************************************************************************************/ +/**************************************************************************************************************************** + 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) + *****************************************************************************************************************************/ #ifndef ESP32 #error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting. @@ -38,7 +51,7 @@ // EEPROM_SIZE must be <= 2048 and >= CONFIG_DATA_SIZE #define EEPROM_SIZE (2 * 1024) // EEPROM_START + CONFIG_DATA_SIZE must be <= EEPROM_SIZE -#define EEPROM_START 768 +#define EEPROM_START 0 #endif // Force some params in Blynk, only valid for library version 1.0.1 and later @@ -58,6 +71,64 @@ #if USE_BLYNK_WM #warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP) #include + +#define USE_DYNAMIC_PARAMETERS true + +/////////////// Start dynamic Credentials /////////////// + +//Defined in +/************************************** + #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 + +#define MAX_MQTT_SERVER_LEN 34 +char MQTT_Server [MAX_MQTT_SERVER_LEN + 1] = ""; + +#define MAX_MQTT_PORT_LEN 6 +char MQTT_Port [MAX_MQTT_PORT_LEN + 1] = ""; + +#define MAX_MQTT_USERNAME_LEN 34 +char MQTT_UserName [MAX_MQTT_USERNAME_LEN + 1] = ""; + +#define MAX_MQTT_PW_LEN 34 +char MQTT_PW [MAX_MQTT_PW_LEN + 1] = ""; + +#define MAX_MQTT_SUBS_TOPIC_LEN 34 +char MQTT_SubsTopic [MAX_MQTT_SUBS_TOPIC_LEN + 1] = ""; + +#define MAX_MQTT_PUB_TOPIC_LEN 34 +char MQTT_PubTopic [MAX_MQTT_PUB_TOPIC_LEN + 1] = ""; + +MenuItem myMenuItems [] = +{ + { "mqtt", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, + { "mqpt", "Port", MQTT_Port, MAX_MQTT_PORT_LEN }, + { "user", "MQTT UserName", MQTT_UserName, MAX_MQTT_USERNAME_LEN }, + { "mqpw", "MQTT PWD", MQTT_PW, MAX_MQTT_PW_LEN }, + { "subs", "Subs Topics", MQTT_SubsTopic, MAX_MQTT_SUBS_TOPIC_LEN }, + { "pubs", "Pubs Topics", MQTT_PubTopic, MAX_MQTT_PUB_TOPIC_LEN }, +}; + +#else + +MenuItem myMenuItems [] = {}; + +#endif + +uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; +/////// // End dynamic Credentials /////////// + #else #include @@ -104,6 +175,9 @@ volatile long count = 0; BlynkTimer timer; +#include +Ticker led_ticker; + void IRAM_ATTR countPulse() { if ((long)(micros() - last_micros) >= DEBOUNCE_TIME_MICRO_SEC) @@ -152,6 +226,37 @@ void Serial_Display() Serial.println(F(" uSv")); } +void set_led(byte status) +{ + digitalWrite(LED_BUILTIN, status); +} + +void heartBeatPrint(void) +{ + static int num = 1; + + if (Blynk.connected()) + { + set_led(HIGH); + led_ticker.once_ms(111, set_led, (byte) LOW); + Serial.print("B"); + } + else + { + Serial.print("F"); + } + + if (num == 80) + { + Serial.println(); + num = 1; + } + else if (num++ % 10 == 0) + { + Serial.print(" "); + } +} + #define USE_SIMULATION true //#define USE_SIMULATION false @@ -195,6 +300,9 @@ void checkStatus() #else count = 0; #endif + + // report Blynk connection + heartBeatPrint(); } } @@ -217,6 +325,9 @@ void setup() USE_BLE = false; Serial.println(F("GPIO14 HIGH, Use WiFi")); #if USE_BLYNK_WM + // Set config portal channel, defalut = 1. Use 0 => random channel from 1-13 to avoid conflict + Blynk_WF.setConfigPortalChannel(0); + Blynk_WF.begin(BLE_Device_Name); #else //Blynk_WF.begin(auth, ssid, pass); @@ -229,7 +340,7 @@ void setup() Serial.println(F("GPIO14 LOW, Use BLE")); Blynk_BLE.setDeviceName(BLE_Device_Name); #if USE_BLYNK_WM - if (Blynk_WF.getBlynkBLEToken() == String("nothing")) + if (Blynk_WF.getBlynkBLEToken() == NO_CONFIG) //String("blank")) { Serial.println(F("No valid stored BLE auth. Have to run WiFi then enter config portal")); USE_BLE = false; @@ -252,6 +363,18 @@ void setup() timer.setInterval(5000L, sendDatatoBlynk); } +#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS) +void displayCredentials(void) +{ + Serial.println("\nYour stored Credentials :"); + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata); + } +} +#endif + void loop() { #if BLYNK_USE_BLE_ONLY @@ -265,4 +388,25 @@ void loop() 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++) + { + if (!strlen(myMenuItems[i].pdata)) + { + break; + } + + if ( i == (NUM_MENU_ITEMS - 1) ) + { + displayedCredentials = true; + displayCredentials(); + } + } + } +#endif } diff --git a/examples/Geiger_Counter_BT/Geiger_Counter_BT.ino b/examples/Geiger_Counter_BT/Geiger_Counter_BT.ino index ef9cc0b..1f59848 100644 --- a/examples/Geiger_Counter_BT/Geiger_Counter_BT.ino +++ b/examples/Geiger_Counter_BT/Geiger_Counter_BT.ino @@ -6,7 +6,7 @@ Forked from Blynk library v0.6.1 https://github.com/blynkkk/blynk-library/releases Built by Khoi Hoang https://github.com/khoih-prog/BlynkGSM_ESPManager Licensed under MIT license - Version: 1.0.4 + Version: 1.0.5 Based on orignal code by Crosswalkersam (https://community.blynk.cc/u/Crosswalkersam) posted in https://community.blynk.cc/t/select-connection-type-via-switch/43176 @@ -20,7 +20,20 @@ 1.0.2 K Hoang 04/02/2020 Add Blynk WiFiManager support similar to Blynk_WM library 1.0.3 K Hoang 24/02/2020 Add checksum, clearConfigData() 1.0.4 K Hoang 14/03/2020 Enhance GUI. Reduce code size. + 1.0.5 K Hoang 18/04/2020 MultiWiFi/Blynk. Dynamic custom parameters. SSID password maxlen is 63 now. + Permit special chars # and % in input data. *****************************************************************************************************************************/ +/**************************************************************************************************************************** + 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) + *****************************************************************************************************************************/ #ifndef ESP32 #error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting. @@ -31,14 +44,14 @@ #define USE_BLYNK_WM true //#define USE_BLYNK_WM false -#define USE_SPIFFS true -//#define USE_SPIFFS false +//#define USE_SPIFFS true +#define USE_SPIFFS false #if (!USE_SPIFFS) // EEPROM_SIZE must be <= 2048 and >= CONFIG_DATA_SIZE #define EEPROM_SIZE (2 * 1024) // EEPROM_START + CONFIG_DATA_SIZE must be <= EEPROM_SIZE -#define EEPROM_START 512 +#define EEPROM_START 0 #endif // Force some params in Blynk, only valid for library version 1.0.1 and later @@ -57,6 +70,64 @@ #if USE_BLYNK_WM #warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP) #include + +#define USE_DYNAMIC_PARAMETERS true + +/////////////// Start dynamic Credentials /////////////// + +//Defined in +/************************************** + #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 + +#define MAX_MQTT_SERVER_LEN 34 +char MQTT_Server [MAX_MQTT_SERVER_LEN + 1] = ""; + +#define MAX_MQTT_PORT_LEN 6 +char MQTT_Port [MAX_MQTT_PORT_LEN + 1] = ""; + +#define MAX_MQTT_USERNAME_LEN 34 +char MQTT_UserName [MAX_MQTT_USERNAME_LEN + 1] = ""; + +#define MAX_MQTT_PW_LEN 34 +char MQTT_PW [MAX_MQTT_PW_LEN + 1] = ""; + +#define MAX_MQTT_SUBS_TOPIC_LEN 34 +char MQTT_SubsTopic [MAX_MQTT_SUBS_TOPIC_LEN + 1] = ""; + +#define MAX_MQTT_PUB_TOPIC_LEN 34 +char MQTT_PubTopic [MAX_MQTT_PUB_TOPIC_LEN + 1] = ""; + +MenuItem myMenuItems [] = +{ + { "mqtt", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, + { "mqpt", "Port", MQTT_Port, MAX_MQTT_PORT_LEN }, + { "user", "MQTT UserName", MQTT_UserName, MAX_MQTT_USERNAME_LEN }, + { "mqpw", "MQTT PWD", MQTT_PW, MAX_MQTT_PW_LEN }, + { "subs", "Subs Topics", MQTT_SubsTopic, MAX_MQTT_SUBS_TOPIC_LEN }, + { "pubs", "Pubs Topics", MQTT_PubTopic, MAX_MQTT_PUB_TOPIC_LEN }, +}; + +#else + +MenuItem myMenuItems [] = {}; + +#endif + +uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; +/////// // End dynamic Credentials /////////// + #else #include @@ -103,6 +174,9 @@ volatile long count = 0; BlynkTimer timer; +#include +Ticker led_ticker; + void IRAM_ATTR countPulse() { if ((long)(micros() - last_micros) >= DEBOUNCE_TIME_MICRO_SEC) @@ -151,6 +225,37 @@ void Serial_Display() Serial.println(F(" uSv")); } +void set_led(byte status) +{ + digitalWrite(LED_BUILTIN, status); +} + +void heartBeatPrint(void) +{ + static int num = 1; + + if (Blynk.connected()) + { + set_led(HIGH); + led_ticker.once_ms(111, set_led, (byte) LOW); + Serial.print("B"); + } + else + { + Serial.print("F"); + } + + if (num == 80) + { + Serial.println(); + num = 1; + } + else if (num++ % 10 == 0) + { + Serial.print(" "); + } +} + #define USE_SIMULATION true //#define USE_SIMULATION false @@ -194,6 +299,9 @@ void checkStatus() #else count = 0; #endif + + // report Blynk connection + heartBeatPrint(); } } @@ -216,6 +324,9 @@ void setup() USE_BT = false; Serial.println(F("GPIO14 HIGH, Use WiFi")); #if USE_BLYNK_WM + // Set config portal channel, defalut = 1. Use 0 => random channel from 1-13 to avoid conflict + Blynk_WF.setConfigPortalChannel(0); + Blynk_WF.begin(BT_Device_Name); #else //Blynk_WF.begin(auth, ssid, pass); @@ -228,7 +339,7 @@ void setup() Serial.println(F("GPIO14 LOW, Use BT")); Blynk_BT.setDeviceName(BT_Device_Name); #if USE_BLYNK_WM - if (Blynk_WF.getBlynkBTToken() == String("nothing")) + if (Blynk_WF.getBlynkBTToken() == NO_CONFIG) //String("blank")) { Serial.println(F("No valid stored BT auth. Have to run WiFi then enter config portal")); USE_BT = false; @@ -251,6 +362,18 @@ void setup() timer.setInterval(5000L, sendDatatoBlynk); } +#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS) +void displayCredentials(void) +{ + Serial.println("\nYour stored Credentials :"); + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata); + } +} +#endif + void loop() { #if BLYNK_USE_BT_ONLY @@ -264,4 +387,25 @@ void loop() 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++) + { + if (!strlen(myMenuItems[i].pdata)) + { + break; + } + + if ( i == (NUM_MENU_ITEMS - 1) ) + { + displayedCredentials = true; + displayCredentials(); + } + } + } +#endif } diff --git a/examples/Geiger_Counter_OLED/Geiger_Counter_OLED.ino b/examples/Geiger_Counter_OLED/Geiger_Counter_OLED.ino index 58798fe..1a8d830 100644 --- a/examples/Geiger_Counter_OLED/Geiger_Counter_OLED.ino +++ b/examples/Geiger_Counter_OLED/Geiger_Counter_OLED.ino @@ -6,7 +6,7 @@ Forked from Blynk library v0.6.1 https://github.com/blynkkk/blynk-library/releases Built by Khoi Hoang https://github.com/khoih-prog/BlynkGSM_ESPManager Licensed under MIT license - Version: 1.0.4 + Version: 1.0.5 Based on orignal code by Crosswalkersam (https://community.blynk.cc/u/Crosswalkersam) posted in https://community.blynk.cc/t/select-connection-type-via-switch/43176 @@ -20,7 +20,20 @@ 1.0.2 K Hoang 04/02/2020 Add Blynk WiFiManager support similar to Blynk_WM library 1.0.3 K Hoang 24/02/2020 Add checksum, clearConfigData() 1.0.4 K Hoang 14/03/2020 Enhance GUI. Reduce code size. + 1.0.5 K Hoang 18/04/2020 MultiWiFi/Blynk. Dynamic custom parameters. SSID password maxlen is 63 now. + Permit special chars # and % in input data. *****************************************************************************************************************************/ +/**************************************************************************************************************************** + 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) + *****************************************************************************************************************************/ #ifndef ESP32 #error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting. @@ -62,6 +75,64 @@ #if USE_BLYNK_WM #warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP) #include + +#define USE_DYNAMIC_PARAMETERS true + +/////////////// Start dynamic Credentials /////////////// + +//Defined in +/************************************** + #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 + +#define MAX_MQTT_SERVER_LEN 34 +char MQTT_Server [MAX_MQTT_SERVER_LEN + 1] = ""; + +#define MAX_MQTT_PORT_LEN 6 +char MQTT_Port [MAX_MQTT_PORT_LEN + 1] = ""; + +#define MAX_MQTT_USERNAME_LEN 34 +char MQTT_UserName [MAX_MQTT_USERNAME_LEN + 1] = ""; + +#define MAX_MQTT_PW_LEN 34 +char MQTT_PW [MAX_MQTT_PW_LEN + 1] = ""; + +#define MAX_MQTT_SUBS_TOPIC_LEN 34 +char MQTT_SubsTopic [MAX_MQTT_SUBS_TOPIC_LEN + 1] = ""; + +#define MAX_MQTT_PUB_TOPIC_LEN 34 +char MQTT_PubTopic [MAX_MQTT_PUB_TOPIC_LEN + 1] = ""; + +MenuItem myMenuItems [] = +{ + { "mqtt", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, + { "mqpt", "Port", MQTT_Port, MAX_MQTT_PORT_LEN }, + { "user", "MQTT UserName", MQTT_UserName, MAX_MQTT_USERNAME_LEN }, + { "mqpw", "MQTT PWD", MQTT_PW, MAX_MQTT_PW_LEN }, + { "subs", "Subs Topics", MQTT_SubsTopic, MAX_MQTT_SUBS_TOPIC_LEN }, + { "pubs", "Pubs Topics", MQTT_PubTopic, MAX_MQTT_PUB_TOPIC_LEN }, +}; + +#else + +MenuItem myMenuItems [] = {}; + +#endif + +uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; +/////// // End dynamic Credentials /////////// + #else #include @@ -112,6 +183,9 @@ volatile long count = 0; Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET_PIN); BlynkTimer timer; +#include +Ticker led_ticker; + void IRAM_ATTR countPulse() { if ((long)(micros() - last_micros) >= DEBOUNCE_TIME_MICRO_SEC) @@ -195,6 +269,37 @@ void OLED_Display() display.display(); } +void set_led(byte status) +{ + digitalWrite(LED_BUILTIN, status); +} + +void heartBeatPrint(void) +{ + static int num = 1; + + if (Blynk.connected()) + { + set_led(HIGH); + led_ticker.once_ms(111, set_led, (byte) LOW); + Serial.print("B"); + } + else + { + Serial.print("F"); + } + + if (num == 80) + { + Serial.println(); + num = 1; + } + else if (num++ % 10 == 0) + { + Serial.print(" "); + } +} + #define USE_SIMULATION false void checkStatus() @@ -230,6 +335,9 @@ void checkStatus() #else count = 0; #endif + + // report Blynk connection + heartBeatPrint(); } } @@ -260,6 +368,9 @@ void setup() USE_BT = false; Serial.println(F("GPIO14 HIGH, Use WiFi")); #if USE_BLYNK_WM + // Set config portal channel, defalut = 1. Use 0 => random channel from 1-13 to avoid conflict + Blynk_WF.setConfigPortalChannel(0); + Blynk_WF.begin(BT_Device_Name); #else //Blynk_WF.begin(auth, ssid, pass); @@ -272,7 +383,7 @@ void setup() Serial.println(F("GPIO14 LOW, Use BT")); Blynk_BT.setDeviceName(BT_Device_Name); #if USE_BLYNK_WM - if (Blynk_WF.getBlynkBTToken() == String("nothing")) + if (Blynk_WF.getBlynkBTToken() == NO_CONFIG) //String("blank")) { Serial.println(F("No valid stored BT auth. Have to run WiFi then enter config portal")); USE_BT = false; @@ -295,6 +406,18 @@ void setup() timer.setInterval(5000L, sendDatatoBlynk); } +#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS) +void displayCredentials(void) +{ + Serial.println("\nYour stored Credentials :"); + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata); + } +} +#endif + void loop() { #if BLYNK_USE_BT_ONLY @@ -308,4 +431,25 @@ void loop() 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++) + { + if (!strlen(myMenuItems[i].pdata)) + { + break; + } + + if ( i == (NUM_MENU_ITEMS - 1) ) + { + displayedCredentials = true; + displayCredentials(); + } + } + } +#endif } 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 a630422..e1be180 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 @@ -6,7 +6,7 @@ Forked from Blynk library v0.6.1 https://github.com/blynkkk/blynk-library/releases Built by Khoi Hoang https://github.com/khoih-prog/BlynkGSM_ESPManager Licensed under MIT license - Version: 1.0.4 + Version: 1.0.5 Based on orignal code by Crosswalkersam (https://community.blynk.cc/u/Crosswalkersam) posted in https://community.blynk.cc/t/select-connection-type-via-switch/43176 @@ -20,7 +20,20 @@ 1.0.2 K Hoang 04/02/2020 Add Blynk WiFiManager support similar to Blynk_WM library 1.0.3 K Hoang 24/02/2020 Add checksum, clearConfigData() 1.0.4 K Hoang 14/03/2020 Enhance GUI. Reduce code size. + 1.0.5 K Hoang 18/04/2020 MultiWiFi/Blynk. Dynamic custom parameters. SSID password maxlen is 63 now. + Permit special chars # and % in input data. *****************************************************************************************************************************/ +/**************************************************************************************************************************** + 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) + *****************************************************************************************************************************/ #ifndef ESP32 #error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting. @@ -66,11 +79,69 @@ #if USE_BLYNK_WM #warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP) #include + +#define USE_DYNAMIC_PARAMETERS true + +/////////////// Start dynamic Credentials /////////////// + +//Defined in +/************************************** + #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 + +#define MAX_MQTT_SERVER_LEN 34 +char MQTT_Server [MAX_MQTT_SERVER_LEN + 1] = ""; + +#define MAX_MQTT_PORT_LEN 6 +char MQTT_Port [MAX_MQTT_PORT_LEN + 1] = ""; + +#define MAX_MQTT_USERNAME_LEN 34 +char MQTT_UserName [MAX_MQTT_USERNAME_LEN + 1] = ""; + +#define MAX_MQTT_PW_LEN 34 +char MQTT_PW [MAX_MQTT_PW_LEN + 1] = ""; + +#define MAX_MQTT_SUBS_TOPIC_LEN 34 +char MQTT_SubsTopic [MAX_MQTT_SUBS_TOPIC_LEN + 1] = ""; + +#define MAX_MQTT_PUB_TOPIC_LEN 34 +char MQTT_PubTopic [MAX_MQTT_PUB_TOPIC_LEN + 1] = ""; + +MenuItem myMenuItems [] = +{ + { "mqtt", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, + { "mqpt", "Port", MQTT_Port, MAX_MQTT_PORT_LEN }, + { "user", "MQTT UserName", MQTT_UserName, MAX_MQTT_USERNAME_LEN }, + { "mqpw", "MQTT PWD", MQTT_PW, MAX_MQTT_PW_LEN }, + { "subs", "Subs Topics", MQTT_SubsTopic, MAX_MQTT_SUBS_TOPIC_LEN }, + { "pubs", "Pubs Topics", MQTT_PubTopic, MAX_MQTT_PUB_TOPIC_LEN }, +}; + +#else + +MenuItem myMenuItems [] = {}; + +#endif + +uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; +/////// // End dynamic Credentials /////////// + #else #include -String cloudBlynkServer = "account.duckdns.org"; -//String cloudBlynkServer = "192.168.2.110"; +//String cloudBlynkServer = "account.duckdns.org"; +String cloudBlynkServer = "192.168.2.110"; #define BLYNK_SERVER_HARDWARE_PORT 8080 char ssid[] = "SSID"; @@ -84,6 +155,7 @@ char BT_auth[] = "BT_token"; // BLE Blynk token, not shared between BT and WiFi char BLE_auth[] = "BLE_token"; + #endif #define WIFI_BT_SELECTION_PIN 14 //Pin D14 mapped to pin GPIO14/HSPI_SCK/ADC16/TOUCH6/TMS of ESP32 @@ -118,6 +190,9 @@ volatile long count = 0; Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET_PIN); BlynkTimer timer; +#include +Ticker led_ticker; + void IRAM_ATTR countPulse() { if ((long)(micros() - last_micros) >= DEBOUNCE_TIME_MICRO_SEC) @@ -201,6 +276,37 @@ void OLED_Display() display.display(); } +void set_led(byte status) +{ + digitalWrite(LED_BUILTIN, status); +} + +void heartBeatPrint(void) +{ + static int num = 1; + + if (Blynk.connected()) + { + set_led(HIGH); + led_ticker.once_ms(111, set_led, (byte) LOW); + Serial.print("B"); + } + else + { + Serial.print("F"); + } + + if (num == 80) + { + Serial.println(); + num = 1; + } + else if (num++ % 10 == 0) + { + Serial.print(" "); + } +} + #define USE_SIMULATION true void checkStatus() @@ -236,6 +342,9 @@ void checkStatus() #else count = 0; #endif + + // report Blynk connection + heartBeatPrint(); } } @@ -262,6 +371,9 @@ void setup() Serial.println(F("Use WiFi to connect Blynk")); #if USE_BLYNK_WM + // Set config portal channel, defalut = 1. Use 0 => random channel from 1-13 to avoid conflict + Blynk_WF.setConfigPortalChannel(0); + Blynk_WF.begin("GeigerCounter-WiFi"); #else //Blynk_WF.begin(WiFi_auth, ssid, pass); @@ -277,7 +389,7 @@ void setup() Serial.print(F("BLE_auth = ")); Serial.println(BLE_auth); - if (BLE_auth == String("nothing")) + if (BLE_auth == NO_CONFIG) //String("blank")) { Serial.println(F("No valid stored BLE auth. Have to run WiFi then enter config portal")); valid_BT_BLE_token = false; @@ -301,7 +413,7 @@ void setup() Serial.print(F("BT_auth = ")); Serial.println(BT_auth); - if (BT_auth == String("nothing")) + if (BT_auth == NO_CONFIG) //String("blank")) { Serial.println(F("No valid stored BT auth. Have to run WiFi then enter config portal")); valid_BT_BLE_token = false; @@ -321,6 +433,18 @@ void setup() timer.setInterval(5000L, sendDatatoBlynk); } +#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS) +void displayCredentials(void) +{ + Serial.println("\nYour stored Credentials :"); + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata); + } +} +#endif + void loop() { if (valid_BT_BLE_token) @@ -335,4 +459,25 @@ void loop() Blynk_WF.run(); 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++) + { + if (!strlen(myMenuItems[i].pdata)) + { + break; + } + + if ( i == (NUM_MENU_ITEMS - 1) ) + { + displayedCredentials = true; + displayCredentials(); + } + } + } +#endif } 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 5f85586..5ca072c 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 @@ -6,7 +6,7 @@ Forked from Blynk library v0.6.1 https://github.com/blynkkk/blynk-library/releases Built by Khoi Hoang https://github.com/khoih-prog/BlynkGSM_ESPManager Licensed under MIT license - Version: 1.0.4 + Version: 1.0.5 Based on orignal code by Crosswalkersam (https://community.blynk.cc/u/Crosswalkersam) posted in https://community.blynk.cc/t/select-connection-type-via-switch/43176 @@ -20,7 +20,20 @@ 1.0.2 K Hoang 04/02/2020 Add Blynk WiFiManager support similar to Blynk_WM library 1.0.3 K Hoang 24/02/2020 Add checksum, clearConfigData() 1.0.4 K Hoang 14/03/2020 Enhance GUI. Reduce code size. + 1.0.5 K Hoang 18/04/2020 MultiWiFi/Blynk. Dynamic custom parameters. SSID password maxlen is 63 now. + Permit special chars # and % in input data. *****************************************************************************************************************************/ +/**************************************************************************************************************************** + 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) + *****************************************************************************************************************************/ #ifndef ESP32 #error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting. @@ -36,14 +49,14 @@ #define USE_BLYNK_WM true //#define USE_BLYNK_WM false -#define USE_SPIFFS true -//#define USE_SPIFFS false +//#define USE_SPIFFS true +#define USE_SPIFFS false #if (!USE_SPIFFS) // EEPROM_SIZE must be <= 2048 and >= CONFIG_DATA_SIZE #define EEPROM_SIZE (2 * 1024) // EEPROM_START + CONFIG_DATA_SIZE must be <= EEPROM_SIZE -#define EEPROM_START 256 +#define EEPROM_START 0 #endif // Force some params in Blynk, only valid for library version 1.0.1 and later @@ -57,6 +70,64 @@ #if USE_BLYNK_WM #warning Please select 1.3MB+ for APP (Minimal SPIFFS (1.9MB APP, OTA), HugeAPP(3MB APP, NoOTA) or NoOA(2MB APP) #include + +#define USE_DYNAMIC_PARAMETERS true + +/////////////// Start dynamic Credentials /////////////// + +//Defined in +/************************************** + #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 + +#define MAX_MQTT_SERVER_LEN 34 +char MQTT_Server [MAX_MQTT_SERVER_LEN + 1] = ""; + +#define MAX_MQTT_PORT_LEN 6 +char MQTT_Port [MAX_MQTT_PORT_LEN + 1] = ""; + +#define MAX_MQTT_USERNAME_LEN 34 +char MQTT_UserName [MAX_MQTT_USERNAME_LEN + 1] = ""; + +#define MAX_MQTT_PW_LEN 34 +char MQTT_PW [MAX_MQTT_PW_LEN + 1] = ""; + +#define MAX_MQTT_SUBS_TOPIC_LEN 34 +char MQTT_SubsTopic [MAX_MQTT_SUBS_TOPIC_LEN + 1] = ""; + +#define MAX_MQTT_PUB_TOPIC_LEN 34 +char MQTT_PubTopic [MAX_MQTT_PUB_TOPIC_LEN + 1] = ""; + +MenuItem myMenuItems [] = +{ + { "mqtt", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, + { "mqpt", "Port", MQTT_Port, MAX_MQTT_PORT_LEN }, + { "user", "MQTT UserName", MQTT_UserName, MAX_MQTT_USERNAME_LEN }, + { "mqpw", "MQTT PWD", MQTT_PW, MAX_MQTT_PW_LEN }, + { "subs", "Subs Topics", MQTT_SubsTopic, MAX_MQTT_SUBS_TOPIC_LEN }, + { "pubs", "Pubs Topics", MQTT_PubTopic, MAX_MQTT_PUB_TOPIC_LEN }, +}; + +#else + +MenuItem myMenuItems [] = {}; + +#endif + +uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; +/////// // End dynamic Credentials /////////// + #else #include @@ -110,6 +181,9 @@ volatile long count = 0; Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET_PIN); BlynkTimer timer; +#include +Ticker led_ticker; + void IRAM_ATTR countPulse() { if ((long)(micros() - last_micros) >= DEBOUNCE_TIME_MICRO_SEC) @@ -184,6 +258,37 @@ void OLED_Display() display.display(); } +void set_led(byte status) +{ + digitalWrite(LED_BUILTIN, status); +} + +void heartBeatPrint(void) +{ + static int num = 1; + + if (Blynk.connected()) + { + set_led(HIGH); + led_ticker.once_ms(111, set_led, (byte) LOW); + Serial.print("B"); + } + else + { + Serial.print("F"); + } + + if (num == 80) + { + Serial.println(); + num = 1; + } + else if (num++ % 10 == 0) + { + Serial.print(" "); + } +} + #define USE_SIMULATION true void checkStatus() @@ -219,6 +324,9 @@ void checkStatus() #else count = 0; #endif + + // report Blynk connection + heartBeatPrint(); } } @@ -245,6 +353,9 @@ void setup() Serial.println(F("Use WiFi to connect Blynk")); #if USE_BLYNK_WM + // Set config portal channel, defalut = 1. Use 0 => random channel from 1-13 to avoid conflict + Blynk_WF.setConfigPortalChannel(0); + Blynk_WF.begin(BT_Device_Name); #else //Blynk_WF.begin(WiFi_auth, ssid, pass); @@ -259,7 +370,7 @@ void setup() Serial.print(F("BT_auth = ")); Serial.println(BT_auth); - if (BT_auth == String("nothing")) + if (BT_auth == NO_CONFIG) //String("blank")) { Serial.println(F("No valid stored BT auth. Have to run WiFi then enter config portal")); valid_BT_token = false; @@ -277,6 +388,18 @@ void setup() timer.setInterval(5000L, sendDatatoBlynk); } +#if (USE_BLYNK_WM && USE_DYNAMIC_PARAMETERS) +void displayCredentials(void) +{ + Serial.println("\nYour stored Credentials :"); + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata); + } +} +#endif + void loop() { if (valid_BT_token) @@ -285,4 +408,25 @@ void loop() Blynk_WF.run(); 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++) + { + if (!strlen(myMenuItems[i].pdata)) + { + break; + } + + if ( i == (NUM_MENU_ITEMS - 1) ) + { + displayedCredentials = true; + displayCredentials(); + } + } + } +#endif } diff --git a/keywords.txt b/keywords.txt index 4b94cfc..de367b4 100644 --- a/keywords.txt +++ b/keywords.txt @@ -14,6 +14,11 @@ WidgetTable KEYWORD1 BlynkParam KEYWORD1 BlynkParamAllocated KEYWORD1 +MenuItem KEYWORD1 +WiFi_Credentials KEYWORD1 +Blynk_Credentials KEYWORD1 +Blynk_WM_Configuration KEYWORD1 + ####################################### # Methods and Functions (KEYWORD2) ####################################### @@ -40,7 +45,10 @@ startConfigurationMode KEYWORD2 setHostname KEYWORD2 setConfigPortalIP KEYWORD2 setConfigPortal KEYWORD2 +setConfigPortalChannel KEYWORD2 setSTAStaticIPConfig KEYWORD2 +getWiFiSSID KEYWORD2 +getWiFiPW KEYWORD2 getServerName KEYWORD2 getToken KEYWORD2 getBlynkBTToken KEYWORD2 diff --git a/library.json b/library.json index 16cb3e0..9f34290 100644 --- a/library.json +++ b/library.json @@ -1,7 +1,7 @@ { "name": "BlynkESP32_BT_WF", - "version": "1.0.4", - "description": "Build a smartphone app for your project in minutes. Blynk allows creating IoT solutions easily. It supports WiFi, BLE, Bluetooth, Ethernet, GSM, USB, Serial. Works with many boards like ESP8266, ESP32, Arduino UNO, Nano, Due, Mega, Zero, MKR100, Yun, Raspberry Pi, Particle, Energia, ARM mbed, Intel Edison/Galileo/Joule, BBC micro:bit, DFRobot, RedBearLab, Microduino, LinkIt ONE ...", + "version": "1.0.5", + "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 SPIFFS or EEPROM.", "keywords": "sensors, control, device, smartphone, mobile, app, web, cloud, communication, protocol, iot, m2m, wifi, ble, bluetooth, ethernet, usb, serial, gsm, gprs, 3g, data, esp8266, http", "authors": { @@ -14,7 +14,7 @@ "type": "git", "url": "//https://github.com/khoih-prog/BlynkESP32_BT_WF" }, - "homepage": "http://blynk.cc", + "homepage": "https://github.com/khoih-prog/BlynkESP32_BT_WF", "export": { "exclude": [ "linux", diff --git a/library.properties b/library.properties index 3857b38..3f73835 100644 --- a/library.properties +++ b/library.properties @@ -1,10 +1,10 @@ name=BlynkESP32_BT_WF -version=1.0.4 +version=1.0.5 author=Khoi Hoang license=MIT maintainer=Khoi Hoang sentence=Enable inclusion of both ESP32 Blynk BT/BLE and WiFi libraries. Then select one at reboot or run both. Eliminate hardcoding your Wifi and Blynk credentials and configuration data saved in either SPIFFS or EEPROM. -paragraph=Library for inclusion of both ESP32 Blynk BT/BLE and WiFi libraries. Then select one at reboot or run both. Eliminate hardcoding your Wifi and Blynk credentials and configuration data saved in either SPIFFS or EEPROM. +paragraph=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 SPIFFS or EEPROM. category=Communication url=https://github.com/khoih-prog/BlynkESP32_BT_WF architectures=esp32 diff --git a/pics/ConfigPortal.png b/pics/ConfigPortal.png index 50096a0..72d60b2 100644 Binary files a/pics/ConfigPortal.png and b/pics/ConfigPortal.png differ diff --git a/pics/Main.png b/pics/Main.png index aa0f471..cd1e510 100644 Binary files a/pics/Main.png and b/pics/Main.png differ diff --git a/src/BlynkSimpleEsp32_BLE_WF.h b/src/BlynkSimpleEsp32_BLE_WF.h index c472b16..554b875 100644 --- a/src/BlynkSimpleEsp32_BLE_WF.h +++ b/src/BlynkSimpleEsp32_BLE_WF.h @@ -6,7 +6,7 @@ Forked from Blynk library v0.6.1 https://github.com/blynkkk/blynk-library/releases Built by Khoi Hoang https://github.com/khoih-prog/BlynkGSM_ESPManager Licensed under MIT license - Version: 1.0.4 + Version: 1.0.5 Original Blynk Library author: @file BlynkSimpleESP32.h @@ -23,6 +23,8 @@ 1.0.2 K Hoang 04/02/2020 Add Blynk WiFiManager support similar to Blynk_WM library 1.0.3 K Hoang 24/02/2020 Add checksum, clearConfigData() 1.0.4 K Hoang 14/03/2020 Enhance GUI. Reduce code size. + 1.0.5 K Hoang 18/04/2020 MultiWiFi/Blynk. Dynamic custom parameters. SSID password maxlen is 63 now. + Permit special chars # and % in input data. *****************************************************************************************************************************/ #ifndef BlynkSimpleEsp32_BLE_WF_h diff --git a/src/BlynkSimpleEsp32_BT_WF.h b/src/BlynkSimpleEsp32_BT_WF.h index f2d890a..80bde2b 100644 --- a/src/BlynkSimpleEsp32_BT_WF.h +++ b/src/BlynkSimpleEsp32_BT_WF.h @@ -6,7 +6,7 @@ Forked from Blynk library v0.6.1 https://github.com/blynkkk/blynk-library/releases Built by Khoi Hoang https://github.com/khoih-prog/BlynkGSM_ESPManager Licensed under MIT license - Version: 1.0.4 + Version: 1.0.5 Original Blynk Library author: @file BlynkSimpleESP32.h @@ -23,6 +23,8 @@ 1.0.2 K Hoang 04/02/2020 Add Blynk WiFiManager support similar to Blynk_WM library 1.0.3 K Hoang 24/02/2020 Add checksum, clearConfigData() 1.0.4 K Hoang 14/03/2020 Enhance GUI. Reduce code size. + 1.0.5 K Hoang 18/04/2020 MultiWiFi/Blynk. Dynamic custom parameters. SSID password maxlen is 63 now. + Permit special chars # and % in input data. *****************************************************************************************************************************/ #ifndef BlynkSimpleEsp32_BT_WF_h diff --git a/src/BlynkSimpleEsp32_WF.h b/src/BlynkSimpleEsp32_WF.h index a91444e..46d7d5d 100644 --- a/src/BlynkSimpleEsp32_WF.h +++ b/src/BlynkSimpleEsp32_WF.h @@ -6,7 +6,7 @@ Forked from Blynk library v0.6.1 https://github.com/blynkkk/blynk-library/releases Built by Khoi Hoang https://github.com/khoih-prog/BlynkGSM_ESPManager Licensed under MIT license - Version: 1.0.4 + Version: 1.0.5 Original Blynk Library author: @file BlynkSimpleESP32.h @@ -23,6 +23,8 @@ 1.0.2 K Hoang 04/02/2020 Add Blynk WiFiManager support similar to Blynk_WM library 1.0.3 K Hoang 24/02/2020 Add checksum, clearConfigData() 1.0.4 K Hoang 14/03/2020 Enhance GUI. Reduce code size. + 1.0.5 K Hoang 18/04/2020 MultiWiFi/Blynk. Dynamic custom parameters. SSID password maxlen is 63 now. + Permit special chars # and % in input data. *****************************************************************************************************************************/ #ifndef BlynkSimpleEsp32_WF_h diff --git a/src/BlynkSimpleEsp32_WFM.h b/src/BlynkSimpleEsp32_WFM.h index c9a7be5..eeddae0 100644 --- a/src/BlynkSimpleEsp32_WFM.h +++ b/src/BlynkSimpleEsp32_WFM.h @@ -6,7 +6,7 @@ Forked from Blynk library v0.6.1 https://github.com/blynkkk/blynk-library/releases Built by Khoi Hoang https://github.com/khoih-prog/BlynkGSM_ESPManager Licensed under MIT license - Version: 1.0.4 + Version: 1.0.5 Original Blynk Library author: @file BlynkSimpleESP32.h @@ -23,6 +23,8 @@ 1.0.2 K Hoang 04/02/2020 Add Blynk WiFiManager support similar to Blynk_WM library 1.0.3 K Hoang 24/02/2020 Add checksum, clearConfigData() 1.0.4 K Hoang 14/03/2020 Enhance GUI. Reduce code size. + 1.0.5 K Hoang 18/04/2020 MultiWiFi/Blynk. Dynamic custom parameters. SSID password maxlen is 63 now. + Permit special chars # and % in input data. *****************************************************************************************************************************/ #ifndef BlynkSimpleEsp32_WFM_h @@ -40,7 +42,9 @@ #include #include #include + #include +#include #include @@ -55,43 +59,103 @@ #include #define ESP_getChipId() ((uint32_t)ESP.getEfuseMac()) -// Configurable items besides fixed Header -#define NUM_CONFIGURABLE_ITEMS 8 +//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; +// + +///NEW +extern uint16_t NUM_MENU_ITEMS; +extern MenuItem myMenuItems []; + +#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 BLYNK_SERVER_MAX_LEN 32 +#define BLYNK_TOKEN_MAX_LEN 36 + +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 [16]; - char wifi_ssid [32]; - char wifi_pw [32]; - char blynk_server [32]; + WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; + Blynk_Credentials Blynk_Creds [NUM_BLYNK_CREDENTIALS]; int blynk_port; - char blynk_token [36]; char blynk_bt_tk [36]; - char blynk_ble_tk [36]; + char blynk_ble_tk [36]; char board_name [24]; int checkSum; -} Blynk_WF_Configuration; +} 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); -// Currently CONFIG_DATA_SIZE = 252 -uint16_t CONFIG_DATA_SIZE = sizeof(Blynk_WF_Configuration); +//From v1.0.5, Permit special chars such as # and % -#define root_html_template "\ -Blynk_Esp32_BT_BLE_WF
\ -
\ -
\ -
\ -
\ -
" +
\ +
\ +
\ +
\ +
\ +
\ +
\ +
\ +
\ +
\ +
\ +
"; +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*/ = ""; +const char BLYNK_WM_HTML_SCRIPT[] /*PROGMEM*/ = ""; +const char BLYNK_WM_HTML_END[] /*PROGMEM*/ = ""; +/// #define BLYNK_SERVER_HARDWARE_PORT 8080 #define BLYNK_BOARD_TYPE "ESP32_WFM" -#define NO_CONFIG "nothing" +#define NO_CONFIG "blank" class BlynkWifi : public BlynkProtocol @@ -110,21 +174,28 @@ class BlynkWifi // New from Blynk_WM v1.0.5 if (static_IP != IPAddress(0, 0, 0, 0)) { - BLYNK_LOG1(BLYNK_F("Use statIP")); + BLYNK_LOG1(BLYNK_F("UseStatIP")); WiFi.config(static_IP, static_GW, static_SN, static_DNS1, static_DNS2); } + setHostname(); - if (pass && strlen(pass)) { - WiFi.begin(ssid, pass); - } else { - WiFi.begin(ssid); + if (WiFi.status() != WL_CONNECTED) + { + if (pass && strlen(pass)) + { + WiFi.begin(ssid, pass); + } else + { + WiFi.begin(ssid); + } } - while (WiFi.status() != WL_CONNECTED) { + while (WiFi.status() != WL_CONNECTED) + { BlynkDelay(500); } - BLYNK_LOG1(BLYNK_F("Con2WiFi")); - + + BLYNK_LOG1(BLYNK_F("Conn2WiFi")); displayWiFiData(); } @@ -170,13 +241,17 @@ class BlynkWifi #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 + void begin(const char *iHostname = "") { #define TIMEOUT_CONNECT_WIFI 30000 //Turn OFF pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); + digitalWrite(LED_BUILTIN, LED_OFF); WiFi.mode(WIFI_STA); @@ -199,26 +274,28 @@ class BlynkWifi if (getConfigData()) { hadConfigData = true; + + for (int 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 (connectToWifi(TIMEOUT_CONNECT_WIFI)) + if (connectMultiWiFi()) { BLYNK_LOG1(BLYNK_F("b:WOK.TryB")); int i = 0; - while ( (i++ < 10) && !this->connect() ) + while ( (i++ < 10) && !connectMultiBlynk() ) { } - if (this->connected()) + if (connected()) { BLYNK_LOG1(BLYNK_F("b:WBOK")); } else { - BLYNK_LOG1(BLYNK_F("b:WOK,Bno")); + BLYNK_LOG1(BLYNK_F("b:WOK,BNot")); // failed to connect to Blynk server, will start configuration mode startConfigurationMode(); } @@ -313,14 +390,15 @@ class BlynkWifi if ( WiFi.status() != WL_CONNECTED ) { BLYNK_LOG1(BLYNK_F("r:Wlost.ReconW+B")); - if (connectToWifi(TIMEOUT_RECONNECT_WIFI)) + + if (connectMultiWiFi()) { // turn the LED_BUILTIN OFF to tell us we exit configuration mode. - digitalWrite(LED_BUILTIN, LOW); + digitalWrite(LED_BUILTIN, LED_OFF); BLYNK_LOG1(BLYNK_F("r:WOK.TryB")); - if (connect()) + if (connectMultiBlynk()) { BLYNK_LOG1(BLYNK_F("r:W+BOK")); } @@ -329,10 +407,11 @@ class BlynkWifi else { BLYNK_LOG1(BLYNK_F("r:Blost.TryB")); - if (connect()) + + if (connectMultiBlynk()) { // turn the LED_BUILTIN OFF to tell us we exit configuration mode. - digitalWrite(LED_BUILTIN, LOW); + digitalWrite(LED_BUILTIN, LED_OFF); BLYNK_LOG1(BLYNK_F("r:BOK")); } @@ -347,10 +426,10 @@ class BlynkWifi 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, LOW); + digitalWrite(LED_BUILTIN, LED_OFF); } - if (connected()) + //if (connected()) { Base::run(); } @@ -377,6 +456,22 @@ class BlynkWifi portal_pass = pass; } +#define MIN_WIFI_CHANNEL 1 +#define MAX_WIFI_CHANNEL 13 + + 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)) @@ -398,20 +493,48 @@ class BlynkWifi static_DNS2 = dns_address_2; } - String getServerName() + 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_server)); + return (String(BlynkESP32_WM_config.Blynk_Creds[index].blynk_server)); } - String getToken() + String getToken(uint8_t index) { + if (index >= NUM_BLYNK_CREDENTIALS) + return String(""); + if (!hadConfigData) getConfigData(); - return (String(BlynkESP32_WM_config.blynk_token)); + return (String(BlynkESP32_WM_config.Blynk_Creds[index].blynk_token)); } String getBlynkBTToken(void) @@ -447,14 +570,14 @@ class BlynkWifi } - Blynk_WF_Configuration* getFullConfigData(Blynk_WF_Configuration *configData) + Blynk_WM_Configuration* getFullConfigData(Blynk_WM_Configuration *configData) { if (!hadConfigData) getConfigData(); // Check if NULL pointer if (configData) - memcpy(configData, &BlynkESP32_WM_config, sizeof(Blynk_WF_Configuration)); + memcpy(configData, &BlynkESP32_WM_config, sizeof(Blynk_WM_Configuration)); return (configData); } @@ -468,11 +591,18 @@ class BlynkWifi private: WebServer *server; bool configuration_mode = false; + + WiFiMulti wifiMulti; unsigned long configTimeout; bool hadConfigData = false; + + // default to channel 1 + int WiFiAPChannel = 1; + + uint16_t totalDataSize = 0; - Blynk_WF_Configuration BlynkESP32_WM_config; + Blynk_WM_Configuration BlynkESP32_WM_config; // For Config Portal, from Blynk_WM v1.0.5 IPAddress portal_apIP = IPAddress(192, 168, 4, 1); @@ -515,14 +645,21 @@ class BlynkWifi void displayConfigData(void) { - BLYNK_LOG6(BLYNK_F("Hdr="), BlynkESP32_WM_config.header, BLYNK_F(",SSID="), BlynkESP32_WM_config.wifi_ssid, - BLYNK_F(",PW="), BlynkESP32_WM_config.wifi_pw); - BLYNK_LOG6(BLYNK_F("Server="), BlynkESP32_WM_config.blynk_server, BLYNK_F(",Port="), BlynkESP32_WM_config.blynk_port, - BLYNK_F(",Token="), BlynkESP32_WM_config.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("BrdName="), BlynkESP32_WM_config.board_name); + 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); } - + void displayWiFiData(void) { BLYNK_LOG6(BLYNK_F("IP="), WiFi.localIP().toString(), BLYNK_F(",GW="), WiFi.gatewayIP().toString(), @@ -543,9 +680,145 @@ class BlynkWifi #if USE_SPIFFS -#define CONFIG_FILENAME BLYNK_F("/wfm_config.dat") -#define CONFIG_FILENAME_BACKUP BLYNK_F("/wfm_config.bak") +#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") + + bool loadCredentials(void) + { + int checkSum = 0; + int readCheckSum; + totalDataSize = sizeof(BlynkESP32_WM_config) + sizeof(readCheckSum); + + File file = SPIFFS.open(CREDENTIALS_FILENAME, "r"); + BLYNK_LOG1(BLYNK_F("LoadCredFile ")); + + if (!file) + { + BLYNK_LOG1(BLYNK_F("failed")); + + // Trying open redundant config file + file = SPIFFS.open(CREDENTIALS_FILENAME_BACKUP, "r"); + BLYNK_LOG1(BLYNK_F("LoadBkUpCredFile ")); + + if (!file) + { + BLYNK_LOG1(BLYNK_F("failed")); + return false; + } + } + + for (int 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); + + 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 saveCredentials(void) + { + int checkSum = 0; + + File file = SPIFFS.open(CREDENTIALS_FILENAME, "w"); + BLYNK_LOG1(BLYNK_F("SaveCredFile ")); + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + char* _pointer = myMenuItems[i].pdata; + + //BLYNK_LOG4(F("pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); + + 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("CrCCSum=0x"), String(checkSum, HEX)); + + // Trying open redundant Auth file + file = SPIFFS.open(CREDENTIALS_FILENAME_BACKUP, "w"); + BLYNK_LOG1(BLYNK_F("SaveBkUpCredFile ")); + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + char* _pointer = myMenuItems[i].pdata; + + BLYNK_LOG4(F("pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); + + 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")); + } + } + void loadConfigData(void) { File file = SPIFFS.open(CONFIG_FILENAME, "r"); @@ -578,6 +851,7 @@ class BlynkWifi int calChecksum = calcChecksum(); BlynkESP32_WM_config.checkSum = calChecksum; + BLYNK_LOG2(BLYNK_F("SaveCfgFile,CSum=0x"), String(calChecksum, HEX)); if (file) @@ -605,11 +879,17 @@ class BlynkWifi { BLYNK_LOG1(BLYNK_F("failed")); } + + saveCredentials(); } // Return false if init new EEPROM or SPIFFS. No more need trying to connect. Go directly to config mode bool getConfigData() { + bool credDataValid; + + hadConfigData = false; + if (!SPIFFS.begin()) { BLYNK_LOG1(BLYNK_F("SPIFFS failed! Use EEPROM.")); @@ -628,23 +908,41 @@ class BlynkWifi BLYNK_F(",RCSum=0x"), String(BlynkESP32_WM_config.checkSum, HEX)); //displayConfigData(); + credDataValid = loadCredentials(); if ( (strncmp(BlynkESP32_WM_config.header, BLYNK_BOARD_TYPE, strlen(BLYNK_BOARD_TYPE)) != 0) || - (calChecksum != BlynkESP32_WM_config.checkSum) ) + (calChecksum != BlynkESP32_WM_config.checkSum) || !credDataValid ) { memset(&BlynkESP32_WM_config, 0, sizeof(BlynkESP32_WM_config)); + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + // Actual size of pdata is [maxlen + 1] + memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); + } - BLYNK_LOG2(BLYNK_F("InitCfgFile,sz="), sizeof(BlynkESP32_WM_config)); + BLYNK_LOG4(BLYNK_F("InitCfgFile,sz="), sizeof(BlynkESP32_WM_config), BLYNK_F(", TotalDataSz="), totalDataSize); + // doesn't have any configuration strcpy(BlynkESP32_WM_config.header, BLYNK_BOARD_TYPE); - strcpy(BlynkESP32_WM_config.wifi_ssid, NO_CONFIG); - strcpy(BlynkESP32_WM_config.wifi_pw, NO_CONFIG); - strcpy(BlynkESP32_WM_config.blynk_server, NO_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_token, NO_CONFIG); 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); + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + strncpy(myMenuItems[i].pdata, NO_CONFIG, myMenuItems[i].maxlen); + } + // Don't need BlynkESP32_WM_config.checkSum = 0; @@ -652,12 +950,16 @@ class BlynkWifi return false; } - else if ( !strncmp(BlynkESP32_WM_config.wifi_ssid, NO_CONFIG, strlen(NO_CONFIG)) || - !strncmp(BlynkESP32_WM_config.wifi_pw, NO_CONFIG, strlen(NO_CONFIG) ) || - !strncmp(BlynkESP32_WM_config.blynk_server, NO_CONFIG, strlen(NO_CONFIG) ) || - !strncmp(BlynkESP32_WM_config.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) ) ) + 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; @@ -696,9 +998,74 @@ class BlynkWifi #endif #endif + bool EEPROM_getCredentials(void) + { + int readCheckSum; + int checkSum = 0; + uint16_t offset = EEPROM_START + sizeof(BlynkESP32_WM_config); + + totalDataSize = sizeof(BlynkESP32_WM_config) + sizeof(readCheckSum); + + for (int 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; + } + } + + 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_putCredentials(void) + { + int checkSum = 0; + uint16_t offset = EEPROM_START + sizeof(BlynkESP32_WM_config); + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + char* _pointer = myMenuItems[i].pdata; + + BLYNK_LOG4(F("pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); + + 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("CrCCSum=0x"), String(checkSum, HEX)); + } + // Return false if init new EEPROM or SPIFFS. No more need trying to connect. Go directly to config mode bool getConfigData() { + bool credDataValid; + + hadConfigData = false; + EEPROM.begin(EEPROM_SIZE); EEPROM.get(EEPROM_START, BlynkESP32_WM_config); @@ -706,37 +1073,60 @@ class BlynkWifi BLYNK_LOG4(BLYNK_F("CCSum=0x"), String(calChecksum, HEX), BLYNK_F(",RCSum=0x"), String(BlynkESP32_WM_config.checkSum, HEX)); + + credDataValid = EEPROM_getCredentials(); if ( (strncmp(BlynkESP32_WM_config.header, BLYNK_BOARD_TYPE, strlen(BLYNK_BOARD_TYPE)) != 0) || - (calChecksum != BlynkESP32_WM_config.checkSum) ) + (calChecksum != BlynkESP32_WM_config.checkSum) || !credDataValid ) { memset(&BlynkESP32_WM_config, 0, sizeof(BlynkESP32_WM_config)); + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + // Actual size of pdata is [maxlen + 1] + memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); + } + + // Including Credentials CSum + BLYNK_LOG4(F("InitEEPROM,sz="), EEPROM_SIZE, F(",Datasz="), totalDataSize); - BLYNK_LOG2(BLYNK_F("InitEEPROM,sz="), EEPROM_SIZE /*EEPROM.length()*/); // doesn't have any configuration strcpy(BlynkESP32_WM_config.header, BLYNK_BOARD_TYPE); - strcpy(BlynkESP32_WM_config.wifi_ssid, NO_CONFIG); - strcpy(BlynkESP32_WM_config.wifi_pw, NO_CONFIG); - strcpy(BlynkESP32_WM_config.blynk_server, NO_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_token, NO_CONFIG); 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); + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + strncpy(myMenuItems[i].pdata, NO_CONFIG, myMenuItems[i].maxlen); + } + // Don't need BlynkESP32_WM_config.checkSum = 0; EEPROM.put(EEPROM_START, BlynkESP32_WM_config); + EEPROM_putCredentials(); EEPROM.commit(); return false; } - else if ( !strncmp(BlynkESP32_WM_config.wifi_ssid, NO_CONFIG, strlen(NO_CONFIG)) || - !strncmp(BlynkESP32_WM_config.wifi_pw, NO_CONFIG, strlen(NO_CONFIG) ) || - !strncmp(BlynkESP32_WM_config.blynk_server, NO_CONFIG, strlen(NO_CONFIG) ) || - !strncmp(BlynkESP32_WM_config.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) ) ) + 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; @@ -756,56 +1146,109 @@ class BlynkWifi BLYNK_F(",CSum=0x"), String(calChecksum, HEX)); EEPROM.put(EEPROM_START, BlynkESP32_WM_config); + EEPROM_putCredentials(); EEPROM.commit(); } #endif - boolean connectToWifi(int timeout) + bool connectMultiBlynk(void) + { +#define BLYNK_CONNECT_TIMEOUT_MS 5000L + + for (int i = 0; i < NUM_BLYNK_CREDENTIALS; i++) + { + config(BlynkESP32_WM_config.Blynk_Creds[i].blynk_token, + BlynkESP32_WM_config.Blynk_Creds[i].blynk_server, BLYNK_SERVER_HARDWARE_PORT); + + if (connect(BLYNK_CONNECT_TIMEOUT_MS) ) + { + BLYNK_LOG4(BLYNK_F("Conn2BlynkServer="), 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) { - int sleep_time = 250; + // 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); + + //New v1.0.11 setHostname(); + + int i = 0; + status = wifiMulti.run(); + delay(WIFI_MULTI_CONNECT_WAITING_MS); - // New from Blynk_WM v1.0.5 - if (static_IP != IPAddress(0, 0, 0, 0)) + while ( ( i++ < 10 ) && ( status != WL_CONNECTED ) ) { - BLYNK_LOG1(BLYNK_F("Use statIP")); - WiFi.config(static_IP, static_GW, static_SN, static_DNS1, static_DNS2); - } + status = wifiMulti.run(); - BLYNK_LOG1(BLYNK_F("con2WF:start")); + if ( status == WL_CONNECTED ) + break; + else + delay(WIFI_MULTI_CONNECT_WAITING_MS); + } - if (BlynkESP32_WM_config.wifi_pw && strlen(BlynkESP32_WM_config.wifi_pw)) + if ( status == WL_CONNECTED ) { - WiFi.begin(BlynkESP32_WM_config.wifi_ssid, BlynkESP32_WM_config.wifi_pw); + 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="), WiFi.localIP() ); } else - { - WiFi.begin(BlynkESP32_WM_config.wifi_ssid); - } + BLYNK_LOG1(BLYNK_F("WiFi not connected")); - while (WiFi.status() != WL_CONNECTED && 0 < timeout) + return status; + } + + // NEW + void createHTML(String &root_html_template) + { + String pitem; + + root_html_template = String(BLYNK_WM_HTML_HEAD) + BLYNK_WM_FLDSET_START; + + for (int i = 0; i < NUM_MENU_ITEMS; i++) { - delay(sleep_time); - timeout -= sleep_time; - } + pitem = String(BLYNK_WM_HTML_PARAM); - if (WiFi.status() == WL_CONNECTED) - { - BLYNK_LOG1(BLYNK_F("con2WF:conOK")); - displayWiFiData(); + pitem.replace("{b}", myMenuItems[i].displayName); + pitem.replace("{v}", myMenuItems[i].id); + pitem.replace("{i}", myMenuItems[i].id); + + root_html_template += pitem; } - else + + root_html_template += String(BLYNK_WM_FLDSET_END) + BLYNK_WM_HTML_BUTTON + BLYNK_WM_HTML_SCRIPT; + + for (int i = 0; i < NUM_MENU_ITEMS; i++) { - BLYNK_LOG1(BLYNK_F("con2WF:conFailed")); + pitem = String(BLYNK_WM_HTML_SCRIPT_ITEM); + + pitem.replace("{d}", myMenuItems[i].id); + + root_html_template += pitem; } - - return WiFi.status() == WL_CONNECTED; + + root_html_template += String(BLYNK_WM_HTML_SCRIPT_END) + BLYNK_WM_HTML_END; + + return; } - - + //// + void handleRequest() { if (server) @@ -817,21 +1260,32 @@ class BlynkWifi if (key == "" && value == "") { - String result = root_html_template; + String result; + createHTML(result); BLYNK_LOG1(BLYNK_F("h:repl")); // Reset configTimeout to stay here until finished. configTimeout = 0; - - result.replace("[[id]]", BlynkESP32_WM_config.wifi_ssid); - result.replace("[[pw]]", BlynkESP32_WM_config.wifi_pw); - result.replace("[[sv]]", BlynkESP32_WM_config.blynk_server); - result.replace("[[pt]]", String(BlynkESP32_WM_config.blynk_port)); - result.replace("[[tk]]", BlynkESP32_WM_config.blynk_token); - result.replace("[[tk1]]", BlynkESP32_WM_config.blynk_bt_tk); - result.replace("[[tk2]]", BlynkESP32_WM_config.blynk_ble_tk); - result.replace("[[nm]]", BlynkESP32_WM_config.board_name); + + 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); + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + String toChange = String("[[") + myMenuItems[i].id + "]]"; + result.replace(toChange, myMenuItems[i].pdata); + } server->send(200, "text/html", result); @@ -847,42 +1301,73 @@ class BlynkWifi if (key == "id") { number_items_Updated++; - if (strlen(value.c_str()) < sizeof(BlynkESP32_WM_config.wifi_ssid) - 1) - strcpy(BlynkESP32_WM_config.wifi_ssid, value.c_str()); + 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_ssid, value.c_str(), sizeof(BlynkESP32_WM_config.wifi_ssid) - 1); + 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 == "pw") { number_items_Updated++; - if (strlen(value.c_str()) < sizeof(BlynkESP32_WM_config.wifi_pw) - 1) - strcpy(BlynkESP32_WM_config.wifi_pw, value.c_str()); + 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_pw, value.c_str(), sizeof(BlynkESP32_WM_config.wifi_pw) - 1); + 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 == "sv") + else if (key == "id1") { number_items_Updated++; - if (strlen(value.c_str()) < sizeof(BlynkESP32_WM_config.blynk_server) - 1) - strcpy(BlynkESP32_WM_config.blynk_server, value.c_str()); + 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.blynk_server, value.c_str(), sizeof(BlynkESP32_WM_config.blynk_server) - 1); + 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 == "pt") + else if (key == "pw1") { number_items_Updated++; - BlynkESP32_WM_config.blynk_port = value.toInt(); + 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 == "sv") + { + 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 == "tk") { number_items_Updated++; - if (strlen(value.c_str()) < sizeof(BlynkESP32_WM_config.blynk_token) - 1) - strcpy(BlynkESP32_WM_config.blynk_token, value.c_str()); + 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_token, value.c_str(), sizeof(BlynkESP32_WM_config.blynk_token) - 1); + 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 == "sv1") + { + 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 == "tk1") + { + 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 == "pt") + { + number_items_Updated++; + BlynkESP32_WM_config.blynk_port = value.toInt(); + } + else if (key == "bttk") { number_items_Updated++; if (strlen(value.c_str()) < sizeof(BlynkESP32_WM_config.blynk_bt_tk) - 1) @@ -890,7 +1375,7 @@ class BlynkWifi else strncpy(BlynkESP32_WM_config.blynk_bt_tk, value.c_str(), sizeof(BlynkESP32_WM_config.blynk_bt_tk) - 1); } - else if (key == "tk2") + else if (key == "bltk") { number_items_Updated++; if (strlen(value.c_str()) < sizeof(BlynkESP32_WM_config.blynk_ble_tk) - 1) @@ -907,9 +1392,27 @@ class BlynkWifi strncpy(BlynkESP32_WM_config.board_name, value.c_str(), sizeof(BlynkESP32_WM_config.board_name) - 1); } + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + if (key == myMenuItems[i].id) + { + //BLYNK_LOG4(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); + 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); + } + } + server->send(200, "text/html", "OK"); - if (number_items_Updated == NUM_CONFIGURABLE_ITEMS) + // NEW + if (number_items_Updated == NUM_CONFIGURABLE_ITEMS + NUM_MENU_ITEMS) { #if USE_SPIFFS BLYNK_LOG2(BLYNK_F("h:UpdSPIFFS "), CONFIG_FILENAME); @@ -933,7 +1436,7 @@ class BlynkWifi #define CONFIG_TIMEOUT 60000L // turn the LED_BUILTIN ON to tell us we are in configuration mode. - digitalWrite(LED_BUILTIN, HIGH); + digitalWrite(LED_BUILTIN, LED_ON); if ( (portal_ssid == "") || portal_pass == "" ) { @@ -945,12 +1448,23 @@ class BlynkWifi portal_pass = "MyESP_" + chipID; } - BLYNK_LOG6(BLYNK_F("stConf:SSID="), portal_ssid, BLYNK_F(",PW="), portal_pass, - BLYNK_F(",IP="), portal_apIP.toString()); - WiFi.mode(WIFI_AP); - WiFi.softAP(portal_ssid.c_str(), portal_pass.c_str()); + + // New + delay(100); + + static int channel; + // Use random channel if WiFiAPChannel == 0 + if (WiFiAPChannel == 0) + channel = random(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));