From b8b663d9277f78d2d6932bb2e3f9a0699b48fcf8 Mon Sep 17 00:00:00 2001 From: Hieromon Ikasamo Date: Wed, 22 Apr 2020 20:46:05 +0900 Subject: [PATCH 1/6] Added AutoConnectCredential size acquisition #209 --- src/AutoConnect.cpp | 13 +++++++++++-- src/AutoConnect.h | 5 +++-- src/AutoConnectCredential.h | 7 ++++--- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index a078a1c..936cc87 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -2,8 +2,8 @@ * AutoConnect class implementation. * @file AutoConnect.cpp * @author hieromon@gmail.com - * @version 1.1.5 - * @date 2020-04-15 + * @version 1.2.0 + * @date 2020-04-22 * @copyright MIT license. */ @@ -746,6 +746,15 @@ bool AutoConnect::_loadAvailCredential(const char* ssid, const AC_PRINCIPLE_t pr return false; } +/** + * Get current AutoConnectCredential size + * @return Size of the AutoConnectCredential + */ +uint16_t AutoConnect::getCredentialSize(void) { + AutoConnectCredential credentials(_apConfig.boundaryOffset); + return credentials.dataSize(); +} + /** * Disconnect from the AP and stop the AutoConnect portal. * Stops DNS server and flush tcp sending. diff --git a/src/AutoConnect.h b/src/AutoConnect.h index a483087..671802a 100644 --- a/src/AutoConnect.h +++ b/src/AutoConnect.h @@ -2,8 +2,8 @@ * Declaration of AutoConnect class and accompanying AutoConnectConfig class. * @file AutoConnect.h * @author hieromon@gmail.com - * @version 1.1.5 - * @date 2020-04-01 + * @version 1.2.0 + * @date 2020-04-22 * @copyright MIT license. */ @@ -252,6 +252,7 @@ class AutoConnect { String where(void) const { return _auxUri; } inline void enableMenu(const uint16_t items) { _apConfig.menuItems |= items; } inline void disableMenu(const uint16_t items) { _apConfig.menuItems &= (0xffff ^ items); } + uint16_t getCredentialSize(void); /** For AutoConnectAux described in JSON */ #ifdef AUTOCONNECT_USE_JSON diff --git a/src/AutoConnectCredential.h b/src/AutoConnectCredential.h index 1a22fc9..3e33de0 100644 --- a/src/AutoConnectCredential.h +++ b/src/AutoConnectCredential.h @@ -2,8 +2,8 @@ * Declaration of AutoConnectCredential class. * @file AutoConnectCredential.h * @author hieromon@gmail.com - * @version 1.1.0 - * @date 2019-10-07 + * @version 1.2.0 + * @date 2020-04-22 * @copyright MIT license. */ @@ -78,7 +78,8 @@ class AutoConnectCredentialBase { public: explicit AutoConnectCredentialBase() : _entries(0), _containSize(0) {} virtual ~AutoConnectCredentialBase() {} - virtual uint8_t entries(void) { return _entries; } + virtual uint8_t entries(void) const { return _entries; } + virtual uint16_t dataSize(void) const { return sizeof(AC_IDENTIFIER) - 1 + sizeof(uint8_t) + sizeof(uint16_t) + _containSize; } virtual bool del(const char* ssid) = 0; virtual int8_t load(const char* ssid, station_config_t* config) = 0; virtual bool load(int8_t entry, station_config_t* config) = 0; From 84d18dedaebb6e6cb9558c12f698a77aa9470d67 Mon Sep 17 00:00:00 2001 From: Hieromon Ikasamo Date: Wed, 22 Apr 2020 21:17:42 +0900 Subject: [PATCH 2/6] Added EEPROM.ino example #209 --- .travis.yml | 1 + examples/EEPROM/EEPROM.ino | 164 +++++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 examples/EEPROM/EEPROM.ino diff --git a/.travis.yml b/.travis.yml index 02bd14d..15b0ce5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,6 +33,7 @@ script: - buildExampleSketch ConfigIP - buildExampleSketch Credential - if [[ "$BOARD" =~ "esp32:esp32:" ]]; then buildExampleSketch CreditMigrate; fi + - if [[ "$BOARD" =~ "esp8266:esp8266:" ]]; then buildExampleSketch EEPROM; fi - buildExampleSketch Elements - buildExampleSketch FileUpload - buildExampleSketch FSBrowser diff --git a/examples/EEPROM/EEPROM.ino b/examples/EEPROM/EEPROM.ino new file mode 100644 index 0000000..5baee9b --- /dev/null +++ b/examples/EEPROM/EEPROM.ino @@ -0,0 +1,164 @@ +/* + EEPROM.ino, Example for the AutoConnect library. + Copyright (c) 2020, Hieromon Ikasamo + https://github.com/Hieromon/AutoConnect + This software is released under the MIT License. + https://opensource.org/licenses/MIT + + This example demonstrates how allocates and handles the custom + configuration for the Sketch. + When Sketch stores the own configuration data in the EEPROM, it must + avoid conflict with the credentials stored by AutoConnect. + AutoConnectConfig::boundayOffet designation helps with the conflict, + but it is inadequate. Sketch uses AutoConnect::getCredentialSize to + get the size of the actual EEPROM area that should be handled for the + own custom data I/O. +*/ + +#ifndef ARDUINO_ARCH_ESP8266 +#error "EEPROM.ino sketch is available for ESP8266 only." +#endif + +#include +#include +#include +#include + +ESP8266WebServer server; +AutoConnect portal(server); +AutoConnectConfig config; + +const char AUX_EEPROM_IO[] PROGMEM = R"( +[ + { + "title": "EEPROM", + "uri": "/", + "menu": true, + "element": [ + { + "name": "data1", + "type": "ACInput", + "label": "DATA1", + "global": true + }, + { + "name": "data2", + "type": "ACInput", + "label": "DATA2", + "global": true + }, + { + "name": "data3", + "type": "ACInput", + "label": "DATA3", + "global": true + }, + { + "name": "write", + "type": "ACSubmit", + "value": "WRITE", + "uri": "/eeprom", + "global": true + } + ] + }, + { + "title": "EEPROM", + "uri": "/eeprom", + "menu": false, + "element": [ + { + "name": "data1", + "type": "ACText", + "format": "DATA1: %s", + "posterior": "br", + "global": true + }, + { + "name": "data2", + "type": "ACText", + "format": "DATA2: %s", + "posterior": "br", + "global": true + }, + { + "name": "data3", + "type": "ACText", + "format": "DATA3: %s", + "posterior": "br", + "global": true + } + ] + } +] +)"; + +// Defines the custom data should be stored in EEPROM. +typedef struct { + char data1[8]; + char data2[8]; + char data3[8]; +} EEPROM_CONFIG_t; + +String toString(char* c, uint8_t length) { + String r; + while (length-- && *c) { + r += (isAlphaNumeric(*c) ? String(*c) : String(*c, HEX)); + c++; + } + return r; +} + +// Read from EEPROM +String onEEPROM(AutoConnectAux& page, PageArgument& args) { + EEPROM_CONFIG_t eepromConfig; + + // The actual area size of the EEPROM region to be given to + // EEPROM.begin is the sum of the size of the own custom data and + // the size of the currently stored AutoConnect credentials. + // eg. + // sizeof(EEPROM_CONFIG_t) + portal.getCredentialSize() + EEPROM.begin(sizeof(EEPROM_CONFIG_t) + portal.getCredentialSize()); + EEPROM.get(0, eepromConfig); + EEPROM.end(); + + page["data1"].value = toString(eepromConfig.data1, sizeof(EEPROM_CONFIG_t::data1)); + page["data2"].value = toString(eepromConfig.data2, sizeof(EEPROM_CONFIG_t::data2)); + page["data3"].value = toString(eepromConfig.data3, sizeof(EEPROM_CONFIG_t::data3)); + return String(); +} + +// Write to EEPROM +String onEEPROMWrite(AutoConnectAux& page, PageArgument& args) { + EEPROM_CONFIG_t eepromConfig; + + strncpy(eepromConfig.data1, page["data1"].value.c_str(), sizeof(EEPROM_CONFIG_t::data1)); + strncpy(eepromConfig.data2, page["data2"].value.c_str(), sizeof(EEPROM_CONFIG_t::data2)); + strncpy(eepromConfig.data3, page["data3"].value.c_str(), sizeof(EEPROM_CONFIG_t::data3)); + + EEPROM.begin(sizeof(EEPROM_CONFIG_t) + portal.getCredentialSize()); + EEPROM.put(0, eepromConfig); + EEPROM.commit(); + EEPROM.end(); + return String(); +} + +void setup() { + delay(1000); + Serial.begin(115200); + Serial.println(); + + portal.load(FPSTR(AUX_EEPROM_IO)); + portal.on("/", onEEPROM); + portal.on("/eeprom", onEEPROMWrite); + + // Specifies to shift the AutoConnect credentials with the custom data region size. + config.boundaryOffset = sizeof(EEPROM_CONFIG_t); + portal.config(config); + + portal.begin(); +} + +void loop() { + portal.handleClient(); +} From 5716bdd0a08c44ed1579f79b770a1446557f3636 Mon Sep 17 00:00:00 2001 From: Hieromon Ikasamo Date: Thu, 23 Apr 2020 00:20:53 +0900 Subject: [PATCH 3/6] Changed getEEPROMUsedSize #209 --- examples/EEPROM/EEPROM.ino | 8 ++++---- src/AutoConnect.cpp | 11 ++++++++--- src/AutoConnect.h | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/examples/EEPROM/EEPROM.ino b/examples/EEPROM/EEPROM.ino index 5baee9b..3e4b829 100644 --- a/examples/EEPROM/EEPROM.ino +++ b/examples/EEPROM/EEPROM.ino @@ -9,7 +9,7 @@ configuration for the Sketch. When Sketch stores the own configuration data in the EEPROM, it must avoid conflict with the credentials stored by AutoConnect. - AutoConnectConfig::boundayOffet designation helps with the conflict, + AutoConnectConfig::boundaryOffset designation helps with the conflict, but it is inadequate. Sketch uses AutoConnect::getCredentialSize to get the size of the actual EEPROM area that should be handled for the own custom data I/O. @@ -117,8 +117,8 @@ String onEEPROM(AutoConnectAux& page, PageArgument& args) { // EEPROM.begin is the sum of the size of the own custom data and // the size of the currently stored AutoConnect credentials. // eg. - // sizeof(EEPROM_CONFIG_t) + portal.getCredentialSize() - EEPROM.begin(sizeof(EEPROM_CONFIG_t) + portal.getCredentialSize()); + // EEPROM.begin(portal.getEEPROMUsedSize()) + EEPROM.begin(portal.getEEPROMUsedSize()); EEPROM.get(0, eepromConfig); EEPROM.end(); @@ -136,7 +136,7 @@ String onEEPROMWrite(AutoConnectAux& page, PageArgument& args) { strncpy(eepromConfig.data2, page["data2"].value.c_str(), sizeof(EEPROM_CONFIG_t::data2)); strncpy(eepromConfig.data3, page["data3"].value.c_str(), sizeof(EEPROM_CONFIG_t::data3)); - EEPROM.begin(sizeof(EEPROM_CONFIG_t) + portal.getCredentialSize()); + EEPROM.begin(portal.getEEPROMUsedSize()); EEPROM.put(0, eepromConfig); EEPROM.commit(); EEPROM.end(); diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index 936cc87..fa68dcf 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -747,12 +747,17 @@ bool AutoConnect::_loadAvailCredential(const char* ssid, const AC_PRINCIPLE_t pr } /** - * Get current AutoConnectCredential size + * Get current AutoConnectCredential size. + * This function is available only for ESP8266 use. * @return Size of the AutoConnectCredential */ -uint16_t AutoConnect::getCredentialSize(void) { +uint16_t AutoConnect::getEEPROMUsedSize(void) { +#if defined(ARDUINO_ARCH_ESP8266) AutoConnectCredential credentials(_apConfig.boundaryOffset); - return credentials.dataSize(); + return _apConfig.boundaryOffset + credentials.dataSize(); +#elif defined(ARDUINO_ARCH_ESP32) + return 0; +#endif } /** diff --git a/src/AutoConnect.h b/src/AutoConnect.h index 671802a..95eac36 100644 --- a/src/AutoConnect.h +++ b/src/AutoConnect.h @@ -252,7 +252,7 @@ class AutoConnect { String where(void) const { return _auxUri; } inline void enableMenu(const uint16_t items) { _apConfig.menuItems |= items; } inline void disableMenu(const uint16_t items) { _apConfig.menuItems &= (0xffff ^ items); } - uint16_t getCredentialSize(void); + uint16_t getEEPROMUsedSize(void); /** For AutoConnectAux described in JSON */ #ifdef AUTOCONNECT_USE_JSON From 756c9c28eae8ca60df9828cb7df22cde92c6034a Mon Sep 17 00:00:00 2001 From: Hieromon Ikasamo Date: Thu, 23 Apr 2020 18:54:27 +0900 Subject: [PATCH 4/6] Changed the comment to be legible #209 --- examples/EEPROM/EEPROM.ino | 28 ++++++++++++++-------------- src/AutoConnect.cpp | 5 +++-- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/examples/EEPROM/EEPROM.ino b/examples/EEPROM/EEPROM.ino index 3e4b829..8e812ba 100644 --- a/examples/EEPROM/EEPROM.ino +++ b/examples/EEPROM/EEPROM.ino @@ -5,14 +5,14 @@ This software is released under the MIT License. https://opensource.org/licenses/MIT - This example demonstrates how allocates and handles the custom - configuration for the Sketch. - When Sketch stores the own configuration data in the EEPROM, it must - avoid conflict with the credentials stored by AutoConnect. - AutoConnectConfig::boundaryOffset designation helps with the conflict, - but it is inadequate. Sketch uses AutoConnect::getCredentialSize to - get the size of the actual EEPROM area that should be handled for the - own custom data I/O. + The AutoConnectConfig::boundaryOffset setting allows AutoConnect to + write its data to EEPROM while preserving custom configuration data. + Similarly, when a Sketch writes its own data to EEPROM, it must + preserve the data written by AutoConnect. + This example demonstrates how to use the getEEPROMUsedSize() method to + store custom configuration settings in EEPROM without conflicting with + AutoConnect's use of that storage. (Note: this applies to the ESP8266 + only, not the ESP32.) */ #ifndef ARDUINO_ARCH_ESP8266 @@ -113,12 +113,7 @@ String toString(char* c, uint8_t length) { String onEEPROM(AutoConnectAux& page, PageArgument& args) { EEPROM_CONFIG_t eepromConfig; - // The actual area size of the EEPROM region to be given to - // EEPROM.begin is the sum of the size of the own custom data and - // the size of the currently stored AutoConnect credentials. - // eg. - // EEPROM.begin(portal.getEEPROMUsedSize()) - EEPROM.begin(portal.getEEPROMUsedSize()); + EEPROM.begin(sizeof(eepromConfig)); EEPROM.get(0, eepromConfig); EEPROM.end(); @@ -136,6 +131,11 @@ String onEEPROMWrite(AutoConnectAux& page, PageArgument& args) { strncpy(eepromConfig.data2, page["data2"].value.c_str(), sizeof(EEPROM_CONFIG_t::data2)); strncpy(eepromConfig.data3, page["data3"].value.c_str(), sizeof(EEPROM_CONFIG_t::data3)); + // The actual area size of the EEPROM region to be given to + // EEPROM.begin is the sum of the size of the own custom data and + // the size of the currently stored AutoConnect credentials. + // eg. + // EEPROM.begin(portal.getEEPROMUsedSize()) EEPROM.begin(portal.getEEPROMUsedSize()); EEPROM.put(0, eepromConfig); EEPROM.commit(); diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index fa68dcf..0c25e47 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -747,9 +747,10 @@ bool AutoConnect::_loadAvailCredential(const char* ssid, const AC_PRINCIPLE_t pr } /** - * Get current AutoConnectCredential size. + * Get the total amount of memory required to hold the AutoConnect credentials + * and any custom configuration settings stored in EEPROM. * This function is available only for ESP8266 use. - * @return Size of the AutoConnectCredential + * @return Combined size of AutoConnect credentials and custom settings. */ uint16_t AutoConnect::getEEPROMUsedSize(void) { #if defined(ARDUINO_ARCH_ESP8266) From f86ec77f48a7ae02a81bb81dfc97262f33dedec4 Mon Sep 17 00:00:00 2001 From: Hieromon Ikasamo Date: Thu, 23 Apr 2020 22:32:40 +0900 Subject: [PATCH 5/6] Adds getEEPROMUsedSize description --- mkdocs/advancedusage.md | 32 ++++++++++++++++++++++++++++++++ mkdocs/api.md | 16 +++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/mkdocs/advancedusage.md b/mkdocs/advancedusage.md index a9a0c94..8fd9cb3 100644 --- a/mkdocs/advancedusage.md +++ b/mkdocs/advancedusage.md @@ -729,6 +729,38 @@ The [**boundaryOffset**](apiconfig.md#boundaryoffset) in [AutoConnectConfig](api !!! info "The boundaryOffset ignored with AutoConnect v1.0.0 later on ESP32 arduino core 1.0.3 later" For ESP32 arduino core 1.0.3 and later, AutoConnect will store credentials to Preferences in the nvs. Since it is defined as the namespace dedicated to AutoConnect and separated from the area used for user sketches. Therefore, the [boundaryOffset](apiconfig.md#boundaryoffset) is ignored with the combination of AutoConnect v1.0.0 or later and the arduino-esp32 1.0.3 or later. +The [*AutoConnectConfig::boundaryOffset*](apiconfig.md#boundaryoffset) setting allows AutoConnect to write its data to EEPROM while preserving custom configuration data. Similarly, when a Sketch writes its own data to EEPROM, it must preserve the data written by AutoConnect. +The EEPROM library for ESP8266 erases the entire flash sector when it writes to any part of the sector. Therefore, when writing data to EEPROM with a sketch that handles the custom data, it is necessary to call `EEPROM.begin` using a total amount of a custom data size and the saved credentials size. +The following code shows how to use the [*AutoConnect::getEEPROMUsedSize*](api.md#geteepromusedsize) function to store custom configuration settings in EEPROM without conflicting with AutoConnect's use of that storage. + +```cpp hl_lines="13 21" +AutoConnect portal; +AutoConnectConfig config; + +// Defines the custom data should be stored in EEPROM. +typedef struct { + char data1[8]; + char data2[8]; + char data3[8]; +} EEPROM_CONFIG_t; +EEPROM_CONFIG_t eepromConfig; +... +// Declares to reserve the EEPROM_CONFIG_t area for a Sketch using. +config.boundaryOffset = sizeof(eepromConfig); +portal.config(config); +... +strcpy(eepromComfig.data1, "data1"); +strcpy(eepromComfig.data2, "data2"); +strcpy(eepromComfig.data3, "data3"); + +// Use getEEPROMUsedSize to access the EEPROM with the appropriate region size. +EEPROM.begin(portal.getEEPROMUsedSize()); +EEPROM.put(0, eepromConfig); +EEPROM.commit(); +EEPROM.end(); +... +``` + ### Relocate the AutoConnect home path A home path of AutoConnect is **/\_ac** by default. You can access from the browser with http://IPADDRESS/\_ac. You can change the home path by revising [**AUTOCONNECT_URI**](https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnectDefs.h#L69) macro in the include header file as [AutoConnectDefs.h](https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnectDefs.h). diff --git a/mkdocs/api.md b/mkdocs/api.md index f7627a7..4e24937 100644 --- a/mkdocs/api.md +++ b/mkdocs/api.md @@ -166,7 +166,6 @@ Stops AutoConnect captive portal service. Release ESP8266WebServer/WebServer and !!! warning "Attention to end" The end function releases the instance of ESP8266WebServer/WebServer and DNSServer. It can not process them after the end function. - ### disableMenu ```cpp @@ -179,6 +178,21 @@ Disable the [AutoConnect menu](menu.md) items specified by the items parameter w
itemsSpecify the combined value of **AC_MENUITEM_t** of the items deleting from the AutoConnect menu. It provides the value calculated from the **logical OR** by the AC_MENUITEM_t value of each item. Refer to the [enableMenu](#enablemenu) about AC_MENUITEM_t.
+### getEEPROMUsedSize + +```cpp +uint16_t getEEPROMUsedSize(void) +``` + +Returns the total amount of memory required to hold the AutoConnect credentials and any custom configuration settings stored in EEPROM. The Sketch that writes its own custom data to the EEPROM must call `EEPROM.begin` with this value. +
+
**Return value**
+
Total amount size of saved AutoConnect credentials and custom data.
+
+ +!!! note "The getEEPROMUsedSize is available for only ESP8266 use" + It is available for only ESP8266 use and will return 0 when used with ESP32. + ### handleClient ```cpp From fd01566292115c6a89dd50615511967f8ef23fba Mon Sep 17 00:00:00 2001 From: Hieromon Ikasamo Date: Thu, 23 Apr 2020 23:47:33 +0900 Subject: [PATCH 6/6] Fixed signature mismatch --- src/AutoConnectCredential.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AutoConnectCredential.h b/src/AutoConnectCredential.h index 3e33de0..6b9f5f2 100644 --- a/src/AutoConnectCredential.h +++ b/src/AutoConnectCredential.h @@ -78,7 +78,7 @@ class AutoConnectCredentialBase { public: explicit AutoConnectCredentialBase() : _entries(0), _containSize(0) {} virtual ~AutoConnectCredentialBase() {} - virtual uint8_t entries(void) const { return _entries; } + virtual uint8_t entries(void) { return _entries; } virtual uint16_t dataSize(void) const { return sizeof(AC_IDENTIFIER) - 1 + sizeof(uint8_t) + sizeof(uint16_t) + _containSize; } virtual bool del(const char* ssid) = 0; virtual int8_t load(const char* ssid, station_config_t* config) = 0;