Supports AutoConnectAux

pull/41/head
Hieromon Ikasamo 6 years ago
parent 51d5537477
commit cfa63c531e
  1. 3
      .gitignore
  2. 4
      README.md
  3. 11
      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
*.vcxproj
*.vcxproj.filters
.pioenvs
.piolibdeps
*.vcxitems

@ -91,8 +91,10 @@ Full documentation is available on https://Hieromon.github.io/AutoConnect, some
### [0.9.7] Dec. 11, 2018
- 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 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```.
### [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.
WiFi.softAPdisconnect(true);
WiFi.enableAP(false);
_disconnectWiFi(false);
WiFi.mode(WIFI_STA);
delay(100);
@ -124,8 +123,10 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long
// Try to connect by STA immediately.
if (ssid == nullptr && passphrase == nullptr)
WiFi.begin();
else
else {
_disconnectWiFi(false);
WiFi.begin(ssid, passphrase);
}
AC_DBG("WiFi.begin(%s%s%s)\n", ssid == nullptr ? "" : ssid, passphrase == nullptr ? "" : ",", passphrase == nullptr ? "" : passphrase);
cs = _waitForConnect(_portalTimeout) == WL_CONNECTED;
}
@ -284,13 +285,14 @@ WebServerClass& AutoConnect::host() {
* @param aux A reference to AutoConnectAux that made up
* the auxiliary page to be added.
*/
void AutoConnect::join(AutoConnectAux& aux) {
bool AutoConnect::join(AutoConnectAux& aux) {
if (_aux)
_aux->_concat(aux);
else
_aux.reset(&aux);
aux._join(*this);
AC_DBG("%s on hands\n", aux.uri());
return true;
}
/**
@ -298,11 +300,12 @@ void AutoConnect::join(AutoConnectAux& aux) {
* @param aux A vector of reference to AutoConnectAux that made up
* 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++) {
AutoConnectAux& addon = aux[n].get();
join(addon);
}
return true;
}
/**

@ -39,6 +39,11 @@ typedef enum AC_SAVECREDENTIAL {
AC_SAVECREDENTIAL_AUTO
} AC_SAVECREDENTIAL_t;
typedef enum AC_URIONBOOT {
AC_URIONBOOT_ROOT,
AC_URIONBOOT_HOME
} AC_URIONBOOT_t;
class AutoConnectConfig {
public:
/**
@ -55,6 +60,7 @@ class AutoConnectConfig {
channel(AUTOCONNECT_AP_CH),
hidden(0),
autoSave(AC_SAVECREDENTIAL_AUTO),
bootUri(AC_URIONBOOT_ROOT),
boundaryOffset(AC_IDENTIFIER_OFFSET),
uptime(AUTOCONNECT_STARTUPTIME),
autoRise(true),
@ -79,6 +85,7 @@ class AutoConnectConfig {
channel(channel),
hidden(0),
autoSave(AC_SAVECREDENTIAL_AUTO),
bootUri(AC_URIONBOOT_ROOT),
boundaryOffset(AC_IDENTIFIER_OFFSET),
uptime(AUTOCONNECT_STARTUPTIME),
autoRise(true),
@ -103,6 +110,7 @@ class AutoConnectConfig {
channel = o.channel;
hidden = o.hidden;
autoSave = o.autoSave;
bootUri = o.bootUri;
boundaryOffset = o.boundaryOffset;
uptime = o.uptime;
autoRise = o.autoRise;
@ -126,6 +134,7 @@ class AutoConnectConfig {
uint8_t channel; /**< SoftAP used wifi channel */
uint8_t hidden; /**< SoftAP SSID hidden */
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 */
int uptime; /**< Length of start up time */
bool autoRise; /**< Automatic starting the captive portal */
@ -154,8 +163,16 @@ class AutoConnect {
void handleClient();
void handleRequest();
WebServerClass& host();
void join(AutoConnectAux& aux);
void join(std::vector<std::reference_wrapper<AutoConnectAux>> aux);
bool join(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;
void onDetect(DetectExit_ft fn);
@ -283,6 +300,7 @@ class AutoConnect {
String _token_HIDDEN_COUNT(PageArgument& args);
String _token_OPEN_SSID(PageArgument& args);
String _token_UPTIME(PageArgument& args);
String _token_BOOTURI(PageArgument& args);
#if defined(ARDUINO_ARCH_ESP8266)
friend class ESP8266WebServer;

@ -234,6 +234,98 @@ const String AutoConnectAux::_injectMenu(PageArgument& args) {
#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.
* @param json A reference of JSON

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

@ -511,7 +511,7 @@ const char AutoConnect::_PAGE_404[] PROGMEM = {
/**< The page that started the reset. */
const char AutoConnect::_PAGE_RESETTING[] PROGMEM = {
"{{HEAD}}"
"<meta http-equiv=\"refresh\" content=\"{{UPTIME}};URL=" AUTOCONNECT_URI "\">"
"<meta http-equiv=\"refresh\" content=\"{{UPTIME}};URL={{BOOTURI}}\">"
"<title>AutoConnect resetting</title>"
"</head>"
"<body>"
@ -1081,6 +1081,17 @@ String AutoConnect::_token_UPTIME(PageArgument& args) {
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
* the requested URI. A PageBuilder instance is stored in _rensponsePage
@ -1178,6 +1189,7 @@ PageElement* AutoConnect::_setupPage(String uri) {
// Setup /auto/reset
elm->setMold(_PAGE_RESETTING);
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("RESET"), std::bind(&AutoConnect::_induceReset, this, std::placeholders::_1));

Loading…
Cancel
Save