Supports AutoConnectAux

pull/41/head
Hieromon Ikasamo 6 years ago
parent dbbb220ffa
commit bc03f917f7
  1. 26
      keywords.txt
  2. 9
      src/AutoConnect.cpp
  3. 2
      src/AutoConnect.h
  4. 191
      src/AutoConnectAux.cpp
  5. 171
      src/AutoConnectAux.h
  6. 56
      src/AutoConnectPage.cpp

@ -5,14 +5,13 @@ AutoConnect KEYWORD1
AutoConnectConfig KEYWORD1 AutoConnectConfig KEYWORD1
AutoConnectCredential KEYWORD1 AutoConnectCredential KEYWORD1
AutoConnectAux KEYWORD1 AutoConnectAux KEYWORD1
AutoConnectText KEYWORD1 AutoConnectButton KEYWORD1
AutoConnectCheckbox KEYWORD1
AutoConnectElement KEYWORD1
AutoConnectInput KEYWORD1 AutoConnectInput KEYWORD1
AutoConnectButon KEYWORD1 AutoConnectSelect KEYWORD1
AutoConnectSubmit KEYWORD1 AutoConnectSubmit KEYWORD1
ACText KEYWORD1 AutoConnectText KEYWORD1
ACInput KEYWORD1
ACButton KEYWORD1
ACSubmit KEYWORD1
####################################### #######################################
# Methods and Functions (KEYWORD2) # Methods and Functions (KEYWORD2)
@ -29,11 +28,15 @@ home KEYWORD2
host KEYWORD2 host KEYWORD2
join KEYWORD2 join KEYWORD2
load KEYWORD2 load KEYWORD2
menu KEYWORD2
name KEYWORD2 name KEYWORD2
on KEYWORD2 on KEYWORD2
onDetect KEYWORD2 onDetect KEYWORD2
onNotFound KEYWORD2 onNotFound KEYWORD2
release KEYWORD2
save KEYWORD2 save KEYWORD2
setTitle KEYWORD2
toHTML KEYWORD2
value KEYWORD2 value KEYWORD2
####################################### #######################################
@ -43,3 +46,14 @@ AC_WEBSERVER_PARASITIC LITERAL1
AC_WEBSERVER_HOSTED LITERAL1 AC_WEBSERVER_HOSTED LITERAL1
AC_SAVECREDENTIAL_NEVER LITERAL1 AC_SAVECREDENTIAL_NEVER LITERAL1
AC_SAVECREDENTIAL_AUTO LITERAL1 AC_SAVECREDENTIAL_AUTO LITERAL1
#######################################
# PREPROCESSOR (KEYWORD3)
#######################################
ACButton PREPROCESSOR
ACCheckbox PREPROCESSOR
ACElement PREPROCESSOR
ACInput PREPROCESSOR
ACSelect PREPROCESSOR
ACSubmit PREPROCESSOR
ACText PREPROCESSOR

@ -274,12 +274,12 @@ WebServerClass& AutoConnect::host() {
* the auxiliary page to be added. * the auxiliary page to be added.
*/ */
void AutoConnect::join(AutoConnectAux& aux) { void AutoConnect::join(AutoConnectAux& aux) {
aux._join(*this);
AC_DBG("%s on hands\n", aux.uri());
if (_aux) if (_aux)
_aux->_concat(aux); _aux->_concat(aux);
else else
_aux.reset(&aux); _aux.reset(&aux);
aux._join(*this);
AC_DBG("%s on hands\n", aux.uri());
} }
/** /**
@ -289,7 +289,7 @@ void AutoConnect::join(AutoConnectAux& aux) {
*/ */
void AutoConnect::join(std::vector<std::reference_wrapper<AutoConnectAux>> aux) { void AutoConnect::join(std::vector<std::reference_wrapper<AutoConnectAux>> aux) {
for (std::size_t n = 0; n < aux.size(); n++) { for (std::size_t n = 0; n < aux.size(); n++) {
AutoConnectAux& addon = aux[n + 1].get(); AutoConnectAux& addon = aux[n].get();
join(addon); join(addon);
} }
} }
@ -397,9 +397,8 @@ void AutoConnect::handleRequest() {
_stopPortal(); _stopPortal();
_disconnectWiFi(true); _disconnectWiFi(true);
AC_DBG("Disconnected\n"); AC_DBG("Disconnected\n");
// Reset disconnection request //, restore the menu title. // Reset disconnection request
_rfDisconnect = false; _rfDisconnect = false;
// _menuTitle = String(AUTOCONNECT_MENU_TITLE);
if (_apConfig.autoReset) { if (_apConfig.autoReset) {
delay(1000); delay(1000);

@ -105,6 +105,8 @@ using WebServerClass = WebServer;
#define AUTOCONNECT_DNSPORT 53 #define AUTOCONNECT_DNSPORT 53
#endif #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,

@ -39,24 +39,114 @@ const char AutoConnectAux::_PAGE_AUX[] PROGMEM = {
"{{MENU_PRE}}" "{{MENU_PRE}}"
"{{MENU_AUX}}" "{{MENU_AUX}}"
"{{MENU_POST}}" "{{MENU_POST}}"
"<div class=\"base-panel\">" "<div class=\"base-panel\"><div class=\"aux-page\">"
"<form id='_aux' method=\"post\">" "<form id='_aux' method=\"post\">"
"<ul class=\"noorder\">" "<ul class=\"noorder\">"
"{{AUX_ELEMENT}}" "{{AUX_ELEMENT}}"
"</ul>" "</ul>"
"</form>" "</form>"
"</div>" "</div></div>"
"</div>" "</div>"
"<script>" "<script>"
"function sa(url) {" "function _sa(url) {"
"document.getElementById('_aux').action=url;" "document.getElementById('_aux').action=url;"
"document.getElementIyId('_aux').submit();" "document.getElementById('_aux').submit();"
"}" "}"
"</script>" "</script>"
"</body>" "</body>"
"</html>" "</html>"
}; };
/**
* Generate an HTML <button> element. The onclick behavior depends on
* the code held in <EFBFBD>faction<EFBFBD>f member.
* @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 (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 * Destructs container of AutoConnectElement and release a unique
* pointer of AutoConnect instance. * pointer of AutoConnect instance.
@ -68,16 +158,54 @@ AutoConnectAux::~AutoConnectAux() {
_ac.release(); _ac.release();
} }
/**
* Add an 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 in %s\n", addon.name().c_str(), uri()); AC_DBG("%s placed on %s\n", addon.name.c_str(), uri());
} }
/**
* Add an AutoConnectElement vector container to the AutoConnectAux page.
* @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++)
add(addons[n]); add(addons[n]);
} }
/**
* Releases the AutoConnectElements with the specified name from
* the AutoConnectAux page. Releases all AutoConnectElements with
* the same name in AutoConnectAux.
* @param name
* @return true The specified AutoConnectElements have been released.
* @return false The specified AutoConnectElement not found in AutoConnectAux.
*/
bool AutoConnectAux::release(const String name) {
bool rc = false;
for (std::size_t n = 0; n < _addonElm.size(); n++) {
String elmName = _addonElm[n].get().name;
if (elmName == name) {
AC_DBG("%s release from %s\n", elmName.c_str(), uri());
_addonElm.erase(_addonElm.begin() + n);
rc = true;
}
}
return rc;
}
/**
* Concatenates subsequent AutoConnectAux pages starting from oneself
* to the chain list.
* AutoConnectAux is collected in the chain list and each object is
* chained by the "_next". AutoConnect follows the "_next" to manage
* auxiliary pages. The _concat function concatenates subsequent
* AutoConnectAuxs.
* @param aux A reference of AutoConnectAux.
*/
void AutoConnectAux::_concat(AutoConnectAux& aux) { void AutoConnectAux::_concat(AutoConnectAux& aux) {
if (_next) if (_next)
_next->_concat(aux); _next->_concat(aux);
@ -85,13 +213,29 @@ void AutoConnectAux::_concat(AutoConnectAux& aux) {
_next.reset(&aux); _next.reset(&aux);
} }
/**
* Register the AutoConnect that owns itself.
* AutoConenctAux needs to access the AutoConnect member. Also
* AutoConnectAux is cataloged by chain list. The _join function
* registers AutoConnect in the following AutoConnectAux chain list.
* @param ac A reference of AutoConnect.
*/
void AutoConnectAux::_join(AutoConnect& ac) { void AutoConnectAux::_join(AutoConnect& ac) {
_ac.reset(&ac); _ac.reset(&ac);
// Chain to subsequent AutoConnectAux in the list.
if (_next) if (_next)
_next->_join(ac); _next->_join(ac);
} }
/**
* Insert the token handler of PageBuilder. This handler inserts HTML
* elements generated by the whole AutoConnectElements to the auxiliary page.
* @param args A reference of PageArgument but unused.
* @return HTML string that should be inserted.
*/
const String AutoConnectAux::_insertElement(PageArgument& args) { const String AutoConnectAux::_insertElement(PageArgument& args) {
AC_UNUSED(args);
String body = String(); String body = String();
for (std::size_t n = 0; n < _addonElm.size(); n++) { for (std::size_t n = 0; n < _addonElm.size(); n++) {
@ -101,6 +245,15 @@ const String AutoConnectAux::_insertElement(PageArgument& args) {
return body; return body;
} }
/**
* Generate an auxiliary page assembled with the AutoConnectElement.
* This function is the core procedure of AutoConnectAux, and uses
* PageBuilder from the _PAGE_AUX template to build an AutoConnect
* menu and insert HTML elements. A template of an auxiliary page is
* fixed and its structure inherits from the AutoConnect.
* @param uri An uri of the auxiliary page.
* @return A PageElement of auxiliary page.
*/
PageElement* AutoConnectAux::_setupPage(String uri) { PageElement* AutoConnectAux::_setupPage(String uri) {
PageElement* elm = nullptr; PageElement* elm = nullptr;
@ -111,16 +264,11 @@ PageElement* AutoConnectAux::_setupPage(String uri) {
} }
} else { } else {
AutoConnect* mother = _ac.get(); AutoConnect* mother = _ac.get();
elm = new PageElement(); // Overwrite actual AutoConnectMenu title to the Aux. page title
if (_title.length())
// Overwrite the default menu title
if (_title.length()) {
mother->_menuTitle = _title; mother->_menuTitle = _title;
_activeTitle = String();
}
else
_activeTitle = mother->_menuTitle;
elm = new PageElement();
// Construct the auxiliary page // Construct the auxiliary page
elm->setMold(_PAGE_AUX); elm->setMold(_PAGE_AUX);
elm->addToken(PSTR("EXIT_HANDLE"), std::bind(&AutoConnectAux::_exitHandle, this, std::placeholders::_1)); elm->addToken(PSTR("EXIT_HANDLE"), std::bind(&AutoConnectAux::_exitHandle, this, std::placeholders::_1));
@ -140,20 +288,31 @@ PageElement* AutoConnectAux::_setupPage(String uri) {
return elm; return elm;
} }
/**
* Inject the <li> element depending on the "luxbar-item" attribute
* for implementing the AutoConnect menu.
* @param args A reference of PageArgument but it's only used for
* interface alignment and is not actually used.
* @return A concatenated string of <li> elements for the menu item of
* AutoConnect.
*/
const String AutoConnectAux::_injectMenu(PageArgument& args) { const String AutoConnectAux::_injectMenu(PageArgument& args) {
String menuItem; String menuItem;
if (_title.length()) if (_menu)
menuItem = String(FPSTR("<li class=\"luxbar-item\"><a href=\"")) + String(_uri) + String("\">") + _title + String(FPSTR("</a></li>")); menuItem = String(FPSTR("<li class=\"luxbar-item\"><a href=\"")) + String(_uri) + String("\">") + _title + String(FPSTR("</a></li>"));
if (_next) if (_next)
menuItem += _next->_injectMenu(args); menuItem += _next->_injectMenu(args);
return menuItem; return menuItem;
} }
/**
* The 'on' handler callback behavior wrapper.
*/
const String AutoConnectAux::_exitHandle(PageArgument& args) { const String AutoConnectAux::_exitHandle(PageArgument& args) {
if (_handler) { if (_handler) {
AC_DBG("CB %s\n", *this->uri()); AC_DBG("CB %s\n", uri());
(*_handler)(*this, args); _handler(args);
} }
return ""; return "";
} }

@ -17,88 +17,91 @@
class AutoConnect; // Reference to avoid circular class AutoConnect; // Reference to avoid circular
// Add-on element base class /**
* 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 { class AutoConnectElement {
public: public:
explicit AutoConnectElement(const char* name, const char* value) : _name(String(name)), _value(String(value)) {} explicit AutoConnectElement(const char* name, const char* value) : name(String(name)), value(String(value)) {}
virtual ~AutoConnectElement() {} virtual ~AutoConnectElement() {}
const String name(void) const { return _name; } /**< Element name */ virtual const String toHTML(void) const { return value; } /**< HTML code to be generated */
const String value(void) const { return _value; } /**< Element value */
virtual const String toHTML(void) { return String(); }; /**< HTML code to be generated */
void setValue(const char* value) { _value = String(value); }
void setValue(const String value) { _value = value; }
protected: String name; /**< Element name */
String _name; String value; /**< Element value */
String _value;
}; };
/** /**
* Text arrangement class, a part of AutoConnectAux element. * Button arrangement class, a part of AutoConnectAux element.
* @param * Placed a labeled button that can be added by user sketch.
* @param name Text name string. * @param name Button name string.
* @param value Text value string. * @param value Button value string.
* @param style A string of style-code for decoration, optionally. * @param action A sting of action code, it contains a simple JavaScript code.
* An arrangement text would be placed with <div> contains. A string
* of style-codes are given for '<div style=>'.
*/ */
class AutoConnectText : public AutoConnectElement { class AutoConnectButton : public AutoConnectElement {
public: public:
explicit AutoConnectText(const char* name = "", const char* value = "", const char* style = "") : AutoConnectElement(name, value), _style(String(style)) {} explicit AutoConnectButton(const char* name = "", const char* value = "", const String action = String()) : AutoConnectElement(name, value), action(action) {}
~AutoConnectText() {} const String toHTML(void) const;
const String style(void) const { return _style; } /**< A modify of HTML 'style' code */
void setStyle(const char* style) { _style = String(style); }
void setStyle(const String style) { _style = style; }
const String toHTML(void) {
return String(FPSTR("<div style=\"")) + _style + String("\">") + _value + String(FPSTR("</div>"));
}
protected: String action; /**< A script for an onclick */
String _style; };
/**
* 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 = "") : AutoConnectElement(name, value), label(String(label)) {}
~AutoConnectCheckbox() {}
const String toHTML(void) const;
String label; /**< A label for a subsequent input box */
}; };
/** /**
* Input-box arrangement class, a part of AutoConnectAux element. * Input-box arrangement class, a part of AutoConnectAux element.
* Place a optionally labeled input-box that can be added by user sketch. * Place a optionally labeled input-box that can be added by user sketch.
* @param name Input-box name string. * @param name Input-box name string.
* @param value Button value 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. * @param label A label string that follows Input-box, optionally.
* The label is placed in front of Input-box. * The label is placed in front of Input-box.
*/ */
class AutoConnectInput : public AutoConnectElement { class AutoConnectInput : public AutoConnectElement {
public: public:
explicit AutoConnectInput(const char* name = "", const char* value = "", const char* label = "") : AutoConnectElement(name, value), _label(String(label)) {} explicit AutoConnectInput(const char* name = "", const char* value = "", const char* label = "") : AutoConnectElement(name, value), label(String(label)) {}
~AutoConnectInput() {} ~AutoConnectInput() {}
const String label(void) const { return _label; } const String toHTML(void) const;
void setLabel(const char* label) { _label = String(label); }
void setLabel(const String label) { _label = label; }
const String toHTML(void) {
return _label + String(FPSTR("<input type=\"text\" name=\"")) + _name + String(FPSTR("\" value=\"")) + _value + String("\"><br>");
}
protected: String label; /**< A label for a subsequent input box */
String _label;
}; };
/** /**
* Button arrangement class, a part of AutoConnectAux element. * Selection-box arrangement class, A part of AutoConnectAux element.
* Placed a labeled button that can be added by user sketch. * Place a optionally labeled Selection-box that can be added by user sketch.
* @param name Button name string. * @param name Input-box name string.
* @param value Button value string. * @param options String array display in a selection list.
* @param action A sting of action code, it contains a simple JavaScript code. * @param label A label string that follows Input-box, optionally.
* The label is placed in front of Input-box.
*/ */
class AutoConnectButton : public AutoConnectElement { class AutoConnectSelect : public AutoConnectElement {
public: public:
explicit AutoConnectButton(const char* name = "", const char* value = "", const String action = String()) : AutoConnectElement(name, value), _action(action) {} explicit AutoConnectSelect(const char* name = "", std::vector<String> options = {}, const char* label = "") : AutoConnectElement(name, ""), label(String(label)), _options(options) {}
const String action(void) const { return _action; } ~AutoConnectSelect() {}
void setAction(const char* action) { _action = String(action); } const String toHTML(void) const;
void setAction(const String action) { _action = action; } void option(const String value) { _options.push_back(value); }
const String toHTML(void) { void empty(void) { _options.clear(); }
return String(FPSTR("<button type=\"button\" name=\"")) + _name + String(FPSTR("\" value=\"")) + _value + String(FPSTR("\" onclick=\"")) + _action + String("\">") + _value + String(FPSTR("</button>"));
} String label; /**< A label for a subsequent input box */
protected: protected:
String _action; std::vector<String> _options; /**< List options array */
}; };
/** /**
@ -112,16 +115,28 @@ class AutoConnectButton : public AutoConnectElement {
*/ */
class AutoConnectSubmit : public AutoConnectElement { class AutoConnectSubmit : public AutoConnectElement {
public: public:
explicit AutoConnectSubmit(const char* name = "", const char* value = "", const char* uri = "") : AutoConnectElement(name, value), _uri(String(uri)) {} explicit AutoConnectSubmit(const char* name = "", const char* value = "", const char* uri = "") : AutoConnectElement(name, value), uri(String(uri)) {}
const String uri(void) const { return _uri; } const String toHTML(void) const;
void setUri(const char* uri) { _uri = String(uri); }
void setUri(const String uri) { _uri = uri; }
const String toHTML(void) {
return String(FPSTR("<button type=\"submit\" name=\"")) + _name + String(FPSTR("\" value=\"")) + _value + String(FPSTR("\" onclick=\"sa('")) + _uri + String("')\">") + _value + String(FPSTR("</button>"));
}
protected: String uri; /**< An url of submitting to */
String _uri; };
/**
* 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 */
}; };
/** /**
@ -129,19 +144,20 @@ class AutoConnectSubmit : public AutoConnectElement {
* arguments. These macros declare the AutoConnectElement variable * arguments. These macros declare the AutoConnectElement variable
* with the same name as a "name" argument. * with the same name as a "name" argument.
*/ */
#define ACText(name, ...) AutoConnectText name(#name, ## __VA_ARGS__) #define ACElement(n, v) AutoConnectElements n(#n, v)
#define ACInput(name, ...) AutoConnectInput name(#name, ## __VA_ARGS__) #define ACButton(n, ...) AutoConnectButton n(#n, ## __VA_ARGS__)
#define ACButton(name, ...) AutoConnectButton name(#name, ## __VA_ARGS__) #define ACCheckbox(n, ...) AutoConnectCheckbox n(#n, ## __VA_ARGS__)
#define ACSubmit(name, ...) AutoConnectSubmit name(#name, ## __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;
// To solve the forward reference.
class AutoConnectAux;
// A type of callback function when AutoConnectAux page requested. // A type of callback function when AutoConnectAux page requested.
typedef std::function<void(AutoConnectAux&, PageArgument&)> AuxHandleFuncT; //typedef std::function<void(AutoConnectAux&, PageArgument&)> AuxHandleFuncT;
typedef std::function<void(PageArgument&)> AuxHandlerFunctionT;
/** /**
* A class that handles an auxiliary page with AutoConnectElement * A class that handles an auxiliary page with AutoConnectElement
@ -149,33 +165,36 @@ typedef std::function<void(AutoConnectAux&, PageArgument&)> AuxHandleFuncT;
* @param uri An uri string of this page. * @param uri An uri string of this page.
* @param title A title string of this page. * @param title A title string of this page.
* @param addons A set of AutoConnectElement vector. * @param addons A set of AutoConnectElement vector.
* @param menu A switch for item displaying in AutoConnect menu.
*/ */
class AutoConnectAux : public PageBuilder { class AutoConnectAux : public PageBuilder {
public: public:
explicit AutoConnectAux(const char* uri = nullptr, const char* title = "", const AutoConnectElementVT addons = AutoConnectElementVT()) : explicit AutoConnectAux(const char* uri = nullptr, const char* title = "", const bool menu = true, const AutoConnectElementVT addons = AutoConnectElementVT()) :
_title(String(title)), _addonElm(addons) { setUri(uri); _next.release(); _ac.release(); _handler = nullptr; } _title(String(title)), _menu(menu), _addonElm(addons) { setUri(uri); _next.release(); _ac.release(); }
~AutoConnectAux(); ~AutoConnectAux();
void add(AutoConnectElement& addon); /**< Add an element to the auxiliary page. */ void add(AutoConnectElement& addon); /**< Add an element to the auxiliary page. */
void add(AutoConnectElementVT addons); /**< Add the element set to the auxiliary page. */ void add(AutoConnectElementVT addons); /**< Add the element set to the auxiliary page. */
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. */ void setTitle(const char* title) { _title = String(title); } /**< Set a title of the auxiliary page. */
void on(const AuxHandleFuncT handler) { _handler = &handler; } /**< Set user handler */ void menu(const bool post) { _menu = post; } /**< Set or reset the display as menu item for this aux. */
void on(const AuxHandlerFunctionT handler) { _handler = handler; } /**< Set user handler */
protected: protected:
void _concat(AutoConnectAux& aux); void _concat(AutoConnectAux& aux);
void _join(AutoConnect& ac); void _join(AutoConnect& ac);
PageElement* _setupPage(String uri); PageElement* _setupPage(String uri);
const String _insertElement(PageArgument& args); const String _insertElement(PageArgument& args);
const String _injectTitle(PageArgument& args) { return _title.length() > 0 ? _title : _activeTitle; } const String _injectTitle(PageArgument& args) { return _title; }
const String _injectMenu(PageArgument& args); const String _injectMenu(PageArgument& args);
const String _exitHandle(PageArgument& args); const String _exitHandle(PageArgument& args);
String _title; /**< A title of the page */ String _title; /**< A title of the page */
String _activeTitle; /**< Previous title of the page */ 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 */
std::unique_ptr<AutoConnectAux> _next; /**< Auxiliary pages chain list */ std::unique_ptr<AutoConnectAux> _next; /**< Auxiliary pages chain list */
std::unique_ptr<AutoConnect> _ac; /**< Hosted AutoConnect instance */ std::unique_ptr<AutoConnect> _ac; /**< Hosted AutoConnect instance */
const AuxHandleFuncT* _handler; /**< User sketch callback function when AutoConnectAux page requested. */ AuxHandlerFunctionT _handler; /**< User sketch callback function when AutoConnectAux page requested. */
static const char _PAGE_AUX[] PROGMEM; /**< Auxiliary page template */ static const char _PAGE_AUX[] PROGMEM; /**< Auxiliary page template */

@ -138,6 +138,9 @@ const char AutoConnect::_CSS_INPUT_BUTTON[] PROGMEM = {
"border-color:#1b5e20;" "border-color:#1b5e20;"
"width:16em;" "width:16em;"
"}" "}"
".aux-page input[type=\"button\"]{"
"width:auto;"
"}"
"input#sb[type=\"submit\"]{" "input#sb[type=\"submit\"]{"
"width:16em;" "width:16em;"
"}" "}"
@ -146,7 +149,7 @@ const char AutoConnect::_CSS_INPUT_BUTTON[] PROGMEM = {
"border-color:#006064;" "border-color:#006064;"
"}" "}"
"input[type=\"button\"], input[type=\"submit\"]:focus," "input[type=\"button\"], input[type=\"submit\"]:focus,"
"input[type=\"button\"], input[type=\"submit\"]:active {" "input[type=\"button\"], input[type=\"submit\"]:active{"
"outline:none;" "outline:none;"
"text-decoration:none;" "text-decoration:none;"
"}" "}"
@ -154,15 +157,17 @@ const char AutoConnect::_CSS_INPUT_BUTTON[] PROGMEM = {
/**< INPUT text style */ /**< INPUT text style */
const char AutoConnect::_CSS_INPUT_TEXT[] PROGMEM = { const char AutoConnect::_CSS_INPUT_TEXT[] PROGMEM = {
"input[type=\"text\"], input[type=\"password\"]{" "input[type=\"text\"], input[type=\"password\"], .aux-page select{"
"background-color:#fff;" "background-color:#fff;"
"padding:10px;"
"border:1px solid #ccc;" "border:1px solid #ccc;"
"margin:8px 0 8px 0;"
"width:calc(100% - 124px);"
"border-radius:2px;" "border-radius:2px;"
"font-weight:300;"
"color:#444;" "color:#444;"
"margin:8px 0 8px 0;"
"padding:10px;"
"}"
"input[type=\"text\"], input[type=\"password\"]{"
"font-weight:300;"
"width:calc(100% - 124px);"
"-webkit-transition:all 0.20s ease-in;" "-webkit-transition:all 0.20s ease-in;"
"-moz-transition:all 0.20s ease-in;" "-moz-transition:all 0.20s ease-in;"
"-o-transition:all 0.20s ease-in;" "-o-transition:all 0.20s ease-in;"
@ -198,6 +203,9 @@ const char AutoConnect::_CSS_INPUT_TEXT[] PROGMEM = {
"input.error:-ms-input-placeholder{" "input.error:-ms-input-placeholder{"
"color:#D9434E;" "color:#D9434E;"
"}" "}"
".aux-page label{"
"padding:10px 0.5em;"
"}"
}; };
/**< TABLE style */ /**< TABLE style */
@ -463,6 +471,9 @@ const char AutoConnect::_ELM_MENU_PRE[] PROGMEM = {
"</li>" "</li>"
"<li class=\"luxbar-item\"><a href=\"" AUTOCONNECT_URI_CONFIG "\">Configure new AP</a></li>" "<li class=\"luxbar-item\"><a href=\"" AUTOCONNECT_URI_CONFIG "\">Configure new AP</a></li>"
"<li class=\"luxbar-item\"><a href=\"" AUTOCONNECT_URI_OPEN "\">Open SSIDs</a></li>" "<li class=\"luxbar-item\"><a href=\"" AUTOCONNECT_URI_OPEN "\">Open SSIDs</a></li>"
"<li class=\"luxbar-item\"><a href=\"" AUTOCONNECT_URI_DISCON "\">Disconnect</a></li>"
"<li class=\"luxbar-item\" id=\"reset\"><a href=\"#rdlg\">Reset...</a></li>"
"<li class=\"luxbar-item\"><a href=\"HOME_URI\">HOME</a></li>"
}; };
const char AutoConnect::_ELM_MENU_AUX[] PROGMEM = { const char AutoConnect::_ELM_MENU_AUX[] PROGMEM = {
@ -470,9 +481,6 @@ const char AutoConnect::_ELM_MENU_AUX[] PROGMEM = {
}; };
const char AutoConnect::_ELM_MENU_POST[] PROGMEM = { const char AutoConnect::_ELM_MENU_POST[] PROGMEM = {
"<li class=\"luxbar-item\"><a href=\"" AUTOCONNECT_URI_DISCON "\">Disconnect</a></li>"
"<li class=\"luxbar-item\" id=\"reset\"><a href=\"#rdlg\">Reset...</a></li>"
"<li class=\"luxbar-item\"><a href=\"HOME_URI\">HOME</a></li>"
"</ul>" "</ul>"
"</div>" "</div>"
"<div class=\"lap\" id=\"rdlg\"><a href=\"#reset\" class=\"overlap\"></a>" "<div class=\"lap\" id=\"rdlg\"><a href=\"#reset\" class=\"overlap\"></a>"
@ -770,33 +778,41 @@ uint32_t AutoConnect::_getFlashChipRealSize() {
} }
String AutoConnect::_token_CSS_BASE(PageArgument& args) { String AutoConnect::_token_CSS_BASE(PageArgument& args) {
AC_UNUSED(args);
return String(_CSS_BASE); return String(_CSS_BASE);
} }
String AutoConnect::_token_CSS_UL(PageArgument& args) { String AutoConnect::_token_CSS_UL(PageArgument& args) {
AC_UNUSED(args);
return String(_CSS_UL); return String(_CSS_UL);
} }
String AutoConnect::_token_CSS_ICON_LOCK(PageArgument& args) { String AutoConnect::_token_CSS_ICON_LOCK(PageArgument& args) {
AC_UNUSED(args);
return String(_CSS_ICON_LOCK); return String(_CSS_ICON_LOCK);
} }
String AutoConnect::_token_CSS_INPUT_BUTTON(PageArgument& args) { String AutoConnect::_token_CSS_INPUT_BUTTON(PageArgument& args) {
AC_UNUSED(args);
return String(_CSS_INPUT_BUTTON); return String(_CSS_INPUT_BUTTON);
} }
String AutoConnect::_token_CSS_INPUT_TEXT(PageArgument& args) { String AutoConnect::_token_CSS_INPUT_TEXT(PageArgument& args) {
AC_UNUSED(args);
return String(_CSS_INPUT_TEXT); return String(_CSS_INPUT_TEXT);
} }
String AutoConnect::_token_CSS_TABLE(PageArgument& args) { String AutoConnect::_token_CSS_TABLE(PageArgument& args) {
AC_UNUSED(args);
return String(_CSS_TABLE); return String(_CSS_TABLE);
} }
String AutoConnect::_token_HEAD(PageArgument& args) { String AutoConnect::_token_HEAD(PageArgument& args) {
AC_UNUSED(args);
return String(_ELM_HTML_HEAD); return String(_ELM_HTML_HEAD);
} }
String AutoConnect::_token_MENU_PRE(PageArgument& args) { String AutoConnect::_token_MENU_PRE(PageArgument& args) {
AC_UNUSED(args);
String currentMenu = String(_ELM_MENU_PRE); String currentMenu = String(_ELM_MENU_PRE);
currentMenu.replace(String("MENU_TITLE"), _menuTitle); currentMenu.replace(String("MENU_TITLE"), _menuTitle);
currentMenu.replace(String("HOME_URI"), _apConfig.homeUri); currentMenu.replace(String("HOME_URI"), _apConfig.homeUri);
@ -811,18 +827,22 @@ String AutoConnect::_token_MENU_AUX(PageArgument& args) {
} }
String AutoConnect::_token_MENU_POST(PageArgument& args) { String AutoConnect::_token_MENU_POST(PageArgument& args) {
AC_UNUSED(args);
return String(FPSTR(_ELM_MENU_POST)); return String(FPSTR(_ELM_MENU_POST));
} }
String AutoConnect::_token_CSS_LUXBAR(PageArgument& args) { String AutoConnect::_token_CSS_LUXBAR(PageArgument& args) {
AC_UNUSED(args);
return String(_CSS_LUXBAR); return String(_CSS_LUXBAR);
} }
String AutoConnect::_token_ESTAB_SSID(PageArgument& args) { String AutoConnect::_token_ESTAB_SSID(PageArgument& args) {
AC_UNUSED(args);
return (WiFi.status() == WL_CONNECTED ? WiFi.SSID() : String("N/A")); return (WiFi.status() == WL_CONNECTED ? WiFi.SSID() : String("N/A"));
} }
String AutoConnect::_token_WIFI_MODE(PageArgument& args) { String AutoConnect::_token_WIFI_MODE(PageArgument& args) {
AC_UNUSED(args);
const char* wifiMode = ""; const char* wifiMode = "";
switch (WiFi.getMode()) { switch (WiFi.getMode()) {
case WIFI_OFF: case WIFI_OFF:
@ -847,10 +867,12 @@ String AutoConnect::_token_WIFI_MODE(PageArgument& args) {
} }
String AutoConnect::_token_WIFI_STATUS(PageArgument& args) { String AutoConnect::_token_WIFI_STATUS(PageArgument& args) {
AC_UNUSED(args);
return String(WiFi.status()); return String(WiFi.status());
} }
String AutoConnect::_token_STATION_STATUS(PageArgument& args) { String AutoConnect::_token_STATION_STATUS(PageArgument& args) {
AC_UNUSED(args);
const char* wlStatusSymbol; const char* wlStatusSymbol;
static const char *wlStatusSymbols[] = { static const char *wlStatusSymbols[] = {
#if defined(ARDUINO_ARCH_ESP8266) #if defined(ARDUINO_ARCH_ESP8266)
@ -922,59 +944,72 @@ String AutoConnect::_token_STATION_STATUS(PageArgument& args) {
} }
String AutoConnect::_token_LOCAL_IP(PageArgument& args) { String AutoConnect::_token_LOCAL_IP(PageArgument& args) {
AC_UNUSED(args);
return WiFi.localIP().toString(); return WiFi.localIP().toString();
} }
String AutoConnect::_token_SOFTAP_IP(PageArgument& args) { String AutoConnect::_token_SOFTAP_IP(PageArgument& args) {
AC_UNUSED(args);
return WiFi.softAPIP().toString(); return WiFi.softAPIP().toString();
} }
String AutoConnect::_token_GATEWAY(PageArgument& args) { String AutoConnect::_token_GATEWAY(PageArgument& args) {
AC_UNUSED(args);
return WiFi.gatewayIP().toString(); return WiFi.gatewayIP().toString();
} }
String AutoConnect::_token_NETMASK(PageArgument& args) { String AutoConnect::_token_NETMASK(PageArgument& args) {
AC_UNUSED(args);
return WiFi.subnetMask().toString(); return WiFi.subnetMask().toString();
} }
String AutoConnect::_token_AP_MAC(PageArgument& args) { String AutoConnect::_token_AP_MAC(PageArgument& args) {
AC_UNUSED(args);
uint8_t macAddress[6]; uint8_t macAddress[6];
WiFi.softAPmacAddress(macAddress); WiFi.softAPmacAddress(macAddress);
return AutoConnect::_toMACAddressString(macAddress); return AutoConnect::_toMACAddressString(macAddress);
} }
String AutoConnect::_token_STA_MAC(PageArgument& args) { String AutoConnect::_token_STA_MAC(PageArgument& args) {
AC_UNUSED(args);
uint8_t macAddress[6]; uint8_t macAddress[6];
WiFi.macAddress(macAddress); WiFi.macAddress(macAddress);
return AutoConnect::_toMACAddressString(macAddress); return AutoConnect::_toMACAddressString(macAddress);
} }
String AutoConnect::_token_CHANNEL(PageArgument& args) { String AutoConnect::_token_CHANNEL(PageArgument& args) {
AC_UNUSED(args);
return String(WiFi.channel()); return String(WiFi.channel());
} }
String AutoConnect::_token_DBM(PageArgument& args) { String AutoConnect::_token_DBM(PageArgument& args) {
AC_UNUSED(args);
int32_t dBm = WiFi.RSSI(); int32_t dBm = WiFi.RSSI();
return (dBm == 31 ? String("N/A") : String(dBm)); return (dBm == 31 ? String("N/A") : String(dBm));
} }
String AutoConnect::_token_CPU_FREQ(PageArgument& args) { String AutoConnect::_token_CPU_FREQ(PageArgument& args) {
AC_UNUSED(args);
return String(ESP.getCpuFreqMHz()); return String(ESP.getCpuFreqMHz());
} }
String AutoConnect::_token_FLASH_SIZE(PageArgument& args) { String AutoConnect::_token_FLASH_SIZE(PageArgument& args) {
AC_UNUSED(args);
return String(_getFlashChipRealSize()); return String(_getFlashChipRealSize());
} }
String AutoConnect::_token_CHIP_ID(PageArgument& args) { String AutoConnect::_token_CHIP_ID(PageArgument& args) {
AC_UNUSED(args);
return String(_getChipId()); return String(_getChipId());
} }
String AutoConnect::_token_FREE_HEAP(PageArgument& args) { String AutoConnect::_token_FREE_HEAP(PageArgument& args) {
AC_UNUSED(args);
return String(ESP.getFreeHeap()); return String(ESP.getFreeHeap());
} }
String AutoConnect::_token_LIST_SSID(PageArgument& args) { String AutoConnect::_token_LIST_SSID(PageArgument& args) {
AC_UNUSED(args);
String ssidList = ""; String ssidList = "";
_hiddenSSIDCount = 0; _hiddenSSIDCount = 0;
int8_t nn = WiFi.scanNetworks(false, true); int8_t nn = WiFi.scanNetworks(false, true);
@ -994,10 +1029,12 @@ String AutoConnect::_token_LIST_SSID(PageArgument& args) {
} }
String AutoConnect::_token_HIDDEN_COUNT(PageArgument& args) { String AutoConnect::_token_HIDDEN_COUNT(PageArgument& args) {
AC_UNUSED(args);
return String(_hiddenSSIDCount); return String(_hiddenSSIDCount);
} }
String AutoConnect::_token_OPEN_SSID(PageArgument& args) { String AutoConnect::_token_OPEN_SSID(PageArgument& args) {
AC_UNUSED(args);
AutoConnectCredential credit(_apConfig.boundaryOffset); AutoConnectCredential credit(_apConfig.boundaryOffset);
struct station_config entry; struct station_config entry;
String ssidList; String ssidList;
@ -1031,6 +1068,7 @@ String AutoConnect::_token_OPEN_SSID(PageArgument& args) {
} }
String AutoConnect::_token_UPTIME(PageArgument& args) { String AutoConnect::_token_UPTIME(PageArgument& args) {
AC_UNUSED(args);
return String(_apConfig.uptime); return String(_apConfig.uptime);
} }

Loading…
Cancel
Save