From 8652dadfaf18174f8f48b687c815aa31dfb8d252 Mon Sep 17 00:00:00 2001 From: Hieromon Ikasamo Date: Tue, 11 Dec 2018 18:36:07 +0900 Subject: [PATCH] Supports AutoConnectAux --- keywords.txt | 7 + src/AutoConnect.cpp | 23 +++ src/AutoConnect.h | 9 +- src/AutoConnectAux.cpp | 252 +++++++++++++++++++++++++++--- src/AutoConnectAux.h | 15 +- src/AutoConnectElement.h | 4 +- src/AutoConnectElementBasis.h | 3 +- src/AutoConnectElementBasisImpl.h | 8 +- src/AutoConnectElementJson.h | 4 +- src/AutoConnectElementJsonImpl.h | 1 + 10 files changed, 289 insertions(+), 37 deletions(-) diff --git a/keywords.txt b/keywords.txt index 6560b48..6492e7a 100644 --- a/keywords.txt +++ b/keywords.txt @@ -23,12 +23,14 @@ begin KEYWORD2 del KEYWORD2 end KEYWORD2 entries KEYWORD2 +getElement KEYWORD2 handleClient KEYWORD2 handleRequest KEYWORD2 home KEYWORD2 host KEYWORD2 join KEYWORD2 load KEYWORD2 +loadElement KEYWORD2 menu KEYWORD2 name KEYWORD2 on KEYWORD2 @@ -47,6 +49,11 @@ AC_WEBSERVER_PARASITIC LITERAL1 AC_WEBSERVER_HOSTED LITERAL1 AC_SAVECREDENTIAL_NEVER LITERAL1 AC_SAVECREDENTIAL_AUTO LITERAL1 +AC_URIONBOOT_ROOT LITERAL1 +AC_URIONBOOT_HOME LITERAL1 +AC_EXIT_AHEAD LITERAL1 +AC_EXIT_LATER LITERAL1 +AC_EXIT_BOTH LITERAL1 ####################################### # PREPROCESSOR (KEYWORD3) diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index 54f123a..6a06ca3 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -424,6 +424,29 @@ void AutoConnect::handleRequest() { } } +/** + * Register the exit routine for AutoConnectAux. + * @param uri Specify the URI of the AutoConnectAux page that + * registers the exit routine. + * @param handler A handler function of the exit routine. + * @param order Specify an enumeration type of + * AutoConnectExitOrder_t for the call timing of the exit routine. + * @return true An exit routine registered. + * @return false AutoConnectAux page for the specified URI is not + * registered. + */ +bool AutoConnect::on(const char* uri, const AuxHandlerFunctionT handler, AutoConnectExitOrder_t order) { + AutoConnectAux* aux = _aux.get(); + while (aux) { + if (!strcmp(uri, aux->uri())) { + aux->on(handler, order); + return true; + } + aux = aux->_next.get(); + } + return false; +} + /** * Register the exit routine for the starting captive portal. * @param fn A function of the exit routine. diff --git a/src/AutoConnect.h b/src/AutoConnect.h index 742131c..a758c6b 100644 --- a/src/AutoConnect.h +++ b/src/AutoConnect.h @@ -165,14 +165,15 @@ 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); /** For AutoConnectAux described in JSON */ #ifdef AUTOCONNECT_USE_JSON - bool join(const char* aux); - bool join(const __FlashStringHelper* aux); - bool join(Stream& aux, size_t bufferSize = AUTOCONNECT_JSON_BUFFER_SIZE); + bool load(const char* aux); + bool load(const __FlashStringHelper* aux); + bool load(Stream& aux, size_t bufferSize = AUTOCONNECT_JSON_BUFFER_SIZE); bool _load(JsonVariant& aux); -#endif +#endif // !AUTOCONNECT_USE_JSON typedef std::function DetectExit_ft; void onDetect(DetectExit_ft fn); diff --git a/src/AutoConnectAux.cpp b/src/AutoConnectAux.cpp index 6d0b309..b70163e 100644 --- a/src/AutoConnectAux.cpp +++ b/src/AutoConnectAux.cpp @@ -88,6 +88,18 @@ void AutoConnectAux::add(AutoConnectElementVT addons) { add(addons[n]); } +/** +* Get already registered AutoConnectElement. +* @param name Element name +* @return A pointer to the registered AutoConnectElement. +*/ +AutoConnectElement* AutoConnectAux::getElement(const String name) { + for (std::size_t n = 0; n < _addonElm.size(); n++) + if (_addonElm[n].get().name == name) + return &(_addonElm[n].get()); + return nullptr; +} + /** * Releases the AutoConnectElements with the specified name from * the AutoConnectAux page. Releases all AutoConnectElements with @@ -153,7 +165,7 @@ const String AutoConnectAux::_insertElement(PageArgument& args) { if (_handler) { if (_order & AC_EXIT_AHEAD) { AC_DBG("CB %s\n", uri()); - body += _handler(args); + body += _handler(*this, args); } } @@ -165,7 +177,7 @@ const String AutoConnectAux::_insertElement(PageArgument& args) { if (_handler) { if (_order & AC_EXIT_LATER) { AC_DBG("CB %s\n", uri()); - body += _handler(args); + body += _handler(*this, args); } } @@ -232,7 +244,114 @@ const String AutoConnectAux::_injectMenu(PageArgument& args) { return menuItem; } -#ifdef AUTOCONNECT_USE_JSON +#ifndef AUTOCONNECT_USE_JSON + +/** + * Get AutoConnectButtonBasis element. + * @param name An element name. + * @return A reference of AutoConnectButton class. + */ +template<> +AutoConnectButtonBasis& AutoConnectAux::getElement(const String name) { + AutoConnectElement* elm = getElement(name); + if (elm) { + if (elm->typeOf() == AC_Button) + return *(reinterpret_cast(elm)); + } + return reinterpret_cast(_nullElement()); +} + +/** + * Get AutoConnectCheckboxBasis element. + * @param name An element name. + * @return A reference of AutoConnectCheckbox class. + */ +template<> +AutoConnectCheckboxBasis& AutoConnectAux::getElement(const String name) { + AutoConnectElement* elm = getElement(name); + if (elm) { + if (elm->typeOf() == AC_Checkbox) + return *(reinterpret_cast(elm)); + } + return reinterpret_cast(_nullElement()); +} + +/** + * Get AutoConnectInputBasis element. + * @param name An element name. + * @return A reference of AutoConnectInput class. + */ +template<> +AutoConnectInputBasis& AutoConnectAux::getElement(const String name) { + AutoConnectElement* elm = getElement(name); + if (elm) { + if (elm->typeOf() == AC_Input) + return *(reinterpret_cast(elm)); + } + return reinterpret_cast(_nullElement()); +} + +/** + * Get AutoConnectRadioBasis element. + * @param name An element name. + * @return A reference of AutoConnectRadio class. + */ +template<> +AutoConnectRadioBasis& AutoConnectAux::getElement(const String name) { + AutoConnectElement* elm = getElement(name); + if (elm) { + if (elm->typeOf() == AC_Radio) + return *(reinterpret_cast(elm)); + } + return reinterpret_cast(_nullElement()); +} + +/** + * Get AutoConnectSelectBasis element. + * @param name An element name. + * @return A reference of AutoConnectSelect class. + */ +template<> +AutoConnectSelectBasis& AutoConnectAux::getElement(const String name) { + AutoConnectElement* elm = getElement(name); + if (elm) { + if (elm->typeOf() == AC_Select) + return *(reinterpret_cast(elm)); + } + return reinterpret_cast(_nullElement()); +} + +/** + * Get AutoConnectSubmitBasis element. + * @param name An element name. + * @return A reference of AutoConnectSubmit class. + */ +template<> +AutoConnectSubmitBasis& AutoConnectAux::getElement(const String name) { + AutoConnectElement* elm = getElement(name); + if (elm) { + if (elm->typeOf() == AC_Submit) + return *(reinterpret_cast(elm)); + } + return reinterpret_cast(_nullElement()); +} + +/** + * Get AutoConnectTextBasis element. + * @param name An element name. + * @return A reference of AutoConnectText class. + */ +template<> +AutoConnectTextBasis& AutoConnectAux::getElement(const String name) { + AutoConnectElement* elm = getElement(name); + if (elm) { + if (elm->typeOf() == AC_Text) + return *(reinterpret_cast(elm)); + } + return reinterpret_cast(_nullElement()); +} + +#else /** * Static storage for JSON buffer size calculation. @@ -249,6 +368,111 @@ int8_t AutoConnectAux::_np; /**< Stack pointer for JSON object counter bool AutoConnectAux::_jbOpen; /**< JSON object paring status */ bool AutoConnectAux::_jbLiteral; /**< JSON object lexical status */ +/** + * Get AutoConnectButtonJson element. + * @param name An element name. + * @return A reference of AutoConnectButton class. + */ +template<> +AutoConnectButtonJson& AutoConnectAux::getElement(const String name) { + AutoConnectElement* elm = getElement(name); + if (elm) { + if (elm->typeOf() == AC_Button) + return *(reinterpret_cast(elm)); + } + return reinterpret_cast(_nullElement()); +} + +/** + * Get AutoConnectCheckboxJson element. + * @param name An element name. + * @return A reference of AutoConnectCheckbox class. + */ +template<> +AutoConnectCheckboxJson& AutoConnectAux::getElement(const String name) { + AutoConnectElement* elm = getElement(name); + if (elm) { + if (elm->typeOf() == AC_Checkbox) + return *(reinterpret_cast(elm)); + } + return reinterpret_cast(_nullElement()); +} + +/** + * Get AutoConnectInputJson element. + * @param name An element name. + * @return A reference of AutoConnectInput class. + */ +template<> +AutoConnectInputJson& AutoConnectAux::getElement(const String name) { + AutoConnectElement* elm = getElement(name); + if (elm) { + if (elm->typeOf() == AC_Input) + return *(reinterpret_cast(elm)); + } + return reinterpret_cast(_nullElement()); +} + +/** + * Get AutoConnectRadioJson element. + * @param name An element name. + * @return A reference of AutoConnectRadio class. + */ +template<> +AutoConnectRadioJson& AutoConnectAux::getElement(const String name) { + AutoConnectElement* elm = getElement(name); + if (elm) { + if (elm->typeOf() == AC_Radio) + return *(reinterpret_cast(elm)); + } + return reinterpret_cast(_nullElement()); +} + +/** + * Get AutoConnectSelectJson element. + * @param name An element name. + * @return A reference of AutoConnectSelect class. + */ +template<> +AutoConnectSelectJson& AutoConnectAux::getElement(const String name) { + AutoConnectElement* elm = getElement(name); + if (elm) { + if (elm->typeOf() == AC_Select) + return *(reinterpret_cast(elm)); + } + return reinterpret_cast(_nullElement()); +} + +/** + * Get AutoConnectSubmitJson element. + * @param name An element name. + * @return A reference of AutoConnectSubmit class. + */ +template<> +AutoConnectSubmitJson& AutoConnectAux::getElement(const String name) { + AutoConnectElement* elm = getElement(name); + if (elm) { + if (elm->typeOf() == AC_Submit) + return *(reinterpret_cast(elm)); + } + return reinterpret_cast(_nullElement()); +} + +/** + * Get AutoConnectTextJson element. + * @param name An element name. + * @return A reference of AutoConnectText class. + */ +template<> +AutoConnectTextJson& AutoConnectAux::getElement(const String name) { + AutoConnectElement* elm = getElement(name); + if (elm) { + if (elm->typeOf() == AC_Text) + return *(reinterpret_cast(elm)); + } + return reinterpret_cast(_nullElement()); +} + /** * Load AutoConnectAux page from JSON description stored in the sketch. * This function can load AutoConnectAux for multiple AUX pages written @@ -256,7 +480,7 @@ bool AutoConnectAux::_jbLiteral; /**< JSON object lexical status */ * @param aux JSON description to be load. * @return true Successfully loaded. */ -bool AutoConnect::join(const char* aux) { +bool AutoConnect::load(const char* aux) { const size_t bufferSize = AutoConnectAux::_calcJsonBufferSize(aux); DynamicJsonBuffer jsonBuffer(bufferSize); JsonVariant jv = jsonBuffer.parse(aux); @@ -270,7 +494,7 @@ bool AutoConnect::join(const char* aux) { * @param aux JSON description to be load. * @return true Successfully loaded. */ -bool AutoConnect::join(const __FlashStringHelper* aux) { +bool AutoConnect::load(const __FlashStringHelper* aux) { const size_t bufferSize = AutoConnectAux::_calcJsonBufferSize(aux); DynamicJsonBuffer jsonBuffer(bufferSize); JsonVariant jv = jsonBuffer.parse(aux); @@ -284,7 +508,7 @@ bool AutoConnect::join(const __FlashStringHelper* aux) { * @param aux Stream for read AutoConnectAux elements. * @return true Successfully loaded. */ -bool AutoConnect::join(Stream& aux, size_t bufferSize) { +bool AutoConnect::load(Stream& aux, size_t bufferSize) { DynamicJsonBuffer jsonBuffer(bufferSize); JsonVariant jv = jsonBuffer.parse(aux); return _load(jv); @@ -480,7 +704,7 @@ AutoConnectElement& AutoConnectAux::_loadElement(JsonObject& jb, const String na if (wc || name.equalsIgnoreCase(elmName)) { // The specified element is defined in the JSON stream. // Loads from JSON object. - auxElm = _getElement(elmName); + auxElm = getElement(elmName); // The element is not created yet, create new one. if (!auxElm) { if ((auxElm = _createElement(element))) { @@ -535,18 +759,6 @@ size_t AutoConnectAux::saveElement(Stream& out, const AutoConnectElement& elemen return 0; } -/** - * Get already registered AutoConnectElement. - * @param name Element name - * @return A pointer to the registered AutoConnectElement. - */ -AutoConnectElement* AutoConnectAux::_getElement(const String name) { - for (std::size_t n = 0; n < _addonElm.size(); n++) - if (_addonElm[n].get().name == name) - return &(_addonElm[n].get()); - return nullptr; -} - /** * Convert element type from type as String. * @param type An element type as String @@ -723,4 +935,4 @@ size_t AutoConnectAux::_resultJsonBufferSize() { } } -#endif +#endif // AUTOCONNECT_USE_JSON diff --git a/src/AutoConnectAux.h b/src/AutoConnectAux.h index 6132f50..d5715eb 100644 --- a/src/AutoConnectAux.h +++ b/src/AutoConnectAux.h @@ -16,20 +16,21 @@ #include #ifdef AUTOCONNECT_USE_JSON #include -#endif +#endif // !AUTOCONNECT_USE_JSON #include #include "AutoConnectElement.h" #define AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH 3 class AutoConnect; // Reference to avoid circular +class AutoConnectAux; // Reference to avoid circular // Manage placed AutoConnectElement with a vector typedef std::vector> AutoConnectElementVT; // A type of callback function when AutoConnectAux page requested. //typedef std::function AuxHandleFuncT; -typedef std::function AuxHandlerFunctionT; +typedef std::function AuxHandlerFunctionT; // A type for the order in which callback functions are called. typedef enum { @@ -53,6 +54,9 @@ class AutoConnectAux : public PageBuilder { ~AutoConnectAux(); 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 String name); /**< Get AutoConnect element */ + AutoConnectElement* getElement(const String name); /**< Get registered AutoConnectElement as specified name */ bool release(const char* name) { return release(String(name)); } /**< Release an AutoConnectElement */ bool release(const String name); /**< Release an AutoConnectElement */ void setTitle(const char* title) { _title = String(title); } /**< Set a title of the auxiliary page. */ @@ -67,7 +71,7 @@ class AutoConnectAux : public PageBuilder { 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 +#endif // !AUTOCONNECT_USE_JSON protected: void _concat(AutoConnectAux& aux); /**< Make up chain of AutoConnectAux */ @@ -81,10 +85,9 @@ class AutoConnectAux : public PageBuilder { 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 +#endif // !AUTOCONNECT_USE_JSON String _title; /**< A title of the page */ bool _menu; /**< Switch for menu displaying */ @@ -120,4 +123,4 @@ class AutoConnectAux : public PageBuilder { static bool _jbLiteral; /**< JSON object lexical status */ }; -#endif // _AUTOCONNECTAUX_H_ \ No newline at end of file +#endif // _AUTOCONNECTAUX_H_ diff --git a/src/AutoConnectElement.h b/src/AutoConnectElement.h index 82cc153..e123a9f 100644 --- a/src/AutoConnectElement.h +++ b/src/AutoConnectElement.h @@ -32,7 +32,7 @@ using AutoConnectRadio = AutoConnectRadioBasis; using AutoConnectSelect = AutoConnectSelectBasis; using AutoConnectSubmit = AutoConnectSubmitBasis; using AutoConnectText = AutoConnectTextBasis; -#endif +#endif // !AUTOCONNECT_USE_JSON /** * Support declare the AutoConnectElement variable with reducing the @@ -48,4 +48,4 @@ using AutoConnectText = AutoConnectTextBasis; #define ACSubmit(n, ...) AutoConnectSubmit n(#n, ##__VA_ARGS__) #define ACText(n, ...) AutoConnectText n(#n, ##__VA_ARGS__) -#endif // _AUTOCONNECTELEMENT_H_ \ No newline at end of file +#endif // _AUTOCONNECTELEMENT_H_ diff --git a/src/AutoConnectElementBasis.h b/src/AutoConnectElementBasis.h index 37d66ed..bd886ac 100644 --- a/src/AutoConnectElementBasis.h +++ b/src/AutoConnectElementBasis.h @@ -100,12 +100,13 @@ class AutoConnectCheckboxBasis : virtual public AutoConnectElementBasis { */ class AutoConnectInputBasis : virtual public AutoConnectElementBasis { public: - explicit AutoConnectInputBasis(const char* name = "", const char* value = "", const char* label = "") : AutoConnectElementBasis(name, value), label(String(label)) { + explicit AutoConnectInputBasis(const char* name = "", const char* value = "", const char* placeholder = "", const char* label = "") : AutoConnectElementBasis(name, value), placeholder(String(placeholder)), label(String(label)) { _type = AC_Input; } virtual ~AutoConnectInputBasis() {} const String toHTML(void) const; + String placeholder; String label; /**< A label for a subsequent input box */ }; diff --git a/src/AutoConnectElementBasisImpl.h b/src/AutoConnectElementBasisImpl.h index 1a3d171..4250fcd 100644 --- a/src/AutoConnectElementBasisImpl.h +++ b/src/AutoConnectElementBasisImpl.h @@ -54,10 +54,12 @@ const String AutoConnectInputBasis::toHTML(void) const { if (label.length()) html = String(FPSTR("")); - html += String(FPSTR("
")); + html += String(FPSTR(" value=\"")) + value + String("\""); + html += String(FPSTR(">
")); return html; } diff --git a/src/AutoConnectElementJson.h b/src/AutoConnectElementJson.h index 075c49c..4bce015 100644 --- a/src/AutoConnectElementJson.h +++ b/src/AutoConnectElementJson.h @@ -22,6 +22,7 @@ #define AUTOCONNECT_JSON_KEY_MENU "menu" #define AUTOCONNECT_JSON_KEY_NAME "name" #define AUTOCONNECT_JSON_KEY_OPTION "option" +#define AUTOCONNECT_JSON_KEY_PLACEHOLDER "placeholder" #define AUTOCONNECT_JSON_KEY_STYLE "style" #define AUTOCONNECT_JSON_KEY_TITLE "title" #define AUTOCONNECT_JSON_KEY_TYPE "type" @@ -107,9 +108,10 @@ class AutoConnectCheckboxJson : public AutoConnectElementJson, public AutoConnec */ class AutoConnectInputJson : public AutoConnectElementJson, public AutoConnectInputBasis { public: - explicit AutoConnectInputJson(const char* name = "", const char* value = "", const char* label = "") { + explicit AutoConnectInputJson(const char* name = "", const char* value = "", const char* placeholder = "", const char* label = "") { AutoConnectInputBasis::name = name; AutoConnectInputBasis::value = value; + AutoConnectInputBasis::placeholder = placeholder; AutoConnectInputBasis::label = label; } ~AutoConnectInputJson() {} diff --git a/src/AutoConnectElementJsonImpl.h b/src/AutoConnectElementJsonImpl.h index 4c15dd6..0116615 100644 --- a/src/AutoConnectElementJsonImpl.h +++ b/src/AutoConnectElementJsonImpl.h @@ -79,6 +79,7 @@ bool AutoConnectInputJson::loadElement(const JsonObject& json) { String type = json.get(F(AUTOCONNECT_JSON_KEY_TYPE)); if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACINPUT))) { _setElement(json); + placeholder = json.get(F(AUTOCONNECT_JSON_KEY_PLACEHOLDER)); label = json.get(F(AUTOCONNECT_JSON_KEY_LABEL)); return true; }