diff --git a/README.md b/README.md index c000cc1..1571e06 100644 --- a/README.md +++ b/README.md @@ -68,8 +68,9 @@ Full documentation is available on https://Hieromon.github.io/AutoConnect, some ## Change log -### [0.9.4] April 22, 2018. +### [0.9.4] May 5, 2018. - Automatically focus passphrase after selecting SSID with Configure New AP. +- Supports AutoConnectConfig::autoReconnect option, it will scan the WLAN when it can not connect to the default SSID, apply the applicable credentials if it is saved, and try reconnecting. ### [0.9.3] March 23, 2018. - Supports a static IP address assignment. diff --git a/docs/advancedusage/index.html b/docs/advancedusage/index.html index b794657..a01c634 100644 --- a/docs/advancedusage/index.html +++ b/docs/advancedusage/index.html @@ -365,6 +365,13 @@ 404 handler + + +
  • + + Automatic reconnect + +
  • @@ -578,6 +585,13 @@ 404 handler +
  • + +
  • + + Automatic reconnect + +
  • @@ -711,6 +725,17 @@

    Advanced usage

    404 handler

    Registering the "not found" handler is a different way than ESP8266WebServer. The onNotFound of ESP8266WebServer does not work with AutoConnect. AutoConnect overrides ESP8266WebServer::onNotFound to handle a captive portal. To register "not found" handler, use AutoConnect::onNotFound.

    +

    Automatic reconnect

    +

    When the captive portal is started, SoftAP starts and the STA is disconnected. The current SSID setting memorized in ESP8266 will be lost.
    +If the autoReconnect option of the AutoConnectConfig class is enabled, it automatically attempts to reconnect to the disconnected past access point. When the autoReconnect option is specified, AutoConnect will not start SoftAP immediately if the first WiFi.begin fails. It will scan WiFi signal and the same connection information as the detected BSSID is stored in EEPROM as AutoConnect's credentials, explicitly apply it with WiFi.begin and rerun.

    +
    AutoConnect       Portal;
    +AutoConnectConfig Config;
    +Config.autoReconnect = true;
    +Portal.config(Config);
    +Portal.begin();
    +
    + +

    An autoReconnect option is available to AutoConnect::begin without SSID and pass passphrase.

    Auto save Credential

    By default, AutoConnect saves the credentials of the established connection in EEPROM. You can disable it with the autoSave parameter specified by AutoConnectConfig.

    AutoConnect       Portal;
    diff --git a/docs/api/index.html b/docs/api/index.html
    index b7ffd52..d803df1 100644
    --- a/docs/api/index.html
    +++ b/docs/api/index.html
    @@ -554,6 +554,13 @@
         apip
       
       
    +
  • + +
  • + + autoReconnect + +
  • @@ -952,6 +959,13 @@ apip +
  • + +
  • + + autoReconnect + +
  • @@ -1186,7 +1200,7 @@ AutoConnect first invokes WiFi.begin. If the case of SSID and Password
    void handleClient()
     
    -

    Process the AutoConnect menu interface. It will be processed the client request too contained in the user sketch handler by calling the host handleClient::ESP8266WebServer from the Autoconnect internally.

    +

    Process the AutoConnect menu interface. It will be processed the client request too contained in the user sketch handler by calling from inside of AutoConnect to the hosted ESP8266WebServer::handleClient.

    handleRequest

    void handleRequest()
     
    @@ -1275,6 +1289,21 @@ Register the handler function for undefined URL request detected.
    Type
    IPAddressThe default value is 192.168.244.1

    +

    autoReconnect

    +

    Automatically reconnect to past established access point (BSSID) when the current configured SSID in ESP8266 could not be connected. By enabling this option, AutoConnect::begin() function will attempt to reconnect to a known access point using credentials stored in the EEPROM, even if the connection failed by current SSID.
    +If the connection fails, starts the captive portal in SoftAP + STA mode.
    +

    +
    Type
    +
    bool
    +
    Value
    +
    trueReconnect automatically.
    +
    falseStarts Captive Portal in SoftAP + STA mode without trying to reconnect. This is the default.
    +

    +

    When the autoReconnect option is enabled, an automatic connection will behave if the following conditions are satisfied.

    +

    autoReset

    Reset ESP8266 module automatically after WLAN disconnected.

    @@ -1395,6 +1424,7 @@ The default value is 0. Config.apip = IPAddress(192,168,10,101); // Sets SoftAP IP address Config.gateway = IPAddress(192,168,10,1); // Sets WLAN router IP address Config.netmask = IPAddress(255,255,255,0); // Sets WLAN scope +Config.autoReconnect = true; // Enable auto-reconnect Config.autoSave = AC_SAVECREDENTIAL_NEVER; // No save credential COnfig.boundaryOffet = 64; // Reserve 64 bytes for the user data in EEPROM. Config.homeUri = "/index.html" // Sets home path of the sketch application diff --git a/docs/changelog/index.html b/docs/changelog/index.html index c6e9ec1..dc36518 100644 --- a/docs/changelog/index.html +++ b/docs/changelog/index.html @@ -101,7 +101,7 @@ - + Skip to content @@ -401,14 +401,13 @@
    +#### autoReconnect + +Automatically reconnect to past established access point (BSSID) when the current configured SSID in ESP8266 could not be connected. By enabling this option, *AutoConnect::begin()* function will attempt to reconnect to a known access point using credentials stored in the EEPROM, even if the connection failed by current SSID. +If the connection fails, starts the captive portal in SoftAP + STA mode. +
    +
    **Type**
    +
    bool
    +
    **Value**
    +
    trueReconnect automatically.
    +
    falseStarts Captive Portal in SoftAP + STA mode without trying to reconnect. This is the default.
    +
    + +When the autoReconnect option is enabled, an automatic connection will behave if the following conditions are satisfied. + +- Invokes *AutoConnect::begin* without user name and password parameter as ```begin()```. +- If one of the saved BSSIDs (not the SSID) of the credentials matches the BSSID detected by the network scan. + #### autoReset Reset ESP8266 module automatically after WLAN disconnected. @@ -382,6 +399,7 @@ Config.apid = ESP.hostname(); // Retrieve host name to SotAp ide Config.apip = IPAddress(192,168,10,101); // Sets SoftAP IP address Config.gateway = IPAddress(192,168,10,1); // Sets WLAN router IP address Config.netmask = IPAddress(255,255,255,0); // Sets WLAN scope +Config.autoReconnect = true; // Enable auto-reconnect Config.autoSave = AC_SAVECREDENTIAL_NEVER; // No save credential COnfig.boundaryOffet = 64; // Reserve 64 bytes for the user data in EEPROM. Config.homeUri = "/index.html" // Sets home path of the sketch application diff --git a/mkdocs/changelog.md b/mkdocs/changelog.md index c984a3f..bde1c6d 100644 --- a/mkdocs/changelog.md +++ b/mkdocs/changelog.md @@ -1,5 +1,7 @@ -### [0.9.4] April 22, 2018. +#### [0.9.4] May 5, 2018. + - Automatically focus passphrase after selecting SSID with Configure New AP. +- Supports AutoConnectConfig::autoReconnect option, it will scan the WLAN when it can not connect to the default SSID, apply the applicable credentials if it is saved, and try reconnecting. #### [0.9.3] March 23, 2018. diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index b649ab6..cb3adce 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -2,8 +2,8 @@ * AutoConnect class implementation. * @file AutoConnect.cpp * @author hieromon@gmail.com - * @version 0.9.3 - * @date 2018-03-23 + * @version 0.9.4 + * @date 2018-05-05 * @copyright MIT license. */ @@ -69,24 +69,11 @@ bool AutoConnect::begin() { * @retval false Could not connected, Captive portal started with WIFI_AP_STA mode. */ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long timeout) { - _portalTimeout = timeout; - return begin(ssid, passphrase); -} - -/** - * Starts establishing WiFi connection. - * Before establishing, start the Web server and DNS server for the captive - * portal. Then begins connection establishment in WIFI_STA mode. If - * connection can not established with the specified SSID and password, - * switch to WIFI_AP_STA mode and activate SoftAP. - * @param ssid SSID to be connected. - * @param passphrase Password for 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. - */ -bool AutoConnect::begin(const char* ssid, const char* passphrase) { bool cs; + // Overwrite for the current timeout value. + _portalTimeout = timeout; + // Start WiFi connection. WiFi.mode(WIFI_STA); delay(100); @@ -113,6 +100,19 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase) { 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; + + // Reconnect with a valid credential as the autoReconnect option is enabled. + if (!cs && _apConfig.autoReconnect && (ssid == nullptr && passphrase == nullptr)) { + // Load a valid credential. + if (_loadAvailCredential()) { + // Try to reconnect with a stored credential. + AC_DBG("Past SSID:%s loaded\n", reinterpret_cast(_credential.ssid)); + const char* psk = strlen(reinterpret_cast(_credential.password)) ? reinterpret_cast(_credential.password) : nullptr; + WiFi.begin(reinterpret_cast(_credential.ssid), psk); + AC_DBG("WiFi.begin(%s%s%s)\n", _credential.ssid, psk == nullptr ? "" : ",", psk == nullptr ? "" : psk); + cs = _waitForConnect(_portalTimeout) == WL_CONNECTED; + } + } _currentHostIP = WiFi.localIP(); // It doesn't matter the connection status for launching the Web server. @@ -373,6 +373,30 @@ void AutoConnect::onNotFound(ESP8266WebServer::THandlerFunction fn) { _notFoundHandler = fn; } +/** + * Load stored credentials that match nearby WLANs. + * @retval true A matched credential of BSSID was loaded. + */ +bool AutoConnect::_loadAvailCredential() { + AutoConnectCredential credential(_apConfig.boundaryOffset); + + if (credential.entries() >= 0) { + // Scan the vicinity only when the saved credentials are existing. + int8_t nn = WiFi.scanNetworks(false, true); + if (nn > 0) { + // Determine valid credentials by BSSID. + for (uint8_t i = 0; i < credential.entries(); i++) { + credential.load(i, &_credential); + for (uint8_t n = 0; n <= nn; n++) { + if (!memcmp(_credential.bssid, WiFi.BSSID(n), sizeof(station_config::bssid))) + return true; + } + } + } + } + return false; +} + /** * Disconnect from the AP and stop the AutoConnect portal. * Stops DNS server and flush tcp sending. diff --git a/src/AutoConnect.h b/src/AutoConnect.h index dd50cfe..89f07f8 100644 --- a/src/AutoConnect.h +++ b/src/AutoConnect.h @@ -2,8 +2,8 @@ * Declaration of AutoConnect class and accompanying AutoConnectConfig class. * @file AutoConnect.h * @author hieromon@gmail.com - * @version 0.9.3 - * @date 2018-03-23 + * @version 0.9.4 + * @date 2018-05-05 * @copyright MIT license. */ @@ -119,6 +119,7 @@ class AutoConnectConfig { uptime(AUTOCONNECT_STARTUPTIME), autoRise(true), autoReset(true), + autoReconnect(false), homeUri(AUTOCONNECT_HOMEURI), staip(0U), staGateway(0U), @@ -141,6 +142,7 @@ class AutoConnectConfig { uptime(AUTOCONNECT_STARTUPTIME), autoRise(true), autoReset(true), + autoReconnect(false), homeUri(AUTOCONNECT_HOMEURI), staip(0U), staGateway(0U), @@ -163,6 +165,7 @@ class AutoConnectConfig { uptime = o.uptime; autoRise = o.autoRise; autoReset = o.autoReset; + autoReconnect = o.autoReconnect; homeUri = o.homeUri; staip = o.staip; staGateway = o.staGateway; @@ -184,6 +187,7 @@ class AutoConnectConfig { int uptime; /**< Length of start up time */ bool autoRise; /**< Automatic starting the captive portal */ bool autoReset; /**< Reset ESP8266 module automatically when WLAN disconnected. */ + bool autoReconnect; /**< Automatic reconnect with past SSID */ String homeUri; /**< A URI of user site */ IPAddress staip; /**< Station static IP address */ IPAddress staGateway; /**< Station gateway address */ @@ -201,8 +205,7 @@ class AutoConnect { bool config(const char* ap, const char* password = nullptr); void home(String uri); bool begin(); - bool begin(const char* ssid, const char* passphrase); - bool begin(const char* ssid, const char* passphrase, unsigned long timeout); + bool begin(const char* ssid, const char* passphrase = nullptr, unsigned long timeout = AUTOCONNECT_TIMEOUT); void end(); void handleClient(); void handleRequest(); @@ -223,6 +226,7 @@ class AutoConnect { void _startWebServer(); void _startDNSServer(); void _handleNotFound(); + bool _loadAvailCredential(); void _stopPortal(); bool _classifyHandle(HTTPMethod mothod, String uri); PageElement* _setupPage(String uri);