Supports AutoConnectAux

pull/41/head
Hieromon Ikasamo 6 years ago
parent ad07e1b448
commit d281bb33e7
  1. 10
      README.md
  2. 2
      src/AutoConnect.cpp
  3. 79
      src/AutoConnect.h
  4. 375
      src/AutoConnectAux.cpp
  5. 168
      src/AutoConnectAux.h
  6. 103
      src/AutoConnectDefs.h
  7. 49
      src/AutoConnectElement.h
  8. 170
      src/AutoConnectElementBasis.h
  9. 107
      src/AutoConnectElementBasisImpl.h
  10. 173
      src/AutoConnectElementJson.h
  11. 140
      src/AutoConnectElementJsonImpl.h

@ -32,10 +32,14 @@ AutoConnect can be embedded easily into your sketch, just "**begin**" and "**han
The sketches which provide the web page using ESP8266WebServer/WebServer there is, AutoConnect will not disturb it. AutoConnect can use an already instantiated ESP8266WebServer object(ESP8266) or WebServer object(ESP32), or itself can assign it. The sketches which provide the web page using ESP8266WebServer/WebServer there is, AutoConnect will not disturb it. AutoConnect can use an already instantiated ESP8266WebServer object(ESP8266) or WebServer object(ESP32), or itself can assign it.
### Adding the user-owned web screen can easily ### Adding the user-owned web screen can easily <sup><sub>ENHANCED w/ v0.9.7</sub></sup>
You can easily add your own web screen with sketch. It can be called from the AutoConnect menu and parameters can be passed. You can easily add your own web screen with sketch. It can be called from the AutoConnect menu and parameters can be passed.
### Adding the extended menu with a simple code can easily <sup><sub>ENHANCED w/ v0.9.7</sub></sup>
Just loading the elements of portal screen extension written with JSON allows you to incorporate your owned portal screen into the AutoConnect menu.
## Supported hardware ## Supported hardware
Apply the [Arduino core](https://github.com/esp8266/Arduino) of the ESP8266 Community. Apply the [Arduino core](https://github.com/esp8266/Arduino) of the ESP8266 Community.
@ -86,8 +90,10 @@ Full documentation is available on https://Hieromon.github.io/AutoConnect, some
## Change log ## Change log
### [0.9.7] Nov. 11, 2018 ### [0.9.7] Nov. 11, 2018
- Supports addition of AutoConnect menu with user sketch by AutoConnectAux implementation. - 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. - 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```.
### [0.9.6] Sept. 27, 2018 ### [0.9.6] Sept. 27, 2018
- Improvement of RSSI detection for saved SSIDs. - Improvement of RSSI detection for saved SSIDs.

@ -700,4 +700,4 @@ void AutoConnect::_disconnectWiFi(bool wifiOff) {
#endif #endif
while (WiFi.status() == WL_CONNECTED) while (WiFi.status() == WL_CONNECTED)
delay(100); delay(100);
} }

@ -28,85 +28,11 @@ using WebServerClass = WebServer;
#endif #endif
#include <EEPROM.h> #include <EEPROM.h>
#include <PageBuilder.h> #include <PageBuilder.h>
#include "AutoConnectDefs.h"
#include "AutoConnectPage.h" #include "AutoConnectPage.h"
#include "AutoConnectCredential.h" #include "AutoConnectCredential.h"
#include "AutoConnectAux.h" #include "AutoConnectAux.h"
// Uncomment the following AC_DEBUG to enable debug output.
#define AC_DEBUG
// Debug output destination can be defined externally with AC_DEBUG_PORT
#ifndef AC_DEBUG_PORT
#define AC_DEBUG_PORT Serial
#endif
#ifdef AC_DEBUG
#define AC_DBG(...) do {AC_DEBUG_PORT.print("[AC] "); AC_DEBUG_PORT.printf( __VA_ARGS__ );} while (0)
#else
#define AC_DBG(...)
#endif
#ifndef AUTOCONNECT_APID
#if defined(ARDUINO_ARCH_ESP8266)
#define AUTOCONNECT_APID "esp8266ap"
#elif defined(ARDUINO_ARCH_ESP32)
#define AUTOCONNECT_APID "esp32ap"
#endif
#endif
#ifndef AUTOCONNECT_PSK
#define AUTOCONNECT_PSK "12345678"
#endif
#ifndef AUTOCONNECT_AP_IP
#define AUTOCONNECT_AP_IP 0x01F4A8C0 //*< 192.168.244.1 */
#endif // !AUTOCONNECT_AP_IP
#ifndef AUTOCONNECT_AP_GW
#define AUTOCONNECT_AP_GW 0x01F4A8C0 //*< 192.168.244.1 */
#endif // !AUTOCONNECT_AP_GW
#ifndef AUTOCONNECT_AP_NM
#define AUTOCONNECT_AP_NM 0x00FFFFFF //*< 255.255.255.0 */
#endif // !AUTOCONNECT_AP_NM
#ifndef AUTOCONNECT_URI
#define AUTOCONNECT_URI "/_ac"
#endif
#ifndef AUTOCONNECT_HOMEURI
#define AUTOCONNECT_HOMEURI "/"
#endif
#ifndef AUTOCONNECT_MENU_TITLE
#define AUTOCONNECT_MENU_TITLE "AutoConnect"
#endif
#define AUTOCONNECT_MENU_TITLE_CONNETED "Connected"
#define AUTOCONNECT_URI_CONFIG AUTOCONNECT_URI "/config"
#define AUTOCONNECT_URI_CONNECT AUTOCONNECT_URI "/connect"
#define AUTOCONNECT_URI_RESULT AUTOCONNECT_URI "/result"
#define AUTOCONNECT_URI_OPEN AUTOCONNECT_URI "/open"
#define AUTOCONNECT_URI_DISCON AUTOCONNECT_URI "/disc"
#define AUTOCONNECT_URI_RESET AUTOCONNECT_URI "/reset"
#define AUTOCONNECT_URI_SUCCESS AUTOCONNECT_URI "/success"
#define AUTOCONNECT_URI_FAIL AUTOCONNECT_URI "/fail"
#ifndef AUTOCONNECT_TIMEOUT
#define AUTOCONNECT_TIMEOUT 30000
#endif
#ifndef AUTOCONNECT_STARTUPTIME
#define AUTOCONNECT_STARTUPTIME 10
#endif
#ifndef AUTOCONNECT_HTTPPORT
#define AUTOCONNECT_HTTPPORT 80
#endif
#ifndef AUTOCONNECT_DNSPORT
#define AUTOCONNECT_DNSPORT 53
#endif
#define AC_UNUSED(expr) do { (void)(expr); } while (0)
/**< A type to save established credential at WiFi.begin automatically. */ /**< A type to save established credential at WiFi.begin automatically. */
typedef enum AC_SAVECREDENTIAL { typedef enum AC_SAVECREDENTIAL {
AC_SAVECREDENTIAL_NEVER, AC_SAVECREDENTIAL_NEVER,
@ -286,7 +212,7 @@ class AutoConnect {
/** Extended pages made up with AutoConnectAux */ /** Extended pages made up with AutoConnectAux */
std::unique_ptr<AutoConnectAux> _aux; std::unique_ptr<AutoConnectAux> _aux;
/** Saved configurations */ /** Saved configurations */
AutoConnectConfig _apConfig; AutoConnectConfig _apConfig;
struct station_config _credential; struct station_config _credential;
@ -363,6 +289,7 @@ class AutoConnect {
#elif defined(ARDUINO_ARCH_ESP32) #elif defined(ARDUINO_ARCH_ESP32)
friend class WebServer; friend class WebServer;
#endif #endif
friend class AutoConnectAux; friend class AutoConnectAux;
}; };

@ -1,18 +1,22 @@
/** /**
* Implementation of AutoConnectAux class and subordinated AutoConnectElement class. * Implementation of AutoConnectAux class.
* @file AutoConnectAux.cpp * @file AutoConnectAuxBasisImpl.h
* @author hieromon@gmail.com * @author hieromon@gmail.com
* @version 0.9.7 * @version 0.9.7
* @date 2018-11-17 * @date 2018-11-17
* @copyright MIT license. * @copyright MIT license.
*/ */
#include "AutoConnect.h" #include "AutoConnect.h"
#include "AutoConnectAux.h" #include "AutoConnectAux.h"
#include "AutoConnectElement.h"
#include "AutoConnectElementBasisImpl.h"
#ifdef AUTOCONNECT_USE_JSON
#include "AutoConnectElementJsonImpl.h"
#endif
/** /**
* Template for auxiliary page composed with AutoConnectAux of user sketch. * Template for auxiliary page composed with AutoConnectAux of user sketch.
*
* The structure of the auxiliary page depends on this template for * The structure of the auxiliary page depends on this template for
* the purpose to be incorporated into the AutoConnect Menu. * the purpose to be incorporated into the AutoConnect Menu.
* The page element implemented by AutoConnectElement is placed at the * The page element implemented by AutoConnectElement is placed at the
@ -57,100 +61,8 @@ const char AutoConnectAux::_PAGE_AUX[] PROGMEM = {
}; };
/** /**
* Generate an HTML <button> element. The onclick behavior depends on * Destructs container of AutoConnectElement and release a unique
* the code held in <EFBFBD>faction<EFBFBD>f member. * pointer of AutoConnect instance.
* @return String an HTML string.
*/
const String AutoConnectButton::toHTML(void) const {
return String(FPSTR("<button type=\"button\" name=\"")) + name + String(FPSTR("\" value=\"")) + value + String(FPSTR("\" onclick=\"")) + action + String("\">") + value + String(FPSTR("</button>"));
}
/**
* Generate an HTML <input type=checkbox> element.
* A "value" is associated with the input tag and sent by the form
* action as the value of "name". If the label member is contained, it
* is placed to the right side of the checkbox to be labeled.
* If the label member is empty, only the checkbox is placed.
* @return String an HTML string.
*/
const String AutoConnectCheckbox::toHTML(void) const {
String html;
html = String(FPSTR("<input type=\"checkbox\" name=\"")) + name + String(FPSTR("\" value=\"")) + value + String("\"");
if (checked)
html += String(FPSTR(" checked"));
if (label.length())
html += String(" id=\"") + name + String("\"><label for=\"") + name + String("\">") + label + String(FPSTR("</label"));
html += String(FPSTR("><br>"));
return html;
}
/**
* Generate an HTML <input type=text> element.
* If the value member is contained, it is reflected in the placeholder
* attribute. The entered value can be obtained using the user callback
* function registered by AutoConnectAux::on after the form is sent in
* combination with AutoConnectSubmit.
* @return String an HTML string.
*/
const String AutoConnectInput::toHTML(void) const {
String html = String();
if (label.length())
html = String(FPSTR("<label for=\"")) + name + String("\">") + label + String(FPSTR("</label>"));
html += String(FPSTR("<input type=\"text\" id=\"")) + name + String(FPSTR("\" name=\"")) + name;
if (value.length())
html += String(FPSTR("\" placeholder=\"")) + value;
html += String(FPSTR("\"><br>"));
return html;
}
/**
* Generate an HTML <select> element with an <option> element.
* The attribute value of the <option> element is given to the
* AutoConnectSelect class as a string array, which would be stored
* in the 'options' member. If a label member is contained, the <label>
* element would be generated the preface of <select>.
* @return String an HTML string.
*/
const String AutoConnectSelect::toHTML(void) const {
String html = String();
if (label.length())
html = String(FPSTR("<label>")) + label + String(FPSTR("</label>"));
html += String(FPSTR("<select name=\"")) + name + String("\">");
std::size_t n = _options.size();
if (n) {
for (std::size_t n = 0; n < _options.size(); n++)
html += String(FPSTR("<option value=\"")) + _options[n] + "\">" + _options[n] + String(FPSTR("</option>"));
}
html += String(FPSTR("</select><br>"));
return html;
}
/**
* Generate an HTML <input type=button> element. This element is used
* for form submission. An 'onclick' attribute calls fixed JavaScript
* code as 'sa' named and it's included in the template.
* @return String an HTML string.
*/
const String AutoConnectSubmit::toHTML(void) const {
return String(FPSTR("<input type=\"button\" name=\"")) + name + String(FPSTR("\" value=\"")) + value + String(FPSTR("\" onclick=\"_sa('")) + uri + String("')\">");
}
/**
* Generate an HTML text element from a string of the value member. If a style
* exists, it gives a style attribute.
* @return String an HTML string.
*/
const String AutoConnectText::toHTML(void) const {
return String(FPSTR("<div style=\"")) + style + String("\">") + value + String(FPSTR("</div>"));
}
/**
* Destructs container of AutoConnectElement and release a unique
* pointer of AutoConnect instance.
*/ */
AutoConnectAux::~AutoConnectAux() { AutoConnectAux::~AutoConnectAux() {
_addonElm.clear(); _addonElm.clear();
@ -160,17 +72,17 @@ AutoConnectAux::~AutoConnectAux() {
} }
/** /**
* Add an AutoConnectElement * Add an AutoConnectElement
* @param addon A reference of AutoConnectElement. * @param addon A reference of AutoConnectElement.
*/ */
void AutoConnectAux::add(AutoConnectElement& addon) { void AutoConnectAux::add(AutoConnectElement& addon) {
_addonElm.push_back(addon); _addonElm.push_back(addon);
AC_DBG("%s placed on %s\n", addon.name.c_str(), uri()); AC_DBG("%s placed on %s\n", addon.name.length() ? addon.name.c_str() : "*nonamed*", uri());
} }
/** /**
* Add an AutoConnectElement vector container to the AutoConnectAux page. * Add an AutoConnectElement vector container to the AutoConnectAux page.
* @param addons AutoConnectElementVT collection. * @param addons AutoConnectElementVT collection.
*/ */
void AutoConnectAux::add(AutoConnectElementVT addons) { void AutoConnectAux::add(AutoConnectElementVT addons) {
for (std::size_t n = 0; n < addons.size(); n++) for (std::size_t n = 0; n < addons.size(); n++)
@ -178,12 +90,12 @@ void AutoConnectAux::add(AutoConnectElementVT addons) {
} }
/** /**
* Releases the AutoConnectElements with the specified name from * Releases the AutoConnectElements with the specified name from
* the AutoConnectAux page. Releases all AutoConnectElements with * the AutoConnectAux page. Releases all AutoConnectElements with
* the same name in AutoConnectAux. * the same name in AutoConnectAux.
* @param name * @param name
* @return true The specified AutoConnectElements have been released. * @return true The specified AutoConnectElements have been released.
* @return false The specified AutoConnectElement not found in AutoConnectAux. * @return false The specified AutoConnectElement not found in AutoConnectAux.
*/ */
bool AutoConnectAux::release(const String name) { bool AutoConnectAux::release(const String name) {
bool rc = false; bool rc = false;
@ -199,13 +111,13 @@ bool AutoConnectAux::release(const String name) {
} }
/** /**
* Concatenates subsequent AutoConnectAux pages starting from oneself * Concatenates subsequent AutoConnectAux pages starting from oneself
* to the chain list. * to the chain list.
* AutoConnectAux is collected in the chain list and each object is * AutoConnectAux is collected in the chain list and each object is
* chained by the "_next". AutoConnect follows the "_next" to manage * chained by the "_next". AutoConnect follows the "_next" to manage
* auxiliary pages. The _concat function concatenates subsequent * auxiliary pages. The _concat function concatenates subsequent
* AutoConnectAuxs. * AutoConnectAuxs.
* @param aux A reference of AutoConnectAux. * @param aux A reference of AutoConnectAux.
*/ */
void AutoConnectAux::_concat(AutoConnectAux& aux) { void AutoConnectAux::_concat(AutoConnectAux& aux) {
if (_next) if (_next)
@ -215,11 +127,11 @@ void AutoConnectAux::_concat(AutoConnectAux& aux) {
} }
/** /**
* Register the AutoConnect that owns itself. * Register the AutoConnect that owns itself.
* AutoConenctAux needs to access the AutoConnect member. Also * AutoConenctAux needs to access the AutoConnect member. Also
* AutoConnectAux is cataloged by chain list. The _join function * AutoConnectAux is cataloged by chain list. The _join function
* registers AutoConnect in the following AutoConnectAux chain list. * registers AutoConnect in the following AutoConnectAux chain list.
* @param ac A reference of AutoConnect. * @param ac A reference of AutoConnect.
*/ */
void AutoConnectAux::_join(AutoConnect& ac) { void AutoConnectAux::_join(AutoConnect& ac) {
_ac.reset(&ac); _ac.reset(&ac);
@ -230,10 +142,10 @@ void AutoConnectAux::_join(AutoConnect& ac) {
} }
/** /**
* Insert the token handler of PageBuilder. This handler inserts HTML * Insert the token handler of PageBuilder. This handler inserts HTML
* elements generated by the whole AutoConnectElements to the auxiliary page. * elements generated by the whole AutoConnectElements to the auxiliary page.
* @param args A reference of PageArgument but unused. * @param args A reference of PageArgument but unused.
* @return HTML string that should be inserted. * @return HTML string that should be inserted.
*/ */
const String AutoConnectAux::_insertElement(PageArgument& args) { const String AutoConnectAux::_insertElement(PageArgument& args) {
AC_UNUSED(args); AC_UNUSED(args);
@ -260,13 +172,13 @@ const String AutoConnectAux::_insertElement(PageArgument& args) {
} }
/** /**
* Generate an auxiliary page assembled with the AutoConnectElement. * Generate an auxiliary page assembled with the AutoConnectElement.
* This function is the core procedure of AutoConnectAux, and uses * This function is the core procedure of AutoConnectAux, and uses
* PageBuilder from the _PAGE_AUX template to build an AutoConnect * PageBuilder from the _PAGE_AUX template to build an AutoConnect
* menu and insert HTML elements. A template of an auxiliary page is * menu and insert HTML elements. A template of an auxiliary page is
* fixed and its structure inherits from the AutoConnect. * fixed and its structure inherits from the AutoConnect.
* @param uri An uri of the auxiliary page. * @param uri An uri of the auxiliary page.
* @return A PageElement of auxiliary page. * @return A PageElement of auxiliary page.
*/ */
PageElement* AutoConnectAux::_setupPage(String uri) { PageElement* AutoConnectAux::_setupPage(String uri) {
PageElement* elm = nullptr; PageElement* elm = nullptr;
@ -302,12 +214,12 @@ PageElement* AutoConnectAux::_setupPage(String uri) {
} }
/** /**
* Inject the <li> element depending on the "luxbar-item" attribute * Inject the <li> element depending on the "luxbar-item" attribute
* for implementing the AutoConnect menu. * for implementing the AutoConnect menu.
* @param args A reference of PageArgument but it's only used for * @param args A reference of PageArgument but it's only used for
* interface alignment and is not actually used. * interface alignment and is not actually used.
* @return A concatenated string of <li> elements for the menu item of * @return A concatenated string of <li> elements for the menu item of
* AutoConnect. * AutoConnect.
*/ */
const String AutoConnectAux::_injectMenu(PageArgument& args) { const String AutoConnectAux::_injectMenu(PageArgument& args) {
String menuItem; String menuItem;
@ -318,3 +230,184 @@ const String AutoConnectAux::_injectMenu(PageArgument& args) {
menuItem += _next->_injectMenu(args); menuItem += _next->_injectMenu(args);
return menuItem; return menuItem;
} }
#ifdef AUTOCONNECT_USE_JSON
/**
* Create an instance from the AutoConnectElement of the JSON object.
* @param json A reference of JSON
* @return A pointer of created AutoConnectElement instance.
*/
AutoConnectElement* AutoConnectAux::_createElement(const JsonObject& json) {
AutoConnectElement* elm = nullptr;
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
switch (_asElementType(type)) {
case AC_Element:
elm = new AutoConnectElement;
break;
case AC_Button: {
AutoConnectButton* cert_elm = new AutoConnectButton;
return reinterpret_cast<AutoConnectElement*>(cert_elm);
}
case AC_Checkbox: {
AutoConnectCheckbox* cert_elm = new AutoConnectCheckbox;
return reinterpret_cast<AutoConnectElement*>(cert_elm);
}
case AC_Input: {
AutoConnectInput* cert_elm = new AutoConnectInput;
return reinterpret_cast<AutoConnectElement*>(cert_elm);
}
case AC_Select: {
AutoConnectSelect* cert_elm = new AutoConnectSelect;
return reinterpret_cast<AutoConnectElement*>(cert_elm);
}
case AC_Submit: {
AutoConnectSubmit* cert_elm = new AutoConnectSubmit;
return reinterpret_cast<AutoConnectElement*>(cert_elm);
}
case AC_Text: {
AutoConnectText* cert_elm = new AutoConnectText;
return reinterpret_cast<AutoConnectElement*>(cert_elm);
}
}
return elm;
}
/**
* Load element specified by the name parameter from the stream
* described by JSON. Usually, the Stream is specified a storm file of
* SD or SPIFFS. The Stream must be opened before invoking the function.
* @param in Reference of the Stream which contains the parameter
* file described by JSON.
* @param name The element name to be loaded.
* @return A reference of loaded AutoConnectElement instance.
*/
AutoConnectElement& AutoConnectAux::loadElement(Stream& in, const String name) {
DynamicJsonBuffer jsonBuffer;
JsonObject& jb = jsonBuffer.parseObject(in);
if (!jb.success())
return _nullElement();
JsonArray& aux = jb[AUTOCONNECT_JSON_KEY_AUX];
if (!aux.success())
return _nullElement();
for (JsonObject& page : aux) {
if (page["uri"].as<String>() == String(uri())) {
JsonArray& element = page[AUTOCONNECT_JSON_KEY_ELEMENT];
for (JsonObject& elm : element) {
if (name.equalsIgnoreCase(elm.get<String>(F(AUTOCONNECT_JSON_KEY_NAME)))) {
// The specified element is defined in the JSON stream.
// Loads from JSON object.
const String inType = elm[AUTOCONNECT_JSON_KEY_TYPE].as<String>();
AutoConnectElement* auxElm = _getElement(name);
// The element is not created yet, create new one.
if (!auxElm) {
if ((auxElm = _createElement(elm))) {
AC_DBG("%s<%d> of %s created\n", name.c_str(), (int)(auxElm->typeOf()), uri());
add(*auxElm); // Insert to AutoConnect
}
else {
AC_DBG("%s unknown element type\n", name.c_str());
return _nullElement();
}
}
if (auxElm->loadElement(elm)) {
AC_DBG("%s<%d> of %s loaded\n", name.c_str(), (int)auxElm->typeOf(), uri());
}
else {
// Element type mismatch
AC_DBG("Type of %s element mismatched\n", name.c_str());
return _nullElement();
}
}
}
}
}
return _nullElement();
}
/**
* Serialize the 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
*/
size_t AutoConnectAux::saveElement(Stream& out, const AutoConnectElement& element) {
DynamicJsonBuffer jsonBuffer;
JsonObject& jb = jsonBuffer.parseObject(out);
if (!jb.success())
return 0;
JsonArray& aux = jb[AUTOCONNECT_JSON_KEY_AUX];
if (!aux.success())
return 0;
for (JsonObject& page : aux) {
if (page["uri"].as<String>() == String(uri())) {
JsonArray& element_j = page[AUTOCONNECT_JSON_KEY_ELEMENT];
for (JsonObject& elm : element_j) {
if (elm[AUTOCONNECT_JSON_KEY_NAME].as<String>() == element.name) {
elm.set(F(AUTOCONNECT_JSON_KEY_VALUE), element.value);
return jb.prettyPrintTo(out);
}
}
}
}
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
* @return A type of ACElement_t
*/
const ACElement_t AutoConnectAux::_asElementType(const String type) {
typedef struct {
const char* tName;
ACElement_t tEnum;
} ACElementType_t;
static const ACElementType_t types[] PROGMEM = {
{ AUTOCONNECT_JSON_TYPE_ACBUTTON, AC_Button },
{ AUTOCONNECT_JSON_TYPE_ACCHECKBOX, AC_Checkbox },
{ AUTOCONNECT_JSON_TYPE_ACELEMENT, AC_Element },
{ AUTOCONNECT_JSON_TYPE_ACINPUT, AC_Input },
{ AUTOCONNECT_JSON_TYPE_ACSELECT, AC_Select },
{ AUTOCONNECT_JSON_TYPE_ACSUBMIT, AC_Submit },
{ AUTOCONNECT_JSON_TYPE_ACTEXT, AC_Text }
};
ACElement_t t = AC_Unknown;
for (size_t n = 0; n < (sizeof(types) / sizeof(ACElementType_t)); n++) {
if (type.equalsIgnoreCase(String(types[n].tName)))
return types[n].tEnum;
}
return t;
}
/**
* Returns a null element as static storage.
* This static element is referred by invalid JSON data.
* @return A reference of a static element defined by name as null.
*/
AutoConnectElement& AutoConnectAux::_nullElement() {
static AutoConnectElement nullElement("","");
return nullElement;
}
#endif

@ -1,10 +1,10 @@
/** /**
* Declaration of AutoConnectAux class and subordinated AutoConnectElement class. * Declaration of AutoConnectAux basic class.
* @file AutoConnectAux.h * @file AutoConnectAuxBasis.h
* @author hieromon@gmail.com * @author hieromon@gmail.com
* @version 0.9.7 * @version 0.9.7
* @date 2018-11-17 * @date 2018-11-17
* @copyright MIT license. * @copyright MIT license.
*/ */
#ifndef _AUTOCONNECTAUX_H_ #ifndef _AUTOCONNECTAUX_H_
@ -14,144 +14,10 @@
#include <memory> #include <memory>
#include <functional> #include <functional>
#include <PageBuilder.h> #include <PageBuilder.h>
#include "AutoConnectDefs.h"
#include "AutoConnectElement.h"
class AutoConnect; // Reference to avoid circular class AutoConnect;
/**
* AutoConnectAux element base.
* Placed a labeled button that can be added by user sketch.
* @param name Button name string.
* @param value Button value string.
*/
class AutoConnectElement {
public:
explicit AutoConnectElement(const char* name, const char* value) : name(String(name)), value(String(value)) {}
virtual ~AutoConnectElement() {}
virtual const String toHTML(void) const { return value; } /**< HTML code to be generated */
String name; /**< Element name */
String value; /**< Element value */
};
/**
* Button arrangement class, a part of AutoConnectAux element.
* Placed a labeled button that can be added by user sketch.
* @param name Button name string.
* @param value Button value string.
* @param action A sting of action code, it contains a simple JavaScript code.
*/
class AutoConnectButton : public AutoConnectElement {
public:
explicit AutoConnectButton(const char* name = "", const char* value = "", const String action = String()) : AutoConnectElement(name, value), action(action) {}
const String toHTML(void) const;
String action; /**< A script for an onclick */
};
/**
* Checkbox arrangement class, a part of AutoConnectAux element.
* Place a optionally labeled input-box that can be added by user sketch.
* @param name Checkbox name string.
* @param value A string value associated with the input.
* @param label A label string that follows checkbox, optionally.
* The label is placed on the right side of the checkbox.
*/
class AutoConnectCheckbox : public AutoConnectElement {
public:
explicit AutoConnectCheckbox(const char* name = "", const char* value = "", const char* label = "", const bool checked = false) : AutoConnectElement(name, value), label(String(label)), checked(checked) {}
~AutoConnectCheckbox() {}
const String toHTML(void) const;
String label; /**< A label for a subsequent input box */
bool checked; /**< The element should be pre-selected */
};
/**
* Input-box arrangement class, a part of AutoConnectAux element.
* Place a optionally labeled input-box that can be added by user sketch.
* @param name Input-box name string.
* @param value Default value string. This string display as a placeholder by the default.
* @param label A label string that follows Input-box, optionally.
* The label is placed in front of Input-box.
*/
class AutoConnectInput : public AutoConnectElement {
public:
explicit AutoConnectInput(const char* name = "", const char* value = "", const char* label = "") : AutoConnectElement(name, value), label(String(label)) {}
~AutoConnectInput() {}
const String toHTML(void) const;
String label; /**< A label for a subsequent input box */
};
/**
* Selection-box arrangement class, A part of AutoConnectAux element.
* Place a optionally labeled Selection-box that can be added by user sketch.
* @param name Input-box name string.
* @param options String array display in a selection list.
* @param label A label string that follows Input-box, optionally.
* The label is placed in front of Input-box.
*/
class AutoConnectSelect : public AutoConnectElement {
public:
explicit AutoConnectSelect(const char* name = "", std::vector<String> options = {}, const char* label = "") : AutoConnectElement(name, ""), label(String(label)), _options(options) {}
~AutoConnectSelect() {}
const String toHTML(void) const;
void option(const String value) { _options.push_back(value); }
void empty(void) { _options.clear(); }
String label; /**< A label for a subsequent input box */
protected:
std::vector<String> _options; /**< List options array */
};
/**
* Submit button arrangement class, a part of AutoConnectAux element.
* Place a submit button with a label that can be added by user sketch.
* With the button behavior, the values of the elements contained in
* the form would be sent using the post method.
* @param name Button name string.
* @param value Sending value string.
* @param uri Sending uri string.
*/
class AutoConnectSubmit : public AutoConnectElement {
public:
explicit AutoConnectSubmit(const char* name = "", const char* value = "", const char* uri = "") : AutoConnectElement(name, value), uri(String(uri)) {}
const String toHTML(void) const;
String uri; /**< An url of submitting to */
};
/**
* Text arrangement class, a part of AutoConnectAux element.
* @param
* @param name Text name string.
* @param value Text value string.
* @param style A string of style-code for decoration, optionally.
* An arrangement text would be placed with <div> contains. A string
* of style-codes are given for '<div style=>'.
*/
class AutoConnectText : public AutoConnectElement {
public:
explicit AutoConnectText(const char* name = "", const char* value = "", const char* style = "") : AutoConnectElement(name, value), style(String(style)) {}
~AutoConnectText() {}
const String toHTML(void) const;
String style; /**< CSS style modifier native code */
};
/**
* Support declare the AutoConnectElement variable with reducing the
* arguments. These macros declare the AutoConnectElement variable
* with the same name as a "name" argument.
*/
#define ACElement(n, v) AutoConnectElements n(#n, v)
#define ACButton(n, ...) AutoConnectButton n(#n, ## __VA_ARGS__)
#define ACCheckbox(n, ...) AutoConnectCheckbox n(#n, ## __VA_ARGS__)
#define ACInput(n, ...) AutoConnectInput n(#n, ## __VA_ARGS__)
#define ACSelect(n, ...) AutoConnectSelect n(#n, ## __VA_ARGS__)
#define ACSubmit(n, ...) AutoConnectSubmit n(#n, ## __VA_ARGS__)
#define ACText(n, ...) AutoConnectText n(#n, ## __VA_ARGS__)
// Manage placed AutoConnectElement with a vector // Manage placed AutoConnectElement with a vector
typedef std::vector<std::reference_wrapper<AutoConnectElement>> AutoConnectElementVT; typedef std::vector<std::reference_wrapper<AutoConnectElement>> AutoConnectElementVT;
@ -167,6 +33,8 @@ typedef enum {
AC_EXIT_BOTH = 3 AC_EXIT_BOTH = 3
} AutoConnectExitOrder_t; } AutoConnectExitOrder_t;
//class AutoConnect; // Reference to avoid circular
/** /**
* A class that handles an auxiliary page with AutoConnectElement * A class that handles an auxiliary page with AutoConnectElement
* that placed on it by binding it to the AutoConnect menu. * that placed on it by binding it to the AutoConnect menu.
@ -188,6 +56,11 @@ class AutoConnectAux : public PageBuilder {
void menu(const bool post) { _menu = post; } /**< Set or reset the display as menu item for this aux. */ void menu(const bool post) { _menu = post; } /**< Set or reset the display as menu item for this aux. */
void on(const AuxHandlerFunctionT handler, const AutoConnectExitOrder_t order = AC_EXIT_AHEAD) { _handler = handler; _order = order; } /**< Set user handler */ void on(const AuxHandlerFunctionT handler, const AutoConnectExitOrder_t order = AC_EXIT_AHEAD) { _handler = handler; _order = order; } /**< Set user handler */
#ifdef AUTOCONNECT_USE_JSON
AutoConnectElement& loadElement(Stream& in, const String name);
size_t saveElement(Stream& out, const AutoConnectElement& element);
#endif
protected: protected:
void _concat(AutoConnectAux& aux); void _concat(AutoConnectAux& aux);
void _join(AutoConnect& ac); void _join(AutoConnect& ac);
@ -196,6 +69,13 @@ class AutoConnectAux : public PageBuilder {
const String _injectTitle(PageArgument& args) { return _title; } const String _injectTitle(PageArgument& args) { return _title; }
const String _injectMenu(PageArgument& args); const String _injectMenu(PageArgument& args);
#ifdef AUTOCONNECT_USE_JSON
AutoConnectElement* _createElement(const JsonObject& json);
AutoConnectElement* _getElement(const String name);
static const ACElement_t _asElementType(const String type);
static AutoConnectElement& _nullElement(void);
#endif
String _title; /**< A title of the page */ String _title; /**< A title of the page */
bool _menu; /**< Switch for menu displaying */ bool _menu; /**< Switch for menu displaying */
AutoConnectElementVT _addonElm; /**< A vector set of AutoConnectElements placed on this auxiliary page */ AutoConnectElementVT _addonElm; /**< A vector set of AutoConnectElements placed on this auxiliary page */
@ -210,4 +90,4 @@ class AutoConnectAux : public PageBuilder {
friend class AutoConnect; friend class AutoConnect;
}; };
#endif // _AUTOCONNECTAUX_H_ #endif // _AUTOCONNECTAUX_H_

@ -0,0 +1,103 @@
/**
* Predefined AutoConnect configuration parameters.
* @file AutoConnectDefs.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-11-17
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTDEFS_H_
#define _AUTOCONNECTDEFS_H_
// Uncomment the following AC_DEBUG to enable debug output.
#define AC_DEBUG
// Debug output destination can be defined externally with AC_DEBUG_PORT
#ifndef AC_DEBUG_PORT
#define AC_DEBUG_PORT Serial
#endif // !AC_DEBUG_PORT
#ifdef AC_DEBUG
#define AC_DBG(...) do {AC_DEBUG_PORT.print("[AC] "); AC_DEBUG_PORT.printf( __VA_ARGS__ );} while (0)
#else
#define AC_DBG(...)
#endif // !AC_DEBUG
// Indicator to specify that AutoConnectAux handles elements with JSON.
#define AUTOCONNECT_USE_JSON
// Predefined parameters
// SSID that Captive portal started.
#ifndef AUTOCONNECT_APID
#if defined(ARDUINO_ARCH_ESP8266)
#define AUTOCONNECT_APID "esp8266ap"
#elif defined(ARDUINO_ARCH_ESP32)
#define AUTOCONNECT_APID "esp32ap"
#endif // !ARDUINO_ARCH_ESP8266
#endif // !AUTOCONNECT_APID
// Password that Captive portal started.
#ifndef AUTOCONNECT_PSK
#define AUTOCONNECT_PSK "12345678"
#endif // !AUTOCONNECT_PSK
#ifndef AUTOCONNECT_AP_IP
#define AUTOCONNECT_AP_IP 0x01F4A8C0 //*< 192.168.244.1 */
#endif // !AUTOCONNECT_AP_IP
#ifndef AUTOCONNECT_AP_GW
#define AUTOCONNECT_AP_GW 0x01F4A8C0 //*< 192.168.244.1 */
#endif // !AUTOCONNECT_AP_GW
#ifndef AUTOCONNECT_AP_NM
#define AUTOCONNECT_AP_NM 0x00FFFFFF //*< 255.255.255.0 */
#endif // !AUTOCONNECT_AP_NM
// AutoConnect menu root path
#ifndef AUTOCONNECT_URI
#define AUTOCONNECT_URI "/_ac"
#endif // !AUTOCONNECT_URI
// Root URI of home path prepared by user sketch
#ifndef AUTOCONNECT_HOMEURI
#define AUTOCONNECT_HOMEURI "/"
#endif // !AUTOCONNECT_HOMEURI
// AutoConnect menu title
#ifndef AUTOCONNECT_MENU_TITLE
#define AUTOCONNECT_MENU_TITLE "AutoConnect"
#endif // !AUTOCONNECT_MENU_TITLE
#define AUTOCONNECT_MENU_TITLE_CONNETED "Connected"
// URIs of AutoConnect menu collection
#define AUTOCONNECT_URI_CONFIG AUTOCONNECT_URI "/config"
#define AUTOCONNECT_URI_CONNECT AUTOCONNECT_URI "/connect"
#define AUTOCONNECT_URI_RESULT AUTOCONNECT_URI "/result"
#define AUTOCONNECT_URI_OPEN AUTOCONNECT_URI "/open"
#define AUTOCONNECT_URI_DISCON AUTOCONNECT_URI "/disc"
#define AUTOCONNECT_URI_RESET AUTOCONNECT_URI "/reset"
#define AUTOCONNECT_URI_SUCCESS AUTOCONNECT_URI "/success"
#define AUTOCONNECT_URI_FAIL AUTOCONNECT_URI "/fail"
// Time-out limitation when AutoConnect::begin
#ifndef AUTOCONNECT_TIMEOUT
#define AUTOCONNECT_TIMEOUT 30000
#endif // !AUTOCONNECT_TIMEOUT
// Advance wait time
#ifndef AUTOCONNECT_STARTUPTIME
#define AUTOCONNECT_STARTUPTIME 10
#endif // !AUTOCONNECT_STARTUPTIME
// Default HTTP port
#ifndef AUTOCONNECT_HTTPPORT
#define AUTOCONNECT_HTTPPORT 80
#endif // !AUTOCONNECT_HTTPPORT
// DNS port
#ifndef AUTOCONNECT_DNSPORT
#define AUTOCONNECT_DNSPORT 53
#endif // !AUTOCONNECT_DNSPORT
// Explicitly avoiding unused warning with token handler of PageBuilder
#define AC_UNUSED(expr) do { (void)(expr); } while (0)
#endif // _AUTOCONNECTDEFS_H_

@ -0,0 +1,49 @@
/**
* Alias declarations for an accessible the AutoConnectElement class.
* @file AutoConnectAux.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-11-17
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTELEMENT_H_
#define _AUTOCONENCTELEMENT_H_
#include "AutoConnectElementBasis.h"
//#include "AutoConnectElementBasisImpl.h"
#ifdef AUTOCONNECT_USE_JSON
#include <ArduinoJson.h>
#include "AutoConnectElementJson.h"
//#include "AutoConnectElementJsonImpl.h"
using AutoConnectElement = AutoConnectElementJson;
using AutoConnectButton = AutoConnectButtonJson;
using AutoConnectCheckbox = AutoConnectCheckboxJson;
using AutoConnectInput = AutoConnectInputJson;
using AutoConnectSelect = AutoConnectSelectJson;
using AutoConnectSubmit = AutoConnectSubmitJson;
using AutoConnectText = AutoConnectTextJson;
#else
using AutoConnectElement = AutoConnectElementBasis;
using AutoConnectButton = AutoConnectButtonBasis;
using AutoConnectCheckbox = AutoConnectCheckboxBasis;
using AutoConnectInput = AutoConnectInputBasis;
using AutoConnectSelect = AutoConnectSelectBasis;
using AutoConnectSubmit = AutoConnectSubmitBasis;
using AutoConnectText = AutoConnectTextBasis;
#endif
/**
* Support declare the AutoConnectElement variable with reducing the
* arguments. These macros declare the AutoConnectElement variable
* with the same name as a "name" argument.
*/
#define ACElement(n, v) AutoConnectElement n(#n, v)
#define ACButton(n, ...) AutoConnectButton n(#n, ##__VA_ARGS__)
#define ACCheckbox(n, ...) AutoConnectCheckbox n(#n, ##__VA_ARGS__)
#define ACInput(n, ...) AutoConnectInput n(#n, ##__VA_ARGS__)
#define ACSelect(n, ...) AutoConnectSelect n(#n, ##__VA_ARGS__)
#define ACSubmit(n, ...) AutoConnectSubmit n(#n, ##__VA_ARGS__)
#define ACText(n, ...) AutoConnectText n(#n, ##__VA_ARGS__)
#endif // _AUTOCONNECTELEMENT_H_

@ -0,0 +1,170 @@
/**
* Declaration of AutoConnectElement basic class.
* @file AutoConnectElementBasis.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-11-17
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTELEMENTBASIS_H_
#define _AUTOCONNECTELEMENTBASIS_H_
#include <vector>
#include <memory>
typedef enum {
AC_Button,
AC_Checkbox,
AC_Element,
AC_Input,
AC_Select,
AC_Submit,
AC_Text,
AC_Unknown
} ACElement_t; /**< AutoConnectElement class type */
/**
* AutoConnectAux element base.
* Placed a raw text that can be added by user sketch.
* @param name A name string for the element.
* @param value A raw text to be placed in HTML.
*/
class AutoConnectElementBasis {
public:
explicit AutoConnectElementBasis(const char* name = "", const char* value = "") : name(String(name)), value(String(value)) {
_type = AC_Element;
}
virtual ~AutoConnectElementBasis() {}
virtual const String toHTML(void) const { return value; }
const ACElement_t typeOf(void) const { return _type; }
String name; /**< Element name */
String value; /**< Element value */
protected:
ACElement_t _type; /**< Element type identifier */
};
/**
* Button arrangement class, a part of AutoConnectAux element.
* Place a labeled button that can be added by user sketch.
* @param name Button element name string.
* @param value Value string with the placed button.
* @param action Script code to execute with the button pushed.
*/
class AutoConnectButtonBasis : virtual public AutoConnectElementBasis {
public:
explicit AutoConnectButtonBasis(const char* name = "", const char* value = "", const String action = String()) : AutoConnectElementBasis(name, value), action(action) {
_type = AC_Button;
}
~AutoConnectButtonBasis() {}
const String toHTML(void) const;
String action;
};
/**
* Checkbox arrangement class, a part of AutoConnectAux element.
* Place a optionally labeled input-box that can be added by user sketch.
* @param name Checkbox name string.
* @param value A string value associated with the input.
* @param label A label string that follows checkbox, optionally.
* The label is placed on the right side of the checkbox.
*/
class AutoConnectCheckboxBasis : virtual public AutoConnectElementBasis {
public:
explicit AutoConnectCheckboxBasis(const char* name = "", const char* value = "", const char* label = "", const bool checked = false) : AutoConnectElementBasis(name, value), label(String(label)), checked(checked) {
_type = AC_Checkbox;
}
virtual ~AutoConnectCheckboxBasis() {}
const String toHTML(void) const;
String label; /**< A label for a subsequent input box */
bool checked; /**< The element should be pre-selected */
};
/**
* Input-box arrangement class, a part of AutoConnectAux element.
* Place a optionally labeled input-box that can be added by user sketch.
* @param name Input-box name string.
* @param value Default value string. This string display as a placeholder by the default.
* @param label A label string that follows Input-box, optionally.
* The label is placed in front of Input-box.
*/
class AutoConnectInputBasis : virtual public AutoConnectElementBasis {
public:
explicit AutoConnectInputBasis(const char* name = "", const char* value = "", const char* label = "") : AutoConnectElementBasis(name, value), label(String(label)) {
_type = AC_Input;
}
virtual ~AutoConnectInputBasis() {}
const String toHTML(void) const;
String label; /**< A label for a subsequent input box */
};
/**
* Selection-box arrangement class, A part of AutoConnectAux element.
* Place a optionally labeled Selection-box that can be added by user sketch.
* @param name Input-box name string.
* @param options String array display in a selection list.
* @param label A label string that follows Input-box, optionally.
* The label is placed in front of Input-box.
*/
class AutoConnectSelectBasis : virtual public AutoConnectElementBasis {
public:
explicit AutoConnectSelectBasis(const char* name = "", std::vector<String> options = {}, const char* label = "") : AutoConnectElementBasis(name, ""), label(String(label)), _options(options) {
_type = AC_Select;
}
virtual ~AutoConnectSelectBasis() {}
const String toHTML(void) const;
void option(const String value) { _options.push_back(value); }
void empty(void) { _options.clear(); }
String label; /**< A label for a subsequent input box */
protected:
std::vector<String> _options; /**< List options array */
};
/**
* Submit button arrangement class, a part of AutoConnectAux element.
* Place a submit button with a label that can be added by user sketch.
* With the button behavior, the values of the elements contained in
* the form would be sent using the post method.
* @param name Button name string.
* @param value Sending value string.
* @param uri Sending uri string.
*/
class AutoConnectSubmitBasis : virtual public AutoConnectElementBasis {
public:
explicit AutoConnectSubmitBasis(const char* name = "", const char* value = "", const char* uri = "") : AutoConnectElementBasis(name, value), uri(String(uri)) {
_type = AC_Submit;
}
virtual ~AutoConnectSubmitBasis() {}
const String toHTML(void) const;
String uri; /**< An url of submitting to */
};
/**
* Text arrangement class, a part of AutoConnectAux element.
* @param
* @param name Text name string.
* @param value Text value string.
* @param style A string of style-code for decoration, optionally.
* An arrangement text would be placed with <div> contains. A string
* of style-codes are given for '<div style=>'.
*/
class AutoConnectTextBasis : virtual public AutoConnectElementBasis {
public:
explicit AutoConnectTextBasis(const char* name = "", const char* value = "", const char* style = "") : AutoConnectElementBasis(name, value), style(String(style)) {
_type = AC_Text;
}
virtual ~AutoConnectTextBasis() {}
const String toHTML(void) const;
String style; /**< CSS style modifier native code */
};
#endif // _AUTOCONNECTELEMENTBASIS_H_

@ -0,0 +1,107 @@
/**
* Implementation of AutoConnectElementBasis classes.
* @file AutoConnectElementImpl.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-11-17
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTELEMENTBASISIMPL_H_
#define _AUTOCONNECTELEMENTBASISIMPL_H_
#include "AutoConnectElementBasis.h"
/**
* Generate an HTML <button> element. The onclick behavior depends on
* the code held in factionf member.
* @return An HTML string.
*/
const String AutoConnectButtonBasis::toHTML(void) const {
return String(FPSTR("<button type=\"button\" name=\"")) + name + String(FPSTR("\" value=\"")) + value + String(FPSTR("\" onclick=\"")) + action + String("\">") + value + String(FPSTR("</button>"));
}
/**
* Generate an HTML <input type=checkbox> element.
* A "value" is associated with the input tag and sent by the form
* action as the value of "name". If the label member is contained, it
* is placed to the right side of the checkbox to be labeled.
* f the label member is empty, only the checkbox is placed.
* @return An HTML string.
*/
const String AutoConnectCheckboxBasis::toHTML(void) const {
String html;
html = String(FPSTR("<input type=\"checkbox\" name=\"")) + name + String(FPSTR("\" value=\"")) + value + String("\"");
if (checked)
html += String(FPSTR(" checked"));
if (label.length())
html += String(" id=\"") + name + String("\"><label for=\"") + name + String("\">") + label + String(FPSTR("</label"));
html += String(FPSTR("><br>"));
return html;
}
/**
* Generate an HTML <input type=text> element.
* If the value member is contained, it is reflected in the placeholder
* attribute. The entered value can be obtained using the user callback
* function registered by AutoConnectAux::on after the form is sent in
* combination with AutoConnectSubmit.
* @return String an HTML string.
*/
const String AutoConnectInputBasis::toHTML(void) const {
String html = String();
if (label.length())
html = String(FPSTR("<label for=\"")) + name + String("\">") + label + String(FPSTR("</label>"));
html += String(FPSTR("<input type=\"text\" id=\"")) + name + String(FPSTR("\" name=\"")) + name;
if (value.length())
html += String(FPSTR("\" placeholder=\"")) + value;
html += String(FPSTR("\"><br>"));
return html;
}
/**
* Generate an HTML <select> element with an <option> element.
* The attribute value of the <option> element is given to the
* AutoConnectSelect class as a string array, which would be stored
* in the 'options' member. If a label member is contained, the <label>
* element would be generated the preface of <select>.
* @return String an HTML string.
*/
const String AutoConnectSelectBasis::toHTML(void) const {
String html = String();
if (label.length())
html = String(FPSTR("<label>")) + label + String(FPSTR("</label>"));
html += String(FPSTR("<select name=\"")) + name + String("\">");
std::size_t n = _options.size();
if (n) {
for (std::size_t n = 0; n < _options.size(); n++)
html += String(FPSTR("<option value=\"")) + _options[n] + "\">" + _options[n] + String(FPSTR("</option>"));
}
html += String(FPSTR("</select><br>"));
return html;
}
/**
* Generate an HTML <input type=button> element. This element is used
* for form submission. An 'onclick' attribute calls fixed JavaScript
* code as 'sa' named and it's included in the template.
* @return String an HTML string.
*/
const String AutoConnectSubmitBasis::toHTML(void) const {
return String(FPSTR("<input type=\"button\" name=\"")) + name + String(FPSTR("\" value=\"")) + value + String(FPSTR("\" onclick=\"_sa('")) + uri + String("')\">");
}
/**
* Generate an HTML text element from a string of the value member. If a style
* exists, it gives a style attribute.
* @return String an HTML string.
*/
const String AutoConnectTextBasis::toHTML(void) const {
return String(FPSTR("<div style=\"")) + style + String("\">") + value + String(FPSTR("</div>"));
}
#endif // _AUTOCONNECTELEMENTBASISIMPL_H_

@ -0,0 +1,173 @@
/**
* Declaration of AutoConnectElement extended classes using JSON.
* @file AutoConnectElementJson.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-11-17
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTELEMENTJSON_H_
#define _AUTOCONNECTELEMENTJSON_H_
#include "AutoConnectElementBasis.h"
#include <ArduinoJson.h>
#define AUTOCONNECT_JSON_KEY_AUX "aux"
#define AUTOCONNECT_JSON_KEY_ELEMENT "element"
#define AUTOCONNECT_JSON_KEY_ACTION "action"
#define AUTOCONNECT_JSON_KEY_CHECKED "checked"
#define AUTOCONNECT_JSON_KEY_LABEL "label"
#define AUTOCONNECT_JSON_KEY_NAME "name"
#define AUTOCONNECT_JSON_KEY_OPTIONS "options"
#define AUTOCONNECT_JSON_KEY_STYLE "style"
#define AUTOCONNECT_JSON_KEY_TYPE "type"
#define AUTOCONNECT_JSON_KEY_URI "uri"
#define AUTOCONNECT_JSON_KEY_VALUE "value"
#define AUTOCONNECT_JSON_TYPE_ACBUTTON "ACButton"
#define AUTOCONNECT_JSON_TYPE_ACCHECKBOX "ACCheckBox"
#define AUTOCONNECT_JSON_TYPE_ACELEMENT "ACElement"
#define AUTOCONNECT_JSON_TYPE_ACINPUT "ACInput"
#define AUTOCONNECT_JSON_TYPE_ACSELECT "ACSelect"
#define AUTOCONNECT_JSON_TYPE_ACSUBMIT "ACSubmit"
#define AUTOCONNECT_JSON_TYPE_ACTEXT "ACText"
/**
* AutoConnectAux element base with handling with JSON object.
* Placed a raw text that can be added by user sketch.
* @param name A name string for the element.
* @param value A raw text to be placed in HTML.
*/
class AutoConnectElementJson : virtual public AutoConnectElementBasis {
public:
explicit AutoConnectElementJson(const char* name = "", const char* value = "") {
AutoConnectElementBasis::name = name;
AutoConnectElementBasis::value = value;
}
~AutoConnectElementJson() {}
virtual bool loadElement(const JsonObject& json);
protected:
void _setElement(const JsonObject& json);
};
/**
* Button arrangement class, a part of AutoConnectAux element with
* handling JSON object.
* Place a labeled button that can be added by user sketch.
* @param name Button element name string.
* @param value Value string with the placed button.
* @param action Script code to execute with the button pushed.
*/
class AutoConnectButtonJson : public AutoConnectElementJson, public AutoConnectButtonBasis {
public:
explicit AutoConnectButtonJson(const char* name = "", const char* value = "", const String action = String()) {
AutoConnectButtonBasis::name = name;
AutoConnectButtonBasis::value = value;
AutoConnectButtonBasis::action = action;
}
~AutoConnectButtonJson() {}
bool loadElement(const JsonObject& json);
};
/**
* Checkbox arrangement class, a part of AutoConnectAux element with
* handling JSON object.
* Place a optionally labeled input-box that can be added by user sketch.
* @param name Checkbox name string.
* @param value A string value associated with the input.
* @param label A label string that follows checkbox, optionally.
* The label is placed on the right side of the checkbox.
*/
class AutoConnectCheckboxJson : public AutoConnectElementJson, public AutoConnectCheckboxBasis {
public:
explicit AutoConnectCheckboxJson(const char* name = "", const char* value = "", const char* label = "", const bool checked = false) {
AutoConnectCheckboxBasis::name = name;
AutoConnectCheckboxBasis::value = value;
AutoConnectCheckboxBasis::label = label;
AutoConnectCheckboxBasis::checked = checked;
}
~AutoConnectCheckboxJson() {}
bool loadElement(const JsonObject& json);
};
/**
* Input-box arrangement class, a part of AutoConnectAux element with
* handling JSON object.
* Place a optionally labeled input-box that can be added by user sketch.
* @param name Input-box name string.
* @param value Default value string. This string display as a placeholder by the default.
* @param label A label string that follows Input-box, optionally.
* The label is placed in front of Input-box.
*/
class AutoConnectInputJson : public AutoConnectElementJson, public AutoConnectInputBasis {
public:
explicit AutoConnectInputJson(const char* name = "", const char* value = "", const char* label = "") {
AutoConnectInputBasis::name = name;
AutoConnectInputBasis::value = value;
AutoConnectInputBasis::label = label;
}
~AutoConnectInputJson() {}
bool loadElement(const JsonObject& json);
};
/**
* Selection-box arrangement class, A part of AutoConnectAux element.
* Place a optionally labeled Selection-box that can be added by user sketch.
* @param name Input-box name string.
* @param options String array display in a selection list.
* @param label A label string that follows Input-box, optionally.
* The label is placed in front of Input-box.
*/
class AutoConnectSelectJson : public AutoConnectElementJson, public AutoConnectSelectBasis {
public:
explicit AutoConnectSelectJson(const char* name = "", std::vector<String> options = {}, const char* label = "") {
AutoConnectSelectBasis::name = name;
AutoConnectSelectBasis::_options = options;
AutoConnectSelectBasis::label = label;
}
~AutoConnectSelectJson() {}
bool loadElement(const JsonObject& json);
};
/**
* Submit button arrangement class, a part of AutoConnectAux element.
* Place a submit button with a label that can be added by user sketch.
* With the button behavior, the values of the elements contained in
* the form would be sent using the post method.
* @param name Button name string.
* @param value Sending value string.
* @param uri Sending uri string.
*/
class AutoConnectSubmitJson : public AutoConnectElementJson, public AutoConnectSubmitBasis {
public:
explicit AutoConnectSubmitJson(const char* name = "", const char* value = "", const char* uri = "") {
AutoConnectSubmitBasis::name = name;
AutoConnectSubmitBasis::value = value;
AutoConnectSubmitBasis::uri = uri;
}
~AutoConnectSubmitJson() {}
bool loadElement(const JsonObject& json);
};
/**
* Text arrangement class, a part of AutoConnectAux element.
* @param
* @param name Text name string.
* @param value Text value string.
* @param style A string of style-code for decoration, optionally.
* An arrangement text would be placed with <div> contains. A string
* of style-codes are given for '<div style=>'.
*/
class AutoConnectTextJson : public AutoConnectElementJson, public AutoConnectTextBasis {
public:
explicit AutoConnectTextJson(const char* name = "", const char* value = "", const char* style = "") {
AutoConnectTextBasis::name = name;
AutoConnectTextBasis::value = value;
AutoConnectTextBasis::style = style;
}
~AutoConnectTextJson() {}
bool loadElement(const JsonObject& json);
};
#endif // _AUTOCONNECTELEMENTJSON_H_

@ -0,0 +1,140 @@
/**
* Implementation of AutoConnectElementJson classes.
* @file AutoConnectElementImpl.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-11-17
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTELEMENTJSONIMPL_H_
#define _AUTOCONNECTELEMENTJSONIMPL_H_
#include "AutoConnectElementJson.h"
/**
* Set items common to any type of AutoConnectElement from JSON objects.
* @param json A JSON object with the definition of AutoConnectElement.
*/
void AutoConnectElementJson::_setElement(const JsonObject& json) {
name = json.get<String>(F(AUTOCONNECT_JSON_KEY_NAME));
value = json.get<String>(F(AUTOCONNECT_JSON_KEY_VALUE));
}
/**
* Load an element member value from the JSON object.
* @param json A JSON object with the definition of AutoConnectElement.
* @return true AutoConnectElement loaded
* @return false Type of AutoConnectElement is mismatched.
*/
bool AutoConnectElementJson::loadElement(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACELEMENT))) {
_setElement(json);
return true;
}
return false;
}
/**
* Load a button element attribute member from the JSON object.
* @param json A JSON object with the definition of AutoConnectElement.
* @return true AutoConnectElement loaded
* @return false Type of AutoConnectElement is mismatched.
*/
bool AutoConnectButtonJson::loadElement(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACBUTTON))) {
_setElement(json);
action = json.get<String>(F(AUTOCONNECT_JSON_KEY_ACTION));
return true;
}
return false;
}
/**
* Load a checkbox element attribute member from the JSON object.
* @param json A JSON object with the definition of AutoConnectElement.
* @return true AutoConnectElement loaded
* @return false Type of AutoConnectElement is mismatched.
*/
bool AutoConnectCheckboxJson::loadElement(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACCHECKBOX))) {
_setElement(json);
label = json.get<String>(F(AUTOCONNECT_JSON_KEY_LABEL));
checked = json.get<bool>(F(AUTOCONNECT_JSON_KEY_CHECKED));
return true;
}
return false;
}
/**
* Load a input-box element attribute member from the JSON object.
* @param json A JSON object with the definition of AutoConnectElement.
* @return true AutoConnectElement loaded
* @return false Type of AutoConnectElement is mismatched.
*/
bool AutoConnectInputJson::loadElement(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACINPUT))) {
_setElement(json);
label = json.get<String>(F(AUTOCONNECT_JSON_KEY_LABEL));
return true;
}
return false;
}
/**
* Load a select element attribute member from the JSON object.
* @param json A JSON object with the definition of AutoConnectElement.
* @return true AutoConnectElement loaded
* @return false Type of AutoConnectElement is mismatched.
*/
bool AutoConnectSelectJson::loadElement(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACSELECT))) {
_setElement(json);
empty();
label = json.get<String>(F(AUTOCONNECT_JSON_KEY_LABEL));
JsonArray& optionArray = json[AUTOCONNECT_JSON_KEY_OPTIONS];
for (auto value : optionArray)
option(value.as<String>());
return true;
}
return false;
}
/**
* Load a submit element attribute member from the JSON object.
* @param json A JSON object with the definition of AutoConnectElement.
* @return true AutoConnectElement loaded
* @return false Type of AutoConnectElement is mismatched.
*/
bool AutoConnectSubmitJson::loadElement(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACSUBMIT))) {
_setElement(json);
uri = json.get<String>(F(AUTOCONNECT_JSON_KEY_URI));
return true;
}
return false;
}
/**
* Load a text element attribute member from the JSON object.
* @param json A JSON object with the definition of AutoConnectElement.
* @return true AutoConnectElement loaded
* @return false Type of AutoConnectElement is mismatched.
*/
bool AutoConnectTextJson::loadElement(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACTEXT))) {
_setElement(json);
style = json.get<String>(F(AUTOCONNECT_JSON_KEY_STYLE));
return true;
}
return false;
}
#endif // _AUTOCONNECTELEMENTJSONIMPL_H_
Loading…
Cancel
Save