diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index 294c9f0..de76fda 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -3,7 +3,7 @@ * @file AutoConnect.cpp * @author hieromon@gmail.com * @version 0.9.7 - * @date 2018-11-17 + * @date 2019-01-21 * @copyright MIT license. */ @@ -51,9 +51,12 @@ void AutoConnect::_initialize() { _rfReset = false; _responsePage = nullptr; _currentPageElement = nullptr; - _menuTitle = String(AUTOCONNECT_MENU_TITLE); + _menuTitle = String(F(AUTOCONNECT_MENU_TITLE)); _connectTimeout = AUTOCONNECT_TIMEOUT; memset(&_credential, 0x00, sizeof(struct station_config)); +#ifdef ARDUINO_ARCH_ESP32 + _disconnectEventId = -1; // The member available for ESP32 only +#endif _aux.release(); } @@ -81,12 +84,11 @@ bool AutoConnect::begin() { * @param ssid SSID to be connected. * @param passphrase Password for connection. * @param timeout A time out value in milliseconds for waiting connection. - * @retval true Connection established, AutoConnect service started with WIFI_STA mode. - * @retval false Could not connected, Captive portal started with WIFI_AP_STA mode. + * @return true Connection established, AutoConnect service started with WIFI_STA mode. + * @return false Could not connected, Captive portal started with WIFI_AP_STA mode. */ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long timeout) { bool cs; - bool hasTimeout; // Overwrite for the current timeout value. _connectTimeout = timeout; @@ -166,8 +168,10 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long // Activate the AP mode with configured softAP and start the access point. WiFi.mode(WIFI_AP_STA); - while (WiFi.getMode() != WIFI_AP_STA) + while (WiFi.getMode() != WIFI_AP_STA) { + delay(1); yield(); + } // Connection unsuccessful, launch the captive portal. #if defined(ARDUINO_ARCH_ESP8266) @@ -176,15 +180,21 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long } #endif WiFi.softAP(_apConfig.apid.c_str(), _apConfig.psk.c_str(), _apConfig.channel, _apConfig.hidden); - while (WiFi.softAPIP() == IPAddress(0, 0, 0, 0)) { + do { delay(100); yield(); - } + } while (WiFi.softAPIP() == IPAddress(0, 0, 0, 0)); #if defined(ARDUINO_ARCH_ESP32) if (!(_apConfig.apip == IPAddress(0, 0, 0, 0) || _apConfig.gateway == IPAddress(0, 0, 0, 0) || _apConfig.netmask == IPAddress(0, 0, 0, 0))) { _config(); } #endif + if (_apConfig.apip != IPAddress(0, 0, 0, 0)) { + do { + delay(100); + yield(); + } while (WiFi.softAPIP() != _apConfig.apip); + } _currentHostIP = WiFi.softAPIP(); AC_DBG("SoftAP %s/%s CH(%d) H(%d) IP:%s\n", _apConfig.apid.c_str(), _apConfig.psk.c_str(), _apConfig.channel, _apConfig.hidden, _currentHostIP.toString().c_str()); @@ -201,15 +211,14 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long _startDNSServer(); // Start the captive portal to make a new connection - hasTimeout = false; + bool hasTimeout = false; _portalAccessPeriod = millis(); while (WiFi.status() != WL_CONNECTED && !_rfReset) { handleClient(); // Force execution of queued processes. yield(); // Check timeout - if (_hasTimeout(_apConfig.portalTimeout)) { - hasTimeout = true; + if ((hasTimeout = _hasTimeout(_apConfig.portalTimeout))) { AC_DBG("CP timeout exceeded:%ld\n", millis() - _portalAccessPeriod); break; } @@ -220,6 +229,7 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long if (cs) { _dnsServer->stop(); _dnsServer.reset(); + AC_DBG("DNS server stopped\n"); } // Captive portal staying time exceeds timeout, // Close the portal if an option for keeping the portal is false. @@ -305,8 +315,10 @@ void AutoConnect::end() { if (_webServer) { switch (_webServerAlloc) { case AC_WEBSERVER_HOSTED: - if (_dnsServer) + if (_dnsServer) { + _dnsServer->stop(); _dnsServer.reset(); + } _webServer.reset(); break; case AC_WEBSERVER_PARASITIC: @@ -379,7 +391,7 @@ void AutoConnect::_startWebServer() { // here, Prepare PageBuilders for captive portal if (!_responsePage) { _responsePage = new PageBuilder(); - _responsePage->chunked(PB_ByteStream); + _responsePage->chunked(AUTOCONNECT_HTTP_TRANSFER); _responsePage->exitCanHandle(std::bind(&AutoConnect::_classifyHandle, this, std::placeholders::_1, std::placeholders::_2)); _responsePage->insert(*_webServer); @@ -428,8 +440,8 @@ void AutoConnect::handleRequest() { // Handling processing requests to AutoConnect. if (_rfConnect) { // Leave from the AP currently. -// if (WiFi.status() == WL_CONNECTED) -// _disconnectWiFi(true); + if (WiFi.status() == WL_CONNECTED) + _disconnectWiFi(true); // An attempt to establish a new AP. AC_DBG("Request for %s\n", reinterpret_cast(_credential.ssid)); @@ -438,7 +450,7 @@ void AutoConnect::handleRequest() { if (WiFi.BSSID() != NULL) { memcpy(_credential.bssid, WiFi.BSSID(), sizeof(station_config::bssid)); _currentHostIP = WiFi.localIP(); - _redirectURI = String(AUTOCONNECT_URI_SUCCESS); + _redirectURI = String(F(AUTOCONNECT_URI_SUCCESS)); // Save current credential if (_apConfig.autoSave == AC_SAVECREDENTIAL_AUTO) { @@ -446,17 +458,20 @@ void AutoConnect::handleRequest() { credit.save(&_credential); AC_DBG("%s credential saved\n", reinterpret_cast(_credential.ssid)); } + + // Ensures that keeps a connection with the current AP while the portal behaves. + _setReconnect(AC_RECONNECT_SET); } else AC_DBG("%s has no BSSID, saving is unavailable\n", reinterpret_cast(_credential.ssid)); } else { _currentHostIP = WiFi.softAPIP(); - _redirectURI = String(AUTOCONNECT_URI_FAIL); + _redirectURI = String(F(AUTOCONNECT_URI_FAIL)); _rsConnect = WiFi.status(); _disconnectWiFi(false); while (WiFi.status() != WL_IDLE_STATUS && WiFi.status() != WL_DISCONNECTED) { - delay(10); + delay(1); yield(); } } @@ -474,6 +489,7 @@ void AutoConnect::handleRequest() { if (_rfDisconnect) { // Disconnect from the current AP. + _waitForEndTransmission(); _stopPortal(); _disconnectWiFi(false); while (WiFi.status() == WL_CONNECTED) { @@ -533,7 +549,7 @@ void AutoConnect::onNotFound(WebServerClass::THandlerFunction fn) { /** * Load stored credentials that match nearby WLANs. - * @retval true A matched credential of BSSID was loaded. + * @return true A matched credential of BSSID was loaded. */ bool AutoConnect::_loadAvailCredential() { AutoConnectCredential credential(_apConfig.boundaryOffset); @@ -570,8 +586,9 @@ void AutoConnect::_stopPortal() { delay(1000); } + _setReconnect(AC_RECONNECT_RESET); WiFi.softAPdisconnect(false); - AC_DBG("SoftAP stopped\n"); + AC_DBG("Portal stopped\n"); } /** @@ -581,9 +598,9 @@ void AutoConnect::_stopPortal() { bool AutoConnect::_captivePortal() { String hostHeader = _webServer->hostHeader(); if (!_isIP(hostHeader) && (hostHeader != WiFi.localIP().toString())) { - String location = String("http://") + _webServer->client().localIP().toString() + String(AUTOCONNECT_URI); - _webServer->sendHeader("Location", location, true); - _webServer->send(302, "text/plain", ""); + String location = String(F("http://")) + _webServer->client().localIP().toString() + String(AUTOCONNECT_URI); + _webServer->sendHeader(F("Location"), location, true); + _webServer->send(302, F("text/plain"), ""); _webServer->client().flush(); _webServer->client().stop(); return true; @@ -593,6 +610,10 @@ bool AutoConnect::_captivePortal() { /** * Check whether the stay-time in the captive portal has a timeout. + * If the station is connected, the time measurement will be reset. + * @param timeout The time limit for keeping the captive portal. + * @return true There is no connection from the station even the time limit exceeds. + * @return false Connectionless duration has not exceeded yet. */ bool AutoConnect::_hasTimeout(unsigned long timeout) { uint8_t staNum; @@ -629,11 +650,11 @@ void AutoConnect::_handleNotFound() { else { PageElement page404(_PAGE_404, { { "HEAD", std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1) } }); String html = page404.build(); - _webServer->sendHeader("Cache-Control", "no-cache, no-store, must-revalidate", true); - _webServer->sendHeader("Pragma", "no-cache"); - _webServer->sendHeader("Expires", "-1"); - _webServer->sendHeader("Content-Length", String(html.length())); - _webServer->send(404, "text/html", html); + _webServer->sendHeader(F("Cache-Control"), F("no-cache, no-store, must-revalidate"), true); + _webServer->sendHeader(F("Pragma"), F("no-cache")); + _webServer->sendHeader(F("Expires"), F("-1")); + _webServer->sendHeader(F("Content-Length"), String(html.length())); + _webServer->send(404, F("text/html"), html); } } } @@ -645,7 +666,7 @@ void AutoConnect::_handleNotFound() { */ String AutoConnect::_induceReset(PageArgument& args) { _rfReset = true; - return String("Reset in progress..."); + return String(F("Reset in progress...")); } /** @@ -664,7 +685,7 @@ String AutoConnect::_induceDisconnect(PageArgument& args) { * handling of the current request by PageBuilder triggered by handleClient(). * If "Credential" exists in POST parameter, it reads from EEPROM. * @param args http request arguments. - * @retval A redirect response including "Location:" header. + * @return A redirect response including "Location:" header. */ String AutoConnect::_induceConnect(PageArgument& args) { // Retrieve credential from the post method content. @@ -675,7 +696,7 @@ String AutoConnect::_induceConnect(PageArgument& args) { credential.load(args.arg(AUTOCONNECT_PARAMID_CRED).c_str(), &entry); strncpy(reinterpret_cast(_credential.ssid), reinterpret_cast(entry.ssid), sizeof(_credential.ssid)); strncpy(reinterpret_cast(_credential.password), reinterpret_cast(entry.password), sizeof(_credential.password)); - AC_DBG("Credential loaded:%s %s\n", _credential.ssid, _credential.password); + AC_DBG("Credential loaded:%s\n", _credential.ssid); } else { // Credential had by the post parameter. @@ -686,16 +707,32 @@ String AutoConnect::_induceConnect(PageArgument& args) { // Turn on the trigger to start WiFi.begin(). _rfConnect = true; - // Redirect to waiting URI while executing connection request. - //_webServer->sendHeader("Location", String("http://") + _webServer->client().localIP().toString() + String(AUTOCONNECT_URI_RESULT), true); - String url = String("http://") + _webServer->client().localIP().toString() + String(AUTOCONNECT_URI_RESULT); - _webServer->sendHeader("Location", url, true); - //_webServer->sendHeader("Connection", "keep-alive"); - _webServer->send(302, "text/plain", ""); - _webServer->client().flush(); - _webServer->client().stop(); - _responsePage->cancel(); +// Since v0.9.7, the redirect method changed from a 302 response to the +// meta tag with refresh attribute. +// This approach for ESP32 makes an inefficient choice. The waiting +// procedure for a connection attempt should be the server side. Also, +// the proper value of waiting time until refreshing is unknown. But +// AutoConnect cannot avoid the following error as affairs stand now +// that occurs at connection establishment. +// [WiFiClient.cpp:463] connected(): Disconnected: RES: 0, ERR: 128 +// When connecting as a station, TCP reset caused by switching of the +// radio channel occurs. Although the Espressif's view is true. However, +// the actual TCP reset occurs not at the time of switching the channel. +// It occurs at the connection from the ESP32 to the AP is established +// and it is possible that TCP reset is occurring in other situations. +// So, it may not be the real cause. Client-origin redirects with HTML +// refresh depend on the behavior of the arduino-esp32 library. Thus, +// the implementations for redirects with HTML will continue until +// the arduino-esp32 core supports reconnection. + // Redirect to waiting URI while executing connection request. + // String url = String(F("http://")) + _webServer->client().localIP().toString() + String(AUTOCONNECT_URI_RESULT); + // _webServer->sendHeader(F("Location"), url, true); + // _webServer->send(302, F("text/plain"), ""); + // _webServer->client().stop(); + // _webServer->client().flush(); + // _waitForEndTransmission(); // Wait for response transmission complete + // _responsePage->cancel(); return String(""); } @@ -704,11 +741,25 @@ String AutoConnect::_induceConnect(PageArgument& args) { * A destination as _redirectURI is indicated by loop to establish connection. */ String AutoConnect::_invokeResult(PageArgument& args) { - String redirect = String("http://") + _currentHostIP.toString() + _redirectURI; - _webServer->sendHeader("Location", redirect, true); - _webServer->send(302, "text/plain", ""); - _webServer->client().flush(); + String redirect = String(F("http://")); + // The host address to which the connection result for ESP32 responds + // changed from v0.9.7. This change is a measure according to the + // implementation of the arduino-esp32 1.0.1 core. +#if defined(ARDUINO_ARCH_ESP32) + // In ESP32, the station IP address just established could not be reached. + redirect += _webServer->client().localIP().toString(); +#elif defined(ARDUINO_ARCH_ESP8266) + // In ESP8266, the host address that responds for the connection + // successful is the IP address of ESP8266 as a station. + // This is the specification as before. + redirect += _currentHostIP.toString(); +#endif + redirect += _redirectURI; + _webServer->sendHeader(F("Location"), redirect, true); + _webServer->send(302, F("text/plain"), ""); _webServer->client().stop(); + _webServer->client().flush(); + _waitForEndTransmission(); // Wait for response transmission complete _responsePage->cancel(); return String(""); } @@ -724,8 +775,8 @@ bool AutoConnect::_classifyHandle(HTTPMethod method, String uri) { _portalAccessPeriod = millis(); AC_DBG("Host:%s, URI:%s", _webServer->hostHeader().c_str(), uri.c_str()); - // When handleClient calls RequestHandler, the parsed http argument remains - // the previous request. + // When handleClient calls RequestHandler, the parsed http argument + // remains the previous request. // If the current request argument contains AutoConnectElement, it is // the form data of the AutoConnectAux page and with this timing save // the value of each element. @@ -796,7 +847,7 @@ bool AutoConnect::_isIP(String ipStr) { /** * Convert MAC address in uint8_t array to Sting XX:XX:XX:XX:XX:XX format. * @param mac Array of MAC address 6 bytes. - * @retval MAC address string in XX:XX:XX:XX:XX:XX format. + * @return MAC address string in XX:XX:XX:XX:XX:XX format. */ String AutoConnect::_toMACAddressString(const uint8_t mac[]) { String macAddr = String(""); @@ -813,7 +864,7 @@ String AutoConnect::_toMACAddressString(const uint8_t mac[]) { /** * Convert dBm to the wifi signal quality. * @param rssi dBm. - * @retval a signal quality percentage. + * @return A signal quality percentage. */ unsigned int AutoConnect::_toWiFiQuality(int32_t rssi) { unsigned int qu; @@ -831,7 +882,7 @@ unsigned int AutoConnect::_toWiFiQuality(int32_t rssi) { /** * Wait for establishment of the connection until the specified time expires. * @param timeout Expiration time by millisecond unit. - * @retval wl_status_t + * @return wl_status_t */ wl_status_t AutoConnect::_waitForConnect(unsigned long timeout) { wl_status_t wifiStatus; @@ -850,6 +901,60 @@ wl_status_t AutoConnect::_waitForConnect(unsigned long timeout) { return wifiStatus; } +/** + * Control the automatic reconnection behaves. Reconnection behavior + * to the AP connected during captive portal operation is activated + * by an order as the argument. + * @param order AC_RECONNECT_SET or AC_RECONNECT_RESET + */ +void AutoConnect::_setReconnect(const AC_STARECONNECT_t order) { +#if defined(ARDUINO_ARCH_ESP32) + if (order == AC_RECONNECT_SET) { + _disconnectEventId = WiFi.onEvent([](WiFiEvent_t e, WiFiEventInfo_t info) { + AC_DBG("STA lost connection:%d\n", info.disconnected.reason); + bool rst = WiFi.reconnect(); + AC_DBG("STA connection %s\n", rst ? "restored" : "failed"); + }, WiFiEvent_t::SYSTEM_EVENT_AP_STADISCONNECTED); + AC_DBG("Event<%d> handler registered\n", static_cast(WiFiEvent_t::SYSTEM_EVENT_AP_STADISCONNECTED)); + } + else if (order == AC_RECONNECT_RESET) { + if (_disconnectEventId) { + WiFi.removeEvent(_disconnectEventId); + AC_DBG("Event<%d> handler released\n", static_cast(WiFiEvent_t::SYSTEM_EVENT_AP_STADISCONNECTED)); + } + } +#elif defined(ARDUINO_ARCH_ESP8266) + bool strc = order == AC_RECONNECT_SET ? true : false; + WiFi.setAutoReconnect(strc); + AC_DBG("STA reconnection:%s\n", strc ? "EN" : "DIS"); +#endif +} + +/** + * Wait for the end of transmission of the http response by closed + * from the http client. + */ +void AutoConnect::_waitForEndTransmission() { +#ifdef AC_DEBUG + AC_DBG("Leaves:"); + unsigned long lt = millis(); +#endif + while (_webServer->client().connected()) { + delay(1); + yield(); + } +#ifdef AC_DEBUG + // Notifies of the time taken to end the session. If the http client + // times out, AC_DEBUG must be enabled and it is necessary to confirm + // that the http response is being transmitted correctly. + // To trace the correctness the close sequence of TCP connection, + // enable the debug log of the Arduino core side. If the normal, + // a message of closed the TCP connection will be logged between + // "Leaves:" and "the time taken to end the session" of the log. + AC_DBG_DUMB("%d[ms]\n", static_cast(millis() - lt)); +#endif +} + /** * Disconnects the station from an associated access point. * @param wifiOff The station mode turning switch. @@ -860,6 +965,8 @@ void AutoConnect::_disconnectWiFi(bool wifiOff) { #elif defined(ARDUINO_ARCH_ESP32) WiFi.disconnect(wifiOff, true); #endif - while (WiFi.status() == WL_CONNECTED) - delay(100); + while (WiFi.status() == WL_CONNECTED) { + delay(1); + yield(); + } } diff --git a/src/AutoConnect.h b/src/AutoConnect.h index 7d9f91e..a54b81f 100644 --- a/src/AutoConnect.h +++ b/src/AutoConnect.h @@ -3,7 +3,7 @@ * @file AutoConnect.h * @author hieromon@gmail.com * @version 0.9.7 - * @date 2018-11-17 + * @date 2019-01-21 * @copyright MIT license. */ @@ -199,6 +199,10 @@ class AutoConnect { AC_WEBSERVER_HOSTED }; typedef enum _webServerAllocateType AC_WEBSERVER_TYPE; + typedef enum { + AC_RECONNECT_SET, + AC_RECONNECT_RESET + } AC_STARECONNECT_t; void _initialize(); bool _config(); void _startWebServer(); @@ -224,7 +228,9 @@ class AutoConnect { bool _hasTimeout(unsigned long timeout); bool _isIP(String ipStr); wl_status_t _waitForConnect(unsigned long timeout); + void _waitForEndTransmission(void); void _disconnectWiFi(bool wifiOff); + void _setReconnect(const AC_STARECONNECT_t order); /** Utilities */ static uint32_t _getChipId(); @@ -262,6 +268,9 @@ class AutoConnect { bool _rfDisconnect; /**< URI /disc requested */ bool _rfReset; /**< URI /reset requested */ wl_status_t _rsConnect; /**< connection result */ +#ifdef ARDUINO_ARCH_ESP32 + WiFiEventId_t _disconnectEventId; /**< STA disconnection event handler registered id */ +#endif /** HTTP header information of the currently requested page. */ String _uri; /**< Requested URI */ @@ -276,6 +285,7 @@ class AutoConnect { static const char _CSS_INPUT_BUTTON[] PROGMEM; static const char _CSS_INPUT_TEXT[] PROGMEM; static const char _CSS_TABLE[] PROGMEM; + static const char _CSS_SPINNER[] PROGMEM; static const char _CSS_LUXBAR[] PROGMEM; static const char _ELM_HTML_HEAD[] PROGMEM; static const char _ELM_MENU_PRE[] PROGMEM; @@ -283,6 +293,7 @@ class AutoConnect { static const char _ELM_MENU_POST[] PROGMEM; static const char _PAGE_STAT[] PROGMEM; static const char _PAGE_CONFIGNEW[] PROGMEM; + static const char _PAGE_CONNECTING[] PROGMEM; static const char _PAGE_OPENCREDT[] PROGMEM; static const char _PAGE_SUCCESS[] PROGMEM; static const char _PAGE_RESETTING[] PROGMEM; @@ -297,6 +308,7 @@ class AutoConnect { String _token_CSS_INPUT_BUTTON(PageArgument& args); String _token_CSS_INPUT_TEXT(PageArgument& args); String _token_CSS_TABLE(PageArgument& args); + String _token_CSS_SPINNER(PageArgument& args); String _token_CSS_LUXBAR(PageArgument& args); String _token_HEAD(PageArgument& args); String _token_MENU_PRE(PageArgument& args); @@ -323,6 +335,7 @@ class AutoConnect { String _token_OPEN_SSID(PageArgument& args); String _token_UPTIME(PageArgument& args); String _token_BOOTURI(PageArgument& args); + String _token_CURRENT_SSID(PageArgument& args); #if defined(ARDUINO_ARCH_ESP8266) friend class ESP8266WebServer; diff --git a/src/AutoConnectDefs.h b/src/AutoConnectDefs.h index a222ca2..ad69bc8 100644 --- a/src/AutoConnectDefs.h +++ b/src/AutoConnectDefs.h @@ -86,21 +86,26 @@ #define AUTOCONNECT_URI_SUCCESS AUTOCONNECT_URI "/success" #define AUTOCONNECT_URI_FAIL AUTOCONNECT_URI "/fail" -// Time-out limitation when AutoConnect::begin +// Time-out limitation when AutoConnect::begin [ms] #ifndef AUTOCONNECT_TIMEOUT #define AUTOCONNECT_TIMEOUT 30000 #endif // !AUTOCONNECT_TIMEOUT -// Captive portal timeout value +// Captive portal timeout value [ms] #ifndef AUTOCONNECT_CAPTIVEPORTAL_TIMEOUT #define AUTOCONNECT_CAPTIVEPORTAL_TIMEOUT 0 #endif // !AUTOCONNECT_CAPTIVEPORTAL_TIMEOUT -// Advance wait time +// Advance wait time [s] #ifndef AUTOCONNECT_STARTUPTIME #define AUTOCONNECT_STARTUPTIME (AUTOCONNECT_TIMEOUT/1000) #endif // !AUTOCONNECT_STARTUPTIME +// Response wait time until requesting a result of connection attempt [s] as String +#ifndef AUTOCONNECT_RESPONSEREQUEST_TIMEOUT +#define AUTOCONNECT_RESPONSEREQUEST_TIMEOUT "7" +#endif // !AUTOCONNECT_RESPONSEREQUEST_TIMEOUT + // Default HTTP port #ifndef AUTOCONNECT_HTTPPORT #define AUTOCONNECT_HTTPPORT 80 @@ -111,6 +116,11 @@ #define AUTOCONNECT_DNSPORT 53 #endif // !AUTOCONNECT_DNSPORT +// http response transfer method +#ifndef AUTOCONNECT_HTTP_TRANSFER +#define AUTOCONNECT_HTTP_TRANSFER PB_ByteStream +#endif // !AUTOCONNECT_HTTP_TRANSFER + // Explicitly avoiding unused warning with token handler of PageBuilder #define AC_UNUSED(expr) do { (void)(expr); } while (0) diff --git a/src/AutoConnectPage.cpp b/src/AutoConnectPage.cpp index 13e7caa..01b509c 100644 --- a/src/AutoConnectPage.cpp +++ b/src/AutoConnectPage.cpp @@ -3,7 +3,7 @@ * @file AutoConnectPage.h * @author hieromon@gmail.com * @version 0.9.7 - * @date 2018-11-17 + * @date 2019-01-23 * @copyright MIT license. */ @@ -24,192 +24,192 @@ extern "C" { /**< Basic CSS common to all pages */ const char AutoConnect::_CSS_BASE[] PROGMEM = { "html{" - "font-family:Helvetica,Arial,sans-serif;" - "font-size:16px;" - "-ms-text-size-adjust:100%;" - "-webkit-text-size-adjust:100%;" - "-moz-osx-font-smoothing:grayscale;" - "-webkit-font-smoothing:antialiased;" + "font-family:Helvetica,Arial,sans-serif;" + "font-size:16px;" + "-ms-text-size-adjust:100%;" + "-webkit-text-size-adjust:100%;" + "-moz-osx-font-smoothing:grayscale;" + "-webkit-font-smoothing:antialiased;" "}" "body{" - "margin:0;" - "padding:0;" + "margin:0;" + "padding:0;" "}" ".base-panel{" - "margin:0 22px 0 22px;" + "margin:0 22px 0 22px;" "}" ".base-panel>*>label{" - "display:inline-block;" - "width:3.0em;" - "text-align:right;" + "display:inline-block;" + "width:3.0em;" + "text-align:right;" "}" "input{" - "-moz-appearance:none;" - "-webkit-appearance:none;" - "font-size:0.9em;" - "margin:8px 0 auto;" + "-moz-appearance:none;" + "-webkit-appearance:none;" + "font-size:0.9em;" + "margin:8px 0 auto;" "}" ".lap{" - "visibility:collapse;" + "visibility:collapse;" "}" ".lap:target{" - "visibility:visible;" + "visibility:visible;" "}" ".lap:target .overlap{" - "opacity:0.7;" - "transition:0.3s;" + "opacity:0.7;" + "transition:0.3s;" "}" ".lap:target .modal_button{" - "opacity:1;" - "transition:0.3s;" + "opacity:1;" + "transition:0.3s;" "}" ".overlap{" - "top:0;" - "left:0;" - "width:100%;" - "height:100%;" - "position:fixed;" - "opacity:0;" - "background:#000;" - "z-index:1000;" + "top:0;" + "left:0;" + "width:100%;" + "height:100%;" + "position:fixed;" + "opacity:0;" + "background:#000;" + "z-index:1000;" "}" ".modal_button{" - "border-radius:13px;" - "background:#660033;" - "color:#ffffcc;" - "padding:20px 30px;" - "text-align:center;" - "text-decoration:none;" - "letter-spacing:1px;" - "font-weight:bold;" - "display:inline-block;" - "top:40%;" - "left:40%;" - "width:20%;" - "position:fixed;" - "opacity:0;" - "z-index:1001;" + "border-radius:13px;" + "background:#660033;" + "color:#ffffcc;" + "padding:20px 30px;" + "text-align:center;" + "text-decoration:none;" + "letter-spacing:1px;" + "font-weight:bold;" + "display:inline-block;" + "top:40%;" + "left:40%;" + "width:20%;" + "position:fixed;" + "opacity:0;" + "z-index:1001;" "}" }; /**< non-marked list for UL */ const char AutoConnect::_CSS_UL[] PROGMEM = { "ul.noorder{" - "padding:0;" - "list-style:none;" + "padding:0;" + "list-style:none;" "}" "ul.noorder>*>label{" - "display:inline-block;" - "width:86px;" - "margin-right:10px;" - "text-align:right;" + "display:inline-block;" + "width:86px;" + "margin-right:10px;" + "text-align:right;" "}" "ul.noorder>input[type=\"checkbox\"]{" - "-moz-appearance:checkbox;" - "-webkit-appearance:checkbox;" + "-moz-appearance:checkbox;" + "-webkit-appearance:checkbox;" "}" "ul.noorder>input[type=\"radio\"]{" - "margin-right:0.5em;" - "-moz-appearance:radio;" - "-webkit-appearance:radio;" + "margin-right:0.5em;" + "-moz-appearance:radio;" + "-webkit-appearance:radio;" "}" }; /**< Image icon for inline expansion, the lock mark. */ const char AutoConnect::_CSS_ICON_LOCK[] PROGMEM = { ".img-lock{" - "display:inline-block;" - "width:24px;" - "height:24px;" - "margin-left:12px;" - "vertical-align:middle;" - "background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsTAAALEwEAmpwYAAAB1ElEQVRIibWVu0scURTGf3d2drBQFAWbbRQVCwuVLIZdi2gnWIiF/4GtKyuJGAJh8mgTcU0T8T8ICC6kiIVu44gvtFEQQWwsbExQJGHXmZtiZsOyzCN3Vz+4cDjfvec7j7l3QAF95onRZ54YKmdE1IbnS0c9mnAyAjkBxDy3LRHrjtRyu7OD52HntTAyvbw/HxP2hkCearrRb2WSCSuTTGi60S+QpzFhbwznDl/VVMHw0sF7hEjFbW2qkB38lfp8nNDipWcATil+uDM3cDWyeNRSijnfkHJnezb5Vkkgvbg3IOXD2e1ts93S+icnkZOAVaalZK3YQMa4L+pC6L1WduhYSeCf0PLBdxzOjZ93Lwvm6APAiLmlF1ubPiHotmaS41ExQjH0ZbfNM1NAFpgD0lVcICIrANqAVaAd+AFIYAy4BqaBG+Wsq5AH3vgk8xpYrzf4KLAZwhe8PYEIvQe4vc6H8Hnc2dQs0AFchvAXQGdEDF8s4A5TZS34BQqqQNaS1WMI3KD4WUbNoBJfce9CO7BSr4BfBe8A21vmUwh0VdjdTyHwscL+UK+AHxoD7FDoAX6/Cnpxn4ay/egCjcCL/w1chkqLakLQ/6ABhT57uAd+Vzv/Ara3iY6fK4WxAAAAAElFTkSuQmCC) no-repeat;" + "display:inline-block;" + "width:24px;" + "height:24px;" + "margin-left:12px;" + "vertical-align:middle;" + "background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsTAAALEwEAmpwYAAAB1ElEQVRIibWVu0scURTGf3d2drBQFAWbbRQVCwuVLIZdi2gnWIiF/4GtKyuJGAJh8mgTcU0T8T8ICC6kiIVu44gvtFEQQWwsbExQJGHXmZtiZsOyzCN3Vz+4cDjfvec7j7l3QAF95onRZ54YKmdE1IbnS0c9mnAyAjkBxDy3LRHrjtRyu7OD52HntTAyvbw/HxP2hkCearrRb2WSCSuTTGi60S+QpzFhbwznDl/VVMHw0sF7hEjFbW2qkB38lfp8nNDipWcATil+uDM3cDWyeNRSijnfkHJnezb5Vkkgvbg3IOXD2e1ts93S+icnkZOAVaalZK3YQMa4L+pC6L1WduhYSeCf0PLBdxzOjZ93Lwvm6APAiLmlF1ubPiHotmaS41ExQjH0ZbfNM1NAFpgD0lVcICIrANqAVaAd+AFIYAy4BqaBG+Wsq5AH3vgk8xpYrzf4KLAZwhe8PYEIvQe4vc6H8Hnc2dQs0AFchvAXQGdEDF8s4A5TZS34BQqqQNaS1WMI3KD4WUbNoBJfce9CO7BSr4BfBe8A21vmUwh0VdjdTyHwscL+UK+AHxoD7FDoAX6/Cnpxn4ay/egCjcCL/w1chkqLakLQ/6ABhT57uAd+Vzv/Ara3iY6fK4WxAAAAAElFTkSuQmCC) no-repeat;" "}" }; /**< INPUT button and submit style */ const char AutoConnect::_CSS_INPUT_BUTTON[] PROGMEM = { "input[type=\"button\"],input[type=\"submit\"]{" - "padding:8px 30px;" - "font-weight:bold;" - "letter-spacing:0.8px;" - "color:#fff;" - "border:1px solid;" - "border-radius:2px;" - "margin-top:12px;" + "padding:8px 30px;" + "font-weight:bold;" + "letter-spacing:0.8px;" + "color:#fff;" + "border:1px solid;" + "border-radius:2px;" + "margin-top:12px;" "}" "input[type=\"button\"]{" - "background-color:#1b5e20;" - "border-color:#1b5e20;" - "width:16em;" + "background-color:#1b5e20;" + "border-color:#1b5e20;" + "width:16em;" "}" ".aux-page input[type=\"button\"]{" - "font-weight:normal;" - "padding:8px 14px;" - "margin:12px;" - "width:auto;" + "font-weight:normal;" + "padding:8px 14px;" + "margin:12px;" + "width:auto;" "}" "input#sb[type=\"submit\"]{" - "width:16em;" + "width:16em;" "}" "input[type=\"submit\"]{" - "background-color:#006064;" - "border-color:#006064;" + "background-color:#006064;" + "border-color:#006064;" "}" "input[type=\"button\"], input[type=\"submit\"]:focus," "input[type=\"button\"], input[type=\"submit\"]:active{" - "outline:none;" - "text-decoration:none;" + "outline:none;" + "text-decoration:none;" "}" }; /**< INPUT text style */ const char AutoConnect::_CSS_INPUT_TEXT[] PROGMEM = { "input[type=\"text\"], input[type=\"password\"], .aux-page select{" - "background-color:#fff;" - "border:1px solid #ccc;" - "border-radius:2px;" - "color:#444;" - "margin:8px 0 8px 0;" - "padding:10px;" + "background-color:#fff;" + "border:1px solid #ccc;" + "border-radius:2px;" + "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;" - "-moz-transition:all 0.20s ease-in;" - "-o-transition:all 0.20s ease-in;" - "-ms-transition:all 0.20s ease-in;" - "transition:all 0.20s ease-in;" + "font-weight:300;" + "width:calc(100% - 124px);" + "-webkit-transition:all 0.20s ease-in;" + "-moz-transition:all 0.20s ease-in;" + "-o-transition:all 0.20s ease-in;" + "-ms-transition:all 0.20s ease-in;" + "transition:all 0.20s ease-in;" "}" "input[type=\"text\"]:focus,input[type=\"password\"]:focus{" - "outline:none;" - "border-color:#5C9DED;" - "box-shadow:0 0 3px #4B8CDC;" + "outline:none;" + "border-color:#5C9DED;" + "box-shadow:0 0 3px #4B8CDC;" "}" "input.error, input.error:focus{" - "border-color:#ED5564;" - "color:#D9434E;" - "box-shadow:0 0 3px #D9434E;" + "border-color:#ED5564;" + "color:#D9434E;" + "box-shadow:0 0 3px #D9434E;" "}" "input:disabled{" - "opacity:0.6;" - "background-color:#f7f7f7;" + "opacity:0.6;" + "background-color:#f7f7f7;" "}" "input:disabled:hover{" - "cursor:not-allowed;" + "cursor:not-allowed;" "}" - "input.error::-webkit-input-placeholder{" - "color:#D9434E;" + "input.error::-webkit-input-placeholder{" + "color:#D9434E;" "}" "input.error:-moz-placeholder{" - "color:#D9434E;" + "color:#D9434E;" "}" "input.error::-moz-placeholder{" - "color:#D9434E;" + "color:#D9434E;" "}" "input.error:-ms-input-placeholder{" - "color:#D9434E;" + "color:#D9434E;" "}" ".aux-page label{" "padding:10px 0.5em;" @@ -219,54 +219,93 @@ const char AutoConnect::_CSS_INPUT_TEXT[] PROGMEM = { /**< TABLE style */ const char AutoConnect::_CSS_TABLE[] PROGMEM = { "table{" - "border-collapse:collapse;" - "border-spacing:0;" - "border:1px solid #ddd;" - "color:#444;" - "background-color:#fff;" - "margin-bottom:20px;" + "border-collapse:collapse;" + "border-spacing:0;" + "border:1px solid #ddd;" + "color:#444;" + "background-color:#fff;" + "margin-bottom:20px;" "}" "table.info," "table.info>tfoot," "table.info>thead{" - "width:100%;" - "border-color:#5C9DED;" + "width:100%;" + "border-color:#5C9DED;" "}" "table.info>thead{" - "background-color:#5C9DED;" + "background-color:#5C9DED;" "}" "table.info>thead>tr>th{" - "color:#fff;" + "color:#fff;" "}" "td," "th{" - "padding:10px 22px;" + "padding:10px 22px;" "}" "thead{" - "background-color:#f3f3f3;" - "border-bottom:1px solid #ddd;" + "background-color:#f3f3f3;" + "border-bottom:1px solid #ddd;" "}" "thead>tr>th{" - "font-weight:400;" - "text-align:left;" + "font-weight:400;" + "text-align:left;" "}" "tfoot{" - "border-top:1px solid #ddd;" + "border-top:1px solid #ddd;" "}" "tbody," "tbody>tr:nth-child(odd){" - "background-color:#fff;" + "background-color:#fff;" "}" "tbody>tr>td," "tfoot>tr>td{" - "font-weight:300;" - "font-size:.88em;" + "font-weight:300;" + "font-size:.88em;" "}" "tbody>tr:nth-child(even){" - "background-color:#f7f7f7;" + "background-color:#f7f7f7;" "}" - "table.info tbody>tr:nth-child(even){" - "background-color:#EFF5FD;" + "table.info tbody>tr:nth-child(even){" + "background-color:#EFF5FD;" + "}" +}; + +/**< SVG animation for spinner */ +const char AutoConnect::_CSS_SPINNER[] PROGMEM = { + ".spinner{" + "width:40px;" + "height:40px;" + "position:relative;" + "margin:100px auto;" + "}" + ".double-bounce1, .double-bounce2{" + "width:100%;" + "height:100%;" + "border-radius:50%;" + "background-color:#333;" + "opacity:0.6;" + "position:absolute;" + "top:0;" + "left:0;" + "-webkit-animation:sk-bounce 2.0s infinite ease-in-out;" + "animation:sk-bounce 2.0s infinite ease-in-out;" + "}" + ".double-bounce2{" + "-webkit-animation-delay:-1.0s;" + "animation-delay:-1.0s;" + "}" + "@-webkit-keyframes sk-bounce{" + "0%, 100%{-webkit-transform:scale(0.0)}" + "50%{-webkit-transform:scale(1.0)}" + "}" + "@keyframes sk-bounce{" + "0%,100%{" + "transform:scale(0.0);" + "-webkit-transform:scale(0.0);" + "}50%{" + "transform:scale(1.0);" + "-webkit-transform:scale(1.0);" + "}" "}" }; @@ -464,46 +503,46 @@ const char AutoConnect::_ELM_HTML_HEAD[] PROGMEM = { "" "" "" - "" + "" }; /**< LuxBar menu element. */ const char AutoConnect::_ELM_MENU_PRE[] PROGMEM = { "
" - "" - "
" - "" + "
" + "
" + "" + "
" "
" }; /**< The 404 page content. */ const char AutoConnect::_PAGE_404[] PROGMEM = { "{{HEAD}}" - "Page not found" + "Page not found" "" "" - "404 Not found" + "404 Not found" "" "" }; @@ -511,11 +550,11 @@ const char AutoConnect::_PAGE_404[] PROGMEM = { /**< The page that started the reset. */ const char AutoConnect::_PAGE_RESETTING[] PROGMEM = { "{{HEAD}}" - "" - "AutoConnect resetting" + "" + "AutoConnect resetting" "" "" - "

{{RESET}}

" + "

{{RESET}}

" "" "" }; @@ -523,81 +562,81 @@ const char AutoConnect::_PAGE_RESETTING[] PROGMEM = { /**< AutoConnect portal page. */ const char AutoConnect::_PAGE_STAT[] PROGMEM = { "{{HEAD}}" - "AutoConnect statistics" - "" + "AutoConnect statistics" + "" "" "" - "
" - "{{MENU_PRE}}" - "{{MENU_AUX}}" - "{{MENU_POST}}" - "
" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "
Established connection{{ESTAB_SSID}}
Mode{{WIFI_MODE}}({{WIFI_STATUS}})
IP{{LOCAL_IP}}
GW{{GATEWAY}}
Subnet mask{{NETMASK}}
SoftAP IP{{SOFTAP_IP}}
AP MAC{{AP_MAC}}
STA MAC{{STA_MAC}}
Channel{{CHANNEL}}
dBm{{DBM}}
Chip ID{{CHIP_ID}}
CPU Freq.{{CPU_FREQ}}MHz
Flash size{{FLASH_SIZE}}
Free memory{{FREE_HEAP}}
" - "
" - "
" + "
" + "{{MENU_PRE}}" + "{{MENU_AUX}}" + "{{MENU_POST}}" + "
" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "
Established connection{{ESTAB_SSID}}
Mode{{WIFI_MODE}}({{WIFI_STATUS}})
IP{{LOCAL_IP}}
GW{{GATEWAY}}
Subnet mask{{NETMASK}}
SoftAP IP{{SOFTAP_IP}}
AP MAC{{AP_MAC}}
STA MAC{{STA_MAC}}
Channel{{CHANNEL}}
dBm{{DBM}}
Chip ID{{CHIP_ID}}
CPU Freq.{{CPU_FREQ}}MHz
Flash size{{FLASH_SIZE}}
Free memory{{FREE_HEAP}}
" + "
" + "
" "" "" }; @@ -605,39 +644,39 @@ const char AutoConnect::_PAGE_STAT[] PROGMEM = { /**< A page that specifies the new configuration. */ const char AutoConnect::_PAGE_CONFIGNEW[] PROGMEM = { "{{HEAD}}" - "AutoConnect config" - "" + "AutoConnect config" + "" "" "" - "
" - "{{MENU_PRE}}" - "{{MENU_AUX}}" - "{{MENU_POST}}" - "
" - "
" - "{{LIST_SSID}}" - "
Hidden:{{HIDDEN_COUNT}}
" - "
    " - "
  • " - "" - "" - "
  • " - "
  • " - "" - "" - "
  • " - "
  • " - "
" - "
" - "
" - "
" + "
" + "{{MENU_PRE}}" + "{{MENU_AUX}}" + "{{MENU_POST}}" + "
" + "
" + "{{LIST_SSID}}" + "
Hidden:{{HIDDEN_COUNT}}
" + "
    " + "
  • " + "" + "" + "
  • " + "
  • " + "" + "" + "
  • " + "
  • " + "
" + "
" + "
" + "
" "" "" }; @@ -645,78 +684,109 @@ const char AutoConnect::_PAGE_CONFIGNEW[] PROGMEM = { /**< A page that reads stored authentication information and starts connection. */ const char AutoConnect::_PAGE_OPENCREDT[] PROGMEM = { "{{HEAD}}" - "AutoConnect credentials" - "" + "AutoConnect credentials" + "" "" "" - "
" - "{{MENU_PRE}}" - "{{MENU_AUX}}" - "{{MENU_POST}}" - "
" - "
" - "{{OPEN_SSID}}" - "
" - "
" - "
" + "
" + "{{MENU_PRE}}" + "{{MENU_AUX}}" + "{{MENU_POST}}" + "
" + "
" + "{{OPEN_SSID}}" + "
" + "
" + "
" "" "" }; +/**< A page that informs during a connection attempting. */ +const char AutoConnect::_PAGE_CONNECTING[] PROGMEM = { + "{{REQ}}" + "{{HEAD}}" + "" + "AutoConnect connecting" + "" + "" + "" + "" + "
" + "{{MENU_PRE}}" + "{{MENU_POST}}" + "
" + "
{{CUR_SSID}}
" + "
" + "
" + "
" + "
" + "" + "" +}; + /**< A page announcing that a connection has been established. */ const char AutoConnect::_PAGE_SUCCESS[] PROGMEM = { "{{HEAD}}" - "AutoConnect statistics" - "" + "AutoConnect statistics" + "" "" "" - "
" - "{{MENU_PRE}}" - "{{MENU_AUX}}" - "{{MENU_POST}}" - "
" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "
Established connection{{ESTAB_SSID}}
Mode{{WIFI_MODE}}({{WIFI_STATUS}})
IP{{LOCAL_IP}}
GW{{GATEWAY}}
Subnet mask{{NETMASK}}
Channel{{CHANNEL}}
dBm{{DBM}}
" - "
" - "
" + "
" + "{{MENU_PRE}}" + "{{MENU_AUX}}" + "{{MENU_POST}}" + "
" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "
Established connection{{ESTAB_SSID}}
Mode{{WIFI_MODE}}({{WIFI_STATUS}})
IP{{LOCAL_IP}}
GW{{GATEWAY}}
Subnet mask{{NETMASK}}
Channel{{CHANNEL}}
dBm{{DBM}}
" + "
" + "
" "" "" }; @@ -724,29 +794,29 @@ const char AutoConnect::_PAGE_SUCCESS[] PROGMEM = { /**< A response page for connection failed. */ const char AutoConnect::_PAGE_FAIL[] PROGMEM = { "{{HEAD}}" - "AutoConnect statistics" - "" + "AutoConnect statistics" + "" "" "" - "
" - "{{MENU_PRE}}" - "{{MENU_AUX}}" - "{{MENU_POST}}" - "
" - "" - "" - "" - "" - "" - "" - "" - "
Connection Failed{{STATION_STATUS}}
" - "
" - "
" + "
" + "{{MENU_PRE}}" + "{{MENU_AUX}}" + "{{MENU_POST}}" + "
" + "" + "" + "" + "" + "" + "" + "" + "
Connection Failed{{STATION_STATUS}}
" + "
" + "
" "" "" }; @@ -755,17 +825,17 @@ const char AutoConnect::_PAGE_FAIL[] PROGMEM = { const char AutoConnect::_PAGE_DISCONN[] PROGMEM = { "{{DISCONNECT}}" "{{HEAD}}" - "AutoConnect disconnected" - "" + "AutoConnect disconnected" + "" "" "" - "
" - "{{MENU_PRE}}" - "{{MENU_AUX}}" - "{{MENU_POST}}" + "
" + "{{MENU_PRE}}" + "{{MENU_POST}}" + "
" "" "" }; @@ -802,6 +872,7 @@ String AutoConnect::_token_CSS_ICON_LOCK(PageArgument& args) { AC_UNUSED(args); return String(FPSTR(_CSS_ICON_LOCK)); } + String AutoConnect::_token_CSS_INPUT_BUTTON(PageArgument& args) { AC_UNUSED(args); return String(FPSTR(_CSS_INPUT_BUTTON)); @@ -817,6 +888,11 @@ String AutoConnect::_token_CSS_TABLE(PageArgument& args) { return String(FPSTR(_CSS_TABLE)); } +String AutoConnect::_token_CSS_SPINNER(PageArgument& args) { + AC_UNUSED(args); + return String(FPSTR(_CSS_SPINNER)); +} + String AutoConnect::_token_HEAD(PageArgument& args) { AC_UNUSED(args); return String(FPSTR(_ELM_HTML_HEAD)); @@ -1093,6 +1169,10 @@ String AutoConnect::_token_BOOTURI(PageArgument& args) { return String(""); } +String AutoConnect::_token_CURRENT_SSID(PageArgument& args) { + AC_UNUSED(args); + return String(reinterpret_cast(_credential.ssid)); +} /** * This function dynamically build up the response pages that conform to @@ -1156,9 +1236,17 @@ PageElement* AutoConnect::_setupPage(String uri) { else if (uri == String(AUTOCONNECT_URI_CONNECT)) { // Setup /auto/connect - elm->setMold("{{REQ}}"); + _menuTitle = FPSTR("Connecting"); + elm->setMold(_PAGE_CONNECTING); elm->addToken(String(FPSTR("REQ")), std::bind(&AutoConnect::_induceConnect, this, std::placeholders::_1)); - } + elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); + elm->addToken(String(FPSTR("CSS_BASE")), std::bind(&AutoConnect::_token_CSS_BASE, this, std::placeholders::_1)); + elm->addToken(String(FPSTR("CSS_SPINNER")), std::bind(&AutoConnect::_token_CSS_SPINNER, this, std::placeholders::_1)); + elm->addToken(String(FPSTR("CSS_LUXBAR")), std::bind(&AutoConnect::_token_CSS_LUXBAR, this, std::placeholders::_1)); + elm->addToken(String(FPSTR("MENU_PRE")), std::bind(&AutoConnect::_token_MENU_PRE, this, std::placeholders::_1)); + elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, this, std::placeholders::_1)); + elm->addToken(String(FPSTR("CUR_SSID")), std::bind(&AutoConnect::_token_CURRENT_SSID, this, std::placeholders::_1)); + } else if (uri == String(AUTOCONNECT_URI_OPEN)) { // Setup /auto/open @@ -1183,7 +1271,6 @@ PageElement* AutoConnect::_setupPage(String uri) { elm->addToken(String(FPSTR("CSS_BASE")), std::bind(&AutoConnect::_token_CSS_BASE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_LUXBAR")), std::bind(&AutoConnect::_token_CSS_LUXBAR, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_PRE")), std::bind(&AutoConnect::_token_MENU_PRE, this, std::placeholders::_1)); - elm->addToken(String(FPSTR("MENU_AUX")), std::bind(&AutoConnect::_token_MENU_AUX, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, this, std::placeholders::_1)); } else if (uri == String(AUTOCONNECT_URI_RESET)) { @@ -1224,6 +1311,7 @@ PageElement* AutoConnect::_setupPage(String uri) { else if (uri == String(AUTOCONNECT_URI_FAIL)) { // Setup /auto/fail + _menuTitle = FPSTR("Failed"); elm->setMold(_PAGE_FAIL); elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_BASE")), std::bind(&AutoConnect::_token_CSS_BASE, this, std::placeholders::_1));