From 9c946b60bb3063e400aae752654a72fc31139e20 Mon Sep 17 00:00:00 2001 From: Jose Manuel Casillas Martin Date: Wed, 27 May 2020 10:11:04 -0500 Subject: [PATCH 1/3] Image element created --- src/AutoConnectElement.h | 3 +++ src/AutoConnectElementBasis.h | 31 ++++++++++++++++++++++ src/AutoConnectElementBasisImpl.h | 30 +++++++++++++++++++++ src/AutoConnectElementJson.h | 34 ++++++++++++++++++++++++ src/AutoConnectElementJsonImpl.h | 43 ++++++++++++++++++++++++++++++- 5 files changed, 140 insertions(+), 1 deletion(-) diff --git a/src/AutoConnectElement.h b/src/AutoConnectElement.h index e25043a..1661c4c 100644 --- a/src/AutoConnectElement.h +++ b/src/AutoConnectElement.h @@ -24,6 +24,7 @@ using AutoConnectSelect = AutoConnectSelectJson; using AutoConnectStyle = AutoConnectStyleJson; using AutoConnectSubmit = AutoConnectSubmitJson; using AutoConnectText = AutoConnectTextJson; +using AutoConnectImage = AutoConnectImageJson; #define AUTOCONNECT_JSON_BUFFER_SIZE 256 #else using AutoConnectElement = AutoConnectElementBasis; @@ -36,6 +37,7 @@ using AutoConnectSelect = AutoConnectSelectBasis; using AutoConnectStyle = AutoConnectStyleBasis; using AutoConnectSubmit = AutoConnectSubmitBasis; using AutoConnectText = AutoConnectTextBasis; +using AutoConnectImage = AutoConnectImageBasis; #endif // !AUTOCONNECT_USE_JSON /** @@ -53,5 +55,6 @@ using AutoConnectText = AutoConnectTextBasis; #define ACSubmit(n, ...) AutoConnectSubmit n(#n, ##__VA_ARGS__) #define ACStyle(n, ...) AutoConnectStyle n(#n, ##__VA_ARGS__) #define ACText(n, ...) AutoConnectText n(#n, ##__VA_ARGS__) +#define ACImage(n, ...) AutoConnectImage n(#n, ##__VA_ARGS__) #endif // _AUTOCONNECTELEMENT_H_ diff --git a/src/AutoConnectElementBasis.h b/src/AutoConnectElementBasis.h index cba00f6..0685ef4 100644 --- a/src/AutoConnectElementBasis.h +++ b/src/AutoConnectElementBasis.h @@ -38,6 +38,7 @@ typedef enum { AC_Style, AC_Submit, AC_Text, + AC_Image, AC_Unknown = -1 } ACElement_t; /**< AutoConnectElement class type */ @@ -300,6 +301,29 @@ class AutoConnectTextBasis : AC_AUTOCONNECTELEMENT_ON_VIRTUAL public AutoConnect String format; /**< C string that contains the text to be written */ }; +/** + * Image arrangement class, a part of AutoConnectAux element. + * @param + * @param name Image name string. + * @param value Image value as base64 string. + * @param style A string of style-code for decoration, optionally. + * @param format C string that contains the value to be formatted. + * An arrangement image would be placed with
contains. A string + * of style-codes are given for '
'. + */ + +class AutoConnectImageBasis : AC_AUTOCONNECTELEMENT_ON_VIRTUAL public AutoConnectElementBasis { + public: + explicit AutoConnectImageBasis(const char* name = "", const char* value = "", const char* style = "", const char* format = "", const ACPosterior_t post = AC_Tag_None) : AutoConnectElementBasis(name, value, post), style(String(style)), format(String(format)) { + _type = AC_Image; + } + virtual ~AutoConnectImageBasis() {} + const String toHTML(void) const override; + + String style; /**< CSS style modifier native code */ + String format; /**< C string that contains the text to be written */ +}; + #ifndef AUTOCONNECT_USE_JSON /** * Casts only a class derived from the AutoConnectElement class to the @@ -367,6 +391,13 @@ inline AutoConnectTextBasis& AutoConnectElementBasis::as(v AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf()); return *(reinterpret_cast(this)); } + +template<> +inline AutoConnectImageBasis& AutoConnectElementBasis::as(void) { + if (typeOf() != AC_Image) + AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf()); + return *(reinterpret_cast(this)); +} #endif #endif // _AUTOCONNECTELEMENTBASIS_H_ diff --git a/src/AutoConnectElementBasisImpl.h b/src/AutoConnectElementBasisImpl.h index ed245b8..9246519 100644 --- a/src/AutoConnectElementBasisImpl.h +++ b/src/AutoConnectElementBasisImpl.h @@ -354,4 +354,34 @@ const String AutoConnectTextBasis::toHTML(void) const { return html; } +/** + * Generate an HTML image element from a base64 string of the value member. If a style + * exists, it gives a style attribute. + * @return String an HTML string. + */ +const String AutoConnectImageBasis::toHTML(void) const { + String html = String(""); + + if (enable) { + html = String(F("
"); + if (format.length()) { + int buflen = (value.length() + format.length() + 16 + 1) & (~0xf); + char* buffer; + if ((buffer = (char*)malloc(buflen))) { + snprintf(buffer, buflen, format.c_str(), value.c_str()); + value_f = String(buffer); + free(buffer); + } + } + html += String(F("Image cannot be rendered
")); + html = AutoConnectElementBasis::posterior(html); + } + return html; +} + #endif // _AUTOCONNECTELEMENTBASISIMPL_H_ diff --git a/src/AutoConnectElementJson.h b/src/AutoConnectElementJson.h index 07724ae..0ba7c55 100644 --- a/src/AutoConnectElementJson.h +++ b/src/AutoConnectElementJson.h @@ -44,6 +44,7 @@ #define AUTOCONNECT_JSON_TYPE_ACSTYLE "ACStyle" #define AUTOCONNECT_JSON_TYPE_ACSUBMIT "ACSubmit" #define AUTOCONNECT_JSON_TYPE_ACTEXT "ACText" +#define AUTOCONNECT_JSON_TYPE_ACIMAGE "ACImage" #define AUTOCONNECT_JSON_VALUE_BEHIND "behind" #define AUTOCONNECT_JSON_VALUE_BR "br" #define AUTOCONNECT_JSON_VALUE_EXTERNAL "extern" @@ -303,6 +304,31 @@ class AutoConnectTextJson : public AutoConnectElementJson, public AutoConnectTex void serialize(JsonObject& json) override; }; +/** + * Image arrangement class, a part of AutoConnectAux element. + * @param + * @param name Image name string. + * @param value Image value string. + * @param style A string of style-code for decoration, optionally. + * An arrangement image would be placed with
contains. A string + * of style-codes are given for '
'. + */ +class AutoConnectImageJson : public AutoConnectElementJson, public AutoConnectImageBasis { + public: + explicit AutoConnectImageJson(const char* name = "", const char* value = "", const char* style = "", const char* format = "", const ACPosterior_t post = AC_Tag_None) { + AutoConnectImageBasis::name = String(name); + AutoConnectImageBasis::value = String(value); + AutoConnectImageBasis::style = String(style); + AutoConnectImageBasis::format = String(format); + AutoConnectImageBasis::post = post; + _defaultPost = AC_Tag_None; + } + ~AutoConnectImageJson() {} + size_t getObjectSize(void) const override; + bool loadMember(const JsonObject& json) override; + void serialize(JsonObject& json) override; +}; + /** * Casts only a class derived from the AutoConnectElement class to the * actual element class. @@ -379,4 +405,12 @@ inline AutoConnectTextJson& AutoConnectElementJson::as(void return *(reinterpret_cast(this)); } +template<> +inline AutoConnectImageJson& AutoConnectElementJson::as(void) { + if (typeOf() != AC_Image) { + AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf()); + } + return *(reinterpret_cast(this)); +} + #endif // _AUTOCONNECTELEMENTJSON_H_ diff --git a/src/AutoConnectElementJsonImpl.h b/src/AutoConnectElementJsonImpl.h index 9219ff5..11d3f15 100644 --- a/src/AutoConnectElementJsonImpl.h +++ b/src/AutoConnectElementJsonImpl.h @@ -200,7 +200,7 @@ void AutoConnectCheckboxJson::serialize(JsonObject& json) { size_t AutoConnectFileJson::getObjectSize(void) const { size_t size = AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(2); size += sizeof(AUTOCONNECT_JSON_KEY_LABEL) + label.length() + 1 + sizeof(AUTOCONNECT_JSON_KEY_STORE) + sizeof(AUTOCONNECT_JSON_VALUE_EXTERNAL); - return size; + return size; } /** @@ -526,4 +526,45 @@ void AutoConnectTextJson::serialize(JsonObject& json) { json[F(AUTOCONNECT_JSON_KEY_FORMAT)] = format; } +/** + * Returns JSON object size. + * @return An object size for JsonBuffer. + */ +size_t AutoConnectImageJson::getObjectSize(void) const { + size_t size = AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(2); + size += sizeof(AUTOCONNECT_JSON_KEY_STYLE) + style.length() + 1 + sizeof(AUTOCONNECT_JSON_KEY_FORMAT) + format.length() + 1; + return size; +} + +/** + * Load a image element attribute member from the JSON object. + * @param json JSON object with the definition of AutoConnectElement. + * @return true AutoConnectElement loaded + * @return false Type of AutoConnectElement is mismatched. + */ +bool AutoConnectImageJson::loadMember(const JsonObject& json) { + String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as(); + if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACIMAGE))) { + _setMember(json); + if (json.containsKey(F(AUTOCONNECT_JSON_KEY_STYLE))) + style = json[F(AUTOCONNECT_JSON_KEY_STYLE)].as(); + if (json.containsKey(F(AUTOCONNECT_JSON_KEY_FORMAT))) + format = json[F(AUTOCONNECT_JSON_KEY_FORMAT)].as(); + return true; + } + return false; +} + +/** + * Serialize AutoConnectImage to JSON. + * @param json JSON object to be serialized. + */ +void AutoConnectImageJson::serialize(JsonObject& json) { + _serialize(json); + json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACIMAGE)); + json[F(AUTOCONNECT_JSON_KEY_VALUE)] = value; + json[F(AUTOCONNECT_JSON_KEY_STYLE)] = style; + json[F(AUTOCONNECT_JSON_KEY_FORMAT)] = format; +} + #endif // _AUTOCONNECTELEMENTJSONIMPL_H_ From fc83f34155ab60009c0bda013767eada7f04e6a0 Mon Sep 17 00:00:00 2001 From: Jose Manuel Casillas Martin Date: Wed, 27 May 2020 10:21:44 -0500 Subject: [PATCH 2/3] Example image element (Equivalent to Hello World but with base64) --- .../HelloWorld_Image/HelloWorld_Image.ino | 83 +++++++++++++++++++ examples/HelloWorld_Image/data/style.json | 5 ++ 2 files changed, 88 insertions(+) create mode 100644 examples/HelloWorld_Image/HelloWorld_Image.ino create mode 100644 examples/HelloWorld_Image/data/style.json diff --git a/examples/HelloWorld_Image/HelloWorld_Image.ino b/examples/HelloWorld_Image/HelloWorld_Image.ino new file mode 100644 index 0000000..6ac648d --- /dev/null +++ b/examples/HelloWorld_Image/HelloWorld_Image.ino @@ -0,0 +1,83 @@ +/* + HelloWorld.ino, Example for the AutoConnect library. + Copyright (c) 2019, Hieromon Ikasamo + https://github.com/Hieromon/AutoConnect + + This software is released under the MIT License. + https://opensource.org/licenses/MIT +*/ +/* + To experience this example, upload the JSON file which is style.json + from the data folder. Its file contains the attributes for the Caption + of AutoConnectText. You can change the elements for your realization. +*/ + +#if defined(ARDUINO_ARCH_ESP8266) +#include +#include +typedef ESP8266WebServer WEBServer; +#elif defined(ARDUINO_ARCH_ESP32) +#include +#include +#include +typedef WebServer WEBServer; +#endif +#include +#include + +#define HELLO_URI "/hello" +#define PARAM_STYLE "/style.json" + +// Declare AutoConnectText with only a value. +// Qualify the Caption by reading style attributes from the SPIFFS style.json file. +ACImage(Caption, "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"); + +//AutoConnectAux for the custom Web page. +AutoConnectAux helloPage(HELLO_URI, "Hello", true, { Caption }); +AutoConnect portal; + +// JSON document loading buffer +String ElementJson; + +// Redirects from root to the hello page. +void onRoot() { + WEBServer& webServer = portal.host(); + webServer.sendHeader("Location", String("http://") + webServer.client().localIP().toString() + String(HELLO_URI)); + webServer.send(302, "text/plain", ""); + webServer.client().flush(); + webServer.client().stop(); +} + +// Load the attribute of the element to modify at runtime from external. +String onHello(AutoConnectAux& aux, PageArgument& args) { + aux.loadElement(ElementJson); + return String(); +} + +// Load the element from specified file in SPIFFS. +void loadParam(const char* fileName) { + SPIFFS.begin(); + File param = SPIFFS.open(fileName, "r"); + if (param) { + ElementJson = param.readString(); + param.close(); + } + SPIFFS.end(); +} + +void setup() { + delay(1000); + Serial.begin(115200); + + loadParam(PARAM_STYLE); // Pre-load the element from JSON. + helloPage.on(onHello); // Register the attribute overwrite handler. + portal.join(helloPage); // Join the hello page. + portal.begin(); + + WEBServer& webServer = portal.host(); + webServer.on("/", onRoot); // Register the root page redirector. +} + +void loop() { + portal.handleClient(); +} diff --git a/examples/HelloWorld_Image/data/style.json b/examples/HelloWorld_Image/data/style.json new file mode 100644 index 0000000..396deee --- /dev/null +++ b/examples/HelloWorld_Image/data/style.json @@ -0,0 +1,5 @@ +{ + "name" : "Caption", + "type" : "ACImage", + "style": "text-align:center;font-size:24px;font-family:'Impact','Futura',sans-serif;color:tomato;" +} From 1cb7a2b44311d0a2f91496316ba9334dc39b6bf2 Mon Sep 17 00:00:00 2001 From: Jose Manuel Casillas Martin Date: Wed, 27 May 2020 13:53:54 -0500 Subject: [PATCH 3/3] Add function in AutoConnect Config to allow use logo image in header encoded as base64 string --- examples/HelloWorld_Image/HelloWorld_Image.ino | 7 +++++++ src/AutoConnect.h | 11 ++++++++--- src/AutoConnectPage.cpp | 16 ++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/examples/HelloWorld_Image/HelloWorld_Image.ino b/examples/HelloWorld_Image/HelloWorld_Image.ino index 6ac648d..8fde04e 100644 --- a/examples/HelloWorld_Image/HelloWorld_Image.ino +++ b/examples/HelloWorld_Image/HelloWorld_Image.ino @@ -35,6 +35,7 @@ ACImage(Caption, "iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAAgVBMVEX///8AAA //AutoConnectAux for the custom Web page. AutoConnectAux helloPage(HELLO_URI, "Hello", true, { Caption }); AutoConnect portal; +AutoConnectConfig Config; // JSON document loading buffer String ElementJson; @@ -65,11 +66,17 @@ void loadParam(const char* fileName) { SPIFFS.end(); } +void setup_AutoConnect(AutoConnect &Portal, AutoConnectConfig &Config){ + Config.logo = "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"; + Portal.config(Config); // Configure AutoConnect +} + void setup() { delay(1000); Serial.begin(115200); loadParam(PARAM_STYLE); // Pre-load the element from JSON. + setup_AutoConnect(portal, Config); // Comment this line if you do not want to use the logo in header helloPage.on(onHello); // Register the attribute overwrite handler. portal.join(helloPage); // Join the hello page. portal.begin(); diff --git a/src/AutoConnect.h b/src/AutoConnect.h index a483087..f4b091f 100644 --- a/src/AutoConnect.h +++ b/src/AutoConnect.h @@ -118,7 +118,8 @@ class AutoConnectConfig { staGateway(0U), staNetmask(0U), dns1(0U), - dns2(0U) {} + dns2(0U), + logo(String("")) {} /** * Configure by SSID for the captive portal access point and password. */ @@ -154,7 +155,8 @@ class AutoConnectConfig { staGateway(0U), staNetmask(0U), dns1(0U), - dns2(0U) {} + dns2(0U), + logo(String("")) {} ~AutoConnectConfig() {} @@ -191,6 +193,7 @@ class AutoConnectConfig { staNetmask = o.staNetmask; dns1 = o.dns1; dns2 = o.dns2; + logo = o.logo; return *this; } @@ -205,7 +208,7 @@ class AutoConnectConfig { int16_t minRSSI; /**< Lowest WiFi signal strength (RSSI) that can be connected. */ AC_SAVECREDENTIAL_t autoSave; /**< Auto save credential */ AC_ONBOOTURI_t bootUri; /**< An uri invoking after reset */ - AC_PRINCIPLE_t principle; /**< WiFi connection principle */ + AC_PRINCIPLE_t principle; /**< WiFi connection principle */ uint16_t boundaryOffset; /**< The save storage offset of EEPROM */ int uptime; /**< Length of start up time */ bool autoRise; /**< Automatic starting the captive portal */ @@ -227,6 +230,7 @@ class AutoConnectConfig { IPAddress staNetmask; /**< Station subnet mask */ IPAddress dns1; /**< Primary DNS server */ IPAddress dns2; /**< Secondary DNS server */ + String logo; /** String in base64 to add logo **/ }; typedef std::vector> AutoConnectAuxVT; @@ -306,6 +310,7 @@ class AutoConnect { /** Utilities */ String _attachMenuItem(const AC_MENUITEM_t item); + String _attachLogoItem(); static uint32_t _getChipId(void); static uint32_t _getFlashChipRealSize(void); static String _toMACAddressString(const uint8_t mac[]); diff --git a/src/AutoConnectPage.cpp b/src/AutoConnectPage.cpp index b3cd07c..40f039a 100644 --- a/src/AutoConnectPage.cpp +++ b/src/AutoConnectPage.cpp @@ -523,6 +523,7 @@ const char AutoConnect::_ELM_MENU_PRE[] PROGMEM = { "" "
" "
    " + "MENU_LOGO" "
  • " "MENU_TITLE" "" @@ -953,6 +954,8 @@ String AutoConnect::_token_MENU_PRE(PageArgument& args) { _attachMenuItem(AC_MENUITEM_OPENSSIDS) + _attachMenuItem(AC_MENUITEM_DISCONNECT) + _attachMenuItem(AC_MENUITEM_RESET); + String logoItem = _attachLogoItem(); + currentMenu.replace(String(F("MENU_LOGO")), logoItem); currentMenu.replace(String(F("MENU_LIST")), menuItem); currentMenu.replace(String(F("BOOT_URI")), _getBootUri()); currentMenu.replace(String(F("MENU_TITLE")), _menuTitle); @@ -1391,6 +1394,19 @@ String AutoConnect::_attachMenuItem(const AC_MENUITEM_t item) { return String(li); } +/** + * Generate AutoConnect logo item configured by AutoConnectConfig::attachMenu. + * @param item An enumerated value for the generating item configured in AutoConnectConfig. + * @return HTML string of a li tag with the menu item. + */ + String AutoConnect::_attachLogoItem() { + if (_apConfig.logo==String("")){ + return String(""); + } + String resp = "
  • \"Logo
  • "; + return resp; + } + /** * This function dynamically build up the response pages that conform to * the requested URI. A PageBuilder instance is stored in _responsePage