From 0845ad64a80f356c3546b3d7e742b49693fce407 Mon Sep 17 00:00:00 2001 From: Hieromon Ikasamo Date: Mon, 3 Dec 2018 03:30:57 +0900 Subject: [PATCH] Supports AutoConnectAux --- .travis.yml | 4 +- README.md | 12 +-- mkdocs/advancedusage.md | 8 +- mkdocs/api.md | 4 + mkdocs/index.md | 11 ++- mkdocs/license.md | 3 + src/AutoConnect.cpp | 6 +- src/AutoConnectAux.cpp | 201 +++++++++++++++++++++++++++++++++++---- src/AutoConnectAux.h | 65 ++++++++----- src/AutoConnectElement.h | 1 + 10 files changed, 259 insertions(+), 56 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8ee77d1..9e787cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: generic env: global: - - IDE_VERSION=1.8.5 + - IDE_VERSION=1.8.6 matrix: - BOARD="esp8266:esp8266:nodemcuv2:CpuFrequency=160,FlashSize=4M3M" - BOARD="esp32:esp32:esp32:FlashFreq=80,FlashSize=4M" @@ -20,7 +20,7 @@ before_install: - if [[ "$BOARD" =~ "esp32:esp32:" ]]; then arduino --install-boards esp32:esp32; 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; } install: - mkdir -p ~/Arduino/libraries diff --git a/README.md b/README.md index fa27055..94cc84f 100644 --- a/README.md +++ b/README.md @@ -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. -### Adding the user-owned web screen can easily ENHANCED w/ v0.9.7 +### Easily add user-owned web screen and parameters ENHANCED w/ v0.9.7 -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 ENHANCED w/ v0.9.7 +### Just loading the JSON description ENHANCED w/ v0.9.7 -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 @@ -89,11 +89,11 @@ Full documentation is available on https://Hieromon.github.io/AutoConnect, some ## 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 loading and saving of user-defined parameters with JSON format. - 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 - Improvement of RSSI detection for saved SSIDs. diff --git a/mkdocs/advancedusage.md b/mkdocs/advancedusage.md index ced6b7e..a4e0fcf 100644 --- a/mkdocs/advancedusage.md +++ b/mkdocs/advancedusage.md @@ -88,7 +88,9 @@ void loop() { ### 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 #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" ``` -### Static IP assignment [^1] +### 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*. @@ -262,4 +264,4 @@ portal.config(Config); 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. diff --git a/mkdocs/api.md b/mkdocs/api.md index c7bd30a..f6d11f2 100644 --- a/mkdocs/api.md +++ b/mkdocs/api.md @@ -20,8 +20,12 @@ #define AUTOCONNECT_STARTUPTIME 10 // Default waiting time[s] for after reset #define AUTOCONNECT_URI "/_ac" // Default AutoConnect root path #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 ### Constructors diff --git a/mkdocs/index.md b/mkdocs/index.md index c4f0ce9..8fb6692 100644 --- a/mkdocs/index.md +++ b/mkdocs/index.md @@ -75,10 +75,19 @@ Install third-party platform using the *Boards Manager* of Arduino IDE. You can Additional necessary library 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] +[^1]:Since AutoConnect v0.9.7, PageBuilder v1.2.0 later is required. + + Optional required library + +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 Clone or download from the [AutoConnect GitHub repository](https://github.com/Hieromon/AutoConnect). diff --git a/mkdocs/license.md b/mkdocs/license.md index 556a3fe..36de71e 100644 --- a/mkdocs/license.md +++ b/mkdocs/license.md @@ -13,3 +13,6 @@ IN THE SOFTWARE. The **Luxbar** is licensed under the MIT License. https://github.com/balzss/luxbar + +**ArduinoJson** is licensed under the MIT License. +https://arduinojson.org/ diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index ab887ed..a0f996c 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -156,11 +156,13 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long WiFi.setAutoConnect(false); _disconnectWiFi(true); WiFi.mode(WIFI_AP_STA); - delay(100); + delay(300); // 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))) { - _config(); + if (!_config()) { + AC_DBG("APConfig failed\n"); + } } WiFi.softAP(_apConfig.apid.c_str(), _apConfig.psk.c_str(), _apConfig.channel, _apConfig.hidden); while (WiFi.softAPIP() == IPAddress(0, 0, 0, 0)) diff --git a/src/AutoConnectAux.cpp b/src/AutoConnectAux.cpp index c74399c..9b5c4ec 100644 --- a/src/AutoConnectAux.cpp +++ b/src/AutoConnectAux.cpp @@ -6,7 +6,6 @@ * @date 2018-11-17 * @copyright MIT license. */ - #include "AutoConnect.h" #include "AutoConnectAux.h" #include "AutoConnectElement.h" @@ -151,22 +150,24 @@ const String AutoConnectAux::_insertElement(PageArgument& args) { AC_UNUSED(args); String body = String(); - if (_handler) + if (_handler) { if (_order & AC_EXIT_AHEAD) { AC_DBG("CB %s\n", uri()); body += _handler(args); } + } for (std::size_t n = 0; n < _addonElm.size(); n++) { AutoConnectElement& addon = _addonElm[n]; body += addon.toHTML(); } - if (_handler) + if (_handler) { if (_order & AC_EXIT_LATER) { AC_DBG("CB %s\n", uri()); body += _handler(args); } + } return body; } @@ -280,38 +281,59 @@ AutoConnectElement* AutoConnectAux::_createElement(const JsonObject& json) { /** * 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. * @return true The element collection successfully loaded. * @return false Invalid JSON data occurred. */ bool AutoConnectAux::load(const char* in) { -// DynamicJsonBuffer jsonBuffer(); - 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; + const size_t bufferSize = _calcJsonBufferSize(in); DynamicJsonBuffer jsonBuffer(bufferSize); JsonObject& jb = jsonBuffer.parseObject(in); 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) { -// DynamicJsonBuffer jsonBuffer(); - 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; + const size_t bufferSize = _calcJsonBufferSize(in); DynamicJsonBuffer jsonBuffer(bufferSize); JsonObject& jb = jsonBuffer.parseObject(in); return _load(jb); } -bool AutoConnectAux::load(Stream& in) { -// DynamicJsonBuffer jsonBuffer(); - 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; +/** + * Constructs an AutoConnectAux instance by reading all the + * 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); JsonObject& jb = jsonBuffer.parseObject(in); 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) { - if (!jb.success()) + if (!jb.success()) { + AC_DBG("json parse error\n"); return false; + } _title = jb.get(F(AUTOCONNECT_JSON_KEY_TITLE)); _uriStr = jb.get(F(AUTOCONNECT_JSON_KEY_URI)); @@ -332,19 +354,21 @@ bool AutoConnectAux::_load(JsonObject& jb) { * @return A reference of loaded AutoConnectElement instance. */ 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); return _loadElement(jb, 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); return _loadElement(jb, name); } -AutoConnectElement& AutoConnectAux::loadElement(Stream& in, const String name) { - DynamicJsonBuffer jsonBuffer; +AutoConnectElement& AutoConnectAux::loadElement(Stream& in, const String name, const size_t bufferSize) { + DynamicJsonBuffer jsonBuffer(bufferSize); JsonObject& jb = jsonBuffer.parseObject(in); return _loadElement(jb, name); } @@ -353,8 +377,10 @@ AutoConnectElement& AutoConnectAux::_loadElement(JsonObject& jb, const String na AutoConnectElement* auxElm = nullptr; bool wc = name == "*"; - if (!jb.success()) + if (!jb.success()) { + AC_DBG("json parse error\n"); return _nullElement(); + } JsonArray& elements = jb[AUTOCONNECT_JSON_KEY_ELEMENT]; 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 element A reference of the element to be output. * @return Number of byte output @@ -464,8 +490,145 @@ const ACElement_t AutoConnectAux::_asElementType(const String type) { * @return A reference of a static element defined by name as null. */ AutoConnectElement& AutoConnectAux::_nullElement() { - static AutoConnectElement nullElement("",""); + static AutoConnectElement 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(in)); + size_t l = 0; + while (c) { + _accJsonBufferSize(static_cast(c)); + c = pgm_read_byte_near(reinterpret_cast(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(_jbSize + _jbByte + 200); + } +} + #endif diff --git a/src/AutoConnectAux.h b/src/AutoConnectAux.h index e935688..a024249 100644 --- a/src/AutoConnectAux.h +++ b/src/AutoConnectAux.h @@ -20,7 +20,9 @@ #include #include "AutoConnectElement.h" -class AutoConnect; +#define AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH 3 + +class AutoConnect; // Reference to avoid circular // Manage placed AutoConnectElement with a vector typedef std::vector> AutoConnectElementVT; @@ -31,13 +33,11 @@ typedef std::function AuxHandlerFunctionT; // A type for the order in which callback functions are called. typedef enum { - AC_EXIT_AHEAD = 1, + AC_EXIT_AHEAD = 1, /**< */ AC_EXIT_LATER = 2, AC_EXIT_BOTH = 3 } AutoConnectExitOrder_t; -//class AutoConnect; // Reference to avoid circular - /** * A class that handles an auxiliary page with AutoConnectElement * 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 */ #ifdef AUTOCONNECT_USE_JSON - bool load(const char* in); - bool load(const __FlashStringHelper* in); - bool load(Stream& in); - AutoConnectElement& loadElement(const char* in, const String name = "*"); - AutoConnectElement& loadElement(const __FlashStringHelper* in, const String name = "*"); - AutoConnectElement& loadElement(Stream& in, const String name = "*"); - size_t saveElement(Stream& out, const AutoConnectElement& element); + bool load(const char* in); /**< Load whole elements to AutoConnectAux Page */ + bool load(const __FlashStringHelper* in); /**< Load whole elements to AutoConnectAux Page */ + 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 = "*"); /**< Load specified element */ + AutoConnectElement& loadElement(const __FlashStringHelper* in, const String name = "*"); /**< Load specified element */ + 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); /**< Load specified element */ #endif protected: - void _concat(AutoConnectAux& aux); - void _join(AutoConnect& ac); - PageElement* _setupPage(String uri); - const String _insertElement(PageArgument& args); - const String _injectTitle(PageArgument& args) { return _title; } - const String _injectMenu(PageArgument& args); + void _concat(AutoConnectAux& aux); /**< Make up chain of AutoConnectAux */ + void _join(AutoConnect& ac); /**< Make a link to AutoConnect */ + PageElement* _setupPage(String uri); /**< AutoConnectAux page builder */ + const String _insertElement(PageArgument& args); /**< Insert a generated HTML to the page built by PageBuilder */ + const String _injectTitle(PageArgument& args) { return _title; } /**< Returns title of this page to PageBuilder */ + const String _injectMenu(PageArgument& args); /**< Inject menu title of this page to PageBuilder */ #ifdef AUTOCONNECT_USE_JSON - bool _load(JsonObject& in); - AutoConnectElement& _loadElement(JsonObject& in, const String name); - AutoConnectElement* _createElement(const JsonObject& json); - AutoConnectElement* _getElement(const String name); - static const ACElement_t _asElementType(const String type); - static AutoConnectElement& _nullElement(void); + bool _load(JsonObject& in); /**< Load all elements from JSON object */ + AutoConnectElement& _loadElement(JsonObject& in, const String name); /**< Load an element as specified name from JSON object */ + AutoConnectElement* _createElement(const JsonObject& json); /**< Create an AutoConnectElement instance from JSON object */ + AutoConnectElement* _getElement(const String name); /**< Get registered AutoConnectElement as specified name */ + static const ACElement_t _asElementType(const String type); /**< Convert a string of element type to the enumeration value */ + static AutoConnectElement& _nullElement(void); /**< A static returning value as invalid */ #endif 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. 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_ \ No newline at end of file diff --git a/src/AutoConnectElement.h b/src/AutoConnectElement.h index 2fa9883..82cc153 100644 --- a/src/AutoConnectElement.h +++ b/src/AutoConnectElement.h @@ -22,6 +22,7 @@ using AutoConnectRadio = AutoConnectRadioJson; using AutoConnectSelect = AutoConnectSelectJson; using AutoConnectSubmit = AutoConnectSubmitJson; using AutoConnectText = AutoConnectTextJson; +#define AUTOCONNECT_JSON_BUFFER_SIZE 3000 #else using AutoConnectElement = AutoConnectElementBasis; using AutoConnectButton = AutoConnectButtonBasis;