Supports AutoConnectAux

pull/41/head
Hieromon Ikasamo 5 years ago
parent 51d5537477
commit cfa63c531e
  1. 3
      .gitignore
  2. 4
      README.md
  3. 19
      src/AutoConnect.cpp
  4. 22
      src/AutoConnect.h
  5. 92
      src/AutoConnectAux.cpp
  6. 34
      src/AutoConnectAux.h
  7. 14
      src/AutoConnectPage.cpp

3
.gitignore vendored

@ -9,5 +9,4 @@ img/
*.sln *.sln
*.vcxproj *.vcxproj
*.vcxproj.filters *.vcxproj.filters
.pioenvs *.vcxitems
.piolibdeps

@ -91,8 +91,10 @@ Full documentation is available on https://Hieromon.github.io/AutoConnect, some
### [0.9.7] Dec. 11, 2018 ### [0.9.7] Dec. 11, 2018
- Supports AutoConnect menu extention by user sketch with **AutoConnectAux** implementation that attached **AutoConnectElement**. - Supports AutoConnect menu extention by user sketch with **AutoConnectAux** implementation that attached **AutoConnectElement**.
- Improved the WiFi connection sequence at the first WiFi.begin. Even if **AutoConnectConfig::autoReconnect** is disabled when SSID and PSK are not specified, it will use the information of the last established access point. The autoReconnect option will achieve trying the connect after a previous connection failed.
- Supports loading and saving of user-defined parameters with JSON format. - 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 boot uri after reset. **AutoConnectConfig::bootUri** can be specified either /_ac or HOME path as the uri to be accessed after invoking Reset from AutoConnect menu.
- Improved source code placement of predefined macros. Defined common macros have been moved to ```AutoConnectDefs.h```. - Improved source code placement of predefined macros. Defined common macros have been moved to ```AutoConnectDefs.h```.
### [0.9.6] Sept. 27, 2018 ### [0.9.6] Sept. 27, 2018

@ -91,7 +91,6 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long
// Start WiFi connection with station mode. // Start WiFi connection with station mode.
WiFi.softAPdisconnect(true); WiFi.softAPdisconnect(true);
WiFi.enableAP(false); WiFi.enableAP(false);
_disconnectWiFi(false);
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
delay(100); delay(100);
@ -124,8 +123,10 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long
// Try to connect by STA immediately. // Try to connect by STA immediately.
if (ssid == nullptr && passphrase == nullptr) if (ssid == nullptr && passphrase == nullptr)
WiFi.begin(); WiFi.begin();
else else {
_disconnectWiFi(false);
WiFi.begin(ssid, passphrase); WiFi.begin(ssid, passphrase);
}
AC_DBG("WiFi.begin(%s%s%s)\n", ssid == nullptr ? "" : ssid, passphrase == nullptr ? "" : ",", passphrase == nullptr ? "" : passphrase); AC_DBG("WiFi.begin(%s%s%s)\n", ssid == nullptr ? "" : ssid, passphrase == nullptr ? "" : ",", passphrase == nullptr ? "" : passphrase);
cs = _waitForConnect(_portalTimeout) == WL_CONNECTED; cs = _waitForConnect(_portalTimeout) == WL_CONNECTED;
} }
@ -284,25 +285,27 @@ WebServerClass& AutoConnect::host() {
* @param aux A reference to AutoConnectAux that made up * @param aux A reference to AutoConnectAux that made up
* the auxiliary page to be added. * the auxiliary page to be added.
*/ */
void AutoConnect::join(AutoConnectAux& aux) { bool AutoConnect::join(AutoConnectAux& aux) {
if (_aux) if (_aux)
_aux->_concat(aux); _aux->_concat(aux);
else else
_aux.reset(&aux); _aux.reset(&aux);
aux._join(*this); aux._join(*this);
AC_DBG("%s on hands\n", aux.uri()); AC_DBG("%s on hands\n", aux.uri());
return true;
} }
/** /**
* Append auxiliary pages made up with AutoConnectAux. * Append auxiliary pages made up with AutoConnectAux.
* @param aux A vector of reference to AutoConnectAux that made up * @param aux A vector of reference to AutoConnectAux that made up
* the auxiliary page to be added. * the auxiliary page to be added.
*/ */
void AutoConnect::join(std::vector<std::reference_wrapper<AutoConnectAux>> aux) { bool 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].get(); AutoConnectAux& addon = aux[n].get();
join(addon); join(addon);
} }
return true;
} }
/** /**

@ -39,6 +39,11 @@ typedef enum AC_SAVECREDENTIAL {
AC_SAVECREDENTIAL_AUTO AC_SAVECREDENTIAL_AUTO
} AC_SAVECREDENTIAL_t; } AC_SAVECREDENTIAL_t;
typedef enum AC_URIONBOOT {
AC_URIONBOOT_ROOT,
AC_URIONBOOT_HOME
} AC_URIONBOOT_t;
class AutoConnectConfig { class AutoConnectConfig {
public: public:
/** /**
@ -55,6 +60,7 @@ class AutoConnectConfig {
channel(AUTOCONNECT_AP_CH), channel(AUTOCONNECT_AP_CH),
hidden(0), hidden(0),
autoSave(AC_SAVECREDENTIAL_AUTO), autoSave(AC_SAVECREDENTIAL_AUTO),
bootUri(AC_URIONBOOT_ROOT),
boundaryOffset(AC_IDENTIFIER_OFFSET), boundaryOffset(AC_IDENTIFIER_OFFSET),
uptime(AUTOCONNECT_STARTUPTIME), uptime(AUTOCONNECT_STARTUPTIME),
autoRise(true), autoRise(true),
@ -79,6 +85,7 @@ class AutoConnectConfig {
channel(channel), channel(channel),
hidden(0), hidden(0),
autoSave(AC_SAVECREDENTIAL_AUTO), autoSave(AC_SAVECREDENTIAL_AUTO),
bootUri(AC_URIONBOOT_ROOT),
boundaryOffset(AC_IDENTIFIER_OFFSET), boundaryOffset(AC_IDENTIFIER_OFFSET),
uptime(AUTOCONNECT_STARTUPTIME), uptime(AUTOCONNECT_STARTUPTIME),
autoRise(true), autoRise(true),
@ -103,6 +110,7 @@ class AutoConnectConfig {
channel = o.channel; channel = o.channel;
hidden = o.hidden; hidden = o.hidden;
autoSave = o.autoSave; autoSave = o.autoSave;
bootUri = o.bootUri;
boundaryOffset = o.boundaryOffset; boundaryOffset = o.boundaryOffset;
uptime = o.uptime; uptime = o.uptime;
autoRise = o.autoRise; autoRise = o.autoRise;
@ -126,6 +134,7 @@ class AutoConnectConfig {
uint8_t channel; /**< SoftAP used wifi channel */ uint8_t channel; /**< SoftAP used wifi channel */
uint8_t hidden; /**< SoftAP SSID hidden */ uint8_t hidden; /**< SoftAP SSID hidden */
AC_SAVECREDENTIAL_t autoSave; /**< Auto save credential */ AC_SAVECREDENTIAL_t autoSave; /**< Auto save credential */
AC_URIONBOOT_t bootUri; /**< An uri invoking after reset */
uint16_t boundaryOffset; /**< The save storage offset of EEPROM */ uint16_t boundaryOffset; /**< The save storage offset of EEPROM */
int uptime; /**< Length of start up time */ int uptime; /**< Length of start up time */
bool autoRise; /**< Automatic starting the captive portal */ bool autoRise; /**< Automatic starting the captive portal */
@ -154,8 +163,16 @@ class AutoConnect {
void handleClient(); void handleClient();
void handleRequest(); void handleRequest();
WebServerClass& host(); WebServerClass& host();
void join(AutoConnectAux& aux); bool join(AutoConnectAux& aux);
void join(std::vector<std::reference_wrapper<AutoConnectAux>> aux); bool join(std::vector<std::reference_wrapper<AutoConnectAux>> aux);
/** For AutoConnectAux described in JSON */
#ifdef AUTOCONNECT_USE_JSON
bool join(const char* aux);
bool join(const __FlashStringHelper* aux);
bool join(Stream& aux, size_t bufferSize = AUTOCONNECT_JSON_BUFFER_SIZE);
bool _load(JsonVariant& aux);
#endif
typedef std::function<bool(IPAddress)> DetectExit_ft; typedef std::function<bool(IPAddress)> DetectExit_ft;
void onDetect(DetectExit_ft fn); void onDetect(DetectExit_ft fn);
@ -283,6 +300,7 @@ class AutoConnect {
String _token_HIDDEN_COUNT(PageArgument& args); String _token_HIDDEN_COUNT(PageArgument& args);
String _token_OPEN_SSID(PageArgument& args); String _token_OPEN_SSID(PageArgument& args);
String _token_UPTIME(PageArgument& args); String _token_UPTIME(PageArgument& args);
String _token_BOOTURI(PageArgument& args);
#if defined(ARDUINO_ARCH_ESP8266) #if defined(ARDUINO_ARCH_ESP8266)
friend class ESP8266WebServer; friend class ESP8266WebServer;

@ -234,6 +234,98 @@ const String AutoConnectAux::_injectMenu(PageArgument& args) {
#ifdef AUTOCONNECT_USE_JSON #ifdef AUTOCONNECT_USE_JSON
/**
* Static storage for JSON buffer size calculation.
*/
int16_t AutoConnectAux::_jbSize; /**< JSON dynamic buffer size */
uint16_t AutoConnectAux::_jbByte; /**< Byte count for calculation of JSON buffer */
uint8_t AutoConnectAux::_jbObject; /**< Object count for calculation of JSON buffer */
uint8_t AutoConnectAux::_jbArray; /**< Array count for calculation of JSON buffer */
uint8_t AutoConnectAux::_jbNest; /**< JSON array nest count */
uint8_t AutoConnectAux::_kStack[AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH]; /**< JSON array counter stack */
uint8_t AutoConnectAux::_nStack[AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH]; /**< JSON object counter stack */
int8_t AutoConnectAux::_kp; /**< Stack pointer for JSON array counter */
int8_t AutoConnectAux::_np; /**< Stack pointer for JSON object counter */
bool AutoConnectAux::_jbOpen; /**< JSON object paring status */
bool AutoConnectAux::_jbLiteral; /**< JSON object lexical status */
/**
* Load AutoConnectAux page from JSON description stored in the sketch.
* This function can load AutoConnectAux for multiple AUX pages written
* in JSON and is registered in AutoConnect.
* @param aux JSON description to be load.
* @return true Successfully loaded.
*/
bool AutoConnect::join(const char* aux) {
const size_t bufferSize = AutoConnectAux::_calcJsonBufferSize(aux);
DynamicJsonBuffer jsonBuffer(bufferSize);
JsonVariant jv = jsonBuffer.parse(aux);
return _load(jv);
}
/**
* Load AutoConnectAux page from JSON description stored in PROGMEM.
* This function can load AutoConnectAux for multiple AUX pages written
* in JSON and is registered in AutoConnect.
* @param aux JSON description to be load.
* @return true Successfully loaded.
*/
bool AutoConnect::join(const __FlashStringHelper* aux) {
const size_t bufferSize = AutoConnectAux::_calcJsonBufferSize(aux);
DynamicJsonBuffer jsonBuffer(bufferSize);
JsonVariant jv = jsonBuffer.parse(aux);
return _load(jv);
}
/**
* Load AutoConnectAux page from JSON description from the stream.
* This function can load AutoConnectAux for multiple AUX pages written
* in JSON and is registered in AutoConnect.
* @param aux Stream for read AutoConnectAux elements.
* @return true Successfully loaded.
*/
bool AutoConnect::join(Stream& aux, size_t bufferSize) {
DynamicJsonBuffer jsonBuffer(bufferSize);
JsonVariant jv = jsonBuffer.parse(aux);
return _load(jv);
}
/**
* Load AutoConnectAux page from JSON object.
* @param aux A JsonVariant object that stores each element of AutoConnectAuxl.
* @return true Successfully loaded.
*/
bool AutoConnect::_load(JsonVariant& aux) {
bool rc = true;
if (aux.success()) {
if (aux.is<JsonArray>()) {
JsonArray& jb = aux.as<JsonArray>();
for (JsonObject& auxJson : jb) {
AutoConnectAux* newAux = new AutoConnectAux;
if (newAux->_load(auxJson))
join(*newAux);
else {
delete newAux;
rc = false;
break;
}
}
}
else {
JsonObject& jb = aux.as<JsonObject>();
AutoConnectAux* newAux = new AutoConnectAux;
if (newAux->_load(jb))
join(*newAux);
else {
delete newAux;
rc = false;
}
}
}
else
return rc;
}
/** /**
* Create an instance from the AutoConnectElement of the JSON object. * Create an instance from the AutoConnectElement of the JSON object.
* @param json A reference of JSON * @param json A reference of JSON

@ -101,23 +101,23 @@ class AutoConnectAux : public PageBuilder {
friend class AutoConnect; friend class AutoConnect;
private: private:
size_t _calcJsonBufferSize(const char* in); /**< Calculate JSON buffer size for constant character array */ static size_t _calcJsonBufferSize(const char* in); /**< Calculate JSON buffer size for constant character array */
size_t _calcJsonBufferSize(const __FlashStringHelper* in); /**< Calculate JSON buffer size for pgm_data */ static size_t _calcJsonBufferSize(const __FlashStringHelper* in); /**< Calculate JSON buffer size for pgm_data */
void _initJsonBufferSize(void); /**< Initialize the stacks for JSON Dynamic buffer size calculation */ static void _initJsonBufferSize(void); /**< Initialize the stacks for JSON Dynamic buffer size calculation */
void _accJsonBufferSize(const char c); /**< Accumulate JSON Dynamic buffer size */ static void _accJsonBufferSize(const char c); /**< Accumulate JSON Dynamic buffer size */
size_t _resultJsonBufferSize(void); /**< Retrieve accumulated result value */ static size_t _resultJsonBufferSize(void); /**< Retrieve accumulated result value */
int16_t _jbSize; /**< JSON dynamic buffer size */ static int16_t _jbSize; /**< JSON dynamic buffer size */
uint16_t _jbByte; /**< Byte count for calculation of JSON buffer */ static uint16_t _jbByte; /**< Byte count for calculation of JSON buffer */
uint8_t _jbObject; /**< Object count for calculation of JSON buffer */ static uint8_t _jbObject; /**< Object count for calculation of JSON buffer */
uint8_t _jbArray; /**< Array count for calculation of JSON buffer */ static uint8_t _jbArray; /**< Array count for calculation of JSON buffer */
uint8_t _jbNest; /**< JSON array nest count */ static uint8_t _jbNest; /**< JSON array nest count */
uint8_t _kStack[AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH]; /**< JSON array counter stack */ static uint8_t _kStack[AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH]; /**< JSON array counter stack */
uint8_t _nStack[AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH]; /**< JSON object counter stack */ static uint8_t _nStack[AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH]; /**< JSON object counter stack */
int8_t _kp; /**< Stack pointer for JSON array counter */ static int8_t _kp; /**< Stack pointer for JSON array counter */
int8_t _np; /**< Stack pointer for JSON object counter */ static int8_t _np; /**< Stack pointer for JSON object counter */
bool _jbOpen; /**< JSON object paring status */ static bool _jbOpen; /**< JSON object paring status */
bool _jbLiteral; /**< JSON object lexical status */ static bool _jbLiteral; /**< JSON object lexical status */
}; };
#endif // _AUTOCONNECTAUX_H_ #endif // _AUTOCONNECTAUX_H_

@ -511,7 +511,7 @@ const char AutoConnect::_PAGE_404[] PROGMEM = {
/**< The page that started the reset. */ /**< The page that started the reset. */
const char AutoConnect::_PAGE_RESETTING[] PROGMEM = { const char AutoConnect::_PAGE_RESETTING[] PROGMEM = {
"{{HEAD}}" "{{HEAD}}"
"<meta http-equiv=\"refresh\" content=\"{{UPTIME}};URL=" AUTOCONNECT_URI "\">" "<meta http-equiv=\"refresh\" content=\"{{UPTIME}};URL={{BOOTURI}}\">"
"<title>AutoConnect resetting</title>" "<title>AutoConnect resetting</title>"
"</head>" "</head>"
"<body>" "<body>"
@ -1081,6 +1081,17 @@ String AutoConnect::_token_UPTIME(PageArgument& args) {
return String(_apConfig.uptime); return String(_apConfig.uptime);
} }
String AutoConnect::_token_BOOTURI(PageArgument& args) {
AC_UNUSED(args);
if (_apConfig.bootUri == AC_URIONBOOT_ROOT)
return String(AUTOCONNECT_URI);
else if (_apConfig.bootUri == AC_URIONBOOT_HOME)
return _apConfig.homeUri.length() > 0 ? _apConfig.homeUri : String("/");
else
return "";
}
/** /**
* This function dynamically build up the response pages that conform to * This function dynamically build up the response pages that conform to
* the requested URI. A PageBuilder instance is stored in _rensponsePage * the requested URI. A PageBuilder instance is stored in _rensponsePage
@ -1178,6 +1189,7 @@ PageElement* AutoConnect::_setupPage(String uri) {
// Setup /auto/reset // Setup /auto/reset
elm->setMold(_PAGE_RESETTING); elm->setMold(_PAGE_RESETTING);
elm->addToken(PSTR("HEAD"), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); elm->addToken(PSTR("HEAD"), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1));
elm->addToken(PSTR("BOOTURI"), std::bind(&AutoConnect::_token_BOOTURI, this, std::placeholders::_1));
elm->addToken(PSTR("UPTIME"), std::bind(&AutoConnect::_token_UPTIME, this, std::placeholders::_1)); elm->addToken(PSTR("UPTIME"), std::bind(&AutoConnect::_token_UPTIME, this, std::placeholders::_1));
elm->addToken(PSTR("RESET"), std::bind(&AutoConnect::_induceReset, this, std::placeholders::_1)); elm->addToken(PSTR("RESET"), std::bind(&AutoConnect::_induceReset, this, std::placeholders::_1));

Loading…
Cancel
Save