Supports AutoConnectAux

pull/41/head
Hieromon Ikasamo 6 years ago
parent 6ee87dacd7
commit 0845ad64a8
  1. 4
      .travis.yml
  2. 12
      README.md
  3. 8
      mkdocs/advancedusage.md
  4. 4
      mkdocs/api.md
  5. 11
      mkdocs/index.md
  6. 3
      mkdocs/license.md
  7. 6
      src/AutoConnect.cpp
  8. 199
      src/AutoConnectAux.cpp
  9. 65
      src/AutoConnectAux.h
  10. 1
      src/AutoConnectElement.h

@ -1,7 +1,7 @@
language: generic language: generic
env: env:
global: global:
- IDE_VERSION=1.8.5 - IDE_VERSION=1.8.6
matrix: matrix:
- BOARD="esp8266:esp8266:nodemcuv2:CpuFrequency=160,FlashSize=4M3M" - BOARD="esp8266:esp8266:nodemcuv2:CpuFrequency=160,FlashSize=4M3M"
- BOARD="esp32:esp32:esp32:FlashFreq=80,FlashSize=4M" - BOARD="esp32:esp32:esp32:FlashFreq=80,FlashSize=4M"
@ -20,7 +20,7 @@ before_install:
- if [[ "$BOARD" =~ "esp32:esp32:" ]]; then - if [[ "$BOARD" =~ "esp32:esp32:" ]]; then
arduino --install-boards esp32:esp32; arduino --install-boards esp32:esp32;
fi fi
- arduino --install-library PubSubClient,PageBuilder:1.2.0 - arduino --install-library PubSubClient,ArduinoJson:5.13.3,PageBuilder:1.2.0
- buildExampleSketch() { arduino --verbose-build --verify --board $BOARD $PWD/examples/$1/$1.ino; } - buildExampleSketch() { arduino --verbose-build --verify --board $BOARD $PWD/examples/$1/$1.ino; }
install: install:
- mkdir -p ~/Arduino/libraries - mkdir -p ~/Arduino/libraries

@ -32,13 +32,13 @@ AutoConnect can be embedded easily into your sketch, just "**begin**" and "**han
The sketches which provide the web page using ESP8266WebServer/WebServer there is, AutoConnect will not disturb it. AutoConnect can use an already instantiated ESP8266WebServer object(ESP8266) or WebServer object(ESP32), or itself can assign it. The sketches which provide the web page using ESP8266WebServer/WebServer there is, AutoConnect will not disturb it. AutoConnect can use an already instantiated ESP8266WebServer object(ESP8266) or WebServer object(ESP32), or itself can assign it.
### Adding the user-owned web screen can easily <sup><sub>ENHANCED w/ v0.9.7</sub></sup> ### Easily add user-owned web screen and parameters <sup><sub>ENHANCED w/ v0.9.7</sub></sup>
You can easily add your own web screen with sketch. It can be called from the AutoConnect menu and parameters can be passed. You can easily add your own web screen that can consist of representative HTML elements as the styled TEXT, INPUT, BUTTON, CHECKBOX, SUBMIT into the menu. It can be invoked from the AutoConnect menu and parameters can be passed.
### Adding the extended menu with a simple code can easily <sup><sub>ENHANCED w/ v0.9.7</sub></sup> ### Just loading the JSON description <sup><sub>ENHANCED w/ v0.9.7</sub></sup>
Just loading the elements of portal screen extension written with JSON allows you to incorporate your owned portal screen into the AutoConnect menu. These HTML elements that make up the user-owned screen can be easily loaded from the JSON description stored in PROGMEM, SPIFFS or SD.
## Supported hardware ## Supported hardware
@ -89,11 +89,11 @@ Full documentation is available on https://Hieromon.github.io/AutoConnect, some
## Change log ## Change log
### [0.9.7] Nov. 11, 2018 ### [0.9.7] Dec. 11, 2018
- Supports AutoConnect menu extention by user sketch with **AutoConnectAux** implementation that attached **AutoConnectElement**. - Supports AutoConnect menu extention by user sketch with **AutoConnectAux** implementation that attached **AutoConnectElement**.
- Supports loading and saving of user-defined parameters with JSON format. - Supports loading and saving of user-defined parameters with JSON format.
- Supports AutoConnectConfig::immediateStart option, to start the portal immediately without first trying WiFi.begin. - Supports AutoConnectConfig::immediateStart option, to start the portal immediately without first trying WiFi.begin.
- Improved source code placement of predefined macros. Defined macros have been moved to ```AutoConnectDefs.h```. - Improved source code placement of predefined macros. Defined common macros have been moved to ```AutoConnectDefs.h```.
### [0.9.6] Sept. 27, 2018 ### [0.9.6] Sept. 27, 2018
- Improvement of RSSI detection for saved SSIDs. - Improvement of RSSI detection for saved SSIDs.

@ -88,7 +88,9 @@ void loop() {
### <i class="fa fa-caret-right"></i> Debug print ### <i class="fa fa-caret-right"></i> Debug print
You can output AutoConnect monitor messages to the **Serial**. A monitor message activation switch is in an include header file [AutoConnect.h](https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnect.h) of library source. Define [**AC_DEBUG**](https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnect.h#L27) macro to output the monitor messages. You can output AutoConnect monitor messages to the **Serial**. A monitor message activation switch is in an include header file [AutoConnectDefs.h](https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnectDefs.h) of library source. Define [**AC_DEBUG**](https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnectDefs.h#L14) macro to output the monitor messages.[^1]
[^1]:The source code placement of common macros for AutoConnect since v0.9.7 has changed.
```cpp ```cpp
#define AC_DEBUG #define AC_DEBUG
@ -237,7 +239,7 @@ A home path of AutoConnect is **/\_ac** by default. You can access from the brow
#define AUTOCONNECT_URI "/_ac" #define AUTOCONNECT_URI "/_ac"
``` ```
### <i class="fa fa-caret-right"></i> Static IP assignment [^1] ### <i class="fa fa-caret-right"></i> Static IP assignment [^2]
It is also possible to assign static IP Address to ESP8266/ESP32 in STA mode. By default DHCP is enabled and it becomes the IP address assigned by the DHCP server with *WiFi.begin*. It is also possible to assign static IP Address to ESP8266/ESP32 in STA mode. By default DHCP is enabled and it becomes the IP address assigned by the DHCP server with *WiFi.begin*.
@ -262,4 +264,4 @@ portal.config(Config);
portal.begin(); portal.begin();
``` ```
[^1]:Static IP address assignment is available from version 0.9.3. [^2]:Static IP address assignment is available from version 0.9.3.

@ -20,8 +20,12 @@
#define AUTOCONNECT_STARTUPTIME 10 // Default waiting time[s] for after reset #define AUTOCONNECT_STARTUPTIME 10 // Default waiting time[s] for after reset
#define AUTOCONNECT_URI "/_ac" // Default AutoConnect root path #define AUTOCONNECT_URI "/_ac" // Default AutoConnect root path
#define AUTOCONNECT_TIMEOUT 30000 // Default connection timeout[ms] #define AUTOCONNECT_TIMEOUT 30000 // Default connection timeout[ms]
#define AUTOCONNECT_USE_JSON // Allow AutoConnect elements to be handled by JSON format
``` ```
!!! note "Macros placement moved"
Source code placement of the above macros provided for user sketch changed from v0.9.7. The new code is in ```AutoConnectDefs.h```.
## AutoConnect API ## AutoConnect API
### <i class="fa fa-code"></i> Constructors ### <i class="fa fa-code"></i> Constructors

@ -75,10 +75,19 @@ Install third-party platform using the *Boards Manager* of Arduino IDE. You can
<i class="fa fa-download"></i> <strong>Additional necessary library</strong> <i class="fa fa-download"></i> <strong>Additional necessary library</strong>
The [PageBuilder](https://github.com/Hieromon/PageBuilder) library to build HTML for ESP8266WebServer is needed. The [PageBuilder](https://github.com/Hieromon/PageBuilder) library to build HTML for ESP8266WebServer is needed.
To install the PageBuilder library into your Arduino IDE, you can use the *Library Manager*. Select the board of ESP8266 series in the Arduino IDE, open the library manager and search keyword '**PageBuilder**' with the topic '**Communication**', then you can see the *PageBuilder*. The latest version is required 1.1.0 later for ESP32. To install the PageBuilder library into your Arduino IDE, you can use the *Library Manager*. Select the board of ESP8266 series in the Arduino IDE, open the library manager and search keyword '**PageBuilder**' with the topic '**Communication**', then you can see the *PageBuilder*. The latest version is required 1.2.0 later for ESP32.[^1]
<img src="./images/lm.png" width="640"/> <img src="./images/lm.png" width="640"/>
[^1]:Since AutoConnect v0.9.7, PageBuilder v1.2.0 later is required.
<i class="fa fa-download"></i> <strong>Optional required library</strong>
The [ArduinoJson](https://github.com/bblanchon/ArduinoJson) library is necessary to be able to process AutoConnect elements with JSON description. Since AutoConnect v0.9.7, you can insert user owned screens that can consist of representative HTML elements as the styled TEXT, INPUT, BUTTON, CHECKBOX, SUBMIT to the AutoConnect menu. These HTML elements can also be programmatic added from user sketches using the AutoConnect API, but they can be easily loaded from JSON description stored in PROGMEM, SPIFFS or SD. [ArduinoJson version 5](https://arduinojson.org/v5/doc/) is required to use this function.
!!! info "ArduinoJson version 6 is still in beta"
The Arduino Library Manager installs the ArduinoJson version 6 by default. Open the Arduino Library Manager and make sure that ArduinoJson version 5 is installed.
### Install the AutoConnect ### Install the AutoConnect
Clone or download from the [AutoConnect GitHub repository](https://github.com/Hieromon/AutoConnect). Clone or download from the [AutoConnect GitHub repository](https://github.com/Hieromon/AutoConnect).

@ -13,3 +13,6 @@ IN THE SOFTWARE.
The **Luxbar** is licensed under the MIT License. The **Luxbar** is licensed under the MIT License.
https://github.com/balzss/luxbar https://github.com/balzss/luxbar
**ArduinoJson** is licensed under the MIT License.
https://arduinojson.org/

@ -156,11 +156,13 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long
WiFi.setAutoConnect(false); WiFi.setAutoConnect(false);
_disconnectWiFi(true); _disconnectWiFi(true);
WiFi.mode(WIFI_AP_STA); WiFi.mode(WIFI_AP_STA);
delay(100); delay(300);
// Connection unsuccessful, launch the captive portal. // Connection unsuccessful, launch the captive portal.
if (!(_apConfig.apip == IPAddress(0, 0, 0, 0) || _apConfig.gateway == IPAddress(0, 0, 0, 0) || _apConfig.netmask == IPAddress(0, 0, 0, 0))) { if (!(_apConfig.apip == IPAddress(0, 0, 0, 0) || _apConfig.gateway == IPAddress(0, 0, 0, 0) || _apConfig.netmask == IPAddress(0, 0, 0, 0))) {
_config(); if (!_config()) {
AC_DBG("APConfig failed\n");
}
} }
WiFi.softAP(_apConfig.apid.c_str(), _apConfig.psk.c_str(), _apConfig.channel, _apConfig.hidden); WiFi.softAP(_apConfig.apid.c_str(), _apConfig.psk.c_str(), _apConfig.channel, _apConfig.hidden);
while (WiFi.softAPIP() == IPAddress(0, 0, 0, 0)) while (WiFi.softAPIP() == IPAddress(0, 0, 0, 0))

@ -6,7 +6,6 @@
* @date 2018-11-17 * @date 2018-11-17
* @copyright MIT license. * @copyright MIT license.
*/ */
#include "AutoConnect.h" #include "AutoConnect.h"
#include "AutoConnectAux.h" #include "AutoConnectAux.h"
#include "AutoConnectElement.h" #include "AutoConnectElement.h"
@ -151,22 +150,24 @@ const String AutoConnectAux::_insertElement(PageArgument& args) {
AC_UNUSED(args); AC_UNUSED(args);
String body = String(); String body = String();
if (_handler) if (_handler) {
if (_order & AC_EXIT_AHEAD) { if (_order & AC_EXIT_AHEAD) {
AC_DBG("CB %s\n", uri()); AC_DBG("CB %s\n", uri());
body += _handler(args); body += _handler(args);
} }
}
for (std::size_t n = 0; n < _addonElm.size(); n++) { for (std::size_t n = 0; n < _addonElm.size(); n++) {
AutoConnectElement& addon = _addonElm[n]; AutoConnectElement& addon = _addonElm[n];
body += addon.toHTML(); body += addon.toHTML();
} }
if (_handler) if (_handler) {
if (_order & AC_EXIT_LATER) { if (_order & AC_EXIT_LATER) {
AC_DBG("CB %s\n", uri()); AC_DBG("CB %s\n", uri());
body += _handler(args); body += _handler(args);
} }
}
return body; return body;
} }
@ -280,38 +281,59 @@ AutoConnectElement* AutoConnectAux::_createElement(const JsonObject& json) {
/** /**
* Constructs an AutoConnectAux instance by reading all the * Constructs an AutoConnectAux instance by reading all the
* AutoConnectElements of the specified URI from the elements defined JSON. * AutoConnectElements of the specified URI from the elements defined
* JSON stored in a constant character string.
* @param in AutoConnectAux element data which is described by JSON. * @param in AutoConnectAux element data which is described by JSON.
* @return true The element collection successfully loaded. * @return true The element collection successfully loaded.
* @return false Invalid JSON data occurred. * @return false Invalid JSON data occurred.
*/ */
bool AutoConnectAux::load(const char* in) { bool AutoConnectAux::load(const char* in) {
// DynamicJsonBuffer jsonBuffer(); const size_t bufferSize = _calcJsonBufferSize(in);
const size_t bufferSize = 2*JSON_ARRAY_SIZE(2) + 3*JSON_ARRAY_SIZE(3) + JSON_ARRAY_SIZE(9) + JSON_OBJECT_SIZE(1) + 2*JSON_OBJECT_SIZE(3) + 9*JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(6) + 1080;
DynamicJsonBuffer jsonBuffer(bufferSize); DynamicJsonBuffer jsonBuffer(bufferSize);
JsonObject& jb = jsonBuffer.parseObject(in); JsonObject& jb = jsonBuffer.parseObject(in);
return _load(jb); return _load(jb);
} }
/**
* Constructs an AutoConnectAux instance by reading all the
* AutoConnectElements of the specified URI from the elements defined
* JSON stored in pgm_data array.
* @param in AutoConnectAux element data which is described by JSON.
* @return true The element collection successfully loaded.
* @return false Invalid JSON data occurred.
*/
bool AutoConnectAux::load(const __FlashStringHelper* in) { bool AutoConnectAux::load(const __FlashStringHelper* in) {
// DynamicJsonBuffer jsonBuffer(); const size_t bufferSize = _calcJsonBufferSize(in);
const size_t bufferSize = 2*JSON_ARRAY_SIZE(2) + 3*JSON_ARRAY_SIZE(3) + JSON_ARRAY_SIZE(9) + JSON_OBJECT_SIZE(1) + 2*JSON_OBJECT_SIZE(3) + 9*JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(6) + 1080;
DynamicJsonBuffer jsonBuffer(bufferSize); DynamicJsonBuffer jsonBuffer(bufferSize);
JsonObject& jb = jsonBuffer.parseObject(in); JsonObject& jb = jsonBuffer.parseObject(in);
return _load(jb); return _load(jb);
} }
bool AutoConnectAux::load(Stream& in) { /**
// DynamicJsonBuffer jsonBuffer(); * Constructs an AutoConnectAux instance by reading all the
const size_t bufferSize = 2*JSON_ARRAY_SIZE(2) + 3*JSON_ARRAY_SIZE(3) + JSON_ARRAY_SIZE(9) + JSON_OBJECT_SIZE(1) + 2*JSON_OBJECT_SIZE(3) + 9*JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(6) + 1080; * AutoConnectElements of the specified URI from the elements defined
* JSON stored in a Stream.
* @param in AutoConnectAux element data which is described by JSON.
* @return true The element collection successfully loaded.
* @return false Invalid JSON data occurred.
*/
bool AutoConnectAux::load(Stream& in, const size_t bufferSize) {
DynamicJsonBuffer jsonBuffer(bufferSize); DynamicJsonBuffer jsonBuffer(bufferSize);
JsonObject& jb = jsonBuffer.parseObject(in); JsonObject& jb = jsonBuffer.parseObject(in);
return _load(jb); return _load(jb);
} }
/**
* Load all elements of AutoConectAux page from JSON object.
* @param jb Reference of JSON object
* @return true Successfully loaded.
* @return false loading unsuccessful, JSON parsing error occurred.
*/
bool AutoConnectAux::_load(JsonObject& jb) { bool AutoConnectAux::_load(JsonObject& jb) {
if (!jb.success()) if (!jb.success()) {
AC_DBG("json parse error\n");
return false; return false;
}
_title = jb.get<String>(F(AUTOCONNECT_JSON_KEY_TITLE)); _title = jb.get<String>(F(AUTOCONNECT_JSON_KEY_TITLE));
_uriStr = jb.get<String>(F(AUTOCONNECT_JSON_KEY_URI)); _uriStr = jb.get<String>(F(AUTOCONNECT_JSON_KEY_URI));
@ -332,19 +354,21 @@ bool AutoConnectAux::_load(JsonObject& jb) {
* @return A reference of loaded AutoConnectElement instance. * @return A reference of loaded AutoConnectElement instance.
*/ */
AutoConnectElement& AutoConnectAux::loadElement(const char* in, const String name) { AutoConnectElement& AutoConnectAux::loadElement(const char* in, const String name) {
DynamicJsonBuffer jsonBuffer; const size_t bufferSize = _calcJsonBufferSize(in);
DynamicJsonBuffer jsonBuffer(bufferSize);
JsonObject& jb = jsonBuffer.parseObject(in); JsonObject& jb = jsonBuffer.parseObject(in);
return _loadElement(jb, name); return _loadElement(jb, name);
} }
AutoConnectElement& AutoConnectAux::loadElement(const __FlashStringHelper* in, const String name) { AutoConnectElement& AutoConnectAux::loadElement(const __FlashStringHelper* in, const String name) {
DynamicJsonBuffer jsonBuffer; const size_t bufferSize = _calcJsonBufferSize(in);
DynamicJsonBuffer jsonBuffer(bufferSize);
JsonObject& jb = jsonBuffer.parseObject(in); JsonObject& jb = jsonBuffer.parseObject(in);
return _loadElement(jb, name); return _loadElement(jb, name);
} }
AutoConnectElement& AutoConnectAux::loadElement(Stream& in, const String name) { AutoConnectElement& AutoConnectAux::loadElement(Stream& in, const String name, const size_t bufferSize) {
DynamicJsonBuffer jsonBuffer; DynamicJsonBuffer jsonBuffer(bufferSize);
JsonObject& jb = jsonBuffer.parseObject(in); JsonObject& jb = jsonBuffer.parseObject(in);
return _loadElement(jb, name); return _loadElement(jb, name);
} }
@ -353,8 +377,10 @@ AutoConnectElement& AutoConnectAux::_loadElement(JsonObject& jb, const String na
AutoConnectElement* auxElm = nullptr; AutoConnectElement* auxElm = nullptr;
bool wc = name == "*"; bool wc = name == "*";
if (!jb.success()) if (!jb.success()) {
AC_DBG("json parse error\n");
return _nullElement(); return _nullElement();
}
JsonArray& elements = jb[AUTOCONNECT_JSON_KEY_ELEMENT]; JsonArray& elements = jb[AUTOCONNECT_JSON_KEY_ELEMENT];
for (JsonObject& element : elements) { for (JsonObject& element : elements) {
@ -387,7 +413,7 @@ AutoConnectElement& AutoConnectAux::_loadElement(JsonObject& jb, const String na
} }
/** /**
* Serialize the element to JSON and write it to the stream. * Serialize a element to JSON and write it to the stream.
* @param out An output stream * @param out An output stream
* @param element A reference of the element to be output. * @param element A reference of the element to be output.
* @return Number of byte output * @return Number of byte output
@ -468,4 +494,141 @@ AutoConnectElement& AutoConnectAux::_nullElement() {
return nullElement; return nullElement;
} }
/**
* Calculate JSON dynamic buffer size.
* @param in JSON string
* @return Estimated buffer size.
*/
size_t AutoConnectAux::_calcJsonBufferSize(const char* in) {
_initJsonBufferSize();
while (*in)
_accJsonBufferSize(*in++);
return _resultJsonBufferSize();
}
/**
* Calculate JSON dynamic buffer size.
* @param in JSON string stored in pgm_data.
* @return Estimated buffer size.
*/
size_t AutoConnectAux::_calcJsonBufferSize(const __FlashStringHelper* in) {
_initJsonBufferSize();
uint8_t c = pgm_read_byte_near(reinterpret_cast<const char*>(in));
size_t l = 0;
while (c) {
_accJsonBufferSize(static_cast<const char>(c));
c = pgm_read_byte_near(reinterpret_cast<const char*>(in) + ++l);
}
return _resultJsonBufferSize();
}
/**
* Initialize the stacks for JSON Dynamic buffer size calculation.
*/
void AutoConnectAux::_initJsonBufferSize() {
_jbSize = 0;
_jbByte = 0;
_jbObject = 0;
_jbArray = 0;
_jbNest = 0;
_kp = -1;
_np = -1;
_jbOpen = false;
_jbLiteral = false;
}
/**
* Accumulate JSON Dynamic buffer size.
*/
void AutoConnectAux::_accJsonBufferSize(const char c) {
if (_jbSize < 0)
return;
if (!isGraph(c))
return;
if (_jbLiteral)
_jbByte++;
switch (c) {
case '"':
_jbLiteral = !_jbLiteral;
break;
case ':':
_jbObject++;
_jbOpen = false;
break;
case '{':
if (_jbObject > 0) {
if (_np >= AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH) {
_jbSize = -1;
break;
}
_nStack[++_np] = _jbObject;
}
_jbObject = 0;
_jbOpen = true;
break;
case '}':
if (_jbNest > 0)
_jbArray++;
if (_jbObject > 0) {
_jbSize += JSON_OBJECT_SIZE(_jbObject);
_jbByte += 2;
}
_jbObject = _nStack[_np--];
_jbOpen = false;
break;
case '[':
if (_jbNest++ > 0) {
if (_kp >= AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH) {
_jbSize = -1;
break;
}
_kStack[++_kp] = _jbArray;
}
_jbArray = 0;
if (_jbObject > 0) {
if (_np >= AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH) {
_jbSize = -1;
break;
}
_nStack[++_np] = _jbObject;
_jbObject = 0;
}
_jbOpen = true;
break;
case ']':
if (_jbOpen)
_jbArray++;
_jbSize += JSON_ARRAY_SIZE(_jbArray);
_jbByte += 2;
_jbArray = _nStack[_kp--];
_jbNest--;
if (_np >= 0)
_jbObject = _nStack[_np--];
_jbObject = false;
break;
case ',':
if (_jbObject && _jbNest > 0)
_jbArray++;
break;
}
}
/**
* Retrieve accumulated result value of JSON dynamic buffer size.
* @return the JSON Dynamic Buffer Size
*/
size_t AutoConnectAux::_resultJsonBufferSize() {
if (_jbSize < 0) {
AC_DBG("json buffer calculation error\n");
return -1;
}
else {
AC_DBG("json buffer size:%d\n", _jbSize + _jbByte + 200);
return static_cast<size_t>(_jbSize + _jbByte + 200);
}
}
#endif #endif

@ -20,7 +20,9 @@
#include <PageBuilder.h> #include <PageBuilder.h>
#include "AutoConnectElement.h" #include "AutoConnectElement.h"
class AutoConnect; #define AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH 3
class AutoConnect; // Reference to avoid circular
// Manage placed AutoConnectElement with a vector // Manage placed AutoConnectElement with a vector
typedef std::vector<std::reference_wrapper<AutoConnectElement>> AutoConnectElementVT; typedef std::vector<std::reference_wrapper<AutoConnectElement>> AutoConnectElementVT;
@ -31,13 +33,11 @@ typedef std::function<String(PageArgument&)> AuxHandlerFunctionT;
// A type for the order in which callback functions are called. // A type for the order in which callback functions are called.
typedef enum { typedef enum {
AC_EXIT_AHEAD = 1, AC_EXIT_AHEAD = 1, /**< */
AC_EXIT_LATER = 2, AC_EXIT_LATER = 2,
AC_EXIT_BOTH = 3 AC_EXIT_BOTH = 3
} AutoConnectExitOrder_t; } AutoConnectExitOrder_t;
//class AutoConnect; // Reference to avoid circular
/** /**
* A class that handles an auxiliary page with AutoConnectElement * A class that handles an auxiliary page with AutoConnectElement
* that placed on it by binding it to the AutoConnect menu. * that placed on it by binding it to the AutoConnect menu.
@ -60,30 +60,30 @@ class AutoConnectAux : public PageBuilder {
void on(const AuxHandlerFunctionT handler, const AutoConnectExitOrder_t order = AC_EXIT_AHEAD) { _handler = handler; _order = order; } /**< Set user handler */ void on(const AuxHandlerFunctionT handler, const AutoConnectExitOrder_t order = AC_EXIT_AHEAD) { _handler = handler; _order = order; } /**< Set user handler */
#ifdef AUTOCONNECT_USE_JSON #ifdef AUTOCONNECT_USE_JSON
bool load(const char* in); bool load(const char* in); /**< Load whole elements to AutoConnectAux Page */
bool load(const __FlashStringHelper* in); bool load(const __FlashStringHelper* in); /**< Load whole elements to AutoConnectAux Page */
bool load(Stream& in); bool load(Stream& in, const size_t bufferSize = AUTOCONNECT_JSON_BUFFER_SIZE); /**< Load whole elements to AutoConnectAux Page */
AutoConnectElement& loadElement(const char* in, const String name = "*"); AutoConnectElement& loadElement(const char* in, const String name = "*"); /**< Load specified element */
AutoConnectElement& loadElement(const __FlashStringHelper* in, const String name = "*"); AutoConnectElement& loadElement(const __FlashStringHelper* in, const String name = "*"); /**< Load specified element */
AutoConnectElement& loadElement(Stream& in, const String name = "*"); AutoConnectElement& loadElement(Stream& in, const String name = "*", const size_t bufferSize = AUTOCONNECT_JSON_BUFFER_SIZE); /**< Load specified element */
size_t saveElement(Stream& out, const AutoConnectElement& element); size_t saveElement(Stream& out, const AutoConnectElement& element); /**< Load specified element */
#endif #endif
protected: protected:
void _concat(AutoConnectAux& aux); void _concat(AutoConnectAux& aux); /**< Make up chain of AutoConnectAux */
void _join(AutoConnect& ac); void _join(AutoConnect& ac); /**< Make a link to AutoConnect */
PageElement* _setupPage(String uri); PageElement* _setupPage(String uri); /**< AutoConnectAux page builder */
const String _insertElement(PageArgument& args); const String _insertElement(PageArgument& args); /**< Insert a generated HTML to the page built by PageBuilder */
const String _injectTitle(PageArgument& args) { return _title; } const String _injectTitle(PageArgument& args) { return _title; } /**< Returns title of this page to PageBuilder */
const String _injectMenu(PageArgument& args); const String _injectMenu(PageArgument& args); /**< Inject menu title of this page to PageBuilder */
#ifdef AUTOCONNECT_USE_JSON #ifdef AUTOCONNECT_USE_JSON
bool _load(JsonObject& in); bool _load(JsonObject& in); /**< Load all elements from JSON object */
AutoConnectElement& _loadElement(JsonObject& in, const String name); AutoConnectElement& _loadElement(JsonObject& in, const String name); /**< Load an element as specified name from JSON object */
AutoConnectElement* _createElement(const JsonObject& json); AutoConnectElement* _createElement(const JsonObject& json); /**< Create an AutoConnectElement instance from JSON object */
AutoConnectElement* _getElement(const String name); AutoConnectElement* _getElement(const String name); /**< Get registered AutoConnectElement as specified name */
static const ACElement_t _asElementType(const String type); static const ACElement_t _asElementType(const String type); /**< Convert a string of element type to the enumeration value */
static AutoConnectElement& _nullElement(void); static AutoConnectElement& _nullElement(void); /**< A static returning value as invalid */
#endif #endif
String _title; /**< A title of the page */ String _title; /**< A title of the page */
@ -99,6 +99,25 @@ class AutoConnectAux : public PageBuilder {
// Protected members can be used from AutoConnect which handles AutoConnectAux pages. // Protected members can be used from AutoConnect which handles AutoConnectAux pages.
friend class AutoConnect; friend class AutoConnect;
private:
size_t _calcJsonBufferSize(const char* in); /**< Calculate JSON buffer size for constant character array */
size_t _calcJsonBufferSize(const __FlashStringHelper* in); /**< Calculate JSON buffer size for pgm_data */
void _initJsonBufferSize(void); /**< Initialize the stacks for JSON Dynamic buffer size calculation */
void _accJsonBufferSize(const char c); /**< Accumulate JSON Dynamic buffer size */
size_t _resultJsonBufferSize(void); /**< Retrieve accumulated result value */
int16_t _jbSize; /**< JSON dynamic buffer size */
uint16_t _jbByte; /**< Byte count for calculation of JSON buffer */
uint8_t _jbObject; /**< Object count for calculation of JSON buffer */
uint8_t _jbArray; /**< Array count for calculation of JSON buffer */
uint8_t _jbNest; /**< JSON array nest count */
uint8_t _kStack[AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH]; /**< JSON array counter stack */
uint8_t _nStack[AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH]; /**< JSON object counter stack */
int8_t _kp; /**< Stack pointer for JSON array counter */
int8_t _np; /**< Stack pointer for JSON object counter */
bool _jbOpen; /**< JSON object paring status */
bool _jbLiteral; /**< JSON object lexical status */
}; };
#endif // _AUTOCONNECTAUX_H_ #endif // _AUTOCONNECTAUX_H_

@ -22,6 +22,7 @@ using AutoConnectRadio = AutoConnectRadioJson;
using AutoConnectSelect = AutoConnectSelectJson; using AutoConnectSelect = AutoConnectSelectJson;
using AutoConnectSubmit = AutoConnectSubmitJson; using AutoConnectSubmit = AutoConnectSubmitJson;
using AutoConnectText = AutoConnectTextJson; using AutoConnectText = AutoConnectTextJson;
#define AUTOCONNECT_JSON_BUFFER_SIZE 3000
#else #else
using AutoConnectElement = AutoConnectElementBasis; using AutoConnectElement = AutoConnectElementBasis;
using AutoConnectButton = AutoConnectButtonBasis; using AutoConnectButton = AutoConnectButtonBasis;

Loading…
Cancel
Save