From a88cf896e8ae5b0c12dc67f0d41b1aa309a0e748 Mon Sep 17 00:00:00 2001 From: Khoi Hoang <57012152+khoih-prog@users.noreply.github.com> Date: Sat, 30 Jan 2021 03:04:39 -0500 Subject: [PATCH] v1.2.0 ### Major Releases v1.2.0 1. Fix Config Portal Bug. 2. Add functions to control Config Portal from software or Virtual Switches. Check [How to trigger a Config Portal from code #25](https://github.com/khoih-prog/Blynk_WM/issues/25) 3. Use more efficient [FlashStorage_SAMD v1.1.0](https://github.com/khoih-prog/FlashStorage_SAMD). --- README.md | 1091 ++++++++++++++++------- keywords.txt | 2 + library.json | 16 +- library.properties | 4 +- platformio/platformio.ini | 6 +- src/Adapters/BlynkEthernetENC.h | 5 +- src/Adapters/BlynkEthernet_DUE_WM.h | 530 ++++++++--- src/Adapters/BlynkEthernet_ESP32_WM.h | 710 +++++++++++---- src/Adapters/BlynkEthernet_ESP8266_WM.h | 648 +++++++++++--- src/Adapters/BlynkEthernet_NRF52_WM.h | 544 ++++++++--- src/Adapters/BlynkEthernet_SAMD_WM.h | 609 +++++++++---- src/Adapters/BlynkEthernet_WM.h | 520 ++++++++--- src/Blynk/BlynkDetectDevice.h | 3 +- src/BlynkSimpleEthernet2_WM.h | 5 +- src/BlynkSimpleEthernetENC.h | 5 +- src/BlynkSimpleEthernetENC_SSL.h | 5 +- src/BlynkSimpleEthernetENC_SSL_WM.h | 5 +- src/BlynkSimpleEthernetENC_WM.h | 5 +- src/BlynkSimpleEthernetSSL_WM.h | 5 +- src/BlynkSimpleEthernetV2_0_WM.h | 5 +- src/BlynkSimpleEthernet_WM.h | 5 +- src/BlynkSimpleUIPEthernetSSL_WM.h | 5 +- src/BlynkSimpleUIPEthernet_WM.h | 5 +- 23 files changed, 3500 insertions(+), 1238 deletions(-) diff --git a/README.md b/README.md index e2985256..b0a20cca 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ * [Currently supported Boards](#currently-supported-boards) * [Currently supported Ethernet shields/modules](#currently-supported-ethernet-shieldsmodules) * [Changelog](#changelog) + * [Major Releases v1.2.0](#major-releases-v120) * [Major Releases v1.1.0](#major-releases-v110) * [Releases v1.0.18](#releases-v1018) * [Releases v1.0.17](#releases-v1017) @@ -105,10 +106,17 @@ * [1. W5500_WM_Config on ESP32_DEV](#1-w5500_wm_config-on-esp32_dev) * [1.1. No DoubleReset Detected => Running normally](#11-no-doublereset-detected--running-normally) * [1.2. DoubleReset Detected => Enter Config Portal](#12-doublereset-detected--enter-config-portal) - * [2. W5500_Blynk on SAMD21 SEEED_XIAO_M0](#2-w5500_blynk-on-samd21-seeed_xiao_m0) + * [1.3. Enter non-persistent ConfigPortal](#13-enter-non-persistent-configportal) + * [1.4. Enter persistent ConfigPortal](#14-enter-persistent-configportal) + * [2. W5500_WM_Config_SAMD on SAMD21 SEEED_XIAO_M0](#2-w5500_wm_config_samd-on-samd21-seeed_xiao_m0) * [2.1. No Config Data without LOAD_DEFAULT_CONFIG_DATA => Config Portal](#21-no-config-data-without-load_default_config_data--config-portal) * [2.2. Input valid Credentials and Save => Exit Config Portal](#22-input-valid-credentials-and-save--exit-config-portal) - * [3. W5500_Blynk on SAM-DUE](#3-w5500_blynk-on-sam-due) + * [2.3. Enter non-persistent ConfigPortal](#23-enter-non-persistent-configportal) + * [2.4. Enter persistent ConfigPortal](#24-enter-persistent-configportal) + * [3. W5500_WM_Config_SAM_DUE on SAM-DUE](#3-w5500_wm_config_sam_due-on-sam-due) + * [4. ENC28J60_Blynk on NRF52840_FEATHER with ENC28J60 using UIPEthernet Library](#4-enc28j60_blynk-on-nrf52840_feather-with-end28j60-using-uipethernet-library) + * [5. W5500_WM_Config_Teensy on TEENSY 4.0 with W5x00 using EthernetLarge Library](#5-w5500_wm_config_teensy-on-teensy-40-with-w5x00-using-ethernetlarge-library) + * [6. W5500_WM_Config on ESP8266 with W5x00 using EthernetLarge Library](#6-w5500_wm_config-on-esp8266-with-w5x00-using-ethernetlarge-library) * [Debug](#debug) * [Troubleshooting](#troubleshooting) * [Releases](#releases) @@ -178,6 +186,13 @@ This [**EthernetWebServer** library](https://github.com/khoih-prog/EthernetWebSe ## Changelog +### Major Releases v1.2.0 + +1. Fix Config Portal Bug. +2. Add functions to control Config Portal from software or Virtual Switches. Check [How to trigger a Config Portal from code #25](https://github.com/khoih-prog/Blynk_WM/issues/25) +3. Use more efficient [FlashStorage_SAMD v1.1.0](https://github.com/khoih-prog/FlashStorage_SAMD). + + ### Major Releases v1.1.0 1. Add support to LittleFS for ESP32 using [LITTLEFS](https://github.com/lorol/LITTLEFS) Library @@ -245,7 +260,7 @@ Thanks to [thorathome in GitHub](https://github.com/thorathome) to test, suggest 1. [`Arduino IDE 1.8.13+` for Arduino](https://www.arduino.cc/en/Main/Software) 2. `Arduino AVR core 1.8.3+` for Arduino (Use Arduino Board Manager) for AVR boards - 3. [`Teensy core v1.53+`](https://www.pjrc.com/teensy/td_download.html) for Teensy (4.1, 4.0, 3.6, 3.5, 3,2, 3.1, 3.0) boards. + 3. [`Teensy core v1.51`](https://www.pjrc.com/teensy/td_download.html) for Teensy (4.1, 4.0, 3.6, 3.5, 3,2, 3.1, 3.0) boards using W5500, ENC28J60 Ethernet shields. [`Teensy core v1.53+`](https://www.pjrc.com/teensy/td_download.html) for Teensy (4.1) boards using NativeEthernet. 4. [`Arduino SAM DUE core v1.6.12+`](https://www.arduino.cc/en/Guide/ArduinoDue) for SAM DUE ARM Cortex-M3 boards. 5. [`Arduino SAMD core 1.8.11+`](https://www.arduino.cc/en/Guide/ArduinoM0) for SAMD ARM Cortex-M0+ boards (Nano 33 IoT, etc.). 6. [`Adafruit SAMD core 1.6.4+`](https://www.adafruit.com/) for SAMD ARM Cortex-M0+ and M4 boards (Itsy-Bitsy M4, etc.) @@ -264,9 +279,9 @@ Thanks to [thorathome in GitHub](https://github.com/thorathome) to test, suggest - [`UIPEthernet library v2.0.9+`](https://github.com/UIPEthernet/UIPEthernet) for ENC28J60 - [`NativeEthernet Library version stable111+`](https://github.com/vjmuzik/NativeEthernet) for Teensy 4.1 built-in NativeEthernet. **New** 13. Depending on which board you're using: - - [`DueFlashStorage library`](https://github.com/sebnil/DueFlashStorage) for SAM DUE - - [`FlashStorage_SAMD library v1.0.0+`](https://github.com/khoih-prog/FlashStorage_SAMD) for SAMD (DUE, ZERO, MKR, NANO_33_IOT, M0, M0 Pro, AdaFruit CIRCUITPLAYGROUND_EXPRESS, etc.) -14. [`EthernetWebServer library v1.2.1+`](https://github.com/khoih-prog/EthernetWebServer). To install. check [![arduino-library-badge](https://www.ardu-badge.com/badge/EthernetWebServer.svg?)](https://www.ardu-badge.com/EthernetWebServer). + - [`DueFlashStorage library v1.0+`](https://github.com/sebnil/DueFlashStorage) for SAM DUE + - [`FlashStorage_SAMD library v1.1.0+`](https://github.com/khoih-prog/FlashStorage_SAMD) for SAMD (DUE, ZERO, MKR, NANO_33_IOT, M0, M0 Pro, AdaFruit CIRCUITPLAYGROUND_EXPRESS, etc.) +14. [`EthernetWebServer library v1.3.0+`](https://github.com/khoih-prog/EthernetWebServer). To install. check [![arduino-library-badge](https://www.ardu-badge.com/badge/EthernetWebServer.svg?)](https://www.ardu-badge.com/EthernetWebServer). 15. [`ESP_DoubleResetDetector library v1.1.1+`](https://github.com/khoih-prog/ESP_DoubleResetDetector) for ESP32 and ESP8266. To install. check [![arduino-library-badge](https://www.ardu-badge.com/badge/ESP_DoubleResetDetector.svg?)](https://www.ardu-badge.com/ESP_DoubleResetDetector). 16. [`DoubleResetDetector_Generic library v1.0.3+`](https://github.com/khoih-prog/DoubleResetDetector_Generic) for other boards (not ESP32 or ESP8266). To install. check [![arduino-library-badge](https://www.ardu-badge.com/badge/DoubleResetDetector_Generic.svg?)](https://www.ardu-badge.com/DoubleResetDetector_Generic). 17. [`Functional-VLPP library v1.0.1+`](https://github.com/khoih-prog/functional-vlpp) to use server's lambda function. To install. check [![arduino-library-badge](https://www.ardu-badge.com/badge/Functional-Vlpp.svg?)](https://www.ardu-badge.com/Functional-Vlpp) @@ -949,11 +964,21 @@ Blynk_Configuration defaultConfig; - To add custom parameters, just modify from the example below +In `defines.h` + +``` +#define USE_DYNAMIC_PARAMETERS false +``` + +in `dynamicParams.h` + ``` -#if !defined(USE_DYNAMIC_PARAMETERS) - #define USE_DYNAMIC_PARAMETERS true +#if (USE_DYNAMIC_PARAMETERS) + #warning USE_DYNAMIC_PARAMETERS #endif +// USE_DYNAMIC_PARAMETERS defined in defined.h + /////////////// Start dynamic Credentials /////////////// //Defined in BlynkEthernet_WM.h, , @@ -1176,12 +1201,16 @@ void setup() Serial.begin(115200); while (!Serial); - #if ( USE_LITTLEFS || USE_SPIFFS) - Serial.println("\nStart W5500_Blynk using " + String(CurrentFileFS) + " on " + String(BOARD_NAME)); + delay(200); + +#if ( USE_LITTLEFS || USE_SPIFFS) + Serial.print(F("\nStart W5500_Blynk using ")); Serial.print(CurrentFileFS); + Serial.print(F(" on ")); Serial.print(BOARD_NAME); #else - Serial.println("\nStart W5500_Blynk on " + String(BOARD_NAME)); + Serial.print(F("\nStart W5500_Blynk on ")); Serial.print(BOARD_NAME); #endif + Serial.print(F(" with ")); Serial.println(SHIELD_TYPE); Serial.println(BLYNK_ETHERNET_WM_VERSION); pinMode(SDCARD_CS, OUTPUT); @@ -1194,25 +1223,25 @@ void setup() #else #if USE_ETHERNET - LOGWARN(F("=========== USE_ETHERNET ===========")); + ET_LOGWARN(F("=========== USE_ETHERNET ===========")); #elif USE_ETHERNET2 - LOGWARN(F("=========== USE_ETHERNET2 ===========")); + ET_LOGWARN(F("=========== USE_ETHERNET2 ===========")); #elif USE_ETHERNET3 - LOGWARN(F("=========== USE_ETHERNET3 ===========")); + ET_LOGWARN(F("=========== USE_ETHERNET3 ===========")); #elif USE_ETHERNET_LARGE - LOGWARN(F("=========== USE_ETHERNET_LARGE ===========")); + ET_LOGWARN(F("=========== USE_ETHERNET_LARGE ===========")); #elif USE_ETHERNET_ESP8266 - LOGWARN(F("=========== USE_ETHERNET_ESP8266 ===========")); + ET_LOGWARN(F("=========== USE_ETHERNET_ESP8266 ===========")); #else - LOGWARN(F("=========================")); + ET_LOGWARN(F("=========================")); #endif - LOGWARN(F("Default SPI pinout:")); - LOGWARN1(F("MOSI:"), MOSI); - LOGWARN1(F("MISO:"), MISO); - LOGWARN1(F("SCK:"), SCK); - LOGWARN1(F("SS:"), SS); - LOGWARN(F("=========================")); + ET_LOGWARN(F("Default SPI pinout:")); + ET_LOGWARN1(F("MOSI:"), MOSI); + ET_LOGWARN1(F("MISO:"), MISO); + ET_LOGWARN1(F("SCK:"), SCK); + ET_LOGWARN1(F("SS:"), SS); + ET_LOGWARN(F("=========================")); #if defined(ESP8266) // For ESP8266, change for other boards if necessary @@ -1220,7 +1249,7 @@ void setup() #define USE_THIS_SS_PIN D2 // For ESP8266 #endif - LOGWARN1(F("ESP8266 setCsPin:"), USE_THIS_SS_PIN); + ET_LOGWARN1(F("ESP8266 setCsPin:"), USE_THIS_SS_PIN); #if ( USE_ETHERNET || USE_ETHERNET_LARGE || USE_ETHERNET2 ) // For ESP8266 @@ -1260,7 +1289,7 @@ void setup() #define USE_THIS_SS_PIN 22 // For ESP32 #endif - LOGWARN1(F("ESP32 setCsPin:"), USE_THIS_SS_PIN); + ET_LOGWARN1(F("ESP32 setCsPin:"), USE_THIS_SS_PIN); // For other boards, to change if necessary #if ( USE_ETHERNET || USE_ETHERNET_LARGE || USE_ETHERNET2 ) @@ -1288,7 +1317,7 @@ void setup() #define USE_THIS_SS_PIN 10 // For other boards #endif - LOGWARN1(F("Unknown board setCsPin:"), USE_THIS_SS_PIN); + ET_LOGWARN1(F("Unknown board setCsPin:"), USE_THIS_SS_PIN); // For other boards, to change if necessary #if ( USE_ETHERNET || USE_ETHERNET_LARGE || USE_ETHERNET2 ) @@ -1428,56 +1457,52 @@ void loop() #define defines_h #if ( defined(ARDUINO_AVR_ADK) || defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) ) -#error This code is designed to run on SAMD, SAM-DUE, Teensy platform, ESP8266, ESP32 not AVR Mega! Please check your Tools->Board setting. + #error This code is designed to run on SAMD, SAM-DUE, Teensy platform, ESP8266, ESP32 not AVR Mega! Please check your Tools->Board setting. #endif /* Comment this out to disable prints and save space */ #define BLYNK_PRINT Serial #if ( defined(ESP32) || defined(ESP8266) ) -#define DOUBLERESETDETECTOR_DEBUG false //true + #define DOUBLERESETDETECTOR_DEBUG true #else -#define DRD_GENERIC_DEBUG false //true + #define DRD_GENERIC_DEBUG false //true #endif -#define BLYNK_WM_DEBUG 0 +#define BLYNK_WM_DEBUG 1 #if ( defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_SAMD_MKRWIFI1010) \ || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRFox1200) || defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) \ || defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_SAMD_MKRVIDOR4000) || defined(__SAMD21G18A__) \ || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(__SAMD21E18A__) || defined(__SAMD51__) || defined(__SAMD51J20A__) || defined(__SAMD51J19A__) \ || defined(__SAMD51G19A__) || defined(__SAMD51P19A__) || defined(__SAMD21G18A__) ) -#if defined(ETHERNET_USE_SAMD) -#undef ETHERNET_USE_SAMD -#endif -#define ETHERNET_USE_SAMD true -#define USE_DYNAMIC_PARAMETERS true + #if defined(ETHERNET_USE_SAMD) + #undef ETHERNET_USE_SAMD + #endif + #define ETHERNET_USE_SAMD true #endif #if ( defined(ARDUINO_SAM_DUE) || defined(__SAM3X8E__) ) -#if defined(ETHERNET_USE_SAM_DUE) -#undef ETHERNET_USE_SAM_DUE -#endif -#define ETHERNET_USE_SAM_DUE true -#define USE_DYNAMIC_PARAMETERS true + #if defined(ETHERNET_USE_SAM_DUE) + #undef ETHERNET_USE_SAM_DUE + #endif + #define ETHERNET_USE_SAM_DUE true #endif #if ( defined(CORE_TEENSY) && !( defined(__MKL26Z64__) || defined(__AVR_AT90USB1286__) || defined(__AVR_ATmega32U4__) ) ) -#if defined(ETHERNET_USE_TEENSY) -#undef ETHERNET_USE_TEENSY -#endif -#define ETHERNET_USE_TEENSY true -#define USE_DYNAMIC_PARAMETERS true + #if defined(ETHERNET_USE_TEENSY) + #undef ETHERNET_USE_TEENSY + #endif + #define ETHERNET_USE_TEENSY true #endif #if ( defined(NRF52840_FEATHER) || defined(NRF52832_FEATHER) || defined(NRF52_SERIES) || defined(ARDUINO_NRF52_ADAFRUIT) || \ defined(NRF52840_FEATHER_SENSE) || defined(NRF52840_ITSYBITSY) || defined(NRF52840_CIRCUITPLAY) || defined(NRF52840_CLUE) || \ defined(NRF52840_METRO) || defined(NRF52840_PCA10056) || defined(PARTICLE_XENON) || defined(NINA_B302_ublox) || defined(NINA_B112_ublox) ) -#if defined(ETHERNET_USE_NRF52) -#undef ETHERNET_USE_NRF528XX -#endif -#define ETHERNET_USE_NRF528XX true -#define USE_DYNAMIC_PARAMETERS true + #if defined(ETHERNET_USE_NRF52) + #undef ETHERNET_USE_NRF528XX + #endif + #define ETHERNET_USE_NRF528XX true #endif #if defined(ETHERNET_USE_NRF528XX) @@ -1614,17 +1639,25 @@ void loop() #endif #elif defined(ETHERNET_USE_SAM_DUE) -#if ( defined(ARDUINO_SAM_DUE) || (__SAM3X8E__) ) -#define BOARD_TYPE "SAM DUE" -#else -#define BOARD_TYPE "SAM Unknown" -#endif + #if ( defined(ARDUINO_SAM_DUE) || (__SAM3X8E__) ) + #define BOARD_TYPE "SAM DUE" + #else + #define BOARD_TYPE "SAM Unknown" + #endif #elif ( defined(CORE_TEENSY) ) #if defined(__IMXRT1062__) // For Teensy 4.1/4.0 - #define BOARD_TYPE "TEENSY 4.1/4.0" + #if defined(ARDUINO_TEENSY41) + #define BOARD_TYPE "TEENSY 4.1" + // Use true for NativeEthernet Library, false if using other Ethernet libraries + #define USE_NATIVE_ETHERNET true + #elif defined(ARDUINO_TEENSY40) + #define BOARD_TYPE "TEENSY 4.0" + #else + #define BOARD_TYPE "TEENSY 4.x" + #endif #elif defined(__MK66FX1M0__) #define BOARD_TYPE "Teensy 3.6" #elif defined(__MK64FX512__) @@ -1663,16 +1696,12 @@ void loop() #else -#error Unknown or unsupported Board. Please check your Tools->Board setting. + #error Unknown or unsupported Board. Please check your Tools->Board setting. #endif //BOARD_TYPE #ifndef BOARD_NAME - #if defined(ARDUINO_BOARD) - #define BOARD_NAME ARDUINO_BOARD - #else #define BOARD_NAME BOARD_TYPE - #endif #endif #define USE_BLYNK_WM true @@ -1683,150 +1712,183 @@ void loop() #if USE_BLYNK_WM -// Not use #define USE_SPIFFS => using EEPROM for configuration data in WiFiManager -// #define USE_SPIFFS false => using EEPROM for configuration data in WiFiManager -// #define USE_SPIFFS true => using SPIFFS for configuration data in WiFiManager -// Be sure to define USE_SPIFFS before #include - -// Start location in EEPROM to store config data. Default 0 -// Config data Size currently is 128 bytes w/o chksum, 132 with chksum) -//#define EEPROM_START 1024 - -#if ( defined(ESP32) || defined(ESP8266) ) - -#if defined(ESP8266) - -// #define USE_SPIFFS and USE_LITTLEFS false => using EEPROM for configuration data in WiFiManager -// #define USE_LITTLEFS true => using LITTLEFS for configuration data in WiFiManager -// #define USE_LITTLEFS false and USE_SPIFFS true => using SPIFFS for configuration data in WiFiManager -// Be sure to define USE_LITTLEFS and USE_SPIFFS before #include -// From ESP8266 core 2.7.1, SPIFFS will be deprecated and to be replaced by LittleFS -// Select USE_LITTLEFS (higher priority) or USE_SPIFFS - -//#define USE_LITTLEFS true -#define USE_LITTLEFS false -#define USE_SPIFFS false -//#define USE_SPIFFS true - -#if USE_LITTLEFS -//LittleFS has higher priority -#define CurrentFileFS "LittleFS" -#ifdef USE_SPIFFS -#undef USE_SPIFFS -#endif -#define USE_SPIFFS false -#elif USE_SPIFFS -#define CurrentFileFS "SPIFFS" -#endif - -#else //#if defined(ESP8266) - -// For ESP32 -//#define USE_SPIFFS true -#define USE_SPIFFS false - -#endif //#if defined(ESP8266) - - -#else //#if ( defined(ESP32) || defined(ESP8266) ) -#define USE_SPIFFS false -#endif //#if ( defined(ESP32) || defined(ESP8266) ) - -#if !( USE_LITTLEFS || USE_SPIFFS) - -#if !( defined(ARDUINO_SAM_DUE) || defined(__SAM3X8E__) ) -// EEPROM_SIZE must be <= 2048 and >= CONFIG_DATA_SIZE (currently 172 bytes) -#define EEPROM_SIZE (2 * 1024) -#endif - -// EEPROM_START + CONFIG_DATA_SIZE must be <= EEPROM_SIZE -#define EEPROM_START 0 -#endif - -// To use faster 25MHz clock instead of defaulf 14MHz. Only for W5200 and W5500. W5100 also tested OK. -//#define USE_W5100 false - -#define USE_ETHERNET_WRAPPER true -//#define USE_ETHERNET_WRAPPER false - -// Use true for ENC28J60 and UIPEthernet library (https://github.com/UIPEthernet/UIPEthernet) -// Use false for W5x00 and Ethernetx library (https://www.arduino.cc/en/Reference/Ethernet) - -//#define USE_UIP_ETHERNET true -//#define USE_UIP_ETHERNET false + #define USE_DYNAMIC_PARAMETERS true -#define USE_CUSTOM_ETHERNET false //true - -// Note: To rename ESP628266 Ethernet lib files to Ethernet_ESP8266.h and Ethernet_ESP8266.cpp -// In order to USE_ETHERNET_ESP8266 -#if ( !defined(USE_UIP_ETHERNET) || !USE_UIP_ETHERNET ) - - // To override the default CS/SS pin. Don't use unless you know exactly which pin to use - // You can define here or customize for each board at same place with BOARD_TYPE - // Check @ defined(SEEED_XIAO_M0) - //#define USE_THIS_SS_PIN 22 //21 //5 //4 //2 //15 - -// Only one if the following to be true -#define USE_ETHERNET2 false -#define USE_ETHERNET3 false //true -#define USE_ETHERNET_LARGE true //true -#define USE_ETHERNET_ESP8266 false //true - -#if !USE_ETHERNET_WRAPPER - -#if ( USE_ETHERNET2 || USE_ETHERNET3 || USE_ETHERNET_LARGE || USE_ETHERNET_ESP8266 ) - #ifdef USE_CUSTOM_ETHERNET - #undef USE_CUSTOM_ETHERNET + // Not use #define USE_SPIFFS => using EEPROM for configuration data in WiFiManager + // #define USE_SPIFFS false => using EEPROM for configuration data in WiFiManager + // #define USE_SPIFFS true => using SPIFFS for configuration data in WiFiManager + // Be sure to define USE_SPIFFS before #include + + // Start location in EEPROM to store config data. Default 0 + // Config data Size currently is 128 bytes w/o chksum, 132 with chksum) + //#define EEPROM_START 1024 + + #if ( defined(ESP32) || defined(ESP8266) ) + + #if defined(ESP8266) + + // #define USE_SPIFFS and USE_LITTLEFS false => using EEPROM for configuration data in WiFiManager + // #define USE_LITTLEFS true => using LITTLEFS for configuration data in WiFiManager + // #define USE_LITTLEFS false and USE_SPIFFS true => using SPIFFS for configuration data in WiFiManager + // Be sure to define USE_LITTLEFS and USE_SPIFFS before #include + // From ESP8266 core 2.7.1, SPIFFS will be deprecated and to be replaced by LittleFS + // Select USE_LITTLEFS (higher priority) or USE_SPIFFS + + #define USE_LITTLEFS false + #define USE_SPIFFS false + + #if USE_LITTLEFS + //LittleFS has higher priority + #define CurrentFileFS "LittleFS" + #ifdef USE_SPIFFS + #undef USE_SPIFFS + #endif + #define USE_SPIFFS false + #elif USE_SPIFFS + #define CurrentFileFS "SPIFFS" + #endif + + #else //#if defined(ESP8266) + + // For ESP32 + // Not use #define USE_LITTLEFS and #define USE_SPIFFS => using SPIFFS for configuration data in WiFiManager + // (USE_LITTLEFS == false) and (USE_SPIFFS == false) => using EEPROM for configuration data in WiFiManager + // (USE_LITTLEFS == true) and (USE_SPIFFS == false) => using LITTLEFS for configuration data in WiFiManager + // (USE_LITTLEFS == true) and (USE_SPIFFS == true) => using LITTLEFS for configuration data in WiFiManager + // (USE_LITTLEFS == false) and (USE_SPIFFS == true) => using SPIFFS for configuration data in WiFiManager + #define USE_LITTLEFS true + #define USE_SPIFFS false + + #if USE_LITTLEFS + //LittleFS has higher priority + #define CurrentFileFS "LittleFS" + #ifdef USE_SPIFFS + #undef USE_SPIFFS + #endif + #define USE_SPIFFS false + #elif USE_SPIFFS + #define CurrentFileFS "SPIFFS" + #endif + + #endif //#if defined(ESP8266) + + + #else //#if ( defined(ESP32) || defined(ESP8266) ) + #define USE_LITTLEFS false + #define USE_SPIFFS false + #endif //#if ( defined(ESP32) || defined(ESP8266) ) + + #if !( USE_LITTLEFS || USE_SPIFFS) + + #if !( defined(ARDUINO_SAM_DUE) || defined(__SAM3X8E__) ) + // EEPROM_SIZE must be <= 2048 and >= CONFIG_DATA_SIZE (currently 172 bytes) + #define EEPROM_SIZE (2 * 1024) + #endif + + // EEPROM_START + CONFIG_DATA_SIZE must be <= EEPROM_SIZE + #define EEPROM_START 0 + #endif + + // To use faster 25MHz clock instead of defaulf 14MHz. Only for W5200 and W5500. W5100 also tested OK. + //#define USE_W5100 false + + //#define USE_ETHERNET_WRAPPER true + #define USE_ETHERNET_WRAPPER false + + // Use true for ENC28J60 and UIPEthernet library (https://github.com/UIPEthernet/UIPEthernet) + // Use false for W5x00 and Ethernetx library (https://www.arduino.cc/en/Reference/Ethernet) + + //#define USE_UIP_ETHERNET true + //#define USE_UIP_ETHERNET false + + #define USE_CUSTOM_ETHERNET false //true + + // Note: To rename ESP628266 Ethernet lib files to Ethernet_ESP8266.h and Ethernet_ESP8266.cpp + // In order to USE_ETHERNET_ESP8266 + #if ( !defined(USE_UIP_ETHERNET) || !USE_UIP_ETHERNET ) + + // To override the default CS/SS pin. Don't use unless you know exactly which pin to use + // You can define here or customize for each board at same place with BOARD_TYPE + // Check @ defined(SEEED_XIAO_M0) + //#define USE_THIS_SS_PIN 22 //21 //5 //4 //2 //15 + + // Only one if the following to be true + #define USE_ETHERNET false + #define USE_ETHERNET2 false + #define USE_ETHERNET3 false + #define USE_ETHERNET_LARGE true + #define USE_ETHERNET_ESP8266 false + #define USE_CUSTOM_ETHERNET false + + #if !USE_ETHERNET_WRAPPER + + #if ( USE_ETHERNET2 || USE_ETHERNET3 || USE_ETHERNET_LARGE || USE_ETHERNET_ESP8266 || USE_ETHERNET_ENC || USE_NATIVE_ETHERNET ) + #ifdef USE_CUSTOM_ETHERNET + #undef USE_CUSTOM_ETHERNET + #endif + #define USE_CUSTOM_ETHERNET false + #endif + + #if USE_NATIVE_ETHERNET + #include "NativeEthernet.h" + #warning Using NativeEthernet lib for Teensy 4.1. Must also use Teensy Packages Patch or error + #define SHIELD_TYPE "Custom Ethernet using Teensy 4.1 NativeEthernet Library" + #elif USE_ETHERNET3 + #include "Ethernet3.h" + #warning Using Ethernet3 lib + #define SHIELD_TYPE "W5x00 using Ethernet3 Library" + #elif USE_ETHERNET2 + #include "Ethernet2.h" + #warning Using Ethernet2 lib + #define SHIELD_TYPE "W5x00 using Ethernet2 Library" + #elif USE_ETHERNET_LARGE + #include "EthernetLarge.h" + #warning Using EthernetLarge lib + #define SHIELD_TYPE "W5x00 using EthernetLarge Library" + #elif USE_ETHERNET_ESP8266 + #include "Ethernet_ESP8266.h" + #warning Using Ethernet_ESP8266 lib + #define SHIELD_TYPE "W5x00 using Ethernet_ESP8266 Library" + #elif USE_CUSTOM_ETHERNET + //#include "Ethernet_XYZ.h" + #include "EthernetENC.h" + #warning Using Custom Ethernet library. You must include a library and initialize. + #define SHIELD_TYPE "Custom Ethernet using Ethernet_XYZ Library" + #else + #ifdef USE_ETHERNET + #undef USE_ETHERNET + #endif + #define USE_ETHERNET true + #include "Ethernet.h" + #warning Using Ethernet lib + #define SHIELD_TYPE "W5x00 using Ethernet Library" + #endif + + // Ethernet_Shield_W5200, EtherCard, EtherSia not supported + // Select just 1 of the following #include if uncomment #define USE_CUSTOM_ETHERNET + // Otherwise, standard Ethernet library will be used for W5x00 + + #endif //USE_ETHERNET_WRAPPER + #endif //#if !USE_UIP_ETHERNET + + + #if USE_SSL + // Need ArduinoECCX08 and ArduinoBearSSL libraries + // Currently, error not enough memory for UNO, Mega2560. Don't use + #include + #else + #include #endif - #define USE_CUSTOM_ETHERNET true -#endif - -#if USE_ETHERNET3 -#include "Ethernet3.h" -#warning Use Ethernet3 lib -#elif USE_ETHERNET2 -#include "Ethernet2.h" -#warning Use Ethernet2 lib -#elif USE_ETHERNET_LARGE -#include "EthernetLarge.h" -#warning Use EthernetLarge lib -#elif USE_ETHERNET_ESP8266 -#include "Ethernet_ESP8266.h" -#warning Use Ethernet_ESP8266 lib -#elif USE_CUSTOM_ETHERNET -#include "Ethernet_XYZ.h" -#warning Use Custom Ethernet library from EthernetWrapper. You must include a library here or error. -#else -#define USE_ETHERNET true -#include "Ethernet.h" -#warning Use Ethernet lib -#endif - -// Ethernet_Shield_W5200, EtherCard, EtherSia not supported -// Select just 1 of the following #include if uncomment #define USE_CUSTOM_ETHERNET -// Otherwise, standard Ethernet library will be used for W5x00 - -#endif //#if !USE_UIP_ETHERNET -#endif //USE_ETHERNET_WRAPPER - - -#if USE_SSL -// Need ArduinoECCX08 and ArduinoBearSSL libraries -// Currently, error not enough memory for UNO, Mega2560. Don't use -#include -#else -#include -#endif #else ////USE_BLYNK_WM -#if USE_SSL -// Need ArduinoECCX08 and ArduinoBearSSL libraries -// Currently, error not enough memory for UNO, Mega2560. Don't use -#include -#else -#include -#endif + #if USE_SSL + // Need ArduinoECCX08 and ArduinoBearSSL libraries + // Currently, error not enough memory for UNO, Mega2560. Don't use + #include + #else + #include + #endif #endif //USE_BLYNK_WM @@ -1955,10 +2017,12 @@ char server[] = "blynk-cloud.com"; #if USE_BLYNK_WM -#if !defined(USE_DYNAMIC_PARAMETERS) - #define USE_DYNAMIC_PARAMETERS true +#if (USE_DYNAMIC_PARAMETERS) + #warning USE_DYNAMIC_PARAMETERS #endif +// USE_DYNAMIC_PARAMETERS defined in defined.h + /////////////// Start dynamic Credentials /////////////// //Defined in BlynkEthernet_WM.h, , @@ -2037,50 +2101,43 @@ This is the terminal output of a ESP32 board with W5500 Ethernet shield running ``` - -Start W5500_Blynk on ESP32_DEV -BlynkEthernet_WM v1.1.0 -EEPROM size = 2048, start = 0 -EEPROM Flag read = 0xd0d04321 +Start W5500_WM_Config using LittleFS on ESP32 with W5x00 using EthernetLarge Library +BlynkEthernet_WM v1.2.0 +LittleFS Flag read = 0xD0D04321 No doubleResetDetected -SetFlag write = 0xd0d01234 -[1108] ======= Start Default Config Data ======= -[1108] Hdr=NonSSL,BName=Air-Control -[1108] Svr=account.duckdns.org,Tok=token1 -[1110] Svr1=blynk-cloud.com,Tok1=<> -[1115] Prt=8080,SIP=192.168.2.230 -[1124] EEPROMsz:2048 -[1124] ======= Start Stored Config Data ======= -[1124] Hdr=W5X00,BName=Air-Control -[1128] Svr=account.duckdns.org,Tok=token -[1133] Svr1=account.ddns.net,Tok1=token -[1139] Prt=8080,SIP=192.168.2.230 -[1142] CCSum=0x2ba3,RCSum=0x2ba3 -[1145] ChkCrR: Error Small Buffer. -[1148] Hdr=W5X00,BName=Air-Control -[1151] Svr=account.duckdns.org,Tok=token -[1157] Svr1=account.ddns.net,Tok1=token -[1163] Prt=8080,SIP=192.168.2.230 -[1166] MAC:FE-9B-D9-D5-9C-E5 -w5100 init, using SS_PIN_DEFAULT = 13 -W5100::init: W5500, SSIZE =4096 -[2749] IP:192.168.2.230 -[2749] bg: noConfigPortal = true -[2749] bg: noConfigPortal = true -[2749] bg:ECon.TryB -[2749] +Saving config file... +Saving config file OK +[312] LoadCfgFile +[317] OK +[317] CCSum=0x2c18,RCSum=0x2c18 +[326] LoadCredFile +[329] OK +[329] CrCCsum=0x29a6,CrRCsum=0x29a6 +[329] Hdr=W5X00,BName=ESP32_LittleFS +[330] Svr=account.duckdns.org,Tok=token +[332] Svr1=account.duckdns.org,Tok1=token1 +[338] Prt=8080,SIP=192.168.2.222 +[341] MAC:FE-C6-B0-96-FE-B9 + +W5100 init, using SS_PIN_DEFAULT = 22, new ss_pin = 10, W5100Class::ss_pin = 27 +W5100::init: W5500, SSIZE =8192 +[1923] IP:192.168.2.222 +[1936] LoadCPFile +[1941] OK +[1941] bg:ECon.TryB +[1941] ___ __ __ / _ )/ /_ _____ / /__ / _ / / // / _ \/ '_/ /____/_/\_, /_//_/_/\_\ /___/ v0.6.1 on ESP32 -[2760] BlynkArduinoClient.connect: Connecting to account.duckdns.org:8080 -[2926] Ready (ping: 6ms). -[2993] Connected to Blynk Server = account.duckdns.org, Token = token -[2993] bg:EBCon +[1945] BlynkArduinoClient.connect: Connecting to account.duckdns.org:8080 +[2064] Ready (ping: 8ms). +[2131] Connected to Blynk Server = account.duckdns.org, Token = token +[2131] bg:EBCon Conn2Blynk: server = account.duckdns.org, port = 8080 -Token = token, IP = 192.168.2.230 +Token = token, IP = 192.168.2.222 B Your stored Credentials : MQTT Server = default-mqtt-server @@ -2088,48 +2145,36 @@ Port = 1883 MQTT UserName = default-mqtt-username MQTT PWD = default-mqtt-password Subs Topics = default-mqtt-SubTopic - Pubs Topics = default-mqtt-PubTopic Stop doubleResetDetecting -ClearFlag write = 0xd0d04321 -BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB +Saving config file... +Saving config file OK +B ``` #### 1.2 DoubleReset Detected => Enter Config Portal ```cpp -Start W5500_Blynk on ESP32_DEV -BlynkEthernet_WM v1.1.0 -EEPROM size = 2048, start = 0 -EEPROM Flag read = 0xd0d01234 +Start W5500_WM_Config using LittleFS on ESP32 with W5x00 using EthernetLarge Library +BlynkEthernet_WM v1.2.0 +LittleFS Flag read = 0xD0D01234 doubleResetDetected -ClearFlag write = 0xd0d04321 -[1106] Double Reset Detected -[1106] ======= Start Default Config Data ======= -[1106] Hdr=NonSSL,BName=Air-Control -[1107] Svr=account.duckdns.org,Tok=token1 -[1111] Svr1=blynk-cloud.com,Tok1=<> -[1116] Prt=8080,SIP=192.168.2.230 -[1125] EEPROMsz:2048 -[1125] ======= Start Stored Config Data ======= -[1125] Hdr=W5X00,BName=Air-Control -[1128] Svr=account.duckdns.org,Tok=token -[1134] Svr1=account.ddns.net,Tok1=token -[1140] Prt=8080,SIP=192.168.2.230 -[1143] CCSum=0x2ba3,RCSum=0x2ba3 -[1146] ChkCrR: Error Small Buffer. -[1149] Hdr=W5X00,BName=Air-Control -[1152] Svr=account.duckdns.org,Tok=token -[1158] Svr1=account.ddns.net,Tok1=token -[1164] Prt=8080,SIP=192.168.2.230 -[1167] MAC:FE-9B-D9-D5-9C-E5 -w5100 init, using SS_PIN_DEFAULT = 13 -W5100::init: W5500, SSIZE =4096 -[2749] IP:192.168.2.230 -[2749] bg: noConfigPortal = false -[2749] bg:CfgPortal Forced.Stay -[2749] CfgIP=192.168.2.230 +Saving config file... +Saving config file OK +[287] MAC:FE-AB-CD-EF-ED-BA +_pinCS = 0 +W5100 init, using SS_PIN_DEFAULT = 22, new ss_pin = 10, W5100Class::ss_pin = 27 +W5100::init: W5500, SSIZE =8192 +[1970] IP:192.168.2.158 +[1982] LoadCPFile +[1987] OK +[1987] bg:Stay forever in CP:DRD/MRD +[1998] SaveCPFile +[2003] OK +[2014] SaveBkUpCPFile +[2187] OK +[2187] CfgIP=192.168.2.158 F Your stored Credentials : MQTT Server = default-mqtt-server @@ -2140,31 +2185,93 @@ Subs Topics = default-mqtt-SubTopic Pubs Topics = default-mqtt-PubTopic ``` ---- -### 2. W5500_Blynk on SAMD21 SEEED_XIAO_M0 +#### 1.3 Enter non-persistent ConfigPortal -The following is the sample terminal output when running example [W5500_Blynk](examples/W5500_Blynk) on Seeeduino SAMD21 SEEED_XIAO_M0 using W5500 Ethernet shield: - -#### 2.1 No Config Data without LOAD_DEFAULT_CONFIG_DATA => Config Portal +``` +CP Button Hit. Rebooting +[38251] SaveCPFile +[38256] OK +[38273] SaveBkUpCPFile +[38278] OK + +Start W5500_WM_Config using LittleFS on ESP32 with W5x00 using EthernetLarge Library +BlynkEthernet_WM v1.2.0 +LittleFS Flag read = 0xD0D04321 +No doubleResetDetected +Saving config file... +Saving config file OK +[518] LoadCfgFile +[520] OK +[521] CCSum=0x2c18,RCSum=0x2c18 +[527] LoadCredFile +[529] OK +[530] CrCCsum=0x29a6,CrRCsum=0x29a6 +[530] Hdr=W5X00,BName=ESP32_LittleFS +[530] Svr=account.duckdns.org,Tok=token +[532] Svr1=account.duckdns.org,Tok1=token1 +[537] Prt=8080,SIP=192.168.2.222 +[540] MAC:FE-C6-B0-96-FE-B9 + +W5100 init, using SS_PIN_DEFAULT = 22, new ss_pin = 10, W5100Class::ss_pin = 27 +W5100::init: W5500, SSIZE =8192 +[2123] IP:192.168.2.222 +[2129] LoadCPFile +[2131] OK +[2131] bg:Stay forever in CP:Forced-non-Persistent +[2138] SaveCPFile +[2141] OK +[2147] SaveBkUpCPFile +[2150] OK +[2151] CfgIP=192.168.2.222 +F +Your stored Credentials : +MQTT Server = default-mqtt-server +Port = 1883 +MQTT UserName = default-mqtt-username +MQTT PWD = default-mqtt-password +Subs Topics = default-mqtt-SubTopic +Pubs Topics = default-mqtt-PubTopic +Stop doubleResetDetecting +Saving config file... +Saving config file OK +F +``` -No Config Data with **LOAD_DEFAULT_CONFIG_DATA = false** => Config Portal don't loads default Credential +#### 1.4 Enter persistent ConfigPortal ``` -Start W5500_Blynk on SEEED_XIAO_M0 -BlynkEthernet_WM v1.1.0 -[936] ChkCrR:CrCCSum=0xaf50,CrRCSum=0xffffffff -[936] CCSum=0x0,RCSum=0x0 -[936] Invalid Stored Dynamic Data. Load default from Sketch -[937] SaveEEPROM,Sz=1024,DataSz=0,WCSum=0x1d4d -[944] CrCCSum=0x29a6 -[944] MAC:FE-A8-80-C6-CE-A3 -_pinCS = 0 -W5100 init, using SS_PIN_DEFAULT = 10, new ss_pin = 10, W5100Class::ss_pin = 1 +Persistent CP Button Hit. Rebooting +[9064] SaveCPFile +[9067] OK +[9074] SaveBkUpCPFile +[9077] OK + +Start W5500_WM_Config using LittleFS on ESP32 with W5x00 using EthernetLarge Library +BlynkEthernet_WM v1.2.0 +LittleFS Flag read = 0xD0D01234 +doubleResetDetected +Saving config file... +Saving config file OK +[302] LoadCfgFile +[305] OK +[306] CCSum=0x2c18,RCSum=0x2c18 +[316] LoadCredFile +[320] OK +[320] CrCCsum=0x29a6,CrRCsum=0x29a6 +[320] Hdr=W5X00,BName=ESP32_LittleFS +[320] Svr=account.duckdns.org,Tok=token +[322] Svr1=account.duckdns.org,Tok1=token1 +[328] Prt=8080,SIP=192.168.2.222 +[331] MAC:FE-C6-B0-96-FE-B9 + +W5100 init, using SS_PIN_DEFAULT = 22, new ss_pin = 10, W5100Class::ss_pin = 27 W5100::init: W5500, SSIZE =8192 -[2632] IP:192.168.2.153 -[2633] b:Stay in CfgPortal:No CfgDat -[2633] CfgIP=192.168.2.153 +[1914] IP:192.168.2.222 +[1923] LoadCPFile +[1926] OK +[1927] bg:Stay forever in CP:Forced-Persistent +[1927] CfgIP=192.168.2.222 F Your stored Credentials : MQTT Server = default-mqtt-server @@ -2173,9 +2280,44 @@ MQTT UserName = default-mqtt-username MQTT PWD = default-mqtt-password Subs Topics = default-mqtt-SubTopic Pubs Topics = default-mqtt-PubTopic -FFFFF -[339285] SaveEEPROM,Sz=1024,DataSz=0,WCSum=0x2e89 -[339292] CrCCSum=0x219f +FFFF +``` + +--- + +### 2. W5500_WM_Config_SAMD on SAMD21 SEEED_XIAO_M0 + +The following is the sample terminal output when running example [W5500_WM_Config_SAMD](examples/W5500_WM_Config_SAMD) on Seeeduino SAMD21 SEEED_XIAO_M0 using W5500 Ethernet shield: + +#### 2.1 No Config Data without LOAD_DEFAULT_CONFIG_DATA => Config Portal + +No Config Data with **LOAD_DEFAULT_CONFIG_DATA = false** => Config Portal don't loads default Credential + +``` +Start W5500_WM_Config_SAMD on SEEED_XIAO_M0 with W5x00 using EthernetLarge Library +BlynkEthernet_WM v1.2.0 +[936] CCSum=0xb8f6,RCSum=0xffffffff +[936] ChkCrR:CrCCsum=0xaf50,CrRCsum=0xffffffff +[937] InitCfgFile,Sz=200 +[937] InitCfgFile,DataSz=0 +[937] SaveEEPROM,Sz=1024,DataSz=0,WCSum=0xe23 +[944] CrCCSum=0xc30 +[951] MAC:FE-8F-83-CC-C5-A6 +_pinCS = 0 +W5100 init, using SS_PIN_DEFAULT = 10, new ss_pin = 10, W5100Class::ss_pin = 1 +W5100::init: W5500, SSIZE =8192 +[4641] IP:192.168.2.149 +[4642] bg:Stay forever in CP:No ConfigDat +[4649] CfgIP=192.168.2.149 +F +Your stored Credentials : +MQTT Server = blank +Port = blank +MQTT UserName = blank +MQTT PWD = blank +Subs Topics = blank +Pubs Topics = blank +RFRF ``` #### 2.2 Input valid Credentials and Save => Exit Config Portal @@ -2183,97 +2325,354 @@ FFFFF Input valid credentials with **LOAD_DEFAULT_CONFIG_DATA = false**. Click `Save` => reboot ``` -Start W5500_Blynk on SEEED_XIAO_M0 -BlynkEthernet_WM v1.1.0 -[1547] ChkCrR:CrCCSum=0x219f,CrRCSum=0x219f -[1547] CCSum=0x0,RCSum=0x0 -[1548] CrCCSum=0x219f,CrRCSum=0x219f -[1548] ======= Start Stored Config Data ======= -[1548] Hdr=W5X00,BName=Seeeduino_W5500_BlynkWM -[1548] Svr=account.duckdns.org,Tok=new_token1 -[1549] Svr1=account.ddns.net,Tok1=new_token2 -[1549] Prt=8080,SIP=192.168.2.220 -[1549] connectEthernet: Use static_IP=192.168.2.220 -[1549] MAC:FE-A1-D4-BC-E8-CB +Start W5500_WM_Config_SAMD on SEEED_XIAO_M0 with W5x00 using EthernetLarge Library +BlynkEthernet_WM v1.2.0 +[1367] CCSum=0x2a5b,RCSum=0x2a5b +[1368] ChkCrR:CrCCsum=0x15bd,CrRCsum=0x15bd +[1368] CrCCSum=15bd,CrRCSum=15bd +[1368] ======= Start Stored Config Data ======= +[1369] Hdr=W5X00,BName=SEEED_XIAO +[1369] Svr=account.duckdns.org,Tok=token +[1369] Svr1=account.duckdns.org,Tok1=token1 +[1369] Prt=8080,SIP=192.168.2.222 +[1370] connectEthernet: Use static_IP=192.168.2.222 +[1370] MAC:FE-80-92-D4-B8-CE W5100 init, using SS_PIN_DEFAULT = 10, new ss_pin = 10, W5100Class::ss_pin = 1 W5100::init: W5500, SSIZE =8192 -[3131] IP:192.168.2.220 -[3131] bg:ECon.TryB -[3131] +[2951] IP:192.168.2.222 +[2952] bg:ECon.TryB +[2952] ___ __ __ / _ )/ /_ _____ / /__ / _ / / // / _ \/ '_/ /____/_/\_, /_//_/_/\_\ - /___/ v0.6.1 on Arduino Zero + /___/ v0.6.1 on SAMD SEEED_XIAO_M0 -[3132] BlynkArduinoClient.connect: Connecting to account.duckdns.org:8080 -[3244] Ready (ping: 6ms). -[3311] Connected to BlynkServer=account.duckdns.org,Token=new_token1 -[3311] bg:EBCon +[2953] BlynkArduinoClient.connect: Connecting to account.duckdns.org:8080 +[3067] Ready (ping: 8ms). +[3134] Connected to BlynkServer=account.duckdns.org,Token=token +[3135] bg:EBCon Conn2Blynk: server = account.duckdns.org, port = 8080 -Token = new_token1, IP = 192.168.2.220 +Token = token, IP = 192.168.2.222 B Your stored Credentials : -MQTT Server = new-mqtt-server +MQTT Server = mqtt_server Port = 1883 -MQTT UserName = new-mqtt-username -MQTT PWD = new-mqtt-password -Subs Topics = new-mqtt-SubTopic -Pubs Topics = new-mqtt-PubTopic +MQTT UserName = mqtt_user +MQTT PWD = mqtt_pwd +Subs Topics = Subs_Topics +Pubs Topics = Pubs_Topics BBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB ``` ---- +#### 2.3 Enter non-persistent ConfigPortal + +``` +CP Button Hit. Rebooting + +Start W5500_WM_Config_SAMD on SEEED_XIAO_M0 with W5x00 using EthernetLarge Library +BlynkEthernet_WM v1.2.0 +[2128] CCSum=0x2a5b,RCSum=0x2a5b +[2128] ChkCrR:CrCCsum=0x15bd,CrRCsum=0x15bd +[2129] CrCCSum=15bd,CrRCSum=15bd +[2129] ======= Start Stored Config Data ======= +[2129] Hdr=W5X00,BName=SEEED_XIAO +[2129] Svr=account.duckdns.org,Tok=token +[2129] Svr1=account.duckdns.org,Tok1=token1 +[2130] Prt=8080,SIP=192.168.2.222 +[2130] connectEthernet: Use static_IP=192.168.2.222 +[2130] MAC:FE-80-92-D4-B8-CE + +W5100 init, using SS_PIN_DEFAULT = 10, new ss_pin = 10, W5100Class::ss_pin = 1 +W5100::init: W5500, SSIZE =8192 +[3712] IP:192.168.2.222 +[3712] bg:Stay forever in CP:Forced-non-Persistent +[3719] CfgIP=192.168.2.222 +F +Your stored Credentials : +MQTT Server = mqtt_server +Port = 1883 +MQTT UserName = mqtt_user +MQTT PWD = mqtt_pwd +Subs Topics = Subs_Topics +Pubs Topics = Pubs_Topics +``` -### 3. W5500_Blynk on SAM-DUE +#### 2.4 Enter persistent ConfigPortal -The following is the sample terminal output when running example [W5500_Blynk](examples/W5500_Blynk) on SAM-DUE using W5100 Ethernet shield +``` +Persistent CP Button Hit. Rebooting + +Start W5500_WM_Config_SAMD on SEEED_XIAO_M0 with W5x00 using EthernetLarge Library +BlynkEthernet_WM v1.2.0 +[1427] CCSum=0x2a5b,RCSum=0x2a5b +[1428] ChkCrR:CrCCsum=0x15bd,CrRCsum=0x15bd +[1428] CrCCSum=15bd,CrRCSum=15bd +[1428] ======= Start Stored Config Data ======= +[1429] Hdr=W5X00,BName=SEEED_XIAO +[1429] Svr=account.duckdns.org,Tok=token +[1429] Svr1=account.duckdns.org,Tok1=token1 +[1429] Prt=8080,SIP=192.168.2.222 +[1430] connectEthernet: Use static_IP=192.168.2.222 +[1430] MAC:FE-80-92-D4-B8-CE +W5100 init, using SS_PIN_DEFAULT = 10, new ss_pin = 10, W5100Class::ss_pin = 1 +W5100::init: W5500, SSIZE =8192 +[3011] IP:192.168.2.222 +[3012] bg:Stay forever in CP:Forced-Persistent +[3012] CfgIP=192.168.2.222 +F +Your stored Credentials : +MQTT Server = mqtt_server +Port = 1883 +MQTT UserName = mqtt_user +MQTT PWD = mqtt_pwd +Subs Topics = Subs_Topics +Pubs Topics = Pubs_Topics ``` -Start W5500_Blynk on SAM DUE -BlynkEthernet_WM v1.1.0 -[10] Simulate EEPROM, sz:1024 -[10] ChkCrR:CrCCSum=0x29a6,CrRCSum=0x29a6 -[11] CCSum=0x0,RCSum=0x0 -[11] CrCCSum=0x29a6,CrRCSum=0x29a6,TotalDataSz=380 +--- + +### 3. W5500_WM_Config_SAM_DUE on SAM-DUE + +The following is the sample terminal output when running example [W5500_WM_Config_SAM_DUE](examples/W5500_WM_Config_SAM_DUE) on SAM-DUE using W5100 Ethernet shield + +``` +Start W5500_WM_Config_SAM_DUE on SAM DUE with W5x00 using EthernetLarge Library +BlynkEthernet_WM v1.2.0 +[9] Simulate EEPROM,Sz=1024 +[9] CCSum=0x29f2,RCSum=0x29f2 +[10] ChkCrR:CrCCsum=0x1465,CrRCsum=0x1465 +[10] CrCCsum=0x1465,CrRCsum=0x1465,TotalDataSz=380 [12] ======= Start Stored Config Data ======= -[16] Hdr=W5X00,BName=SAM_DUE_W5100 -[20] Svr=account.duckdns.org,Tok=token1 -[25] Svr1=account.duckdns.org,Tok1=token2 -[31] Prt=8080,SIP=192.168.2.188 -[34] MAC:FE-80-A3-D2-DE-EC +[16] Hdr=W5X00,BName=SAM_DUE +[18] Svr=account.duckdns.org,Tok=token +[24] Svr1=account.duckdns.org,Tok1=token1 +[30] Prt=8080,SIP=192.168.2.188 +[32] MAC:FE-80-A3-D2-DE-EC W5100 init, using SS_PIN_DEFAULT = 10, new ss_pin = 10, W5100Class::ss_pin = 10 W5100::init: W5100, SSIZE =4096 -[1596] GetIP: -[1596] IP:192.168.2.188 -[1596] bg:ECon.TryB -[1596] +[1595] GetIP: +[1595] IP:192.168.2.188 +[1595] bg:ECon.TryB +[1595] ___ __ __ / _ )/ /_ _____ / /__ / _ / / // / _ \/ '_/ /____/_/\_, /_//_/_/\_\ /___/ v0.6.1 on Arduino Due -[1603] BlynkArduinoClient.connect: Connecting to account.duckdns.org:8080 -[1922] Ready (ping: 5ms). -[1990] Connected to BlynkServer=account.duckdns.org,Token=token1 -[1990] bg:EBCon +[1602] BlynkArduinoClient.connect: Connecting to account.duckdns.org:8080 +[1670] Ready (ping: 5ms). +[1738] Connected to BlynkServer=account.duckdns.org,Token=token +[1738] bg:EBCon Conn2Blynk: server = account.duckdns.org, port = 8080 -Token = token1, IP = 192.168.2.188 +Token = token, IP = 192.168.2.188 B Your stored Credentials : -MQTT Server = default-mqtt-server +MQTT Server = mqtt_server +Port = 1883 +MQTT UserName = mqtt_user +MQTT PWD = mqtt_pwd +Subs Topics = mqtt_Subs +Pubs Topics = mqtt_Pubs +``` + +--- + +### 4. ENC28J60_Blynk on NRF52840_FEATHER with ENC28J60 using UIPEthernet Library + +The following is the sample terminal output when running example [ENC28J60_Blynk](examples/ENC28J60_Blynk) on NRF52840_FEATHER with ENC28J60 using UIPEthernet Library + +``` +Start ENC28J60_Blynk on NRF52840_FEATHER with ENC28J60 using UIPEthernet Library +BlynkEthernet_WM v1.2.0 +LittleFS Flag read = 0xd0d04321 +Flag read = 0xd0d04321 +No doubleResetDetected +Saving DOUBLERESETDETECTOR_FLAG to DRD file : 0xd0d01234 +Saving DRD file OK +SetFlag write = 0xd0d01234 +[7791] LoadCfgFile +[7792] OK +[7792] CCSum=0x29de,RCSum=0x29de +[7794] LoadCredFile +[7794] OK +[7794] ChkCrR: Buffer allocated, Sz=35 +[7794] ChkCrR:pdata=new-mqtt-server,len=34 +[7794] ChkCrR:pdata=1883,len=6 +[7794] ChkCrR:pdata=default-mqtt-username,len=34 +[7794] ChkCrR:pdata=default-mqtt-password,len=34 +[7795] ChkCrR:pdata=default-mqtt-SubTopic,len=34 +[7795] ChkCrR:pdata=default-mqtt-PubTopic,len=34 +[7795] CrCCsum=0x280b,CrRCsum=0x280b +[7796] Buffer freed +[7797] LoadCredFile +[7797] OK +[7797] CrR:pdata=new-mqtt-server,len=34 +[7797] CrR:pdata=1883,len=6 +[7798] CrR:pdata=default-mqtt-username,len=34 +[7798] CrR:pdata=default-mqtt-password,len=34 +[7798] CrR:pdata=default-mqtt-SubTopic,len=34 +[7798] CrR:pdata=default-mqtt-PubTopic,len=34 +[7798] CrCCsum=0x280b,CrRCsum=0x280b +[7799] Valid Stored Dynamic Data +[7799] ======= Start Stored Config Data ======= +[7799] Hdr=ENC28J60,BName=nRF52_ENC +[7799] Svr=account.duckdns.org,Tok=token +[7799] Svr1=account.ddns.net,Tok1=n1u-uhfrc0chbmLRqSjl8SjphkGfHRTN +[7799] Prt=8080,SIP=192.168.2.188 +[7799] i=0,id=mqtt,data=new-mqtt-server +[7800] i=1,id=mqpt,data=1883 +[7800] i=2,id=user,data=default-mqtt-username +[7800] i=3,id=mqpw,data=default-mqtt-password +[7800] i=4,id=subs,data=default-mqtt-SubTopic +[7801] i=5,id=pubs,data=default-mqtt-PubTopic +[7801] MAC:FE-C6-B0-96-FE-B9 +ENC28J60_CONTROL_CS =10 +SS =5 +SPI_MOSI =25 +SPI_MISO =24 +SPI_SCK =26 +[8853] IP:192.168.2.188 +[8853] Check if isForcedCP +[8856] LoadCPFile +[8856] OK +[8856] bg: noConfigPortal = true +[8856] bg:ECon.TryB +[8856] + ___ __ __ + / _ )/ /_ _____ / /__ + / _ / / // / _ \/ '_/ + /____/_/\_, /_//_/_/\_\ + /___/ v0.6.1 on ARDUINO_NRF52_ADAFRUIT + +[8857] BlynkArduinoClient.connect: Connecting to account.duckdns.org:8080 +[10772] Ready (ping: 15ms). +[10839] Connected to Blynk Server = account.duckdns.org, Token = token +[10840] bg:EBCon +Local IP = 192.168.2.188 +Conn2Blynk: server = account.duckdns.org, port = 8080 +Token = token, IP = 192.168.2.188 +Stop doubleResetDetecting +Saving to DRD file : 0xd0d04321 +Saving DRD file OK +LittleFS Flag read = 0xd0d04321 +ClearFlag write = 0xd0d04321 +B +Your stored Credentials : +MQTT Server = new-mqtt-server Port = 1883 MQTT UserName = default-mqtt-username MQTT PWD = default-mqtt-password Subs Topics = default-mqtt-SubTopic Pubs Topics = default-mqtt-PubTopic +``` + +--- + +### 5. W5500_WM_Config_Teensy on TEENSY 4.0 with W5x00 using EthernetLarge Library + +The following is the sample terminal output when running example [W5500_WM_Config_Teensy](examples/W5500_WM_Config_Teensy) on TEENSY 4.1/4.0 with W5x00 using EthernetLarge Library +``` +Start W5500_WM_Config_Teensy on TEENSY 4.1/4.0 with W5x00 using EthernetLarge Library +BlynkEthernet_WM v1.2.0 +Warning: W5x00 and ENC EthernetWebServer/Config-Portal only works with Teensy core v1.51 +[16480] CCSum=0x28d0,RCSum=0x28d0 +[16486] ChkCrR:CrCCSum=0x280b,CrRCSum=0x280b +[16487] CrCCSum=0x280b,CrRCSum=0x280b +[16487] ======= Start Stored Config Data ======= +[16487] Hdr=W5X00,BName=Teensy_W5500 +[16487] Svr=account.duckdns.org,Tok=token +[16487] Svr1=account.duckdns.org,Tok1=token1 +[16487] Prt=8080,SIP= +[16487] MAC:FE-80-D6-B4-FC-EE +_pinCS = 0 +W5100 init, using SS_PIN_DEFAULT = 10, new ss_pin = 10, W5100Class::ss_pin = 10 +W5100::init: W5500, SSIZE =8192 +[20168] IP:192.168.2.156 +[20168] bg:ECon.TryB +[20168] + ___ __ __ + / _ )/ /_ _____ / /__ + / _ / / // / _ \/ '_/ + /____/_/\_, /_//_/_/\_\ + /___/ v0.6.1 on Teensy 4.1/4.0 + +[20169] BlynkArduinoClient.connect: Connecting to account.duckdns.org:8080 +[20279] Ready (ping: 7ms). +[20346] Connected to Blynk Server = account.duckdns.org, Token = token +[20346] bg:EBCon +Conn2Blynk: server = account.duckdns.org, port = 8080 +Token = token, IP = 192.168.2.156 +B +Your stored Credentials : +MQTT Server = new-mqtt-server +Port = 1883 +MQTT UserName = default-mqtt-username +MQTT PWD = default-mqtt-password +Subs Topics = default-mqtt-SubTopic +Pubs Topics = default-mqtt-PubTopic ``` +--- + +### 6. W5500_WM_Config on ESP8266 with W5x00 using EthernetLarge Library + +The following is the sample terminal output when running example [W5500_WM_Config](examples/W5500_WM_Config) on ESP8266 with W5x00 using EthernetLarge Library + +``` +Start W5500_WM_Config on ESP8266 with W5x00 using EthernetLarge Library +BlynkEthernet_WM v1.2.0 +EEPROM size = 2048, start = 0 +EEPROM Flag read = 0xD0D04321 +No doubleResetDetected +SetFlag write = 0xD0D01234 +[1311] EEPROMsz:2048 +[1311] CCSum=0x2b55,RCSum=0x2b55 +[1311] ChkCrR:CrCCsum=0x25dd,CrRCsum=0x25dd +[1311] CrCCsum=0x25dd,CrRCsum=0x25dd +[1313] ======= Start Stored Config Data ======= +[1318] Hdr=W5X00,BName=ESP8266_EEPROM +[1321] Svr=account.duckdns.org,Tok=token +[1327] Svr1=account.duckdns.org,Tok1=token1 +[1333] Prt=8080,SIP=192.168.2.188 +[1336] MAC:FE-C6-B0-96-FE-B9 + +W5100 init, using SS_PIN_DEFAULT = 15, new ss_pin = 10, W5100Class::ss_pin = 4 +W5100::init: W5500, SSIZE =8192 +[2921] IP:192.168.2.188 +[2921] bg:ECon.TryB +[2921] + ___ __ __ + / _ )/ /_ _____ / /__ + / _ / / // / _ \/ '_/ + /____/_/\_, /_//_/_/\_\ + /___/ v0.6.1 on NodeMCU + +[2927] BlynkArduinoClient.connect: Connecting to account.duckdns.org:8080 +[3043] Ready (ping: 5ms). +[3110] Connected to Blynk Server = account.duckdns.org, Token = token +[3110] bg:EBCon +Conn2Blynk: server = account.duckdns.org, port = 8080 +Token = token, IP = 192.168.2.188 +B +Your stored Credentials : +MQTT Server = default-mqtt-server +Port = 1883 +MQTT UserName = default-mqtt-user +MQTT PWD = default-mqtt-pwd +Subs Topics = default-mqtt-SubTopic +Pubs Topics = default-mqtt-PubTopic +Stop doubleResetDetecting +ClearFlag write = 0xD0D04321 +BBBBBBB +``` + + --- --- @@ -2313,6 +2712,12 @@ Sometimes, the library will only work if you update the board core to the latest ## Releases +### Major Releases v1.2.0 + +1. Fix Config Portal Bug. +2. Add functions to control Config Portal from software or Virtual Switches. Check [How to trigger a Config Portal from code #25](https://github.com/khoih-prog/Blynk_WM/issues/25) +3. Use more efficient [FlashStorage_SAMD v1.1.0](https://github.com/khoih-prog/FlashStorage_SAMD). + ### Major Releases v1.1.0 1. Add support to LittleFS for ESP32 using [LITTLEFS](https://github.com/lorol/LITTLEFS) Library diff --git a/keywords.txt b/keywords.txt index eaf856f4..cf9ea490 100644 --- a/keywords.txt +++ b/keywords.txt @@ -50,6 +50,8 @@ getHWPort KEYWORD2 getFullConfigData KEYWORD2 clearConfigData KEYWORD2 resetFunc KEYWORD2 +resetAndEnterConfigPortal KEYWORD2 +resetAndEnterConfigPortalPersistent KEYWORD2 ################# # Handler helpers diff --git a/library.json b/library.json index 0949a15a..f7659996 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "BlynkEthernet_Manager", - "version": "1.1.0", + "version": "1.2.0", "description": "Simple Ethernet Manager for MultiBlynk for Teensy, SAM DUE, SAMD21, SAMD51, nRF52, ESP32, ESP8266, etc. boards, with or without SSL, configuration data saved in ESP8266/ESP32 LittleFS, SPIFFS, nRF52 LittleFS/InternalFS, EEPROM, DueFlashStorage or SAMD FlashStorage. Library for configuring/auto(re)connecting Ethernet W5100/W5200/W5500, ENC28J60 or NativeEthernet shields to Ethernet and MultiBlynk at runtime. 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. DoubleDetectDetector is used to force Config Portal opening even if the Credentials are still valid. 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, SAM DUE, SAMD21, SAMD51, nRF52, Teensy.", "keywords": "sensors, control, device, smartphone, mobile, app, web, cloud, communication, protocol, iot, m2m, wifi, ble, bluetooth, ethernet, usb, serial, gsm, gprs, 3g, data, esp32, esp8266, samd21, samd51, nrf52, stm32, nano-33-iot, sam-due, eeprom, littlefs, spiffs, flash-storage, flash-storage-samd, http, W5500, W5x00, ENC28J60, nativeethernet, native-ethernet", "authors": @@ -33,7 +33,7 @@ { "owner": "khoih-prog", "name": "EthernetWebServer", - "version": ">=1.2.1", + "version": ">=1.3.0", "platforms": ["*"] }, { @@ -48,11 +48,23 @@ "version": "^1.0.3", "platforms": ["*"] }, + { + "owner": "khoih.prog", + "name": "FlashStorage_SAMD", + "version": "^1.1.0", + "platforms": ["*"] + }, { "owner": "khoih-prog", "name": "Functional-Vlpp", "version": "^1.0.1", "platforms": ["*"] + }, + { + "owner": "lorol", + "name": "LittleFS_esp32", + "version": ">=1.0.5", + "platforms": ["espressif32"] } ], "frameworks": "*", diff --git a/library.properties b/library.properties index 50264c81..f141f5b8 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=BlynkEthernet_Manager -version=1.1.0 +version=1.2.0 author=Khoi Hoang license=MIT maintainer=Khoi Hoang @@ -8,4 +8,4 @@ paragraph=Library for configuring/auto(re)connecting Ethernet W5100/W5200/W5500, category=Communication url=https://github.com/khoih-prog/BlynkEthernet_WM architectures=* -depends=Blynk,EthernetWebServer,DoubleResetDetector_Generic,ESP_DoubleResetDetector,Functional-Vlpp +depends=Blynk,EthernetWebServer,DoubleResetDetector_Generic,ESP_DoubleResetDetector,Functional-Vlpp,FlashStorage_SAMD,LittleFS_esp32 diff --git a/platformio/platformio.ini b/platformio/platformio.ini index 731bb852..7ae746ee 100644 --- a/platformio/platformio.ini +++ b/platformio/platformio.ini @@ -32,16 +32,18 @@ upload_speed = 921600 lib_deps = ; PlatformIO 4.x Blynk@>=0.6.1 - EthernetWebServer@>=1.2.1 + EthernetWebServer@>=1.3.0 ESP_DoubleResetDetector@>=1.1.1 DoubleResetDetector_Generic@>=1.0.3 Functional-Vlpp@>=1.0.1 + FlashStorage_SAMD@>=1.1.0 ; PlatformIO 5.x ; blynkkk/Blynk@>=0.6.1 -; khoih-prog/EthernetWebServer@>=1.2.1 +; khoih-prog/EthernetWebServer@>=1.3.0 ; khoih.prog/ESP_DoubleResetDetector@>=1.1.1 ; khoih-prog/DoubleResetDetector_Generic@>=1.0.3 ; khoih-prog/Functional-Vlpp@>=1.0.1 +; khoih.prog/FlashStorage_SAMD@>=1.1.0 build_flags = ; set your debug output (default=Serial) diff --git a/src/Adapters/BlynkEthernetENC.h b/src/Adapters/BlynkEthernetENC.h index 51c23d8f..389f70ec 100644 --- a/src/Adapters/BlynkEthernetENC.h +++ b/src/Adapters/BlynkEthernetENC.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,13 +38,14 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkEthernetENC_h #define BlynkEthernetENC_h #ifndef BLYNK_INFO_CONNECTION -#define BLYNK_INFO_CONNECTION "ENC28J60" + #define BLYNK_INFO_CONNECTION "ENC28J60" #endif #ifdef BLYNK_USE_SSL diff --git a/src/Adapters/BlynkEthernet_DUE_WM.h b/src/Adapters/BlynkEthernet_DUE_WM.h index 743722bc..06eb6ec9 100644 --- a/src/Adapters/BlynkEthernet_DUE_WM.h +++ b/src/Adapters/BlynkEthernet_DUE_WM.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,6 +38,7 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkEthernet_DUE_WM_h @@ -115,13 +116,20 @@ typedef struct } MenuItem; // -///NEW -extern uint16_t NUM_MENU_ITEMS; -extern MenuItem myMenuItems []; +#if USE_DYNAMIC_PARAMETERS + extern uint16_t NUM_MENU_ITEMS; + extern MenuItem myMenuItems []; + bool *menuItemUpdated = NULL; +#endif + +#define HEADER_MAX_LEN 16 #define BLYNK_SERVER_MAX_LEN 32 #define BLYNK_TOKEN_MAX_LEN 36 +#define STATIC_IP_MAX_LEN 16 +#define BOARD_NAME_MAX_LEN 24 + typedef struct { char blynk_server[BLYNK_SERVER_MAX_LEN]; @@ -135,11 +143,11 @@ typedef struct typedef struct Configuration { - char header [16]; + char header [HEADER_MAX_LEN]; Blynk_Credentials Blynk_Creds [NUM_BLYNK_CREDENTIALS]; int blynk_port; - char static_IP [16]; - char board_name [24]; + char static_IP [STATIC_IP_MAX_LEN]; + char board_name [BOARD_NAME_MAX_LEN]; int checkSum; } Blynk_Configuration; @@ -350,8 +358,7 @@ class BlynkEthernet #define LED_ON HIGH void begin() - { - + { //Turn OFF pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LED_OFF); @@ -368,21 +375,31 @@ class BlynkEthernet noConfigPortal = false; } //// New DRD //// -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("======= Start Default Config Data =======")); - displayConfigData(defaultConfig); + +#if ( BLYNK_WM_DEBUG > 2) + if (LOAD_DEFAULT_CONFIG_DATA) + { + BLYNK_LOG1(BLYNK_F("======= Start Default Config Data =======")); + displayConfigData(defaultConfig); + } #endif hadConfigData = getConfigData(); connectEthernet(); - //// New DRD //// - // noConfigPortal when getConfigData() OK and no DRD'ed - if (hadConfigData && noConfigPortal) - //// New DRD //// + isForcedConfigPortal = isForcedCP(); + + //// New DRD/MRD //// + // noConfigPortal when getConfigData() OK and no MRD/DRD'ed + //if (getConfigData() && noConfigPortal) + if (hadConfigData && noConfigPortal && (!isForcedConfigPortal) ) { hadConfigData = true; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(noConfigPortal? BLYNK_F("bg: noConfigPortal = true") : BLYNK_F("bg: noConfigPortal = false")); +#endif if (ethernetConnected) { @@ -413,9 +430,22 @@ class BlynkEthernet } } else - { - BLYNK_LOG2(BLYNK_F("b:Stay in CfgPortal:"), noConfigPortal ? BLYNK_F("No CfgDat") : BLYNK_F("DRD")); - + { +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(isForcedConfigPortal? BLYNK_F("bg: isForcedConfigPortal = true") : BLYNK_F("bg: isForcedConfigPortal = false")); +#endif + + // If not persistent => clear the flag so that after reset. no more CP, even CP not entered and saved + if (persForcedConfigPortal) + { + BLYNK_LOG2(BLYNK_F("bg:Stay forever in CP:"), isForcedConfigPortal ? BLYNK_F("Forced-Persistent") : (noConfigPortal ? BLYNK_F("No ConfigDat") : BLYNK_F("DRD/MRD"))); + } + else + { + BLYNK_LOG2(BLYNK_F("bg:Stay forever in CP:"), isForcedConfigPortal ? BLYNK_F("Forced-non-Persistent") : (noConfigPortal ? BLYNK_F("No ConfigDat") : BLYNK_F("DRD/MRD"))); + clearForcedCP(); + } + // failed to connect to Blynk server, will start configuration mode hadConfigData = false; startConfigurationMode(); @@ -576,6 +606,45 @@ class BlynkEthernet //EEPROM.put(BLYNK_EEPROM_START, BlynkEthernet_WM_config); saveConfigData(); } + + // Forced CP => Flag = 0xBEEFBEEF. Else => No forced CP + // Flag to be stored at (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // to avoid corruption to current data + //#define FORCED_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xDEADBEEF) + //#define FORCED_PERS_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xBEEFDEAD) + + const uint32_t FORCED_CONFIG_PORTAL_FLAG_DATA = 0xDEADBEEF; + const uint32_t FORCED_PERS_CONFIG_PORTAL_FLAG_DATA = 0xBEEFDEAD; + + #define FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE 4 + + void resetAndEnterConfigPortal() + { + persForcedConfigPortal = false; + + setForcedCP(false); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + // This will keep CP forever, until you successfully enter CP, and Save data to clear the flag. + void resetAndEnterConfigPortalPersistent() + { + persForcedConfigPortal = true; + + setForcedCP(true); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + void resetFunc() + { + BlynkReset(); + } private: @@ -590,6 +659,9 @@ class BlynkEthernet unsigned long configTimeout; bool hadConfigData = false; + + bool isForcedConfigPortal = false; + bool persForcedConfigPortal = false; Blynk_Configuration BlynkEthernet_WM_config; @@ -669,8 +741,8 @@ class BlynkEthernet uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; #ifndef EEPROM_START -#define EEPROM_START 0 -#warning EEPROM_START not defined. Set to 0 + #define EEPROM_START 0 + #warning EEPROM_START not defined. Set to 0 #endif // Stating positon to store Blynk8266_WM_config @@ -679,6 +751,7 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; int calcChecksum() { int checkSum = 0; + for (uint16_t index = 0; index < (sizeof(BlynkEthernet_WM_config) - sizeof(BlynkEthernet_WM_config.checkSum)); index++) { checkSum += * ( ( (byte*) &BlynkEthernet_WM_config ) + index); @@ -686,11 +759,79 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; return checkSum; } + + ////////////////////////////////////////////// + + void saveForcedCP(uint32_t value) + { + uint32_t readForcedConfigPortalFlag = value; - bool checkDynamicData() + uint16_t offset = BLYNK_EEPROM_START + CONFIG_DATA_SIZE; + + dueFlashStorageData.write(offset, (byte *) &readForcedConfigPortalFlag, sizeof(readForcedConfigPortalFlag)); + + //EEPROM.put(BLYNK_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag); + } + + void setForcedCP(bool isPersistent) { -#if USE_DYNAMIC_PARAMETERS + uint32_t readForcedConfigPortalFlag = isPersistent? FORCED_PERS_CONFIG_PORTAL_FLAG_DATA : FORCED_CONFIG_PORTAL_FLAG_DATA; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(isPersistent ? BLYNK_F("setForcedCP Persistent") : BLYNK_F("setForcedCP non-Persistent")); +#endif + + saveForcedCP(readForcedConfigPortalFlag); + } + void clearForcedCP() + { + uint32_t readForcedConfigPortalFlag = 0; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("clearForcedCP")); +#endif + + saveForcedCP(readForcedConfigPortalFlag); + } + + bool isForcedCP() + { + uint32_t readForcedConfigPortalFlag; + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + uint16_t offset = BLYNK_EEPROM_START + CONFIG_DATA_SIZE; + + byte* dataPointer = (byte* ) dueFlashStorageData.readAddress(offset); + + memcpy(&readForcedConfigPortalFlag, dataPointer, sizeof(readForcedConfigPortalFlag)); + //EEPROM.get(BLYNK_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag); + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + if (readForcedConfigPortalFlag == FORCED_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = false; + return true; + } + else if (readForcedConfigPortalFlag == FORCED_PERS_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = true; + return true; + } + else + { + return false; + } + } + + ////////////////////////////////////////////// + +#if USE_DYNAMIC_PARAMETERS + + bool checkDynamicData() + { int checkSum = 0; int readCheckSum; @@ -702,7 +843,7 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; #define BIG_BUFFER_LEN 768 byte bigBuffer[BIG_BUFFER_LEN + 1]; - uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config); + uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; // Make address 4-byte aligned if ( (offset % 4) != 0 ) @@ -715,14 +856,14 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; // We dont like to destroy myMenuItems[i].pdata with invalid data int totalLength = 0; - for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + for (int i = 0; i < NUM_MENU_ITEMS; i++) { totalLength += myMenuItems[i].maxlen; - if ( (totalLength > BIG_BUFFER_LEN) ) + if ( (totalLength > BIG_BUFFER_LEN) || (myMenuItems[i].maxlen > BIG_BUFFER_LEN) ) { // Size too large, abort and flag false - BLYNK_LOG1(BLYNK_F("ChkCrR: Error Small Buffer.")); + BLYNK_LOG1(F("ChkCrR: Error Small Buffer.")); return false; } } @@ -737,7 +878,7 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; // Don't need readBuffer // Now to split into individual piece to add to CSum - for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + for (int i = 0; i < NUM_MENU_ITEMS; i++) { char* _pointer = (char*) bigBuffer; @@ -751,26 +892,21 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; memcpy(&readCheckSum, &bigBuffer[byteCount], sizeof(readCheckSum)); - BLYNK_LOG4(F("ChkCrR:CrCCSum=0x"), String(checkSum, HEX), F(",CrRCSum=0x"), String(readCheckSum, HEX)); + BLYNK_LOG4(F("ChkCrR:CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum ) { return false; } -#endif return true; } - - bool dueFlashStorage_get() - { - uint16_t offset = BLYNK_EEPROM_START; - - byte* dataPointer = (byte* ) dueFlashStorageData.readAddress(offset); - - memcpy(&BlynkEthernet_WM_config, dataPointer, sizeof(BlynkEthernet_WM_config)); - - offset += sizeof(BlynkEthernet_WM_config); + + ////////////////////////////////////////////// + + bool dueFlashStorage_getDynamicData() + { + uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; // Make address 4-byte aligned if ( (offset % 4) != 0 ) @@ -783,16 +919,16 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; uint16_t byteCount = 0; - byte buffer[768]; + #define BIG_BUFFER_LEN 768 + byte buffer[BIG_BUFFER_LEN + 1]; - dataPointer = (byte* ) dueFlashStorageData.readAddress(offset); + byte* dataPointer = (byte* ) dueFlashStorageData.readAddress(offset); memcpy(buffer, dataPointer, sizeof(buffer)); totalDataSize = sizeof(BlynkEthernet_WM_config) + sizeof(readCheckSum); - -#if USE_DYNAMIC_PARAMETERS - for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + + for (int i = 0; i < NUM_MENU_ITEMS; i++) { char* _pointer = myMenuItems[i].pdata; totalDataSize += myMenuItems[i].maxlen; @@ -805,15 +941,14 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; *_pointer = buffer[byteCount]; checkSum += *_pointer; - } + } } -#endif memcpy(&readCheckSum, &buffer[byteCount], sizeof(readCheckSum)); byteCount += sizeof(readCheckSum); - BLYNK_LOG6(F("CrCCSum=0x"), String(checkSum, HEX), F(",CrRCSum=0x"), String(readCheckSum, HEX), + BLYNK_LOG6(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX), F(",TotalDataSz="), totalDataSize); if ( checkSum != readCheckSum) @@ -822,15 +957,13 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; } return true; - } + } - void dueFlashStorage_put() - { - uint16_t offset = BLYNK_EEPROM_START; - - dueFlashStorageData.write(offset, (byte *) &BlynkEthernet_WM_config, sizeof(BlynkEthernet_WM_config)); - - offset += sizeof(BlynkEthernet_WM_config); + ////////////////////////////////////////////// + + void dueFlashStorage_putDynamicData() + { + uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; // Make address 4-byte aligned if ( (offset % 4) != 0 ) @@ -844,25 +977,25 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; // Use 2K buffer, if need more memory, can reduce this byte buffer[2048]; -#if USE_DYNAMIC_PARAMETERS - for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + 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 ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG4(F("pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); +#endif for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++, _pointer++, /*offset++,*/ byteCount++) { if (byteCount >= sizeof(buffer)) { - BLYNK_LOG2(BLYNK_F("Danger:dynamic data too long >"), sizeof(buffer)); + BLYNK_LOG2(F("Danger:dynamic data too long >"), sizeof(buffer)); } buffer[byteCount] = *_pointer; checkSum += *_pointer; } } -#endif memcpy(&buffer[byteCount], &checkSum, sizeof(checkSum)); @@ -872,6 +1005,70 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; BLYNK_LOG4(F("CrCCSum=0x"), String(checkSum, HEX), F(",byteCount="), byteCount); } +#endif + + ////////////////////////////////////////////// + + void NULLTerminateConfig() + { + //#define HEADER_MAX_LEN 16 + //#define BLYNK_SERVER_MAX_LEN 32 + //#define BLYNK_TOKEN_MAX_LEN 36 + //#define STATIC_IP_MAX_LEN 16 + //#define BOARD_NAME_MAX_LEN 24 + + // NULL Terminating to be sure + BlynkEthernet_WM_config.header[HEADER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server[BLYNK_SERVER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token [BLYNK_TOKEN_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server[BLYNK_SERVER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token [BLYNK_TOKEN_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.blynk_port = BLYNK_SERVER_HARDWARE_PORT; + BlynkEthernet_WM_config.static_IP[STATIC_IP_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.board_name [BOARD_NAME_MAX_LEN - 1] = 0; + } + + ////////////////////////////////////////////// + + bool dueFlashStorage_get() + { + uint16_t offset = BLYNK_EEPROM_START; + + byte* dataPointer = (byte* ) dueFlashStorageData.readAddress(offset); + + memcpy(&BlynkEthernet_WM_config, dataPointer, sizeof(BlynkEthernet_WM_config)); + + NULLTerminateConfig(); + + return true; + } + + ////////////////////////////////////////////// + + void dueFlashStorage_put() + { + uint16_t offset = BLYNK_EEPROM_START; + + dueFlashStorageData.write(offset, (byte *) &BlynkEthernet_WM_config, sizeof(BlynkEthernet_WM_config)); + } + + ////////////////////////////////////////////// + + void saveConfigData() + { + int calChecksum = calcChecksum(); + BlynkEthernet_WM_config.checkSum = calChecksum; + + BLYNK_LOG4(F("SaveData,Sz="), totalDataSize, F(",chkSum=0x"), String(calChecksum, HEX)); + + dueFlashStorage_put(); + +#if USE_DYNAMIC_PARAMETERS + dueFlashStorage_putDynamicData(); +#endif + } + + ////////////////////////////////////////////// void loadAndSaveDefaultConfigData() { @@ -888,15 +1085,17 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; #endif } + ////////////////////////////////////////////// + bool getConfigData() { - bool dynamicDataValid; + bool dynamicDataValid = true; int calChecksum; hadConfigData = false; // For DUE, DATA_LENGTH = ((IFLASH1_PAGE_SIZE/sizeof(byte))*4) = 1KBytes - BLYNK_LOG2(F("Simulate EEPROM, sz:"), DATA_LENGTH); + BLYNK_LOG2(F("Simulate EEPROM,Sz="), DATA_LENGTH); // Use new LOAD_DEFAULT_CONFIG_DATA logic if (LOAD_DEFAULT_CONFIG_DATA) @@ -911,47 +1110,58 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; { // Load stored config / dynamic data from dueFlashStorage // Verify ChkSum - //dynamicDataValid = dueFlashStorage_get(); - dynamicDataValid = checkDynamicData(); - + dueFlashStorage_get(); + calChecksum = calcChecksum(); BLYNK_LOG4(BLYNK_F("CCSum=0x"), String(calChecksum, HEX), BLYNK_F(",RCSum=0x"), String(BlynkEthernet_WM_config.checkSum, HEX)); - if (dynamicDataValid) - { - dueFlashStorage_get(); - -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("Valid Stored Dynamic Data")); -#endif - BLYNK_LOG1(BLYNK_F("======= Start Stored Config Data =======")); - displayConfigData(BlynkEthernet_WM_config); - - // Don't need Config Portal anymore - return true; - } - else +#if USE_DYNAMIC_PARAMETERS + // Load stored dynamic data from dueFlashStorage + dynamicDataValid = checkDynamicData(); +#endif + // If checksum = 0 => DueFlashStorage has been cleared (by uploading new FW, etc) => force to CP + // If bad checksum = 0 => force to CP + if ( (calChecksum != 0) && (calChecksum == BlynkEthernet_WM_config.checkSum) ) { - // Invalid Stored config data => Config Portal - BLYNK_LOG1(BLYNK_F("Invalid Stored Dynamic Data. Load default from Sketch")); - - // Load Default Config Data from Sketch, better than just "blank" - loadAndSaveDefaultConfigData(); - - // Need Config Portal here as data can be just dummy - // Even if you don't open CP, you're OK on next boot if your default config data is valid - return false; - } - } - + if (dynamicDataValid) + { + #if USE_DYNAMIC_PARAMETERS + dueFlashStorage_getDynamicData(); + + #if ( BLYNK_WM_DEBUG > 2 ) + BLYNK_LOG1(BLYNK_F("Valid Stored Dynamic Data")); + #endif + #endif + BLYNK_LOG1(BLYNK_F("======= Start Stored Config Data =======")); + displayConfigData(BlynkEthernet_WM_config); + + // Don't need Config Portal anymore + return true; + } + else + { + // Invalid Stored config data => Config Portal + BLYNK_LOG1(BLYNK_F("Invalid Stored Dynamic Data. Load default from Sketch")); + + // Load Default Config Data from Sketch, better than just "blank" + loadAndSaveDefaultConfigData(); + + // Need Config Portal here as data can be just dummy + // Even if you don't open CP, you're OK on next boot if your default config data is valid + return false; + } + } + } + if ( (strncmp(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE, strlen(BLYNK_BOARD_TYPE)) != 0) || - (calChecksum != BlynkEthernet_WM_config.checkSum) || !dynamicDataValid ) + (calChecksum != BlynkEthernet_WM_config.checkSum) || !dynamicDataValid || + ( (calChecksum == 0) && (BlynkEthernet_WM_config.checkSum == 0) ) ) { // Including Credentials CSum - BLYNK_LOG2(F("InitEEPROM,Datasz="), totalDataSize); - + BLYNK_LOG2(F("InitCfgFile,Sz="), sizeof(BlynkEthernet_WM_config)); + // doesn't have any configuration if (LOAD_DEFAULT_CONFIG_DATA) { @@ -970,7 +1180,7 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; #endif // Including Credentials CSum - BLYNK_LOG2(F("InitEEPROM,Datasz="), totalDataSize); + BLYNK_LOG2(BLYNK_F("InitCfgFile,DataSz="), totalDataSize); // doesn't have any configuration strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, WM_NO_CONFIG); @@ -981,27 +1191,27 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; strcpy(BlynkEthernet_WM_config.static_IP, WM_NO_CONFIG); strcpy(BlynkEthernet_WM_config.board_name, WM_NO_CONFIG); -#if USE_DYNAMIC_PARAMETERS +#if USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { strncpy(myMenuItems[i].pdata, WM_NO_CONFIG, myMenuItems[i].maxlen); } #endif } - + strcpy(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE); - - #if (USE_DYNAMIC_PARAMETERS && ( BLYNK_WM_DEBUG > 2)) + +#if ( BLYNK_WM_DEBUG > 2) && USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { BLYNK_LOG4(BLYNK_F("g:myMenuItems["), i, BLYNK_F("]="), myMenuItems[i].pdata ); } - #endif +#endif // Don't need BlynkEthernet_WM_config.checkSum = 0; - dueFlashStorage_put(); + saveConfigData(); return false; } @@ -1020,16 +1230,8 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; return true; } - - void saveConfigData() - { - int calChecksum = calcChecksum(); - BlynkEthernet_WM_config.checkSum = calChecksum; - - BLYNK_LOG4(F("SaveData,sz="), totalDataSize, F(",WCSum=0x"), String(calChecksum, HEX)); - - dueFlashStorage_put(); - } + + ////////////////////////////////////////////// bool connectMultiBlynk() { @@ -1054,6 +1256,8 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; return false; } + + ////////////////////////////////////////////// // NEW void createHTML(String& root_html_template) @@ -1102,7 +1306,8 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; return; } - //// + + ////////////////////////////////////////////// void handleRequest() { @@ -1167,87 +1372,136 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; strcpy(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE); } - if (key == "sv") +#if USE_DYNAMIC_PARAMETERS + if (!menuItemUpdated) + { + // Don't need to free + menuItemUpdated = new bool[NUM_MENU_ITEMS]; + + if (menuItemUpdated) + { + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + // To flag item is not yet updated + menuItemUpdated[i] = false; + } + #if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("h: Init menuItemUpdated" )); + #endif + } + else + { + BLYNK_LOG1(BLYNK_F("h: Error can't alloc memory for menuItemUpdated" )); + } + } +#endif + + static bool sv_Updated = false; + static bool tk_Updated = false; + static bool sv1_Updated = false; + static bool tk1_Updated = false; + static bool pt_Updated = false; + static bool ip_Updated = false; + static bool nm_Updated = false; + + //if (key == "sv") + if (!sv_Updated && (key == String("sv"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:sv")); #endif + sv_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server) - 1); } - else if (key == "tk") + else if (!tk_Updated && (key == String("tk"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:tk")); #endif + tk_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token) - 1); } - else if (key == "sv1") + else if (!sv1_Updated && (key == String("sv1"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:sv1")); #endif + sv1_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server) - 1); } - else if (key == "tk1") + else if (!tk1_Updated && (key == String("tk1"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:tk1")); #endif + tk1_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token) - 1); } - else if (key == "pt") + else if (!pt_Updated && (key == String("pt"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:pt")); #endif + pt_Updated = true; number_items_Updated++; BlynkEthernet_WM_config.blynk_port = value.toInt(); } - else if (key == "ip") + else if (!ip_Updated && (key == String("ip"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:ip")); #endif + ip_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.static_IP) - 1) strcpy(BlynkEthernet_WM_config.static_IP, value.c_str()); else strncpy(BlynkEthernet_WM_config.static_IP, value.c_str(), sizeof(BlynkEthernet_WM_config.static_IP) - 1); } - else if (key == "nm") + else if (!nm_Updated && (key == String("nm"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:nm")); #endif + nm_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.board_name) - 1) strcpy(BlynkEthernet_WM_config.board_name, value.c_str()); else strncpy(BlynkEthernet_WM_config.board_name, value.c_str(), sizeof(BlynkEthernet_WM_config.board_name) - 1); } -#if USE_DYNAMIC_PARAMETERS +#if USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - if (key == myMenuItems[i].id) + if ( !menuItemUpdated[i] && (key == myMenuItems[i].id) ) { - //BLYNK_LOG4(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); + BLYNK_LOG4(BLYNK_F("h:"), myMenuItems[i].id, BLYNK_F("="), value.c_str() ); + + menuItemUpdated[i] = true; + number_items_Updated++; // Actual size of pdata is [maxlen + 1] @@ -1257,28 +1511,32 @@ uint16_t EEPROM_SIZE = (IFLASH1_PAGE_SIZE / sizeof(byte)) * 4; strcpy(myMenuItems[i].pdata, value.c_str()); else strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); - -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG4(BLYNK_F("h2:myMenuItems["), i, BLYNK_F("]="), myMenuItems[i].pdata ); -#endif } } #endif -#if (BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("h:OK")); -#endif + //#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG2(F("h:items updated ="), number_items_Updated); + BLYNK_LOG4(F("h:key ="), key, ", value =", value); + //#endif server->send(200, "text/html", "OK"); - // NEW +#if USE_DYNAMIC_PARAMETERS if (number_items_Updated == NUM_CONFIGURABLE_ITEMS + NUM_MENU_ITEMS) +#else + if (number_items_Updated == NUM_CONFIGURABLE_ITEMS) +#endif { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:UpdEEPROM")); #endif saveConfigData(); + + // Done with CP, Clear CP Flag here if forced + if (isForcedConfigPortal) + clearForcedCP(); #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:Rst")); diff --git a/src/Adapters/BlynkEthernet_ESP32_WM.h b/src/Adapters/BlynkEthernet_ESP32_WM.h index e54f1a03..0d4f168c 100644 --- a/src/Adapters/BlynkEthernet_ESP32_WM.h +++ b/src/Adapters/BlynkEthernet_ESP32_WM.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,6 +38,7 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkEthernet_ESP32_WM_h @@ -68,13 +69,32 @@ #include #include -//default to use EEPROM, otherwise, use SPIFFS -#if USE_SPIFFS -#include -#include "SPIFFS.h" -#define FileFS SPIFFS +// LittleFS has higher priority than SPIFFS. +// But if not specified any, use SPIFFS to not forcing user to install LITTLEFS library +//#if ! (defined(USE_LITTLEFS) || defined(USE_SPIFFS) ) +// #define USE_SPIFFS true +//#endif + +#if USE_LITTLEFS + // Use LittleFS + #include "FS.h" + + // The library will be depreciated after being merged to future major Arduino esp32 core release 2.x + // At that time, just remove this library inclusion + #include // https://github.com/lorol/LITTLEFS + + FS* filesystem = &LITTLEFS; + #define FileFS LITTLEFS + #warning Using LittleFS in BlynkEthernet_ESP32_WM.h +#elif USE_SPIFFS + #include "FS.h" + #include + FS* filesystem = &SPIFFS; + #define FileFS SPIFFS + #warning Using SPIFFS in BlynkEthernet_ESP32_WM.h #else -#include + #include + #warning Using EEPROM in BlynkEthernet_ESP32_WM.h #endif ///////// NEW for DRD ///////////// @@ -85,16 +105,22 @@ // Otherwise, library will use default EEPROM storage #define ESP8266_DRD_USE_RTC false //true -#if USE_SPIFFS -#define ESP_DRD_USE_EEPROM false -#define ESP_DRD_USE_SPIFFS true +#if USE_LITTLEFS + #define ESP_DRD_USE_LITTLEFS true + #define ESP_DRD_USE_SPIFFS false + #define ESP_DRD_USE_EEPROM false +#elif USE_SPIFFS + #define ESP_DRD_USE_LITTLEFS false + #define ESP_DRD_USE_SPIFFS true + #define ESP_DRD_USE_EEPROM false #else -#define ESP_DRD_USE_EEPROM true -#define ESP_DRD_USE_SPIFFS false + #define ESP_DRD_USE_LITTLEFS false + #define ESP_DRD_USE_SPIFFS false + #define ESP_DRD_USE_EEPROM true #endif #ifndef DOUBLERESETDETECTOR_DEBUG -#define DOUBLERESETDETECTOR_DEBUG false + #define DOUBLERESETDETECTOR_DEBUG false #endif #include //https://github.com/khoih-prog/ESP_DoubleResetDetector @@ -127,13 +153,20 @@ typedef struct } MenuItem; // -///NEW -extern uint16_t NUM_MENU_ITEMS; -extern MenuItem myMenuItems []; +#if USE_DYNAMIC_PARAMETERS + extern uint16_t NUM_MENU_ITEMS; + extern MenuItem myMenuItems []; + bool *menuItemUpdated = NULL; +#endif + +#define HEADER_MAX_LEN 16 #define BLYNK_SERVER_MAX_LEN 32 #define BLYNK_TOKEN_MAX_LEN 36 +#define STATIC_IP_MAX_LEN 16 +#define BOARD_NAME_MAX_LEN 24 + typedef struct { char blynk_server[BLYNK_SERVER_MAX_LEN]; @@ -147,11 +180,11 @@ typedef struct typedef struct Configuration { - char header [16]; + char header [HEADER_MAX_LEN]; Blynk_Credentials Blynk_Creds [NUM_BLYNK_CREDENTIALS]; int blynk_port; - char static_IP [16]; - char board_name [24]; + char static_IP [STATIC_IP_MAX_LEN]; + char board_name [BOARD_NAME_MAX_LEN]; int checkSum; } Blynk_Configuration; @@ -363,14 +396,14 @@ class BlynkEthernet #define LED_ON HIGH void begin() - { - + { //Turn OFF pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LED_OFF); //// New DRD //// - drd = new DoubleResetDetector(DRD_TIMEOUT, DRD_ADDRESS); + drd = new DoubleResetDetector(DRD_TIMEOUT, DRD_ADDRESS); + bool noConfigPortal = true; if (drd->detectDoubleReset()) @@ -381,21 +414,31 @@ class BlynkEthernet noConfigPortal = false; } //// New DRD //// -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("======= Start Default Config Data =======")); - displayConfigData(defaultConfig); + +#if ( BLYNK_WM_DEBUG > 2) + if (LOAD_DEFAULT_CONFIG_DATA) + { + BLYNK_LOG1(BLYNK_F("======= Start Default Config Data =======")); + displayConfigData(defaultConfig); + } #endif hadConfigData = getConfigData(); connectEthernet(); - //// New DRD //// - // noConfigPortal when getConfigData() OK and no DRD'ed - if (hadConfigData && noConfigPortal) - //// New DRD //// + isForcedConfigPortal = isForcedCP(); + + //// New DRD/MRD //// + // noConfigPortal when getConfigData() OK and no MRD/DRD'ed + //if (getConfigData() && noConfigPortal) + if (hadConfigData && noConfigPortal && (!isForcedConfigPortal) ) { hadConfigData = true; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(noConfigPortal? BLYNK_F("bg: noConfigPortal = true") : BLYNK_F("bg: noConfigPortal = false")); +#endif if (ethernetConnected) { @@ -426,9 +469,22 @@ class BlynkEthernet } } else - { - BLYNK_LOG2(BLYNK_F("b:Stay in CfgPortal:"), noConfigPortal ? BLYNK_F("No CfgDat") : BLYNK_F("DRD")); - + { +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(isForcedConfigPortal? BLYNK_F("bg: isForcedConfigPortal = true") : BLYNK_F("bg: isForcedConfigPortal = false")); +#endif + + // If not persistent => clear the flag so that after reset. no more CP, even CP not entered and saved + if (persForcedConfigPortal) + { + BLYNK_LOG2(BLYNK_F("bg:Stay forever in CP:"), isForcedConfigPortal ? BLYNK_F("Forced-Persistent") : (noConfigPortal ? BLYNK_F("No ConfigDat") : BLYNK_F("DRD/MRD"))); + } + else + { + BLYNK_LOG2(BLYNK_F("bg:Stay forever in CP:"), isForcedConfigPortal ? BLYNK_F("Forced-non-Persistent") : (noConfigPortal ? BLYNK_F("No ConfigDat") : BLYNK_F("DRD/MRD"))); + clearForcedCP(); + } + // failed to connect to Blynk server, will start configuration mode hadConfigData = false; startConfigurationMode(); @@ -588,10 +644,43 @@ class BlynkEthernet } #endif - //EEPROM.put(BLYNK_EEPROM_START, BlynkEthernet_WM_config); saveConfigData(); } + // Forced CP => Flag = 0xBEEFBEEF. Else => No forced CP + // Flag to be stored at (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // to avoid corruption to current data + //#define FORCED_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xDEADBEEF) + //#define FORCED_PERS_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xBEEFDEAD) + + const uint32_t FORCED_CONFIG_PORTAL_FLAG_DATA = 0xDEADBEEF; + const uint32_t FORCED_PERS_CONFIG_PORTAL_FLAG_DATA = 0xBEEFDEAD; + + #define FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE 4 + + void resetAndEnterConfigPortal() + { + persForcedConfigPortal = false; + + setForcedCP(false); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + // This will keep CP forever, until you successfully enter CP, and Save data to clear the flag. + void resetAndEnterConfigPortalPersistent() + { + persForcedConfigPortal = true; + + setForcedCP(true); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + void resetFunc() { delay(1000); @@ -611,6 +700,9 @@ class BlynkEthernet unsigned long configTimeout; bool hadConfigData = false; + + bool isForcedConfigPortal = false; + bool persForcedConfigPortal = false; Blynk_Configuration BlynkEthernet_WM_config; @@ -698,7 +790,7 @@ class BlynkEthernet return checkSum; } -#if USE_SPIFFS +#if ( USE_LITTLEFS || USE_SPIFFS ) #define CONFIG_FILENAME BLYNK_F("/wm_config.dat") #define CONFIG_FILENAME_BACKUP BLYNK_F("/wm_config.bak") @@ -706,13 +798,131 @@ class BlynkEthernet #define CREDENTIALS_FILENAME BLYNK_F("/wm_cred.dat") #define CREDENTIALS_FILENAME_BACKUP BLYNK_F("/wm_cred.bak") - bool checkDynamicData() +#define CONFIG_PORTAL_FILENAME BLYNK_F("/wm_cp.dat") +#define CONFIG_PORTAL_FILENAME_BACKUP BLYNK_F("/wm_cp.bak") + + ////////////////////////////////////////////// + + void saveForcedCP(uint32_t value) { -#if USE_DYNAMIC_PARAMETERS + File file = FileFS.open(CONFIG_PORTAL_FILENAME, "w"); + + BLYNK_LOG1(BLYNK_F("SaveCPFile ")); + + if (file) + { + file.write((uint8_t*) &value, sizeof(value)); + file.close(); + BLYNK_LOG1(BLYNK_F("OK")); + } + else + { + BLYNK_LOG1(BLYNK_F("failed")); + } + + // Trying open redundant CP file + file = FileFS.open(CONFIG_PORTAL_FILENAME_BACKUP, "w"); + + BLYNK_LOG1(BLYNK_F("SaveBkUpCPFile ")); + + if (file) + { + file.write((uint8_t *) &value, sizeof(value)); + file.close(); + BLYNK_LOG1(BLYNK_F("OK")); + } + else + { + BLYNK_LOG1(BLYNK_F("failed")); + } + } + + ////////////////////////////////////////////// + + void setForcedCP(bool isPersistent) + { + uint32_t readForcedConfigPortalFlag = isPersistent? FORCED_PERS_CONFIG_PORTAL_FLAG_DATA : FORCED_CONFIG_PORTAL_FLAG_DATA; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(isPersistent ? BLYNK_F("setForcedCP Persistent") : BLYNK_F("setForcedCP non-Persistent")); +#endif + + saveForcedCP(readForcedConfigPortalFlag); + } + + ////////////////////////////////////////////// + void clearForcedCP() + { + uint32_t readForcedConfigPortalFlag = 0; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("clearForcedCP")); +#endif + + saveForcedCP(readForcedConfigPortalFlag); + } + + ////////////////////////////////////////////// + + bool isForcedCP() + { + uint32_t readForcedConfigPortalFlag; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("Check if isForcedCP")); +#endif + + File file = FileFS.open(CONFIG_PORTAL_FILENAME, "r"); + BLYNK_LOG1(BLYNK_F("LoadCPFile ")); + + if (!file) + { + BLYNK_LOG1(BLYNK_F("failed")); + + // Trying open redundant config file + file = FileFS.open(CONFIG_PORTAL_FILENAME_BACKUP, "r"); + BLYNK_LOG1(BLYNK_F("LoadBkUpCPFile ")); + + if (!file) + { + BLYNK_LOG1(BLYNK_F("failed")); + return false; + } + } + + file.readBytes((char *) &readForcedConfigPortalFlag, sizeof(readForcedConfigPortalFlag)); + + BLYNK_LOG1(BLYNK_F("OK")); + file.close(); + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + if (readForcedConfigPortalFlag == FORCED_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = false; + return true; + } + else if (readForcedConfigPortalFlag == FORCED_PERS_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = true; + return true; + } + else + { + return false; + } + } + + ////////////////////////////////////////////// + +#if USE_DYNAMIC_PARAMETERS + + bool checkDynamicData() + { int checkSum = 0; int readCheckSum; - char* readBuffer = NULL; + char* readBuffer; File file = FileFS.open(CREDENTIALS_FILENAME, "r"); BLYNK_LOG1(BLYNK_F("LoadCredFile ")); @@ -737,7 +947,6 @@ class BlynkEthernet // We dont like to destroy myMenuItems[i].pdata with invalid data uint16_t maxBufferLength = 0; - for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { if (myMenuItems[i].maxlen > maxBufferLength) @@ -786,7 +995,7 @@ class BlynkEthernet BLYNK_LOG1(BLYNK_F("OK")); file.close(); - BLYNK_LOG4(F("CrCCSum=0x"), String(checkSum, HEX), F(",CrRCSum=0x"), String(readCheckSum, HEX)); + BLYNK_LOG4(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); // Free buffer if (readBuffer != NULL) @@ -799,15 +1008,14 @@ class BlynkEthernet { return false; } -#endif return true; } + + ////////////////////////////////////////////// bool loadDynamicData() { -#if USE_DYNAMIC_PARAMETERS - int checkSum = 0; int readCheckSum; totalDataSize = sizeof(BlynkEthernet_WM_config) + sizeof(readCheckSum); @@ -855,21 +1063,20 @@ class BlynkEthernet BLYNK_LOG1(BLYNK_F("OK")); file.close(); - BLYNK_LOG4(F("CrCCSum=0x"), String(checkSum, HEX), F(",CrRCSum=0x"), String(readCheckSum, HEX)); + BLYNK_LOG4(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum) { return false; } -#endif return true; } + + ////////////////////////////////////////////// void saveDynamicData() { -#if USE_DYNAMIC_PARAMETERS - int checkSum = 0; File file = FileFS.open(CREDENTIALS_FILENAME, "w"); @@ -947,10 +1154,33 @@ class BlynkEthernet else { BLYNK_LOG1(BLYNK_F("failed")); - } -#endif + } + } +#endif + + ////////////////////////////////////////////// + + void NULLTerminateConfig() + { + //#define HEADER_MAX_LEN 16 + //#define BLYNK_SERVER_MAX_LEN 32 + //#define BLYNK_TOKEN_MAX_LEN 36 + //#define STATIC_IP_MAX_LEN 16 + //#define BOARD_NAME_MAX_LEN 24 + + // NULL Terminating to be sure + BlynkEthernet_WM_config.header[HEADER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server[BLYNK_SERVER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token [BLYNK_TOKEN_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server[BLYNK_SERVER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token [BLYNK_TOKEN_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.blynk_port = BLYNK_SERVER_HARDWARE_PORT; + BlynkEthernet_WM_config.static_IP[STATIC_IP_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.board_name [BOARD_NAME_MAX_LEN - 1] = 0; } + ////////////////////////////////////////////// + void loadConfigData() { File file = FileFS.open(CONFIG_FILENAME, "r"); @@ -976,6 +1206,8 @@ class BlynkEthernet BLYNK_LOG1(BLYNK_F("OK")); file.close(); } + + ////////////////////////////////////////////// void saveConfigData() { @@ -1011,10 +1243,13 @@ class BlynkEthernet { BLYNK_LOG1(BLYNK_F("failed")); } - + +#if USE_DYNAMIC_PARAMETERS saveDynamicData(); +#endif } - + + ////////////////////////////////////////////// void loadAndSaveDefaultConfigData() { @@ -1030,23 +1265,25 @@ class BlynkEthernet displayConfigData(BlynkEthernet_WM_config); #endif } + + ////////////////////////////////////////////// // Return false if init new EEPROM or SPIFFS. No more need trying to connect. Go directly to config mode bool getConfigData() { - bool dynamicDataValid; + bool dynamicDataValid = true; int calChecksum; hadConfigData = false; - // Format SPIFFS if not yet - if (!SPIFFS.begin(true)) + // Format LittleFS/SPIFFS if not yet + if (!FileFS.begin(true)) { - BLYNK_LOG1(BLYNK_F("SPIFFS failed! Formatting.")); + BLYNK_LOG1(BLYNK_F("SPIFFS/LittleFS failed! Formatting.")); - if (!SPIFFS.begin()) + if (!FileFS.begin()) { - BLYNK_LOG1(BLYNK_F("SPIFFS failed! Pls use EEPROM.")); + BLYNK_LOG1(BLYNK_F("SPIFFS/LittleFS failed! Pls use EEPROM.")); return false; } } @@ -1059,8 +1296,12 @@ class BlynkEthernet // Don't need Config Portal anymore return true; } - else if ( ( SPIFFS.exists(CONFIG_FILENAME) || SPIFFS.exists(CONFIG_FILENAME_BACKUP) ) && - ( SPIFFS.exists(CREDENTIALS_FILENAME) || SPIFFS.exists(CREDENTIALS_FILENAME_BACKUP) ) ) +#if USE_DYNAMIC_PARAMETERS + else if ( ( FileFS.exists(CONFIG_FILENAME) || FileFS.exists(CONFIG_FILENAME_BACKUP) ) && + ( FileFS.exists(CREDENTIALS_FILENAME) || FileFS.exists(CREDENTIALS_FILENAME_BACKUP) ) ) +#else + else if ( FileFS.exists(CONFIG_FILENAME) || FileFS.exists(CONFIG_FILENAME_BACKUP) ) +#endif { // if config file exists, load loadConfigData(); @@ -1075,28 +1316,29 @@ class BlynkEthernet BLYNK_LOG4(BLYNK_F("CCSum=0x"), String(calChecksum, HEX), BLYNK_F(",RCSum=0x"), String(BlynkEthernet_WM_config.checkSum, HEX)); +#if USE_DYNAMIC_PARAMETERS // Load dynamic data dynamicDataValid = loadDynamicData(); if (dynamicDataValid) { -#if ( BLYNK_WM_DEBUG > 2) + #if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("Valid Stored Dynamic Data")); -#endif + #endif } -#if ( BLYNK_WM_DEBUG > 2) + #if ( BLYNK_WM_DEBUG > 2) else { BLYNK_LOG1(BLYNK_F("Invalid Stored Dynamic Data. Ignored")); } + #endif #endif } else { // Not loading Default config data, but having no config file => Config Portal return false; - } - + } if ( (strncmp(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE, strlen(BLYNK_BOARD_TYPE)) != 0) || (calChecksum != BlynkEthernet_WM_config.checkSum) || !dynamicDataValid ) @@ -1175,7 +1417,7 @@ class BlynkEthernet #else #ifndef EEPROM_SIZE - #define EEPROM_SIZE 1024 + #define EEPROM_SIZE 2048 #else #if (EEPROM_SIZE > 2048) #warning EEPROM_SIZE must be <= 2048. Reset to 2048 @@ -1191,32 +1433,91 @@ class BlynkEthernet #endif #ifndef EEPROM_START - #define EEPROM_START 0 //define 256 in DRD - #warning EEPROM_START not defined. Set to 0 + #define EEPROM_START 0 //define 256 in DRD/MRD #else - #if (EEPROM_START + FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE) - #error EPROM_START + FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE. Please adjust. + #if (EEPROM_START + FLAG_DATA_SIZE + CONFIG_DATA_SIZE + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE > EEPROM_SIZE) + #error EPROM_START + FLAG_DATA_SIZE + CONFIG_DATA_SIZE + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE > EEPROM_SIZE. Please adjust. #endif #endif // Stating positon to store Blynk8266_WM_config #define BLYNK_EEPROM_START (EEPROM_START + FLAG_DATA_SIZE) + + ////////////////////////////////////////////// + + void setForcedCP(bool isPersistent) + { + uint32_t readForcedConfigPortalFlag = isPersistent? FORCED_PERS_CONFIG_PORTAL_FLAG_DATA : FORCED_CONFIG_PORTAL_FLAG_DATA; - bool checkDynamicData() +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("setForcedCP")); +#endif + + EEPROM.put(BLYNK_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag); + EEPROM.commit(); + } + ////////////////////////////////////////////// + + void clearForcedCP() + { +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("clearForcedCP")); +#endif + + EEPROM.put(BLYNK_EEPROM_START + CONFIG_DATA_SIZE, 0); + EEPROM.commit(); + } + + ////////////////////////////////////////////// + + bool isForcedCP() { + uint32_t readForcedConfigPortalFlag; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("Check if isForcedCP")); +#endif + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + EEPROM.get(BLYNK_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag); + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + if (readForcedConfigPortalFlag == FORCED_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = false; + return true; + } + else if (readForcedConfigPortalFlag == FORCED_PERS_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = true; + return true; + } + else + { + return false; + } + } + + ////////////////////////////////////////////// + #if USE_DYNAMIC_PARAMETERS + bool checkDynamicData() + { int checkSum = 0; int readCheckSum; #define BUFFER_LEN 128 char readBuffer[BUFFER_LEN + 1]; - uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config); + uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; // Find the longest pdata, then dynamically allocate buffer. Remember to free when done // This is used to store tempo data to calculate checksum to see of data is valid - // We dont like to destroy myMenuItems[i].pdata with invalid data + // We dont like to destroy myMenuItems[i].pdata with invalid data + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { if (myMenuItems[i].maxlen > BUFFER_LEN) @@ -1253,25 +1554,23 @@ class BlynkEthernet EEPROM.get(offset, readCheckSum); - BLYNK_LOG4(F("ChkCrR:CrCCsum="), String(checkSum, HEX), F(",CrRCsum="), String(readCheckSum, HEX)); + BLYNK_LOG4(F("ChkCrR:CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum) { return false; } -#endif return true; } - + ////////////////////////////////////////////// + bool EEPROM_getDynamicData() { -#if USE_DYNAMIC_PARAMETERS - int readCheckSum; int checkSum = 0; - uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config); + uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; totalDataSize = sizeof(BlynkEthernet_WM_config) + sizeof(readCheckSum); @@ -1296,23 +1595,22 @@ class BlynkEthernet EEPROM.get(offset, readCheckSum); - BLYNK_LOG4(F("CrCCsum="), String(checkSum, HEX), F(",CrRCsum="), String(readCheckSum, HEX)); + BLYNK_LOG4(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum) { return false; } -#endif return true; } + + ////////////////////////////////////////////// void EEPROM_putDynamicData() { -#if USE_DYNAMIC_PARAMETERS - int checkSum = 0; - uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config); + uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { @@ -1334,8 +1632,27 @@ class BlynkEthernet //EEPROM.commit(); BLYNK_LOG2(F("CrWCSum=0x"), String(checkSum, HEX)); -#endif } +#endif + + ////////////////////////////////////////////// + + void saveConfigData() + { + int calChecksum = calcChecksum(); + BlynkEthernet_WM_config.checkSum = calChecksum; + BLYNK_LOG2(BLYNK_F("Save,WCSum=0x"), String(calChecksum, HEX)); + + EEPROM.put(BLYNK_EEPROM_START, BlynkEthernet_WM_config); + +#if USE_DYNAMIC_PARAMETERS + EEPROM_putDynamicData(); +#endif + + EEPROM.commit(); + } + + ////////////////////////////////////////////// void loadAndSaveDefaultConfigData() { @@ -1352,9 +1669,11 @@ class BlynkEthernet #endif } + ////////////////////////////////////////////// + bool getConfigData() { - bool dynamicDataValid; + bool dynamicDataValid = true; int calChecksum; hadConfigData = false; @@ -1371,43 +1690,63 @@ class BlynkEthernet return true; } else - { - // Load data from EEPROM + { + // Load stored config from EEPROM-simulated FlashStorage EEPROM.get(BLYNK_EEPROM_START, BlynkEthernet_WM_config); - -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("======= Start Stored Config Data =======")); - displayConfigData(BlynkEthernet_WM_config); -#endif - + + // Verify ChkSum calChecksum = calcChecksum(); BLYNK_LOG4(BLYNK_F("CCSum=0x"), String(calChecksum, HEX), BLYNK_F(",RCSum=0x"), String(BlynkEthernet_WM_config.checkSum, HEX)); - - // Load dynamic data from EEPROM - dynamicDataValid = EEPROM_getDynamicData(); - - if (dynamicDataValid) - { -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("Valid Stored Dynamic Data")); -#endif - } -#if ( BLYNK_WM_DEBUG > 2) - else - { - BLYNK_LOG1(BLYNK_F("Invalid Stored Dynamic Data. Ignored")); - } + +#if USE_DYNAMIC_PARAMETERS + // Load stored dynamic data from dueFlashStorage + dynamicDataValid = checkDynamicData(); #endif - } - + // If checksum = 0 => DueFlashStorage has been cleared (by uploading new FW, etc) => force to CP + // If bad checksum = 0 => force to CP + if ( (calChecksum != 0) && (calChecksum == BlynkEthernet_WM_config.checkSum) ) + { + if (dynamicDataValid) + { + #if USE_DYNAMIC_PARAMETERS + // CkSum verified, Now get valid dynamic data + EEPROM_getDynamicData(); + + #if ( BLYNK_WM_DEBUG > 2 ) + BLYNK_LOG1(BLYNK_F("Valid Stored Dynamic Data")); + #endif + #endif + + BLYNK_LOG1(BLYNK_F("======= Start Stored Config Data =======")); + displayConfigData(BlynkEthernet_WM_config); + + // Don't need Config Portal anymore + return true; + } + else + { + // Invalid Stored config data => Config Portal + BLYNK_LOG1(BLYNK_F("Invalid Stored Dynamic Data. Load default from Sketch")); + + // Load Default Config Data from Sketch, better than just "blank" + loadAndSaveDefaultConfigData(); + + // Need Config Portal here as data can be just dummy + // Even if you don't open CP, you're OK on next boot if your default config data is valid + return false; + } + } + } + if ( (strncmp(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE, strlen(BLYNK_BOARD_TYPE)) != 0) || - (calChecksum != BlynkEthernet_WM_config.checkSum) || !dynamicDataValid ) + (calChecksum != BlynkEthernet_WM_config.checkSum) || !dynamicDataValid || + ( (calChecksum == 0) && (BlynkEthernet_WM_config.checkSum == 0) ) ) { // Including Credentials CSum - BLYNK_LOG4(F("InitEEPROM,sz="), EEPROM_SIZE, F(",Datasz="), totalDataSize); - + BLYNK_LOG2(F("InitCfgFile,Sz="), sizeof(BlynkEthernet_WM_config)); + // doesn't have any configuration if (LOAD_DEFAULT_CONFIG_DATA) { @@ -1426,7 +1765,7 @@ class BlynkEthernet #endif // Including Credentials CSum - BLYNK_LOG4(F("InitEEPROM,sz="), EEPROM_SIZE, F(",Datasz="), totalDataSize); + BLYNK_LOG2(BLYNK_F("InitCfgFile,DataSz="), totalDataSize); // doesn't have any configuration strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, WM_NO_CONFIG); @@ -1437,29 +1776,27 @@ class BlynkEthernet strcpy(BlynkEthernet_WM_config.static_IP, WM_NO_CONFIG); strcpy(BlynkEthernet_WM_config.board_name, WM_NO_CONFIG); -#if USE_DYNAMIC_PARAMETERS +#if USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { strncpy(myMenuItems[i].pdata, WM_NO_CONFIG, myMenuItems[i].maxlen); } #endif } - + strcpy(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE); - - #if (USE_DYNAMIC_PARAMETERS && ( BLYNK_WM_DEBUG > 2)) + +#if ( BLYNK_WM_DEBUG > 2) && USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { BLYNK_LOG4(BLYNK_F("g:myMenuItems["), i, BLYNK_F("]="), myMenuItems[i].pdata ); } - #endif +#endif // Don't need BlynkEthernet_WM_config.checkSum = 0; - EEPROM.put(BLYNK_EEPROM_START, BlynkEthernet_WM_config); - EEPROM_putDynamicData(); - EEPROM.commit(); + saveConfigData(); return false; } @@ -1479,20 +1816,10 @@ class BlynkEthernet return true; } - void saveConfigData() - { - int calChecksum = calcChecksum(); - BlynkEthernet_WM_config.checkSum = calChecksum; - BLYNK_LOG2(BLYNK_F("Save,WCSum=0x"), String(calChecksum, HEX)); - - EEPROM.put(BLYNK_EEPROM_START, BlynkEthernet_WM_config); - EEPROM_putDynamicData(); - - EEPROM.commit(); - } - #endif // SPIFFS + ////////////////////////////////////////////// + bool connectMultiBlynk() { #define BLYNK_CONNECT_TIMEOUT_MS 10000L @@ -1517,7 +1844,8 @@ class BlynkEthernet return false; } - // NEW + ////////////////////////////////////////////// + void createHTML(String& root_html_template) { String pitem; @@ -1564,7 +1892,8 @@ class BlynkEthernet return; } - //// + + ////////////////////////////////////////////// void handleRequest() { @@ -1629,91 +1958,135 @@ class BlynkEthernet strcpy(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE); } - if (key == "sv") +#if USE_DYNAMIC_PARAMETERS + if (!menuItemUpdated) + { + // Don't need to free + menuItemUpdated = new bool[NUM_MENU_ITEMS]; + + if (menuItemUpdated) + { + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + // To flag item is not yet updated + menuItemUpdated[i] = false; + } + #if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("h: Init menuItemUpdated" )); + #endif + } + else + { + BLYNK_LOG1(BLYNK_F("h: Error can't alloc memory for menuItemUpdated" )); + } + } +#endif + + static bool sv_Updated = false; + static bool tk_Updated = false; + static bool sv1_Updated = false; + static bool tk1_Updated = false; + static bool pt_Updated = false; + static bool ip_Updated = false; + static bool nm_Updated = false; + + if (!sv_Updated && (key == String("sv"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:sv")); #endif + sv_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server) - 1); } - else if (key == "tk") + else if (!tk_Updated && (key == String("tk"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:tk")); #endif + tk_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token) - 1); } - else if (key == "sv1") + else if (!sv1_Updated && (key == String("sv1"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:sv1")); #endif + sv1_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server) - 1); } - else if (key == "tk1") + else if (!tk1_Updated && (key == String("tk1"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:tk1")); #endif + tk1_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token) - 1); } - else if (key == "pt") + else if (!pt_Updated && (key == String("pt"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:pt")); #endif + pt_Updated = true; number_items_Updated++; BlynkEthernet_WM_config.blynk_port = value.toInt(); } - else if (key == "ip") + else if (!ip_Updated && (key == String("ip"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:ip")); #endif + ip_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.static_IP) - 1) strcpy(BlynkEthernet_WM_config.static_IP, value.c_str()); else strncpy(BlynkEthernet_WM_config.static_IP, value.c_str(), sizeof(BlynkEthernet_WM_config.static_IP) - 1); } - else if (key == "nm") + else if (!nm_Updated && (key == String("nm"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:nm")); #endif + nm_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.board_name) - 1) strcpy(BlynkEthernet_WM_config.board_name, value.c_str()); else strncpy(BlynkEthernet_WM_config.board_name, value.c_str(), sizeof(BlynkEthernet_WM_config.board_name) - 1); } -#if (BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("h:OK")); -#endif - -#if USE_DYNAMIC_PARAMETERS +#if USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - if (key == myMenuItems[i].id) + if ( !menuItemUpdated[i] && (key == myMenuItems[i].id) ) { - //BLYNK_LOG4(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); + BLYNK_LOG4(BLYNK_F("h:"), myMenuItems[i].id, BLYNK_F("="), value.c_str() ); + + menuItemUpdated[i] = true; + number_items_Updated++; // Actual size of pdata is [maxlen + 1] @@ -1723,26 +2096,36 @@ class BlynkEthernet strcpy(myMenuItems[i].pdata, value.c_str()); else strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); - -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG4(BLYNK_F("h2:myMenuItems["), i, BLYNK_F("]="), myMenuItems[i].pdata ); -#endif } } #endif + //#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG2(F("h:items updated ="), number_items_Updated); + BLYNK_LOG4(F("h:key ="), key, ", value =", value); + //#endif + server->send(200, "text/html", "OK"); - // NEW +#if USE_DYNAMIC_PARAMETERS if (number_items_Updated == NUM_CONFIGURABLE_ITEMS + NUM_MENU_ITEMS) +#else + if (number_items_Updated == NUM_CONFIGURABLE_ITEMS) +#endif { -#if USE_SPIFFS - BLYNK_LOG2(BLYNK_F("h:UpdSPIFFS:"), CONFIG_FILENAME); +#if USE_LITTLEFS + BLYNK_LOG1(BLYNK_F("h:Updating LittleFS")); +#elif USE_SPIFFS + BLYNK_LOG1(BLYNK_F("h:Updating SPIFFS")); #else - BLYNK_LOG1(BLYNK_F("h:UpdEEPROM")); + BLYNK_LOG1(BLYNK_F("h:Updating EEPROM. Please wait for reset")); #endif saveConfigData(); + + // Done with CP, Clear CP Flag here if forced + if (isForcedConfigPortal) + clearForcedCP(); #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:Rst")); @@ -1750,11 +2133,12 @@ class BlynkEthernet // Delay then reset after save data delay(200); - //BlynkReset(); resetFunc(); } } // if (server) } + + ////////////////////////////////////////////// void startConfigurationMode() { @@ -1819,6 +2203,8 @@ class BlynkEthernet return ethernetConnected; } + + ////////////////////////////////////////////// byte* SelectMacAddress(const char* token, const byte mac[]) { diff --git a/src/Adapters/BlynkEthernet_ESP8266_WM.h b/src/Adapters/BlynkEthernet_ESP8266_WM.h index d46699eb..5da48d34 100644 --- a/src/Adapters/BlynkEthernet_ESP8266_WM.h +++ b/src/Adapters/BlynkEthernet_ESP8266_WM.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,6 +38,7 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkEthernet_WM_h @@ -141,13 +142,20 @@ typedef struct } MenuItem; // -///NEW -extern uint16_t NUM_MENU_ITEMS; -extern MenuItem myMenuItems []; +#if USE_DYNAMIC_PARAMETERS + extern uint16_t NUM_MENU_ITEMS; + extern MenuItem myMenuItems []; + bool *menuItemUpdated = NULL; +#endif + +#define HEADER_MAX_LEN 16 #define BLYNK_SERVER_MAX_LEN 32 #define BLYNK_TOKEN_MAX_LEN 36 +#define STATIC_IP_MAX_LEN 16 +#define BOARD_NAME_MAX_LEN 24 + typedef struct { char blynk_server[BLYNK_SERVER_MAX_LEN]; @@ -161,11 +169,11 @@ typedef struct typedef struct Configuration { - char header [16]; + char header [HEADER_MAX_LEN]; Blynk_Credentials Blynk_Creds [NUM_BLYNK_CREDENTIALS]; int blynk_port; - char static_IP [16]; - char board_name [24]; + char static_IP [STATIC_IP_MAX_LEN]; + char board_name [BOARD_NAME_MAX_LEN]; int checkSum; } Blynk_Configuration; @@ -377,14 +385,14 @@ class BlynkEthernet #define LED_OFF HIGH void begin() - { - + { //Turn OFF pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LED_OFF); //// New DRD //// - drd = new DoubleResetDetector(DRD_TIMEOUT, DRD_ADDRESS); + drd = new DoubleResetDetector(DRD_TIMEOUT, DRD_ADDRESS); + bool noConfigPortal = true; if (drd->detectDoubleReset()) @@ -395,21 +403,31 @@ class BlynkEthernet noConfigPortal = false; } //// New DRD //// -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("======= Start Default Config Data =======")); - displayConfigData(defaultConfig); + +#if ( BLYNK_WM_DEBUG > 2) + if (LOAD_DEFAULT_CONFIG_DATA) + { + BLYNK_LOG1(BLYNK_F("======= Start Default Config Data =======")); + displayConfigData(defaultConfig); + } #endif hadConfigData = getConfigData(); connectEthernet(); - //// New DRD //// - // noConfigPortal when getConfigData() OK and no DRD'ed - if (hadConfigData && noConfigPortal) - //// New DRD //// + isForcedConfigPortal = isForcedCP(); + + //// New DRD/MRD //// + // noConfigPortal when getConfigData() OK and no MRD/DRD'ed + //if (getConfigData() && noConfigPortal) + if (hadConfigData && noConfigPortal && (!isForcedConfigPortal) ) { hadConfigData = true; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(noConfigPortal? BLYNK_F("bg: noConfigPortal = true") : BLYNK_F("bg: noConfigPortal = false")); +#endif if (ethernetConnected) { @@ -440,9 +458,22 @@ class BlynkEthernet } } else - { - BLYNK_LOG2(BLYNK_F("b:Stay in CfgPortal:"), noConfigPortal ? BLYNK_F("No CfgDat") : BLYNK_F("DRD")); - + { +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(isForcedConfigPortal? BLYNK_F("bg: isForcedConfigPortal = true") : BLYNK_F("bg: isForcedConfigPortal = false")); +#endif + + // If not persistent => clear the flag so that after reset. no more CP, even CP not entered and saved + if (persForcedConfigPortal) + { + BLYNK_LOG2(BLYNK_F("bg:Stay forever in CP:"), isForcedConfigPortal ? BLYNK_F("Forced-Persistent") : (noConfigPortal ? BLYNK_F("No ConfigDat") : BLYNK_F("DRD/MRD"))); + } + else + { + BLYNK_LOG2(BLYNK_F("bg:Stay forever in CP:"), isForcedConfigPortal ? BLYNK_F("Forced-non-Persistent") : (noConfigPortal ? BLYNK_F("No ConfigDat") : BLYNK_F("DRD/MRD"))); + clearForcedCP(); + } + // failed to connect to Blynk server, will start configuration mode hadConfigData = false; startConfigurationMode(); @@ -601,10 +632,43 @@ class BlynkEthernet } #endif - //EEPROM.put(BLYNK_EEPROM_START, BlynkEthernet_WM_config); saveConfigData(); } + // Forced CP => Flag = 0xBEEFBEEF. Else => No forced CP + // Flag to be stored at (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // to avoid corruption to current data + //#define FORCED_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xDEADBEEF) + //#define FORCED_PERS_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xBEEFDEAD) + + const uint32_t FORCED_CONFIG_PORTAL_FLAG_DATA = 0xDEADBEEF; + const uint32_t FORCED_PERS_CONFIG_PORTAL_FLAG_DATA = 0xBEEFDEAD; + + #define FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE 4 + + void resetAndEnterConfigPortal() + { + persForcedConfigPortal = false; + + setForcedCP(false); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + // This will keep CP forever, until you successfully enter CP, and Save data to clear the flag. + void resetAndEnterConfigPortalPersistent() + { + persForcedConfigPortal = true; + + setForcedCP(true); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + void resetFunc() { delay(1000); @@ -624,6 +688,9 @@ class BlynkEthernet unsigned long configTimeout; bool hadConfigData = false; + + bool isForcedConfigPortal = false; + bool persForcedConfigPortal = false; Blynk_Configuration BlynkEthernet_WM_config; @@ -719,13 +786,131 @@ class BlynkEthernet #define CREDENTIALS_FILENAME BLYNK_F("/wm_cred.dat") #define CREDENTIALS_FILENAME_BACKUP BLYNK_F("/wm_cred.bak") - bool checkDynamicData() +#define CONFIG_PORTAL_FILENAME BLYNK_F("/wm_cp.dat") +#define CONFIG_PORTAL_FILENAME_BACKUP BLYNK_F("/wm_cp.bak") + + ////////////////////////////////////////////// + + void saveForcedCP(uint32_t value) { -#if USE_DYNAMIC_PARAMETERS + File file = FileFS.open(CONFIG_PORTAL_FILENAME, "w"); + + BLYNK_LOG1(BLYNK_F("SaveCPFile ")); + + if (file) + { + file.write((uint8_t*) &value, sizeof(value)); + file.close(); + BLYNK_LOG1(BLYNK_F("OK")); + } + else + { + BLYNK_LOG1(BLYNK_F("failed")); + } + + // Trying open redundant CP file + file = FileFS.open(CONFIG_PORTAL_FILENAME_BACKUP, "w"); + + BLYNK_LOG1(BLYNK_F("SaveBkUpCPFile ")); + + if (file) + { + file.write((uint8_t *) &value, sizeof(value)); + file.close(); + BLYNK_LOG1(BLYNK_F("OK")); + } + else + { + BLYNK_LOG1(BLYNK_F("failed")); + } + } + + ////////////////////////////////////////////// + + void setForcedCP(bool isPersistent) + { + uint32_t readForcedConfigPortalFlag = isPersistent? FORCED_PERS_CONFIG_PORTAL_FLAG_DATA : FORCED_CONFIG_PORTAL_FLAG_DATA; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(isPersistent ? BLYNK_F("setForcedCP Persistent") : BLYNK_F("setForcedCP non-Persistent")); +#endif + + saveForcedCP(readForcedConfigPortalFlag); + } + + ////////////////////////////////////////////// + + void clearForcedCP() + { + uint32_t readForcedConfigPortalFlag = 0; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("clearForcedCP")); +#endif + + saveForcedCP(readForcedConfigPortalFlag); + } + ////////////////////////////////////////////// + + bool isForcedCP() + { + uint32_t readForcedConfigPortalFlag; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("Check if isForcedCP")); +#endif + + File file = FileFS.open(CONFIG_PORTAL_FILENAME, "r"); + BLYNK_LOG1(BLYNK_F("LoadCPFile ")); + + if (!file) + { + BLYNK_LOG1(BLYNK_F("failed")); + + // Trying open redundant config file + file = FileFS.open(CONFIG_PORTAL_FILENAME_BACKUP, "r"); + BLYNK_LOG1(BLYNK_F("LoadBkUpCPFile ")); + + if (!file) + { + BLYNK_LOG1(BLYNK_F("failed")); + return false; + } + } + + file.readBytes((char *) &readForcedConfigPortalFlag, sizeof(readForcedConfigPortalFlag)); + + BLYNK_LOG1(BLYNK_F("OK")); + file.close(); + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + if (readForcedConfigPortalFlag == FORCED_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = false; + return true; + } + else if (readForcedConfigPortalFlag == FORCED_PERS_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = true; + return true; + } + else + { + return false; + } + } + + ////////////////////////////////////////////// + +#if USE_DYNAMIC_PARAMETERS + + bool checkDynamicData() + { int checkSum = 0; int readCheckSum; - char* readBuffer = NULL; + char* readBuffer; File file = FileFS.open(CREDENTIALS_FILENAME, "r"); BLYNK_LOG1(BLYNK_F("LoadCredFile ")); @@ -750,7 +935,6 @@ class BlynkEthernet // We dont like to destroy myMenuItems[i].pdata with invalid data uint16_t maxBufferLength = 0; - for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { if (myMenuItems[i].maxlen > maxBufferLength) @@ -799,7 +983,7 @@ class BlynkEthernet BLYNK_LOG1(BLYNK_F("OK")); file.close(); - BLYNK_LOG4(F("CrCCSum=0x"), String(checkSum, HEX), F(",CrRCSum=0x"), String(readCheckSum, HEX)); + BLYNK_LOG4(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); // Free buffer if (readBuffer != NULL) @@ -812,15 +996,14 @@ class BlynkEthernet { return false; } -#endif return true; } + + ////////////////////////////////////////////// bool loadDynamicData() { -#if USE_DYNAMIC_PARAMETERS - int checkSum = 0; int readCheckSum; totalDataSize = sizeof(BlynkEthernet_WM_config) + sizeof(readCheckSum); @@ -868,21 +1051,20 @@ class BlynkEthernet BLYNK_LOG1(BLYNK_F("OK")); file.close(); - BLYNK_LOG4(F("CrCCSum=0x"), String(checkSum, HEX), F(",CrRCSum=0x"), String(readCheckSum, HEX)); + BLYNK_LOG4(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum) { return false; } -#endif return true; } + ////////////////////////////////////////////// + void saveDynamicData() { -#if USE_DYNAMIC_PARAMETERS - int checkSum = 0; File file = FileFS.open(CREDENTIALS_FILENAME, "w"); @@ -960,10 +1142,33 @@ class BlynkEthernet else { BLYNK_LOG1(BLYNK_F("failed")); - } -#endif + } + } +#endif + + ////////////////////////////////////////////// + + void NULLTerminateConfig() + { + //#define HEADER_MAX_LEN 16 + //#define BLYNK_SERVER_MAX_LEN 32 + //#define BLYNK_TOKEN_MAX_LEN 36 + //#define STATIC_IP_MAX_LEN 16 + //#define BOARD_NAME_MAX_LEN 24 + + // NULL Terminating to be sure + BlynkEthernet_WM_config.header[HEADER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server[BLYNK_SERVER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token [BLYNK_TOKEN_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server[BLYNK_SERVER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token [BLYNK_TOKEN_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.blynk_port = BLYNK_SERVER_HARDWARE_PORT; + BlynkEthernet_WM_config.static_IP[STATIC_IP_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.board_name [BOARD_NAME_MAX_LEN - 1] = 0; } + ////////////////////////////////////////////// + void loadConfigData() { File file = FileFS.open(CONFIG_FILENAME, "r"); @@ -989,6 +1194,8 @@ class BlynkEthernet BLYNK_LOG1(BLYNK_F("OK")); file.close(); } + + ////////////////////////////////////////////// void saveConfigData() { @@ -1024,9 +1231,13 @@ class BlynkEthernet { BLYNK_LOG1(BLYNK_F("failed")); } - + +#if USE_DYNAMIC_PARAMETERS saveDynamicData(); +#endif } + + ////////////////////////////////////////////// void loadAndSaveDefaultConfigData() { @@ -1042,11 +1253,13 @@ class BlynkEthernet displayConfigData(BlynkEthernet_WM_config); #endif } + + ////////////////////////////////////////////// // Return false if init new EEPROM, LittleFS or SPIFFS. No more need trying to connect. Go directly to config mode bool getConfigData() { - bool dynamicDataValid; + bool dynamicDataValid = true; int calChecksum; hadConfigData = false; @@ -1074,8 +1287,12 @@ class BlynkEthernet // Don't need Config Portal anymore return true; } +#if USE_DYNAMIC_PARAMETERS else if ( ( FileFS.exists(CONFIG_FILENAME) || FileFS.exists(CONFIG_FILENAME_BACKUP) ) && ( FileFS.exists(CREDENTIALS_FILENAME) || FileFS.exists(CREDENTIALS_FILENAME_BACKUP) ) ) +#else + else if ( FileFS.exists(CONFIG_FILENAME) || FileFS.exists(CONFIG_FILENAME_BACKUP) ) +#endif { // if config file exists, load loadConfigData(); @@ -1090,28 +1307,29 @@ class BlynkEthernet BLYNK_LOG4(BLYNK_F("CCSum=0x"), String(calChecksum, HEX), BLYNK_F(",RCSum=0x"), String(BlynkEthernet_WM_config.checkSum, HEX)); +#if USE_DYNAMIC_PARAMETERS // Load dynamic data dynamicDataValid = loadDynamicData(); if (dynamicDataValid) { -#if ( BLYNK_WM_DEBUG > 2) + #if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("Valid Stored Dynamic Data")); -#endif + #endif } -#if ( BLYNK_WM_DEBUG > 2) + #if ( BLYNK_WM_DEBUG > 2) else { BLYNK_LOG1(BLYNK_F("Invalid Stored Dynamic Data. Ignored")); } + #endif #endif } else { // Not loading Default config data, but having no config file => Config Portal return false; - } - + } if ( (strncmp(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE, strlen(BLYNK_BOARD_TYPE)) != 0) || (calChecksum != BlynkEthernet_WM_config.checkSum) || !dynamicDataValid ) @@ -1144,7 +1362,7 @@ class BlynkEthernet strcpy(BlynkEthernet_WM_config.static_IP, WM_NO_CONFIG); strcpy(BlynkEthernet_WM_config.board_name, WM_NO_CONFIG); -#if USE_DYNAMIC_PARAMETERS +#if USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { strncpy(myMenuItems[i].pdata, WM_NO_CONFIG, myMenuItems[i].maxlen); @@ -1190,7 +1408,7 @@ class BlynkEthernet #else //#if ( USE_LITTLEFS || USE_SPIFFS ) #ifndef EEPROM_SIZE - #define EEPROM_SIZE 1024 + #define EEPROM_SIZE 2048 #else #if (EEPROM_SIZE > 2048) #warning EEPROM_SIZE must be <= 2048. Reset to 2048 @@ -1206,28 +1424,86 @@ class BlynkEthernet #endif #ifndef EEPROM_START - #define EEPROM_START 0 //define 256 in DRD - #warning EEPROM_START not defined. Set to 0 + #define EEPROM_START 0 //define 256 in DRD/MRD #else - #if (EEPROM_START + FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE) - #error EPROM_START + FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE. Please adjust. + #if (EEPROM_START + FLAG_DATA_SIZE + CONFIG_DATA_SIZE + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE > EEPROM_SIZE) + #error EPROM_START + FLAG_DATA_SIZE + CONFIG_DATA_SIZE + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE > EEPROM_SIZE. Please adjust. #endif #endif // Stating positon to store BlynkEthernet_WM_config #define BLYNK_EEPROM_START (EEPROM_START + FLAG_DATA_SIZE) - bool checkDynamicData() + ////////////////////////////////////////////// + + void setForcedCP(bool isPersistent) { + uint32_t readForcedConfigPortalFlag = isPersistent? FORCED_PERS_CONFIG_PORTAL_FLAG_DATA : FORCED_CONFIG_PORTAL_FLAG_DATA; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("setForcedCP")); +#endif + + EEPROM.put(BLYNK_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag); + EEPROM.commit(); + } + ////////////////////////////////////////////// + + void clearForcedCP() + { +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("clearForcedCP")); +#endif + + EEPROM.put(BLYNK_EEPROM_START + CONFIG_DATA_SIZE, 0); + EEPROM.commit(); + } + + ////////////////////////////////////////////// + + bool isForcedCP() + { + uint32_t readForcedConfigPortalFlag; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("Check if isForcedCP")); +#endif + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + EEPROM.get(BLYNK_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag); + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + if (readForcedConfigPortalFlag == FORCED_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = false; + return true; + } + else if (readForcedConfigPortalFlag == FORCED_PERS_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = true; + return true; + } + else + { + return false; + } + } + + ////////////////////////////////////////////// + #if USE_DYNAMIC_PARAMETERS + bool checkDynamicData() + { int checkSum = 0; int readCheckSum; #define BUFFER_LEN 128 char readBuffer[BUFFER_LEN + 1]; - uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config); + uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; // Find the longest pdata, then dynamically allocate buffer. Remember to free when done // This is used to store tempo data to calculate checksum to see of data is valid @@ -1269,25 +1545,23 @@ class BlynkEthernet EEPROM.get(offset, readCheckSum); - BLYNK_LOG4(F("ChkCrR:CrCCsum="), String(checkSum, HEX), F(",CrRCsum="), String(readCheckSum, HEX)); + BLYNK_LOG4(F("ChkCrR:CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum) { return false; } -#endif return true; } - + ////////////////////////////////////////////// + bool EEPROM_getDynamicData() { -#if USE_DYNAMIC_PARAMETERS - int readCheckSum; int checkSum = 0; - uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config); + uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; totalDataSize = sizeof(BlynkEthernet_WM_config) + sizeof(readCheckSum); @@ -1312,23 +1586,22 @@ class BlynkEthernet EEPROM.get(offset, readCheckSum); - BLYNK_LOG4(F("CrCCsum="), String(checkSum, HEX), F(",CrRCsum="), String(readCheckSum, HEX)); + BLYNK_LOG4(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum) { return false; } -#endif return true; } + + ////////////////////////////////////////////// void EEPROM_putDynamicData() { -#if USE_DYNAMIC_PARAMETERS - int checkSum = 0; - uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config); + uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { @@ -1349,9 +1622,28 @@ class BlynkEthernet EEPROM.put(offset, checkSum); //EEPROM.commit(); - BLYNK_LOG2(F("CrWCSum="), String(checkSum, HEX)); -#endif + BLYNK_LOG2(F("CrWCSum=0x"), String(checkSum, HEX)); + } +#endif + + ////////////////////////////////////////////// + + void saveConfigData() + { + int calChecksum = calcChecksum(); + BlynkEthernet_WM_config.checkSum = calChecksum; + BLYNK_LOG2(BLYNK_F("Save,WCSum=0x"), String(calChecksum, HEX)); + + EEPROM.put(BLYNK_EEPROM_START, BlynkEthernet_WM_config); + +#if USE_DYNAMIC_PARAMETERS + EEPROM_putDynamicData(); +#endif + + EEPROM.commit(); } + + ////////////////////////////////////////////// void loadAndSaveDefaultConfigData() { @@ -1367,10 +1659,12 @@ class BlynkEthernet displayConfigData(BlynkEthernet_WM_config); #endif } + + ////////////////////////////////////////////// bool getConfigData() { - bool dynamicDataValid; + bool dynamicDataValid = true; int calChecksum; hadConfigData = false; @@ -1387,43 +1681,63 @@ class BlynkEthernet return true; } else - { - // Load data from EEPROM + { + // Load stored config from EEPROM-simulated FlashStorage EEPROM.get(BLYNK_EEPROM_START, BlynkEthernet_WM_config); - -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("======= Start Stored Config Data =======")); - displayConfigData(BlynkEthernet_WM_config); -#endif - + + // Verify ChkSum calChecksum = calcChecksum(); BLYNK_LOG4(BLYNK_F("CCSum=0x"), String(calChecksum, HEX), BLYNK_F(",RCSum=0x"), String(BlynkEthernet_WM_config.checkSum, HEX)); - - // Load dynamic data from EEPROM - dynamicDataValid = EEPROM_getDynamicData(); - - if (dynamicDataValid) - { -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("Valid Stored Dynamic Data")); -#endif - } -#if ( BLYNK_WM_DEBUG > 2) - else - { - BLYNK_LOG1(BLYNK_F("Invalid Stored Dynamic Data. Ignored")); - } + +#if USE_DYNAMIC_PARAMETERS + // Load stored dynamic data from dueFlashStorage + dynamicDataValid = checkDynamicData(); #endif - } - + // If checksum = 0 => DueFlashStorage has been cleared (by uploading new FW, etc) => force to CP + // If bad checksum = 0 => force to CP + if ( (calChecksum != 0) && (calChecksum == BlynkEthernet_WM_config.checkSum) ) + { + if (dynamicDataValid) + { + #if USE_DYNAMIC_PARAMETERS + // CkSum verified, Now get valid dynamic data + EEPROM_getDynamicData(); + + #if ( BLYNK_WM_DEBUG > 2 ) + BLYNK_LOG1(BLYNK_F("Valid Stored Dynamic Data")); + #endif + #endif + + BLYNK_LOG1(BLYNK_F("======= Start Stored Config Data =======")); + displayConfigData(BlynkEthernet_WM_config); + + // Don't need Config Portal anymore + return true; + } + else + { + // Invalid Stored config data => Config Portal + BLYNK_LOG1(BLYNK_F("Invalid Stored Dynamic Data. Load default from Sketch")); + + // Load Default Config Data from Sketch, better than just "blank" + loadAndSaveDefaultConfigData(); + + // Need Config Portal here as data can be just dummy + // Even if you don't open CP, you're OK on next boot if your default config data is valid + return false; + } + } + } + if ( (strncmp(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE, strlen(BLYNK_BOARD_TYPE)) != 0) || - (calChecksum != BlynkEthernet_WM_config.checkSum) || !dynamicDataValid ) + (calChecksum != BlynkEthernet_WM_config.checkSum) || !dynamicDataValid || + ( (calChecksum == 0) && (BlynkEthernet_WM_config.checkSum == 0) ) ) { // Including Credentials CSum - BLYNK_LOG4(F("InitEEPROM,sz="), EEPROM_SIZE, F(",Datasz="), totalDataSize); - + BLYNK_LOG2(F("InitCfgFile,Sz="), sizeof(BlynkEthernet_WM_config)); + // doesn't have any configuration if (LOAD_DEFAULT_CONFIG_DATA) { @@ -1442,7 +1756,7 @@ class BlynkEthernet #endif // Including Credentials CSum - BLYNK_LOG4(F("InitEEPROM,sz="), EEPROM_SIZE, F(",Datasz="), totalDataSize); + BLYNK_LOG2(BLYNK_F("InitCfgFile,DataSz="), totalDataSize); // doesn't have any configuration strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, WM_NO_CONFIG); @@ -1453,29 +1767,27 @@ class BlynkEthernet strcpy(BlynkEthernet_WM_config.static_IP, WM_NO_CONFIG); strcpy(BlynkEthernet_WM_config.board_name, WM_NO_CONFIG); -#if USE_DYNAMIC_PARAMETERS +#if USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { strncpy(myMenuItems[i].pdata, WM_NO_CONFIG, myMenuItems[i].maxlen); } #endif } - + strcpy(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE); - - #if (USE_DYNAMIC_PARAMETERS && ( BLYNK_WM_DEBUG > 2)) + +#if ( BLYNK_WM_DEBUG > 2) && USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { BLYNK_LOG4(BLYNK_F("g:myMenuItems["), i, BLYNK_F("]="), myMenuItems[i].pdata ); } - #endif +#endif // Don't need BlynkEthernet_WM_config.checkSum = 0; - EEPROM.put(BLYNK_EEPROM_START, BlynkEthernet_WM_config); - EEPROM_putDynamicData(); - EEPROM.commit(); + saveConfigData(); return false; } @@ -1495,20 +1807,10 @@ class BlynkEthernet return true; } - void saveConfigData() - { - int calChecksum = calcChecksum(); - BlynkEthernet_WM_config.checkSum = calChecksum; - BLYNK_LOG2(BLYNK_F("Save,WCSum=0x"), String(calChecksum, HEX)); - - EEPROM.put(BLYNK_EEPROM_START, BlynkEthernet_WM_config); - EEPROM_putDynamicData(); - - EEPROM.commit(); - } - #endif // #if ( USE_LITTLEFS || USE_SPIFFS ) + ////////////////////////////////////////////// + bool connectMultiBlynk() { #define BLYNK_CONNECT_TIMEOUT_MS 10000L @@ -1533,7 +1835,8 @@ class BlynkEthernet return false; } - // NEW + ////////////////////////////////////////////// + void createHTML(String& root_html_template) { String pitem; @@ -1580,7 +1883,8 @@ class BlynkEthernet return; } - //// + + ////////////////////////////////////////////// void handleRequest() { @@ -1645,91 +1949,136 @@ class BlynkEthernet strcpy(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE); } - if (key == "sv") +#if USE_DYNAMIC_PARAMETERS + if (!menuItemUpdated) + { + // Don't need to free + menuItemUpdated = new bool[NUM_MENU_ITEMS]; + + if (menuItemUpdated) + { + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + // To flag item is not yet updated + menuItemUpdated[i] = false; + } + #if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("h: Init menuItemUpdated" )); + #endif + } + else + { + BLYNK_LOG1(BLYNK_F("h: Error can't alloc memory for menuItemUpdated" )); + } + } +#endif + + static bool sv_Updated = false; + static bool tk_Updated = false; + static bool sv1_Updated = false; + static bool tk1_Updated = false; + static bool pt_Updated = false; + static bool ip_Updated = false; + static bool nm_Updated = false; + + //if (key == "sv") + if (!sv_Updated && (key == String("sv"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:sv")); #endif + sv_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server) - 1); } - else if (key == "tk") + else if (!tk_Updated && (key == String("tk"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:tk")); #endif + tk_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token) - 1); } - else if (key == "sv1") + else if (!sv1_Updated && (key == String("sv1"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:sv1")); #endif + sv1_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server) - 1); } - else if (key == "tk1") + else if (!tk1_Updated && (key == String("tk1"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:tk1")); #endif + tk1_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token) - 1); } - else if (key == "pt") + else if (!pt_Updated && (key == String("pt"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:pt")); #endif + pt_Updated = true; number_items_Updated++; BlynkEthernet_WM_config.blynk_port = value.toInt(); } - else if (key == "ip") + else if (!ip_Updated && (key == String("ip"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:ip")); #endif + ip_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.static_IP) - 1) strcpy(BlynkEthernet_WM_config.static_IP, value.c_str()); else strncpy(BlynkEthernet_WM_config.static_IP, value.c_str(), sizeof(BlynkEthernet_WM_config.static_IP) - 1); } - else if (key == "nm") + else if (!nm_Updated && (key == String("nm"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:nm")); #endif + nm_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.board_name) - 1) strcpy(BlynkEthernet_WM_config.board_name, value.c_str()); else strncpy(BlynkEthernet_WM_config.board_name, value.c_str(), sizeof(BlynkEthernet_WM_config.board_name) - 1); } -#if (BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("h:OK")); -#endif - -#if USE_DYNAMIC_PARAMETERS +#if USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - if (key == myMenuItems[i].id) + if ( !menuItemUpdated[i] && (key == myMenuItems[i].id) ) { - //BLYNK_LOG4(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); + BLYNK_LOG4(BLYNK_F("h:"), myMenuItems[i].id, BLYNK_F("="), value.c_str() ); + + menuItemUpdated[i] = true; + number_items_Updated++; // Actual size of pdata is [maxlen + 1] @@ -1739,40 +2088,49 @@ class BlynkEthernet strcpy(myMenuItems[i].pdata, value.c_str()); else strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); - -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG4(BLYNK_F("h2:myMenuItems["), i, BLYNK_F("]="), myMenuItems[i].pdata ); -#endif } } #endif + //#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG2(F("h:items updated ="), number_items_Updated); + BLYNK_LOG4(F("h:key ="), key, ", value =", value); + //#endif + server->send(200, "text/html", "OK"); - // NEW +#if USE_DYNAMIC_PARAMETERS if (number_items_Updated == NUM_CONFIGURABLE_ITEMS + NUM_MENU_ITEMS) +#else + if (number_items_Updated == NUM_CONFIGURABLE_ITEMS) +#endif { #if USE_LITTLEFS - BLYNK_LOG2(BLYNK_F("h:UpdLittleFS:"), CONFIG_FILENAME); + BLYNK_LOG1(BLYNK_F("h:Updating LittleFS")); #elif USE_SPIFFS - BLYNK_LOG2(BLYNK_F("h:UpdSPIFFS:"), CONFIG_FILENAME); + BLYNK_LOG1(BLYNK_F("h:Updating SPIFFS")); #else - BLYNK_LOG1(BLYNK_F("h:UpdEEPROM")); + BLYNK_LOG1(BLYNK_F("h:Updating EEPROM. Please wait for reset")); #endif saveConfigData(); + + // Done with CP, Clear CP Flag here if forced + if (isForcedConfigPortal) + clearForcedCP(); #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:Rst")); #endif // Delay then reset after save data - //delay(200); - //BlynkReset(); + delay(200); resetFunc(); } } // if (server) } + + ////////////////////////////////////////////// void startConfigurationMode() { @@ -1803,6 +2161,8 @@ class BlynkEthernet configuration_mode = true; } + + ////////////////////////////////////////////// bool connectEthernet() { @@ -1838,6 +2198,8 @@ class BlynkEthernet return ethernetConnected; } + + ////////////////////////////////////////////// byte* SelectMacAddress(const char* token, const byte mac[]) { diff --git a/src/Adapters/BlynkEthernet_NRF52_WM.h b/src/Adapters/BlynkEthernet_NRF52_WM.h index 447c9a17..0609145e 100644 --- a/src/Adapters/BlynkEthernet_NRF52_WM.h +++ b/src/Adapters/BlynkEthernet_NRF52_WM.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,6 +38,7 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkEthernet_NRF52_WM_h @@ -124,13 +125,20 @@ typedef struct } MenuItem; // -///NEW -extern uint16_t NUM_MENU_ITEMS; -extern MenuItem myMenuItems []; +#if USE_DYNAMIC_PARAMETERS + extern uint16_t NUM_MENU_ITEMS; + extern MenuItem myMenuItems []; + bool *menuItemUpdated = NULL; +#endif + +#define HEADER_MAX_LEN 16 #define BLYNK_SERVER_MAX_LEN 32 #define BLYNK_TOKEN_MAX_LEN 36 +#define STATIC_IP_MAX_LEN 16 +#define BOARD_NAME_MAX_LEN 24 + typedef struct { char blynk_server[BLYNK_SERVER_MAX_LEN]; @@ -144,11 +152,11 @@ typedef struct typedef struct Configuration { - char header [16]; + char header [HEADER_MAX_LEN]; Blynk_Credentials Blynk_Creds [NUM_BLYNK_CREDENTIALS]; int blynk_port; - char static_IP [16]; - char board_name [24]; + char static_IP [STATIC_IP_MAX_LEN]; + char board_name [BOARD_NAME_MAX_LEN]; int checkSum; } Blynk_Configuration; @@ -376,21 +384,31 @@ class BlynkEthernet noConfigPortal = false; } //// New DRD //// -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("======= Start Default Config Data =======")); - displayConfigData(defaultConfig); + +#if ( BLYNK_WM_DEBUG > 2) + if (LOAD_DEFAULT_CONFIG_DATA) + { + BLYNK_LOG1(BLYNK_F("======= Start Default Config Data =======")); + displayConfigData(defaultConfig); + } #endif hadConfigData = getConfigData(); connectEthernet(); - //// New DRD //// - // noConfigPortal when getConfigData() OK and no DRD'ed - if (hadConfigData && noConfigPortal) - //// New DRD //// + isForcedConfigPortal = isForcedCP(); + + //// New DRD/MRD //// + // noConfigPortal when getConfigData() OK and no MRD/DRD'ed + //if (getConfigData() && noConfigPortal) + if (hadConfigData && noConfigPortal && (!isForcedConfigPortal) ) { hadConfigData = true; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(noConfigPortal? BLYNK_F("bg: noConfigPortal = true") : BLYNK_F("bg: noConfigPortal = false")); +#endif if (ethernetConnected) { @@ -421,9 +439,22 @@ class BlynkEthernet } } else - { - BLYNK_LOG2(BLYNK_F("b:Stay in CfgPortal:"), noConfigPortal ? BLYNK_F("No CfgDat") : BLYNK_F("DRD")); - + { +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(isForcedConfigPortal? BLYNK_F("bg: isForcedConfigPortal = true") : BLYNK_F("bg: isForcedConfigPortal = false")); +#endif + + // If not persistent => clear the flag so that after reset. no more CP, even CP not entered and saved + if (persForcedConfigPortal) + { + BLYNK_LOG2(BLYNK_F("bg:Stay forever in CP:"), isForcedConfigPortal ? BLYNK_F("Forced-Persistent") : (noConfigPortal ? BLYNK_F("No ConfigDat") : BLYNK_F("DRD/MRD"))); + } + else + { + BLYNK_LOG2(BLYNK_F("bg:Stay forever in CP:"), isForcedConfigPortal ? BLYNK_F("Forced-non-Persistent") : (noConfigPortal ? BLYNK_F("No ConfigDat") : BLYNK_F("DRD/MRD"))); + clearForcedCP(); + } + // failed to connect to Blynk server, will start configuration mode hadConfigData = false; startConfigurationMode(); @@ -582,10 +613,43 @@ class BlynkEthernet } #endif - //EEPROM.put(BLYNK_EEPROM_START, BlynkEthernet_WM_config); saveConfigData(); } + // Forced CP => Flag = 0xBEEFBEEF. Else => No forced CP + // Flag to be stored at (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // to avoid corruption to current data + //#define FORCED_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xDEADBEEF) + //#define FORCED_PERS_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xBEEFDEAD) + + const uint32_t FORCED_CONFIG_PORTAL_FLAG_DATA = 0xDEADBEEF; + const uint32_t FORCED_PERS_CONFIG_PORTAL_FLAG_DATA = 0xBEEFDEAD; + + #define FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE 4 + + void resetAndEnterConfigPortal() + { + persForcedConfigPortal = false; + + setForcedCP(false); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + // This will keep CP forever, until you successfully enter CP, and Save data to clear the flag. + void resetAndEnterConfigPortalPersistent() + { + persForcedConfigPortal = true; + + setForcedCP(true); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + void resetFunc() { delay(1000); @@ -606,6 +670,9 @@ class BlynkEthernet unsigned long configTimeout; bool hadConfigData = false; + + bool isForcedConfigPortal = false; + bool persForcedConfigPortal = false; Blynk_Configuration BlynkEthernet_WM_config; @@ -700,13 +767,143 @@ class BlynkEthernet #define CREDENTIALS_FILENAME BLYNK_F("/wm_cred.dat") #define CREDENTIALS_FILENAME_BACKUP BLYNK_F("/wm_cred.bak") - bool checkDynamicData() +#define CONFIG_PORTAL_FILENAME ("/wm_cp.dat") +#define CONFIG_PORTAL_FILENAME_BACKUP ("/wm_cp.bak") + + ////////////////////////////////////////////// + + void saveForcedCP(uint32_t value) { + file.open(CONFIG_PORTAL_FILENAME, FILE_O_WRITE); + //File file = FileFS.open(CONFIG_PORTAL_FILENAME, "w"); + + BLYNK_LOG1(BLYNK_F("SaveCPFile ")); + + if (file) + { + file.seek(0); + file.write((uint8_t*) &value, sizeof(value)); + //file.write((uint8_t*) &value, sizeof(value)); + + file.close(); + BLYNK_LOG1(BLYNK_F("OK")); + } + else + { + BLYNK_LOG1(BLYNK_F("failed")); + } + + // Trying open redundant CP file + file.open(CONFIG_PORTAL_FILENAME_BACKUP, FILE_O_WRITE); + //file = FileFS.open(CONFIG_PORTAL_FILENAME_BACKUP, "w"); + + BLYNK_LOG1(BLYNK_F("SaveBkUpCPFile ")); + + if (file) + { + file.seek(0); + file.write((uint8_t*) &value, sizeof(value)); + //file.write((uint8_t*) &value, sizeof(value)); + file.close(); + BLYNK_LOG1(BLYNK_F("OK")); + } + else + { + BLYNK_LOG1(BLYNK_F("failed")); + } + } + + ////////////////////////////////////////////// + + void setForcedCP(bool isPersistent) + { + uint32_t readForcedConfigPortalFlag = isPersistent? FORCED_PERS_CONFIG_PORTAL_FLAG_DATA : FORCED_CONFIG_PORTAL_FLAG_DATA; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(isPersistent ? BLYNK_F("setForcedCP Persistent") : BLYNK_F("setForcedCP non-Persistent")); +#endif + + saveForcedCP(readForcedConfigPortalFlag); + } -#if USE_DYNAMIC_PARAMETERS + ////////////////////////////////////////////// + + void clearForcedCP() + { + uint32_t readForcedConfigPortalFlag = 0; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("clearForcedCP")); +#endif + + saveForcedCP(readForcedConfigPortalFlag); + } + + ////////////////////////////////////////////// + + bool isForcedCP() + { + uint32_t readForcedConfigPortalFlag; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("Check if isForcedCP")); +#endif + + file.open(CONFIG_PORTAL_FILENAME, FILE_O_READ); + //File file = FileFS.open(CONFIG_PORTAL_FILENAME, "r"); + BLYNK_LOG1(BLYNK_F("LoadCPFile ")); + + if (!file) + { + BLYNK_LOG1(BLYNK_F("failed")); + + // Trying open redundant config file + file.open(CONFIG_PORTAL_FILENAME_BACKUP, FILE_O_READ); + //file = FileFS.open(CONFIG_PORTAL_FILENAME_BACKUP, "r"); + BLYNK_LOG1(BLYNK_F("LoadBkUpCPFile ")); + + if (!file) + { + BLYNK_LOG1(BLYNK_F("failed")); + return false; + } + } + + file.seek(0); + file.read((char *) &readForcedConfigPortalFlag, sizeof(readForcedConfigPortalFlag)); + //file.readBytes((char *) &readForcedConfigPortalFlag, sizeof(readForcedConfigPortalFlag)); + + file.close(); + BLYNK_LOG1(BLYNK_F("OK")); + + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + if (readForcedConfigPortalFlag == FORCED_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = false; + return true; + } + else if (readForcedConfigPortalFlag == FORCED_PERS_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = true; + return true; + } + else + { + return false; + } + } + + ////////////////////////////////////////////// + +#if USE_DYNAMIC_PARAMETERS + + bool checkDynamicData() + { int checkSum = 0; int readCheckSum; - char* readBuffer = NULL; + char* readBuffer; file.open(CREDENTIALS_FILENAME, FILE_O_READ); BLYNK_LOG1(BLYNK_F("LoadCredFile ")); @@ -716,7 +913,6 @@ class BlynkEthernet BLYNK_LOG1(BLYNK_F("failed")); // Trying open redundant config file - //file(CREDENTIALS_FILENAME_BACKUP, FILE_O_READ); file.open(CREDENTIALS_FILENAME_BACKUP, FILE_O_READ); BLYNK_LOG1(BLYNK_F("LoadBkUpCredFile ")); @@ -727,13 +923,14 @@ class BlynkEthernet } } + BLYNK_LOG1(BLYNK_F("OK")); + // Find the longest pdata, then dynamically allocate buffer. Remember to free when done // This is used to store tempo data to calculate checksum to see of data is valid // We dont like to destroy myMenuItems[i].pdata with invalid data uint16_t maxBufferLength = 0; - - for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + for (int i = 0; i < NUM_MENU_ITEMS; i++) { if (myMenuItems[i].maxlen > maxBufferLength) maxBufferLength = myMenuItems[i].maxlen; @@ -749,17 +946,17 @@ class BlynkEthernet BLYNK_LOG1(BLYNK_F("ChkCrR: Error can't allocate buffer.")); return false; } -#if ( BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) else { BLYNK_LOG2(BLYNK_F("ChkCrR: Buffer allocated, Sz="), maxBufferLength + 1); - } -#endif + } +#endif } uint16_t offset = 0; - for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + for (int i = 0; i < NUM_MENU_ITEMS; i++) { char* _pointer = readBuffer; @@ -772,9 +969,9 @@ class BlynkEthernet offset += myMenuItems[i].maxlen; -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG4(F("ChkCrR:pdata="), readBuffer, F(",len="), myMenuItems[i].maxlen); -#endif +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG4(BLYNK_F("ChkCrR:pdata="), readBuffer, BLYNK_F(",len="), myMenuItems[i].maxlen); +#endif for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++) { @@ -783,31 +980,33 @@ class BlynkEthernet } file.read((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)); + BLYNK_LOG4(BLYNK_F("CrCCsum=0x"), String(checkSum, HEX), BLYNK_F(",CrRCsum=0x"), String(readCheckSum, HEX)); // Free buffer if (readBuffer != NULL) { free(readBuffer); + +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("Buffer freed")); +#endif } if ( checkSum != readCheckSum) { return false; } -#endif return true; } + + ////////////////////////////////////////////// bool loadDynamicData() { -#if USE_DYNAMIC_PARAMETERS int checkSum = 0; int readCheckSum; totalDataSize = sizeof(BlynkEthernet_WM_config) + sizeof(readCheckSum); @@ -829,10 +1028,12 @@ class BlynkEthernet return false; } } + + BLYNK_LOG1(BLYNK_F("OK")); uint16_t offset = 0; - for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + for (int i = 0; i < NUM_MENU_ITEMS; i++) { char* _pointer = myMenuItems[i].pdata; totalDataSize += myMenuItems[i].maxlen; @@ -846,9 +1047,9 @@ class BlynkEthernet offset += myMenuItems[i].maxlen; -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG4(F("CrR:pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); -#endif +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG4(BLYNK_F("CrR:pdata="), myMenuItems[i].pdata, BLYNK_F(",len="), myMenuItems[i].maxlen); +#endif for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++) { @@ -856,25 +1057,24 @@ class BlynkEthernet } } - file.read((char *) &readCheckSum, sizeof(readCheckSum)); + file.read((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)); + BLYNK_LOG4(BLYNK_F("CrCCsum=0x"), String(checkSum, HEX), BLYNK_F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum) { return false; } -#endif return true; } + + ////////////////////////////////////////////// void saveDynamicData() { -#if USE_DYNAMIC_PARAMETERS int checkSum = 0; file.open(CREDENTIALS_FILENAME, FILE_O_WRITE); @@ -882,12 +1082,12 @@ class BlynkEthernet uint16_t offset = 0; - for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + for (int i = 0; i < NUM_MENU_ITEMS; i++) { char* _pointer = myMenuItems[i].pdata; -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG4(F("CW1:pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG4(BLYNK_F("CW1:pdata="), myMenuItems[i].pdata, BLYNK_F(",len="), myMenuItems[i].maxlen); #endif if (file) @@ -920,7 +1120,7 @@ class BlynkEthernet BLYNK_LOG1(BLYNK_F("failed")); } - BLYNK_LOG2(F("CrWCSum="), String(checkSum, HEX)); + BLYNK_LOG2(BLYNK_F("CrWCSum=0x"), String(checkSum, HEX)); // Trying open redundant Auth file file.open(CREDENTIALS_FILENAME_BACKUP, FILE_O_WRITE); @@ -928,12 +1128,12 @@ class BlynkEthernet offset = 0; - for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + for (int i = 0; i < NUM_MENU_ITEMS; i++) { char* _pointer = myMenuItems[i].pdata; -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG4(F("CW2:pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG4(BLYNK_F("CW2:pdata="), myMenuItems[i].pdata, BLYNK_F(",len="), myMenuItems[i].maxlen); #endif if (file) @@ -964,16 +1164,40 @@ class BlynkEthernet else { BLYNK_LOG1(BLYNK_F("failed")); - } -#endif + } } +#endif + + ////////////////////////////////////////////// + + void NULLTerminateConfig() + { + //#define HEADER_MAX_LEN 16 + //#define BLYNK_SERVER_MAX_LEN 32 + //#define BLYNK_TOKEN_MAX_LEN 36 + //#define STATIC_IP_MAX_LEN 16 + //#define BOARD_NAME_MAX_LEN 24 + + // NULL Terminating to be sure + BlynkEthernet_WM_config.header[HEADER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server[BLYNK_SERVER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token [BLYNK_TOKEN_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server[BLYNK_SERVER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token [BLYNK_TOKEN_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.blynk_port = BLYNK_SERVER_HARDWARE_PORT; + BlynkEthernet_WM_config.static_IP[STATIC_IP_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.board_name [BOARD_NAME_MAX_LEN - 1] = 0; + } + + ////////////////////////////////////////////// void loadConfigData() { BLYNK_LOG1(BLYNK_F("LoadCfgFile ")); // file existed - file.open(CONFIG_FILENAME, FILE_O_READ); + file.open(CONFIG_FILENAME, FILE_O_READ); + if (!file) { BLYNK_LOG1(BLYNK_F("failed")); @@ -994,7 +1218,11 @@ class BlynkEthernet BLYNK_LOG1(BLYNK_F("OK")); file.close(); + + NULLTerminateConfig(); } + + ////////////////////////////////////////////// void saveConfigData() { @@ -1037,7 +1265,9 @@ class BlynkEthernet BLYNK_LOG1(BLYNK_F("failed")); } +#if USE_DYNAMIC_PARAMETERS saveDynamicData(); +#endif } void loadAndSaveDefaultConfigData() @@ -1058,7 +1288,7 @@ class BlynkEthernet // Return false if init new EEPROM or SPIFFS. No more need trying to connect. Go directly to config mode bool getConfigData() { - bool dynamicDataValid; + bool dynamicDataValid = true; int calChecksum; hadConfigData = false; @@ -1083,49 +1313,59 @@ class BlynkEthernet { // Load stored config data from LittleFS loadConfigData(); - - // Load stored default data from LittleFS - //dynamicDataValid = loadDynamicData(); - dynamicDataValid = checkDynamicData(); - + // Verify ChkSum calChecksum = calcChecksum(); BLYNK_LOG4(BLYNK_F("CCSum=0x"), String(calChecksum, HEX), BLYNK_F(",RCSum=0x"), String(BlynkEthernet_WM_config.checkSum, HEX)); + +#if USE_DYNAMIC_PARAMETERS + // Load stored dynamic data from LittleFS + dynamicDataValid = checkDynamicData(); +#endif - if (dynamicDataValid) + // If checksum = 0 => LittleFS has been cleared (by uploading new FW, etc) => force to CP + // If bad checksum = 0 => force to CP + if ( (calChecksum != 0) && (calChecksum == BlynkEthernet_WM_config.checkSum) ) { - loadDynamicData(); - -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("Valid Stored Dynamic Data")); -#endif - BLYNK_LOG1(BLYNK_F("======= Start Stored Config Data =======")); - displayConfigData(BlynkEthernet_WM_config); - - // Don't need Config Portal anymore - return true; - } - else - { - // Invalid Stored config data => Config Portal - BLYNK_LOG1(BLYNK_F("Invalid Stored Dynamic Data. Load default from Sketch")); - - // Load Default Config Data from Sketch, better than just "blank" - loadAndSaveDefaultConfigData(); - - // Need Config Portal here as data can be just dummy - // Even if you don't open CP, you're OK on next boot if your default config data is valid - return false; - } + if (dynamicDataValid) + { + #if USE_DYNAMIC_PARAMETERS + loadDynamicData(); + + #if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("Valid Stored Dynamic Data")); + #endif + #endif + + BLYNK_LOG1(BLYNK_F("======= Start Stored Config Data =======")); + displayConfigData(BlynkEthernet_WM_config); + + // Don't need Config Portal anymore + return true; + } + else + { + // Invalid Stored config data => Config Portal + BLYNK_LOG1(BLYNK_F("Invalid Stored Dynamic Data. Load default from Sketch")); + + // Load Default Config Data from Sketch, better than just "blank" + loadAndSaveDefaultConfigData(); + + // Need Config Portal here as data can be just dummy + // Even if you don't open CP, you're OK on next boot if your default config data is valid + return false; + } + } } if ( (strncmp(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE, strlen(BLYNK_BOARD_TYPE)) != 0) || - (calChecksum != BlynkEthernet_WM_config.checkSum) || !dynamicDataValid ) - { + (calChecksum != BlynkEthernet_WM_config.checkSum) || !dynamicDataValid || + ( (calChecksum == 0) && (BlynkEthernet_WM_config.checkSum == 0) ) ) + { // Including Credentials CSum - BLYNK_LOG2(BLYNK_F("InitCfgFile,sz="), sizeof(BlynkEthernet_WM_config)); + BLYNK_LOG2(F("InitCfgFile,Sz="), sizeof(BlynkEthernet_WM_config)); // doesn't have any configuration if (LOAD_DEFAULT_CONFIG_DATA) @@ -1133,7 +1373,7 @@ class BlynkEthernet memcpy(&BlynkEthernet_WM_config, &defaultConfig, sizeof(BlynkEthernet_WM_config)); } else - { + { memset(&BlynkEthernet_WM_config, 0, sizeof(BlynkEthernet_WM_config)); #if USE_DYNAMIC_PARAMETERS @@ -1143,7 +1383,11 @@ class BlynkEthernet memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); } #endif - + + // Including Credentials CSum + BLYNK_LOG2(BLYNK_F("InitCfgFile,DataSz="), totalDataSize); + + // doesn't have any configuration strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, WM_NO_CONFIG); strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token, WM_NO_CONFIG); strcpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server, WM_NO_CONFIG); @@ -1152,29 +1396,28 @@ class BlynkEthernet strcpy(BlynkEthernet_WM_config.static_IP, WM_NO_CONFIG); strcpy(BlynkEthernet_WM_config.board_name, WM_NO_CONFIG); -#if USE_DYNAMIC_PARAMETERS +#if USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { strncpy(myMenuItems[i].pdata, WM_NO_CONFIG, myMenuItems[i].maxlen); } #endif } - strcpy(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE); - #if (USE_DYNAMIC_PARAMETERS && ( BLYNK_WM_DEBUG > 2)) +#if ( BLYNK_WM_DEBUG > 2) && USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { BLYNK_LOG4(BLYNK_F("g:myMenuItems["), i, BLYNK_F("]="), myMenuItems[i].pdata ); } - #endif - +#endif + // Don't need BlynkEthernet_WM_config.checkSum = 0; saveConfigData(); - + return false; } else if ( !strncmp(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || @@ -1183,9 +1426,6 @@ class BlynkEthernet !strncmp(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) ) { // If SSID, PW, Server,Token ="nothing", stay in config mode forever until having config Data. -#if ( BLYNK_WM_DEBUG > 2) - displayConfigData(BlynkEthernet_WM_config); -#endif return false; } else @@ -1195,6 +1435,8 @@ class BlynkEthernet return true; } + + ////////////////////////////////////////////// bool connectMultiBlynk() { @@ -1332,91 +1574,136 @@ class BlynkEthernet strcpy(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE); } - if (key == "sv") +#if USE_DYNAMIC_PARAMETERS + if (!menuItemUpdated) + { + // Don't need to free + menuItemUpdated = new bool[NUM_MENU_ITEMS]; + + if (menuItemUpdated) + { + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + // To flag item is not yet updated + menuItemUpdated[i] = false; + } + #if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("h: Init menuItemUpdated" )); + #endif + } + else + { + BLYNK_LOG1(BLYNK_F("h: Error can't alloc memory for menuItemUpdated" )); + } + } +#endif + + static bool sv_Updated = false; + static bool tk_Updated = false; + static bool sv1_Updated = false; + static bool tk1_Updated = false; + static bool pt_Updated = false; + static bool ip_Updated = false; + static bool nm_Updated = false; + + //if (key == "sv") + if (!sv_Updated && (key == String("sv"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:sv")); #endif + sv_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server) - 1); } - else if (key == "tk") + else if (!tk_Updated && (key == String("tk"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:tk")); #endif + tk_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token) - 1); } - else if (key == "sv1") + else if (!sv1_Updated && (key == String("sv1"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:sv1")); #endif + sv1_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server) - 1); } - else if (key == "tk1") + else if (!tk1_Updated && (key == String("tk1"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:tk1")); #endif + tk1_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token) - 1); } - else if (key == "pt") + else if (!pt_Updated && (key == String("pt"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:pt")); #endif + pt_Updated = true; number_items_Updated++; BlynkEthernet_WM_config.blynk_port = value.toInt(); } - else if (key == "ip") + else if (!ip_Updated && (key == String("ip"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:ip")); #endif + ip_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.static_IP) - 1) strcpy(BlynkEthernet_WM_config.static_IP, value.c_str()); else strncpy(BlynkEthernet_WM_config.static_IP, value.c_str(), sizeof(BlynkEthernet_WM_config.static_IP) - 1); } - else if (key == "nm") + else if (!nm_Updated && (key == String("nm"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:nm")); #endif + nm_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.board_name) - 1) strcpy(BlynkEthernet_WM_config.board_name, value.c_str()); else strncpy(BlynkEthernet_WM_config.board_name, value.c_str(), sizeof(BlynkEthernet_WM_config.board_name) - 1); } -#if (BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("h:OK")); -#endif - -#if USE_DYNAMIC_PARAMETERS +#if USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - if (key == myMenuItems[i].id) + if ( !menuItemUpdated[i] && (key == myMenuItems[i].id) ) { - //BLYNK_LOG4(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); + BLYNK_LOG4(BLYNK_F("h:"), myMenuItems[i].id, BLYNK_F("="), value.c_str() ); + + menuItemUpdated[i] = true; + number_items_Updated++; // Actual size of pdata is [maxlen + 1] @@ -1426,26 +1713,32 @@ class BlynkEthernet strcpy(myMenuItems[i].pdata, value.c_str()); else strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); - -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG4(BLYNK_F("h2:myMenuItems["), i, BLYNK_F("]="), myMenuItems[i].pdata ); -#endif } } #endif + //#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG2(F("h:items updated ="), number_items_Updated); + BLYNK_LOG4(F("h:key ="), key, ", value =", value); + //#endif + server->send(200, "text/html", "OK"); - // NEW +#if USE_DYNAMIC_PARAMETERS if (number_items_Updated == NUM_CONFIGURABLE_ITEMS + NUM_MENU_ITEMS) - { -#if USE_SPIFFS - BLYNK_LOG2(BLYNK_F("h:UpdSPIFFS:"), CONFIG_FILENAME); #else + if (number_items_Updated == NUM_CONFIGURABLE_ITEMS) +#endif + { +#if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:UpdEEPROM")); #endif saveConfigData(); + + // Done with CP, Clear CP Flag here if forced + if (isForcedConfigPortal) + clearForcedCP(); #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:Rst")); @@ -1453,7 +1746,6 @@ class BlynkEthernet // Delay then reset after save data delay(200); - //BlynkReset(); resetFunc(); } } // if (server) diff --git a/src/Adapters/BlynkEthernet_SAMD_WM.h b/src/Adapters/BlynkEthernet_SAMD_WM.h index d33a2c06..17a251cd 100644 --- a/src/Adapters/BlynkEthernet_SAMD_WM.h +++ b/src/Adapters/BlynkEthernet_SAMD_WM.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,6 +38,7 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkEthernet_SAMD_WM_h @@ -118,13 +119,20 @@ typedef struct } MenuItem; // -///NEW -extern uint16_t NUM_MENU_ITEMS; -extern MenuItem myMenuItems []; +#if USE_DYNAMIC_PARAMETERS + extern uint16_t NUM_MENU_ITEMS; + extern MenuItem myMenuItems []; + bool *menuItemUpdated = NULL; +#endif + +#define HEADER_MAX_LEN 16 #define BLYNK_SERVER_MAX_LEN 32 #define BLYNK_TOKEN_MAX_LEN 36 +#define STATIC_IP_MAX_LEN 16 +#define BOARD_NAME_MAX_LEN 24 + typedef struct { char blynk_server[BLYNK_SERVER_MAX_LEN]; @@ -138,11 +146,11 @@ typedef struct typedef struct Configuration { - char header [16]; + char header [HEADER_MAX_LEN]; Blynk_Credentials Blynk_Creds [NUM_BLYNK_CREDENTIALS]; int blynk_port; - char static_IP [16]; - char board_name [24]; + char static_IP [STATIC_IP_MAX_LEN]; + char board_name [BOARD_NAME_MAX_LEN]; int checkSum; } Blynk_Configuration; @@ -354,7 +362,7 @@ class BlynkEthernet #define LED_ON HIGH void begin() - { + { //Turn OFF pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LED_OFF); @@ -371,21 +379,31 @@ class BlynkEthernet noConfigPortal = false; } //// New DRD //// -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("======= Start Default Config Data =======")); - displayConfigData(defaultConfig); + +#if ( BLYNK_WM_DEBUG > 2) + if (LOAD_DEFAULT_CONFIG_DATA) + { + BLYNK_LOG1(BLYNK_F("======= Start Default Config Data =======")); + displayConfigData(defaultConfig); + } #endif hadConfigData = getConfigData(); connectEthernet(); - //// New DRD //// - // noConfigPortal when getConfigData() OK and no DRD'ed - if (hadConfigData && noConfigPortal) - //// New DRD //// + isForcedConfigPortal = isForcedCP(); + + //// New DRD/MRD //// + // noConfigPortal when getConfigData() OK and no MRD/DRD'ed + //if (getConfigData() && noConfigPortal) + if (hadConfigData && noConfigPortal && (!isForcedConfigPortal) ) { hadConfigData = true; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(noConfigPortal? BLYNK_F("bg: noConfigPortal = true") : BLYNK_F("bg: noConfigPortal = false")); +#endif if (ethernetConnected) { @@ -416,9 +434,22 @@ class BlynkEthernet } } else - { - BLYNK_LOG2(BLYNK_F("b:Stay in CfgPortal:"), noConfigPortal ? BLYNK_F("No CfgDat") : BLYNK_F("DRD")); - + { +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(isForcedConfigPortal? BLYNK_F("bg: isForcedConfigPortal = true") : BLYNK_F("bg: isForcedConfigPortal = false")); +#endif + + // If not persistent => clear the flag so that after reset. no more CP, even CP not entered and saved + if (persForcedConfigPortal) + { + BLYNK_LOG2(BLYNK_F("bg:Stay forever in CP:"), isForcedConfigPortal ? BLYNK_F("Forced-Persistent") : (noConfigPortal ? BLYNK_F("No ConfigDat") : BLYNK_F("DRD/MRD"))); + } + else + { + BLYNK_LOG2(BLYNK_F("bg:Stay forever in CP:"), isForcedConfigPortal ? BLYNK_F("Forced-non-Persistent") : (noConfigPortal ? BLYNK_F("No ConfigDat") : BLYNK_F("DRD/MRD"))); + clearForcedCP(); + } + // failed to connect to Blynk server, will start configuration mode hadConfigData = false; startConfigurationMode(); @@ -476,7 +507,6 @@ class BlynkEthernet } else { - //BlynkReset(); resetFunc(); } } @@ -576,9 +606,47 @@ class BlynkEthernet } #endif - //EEPROM.put(BLYNK_EEPROM_START, BlynkEthernet_WM_config); saveConfigData(); } + + // Forced CP => Flag = 0xBEEFBEEF. Else => No forced CP + // Flag to be stored at (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // to avoid corruption to current data + //#define FORCED_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xDEADBEEF) + //#define FORCED_PERS_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xBEEFDEAD) + + const uint32_t FORCED_CONFIG_PORTAL_FLAG_DATA = 0xDEADBEEF; + const uint32_t FORCED_PERS_CONFIG_PORTAL_FLAG_DATA = 0xBEEFDEAD; + + #define FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE 4 + + void resetAndEnterConfigPortal() + { + persForcedConfigPortal = false; + + setForcedCP(false); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + // This will keep CP forever, until you successfully enter CP, and Save data to clear the flag. + void resetAndEnterConfigPortalPersistent() + { + persForcedConfigPortal = true; + + setForcedCP(true); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + void resetFunc() + { + NVIC_SystemReset(); + } private: @@ -593,6 +661,9 @@ class BlynkEthernet unsigned long configTimeout; bool hadConfigData = false; + + bool isForcedConfigPortal = false; + bool persForcedConfigPortal = false; Blynk_Configuration BlynkEthernet_WM_config; @@ -686,6 +757,8 @@ class BlynkEthernet // Stating positon to store Blynk8266_WM_config #define BLYNK_EEPROM_START (EEPROM_START + DRD_FLAG_DATA_SIZE) + ////////////////////////////////////////////// + int calcChecksum() { int checkSum = 0; @@ -696,97 +769,160 @@ class BlynkEthernet return checkSum; } + + ////////////////////////////////////////////// + + void setForcedCP(bool isPersistent) + { + uint32_t readForcedConfigPortalFlag = isPersistent? FORCED_PERS_CONFIG_PORTAL_FLAG_DATA : FORCED_CONFIG_PORTAL_FLAG_DATA; - bool checkDynamicData() +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("setForcedCP")); +#endif + + EEPROM.put(BLYNK_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag); + EEPROM.commit(); + } + ////////////////////////////////////////////// + + void clearForcedCP() { -#if USE_DYNAMIC_PARAMETERS +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("clearForcedCP")); +#endif + + EEPROM.put(BLYNK_EEPROM_START + CONFIG_DATA_SIZE, 0); + EEPROM.commit(); + } - // It's too bad that emulate EEPROM.read()/write() can only deal with bytes. - // Have to read/write each byte. To rewrite the library + ////////////////////////////////////////////// + + bool isForcedCP() + { + uint32_t readForcedConfigPortalFlag; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("Check if isForcedCP")); +#endif + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + EEPROM.get(BLYNK_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag); + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + if (readForcedConfigPortalFlag == FORCED_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = false; + return true; + } + else if (readForcedConfigPortalFlag == FORCED_PERS_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = true; + return true; + } + else + { + return false; + } + } + + ////////////////////////////////////////////// + +#if USE_DYNAMIC_PARAMETERS + + bool checkDynamicData() + { int checkSum = 0; int readCheckSum; - //#define BUFFER_LEN 128 - //char readBuffer[BUFFER_LEN + 1]; + #define BUFFER_LEN 128 + char readBuffer[BUFFER_LEN + 1]; - uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config); + uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; // Find the longest pdata, then dynamically allocate buffer. Remember to free when done // This is used to store tempo data to calculate checksum to see of data is valid // We dont like to destroy myMenuItems[i].pdata with invalid data - for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) - { - for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++, offset++) - { - checkSum += EEPROM.read(offset); - } + { + if (myMenuItems[i].maxlen > BUFFER_LEN) + { + // Size too large, abort and flag false + BLYNK_LOG1(BLYNK_F("ChkCrR: Error Small Buffer.")); + return false; + } } - - uint8_t* _pointer = (uint8_t *) &readCheckSum; - - for (uint16_t i = 0; i < sizeof(readCheckSum); i++, _pointer++, offset++) - { - *_pointer = EEPROM.read(offset); - } - - BLYNK_LOG4(F("ChkCrR:CrCCSum=0x"), String(checkSum, HEX), F(",CrRCSum=0x"), String(readCheckSum, HEX)); + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + char* _pointer = readBuffer; + + // Prepare buffer, more than enough + memset(readBuffer, 0, sizeof(readBuffer)); + + // Read more than necessary, but OK and easier to code + EEPROM.get(offset, readBuffer); + // NULL terminated + readBuffer[myMenuItems[i].maxlen] = 0; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG4(F("ChkCrR:pdata="), readBuffer, F(",len="), myMenuItems[i].maxlen); +#endif + + for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++) + { + checkSum += *_pointer; + } + + offset += myMenuItems[i].maxlen; + } + + EEPROM.get(offset, readCheckSum); + + BLYNK_LOG4(F("ChkCrR:CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum) { return false; } -#endif return true; } + + ////////////////////////////////////////////// - bool EEPROM_get() + bool EEPROM_getDynamicData() { - // It's too bad that emulate EEPROM.read()/write() can only deal with bytes. - // Have to read/write each byte. To rewrite the library - - uint16_t offset = BLYNK_EEPROM_START; - - uint8_t* _pointer = (uint8_t *) &BlynkEthernet_WM_config; - - for (uint16_t i = 0; i < sizeof(BlynkEthernet_WM_config); i++, _pointer++, offset++) - { - *_pointer = EEPROM.read(offset); - } - - int checkSum = 0; int readCheckSum; - + int checkSum = 0; + uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; + totalDataSize = sizeof(BlynkEthernet_WM_config) + sizeof(readCheckSum); - -#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - _pointer = (uint8_t *) myMenuItems[i].pdata; + 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++) + for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++,offset++) { - *_pointer = EEPROM.read(offset); + *_pointer = EEPROM.read(offset); + checkSum += *_pointer; - } + } +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG4(F("CR:pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); +#endif } -#endif - _pointer = (uint8_t *) &readCheckSum; + EEPROM.get(offset, readCheckSum); - for (uint16_t i = 0; i < sizeof(readCheckSum); i++, _pointer++, offset++) - { - *_pointer = EEPROM.read(offset); - } - - BLYNK_LOG4(F("CrCCSum=0x"), String(checkSum, HEX), F(",CrRCSum=0x"), String(readCheckSum, HEX)); + BLYNK_LOG4(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum) { @@ -794,33 +930,23 @@ class BlynkEthernet } return true; - } + } - void EEPROM_put() + ////////////////////////////////////////////// + + void EEPROM_putDynamicData() { - // It's too bad that emulate EEPROM.read()/writ() can only deal with bytes. - // Have to read/write each byte. To rewrite the library - - uint16_t offset = BLYNK_EEPROM_START; - - uint8_t* _pointer = (uint8_t *) &BlynkEthernet_WM_config; - - for (uint16_t i = 0; i < sizeof(BlynkEthernet_WM_config); i++, _pointer++, offset++) - { - EEPROM.write(offset, *_pointer); - } - int checkSum = 0; - -#if USE_DYNAMIC_PARAMETERS + uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - _pointer = (uint8_t *) myMenuItems[i].pdata; + char* _pointer = myMenuItems[i].pdata; #if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG4(BLYNK_F("pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); + BLYNK_LOG4(F("CW:pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); #endif - + for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++,offset++) { EEPROM.write(offset, *_pointer); @@ -828,20 +954,95 @@ class BlynkEthernet checkSum += *_pointer; } } -#endif - _pointer = (uint8_t *) &checkSum; + EEPROM.put(offset, checkSum); + //EEPROM.commit(); + + BLYNK_LOG2(F("CrWCSum=0x"), String(checkSum, HEX)); + } +#endif + + ////////////////////////////////////////////// + + void NULLTerminateConfig() + { + //#define HEADER_MAX_LEN 16 + //#define BLYNK_SERVER_MAX_LEN 32 + //#define BLYNK_TOKEN_MAX_LEN 36 + //#define STATIC_IP_MAX_LEN 16 + //#define BOARD_NAME_MAX_LEN 24 + + // NULL Terminating to be sure + BlynkEthernet_WM_config.header[HEADER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server[BLYNK_SERVER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token [BLYNK_TOKEN_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server[BLYNK_SERVER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token [BLYNK_TOKEN_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.blynk_port = BLYNK_SERVER_HARDWARE_PORT; + BlynkEthernet_WM_config.static_IP[STATIC_IP_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.board_name [BOARD_NAME_MAX_LEN - 1] = 0; + } + + ////////////////////////////////////////////// + + bool EEPROM_get() + { + // It's too bad that emulate EEPROM.read()/write() can only deal with bytes. + // Have to read/write each byte. To rewrite the library - for (uint16_t i = 0; i < sizeof(checkSum); i++, _pointer++, offset++) + uint16_t offset = BLYNK_EEPROM_START; + + uint8_t* _pointer = (uint8_t *) &BlynkEthernet_WM_config; + + for (uint16_t i = 0; i < sizeof(BlynkEthernet_WM_config); i++, _pointer++, offset++) { - EEPROM.write(offset, *_pointer); + *_pointer = EEPROM.read(offset); } + + NULLTerminateConfig(); + + return true; + } + + ////////////////////////////////////////////// + + void EEPROM_put() + { + // It's too bad that emulate EEPROM.read()/writ() can only deal with bytes. + // Have to read/write each byte. To rewrite the library + uint16_t offset = BLYNK_EEPROM_START; + + uint8_t* _pointer = (uint8_t *) &BlynkEthernet_WM_config; + + for (uint16_t i = 0; i < sizeof(BlynkEthernet_WM_config); i++, _pointer++, offset++) + { + EEPROM.write(offset, *_pointer); + } + EEPROM.commit(); + } + + + + ////////////////////////////////////////////// + + void saveConfigData() + { + int calChecksum = calcChecksum(); + BlynkEthernet_WM_config.checkSum = calChecksum; - BLYNK_LOG2(F("CrCCSum=0x"), String(checkSum, HEX)); + BLYNK_LOG6(F("SaveEEPROM,Sz="), EEPROM.length(), F(",DataSz="), totalDataSize, F(",WCSum=0x"), String(calChecksum, HEX)); + + EEPROM_put(); + +#if USE_DYNAMIC_PARAMETERS + EEPROM_putDynamicData(); +#endif } + ////////////////////////////////////////////// + void loadAndSaveDefaultConfigData() { // Load Default Config Data from Sketch @@ -857,9 +1058,11 @@ class BlynkEthernet #endif } + ////////////////////////////////////////////// + bool getConfigData() { - bool dynamicDataValid; + bool dynamicDataValid = true; int calChecksum; hadConfigData = false; @@ -875,50 +1078,62 @@ class BlynkEthernet } else { - // Load stored config / dynamic data from EEPROM-simulated FlashStorage - //dynamicDataValid = EEPROM_get(); - dynamicDataValid = checkDynamicData(); + // Load stored config from EEPROM-simulated FlashStorage + EEPROM_get(); // Verify ChkSum calChecksum = calcChecksum(); BLYNK_LOG4(BLYNK_F("CCSum=0x"), String(calChecksum, HEX), BLYNK_F(",RCSum=0x"), String(BlynkEthernet_WM_config.checkSum, HEX)); - - if (dynamicDataValid) - { - // CkSum verified, Now get valid config/ dynamic data - EEPROM_get(); - -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("Valid Stored Dynamic Data")); -#endif - BLYNK_LOG1(BLYNK_F("======= Start Stored Config Data =======")); - displayConfigData(BlynkEthernet_WM_config); - - // Don't need Config Portal anymore - return true; - } - else - { - // Invalid Stored config data => Config Portal - BLYNK_LOG1(BLYNK_F("Invalid Stored Dynamic Data. Load default from Sketch")); - - // Load Default Config Data from Sketch, better than just "blank" - loadAndSaveDefaultConfigData(); - - // Need Config Portal here as data can be just dummy - // Even if you don't open CP, you're OK on next boot if your default config data is valid - return false; - } + +#if USE_DYNAMIC_PARAMETERS + // Load stored dynamic data from dueFlashStorage + dynamicDataValid = checkDynamicData(); +#endif + // If checksum = 0 => DueFlashStorage has been cleared (by uploading new FW, etc) => force to CP + // If bad checksum = 0 => force to CP + if ( (calChecksum != 0) && (calChecksum == BlynkEthernet_WM_config.checkSum) ) + { + if (dynamicDataValid) + { + #if USE_DYNAMIC_PARAMETERS + // CkSum verified, Now get valid dynamic data + EEPROM_getDynamicData(); + + #if ( BLYNK_WM_DEBUG > 2 ) + BLYNK_LOG1(BLYNK_F("Valid Stored Dynamic Data")); + #endif + #endif + + BLYNK_LOG1(BLYNK_F("======= Start Stored Config Data =======")); + displayConfigData(BlynkEthernet_WM_config); + + // Don't need Config Portal anymore + return true; + } + else + { + // Invalid Stored config data => Config Portal + BLYNK_LOG1(BLYNK_F("Invalid Stored Dynamic Data. Load default from Sketch")); + + // Load Default Config Data from Sketch, better than just "blank" + loadAndSaveDefaultConfigData(); + + // Need Config Portal here as data can be just dummy + // Even if you don't open CP, you're OK on next boot if your default config data is valid + return false; + } + } } if ( (strncmp(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE, strlen(BLYNK_BOARD_TYPE)) != 0) || - (calChecksum != BlynkEthernet_WM_config.checkSum) || !dynamicDataValid ) + (calChecksum != BlynkEthernet_WM_config.checkSum) || !dynamicDataValid || + ( (calChecksum == 0) && (BlynkEthernet_WM_config.checkSum == 0) ) ) { // Including Credentials CSum - BLYNK_LOG2(F("InitEEPROM,Datasz="), totalDataSize); - + BLYNK_LOG2(F("InitCfgFile,Sz="), sizeof(BlynkEthernet_WM_config)); + // doesn't have any configuration if (LOAD_DEFAULT_CONFIG_DATA) { @@ -937,7 +1152,7 @@ class BlynkEthernet #endif // Including Credentials CSum - BLYNK_LOG4(F("InitEEPROM,sz="), EEPROM_SIZE, F(",Datasz="), totalDataSize); + BLYNK_LOG2(BLYNK_F("InitCfgFile,DataSz="), totalDataSize); // doesn't have any configuration strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, WM_NO_CONFIG); @@ -948,17 +1163,17 @@ class BlynkEthernet strcpy(BlynkEthernet_WM_config.static_IP, WM_NO_CONFIG); strcpy(BlynkEthernet_WM_config.board_name, WM_NO_CONFIG); -#if USE_DYNAMIC_PARAMETERS +#if USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { strncpy(myMenuItems[i].pdata, WM_NO_CONFIG, myMenuItems[i].maxlen); } #endif } - + strcpy(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE); - -#if (USE_DYNAMIC_PARAMETERS && ( BLYNK_WM_DEBUG > 2)) + +#if ( BLYNK_WM_DEBUG > 2) && USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { BLYNK_LOG4(BLYNK_F("g:myMenuItems["), i, BLYNK_F("]="), myMenuItems[i].pdata ); @@ -968,7 +1183,7 @@ class BlynkEthernet // Don't need BlynkEthernet_WM_config.checkSum = 0; - EEPROM_put(); + saveConfigData(); return false; } @@ -988,15 +1203,7 @@ class BlynkEthernet return true; } - void saveConfigData() - { - int calChecksum = calcChecksum(); - BlynkEthernet_WM_config.checkSum = calChecksum; - - BLYNK_LOG6(F("SaveEEPROM,Sz="), EEPROM.length(), F(",DataSz="), totalDataSize, F(",WCSum=0x"), String(calChecksum, HEX)); - - EEPROM_put(); - } + ////////////////////////////////////////////// bool connectMultiBlynk() { @@ -1021,6 +1228,8 @@ class BlynkEthernet return false; } + + ////////////////////////////////////////////// void createHTML(String& root_html_template) { @@ -1068,7 +1277,8 @@ class BlynkEthernet return; } - //// + + ////////////////////////////////////////////// void handleRequest() { @@ -1133,91 +1343,136 @@ class BlynkEthernet strcpy(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE); } - if (key == "sv") +#if USE_DYNAMIC_PARAMETERS + if (!menuItemUpdated) + { + // Don't need to free + menuItemUpdated = new bool[NUM_MENU_ITEMS]; + + if (menuItemUpdated) + { + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + // To flag item is not yet updated + menuItemUpdated[i] = false; + } + #if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("h: Init menuItemUpdated" )); + #endif + } + else + { + BLYNK_LOG1(BLYNK_F("h: Error can't alloc memory for menuItemUpdated" )); + } + } +#endif + + static bool sv_Updated = false; + static bool tk_Updated = false; + static bool sv1_Updated = false; + static bool tk1_Updated = false; + static bool pt_Updated = false; + static bool ip_Updated = false; + static bool nm_Updated = false; + + //if (key == "sv") + if (!sv_Updated && (key == String("sv"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:sv")); #endif + sv_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server) - 1); } - else if (key == "tk") + else if (!tk_Updated && (key == String("tk"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:tk")); #endif + tk_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token) - 1); } - else if (key == "sv1") + else if (!sv1_Updated && (key == String("sv1"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:sv1")); #endif + sv1_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server) - 1); } - else if (key == "tk1") + else if (!tk1_Updated && (key == String("tk1"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:tk1")); #endif + tk1_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token) - 1); } - else if (key == "pt") + else if (!pt_Updated && (key == String("pt"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:pt")); #endif + pt_Updated = true; number_items_Updated++; BlynkEthernet_WM_config.blynk_port = value.toInt(); } - else if (key == "ip") + else if (!ip_Updated && (key == String("ip"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:ip")); #endif + ip_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.static_IP) - 1) strcpy(BlynkEthernet_WM_config.static_IP, value.c_str()); else strncpy(BlynkEthernet_WM_config.static_IP, value.c_str(), sizeof(BlynkEthernet_WM_config.static_IP) - 1); } - else if (key == "nm") + else if (!nm_Updated && (key == String("nm"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:nm")); #endif + nm_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.board_name) - 1) strcpy(BlynkEthernet_WM_config.board_name, value.c_str()); else strncpy(BlynkEthernet_WM_config.board_name, value.c_str(), sizeof(BlynkEthernet_WM_config.board_name) - 1); } -#if (BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("h:OK")); -#endif - -#if USE_DYNAMIC_PARAMETERS +#if USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - if (key == myMenuItems[i].id) + if ( !menuItemUpdated[i] && (key == myMenuItems[i].id) ) { - //BLYNK_LOG4(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); + BLYNK_LOG4(BLYNK_F("h:"), myMenuItems[i].id, BLYNK_F("="), value.c_str() ); + + menuItemUpdated[i] = true; + number_items_Updated++; // Actual size of pdata is [maxlen + 1] @@ -1227,24 +1482,32 @@ class BlynkEthernet strcpy(myMenuItems[i].pdata, value.c_str()); else strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); - -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG4(BLYNK_F("h2:myMenuItems["), i, BLYNK_F("]="), myMenuItems[i].pdata ); -#endif } } #endif + //#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG2(F("h:items updated ="), number_items_Updated); + BLYNK_LOG4(F("h:key ="), key, ", value =", value); + //#endif + server->send(200, "text/html", "OK"); - // NEW +#if USE_DYNAMIC_PARAMETERS if (number_items_Updated == NUM_CONFIGURABLE_ITEMS + NUM_MENU_ITEMS) +#else + if (number_items_Updated == NUM_CONFIGURABLE_ITEMS) +#endif { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:UpdEEPROM")); #endif saveConfigData(); + + // Done with CP, Clear CP Flag here if forced + if (isForcedConfigPortal) + clearForcedCP(); #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:Rst")); @@ -1252,10 +1515,12 @@ class BlynkEthernet // Delay then reset after save data delay(200); - BlynkReset(); + resetFunc(); } } // if (server) } + + ////////////////////////////////////////////// void startConfigurationMode() { @@ -1286,6 +1551,8 @@ class BlynkEthernet configuration_mode = true; } + + ////////////////////////////////////////////// bool connectEthernet() { @@ -1322,6 +1589,8 @@ class BlynkEthernet return ethernetConnected; } + + ////////////////////////////////////////////// byte* SelectMacAddress(const char* token, const byte mac[]) { diff --git a/src/Adapters/BlynkEthernet_WM.h b/src/Adapters/BlynkEthernet_WM.h index e6e034cf..02b62c63 100644 --- a/src/Adapters/BlynkEthernet_WM.h +++ b/src/Adapters/BlynkEthernet_WM.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,28 +38,32 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkEthernet_WM_h #define BlynkEthernet_WM_h #if !( defined(CORE_TEENSY) && !( defined(__MKL26Z64__) || defined(__AVR_AT90USB1286__) || defined(__AVR_ATmega32U4__) ) ) -#error This code is designed to run on Teensy 4.0 and 3.x boards! Please check your Tools->Board setting. + #error This code is designed to run on Teensy 4.x and 3.x boards! Please check your Tools->Board setting. #endif +#if !( (TEENSYDUINO==150) || (TEENSYDUINO==151) || USE_NATIVE_ETHERNET ) + #error This code is intended to run only on the Teensy code v1.51 if not using NativeEthernet ! Please check your Teensy core. +#endif #ifndef BLYNK_WM_DEBUG -#define BLYNK_WM_DEBUG 0 + #define BLYNK_WM_DEBUG 0 #endif #ifndef BLYNK_INFO_CONNECTION -#define BLYNK_INFO_CONNECTION "W5000" + #define BLYNK_INFO_CONNECTION "W5000" #endif #ifdef BLYNK_USE_SSL -#define BLYNK_SERVER_PORT BLYNK_DEFAULT_PORT_SSL + #define BLYNK_SERVER_PORT BLYNK_DEFAULT_PORT_SSL #else -#define BLYNK_SERVER_PORT BLYNK_DEFAULT_PORT + #define BLYNK_SERVER_PORT BLYNK_DEFAULT_PORT #endif #include @@ -77,7 +81,7 @@ #define DRD_FLAG_DATA_SIZE 4 #ifndef DOUBLERESETDETECTOR_DEBUG -#define DOUBLERESETDETECTOR_DEBUG false + #define DOUBLERESETDETECTOR_DEBUG false #endif #include //https://github.com/khoih-prog/DoubleResetDetector_Generic @@ -106,13 +110,20 @@ typedef struct } MenuItem; // -///NEW -extern uint16_t NUM_MENU_ITEMS; -extern MenuItem myMenuItems []; +#if USE_DYNAMIC_PARAMETERS + extern uint16_t NUM_MENU_ITEMS; + extern MenuItem myMenuItems []; + bool *menuItemUpdated = NULL; +#endif + +#define HEADER_MAX_LEN 16 #define BLYNK_SERVER_MAX_LEN 32 #define BLYNK_TOKEN_MAX_LEN 36 +#define STATIC_IP_MAX_LEN 16 +#define BOARD_NAME_MAX_LEN 24 + typedef struct { char blynk_server[BLYNK_SERVER_MAX_LEN]; @@ -126,11 +137,11 @@ typedef struct typedef struct Configuration { - char header [16]; + char header [HEADER_MAX_LEN]; Blynk_Credentials Blynk_Creds [NUM_BLYNK_CREDENTIALS]; int blynk_port; - char static_IP [16]; - char board_name [24]; + char static_IP [STATIC_IP_MAX_LEN]; + char board_name [BOARD_NAME_MAX_LEN]; int checkSum; } Blynk_Configuration; @@ -341,8 +352,7 @@ class BlynkEthernet #define LED_ON HIGH void begin() - { - + { //Turn OFF pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LED_OFF); @@ -359,21 +369,31 @@ class BlynkEthernet noConfigPortal = false; } //// New DRD //// -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("======= Start Default Config Data =======")); - displayConfigData(defaultConfig); + +#if ( BLYNK_WM_DEBUG > 2) + if (LOAD_DEFAULT_CONFIG_DATA) + { + BLYNK_LOG1(BLYNK_F("======= Start Default Config Data =======")); + displayConfigData(defaultConfig); + } #endif hadConfigData = getConfigData(); connectEthernet(); - //// New DRD //// - // noConfigPortal when getConfigData() OK and no DRD'ed - if (hadConfigData && noConfigPortal) - //// New DRD //// + isForcedConfigPortal = isForcedCP(); + + //// New DRD/MRD //// + // noConfigPortal when getConfigData() OK and no MRD/DRD'ed + //if (getConfigData() && noConfigPortal) + if (hadConfigData && noConfigPortal && (!isForcedConfigPortal) ) { hadConfigData = true; + +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(noConfigPortal? BLYNK_F("bg: noConfigPortal = true") : BLYNK_F("bg: noConfigPortal = false")); +#endif if (ethernetConnected) { @@ -404,9 +424,22 @@ class BlynkEthernet } } else - { - BLYNK_LOG2(BLYNK_F("b:Stay in CfgPortal:"), noConfigPortal ? BLYNK_F("No CfgDat") : BLYNK_F("DRD")); - + { +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(isForcedConfigPortal? BLYNK_F("bg: isForcedConfigPortal = true") : BLYNK_F("bg: isForcedConfigPortal = false")); +#endif + + // If not persistent => clear the flag so that after reset. no more CP, even CP not entered and saved + if (persForcedConfigPortal) + { + BLYNK_LOG2(BLYNK_F("bg:Stay forever in CP:"), isForcedConfigPortal ? BLYNK_F("Forced-Persistent") : (noConfigPortal ? BLYNK_F("No ConfigDat") : BLYNK_F("DRD/MRD"))); + } + else + { + BLYNK_LOG2(BLYNK_F("bg:Stay forever in CP:"), isForcedConfigPortal ? BLYNK_F("Forced-non-Persistent") : (noConfigPortal ? BLYNK_F("No ConfigDat") : BLYNK_F("DRD/MRD"))); + clearForcedCP(); + } + // failed to connect to Blynk server, will start configuration mode hadConfigData = false; startConfigurationMode(); @@ -564,10 +597,43 @@ class BlynkEthernet } #endif - //EEPROM.put(BLYNK_EEPROM_START, BlynkEthernet_WM_config); saveConfigData(); } + // Forced CP => Flag = 0xBEEFBEEF. Else => No forced CP + // Flag to be stored at (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // to avoid corruption to current data + //#define FORCED_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xDEADBEEF) + //#define FORCED_PERS_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xBEEFDEAD) + + const uint32_t FORCED_CONFIG_PORTAL_FLAG_DATA = 0xDEADBEEF; + const uint32_t FORCED_PERS_CONFIG_PORTAL_FLAG_DATA = 0xBEEFDEAD; + + #define FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE 4 + + void resetAndEnterConfigPortal() + { + persForcedConfigPortal = false; + + setForcedCP(false); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + // This will keep CP forever, until you successfully enter CP, and Save data to clear the flag. + void resetAndEnterConfigPortalPersistent() + { + persForcedConfigPortal = true; + + setForcedCP(true); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + void resetFunc() { #if defined(__IMXRT1062__) @@ -593,6 +659,9 @@ class BlynkEthernet unsigned long configTimeout; bool hadConfigData = false; + + bool isForcedConfigPortal = false; + bool persForcedConfigPortal = false; Blynk_Configuration BlynkEthernet_WM_config; @@ -706,18 +775,99 @@ class BlynkEthernet return checkSum; } + + ////////////////////////////////////////////// + + void setForcedCP(bool isPersistent) + { + uint32_t readForcedConfigPortalFlag = isPersistent? FORCED_PERS_CONFIG_PORTAL_FLAG_DATA : FORCED_CONFIG_PORTAL_FLAG_DATA; - bool checkDynamicData() +#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(isPersistent ? BLYNK_F("setForcedCP Persistent") : BLYNK_F("setForcedCP non-Persistent")); +#endif + + uint16_t offset = BLYNK_EEPROM_START + CONFIG_DATA_SIZE; + + uint8_t* _pointer = (uint8_t *) &readForcedConfigPortalFlag; + + for (uint16_t i = 0; i < sizeof(readForcedConfigPortalFlag); i++, _pointer++, offset++) + { + EEPROM.write(offset, *_pointer); + } + +#if !defined(CORE_TEENSY) + EEPROM.commit(); +#endif + } + + ////////////////////////////////////////////// + + void clearForcedCP() { -#if USE_DYNAMIC_PARAMETERS + uint32_t readForcedConfigPortalFlag = 0; + + uint16_t offset = BLYNK_EEPROM_START + CONFIG_DATA_SIZE; + + uint8_t* _pointer = (uint8_t *) &readForcedConfigPortalFlag; + + for (uint16_t i = 0; i < sizeof(readForcedConfigPortalFlag); i++, _pointer++, offset++) + { + EEPROM.write(offset, *_pointer); + } + +#if !defined(CORE_TEENSY) + EEPROM.commit(); +#endif + } + + ////////////////////////////////////////////// + + bool isForcedCP() + { + uint32_t readForcedConfigPortalFlag; + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + uint16_t offset = BLYNK_EEPROM_START + CONFIG_DATA_SIZE; + + uint8_t* _pointer = (uint8_t *) &readForcedConfigPortalFlag; + + for (uint16_t i = 0; i < sizeof(readForcedConfigPortalFlag); i++, _pointer++, offset++) + { + *_pointer = EEPROM.read(offset); + } + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + if (readForcedConfigPortalFlag == FORCED_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = false; + return true; + } + else if (readForcedConfigPortalFlag == FORCED_PERS_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = true; + return true; + } + else + { + return false; + } + } + + ////////////////////////////////////////////// +#if USE_DYNAMIC_PARAMETERS + + bool checkDynamicData() + { int checkSum = 0; int readCheckSum; #define BUFFER_LEN 255 char readBuffer[BUFFER_LEN + 1]; - uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config); + uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; // Find the longest pdata, then dynamically allocate buffer. Remember to free when done // This is used to store tempo data to calculate checksum to see of data is valid @@ -764,19 +914,17 @@ class BlynkEthernet if ( checkSum != readCheckSum) { return false; - } -#endif - + } return true; } - bool EEPROM_getDynamicData() - { -#if USE_DYNAMIC_PARAMETERS + ////////////////////////////////////////////// + bool EEPROM_getDynamicData() + { int readCheckSum; int checkSum = 0; - uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config); + uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; totalDataSize = sizeof(BlynkEthernet_WM_config) + sizeof(readCheckSum); @@ -804,16 +952,16 @@ class BlynkEthernet { return false; } -#endif return true; } + + ////////////////////////////////////////////// void EEPROM_putDynamicData() - { -#if USE_DYNAMIC_PARAMETERS + { int checkSum = 0; - uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config); + uint16_t offset = BLYNK_EEPROM_START + sizeof(BlynkEthernet_WM_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { @@ -832,9 +980,47 @@ class BlynkEthernet EEPROM.put(offset, checkSum); //EEPROM.commit(); - BLYNK_LOG2(F("CrCCSum=0x"), String(checkSum, HEX)); -#endif + BLYNK_LOG2(F("CrCCSum=0x"), String(checkSum, HEX)); } +#endif + + ////////////////////////////////////////////// + + void NULLTerminateConfig() + { + //#define HEADER_MAX_LEN 16 + //#define BLYNK_SERVER_MAX_LEN 32 + //#define BLYNK_TOKEN_MAX_LEN 36 + //#define STATIC_IP_MAX_LEN 16 + //#define BOARD_NAME_MAX_LEN 24 + + // NULL Terminating to be sure + BlynkEthernet_WM_config.header[HEADER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server[BLYNK_SERVER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token [BLYNK_TOKEN_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server[BLYNK_SERVER_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token [BLYNK_TOKEN_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.blynk_port = BLYNK_SERVER_HARDWARE_PORT; + BlynkEthernet_WM_config.static_IP[STATIC_IP_MAX_LEN - 1] = 0; + BlynkEthernet_WM_config.board_name [BOARD_NAME_MAX_LEN - 1] = 0; + } + + ////////////////////////////////////////////// + + void saveConfigData() + { + int calChecksum = calcChecksum(); + BlynkEthernet_WM_config.checkSum = calChecksum; + BLYNK_LOG2(BLYNK_F("Save,WCSum=0x"), String(calChecksum, HEX)); + + EEPROM.put(BLYNK_EEPROM_START, BlynkEthernet_WM_config); + +#if USE_DYNAMIC_PARAMETERS + EEPROM_putDynamicData(); +#endif + } + + ////////////////////////////////////////////// void loadAndSaveDefaultConfigData() { @@ -851,59 +1037,85 @@ class BlynkEthernet #endif } + ////////////////////////////////////////////// + bool getConfigData() - { - bool dynamicDataValid; + { + bool dynamicDataValid = true; + int calChecksum; - hadConfigData = false; + hadConfigData = false; EEPROM.begin(); - BLYNK_LOG2(BLYNK_F("EEPROMsz:"), EEPROM_SIZE); - EEPROM.get(BLYNK_EEPROM_START, BlynkEthernet_WM_config); - -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("======= Start Stored Config Data =======")); - displayConfigData(BlynkEthernet_WM_config); -#endif + + // Use new LOAD_DEFAULT_CONFIG_DATA logic + if (LOAD_DEFAULT_CONFIG_DATA) + { + // Load Config Data from Sketch + loadAndSaveDefaultConfigData(); + + // Don't need Config Portal anymore + return true; + } + else + { + // Load stored config from EEPROM-simulated FlashStorage + EEPROM.get(BLYNK_EEPROM_START, BlynkEthernet_WM_config); + + // Verify ChkSum + calChecksum = calcChecksum(); - int calChecksum = calcChecksum(); + BLYNK_LOG4(BLYNK_F("CCSum=0x"), String(calChecksum, HEX), + BLYNK_F(",RCSum=0x"), String(BlynkEthernet_WM_config.checkSum, HEX)); - BLYNK_LOG4(BLYNK_F("CCSum=0x"), String(calChecksum, HEX), - BLYNK_F(",RCSum=0x"), String(BlynkEthernet_WM_config.checkSum, HEX)); +#if USE_DYNAMIC_PARAMETERS + // Load stored dynamic data from dueFlashStorage + dynamicDataValid = checkDynamicData(); +#endif + // If checksum = 0 => DueFlashStorage has been cleared (by uploading new FW, etc) => force to CP + // If bad checksum = 0 => force to CP + if ( (calChecksum != 0) && (calChecksum == BlynkEthernet_WM_config.checkSum) ) + { + if (dynamicDataValid) + { + #if USE_DYNAMIC_PARAMETERS + // CkSum verified, Now get valid dynamic data + EEPROM_getDynamicData(); + + #if ( BLYNK_WM_DEBUG > 2 ) + BLYNK_LOG1(BLYNK_F("Valid Stored Dynamic Data")); + #endif + #endif - if (LOAD_DEFAULT_CONFIG_DATA) - { - // Load default dynamicData, if checkSum OK => valid data => load - // otherwise, use default in sketch and just assume it's OK - if (checkDynamicData()) - { -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("Valid Stored Dynamic Data")); -#endif - EEPROM_getDynamicData(); - dynamicDataValid = true; - } + BLYNK_LOG1(BLYNK_F("======= Start Stored Config Data =======")); + displayConfigData(BlynkEthernet_WM_config); + + // Don't need Config Portal anymore + return true; + } + else + { + // Invalid Stored config data => Config Portal + BLYNK_LOG1(BLYNK_F("Invalid Stored Dynamic Data. Load default from Sketch")); + + // Load Default Config Data from Sketch, better than just "blank" + loadAndSaveDefaultConfigData(); + + // Need Config Portal here as data can be just dummy + // Even if you don't open CP, you're OK on next boot if your default config data is valid + return false; + } + } + } - else - { -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("Invalid Stored Dynamic Data. Ignored")); -#endif - dynamicDataValid = false; - } - } - else - { - dynamicDataValid = EEPROM_getDynamicData(); - } - if ( (strncmp(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE, strlen(BLYNK_BOARD_TYPE)) != 0) || - (calChecksum != BlynkEthernet_WM_config.checkSum) || !dynamicDataValid ) + (calChecksum != BlynkEthernet_WM_config.checkSum) || !dynamicDataValid || + ( (calChecksum == 0) && (BlynkEthernet_WM_config.checkSum == 0) ) ) { // Including Credentials CSum - BLYNK_LOG4(F("InitEEPROM,sz="), EEPROM_SIZE, F(",Datasz="), totalDataSize); - - // doesn't have any configuration + BLYNK_LOG2(F("InitCfgFile,Sz="), sizeof(BlynkEthernet_WM_config)); + + // doesn't have any configuration if (LOAD_DEFAULT_CONFIG_DATA) { memcpy(&BlynkEthernet_WM_config, &defaultConfig, sizeof(BlynkEthernet_WM_config)); @@ -918,9 +1130,10 @@ class BlynkEthernet // Actual size of pdata is [maxlen + 1] memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); } -#endif +#endif + // Including Credentials CSum - BLYNK_LOG4(F("InitEEPROM,sz="), EEPROM_SIZE, F(",Datasz="), totalDataSize); + BLYNK_LOG2(BLYNK_F("InitCfgFile,DataSz="), totalDataSize); // doesn't have any configuration strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, WM_NO_CONFIG); @@ -931,28 +1144,27 @@ class BlynkEthernet strcpy(BlynkEthernet_WM_config.static_IP, WM_NO_CONFIG); strcpy(BlynkEthernet_WM_config.board_name, WM_NO_CONFIG); -#if USE_DYNAMIC_PARAMETERS +#if USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { strncpy(myMenuItems[i].pdata, WM_NO_CONFIG, myMenuItems[i].maxlen); } #endif } - + strcpy(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE); - - #if (USE_DYNAMIC_PARAMETERS && ( BLYNK_WM_DEBUG > 2)) + +#if ( BLYNK_WM_DEBUG > 2) && USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { BLYNK_LOG4(BLYNK_F("g:myMenuItems["), i, BLYNK_F("]="), myMenuItems[i].pdata ); } - #endif +#endif // Don't need BlynkEthernet_WM_config.checkSum = 0; - EEPROM.put(BLYNK_EEPROM_START, BlynkEthernet_WM_config); - EEPROM_putDynamicData(); + saveConfigData(); return false; } @@ -971,16 +1183,8 @@ class BlynkEthernet return true; } - - void saveConfigData() - { - int calChecksum = calcChecksum(); - BlynkEthernet_WM_config.checkSum = calChecksum; - BLYNK_LOG2(BLYNK_F("Save,WCSum=0x"), String(calChecksum, HEX)); - - EEPROM.put(BLYNK_EEPROM_START, BlynkEthernet_WM_config); - EEPROM_putDynamicData(); - } + + ////////////////////////////////////////////// bool connectMultiBlynk() { @@ -1006,7 +1210,8 @@ class BlynkEthernet return false; } - // NEW + ////////////////////////////////////////////// + void createHTML(String& root_html_template) { String pitem; @@ -1053,7 +1258,8 @@ class BlynkEthernet return; } - //// + + ////////////////////////////////////////////// void handleRequest() { @@ -1118,91 +1324,136 @@ class BlynkEthernet strcpy(BlynkEthernet_WM_config.header, BLYNK_BOARD_TYPE); } - if (key == "sv") +#if USE_DYNAMIC_PARAMETERS + if (!menuItemUpdated) + { + // Don't need to free + menuItemUpdated = new bool[NUM_MENU_ITEMS]; + + if (menuItemUpdated) + { + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + // To flag item is not yet updated + menuItemUpdated[i] = false; + } + #if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG1(BLYNK_F("h: Init menuItemUpdated" )); + #endif + } + else + { + BLYNK_LOG1(BLYNK_F("h: Error can't alloc memory for menuItemUpdated" )); + } + } +#endif + + static bool sv_Updated = false; + static bool tk_Updated = false; + static bool sv1_Updated = false; + static bool tk1_Updated = false; + static bool pt_Updated = false; + static bool ip_Updated = false; + static bool nm_Updated = false; + + //if (key == "sv") + if (!sv_Updated && (key == String("sv"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:sv")); #endif + sv_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_server) - 1); } - else if (key == "tk") + else if (!tk_Updated && (key == String("tk"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:tk")); #endif + tk_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[0].blynk_token) - 1); } - else if (key == "sv1") + else if (!sv1_Updated && (key == String("sv1"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:sv1")); #endif + sv1_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_server) - 1); } - else if (key == "tk1") + else if (!tk1_Updated && (key == String("tk1"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:tk1")); #endif + tk1_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token) - 1) strcpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token, value.c_str()); else strncpy(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token, value.c_str(), sizeof(BlynkEthernet_WM_config.Blynk_Creds[1].blynk_token) - 1); } - else if (key == "pt") + else if (!pt_Updated && (key == String("pt"))) { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:pt")); #endif + pt_Updated = true; number_items_Updated++; BlynkEthernet_WM_config.blynk_port = value.toInt(); } - else if (key == "ip") + else if (!ip_Updated && (key == String("ip"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:ip")); #endif + ip_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.static_IP) - 1) strcpy(BlynkEthernet_WM_config.static_IP, value.c_str()); else strncpy(BlynkEthernet_WM_config.static_IP, value.c_str(), sizeof(BlynkEthernet_WM_config.static_IP) - 1); } - else if (key == "nm") + else if (!nm_Updated && (key == String("nm"))) { -#if (BLYNK_WM_DEBUG > 2) +#if ( BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:nm")); #endif + nm_Updated = true; number_items_Updated++; + if (strlen(value.c_str()) < sizeof(BlynkEthernet_WM_config.board_name) - 1) strcpy(BlynkEthernet_WM_config.board_name, value.c_str()); else strncpy(BlynkEthernet_WM_config.board_name, value.c_str(), sizeof(BlynkEthernet_WM_config.board_name) - 1); } -#if (BLYNK_WM_DEBUG > 2) - BLYNK_LOG1(BLYNK_F("h:OK")); -#endif - -#if USE_DYNAMIC_PARAMETERS +#if USE_DYNAMIC_PARAMETERS for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - if (key == myMenuItems[i].id) + if ( !menuItemUpdated[i] && (key == myMenuItems[i].id) ) { - //BLYNK_LOG4(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); + BLYNK_LOG4(BLYNK_F("h:"), myMenuItems[i].id, BLYNK_F("="), value.c_str() ); + + menuItemUpdated[i] = true; + number_items_Updated++; // Actual size of pdata is [maxlen + 1] @@ -1212,24 +1463,32 @@ class BlynkEthernet strcpy(myMenuItems[i].pdata, value.c_str()); else strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); - -#if ( BLYNK_WM_DEBUG > 2) - BLYNK_LOG4(BLYNK_F("h2:myMenuItems["), i, BLYNK_F("]="), myMenuItems[i].pdata ); -#endif } } #endif + //#if ( BLYNK_WM_DEBUG > 2) + BLYNK_LOG2(F("h:items updated ="), number_items_Updated); + BLYNK_LOG4(F("h:key ="), key, ", value =", value); + //#endif + server->send(200, "text/html", "OK"); - // NEW +#if USE_DYNAMIC_PARAMETERS if (number_items_Updated == NUM_CONFIGURABLE_ITEMS + NUM_MENU_ITEMS) +#else + if (number_items_Updated == NUM_CONFIGURABLE_ITEMS) +#endif { #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:UpdEEPROM")); #endif saveConfigData(); + + // Done with CP, Clear CP Flag here if forced + if (isForcedConfigPortal) + clearForcedCP(); #if (BLYNK_WM_DEBUG > 2) BLYNK_LOG1(BLYNK_F("h:Rst")); @@ -1237,11 +1496,12 @@ class BlynkEthernet // Delay then reset after save data delay(200); - //BlynkReset(); resetFunc(); } } // if (server) } + + ////////////////////////////////////////////// void startConfigurationMode() { @@ -1306,6 +1566,8 @@ class BlynkEthernet return ethernetConnected; } + + ////////////////////////////////////////////// byte* SelectMacAddress(const char* token, const byte mac[]) { diff --git a/src/Blynk/BlynkDetectDevice.h b/src/Blynk/BlynkDetectDevice.h index 3ecd75ff..5cd70b74 100644 --- a/src/Blynk/BlynkDetectDevice.h +++ b/src/Blynk/BlynkDetectDevice.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,6 +38,7 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkDetectDevice_h diff --git a/src/BlynkSimpleEthernet2_WM.h b/src/BlynkSimpleEthernet2_WM.h index 8508c0cd..be180ee4 100644 --- a/src/BlynkSimpleEthernet2_WM.h +++ b/src/BlynkSimpleEthernet2_WM.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,6 +38,7 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkSimpleEthernet2_WM_h @@ -48,7 +49,7 @@ #endif #ifndef BLYNK_ETHERNET_WM_VERSION - #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.1.0" + #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.2.0" #endif #include diff --git a/src/BlynkSimpleEthernetENC.h b/src/BlynkSimpleEthernetENC.h index ca69b121..478fe18c 100644 --- a/src/BlynkSimpleEthernetENC.h +++ b/src/BlynkSimpleEthernetENC.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,6 +38,7 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkSimpleEthernetENC_h @@ -48,7 +49,7 @@ #endif #ifndef BLYNK_ETHERNET_WM_VERSION - #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.1.0" + #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.2.0" #endif #include diff --git a/src/BlynkSimpleEthernetENC_SSL.h b/src/BlynkSimpleEthernetENC_SSL.h index 5d8d0d54..ec8e2187 100644 --- a/src/BlynkSimpleEthernetENC_SSL.h +++ b/src/BlynkSimpleEthernetENC_SSL.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,6 +38,7 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkSimpleEthernetENC_SSL_h @@ -50,7 +51,7 @@ #endif #ifndef BLYNK_ETHERNET_WM_VERSION - #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.1.0" + #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.2.0" #endif #include diff --git a/src/BlynkSimpleEthernetENC_SSL_WM.h b/src/BlynkSimpleEthernetENC_SSL_WM.h index 91356a88..e82d6aa2 100644 --- a/src/BlynkSimpleEthernetENC_SSL_WM.h +++ b/src/BlynkSimpleEthernetENC_SSL_WM.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,6 +38,7 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkSimpleEthernetENC_SSL_WM_h @@ -50,7 +51,7 @@ #endif #ifndef BLYNK_ETHERNET_WM_VERSION - #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.1.0" + #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.2.0" #endif #define USE_ETHERNET_ENC true diff --git a/src/BlynkSimpleEthernetENC_WM.h b/src/BlynkSimpleEthernetENC_WM.h index f7502f18..9cf6663f 100644 --- a/src/BlynkSimpleEthernetENC_WM.h +++ b/src/BlynkSimpleEthernetENC_WM.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,6 +38,7 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkSimpleEthernet_WM_h @@ -48,7 +49,7 @@ #endif #ifndef BLYNK_ETHERNET_WM_VERSION - #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.1.0" + #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.2.0" #endif #define USE_ETHERNET_ENC true diff --git a/src/BlynkSimpleEthernetSSL_WM.h b/src/BlynkSimpleEthernetSSL_WM.h index fb5883d4..04204158 100644 --- a/src/BlynkSimpleEthernetSSL_WM.h +++ b/src/BlynkSimpleEthernetSSL_WM.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,6 +38,7 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkSimpleEthernetSSL_WM_h @@ -50,7 +51,7 @@ #endif #ifndef BLYNK_ETHERNET_WM_VERSION - #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.1.0" + #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.2.0" #endif #if USE_NATIVE_ETHERNET diff --git a/src/BlynkSimpleEthernetV2_0_WM.h b/src/BlynkSimpleEthernetV2_0_WM.h index cebe4b8c..5af045a5 100644 --- a/src/BlynkSimpleEthernetV2_0_WM.h +++ b/src/BlynkSimpleEthernetV2_0_WM.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,6 +38,7 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkSimpleEthernetV2_0_WM_h @@ -48,7 +49,7 @@ #endif #ifndef BLYNK_ETHERNET_WM_VERSION - #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.1.0" + #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.2.0" #endif #include diff --git a/src/BlynkSimpleEthernet_WM.h b/src/BlynkSimpleEthernet_WM.h index f6e8ed8b..d587966c 100644 --- a/src/BlynkSimpleEthernet_WM.h +++ b/src/BlynkSimpleEthernet_WM.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,6 +38,7 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkSimpleEthernet_WM_h @@ -48,7 +49,7 @@ #endif #ifndef BLYNK_ETHERNET_WM_VERSION - #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.1.0" + #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.2.0" #endif #if USE_NATIVE_ETHERNET diff --git a/src/BlynkSimpleUIPEthernetSSL_WM.h b/src/BlynkSimpleUIPEthernetSSL_WM.h index 087ad3be..3af3ac28 100644 --- a/src/BlynkSimpleUIPEthernetSSL_WM.h +++ b/src/BlynkSimpleUIPEthernetSSL_WM.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,6 +38,7 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkSimpleUIPEthernetSSL_WM_h @@ -50,7 +51,7 @@ #endif #ifndef BLYNK_ETHERNET_WM_VERSION - #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.1.0" + #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.2.0" #endif #define BLYNK_ENC28J60_FIX diff --git a/src/BlynkSimpleUIPEthernet_WM.h b/src/BlynkSimpleUIPEthernet_WM.h index a053c676..0ae0c5ab 100644 --- a/src/BlynkSimpleUIPEthernet_WM.h +++ b/src/BlynkSimpleUIPEthernet_WM.h @@ -17,7 +17,7 @@ @date Jan 2015 @brief - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -38,6 +38,7 @@ 1.0.17 K Hoang 25/07/2020 New logic for USE_DEFAULT_CONFIG_DATA. Add support to Seeeduino SAMD21/SAMD51 boards. 1.0.18 K Hoang 15/09/2020 Add support to new EthernetENC library for ENC28J60. 1.1.0 K Hoang 13/01/2021 Add support to new NativeEthernet library for Teensy 4.1. Fix compiler warnings. + 1.2.0 K Hoang 29/01/2021 Fix bug. Add feature. Use more efficient FlashStorage_STM32 and FlashStorage_SAMD. *****************************************************************************************************************************/ #ifndef BlynkSimpleUIPEthernet_WM @@ -48,7 +49,7 @@ #endif #ifndef BLYNK_ETHERNET_WM_VERSION - #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.1.0" + #define BLYNK_ETHERNET_WM_VERSION "BlynkEthernet_WM v1.2.0" #endif #define BLYNK_ENC28J60_FIX