From a7402ea391b270022c13ca66c5a2e30c6ae3ac5f Mon Sep 17 00:00:00 2001 From: Hieromon Ikasamo Date: Wed, 19 Dec 2018 19:07:51 +0900 Subject: [PATCH] Supports AutoConnectAux --- keywords.txt | 1 - src/AutoConnect.cpp | 9 +- src/AutoConnect.h | 6 +- src/AutoConnectAux.cpp | 226 +++++++++++++++++++++------------------- src/AutoConnectAux.h | 61 +++++------ src/AutoConnectPage.cpp | 2 +- 6 files changed, 154 insertions(+), 151 deletions(-) diff --git a/keywords.txt b/keywords.txt index a181bde..54fc3cf 100644 --- a/keywords.txt +++ b/keywords.txt @@ -39,7 +39,6 @@ onDetect KEYWORD2 onNotFound KEYWORD2 release KEYWORD2 save KEYWORD2 -saveElement KEYWORD2 setElementValue KEYWORD2 setTitle KEYWORD2 toHTML KEYWORD2 diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index b6d4187..3509837 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -285,10 +285,10 @@ WebServerClass& AutoConnect::host() { * @param uri An uri string. * @return A pointer of AutoConnectAux instance. */ -AutoConnectAux* AutoConnect::aux(const char* uri) const { +AutoConnectAux* AutoConnect::aux(const String& uri) const { AutoConnectAux* aux_p = _aux.get(); while (aux_p) { - if (!strcmp(aux_p->uri(), uri)) + if (!strcmp(aux_p->uri(), uri.c_str())) break; aux_p = aux_p->_next.get(); } @@ -339,7 +339,6 @@ void AutoConnect::_startWebServer() { _webServer->onNotFound(std::bind(&AutoConnect::_handleNotFound, this)); // here, Prepare PageBuilders for captive portal _responsePage = new PageBuilder(); -// _responsePage->chunked(PB_ByteStream); _responsePage->chunked(PB_ByteStream); _responsePage->exitCanHandle(std::bind(&AutoConnect::_classifyHandle, this, std::placeholders::_1, std::placeholders::_2)); _responsePage->insert(*_webServer); @@ -460,10 +459,10 @@ void AutoConnect::handleRequest() { * @return false AutoConnectAux page for the specified URI is not * registered. */ -bool AutoConnect::on(const char* uri, const AuxHandlerFunctionT handler, AutoConnectExitOrder_t order) { +bool AutoConnect::on(const String& uri, const AuxHandlerFunctionT handler, AutoConnectExitOrder_t order) { AutoConnectAux* aux = _aux.get(); while (aux) { - if (!strcmp(uri, aux->uri())) { + if (!strcmp(uri.c_str(), aux->uri())) { aux->on(handler, order); return true; } diff --git a/src/AutoConnect.h b/src/AutoConnect.h index b4c1fc2..f6b568b 100644 --- a/src/AutoConnect.h +++ b/src/AutoConnect.h @@ -154,7 +154,7 @@ class AutoConnect { AutoConnect(); AutoConnect(WebServerClass& webServer); ~AutoConnect(); - AutoConnectAux* aux(const char* uri) const; + AutoConnectAux* aux(const String& uri) const; bool config(AutoConnectConfig& Config); bool config(const char* ap, const char* password = nullptr); void home(String uri); @@ -166,11 +166,11 @@ class AutoConnect { WebServerClass& host(); bool join(AutoConnectAux& aux); bool join(std::vector> aux); - bool on(const char* uri, const AuxHandlerFunctionT handler, AutoConnectExitOrder_t order = AC_EXIT_AHEAD); + bool on(const String& uri, const AuxHandlerFunctionT handler, AutoConnectExitOrder_t order = AC_EXIT_AHEAD); /** For AutoConnectAux described in JSON */ #ifdef AUTOCONNECT_USE_JSON - bool load(const char* aux); + bool load(const String& aux); bool load(const __FlashStringHelper* aux); bool load(Stream& aux, size_t bufferSize = AUTOCONNECT_JSON_BUFFER_SIZE); bool _load(JsonVariant& aux); diff --git a/src/AutoConnectAux.cpp b/src/AutoConnectAux.cpp index e4a4e0d..2545f28 100644 --- a/src/AutoConnectAux.cpp +++ b/src/AutoConnectAux.cpp @@ -93,7 +93,7 @@ void AutoConnectAux::add(AutoConnectElementVT addons) { * @param name Element name * @return A pointer to the registered AutoConnectElement. */ -AutoConnectElement* AutoConnectAux::getElement(const String name) { +AutoConnectElement* AutoConnectAux::getElement(const String& name) { for (std::size_t n = 0; n < _addonElm.size(); n++) if (name.equalsIgnoreCase(_addonElm[n].get().name)) return &(_addonElm[n].get()); @@ -109,7 +109,7 @@ AutoConnectElement* AutoConnectAux::getElement(const String name) { * @return true The specified AutoConnectElements have been released. * @return false The specified AutoConnectElement not found in AutoConnectAux. */ -bool AutoConnectAux::release(const String name) { +bool AutoConnectAux::release(const String& name) { bool rc = false; for (std::size_t n = 0; n < _addonElm.size(); n++) { String elmName = _addonElm[n].get().name; @@ -130,7 +130,7 @@ bool AutoConnectAux::release(const String name) { * @return false An element specified name is not registered, * or its element value does not match storage type. */ -bool AutoConnectAux::setElementValue(const String name, const String value) { +bool AutoConnectAux::setElementValue(const String& name, const String value) { AutoConnectElement* elm = getElement(name); if (elm) { if (elm->typeOf() != AC_Select && elm->typeOf() != AC_Radio) { @@ -151,7 +151,7 @@ bool AutoConnectAux::setElementValue(const String name, const String value) { * @return false An element specified name is not registered, * or its element value must be array. */ -bool AutoConnectAux::setElementValue(const String name, std::vector values) { +bool AutoConnectAux::setElementValue(const String& name, std::vector values) { bool rc = false; AutoConnectElement* elm = getElement(name); @@ -271,17 +271,17 @@ PageElement* AutoConnectAux::_setupPage(String uri) { elm = new PageElement(); // Construct the auxiliary page elm->setMold(_PAGE_AUX); - elm->addToken(PSTR("HEAD"), std::bind(&AutoConnect::_token_HEAD, mother, std::placeholders::_1)); - elm->addToken(PSTR("AUX_TITLE"), std::bind(&AutoConnectAux::_injectTitle, this, std::placeholders::_1)); - elm->addToken(PSTR("CSS_BASE"), std::bind(&AutoConnect::_token_CSS_BASE, mother, std::placeholders::_1)); - elm->addToken(PSTR("CSS_UL"), std::bind(&AutoConnect::_token_CSS_UL, mother, std::placeholders::_1)); - elm->addToken(PSTR("CSS_INPUT_BUTTON"), std::bind(&AutoConnect::_token_CSS_INPUT_BUTTON, mother, std::placeholders::_1)); - elm->addToken(PSTR("CSS_INPUT_TEXT"), std::bind(&AutoConnect::_token_CSS_INPUT_TEXT, mother, std::placeholders::_1)); - elm->addToken(PSTR("CSS_LUXBAR"), std::bind(&AutoConnect::_token_CSS_LUXBAR, mother, std::placeholders::_1)); - elm->addToken(PSTR("MENU_PRE"), std::bind(&AutoConnect::_token_MENU_PRE, mother, std::placeholders::_1)); - elm->addToken(PSTR("MENU_AUX"), std::bind(&AutoConnect::_token_MENU_AUX, mother, std::placeholders::_1)); - elm->addToken(PSTR("MENU_POST"), std::bind(&AutoConnect::_token_MENU_POST, mother, std::placeholders::_1)); - elm->addToken(PSTR("AUX_ELEMENT"), std::bind(&AutoConnectAux::_insertElement, this, std::placeholders::_1)); + elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, mother, std::placeholders::_1)); + elm->addToken(String(FPSTR("AUX_TITLE")), std::bind(&AutoConnectAux::_injectTitle, this, std::placeholders::_1)); + elm->addToken(String(FPSTR("CSS_BASE")), std::bind(&AutoConnect::_token_CSS_BASE, mother, std::placeholders::_1)); + elm->addToken(String(FPSTR("CSS_UL")), std::bind(&AutoConnect::_token_CSS_UL, mother, std::placeholders::_1)); + elm->addToken(String(FPSTR("CSS_INPUT_BUTTON")), std::bind(&AutoConnect::_token_CSS_INPUT_BUTTON, mother, std::placeholders::_1)); + elm->addToken(String(FPSTR("CSS_INPUT_TEXT")), std::bind(&AutoConnect::_token_CSS_INPUT_TEXT, mother, std::placeholders::_1)); + elm->addToken(String(FPSTR("CSS_LUXBAR")), std::bind(&AutoConnect::_token_CSS_LUXBAR, mother, std::placeholders::_1)); + elm->addToken(String(FPSTR("MENU_PRE")), std::bind(&AutoConnect::_token_MENU_PRE, mother, std::placeholders::_1)); + elm->addToken(String(FPSTR("MENU_AUX")), std::bind(&AutoConnect::_token_MENU_AUX, mother, std::placeholders::_1)); + elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, mother, std::placeholders::_1)); + elm->addToken(String(FPSTR("AUX_ELEMENT")), std::bind(&AutoConnectAux::_insertElement, this, std::placeholders::_1)); } } return elm; @@ -323,13 +323,13 @@ AutoConnectElement& AutoConnectAux::_nullElement() { * @return A reference of AutoConnectButton class. */ template<> -AutoConnectButtonBasis& AutoConnectAux::getElement(const char* name) { +AutoConnectButtonBasis& AutoConnectAux::getElement(const String& name) { AutoConnectElement* elm = getElement(name); if (elm) { if (elm->typeOf() == AC_Button) return *(reinterpret_cast(elm)); else - AC_DBG("Element<%s> type mismatch<%d>\n", name, elm->typeOf()); + AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); } return reinterpret_cast(_nullElement()); } @@ -340,13 +340,13 @@ AutoConnectButtonBasis& AutoConnectAux::getElement(const char* name) { * @return A reference of AutoConnectCheckbox class. */ template<> -AutoConnectCheckboxBasis& AutoConnectAux::getElement(const char* name) { +AutoConnectCheckboxBasis& AutoConnectAux::getElement(const String& name) { AutoConnectElement* elm = getElement(name); if (elm) { if (elm->typeOf() == AC_Checkbox) return *(reinterpret_cast(elm)); else - AC_DBG("Element<%s> type mismatch<%d>\n", name, elm->typeOf()); + AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); } return reinterpret_cast(_nullElement()); } @@ -357,13 +357,13 @@ AutoConnectCheckboxBasis& AutoConnectAux::getElement(const char* name) { * @return A reference of AutoConnectInput class. */ template<> -AutoConnectInputBasis& AutoConnectAux::getElement(const char* name) { +AutoConnectInputBasis& AutoConnectAux::getElement(const String& name) { AutoConnectElement* elm = getElement(name); if (elm) { if (elm->typeOf() == AC_Input) return *(reinterpret_cast(elm)); else - AC_DBG("Element<%s> type mismatch<%d>\n", name, elm->typeOf()); + AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); } return reinterpret_cast(_nullElement()); } @@ -374,13 +374,13 @@ AutoConnectInputBasis& AutoConnectAux::getElement(const char* name) { * @return A reference of AutoConnectRadio class. */ template<> -AutoConnectRadioBasis& AutoConnectAux::getElement(const char* name) { +AutoConnectRadioBasis& AutoConnectAux::getElement(const String& name) { AutoConnectElement* elm = getElement(name); if (elm) { if (elm->typeOf() == AC_Radio) return *(reinterpret_cast(elm)); else - AC_DBG("Element<%s> type mismatch<%d>\n", name, elm->typeOf()); + AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); } return reinterpret_cast(_nullElement()); } @@ -391,13 +391,13 @@ AutoConnectRadioBasis& AutoConnectAux::getElement(const char* name) { * @return A reference of AutoConnectSelect class. */ template<> -AutoConnectSelectBasis& AutoConnectAux::getElement(const char* name) { +AutoConnectSelectBasis& AutoConnectAux::getElement(const String& name) { AutoConnectElement* elm = getElement(name); if (elm) { if (elm->typeOf() == AC_Select) return *(reinterpret_cast(elm)); else - AC_DBG("Element<%s> type mismatch<%d>\n", name, elm->typeOf()); + AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); } return reinterpret_cast(_nullElement()); } @@ -408,13 +408,13 @@ AutoConnectSelectBasis& AutoConnectAux::getElement(const char* name) { * @return A reference of AutoConnectSubmit class. */ template<> -AutoConnectSubmitBasis& AutoConnectAux::getElement(const char* name) { +AutoConnectSubmitBasis& AutoConnectAux::getElement(const String& name) { AutoConnectElement* elm = getElement(name); if (elm) { if (elm->typeOf() == AC_Submit) return *(reinterpret_cast(elm)); else - AC_DBG("Element<%s> type mismatch<%d>\n", name, elm->typeOf()); + AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); } return reinterpret_cast(_nullElement()); } @@ -425,13 +425,13 @@ AutoConnectSubmitBasis& AutoConnectAux::getElement(const char* name) { * @return A reference of AutoConnectText class. */ template<> -AutoConnectTextBasis& AutoConnectAux::getElement(const char* name) { +AutoConnectTextBasis& AutoConnectAux::getElement(const String& name) { AutoConnectElement* elm = getElement(name); if (elm) { if (elm->typeOf() == AC_Text) return *(reinterpret_cast(elm)); else - AC_DBG("Element<%s> type mismatch<%d>\n", name, elm->typeOf()); + AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); } return reinterpret_cast(_nullElement()); } @@ -459,13 +459,13 @@ bool AutoConnectAux::_jbLiteral; /**< JSON object lexical status */ * @return A reference of AutoConnectButton class. */ template<> -AutoConnectButtonJson& AutoConnectAux::getElement(const char* name) { +AutoConnectButtonJson& AutoConnectAux::getElement(const String& name) { AutoConnectElement* elm = getElement(name); if (elm) { if (elm->typeOf() == AC_Button) return *(reinterpret_cast(elm)); else - AC_DBG("Element<%s> type mismatch<%d>\n", name, elm->typeOf()); + AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); } return reinterpret_cast(_nullElement()); } @@ -476,13 +476,13 @@ AutoConnectButtonJson& AutoConnectAux::getElement(const char* name) { * @return A reference of AutoConnectCheckbox class. */ template<> -AutoConnectCheckboxJson& AutoConnectAux::getElement(const char* name) { +AutoConnectCheckboxJson& AutoConnectAux::getElement(const String& name) { AutoConnectElement* elm = getElement(name); if (elm) { if (elm->typeOf() == AC_Checkbox) return *(reinterpret_cast(elm)); else - AC_DBG("Element<%s> type mismatch<%d>\n", name, elm->typeOf()); + AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); } return reinterpret_cast(_nullElement()); } @@ -493,13 +493,13 @@ AutoConnectCheckboxJson& AutoConnectAux::getElement(const char* name) { * @return A reference of AutoConnectInput class. */ template<> -AutoConnectInputJson& AutoConnectAux::getElement(const char* name) { +AutoConnectInputJson& AutoConnectAux::getElement(const String& name) { AutoConnectElement* elm = getElement(name); if (elm) { if (elm->typeOf() == AC_Input) return *(reinterpret_cast(elm)); else - AC_DBG("Element<%s> type mismatch<%d>\n", name, elm->typeOf()); + AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); } return reinterpret_cast(_nullElement()); } @@ -510,13 +510,13 @@ AutoConnectInputJson& AutoConnectAux::getElement(const char* name) { * @return A reference of AutoConnectRadio class. */ template<> -AutoConnectRadioJson& AutoConnectAux::getElement(const char* name) { +AutoConnectRadioJson& AutoConnectAux::getElement(const String& name) { AutoConnectElement* elm = getElement(name); if (elm) { if (elm->typeOf() == AC_Radio) return *(reinterpret_cast(elm)); else - AC_DBG("Element<%s> type mismatch<%d>\n", name, elm->typeOf()); + AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); } return reinterpret_cast(_nullElement()); } @@ -527,13 +527,13 @@ AutoConnectRadioJson& AutoConnectAux::getElement(const char* name) { * @return A reference of AutoConnectSelect class. */ template<> -AutoConnectSelectJson& AutoConnectAux::getElement(const char* name) { +AutoConnectSelectJson& AutoConnectAux::getElement(const String& name) { AutoConnectElement* elm = getElement(name); if (elm) { if (elm->typeOf() == AC_Select) return *(reinterpret_cast(elm)); else - AC_DBG("Element<%s> type mismatch<%d>\n", name, elm->typeOf()); + AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); } return reinterpret_cast(_nullElement()); } @@ -544,13 +544,13 @@ AutoConnectSelectJson& AutoConnectAux::getElement(const char* name) { * @return A reference of AutoConnectSubmit class. */ template<> -AutoConnectSubmitJson& AutoConnectAux::getElement(const char* name) { +AutoConnectSubmitJson& AutoConnectAux::getElement(const String& name) { AutoConnectElement* elm = getElement(name); if (elm) { if (elm->typeOf() == AC_Submit) return *(reinterpret_cast(elm)); else - AC_DBG("Element<%s> type mismatch<%d>\n", name, elm->typeOf()); + AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); } return reinterpret_cast(_nullElement()); } @@ -561,13 +561,13 @@ AutoConnectSubmitJson& AutoConnectAux::getElement(const char* name) { * @return A reference of AutoConnectText class. */ template<> -AutoConnectTextJson& AutoConnectAux::getElement(const char* name) { +AutoConnectTextJson& AutoConnectAux::getElement(const String& name) { AutoConnectElement* elm = getElement(name); if (elm) { if (elm->typeOf() == AC_Text) return *(reinterpret_cast(elm)); else - AC_DBG("Element<%s> type mismatch<%d>\n", name, elm->typeOf()); + AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); } return reinterpret_cast(_nullElement()); } @@ -579,20 +579,20 @@ AutoConnectTextJson& AutoConnectAux::getElement(const char* name) { * @param aux JSON description to be load. * @return true Successfully loaded. */ -bool AutoConnect::load(const char* aux) { - const size_t bufferSize = AutoConnectAux::_calcJsonBufferSize(aux); +bool AutoConnect::load(const String& aux) { + const size_t bufferSize = AutoConnectAux::_calcJsonBufferSize(aux.c_str()); DynamicJsonBuffer jsonBuffer(bufferSize); JsonVariant jv = jsonBuffer.parse(aux); return _load(jv); } /** - * Load AutoConnectAux page from JSON description stored in PROGMEM. - * This function can load AutoConnectAux for multiple AUX pages written - * in JSON and is registered in AutoConnect. - * @param aux JSON description to be load. - * @return true Successfully loaded. - */ +* Load AutoConnectAux page from JSON description stored in PROGMEM. +* This function can load AutoConnectAux for multiple AUX pages written +* in JSON and is registered in AutoConnect. +* @param aux JSON description to be load. +* @return true Successfully loaded. +*/ bool AutoConnect::load(const __FlashStringHelper* aux) { const size_t bufferSize = AutoConnectAux::_calcJsonBufferSize(aux); DynamicJsonBuffer jsonBuffer(bufferSize); @@ -704,8 +704,8 @@ AutoConnectElement* AutoConnectAux::_createElement(const JsonObject& json) { * @return true The element collection successfully loaded. * @return false Invalid JSON data occurred. */ -bool AutoConnectAux::load(const char* in) { - const size_t bufferSize = _calcJsonBufferSize(in); +bool AutoConnectAux::load(const String& in) { + const size_t bufferSize = _calcJsonBufferSize(in.c_str()); DynamicJsonBuffer jsonBuffer(bufferSize); JsonObject& jb = jsonBuffer.parseObject(in); return _load(jb); @@ -756,7 +756,8 @@ bool AutoConnectAux::_load(JsonObject& jb) { _uriStr = jb.get(F(AUTOCONNECT_JSON_KEY_URI)); _uri = _uriStr.c_str(); _menu = jb.get(F(AUTOCONNECT_JSON_KEY_MENU)); - (void)_loadElement(jb, "*"); + JsonVariant elements = jb[F(AUTOCONNECT_JSON_KEY_ELEMENT)]; + (void)_loadElement(elements, ""); return true; } @@ -770,61 +771,72 @@ bool AutoConnectAux::_load(JsonObject& jb) { * elements are to be loaded. * @return A reference of loaded AutoConnectElement instance. */ -AutoConnectElement& AutoConnectAux::loadElement(const String in, const String name) { +bool AutoConnectAux::loadElement(const String& in, const String& name) { const size_t bufferSize = _calcJsonBufferSize(in.c_str()); DynamicJsonBuffer jsonBuffer(bufferSize); - JsonObject& jb = jsonBuffer.parseObject(in); + JsonVariant jb = jsonBuffer.parse(in); return _loadElement(jb, name); } -AutoConnectElement& AutoConnectAux::loadElement(const __FlashStringHelper* in, const String name) { +bool AutoConnectAux::loadElement(const __FlashStringHelper* in, const String& name) { const size_t bufferSize = _calcJsonBufferSize(in); DynamicJsonBuffer jsonBuffer(bufferSize); - JsonObject& jb = jsonBuffer.parseObject(in); + JsonVariant jb = jsonBuffer.parse(in); return _loadElement(jb, name); } -AutoConnectElement& AutoConnectAux::loadElement(Stream& in, const String name, const size_t bufferSize) { +bool AutoConnectAux::loadElement(Stream& in, const String& name, const size_t bufferSize) { DynamicJsonBuffer jsonBuffer(bufferSize); - JsonObject& jb = jsonBuffer.parseObject(in); + JsonVariant jb = jsonBuffer.parse(in); return _loadElement(jb, name); } -AutoConnectElement& AutoConnectAux::_loadElement(JsonObject& jb, const String name) { - AutoConnectElement* auxElm = nullptr; - bool wc = name == "*"; - - if (!jb.success()) { - AC_DBG("json parse error\n"); - return _nullElement(); +bool AutoConnectAux::_loadElement(JsonVariant& jb, const String& name) { + bool rc = jb.success(); + if (rc) { + if (jb.is()) { + JsonArray& elements = jb.as(); + for (JsonObject& element : elements) { + AutoConnectElement& elm = _loadElement(element, name); + if (!elm.name.length()) { + rc = false; + break; + } + } + } + else { + JsonObject& element = jb.as(); + AutoConnectElement& elm = _loadElement(element, name); + if (!elm.name.length()) + rc = false; + } } + return rc; +} - JsonArray& elements = jb[AUTOCONNECT_JSON_KEY_ELEMENT]; - for (JsonObject& element : elements) { - String elmName = element.get(F(AUTOCONNECT_JSON_KEY_NAME)); - if (wc || name.equalsIgnoreCase(elmName)) { - // The specified element is defined in the JSON stream. - // Loads from JSON object. - auxElm = getElement(elmName); - // The element is not created yet, create new one. - if (!auxElm) { - if ((auxElm = _createElement(element))) { - AC_DBG("%s<%d> of %s created\n", elmName.c_str(), (int)(auxElm->typeOf()), uri()); - add(*auxElm); // Insert to AutoConnect - } - else { - AC_DBG("%s unknown element type\n", elmName.c_str()); - continue; - } +AutoConnectElement& AutoConnectAux::_loadElement(JsonObject& element, const String& name) { + AutoConnectElement* auxElm = nullptr; + String elmName = element.get(F(AUTOCONNECT_JSON_KEY_NAME)); + if (!name.length() || name.equalsIgnoreCase(elmName)) { + // The specified element is defined in the JSON stream. + // Loads from JSON object. + auxElm = getElement(elmName); + // The element is not created yet, create new one. + if (!auxElm) { + if ((auxElm = _createElement(element))) { + AC_DBG("%s<%d> of %s created\n", elmName.c_str(), (int)(auxElm->typeOf()), uri()); + add(*auxElm); // Insert to AutoConnect } - if (auxElm->loadMember(element)) - AC_DBG("%s<%d> of %s loaded\n", auxElm->name.c_str(), (int)auxElm->typeOf(), uri()); else { - // Element type mismatch - AC_DBG("Type of %s element mismatched\n", elmName.c_str()); - continue; + AC_DBG("%s unknown element type\n", elmName.c_str()); } } + if (auxElm->loadMember(element)) + AC_DBG("%s<%d> of %s loaded\n", auxElm->name.c_str(), (int)auxElm->typeOf(), uri()); + else { + // Element type mismatch + AC_DBG("Type of %s element mismatched\n", elmName.c_str()); + } } return auxElm ? *auxElm : _nullElement(); } @@ -864,7 +876,7 @@ size_t AutoConnectAux::save(Stream& out) { * @param name An element name to be output. * @return Number of bytes output */ -size_t AutoConnectAux::saveElement(const String name, Stream& out) { +size_t AutoConnectAux::saveElement(const String& name, Stream& out) { for (std::size_t n = 0; n < _addonElm.size(); n++) { AutoConnectElement& elm = _addonElm[n]; if (elm.name == name) { @@ -882,7 +894,7 @@ size_t AutoConnectAux::saveElement(const String name, Stream& out) { * @param type An element type as String * @return A type of ACElement_t */ -const ACElement_t AutoConnectAux::_asElementType(const String type) { +const ACElement_t AutoConnectAux::_asElementType(const String& type) { typedef struct { const char* tName; ACElement_t tEnum; @@ -900,17 +912,17 @@ const ACElement_t AutoConnectAux::_asElementType(const String type) { ACElement_t t = AC_Unknown; for (size_t n = 0; n < (sizeof(types) / sizeof(ACElementType_t)); n++) { - if (type.equalsIgnoreCase(String(types[n].tName))) + if (type.equalsIgnoreCase(String(FPSTR(types[n].tName)))) return types[n].tEnum; } return t; } /** -* Calculate JSON dynamic buffer size. -* @param in JSON string -* @return Estimated buffer size. -*/ + * Calculate JSON dynamic buffer size. + * @param in JSON string + * @return Estimated buffer size. + */ size_t AutoConnectAux::_calcJsonBufferSize(const char* in) { _initJsonBufferSize(); while (*in) @@ -919,10 +931,10 @@ size_t AutoConnectAux::_calcJsonBufferSize(const char* in) { } /** -* Calculate JSON dynamic buffer size. -* @param in JSON string stored in pgm_data. -* @return Estimated buffer size. -*/ + * 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)); @@ -935,8 +947,8 @@ size_t AutoConnectAux::_calcJsonBufferSize(const __FlashStringHelper* in) { } /** -* Initialize the stacks for JSON Dynamic buffer size calculation. -*/ + * Initialize the stacks for JSON Dynamic buffer size calculation. + */ void AutoConnectAux::_initJsonBufferSize() { _jbSize = 0; _jbByte = 0; @@ -950,8 +962,8 @@ void AutoConnectAux::_initJsonBufferSize() { } /** -* Accumulate JSON Dynamic buffer size. -*/ + * Accumulate JSON Dynamic buffer size. + */ void AutoConnectAux::_accJsonBufferSize(const char c) { if (_jbSize < 0) return; @@ -1029,9 +1041,9 @@ void AutoConnectAux::_accJsonBufferSize(const char c) { } /** -* Retrieve accumulated result value of JSON dynamic buffer size. -* @return the JSON Dynamic Buffer Size -*/ + * 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"); diff --git a/src/AutoConnectAux.h b/src/AutoConnectAux.h index 3b0800c..50b8507 100644 --- a/src/AutoConnectAux.h +++ b/src/AutoConnectAux.h @@ -3,7 +3,7 @@ * @file AutoConnectAuxBasis.h * @author hieromon@gmail.com * @version 0.9.7 - * @date 2018-11-17 + * @date 2018-12-17 * @copyright MIT license. */ @@ -20,7 +20,7 @@ #include #include "AutoConnectElement.h" -#define AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH 3 +#define AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH 3 class AutoConnect; // Reference to avoid circular class AutoConnectAux; // Reference to avoid circular @@ -29,14 +29,13 @@ class AutoConnectAux; // Reference to avoid circular typedef std::vector> AutoConnectElementVT; // A type of callback function when AutoConnectAux page requested. -//typedef std::function AuxHandleFuncT; typedef std::function AuxHandlerFunctionT; // A type for the order in which callback functions are called. typedef enum { - AC_EXIT_AHEAD = 1, /**< */ - AC_EXIT_LATER = 2, - AC_EXIT_BOTH = 3 + AC_EXIT_AHEAD = 1, /**< Callback before building HTML */ + AC_EXIT_LATER = 2, /**< Callback after building HTML */ + AC_EXIT_BOTH = 3 /**< Callback twice before and after building HTML */ } AutoConnectExitOrder_t; /** @@ -49,37 +48,30 @@ typedef enum { */ class AutoConnectAux : public PageBuilder { public: - explicit AutoConnectAux(const char* uri = nullptr, const char* title = "", const bool menu = true, const AutoConnectElementVT addons = AutoConnectElementVT()) : - _title(String(title)), _menu(menu), _addonElm(addons) { setUri(uri); _next.release(); _ac.release(); } + explicit AutoConnectAux(const String uri = String(""), const String title = String(""), const bool menu = true, const AutoConnectElementVT addons = AutoConnectElementVT()) : + _title(title), _menu(menu), _addonElm(addons) { setUri(uri.c_str()); _next.release(); _ac.release(); } ~AutoConnectAux(); - void add(AutoConnectElement& addon); /**< Add an element to the auxiliary page. */ - void add(AutoConnectElementVT addons); /**< Add the element set to the auxiliary page. */ + void add(AutoConnectElement& addon); /**< Add an element to the auxiliary page */ + void add(AutoConnectElementVT addons); /**< Add the element set to the auxiliary page */ template - T& getElement(const char* name); /**< Get AutoConnect element */ - AutoConnectElement* getElement(const char* name) { return getElement(String(name)); } /**< Get registered AutoConnectElement as specified name */ - AutoConnectElement* getElement(const String name); /**< Get registered AutoConnectElement as specified name */ - void menu(const bool post) { _menu = post; } /**< Set or reset the display as menu item for this aux. */ - bool release(const char* name) { return release(String(name)); } /**< Release an AutoConnectElement */ - bool release(const String name); /**< Release an AutoConnectElement */ - AutoConnectElement& setElement(AutoConnectElement& element); /**< Set or replace the element */ - bool setElementValue(const char* name, const String value) { return setElementValue(String(name), value); } - bool setElementValue(const String name, const String value); - bool setElementValue(const char* name, std::vector values) { return setElementValue(String(name), values); } - bool setElementValue(const String name, std::vector values); - void setTitle(const char* title) { setTitle(String(title)); } /**< Set a title of the auxiliary page. */ - void setTitle(const String title) { _title = title; } /**< Set a title of the auxiliary page. */ + T& getElement(const String& name); + AutoConnectElement* getElement(const String& name); /**< Get registered AutoConnectElement as specified name */ + void menu(const bool post) { _menu = post; } /**< Set or reset the display as menu item for this aux */ + bool release(const String& name); /**< Release an AutoConnectElement */ + bool setElementValue(const String& name, const String value); /**< Set value to specified element */ + bool setElementValue(const String& name, std::vector values); /**< Set values collection to specified element */ + void setTitle(const String title) { _title = title; } /**< Set a title of the auxiliary page */ 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); /**< Load whole elements to AutoConnectAux Page */ + bool load(const String& 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 String 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 */ + bool load(Stream& in, const size_t bufferSize = AUTOCONNECT_JSON_BUFFER_SIZE); /**< Load whole elements to AutoConnectAux Page */ + bool loadElement(const String& in, const String& name = String("")); /**< Load specified element */ + bool loadElement(const __FlashStringHelper* in, const String& name = String("")); /**< Load specified element */ + bool loadElement(Stream& in, const String& name = String(""), const size_t bufferSize = AUTOCONNECT_JSON_BUFFER_SIZE); /**< Load specified element */ size_t save(Stream& out); /**< Write AutoConnectAux elements to the stream */ - size_t saveElement(const char* name, Stream& out) { return saveElement(String(name), out); } /**< Write an element of AutoConnectAux to the stream */ - size_t saveElement(const String name, Stream& out); /**< Write an element of AutoConnectAux to the stream */ + size_t saveElement(const String& name, Stream& out); /**< Write an element of AutoConnectAux to the stream */ #endif // !AUTOCONNECT_USE_JSON protected: @@ -87,15 +79,16 @@ class AutoConnectAux : public PageBuilder { 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 _injectTitle(PageArgument& args) const { (void)(args); return _title; } /**< Returns title of this page to PageBuilder */ const String _injectMenu(PageArgument& args); /**< Inject menu title of this page to PageBuilder */ static AutoConnectElement& _nullElement(void); /**< A static returning value as invalid */ #ifdef AUTOCONNECT_USE_JSON - 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 */ + bool _load(JsonObject& in); /**< Load all elements from JSON object */ + bool _loadElement(JsonVariant& in, const String& name); /**< Load an element as specified name 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 */ - static const ACElement_t _asElementType(const String type); /**< Convert a string of element type to the enumeration value */ + static const ACElement_t _asElementType(const String& type); /**< Convert a string of element type to the enumeration value */ #endif // !AUTOCONNECT_USE_JSON String _title; /**< A title of the page */ diff --git a/src/AutoConnectPage.cpp b/src/AutoConnectPage.cpp index 9402900..1e92184 100644 --- a/src/AutoConnectPage.cpp +++ b/src/AutoConnectPage.cpp @@ -819,7 +819,7 @@ String AutoConnect::_token_CSS_TABLE(PageArgument& args) { String AutoConnect::_token_HEAD(PageArgument& args) { AC_UNUSED(args); - return String((_ELM_HTML_HEAD)); + return String(FPSTR(_ELM_HTML_HEAD)); } String AutoConnect::_token_MENU_PRE(PageArgument& args) {