Supports the captive portal timeout

pull/41/head
Hieromon Ikasamo 6 years ago
parent 0cbb08a6f1
commit ad3085f62d
  1. 3
      README.md
  2. 94
      mkdocs/advancedusage.md
  3. 1
      mkdocs/api.md
  4. 80
      mkdocs/apiconfig.md
  5. 77
      src/AutoConnect.cpp
  6. 15
      src/AutoConnect.h
  7. 6
      src/AutoConnectDefs.h

@ -96,7 +96,7 @@ Full documentation is available on https://Hieromon.github.io/AutoConnect, some
## Change log ## Change log
### [0.9.7] Jan. 1, 2019 ### [0.9.7] Jan. 10, 2019
- Fixed crash in some environments. Thank you @ageurtse - Fixed crash in some environments. Thank you @ageurtse
- Supports AutoConnect menu extention by user sketch with **AutoConnectAux**. - Supports AutoConnect menu extention by user sketch with **AutoConnectAux**.
- Supports loading and saving of user-defined parameters with JSON format. - Supports loading and saving of user-defined parameters with JSON format.
@ -105,6 +105,7 @@ Full documentation is available on https://Hieromon.github.io/AutoConnect, some
- 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 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```.
- Supports **AutoConnectConfig::hostName**. It activates ```WiFi.hostname()```. - Supports **AutoConnectConfig::hostName**. It activates ```WiFi.hostname()```.
- Supports the captive portal time-out. It can be controlled by **AutoConnectConfig::portalTimeout** and **AutoConnectConfig::retainPortal**.
### [0.9.6] Sept. 27, 2018 ### [0.9.6] Sept. 27, 2018
- Improvement of RSSI detection for saved SSIDs. - Improvement of RSSI detection for saved SSIDs.

@ -6,8 +6,10 @@ Registering the "not found" handler is a different way than ESP8266WebServer/Web
### <i class="fa fa-caret-right"></i> Automatic reconnect ### <i class="fa fa-caret-right"></i> 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 but then the reconnect behavior of ESP32 is somewhat different from this. When the captive portal is started, SoftAP starts and the STA is disconnected. The current SSID setting memorized in ESP8266 will be lost but then the reconnect behavior of ESP32 is somewhat different from this.
The [WiFiSTAClass::disconnect](https://github.com/espressif/arduino-esp32/blob/a0f0bd930cfd2d607bf3d3288f46e2d265dd2e11/libraries/WiFi/src/WiFiSTA.h#L46) function implemented in the arduino-esp32 has extended parameters than the ESP8266's arduino-core. The second parameter of WiFi.disconnect on the arduino-esp32 core that does not exist in the [ESP8266WiFiSTAClass](https://github.com/esp8266/Arduino/blob/7e1bdb225da8ab337373517e6a86a99432921a86/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp#L296) has the effect of deleting the currently connected WiFi configuration and its default value is "false". On the ESP32 platform, even if WiFi.disconnect is executed, WiFi.begin() without the parameters in the next turn will try to connect to that AP. That is, automatic reconnection is implemented in arduino-esp32 already. Although this behavior appears seemingly competent, it is rather a disadvantage in scenes where you want to change the access point each time. When explicitly disconnecting WiFi from the Disconnect menu, AutoConnect will erase the AP connection settings saved by arduino-esp32 core. AutoConnect's automatic reconnection is a mechanism independent from the automatic reconnection of the arduino-esp32 core.
The [WiFiSTAClass::disconnect](https://github.com/espressif/arduino-esp32/blob/a0f0bd930cfd2d607bf3d3288f46e2d265dd2e11/libraries/WiFi/src/WiFiSTA.h#L46) function implemented in the arduino-esp32 has extended parameters than the ESP8266's arduino-core. The second parameter of WiFi.disconnect on the arduino-esp32 core that does not exist in the [ESP8266WiFiSTAClass](https://github.com/esp8266/Arduino/blob/7e1bdb225da8ab337373517e6a86a99432921a86/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp#L296) has the effect of deleting the currently connected WiFi configuration and its default value is "false". On the ESP32 platform, even if WiFi.disconnect is executed, WiFi.begin() without the parameters in the next turn will try to connect to that AP. That is, automatic reconnection is implemented in arduino-esp32 already. Although this behavior appears seemingly competent, it is rather a disadvantage in scenes where you want to change the access point each time. When explicitly disconnecting WiFi from the Disconnect menu, AutoConnect will erase the AP connection settings saved by arduino-esp32 core. AutoConnect's automatic reconnection is a mechanism independent from the automatic reconnection of the arduino-esp32 core.
If the [**autoReconnect**](api.md#autoreconnect) option of the [**AutoConnectConfig**](api.md#autoconnectconfig-api) 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. If the [**autoReconnect**](api.md#autoreconnect) option of the [**AutoConnectConfig**](api.md#autoconnectconfig-api) 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.
```arduino hl_lines="3" ```arduino hl_lines="3"
@ -62,6 +64,92 @@ void loop() {
Portal.handleClient(); Portal.handleClient();
} }
``` ```
### <i class="fa fa-caret-right"></i> Captive portal timeout control
AutoConnect has two parameters for timeout control. One is a timeout value used when trying to connect to the specified AP. It behaves the same as general timeout control in connection attempt by WiFi.begin. This control is specified by the third parameter of [*AutoConnect::begin*](api.md#begin). Default value is macro defined by [**AUTOCONNECT_TIMEOUT**](api.md#defined-macros) in the `AutoConnectDef.h` file.
The other is timeout control for the captive portal itself. It is useful when you want to continue sketch execution with offline even if the WiFi connection is not possible. You can also combine it with the [**immediateStart**](#on-demand-start-the-captive-portal) option to create sketches with high mobility.
The timeout of the captive portal is specified together with [**AutoConnectConfig::portalTimeout**](apiconfig.md#portaltimeout) as follows.
```cpp hl_lines="9"
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <AutoConnect.h>
AutoConnect portal;
AutoConnectConfig config;
void setup() {
config.portalTimeout = 60000; // It will time out in 60 seconds
portal.config(config);
portal.begin();
}
void loop() {
if (WiFi.status() == WL_CONNECTED) {
// Some sketck code for the connected scene is here.
}
else {
// Some sketch code for not connected scene is here.
}
portal.handleClient();
}
```
Also, if you want to stop AutoConnect completely when the captive portal is timed out, you need to call the [**AutoConnect::end**](api.md#end) function. It looks like the following code:
```cpp
bool acEnable;
void setup() {
config.portalTimeout = 60000; // It will time out in 60 seconds
portal.config(config);
acEnable = portal.begin();
if (!acEnable) {
portal.end();
}
}
void loop() {
if (WiFi.status() == WL_CONNECTED) {
// Some sketck code for the connected scene is here.
}
else {
// Some sketch code for not connected scene is here.
}
if (acEnable) {
portal.handleClient();
}
}
```
There is another option related to timeout in AutoConnectConfig. It can make use of the captive portal function even after a timeout. The [**AutoConnectConfig::retainPortal**](apiconfig.md#retainlportal) option will not stop the SoftAP when the captive portal is timed out. If you enable the ratainPortal option, you can try to connect to the AP at any time while continuing to sketch execution with offline even after the captive portal timed-out. The following code is its example. It can enable the captive portal after timed-out without changing sketch skeleton compared to the above code which does not specify an option.
```cpp hl_lines="10"
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <AutoConnect.h>
AutoConnect portal;
AutoConnectConfig config;
void setup() {
config.portalTimeout = 60000; // It will time out in 60 seconds
config.retainPortal = true;
portal.config(config);
portal.begin();
}
void loop() {
if (WiFi.status() == WL_CONNECTED) {
// Some sketck code for the connected scene is here.
}
else {
// Some sketch code for not connected scene is here.
}
portal.handleClient();
}
```
### <i class="fa fa-caret-right"></i> Combination with mDNS ### <i class="fa fa-caret-right"></i> Combination with mDNS
@ -243,6 +331,8 @@ AutoConnect will activate SoftAP at failed the first *WiFi.begin*. It SoftAP set
- Hidden attribute. - Hidden attribute.
- Auto save credential. - Auto save credential.
- Offset address of the credentials storage area in EEPROM. - Offset address of the credentials storage area in EEPROM.
- Captive portal time out limit.
- Retains the portal function after time out.
- Length of start up time after reset. - Length of start up time after reset.
- Automatic starting the captive portal. - Automatic starting the captive portal.
- Start the captive portal forcely. - Start the captive portal forcely.

@ -22,6 +22,7 @@ They contain in ```AutoConnectDefs.h```.
#define AUTOCONNECT_STARTUPTIME 10 // Default waiting time[s] for after reset #define AUTOCONNECT_STARTUPTIME 10 // Default waiting time[s] for after reset
#define AUTOCONNECT_URI "/_ac" // Default AutoConnect root path #define AUTOCONNECT_URI "/_ac" // Default AutoConnect root path
#define AUTOCONNECT_TIMEOUT 30000 // Default connection timeout[ms] #define AUTOCONNECT_TIMEOUT 30000 // Default connection timeout[ms]
#define AUTOCONNECT_CAPTIVEPORTAL_TIMEOUT 0 // Captive portal timeout value
#define AUTOCONNECT_USE_JSON // Allow AutoConnect elements to be handled by JSON format #define AUTOCONNECT_USE_JSON // Allow AutoConnect elements to be handled by JSON format
``` ```

@ -3,20 +3,28 @@
### AutoConnectConfig ### AutoConnectConfig
```cpp ```cpp
AutoConnectConfig(); AutoConnectConfig()
``` ```
```cpp ```cpp
AutoConnectConfig(const char* ap, const char* password); AutoConnectConfig(const char* ap, const char* password)
```
```cpp
AutoConnectConfig(const char* ap, const char* password, const unsigned long timeout)
```
```cpp
AutoConnectConfig(const char* ap, const char* password, const unsigned long timeout, const uint8_t channel)
``` ```
<dl class="apidl"> <dl class="apidl">
<dt>**Parameters**</dt> <dt>**Parameters**</dt>
<dd><span class="apidef">ap</span>SSID for SoftAP. The length should be up to 31. The default value is **esp8266ap** for ESP8266, **esp32ap** for ESP32.</dd> <dd><span class="apidef">ap</span>SSID for SoftAP. The length should be up to 31. The default value is **esp8266ap** for ESP8266, **esp32ap** for ESP32.</dd>
<dd><span class="apidef">password</span>Password for SodtAP. The length should be from 8 to up to 63. The default value is **12345678**.</dd> <dd><span class="apidef">password</span>Password for SodtAP. The length should be from 8 to up to 63. The default value is **12345678**.</dd>
<dd><span class="apidef">timeout</span>The timeout value of the captive portal in [ms] units. The default value is 0.</dd>
<dd><span class="apidef">channel</span>The channel number of WIFi when SoftAP starts. The default values is 1.</dd>
</dl> </dl>
## <i class="fa fa-code"></i> Public member variables ## <i class="fa fa-code"></i> Public member variables
### apid ### <i class="fa fa-caret-right"></i> apid
SoftAP's SSID. SoftAP's SSID.
<dl class="apidl"> <dl class="apidl">
@ -24,7 +32,7 @@ SoftAP's SSID.
<dd>String</dd> <dd>String</dd>
</dl> </dl>
### apip ### <i class="fa fa-caret-right"></i> apip
Sets IP address for Soft AP in captive portal. When AutoConnect fails the initial WiFi.begin, it starts the captive portal with the IP address specified this. Sets IP address for Soft AP in captive portal. When AutoConnect fails the initial WiFi.begin, it starts the captive portal with the IP address specified this.
<dl class="apidl"> <dl class="apidl">
@ -32,7 +40,7 @@ Sets IP address for Soft AP in captive portal. When AutoConnect fails the initia
<dd><span class="apidef" style="width:230px;">IPAddress</span>The default value is **192.168.244.1**</dd> <dd><span class="apidef" style="width:230px;">IPAddress</span>The default value is **192.168.244.1**</dd>
</dl> </dl>
### autoReconnect ### <i class="fa fa-caret-right"></i> autoReconnect
Automatically will try to reconnect with the past established access point (BSSID) when the current configured SSID in ESP8266/ESP32 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. Automatically will try to reconnect with the past established access point (BSSID) when the current configured SSID in ESP8266/ESP32 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. If the connection fails, starts the captive portal in SoftAP + STA mode.
@ -49,7 +57,7 @@ When the autoReconnect option is enabled, an automatic connection will behave if
- Invokes *AutoConnect::begin* without user name and password parameter as ```begin()```. - 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. - If one of the saved BSSIDs (not the SSID) of the credentials matches the BSSID detected by the network scan.
### autoReset ### <i class="fa fa-caret-right"></i> autoReset
Reset ESP8266 module automatically after WLAN disconnected. Reset ESP8266 module automatically after WLAN disconnected.
<dl class="apidl"> <dl class="apidl">
@ -60,7 +68,7 @@ Reset ESP8266 module automatically after WLAN disconnected.
<dd><span class="apidef" style="width:230px;">false</span>No reset.</dd> <dd><span class="apidef" style="width:230px;">false</span>No reset.</dd>
</dl> </dl>
### autoRise ### <i class="fa fa-caret-right"></i> autoRise
Captive portal activation switch. False for disabling the captive portal. It prevents starting the captive portal even if the connection at the first *WiFi.begin* fails. Captive portal activation switch. False for disabling the captive portal. It prevents starting the captive portal even if the connection at the first *WiFi.begin* fails.
<dl class="apidl"> <dl class="apidl">
@ -71,7 +79,7 @@ Captive portal activation switch. False for disabling the captive portal. It pre
<dd><span class="apidef" style="width:230px;">false</span>Disable the captive portal.</dd> <dd><span class="apidef" style="width:230px;">false</span>Disable the captive portal.</dd>
</dl> </dl>
### autoSave ### <i class="fa fa-caret-right"></i> autoSave
The credential saved automatically at the connection establishment. The credential saved automatically at the connection establishment.
<dl class="apidl"> <dl class="apidl">
@ -82,7 +90,7 @@ The credential saved automatically at the connection establishment.
<dd><span class="apidef" style="width:230px;">AC_SAVECREDENTIAL_NEVER</span>The credential no saved.</dd> <dd><span class="apidef" style="width:230px;">AC_SAVECREDENTIAL_NEVER</span>The credential no saved.</dd>
</dl> </dl>
### bootUri ### <i class="fa fa-caret-right"></i> bootUri
Specify the location to be redirected after module reset in the AutoConnect menu. It is given as an enumeration value of **AC_ONBOOTURI_t** indicating either the AutoConnect root path or the user screen home path. Specify the location to be redirected after module reset in the AutoConnect menu. It is given as an enumeration value of **AC_ONBOOTURI_t** indicating either the AutoConnect root path or the user screen home path.
<dl class="apidl"> <dl class="apidl">
@ -93,7 +101,7 @@ Specify the location to be redirected after module reset in the AutoConnect menu
<dd><span class="apidef" style="width:230px;">AC_ONBOOTURI_HOME</span>It is redirected to the uri specified by [**AutoConnectConfig::homeUri**](apiconfig.md#homeuri).</dd> <dd><span class="apidef" style="width:230px;">AC_ONBOOTURI_HOME</span>It is redirected to the uri specified by [**AutoConnectConfig::homeUri**](apiconfig.md#homeuri).</dd>
</dl> </dl>
### boundaryOffset ### <i class="fa fa-caret-right"></i> boundaryOffset
Sets the offset address of the credential storage area for EEPROM. This value must be between greater than 4 and less than flash sector size. (4096 by SDK) Sets the offset address of the credential storage area for EEPROM. This value must be between greater than 4 and less than flash sector size. (4096 by SDK)
The default value is 0. The default value is 0.
@ -105,7 +113,7 @@ The default value is 0.
!!! warning "It will conflict with user data." !!! warning "It will conflict with user data."
If the sketch leaves this offset at zero, it will conflict the storage area of credentials with the user sketch owned data. It needs to use the behind of credential area. If the sketch leaves this offset at zero, it will conflict the storage area of credentials with the user sketch owned data. It needs to use the behind of credential area.
### channel ### <i class="fa fa-caret-right"></i> channel
The channel number of WIFi when SoftAP starts. The channel number of WIFi when SoftAP starts.
<dl class="apidl"> <dl class="apidl">
@ -118,7 +126,7 @@ The channel number of WIFi when SoftAP starts.
!!! info "How do I choose Channel" !!! info "How do I choose Channel"
Espressif Systems had announced the [application note](https://www.espressif.com/sites/default/files/esp8266_wi-fi_channel_selection_guidelines.pdf) about Wi-Fi channel selection. Espressif Systems had announced the [application note](https://www.espressif.com/sites/default/files/esp8266_wi-fi_channel_selection_guidelines.pdf) about Wi-Fi channel selection.
### dns1 ### <i class="fa fa-caret-right"></i> dns1
Set primary DNS server address when using static IP address. Set primary DNS server address when using static IP address.
<dl class="apidl"> <dl class="apidl">
@ -126,7 +134,7 @@ Set primary DNS server address when using static IP address.
<dd>IPAddress</dd> <dd>IPAddress</dd>
</dl> </dl>
#### dns2 ### <i class="fa fa-caret-right"></i> dns2
Set secondary DNS server address when using static IP address. Set secondary DNS server address when using static IP address.
<dl class="apidl"> <dl class="apidl">
@ -134,7 +142,7 @@ Set secondary DNS server address when using static IP address.
<dd>IPAddress</dd> <dd>IPAddress</dd>
</dl> </dl>
### gateway ### <i class="fa fa-caret-right"></i> gateway
Sets gateway address for Soft AP in captive portal. When AutoConnect fails the initial WiFi.begin, it starts the captive portal with the IP address specified this. Sets gateway address for Soft AP in captive portal. When AutoConnect fails the initial WiFi.begin, it starts the captive portal with the IP address specified this.
<dl class="apidl"> <dl class="apidl">
@ -142,7 +150,7 @@ Sets gateway address for Soft AP in captive portal. When AutoConnect fails the i
<dd><span class="apidef" style="width:230px;">IPAddress</span>The default value is **192.168.244.1**</dd> <dd><span class="apidef" style="width:230px;">IPAddress</span>The default value is **192.168.244.1**</dd>
</dl> </dl>
### hidden ### <i class="fa fa-caret-right"></i> hidden
Sets SoftAP to hidden SSID. Sets SoftAP to hidden SSID.
<dl class="apidl"> <dl class="apidl">
@ -153,7 +161,7 @@ Sets SoftAP to hidden SSID.
<dd><span class="apidef" style="width:230px;">1</span>SSID will be hidden.</dd> <dd><span class="apidef" style="width:230px;">1</span>SSID will be hidden.</dd>
</dl> </dl>
### homeUri ### <i class="fa fa-caret-right"></i> homeUri
Sets the home path of user sketch. This path would be linked from 'HOME' in the AutoConnect menu. The default for homeUri is "/". Sets the home path of user sketch. This path would be linked from 'HOME' in the AutoConnect menu. The default for homeUri is "/".
<dl class="apidl"> <dl class="apidl">
@ -161,7 +169,7 @@ Sets the home path of user sketch. This path would be linked from 'HOME' in the
<dd>String</dd> <dd>String</dd>
</dl> </dl>
### hostName ### <i class="fa fa-caret-right"></i> hostName
Sets the station host name of ESP8266/ESP32. Sets the station host name of ESP8266/ESP32.
<dl class="apidl"> <dl class="apidl">
@ -169,7 +177,7 @@ Sets the station host name of ESP8266/ESP32.
<dd>String</dd> <dd>String</dd>
</dl> </dl>
### immediateStart ### <i class="fa fa-caret-right"></i> immediateStart
Disable the first WiFi.begin() and start the captive portal. If this option is enabled, the module will be in AP_STA mode and the captive portal will be activated regardless of [**AutoConnectConfig::autoRise**](apiconfig.md#autorise) specification. Disable the first WiFi.begin() and start the captive portal. If this option is enabled, the module will be in AP_STA mode and the captive portal will be activated regardless of [**AutoConnectConfig::autoRise**](apiconfig.md#autorise) specification.
<dl class="apidl"> <dl class="apidl">
@ -180,7 +188,7 @@ Disable the first WiFi.begin() and start the captive portal. If this option is e
<dd><span class="apidef" style="width:230px;">false</span>Enable the first WiFi.begin() and it will start captive portal when connection failed. This is default.</dd> <dd><span class="apidef" style="width:230px;">false</span>Enable the first WiFi.begin() and it will start captive portal when connection failed. This is default.</dd>
</dl> </dl>
### netmask ### <i class="fa fa-caret-right"></i> netmask
Sets subnet mask for Soft AP in captive portal. When AutoConnect fails the initial WiFi.begin, it starts the captive portal with the IP address specified this. Sets subnet mask for Soft AP in captive portal. When AutoConnect fails the initial WiFi.begin, it starts the captive portal with the IP address specified this.
<dl class="apidl"> <dl class="apidl">
@ -188,7 +196,15 @@ Sets subnet mask for Soft AP in captive portal. When AutoConnect fails the initi
<dd><span class="apidef" style="width:230px;">IPAddress</span>The default value is **255.255.255.0**</dd> <dd><span class="apidef" style="width:230px;">IPAddress</span>The default value is **255.255.255.0**</dd>
</dl> </dl>
### psk ### <i class="fa fa-caret-right"></i> portalTimeout
Specify the timeout value of the captive portal in [ms] units. It is valid when the station is not connected and does not time out if the station is connected to the ESP module in SoftAP mode (ie Attempting WiFi connection with the portal function). If 0, the captive portal will not be timed-out.
<dl class="apidl">
<dt>**Type**</dt>
<dd><span class="apidef" style="width:230px;">unsigned long</span>Captive portal timeout value. The default value is 0.</dd>
</dl>
### <i class="fa fa-caret-right"></i> psk
Sets password for SoftAP. The length should be from 8 to up to 63. The default value is **12345678**. Sets password for SoftAP. The length should be from 8 to up to 63. The default value is **12345678**.
<dl class="apidl"> <dl class="apidl">
@ -196,7 +212,21 @@ Sets password for SoftAP. The length should be from 8 to up to 63. The default v
<dd>String</dd> <dd>String</dd>
</dl> </dl>
### staip ### <i class="fa fa-caret-right"></i> retainlPortal
Specify whether to continue the portal function even if the captive portal timed out. If the true, when a timeout occurs, the [**AutoConnect::begin**](api.md#begin) function is exited with returns false, but the portal facility remains alive. So SoftAP remains alive and you can invoke AutoConnect while continuing sketch execution. The default is false.
<dl class="apidl">
<dt>**Type**</dt>
<dd>bool</dd>
<dt>**Value**</dt>
<dd><span class="apidef" style="width:230px;">true</span>Continue the portal function even if the captive portal times out. The STA + SoftAP mode of the ESP module continues and accepts the connection request to the AP.</dd>
<dd><span class="apidef" style="width:230px;">false</span>When the captive portal times out, STA + SoftAP mode of the ESP module is stopped. This is default.</dd>
</dl>
!!! hint "Connection request after timed-out"
With the **retainPortal**, even if AutoConnect::begin in the setup() is timed out, you can execute the sketch and the portal function as a WiFi connection attempt by calling AutoConnect::handleClient in the loop().
### <i class="fa fa-caret-right"></i> staip
Set a static IP address. The IP will behave with STA mode. Set a static IP address. The IP will behave with STA mode.
<dl class="apidl"> <dl class="apidl">
@ -204,7 +234,7 @@ Set a static IP address. The IP will behave with STA mode.
<dd>IPAddress</dd> <dd>IPAddress</dd>
</dl> </dl>
### staGateway ### <i class="fa fa-caret-right"></i> staGateway
Set the gateway address when using static IP address. Set the gateway address when using static IP address.
<dl class="apidl"> <dl class="apidl">
@ -212,7 +242,7 @@ Set the gateway address when using static IP address.
<dd>IPAddress</dd> <dd>IPAddress</dd>
</dl> </dl>
### staNetmask ### <i class="fa fa-caret-right"></i> staNetmask
Set the subnetmask when using static IP address. Set the subnetmask when using static IP address.
<dl class="apidl"> <dl class="apidl">
@ -231,7 +261,9 @@ Config.gateway = IPAddress(192,168,10,1); // Sets WLAN router IP address
Config.netmask = IPAddress(255,255,255,0); // Sets WLAN scope Config.netmask = IPAddress(255,255,255,0); // Sets WLAN scope
Config.autoReconnect = true; // Enable auto-reconnect Config.autoReconnect = true; // Enable auto-reconnect
Config.autoSave = AC_SAVECREDENTIAL_NEVER; // No save credential Config.autoSave = AC_SAVECREDENTIAL_NEVER; // No save credential
COnfig.boundaryOffet = 64; // Reserve 64 bytes for the user data in EEPROM. Config.boundaryOffet = 64; // Reserve 64 bytes for the user data in EEPROM.
Config.portalTimeout = 60000; // Sets timeout value for the captive portal
Config.retainPortal = true; // Retains the portal function after timed-out
Config.homeUri = "/index.html" // Sets home path of the sketch application Config.homeUri = "/index.html" // Sets home path of the sketch application
Config.staip = IPAddress(192,168,10,10); // Sets static IP Config.staip = IPAddress(192,168,10,10); // Sets static IP
Config.staGateway = IPAddress(192,168,10,1); // Sets WiFi router address Config.staGateway = IPAddress(192,168,10,1); // Sets WiFi router address

@ -52,7 +52,7 @@ void AutoConnect::_initialize() {
_responsePage = nullptr; _responsePage = nullptr;
_currentPageElement = nullptr; _currentPageElement = nullptr;
_menuTitle = String(AUTOCONNECT_MENU_TITLE); _menuTitle = String(AUTOCONNECT_MENU_TITLE);
_portalTimeout = AUTOCONNECT_TIMEOUT; _connectTimeout = AUTOCONNECT_TIMEOUT;
memset(&_credential, 0x00, sizeof(struct station_config)); memset(&_credential, 0x00, sizeof(struct station_config));
_aux.release(); _aux.release();
} }
@ -86,11 +86,15 @@ bool AutoConnect::begin() {
*/ */
bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long timeout) { bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long timeout) {
bool cs; bool cs;
bool hasTimeout;
// Overwrite for the current timeout value. // Overwrite for the current timeout value.
_portalTimeout = timeout; _connectTimeout = timeout;
// Start WiFi connection with station mode. // Start WiFi connection with station mode.
#if defined(ARDUINO_ARCH_ESP32)
WiFi.softAPdisconnect(false);
#endif
WiFi.enableAP(false); WiFi.enableAP(false);
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
delay(100); delay(100);
@ -133,7 +137,7 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long
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(_connectTimeout) == WL_CONNECTED;
} }
// Reconnect with a valid credential as the autoReconnect option is enabled. // Reconnect with a valid credential as the autoReconnect option is enabled.
@ -145,7 +149,7 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long
const char* psk = strlen(reinterpret_cast<const char*>(_credential.password)) ? reinterpret_cast<const char*>(_credential.password) : nullptr; const char* psk = strlen(reinterpret_cast<const char*>(_credential.password)) ? reinterpret_cast<const char*>(_credential.password) : nullptr;
WiFi.begin(reinterpret_cast<const char*>(_credential.ssid), psk); WiFi.begin(reinterpret_cast<const char*>(_credential.ssid), psk);
AC_DBG("WiFi.begin(%s%s%s)\n", _credential.ssid, psk == nullptr ? "" : ",", psk == nullptr ? "" : psk); AC_DBG("WiFi.begin(%s%s%s)\n", _credential.ssid, psk == nullptr ? "" : ",", psk == nullptr ? "" : psk);
cs = _waitForConnect(_portalTimeout) == WL_CONNECTED; cs = _waitForConnect(_connectTimeout) == WL_CONNECTED;
} }
} }
_currentHostIP = WiFi.localIP(); _currentHostIP = WiFi.localIP();
@ -192,10 +196,18 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long
_startDNSServer(); _startDNSServer();
// Start the captive portal to make a new connection // Start the captive portal to make a new connection
hasTimeout = false;
_portalAccessPeriod = millis();
while (WiFi.status() != WL_CONNECTED && !_rfReset) { while (WiFi.status() != WL_CONNECTED && !_rfReset) {
handleClient(); handleClient();
// Force execution of queued processes. // Force execution of queued processes.
yield(); yield();
// Check timeout
if (_hasTimeout(_apConfig.portalTimeout)) {
hasTimeout = true;
AC_DBG("CP timeout exceeded:%ld\n", millis() - _portalAccessPeriod);
break;
}
} }
cs = WiFi.status() == WL_CONNECTED; cs = WiFi.status() == WL_CONNECTED;
@ -204,6 +216,17 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long
_dnsServer->stop(); _dnsServer->stop();
_dnsServer.reset(); _dnsServer.reset();
} }
// Captive portal styaing time exceeds timeout,
// Close the portal if an option for keeping the portal is false.
else if (hasTimeout) {
if (_apConfig.retainPortal) {
_purgePages();
AC_DBG("Maintain portal\n");
}
else {
_stopPortal();
}
}
} }
} }
} }
@ -395,7 +418,7 @@ void AutoConnect::handleRequest() {
// An attempt to establish a new AP. // An attempt to establish a new AP.
AC_DBG("Request for %s\n", reinterpret_cast<const char*>(_credential.ssid)); AC_DBG("Request for %s\n", reinterpret_cast<const char*>(_credential.ssid));
WiFi.begin(reinterpret_cast<const char*>(_credential.ssid), reinterpret_cast<const char*>(_credential.password), _apConfig.channel); WiFi.begin(reinterpret_cast<const char*>(_credential.ssid), reinterpret_cast<const char*>(_credential.password), _apConfig.channel);
if (_waitForConnect(_portalTimeout) == WL_CONNECTED) { if (_waitForConnect(_connectTimeout) == WL_CONNECTED) {
if (WiFi.BSSID() != NULL) { if (WiFi.BSSID() != NULL) {
memcpy(_credential.bssid, WiFi.BSSID(), sizeof(station_config::bssid)); memcpy(_credential.bssid, WiFi.BSSID(), sizeof(station_config::bssid));
_currentHostIP = WiFi.localIP(); _currentHostIP = WiFi.localIP();
@ -552,6 +575,32 @@ bool AutoConnect::_captivePortal() {
return false; return false;
} }
/**
* Check whether the stay-time in the captive portal has a timeout.
*/
bool AutoConnect::_hasTimeout(unsigned long timeout) {
uint8_t staNum;
if (!_apConfig.portalTimeout)
return false;
#if defined(ARDUINO_ARCH_ESP8266)
staNum = 0;
struct station_info* station = wifi_softap_get_station_info();
while (station) {
staNum++;
station = STAILQ_NEXT(station, next);
}
wifi_softap_free_station_info();
#elif defined(ARDUINO_ARCH_ESP32)
staNum = WiFi.softAPgetStationNum();
#endif
if (staNum)
_portalAccessPeriod = millis();
return (millis() - _portalAccessPeriod > timeout) ? true : false;
}
/** /**
* A handler that redirects access to the captive portal to the connection * A handler that redirects access to the captive portal to the connection
* configuration page. * configuration page.
@ -656,6 +705,7 @@ String AutoConnect::_invokeResult(PageArgument& args) {
* a part of the handling of http request originated from handleClient. * a part of the handling of http request originated from handleClient.
*/ */
bool AutoConnect::_classifyHandle(HTTPMethod method, String uri) { bool AutoConnect::_classifyHandle(HTTPMethod method, String uri) {
_portalAccessPeriod = millis();
AC_DBG("Host:%s, URI:%s", _webServer->hostHeader().c_str(), uri.c_str()); AC_DBG("Host:%s, URI:%s", _webServer->hostHeader().c_str(), uri.c_str());
// When handleClient calls RequestHandler, the parsed http argument remains // When handleClient calls RequestHandler, the parsed http argument remains
@ -683,10 +733,7 @@ bool AutoConnect::_classifyHandle(HTTPMethod method, String uri) {
} }
// Dispose decrepit page // Dispose decrepit page
_responsePage->clearElement(); _purgePages();
if (_currentPageElement != nullptr)
delete _currentPageElement;
_uri = String("");
// Create the page dynamically // Create the page dynamically
if ((_currentPageElement = _setupPage(uri)) == nullptr) if ((_currentPageElement = _setupPage(uri)) == nullptr)
@ -704,6 +751,18 @@ bool AutoConnect::_classifyHandle(HTTPMethod method, String uri) {
return _currentPageElement != nullptr ? true : false; return _currentPageElement != nullptr ? true : false;
} }
/**
* Purge allocated pages.
*/
void AutoConnect::_purgePages() {
_responsePage->clearElement();
if (_currentPageElement != nullptr) {
delete _currentPageElement;
_currentPageElement = nullptr;
}
_uri = String("");
}
/** /**
* It checks whether the specified character string is a valid IP address. * It checks whether the specified character string is a valid IP address.
* @param ipStr IP string for validation. * @param ipStr IP string for validation.

@ -67,6 +67,8 @@ class AutoConnectConfig {
autoReset(true), autoReset(true),
autoReconnect(false), autoReconnect(false),
immediateStart(false), immediateStart(false),
retainPortal(false),
portalTimeout(AUTOCONNECT_CAPTIVEPORTAL_TIMEOUT),
hostName(String("")), hostName(String("")),
homeUri(AUTOCONNECT_HOMEURI), homeUri(AUTOCONNECT_HOMEURI),
staip(0U), staip(0U),
@ -77,7 +79,7 @@ class AutoConnectConfig {
/** /**
* Configure by SSID for the captive portal access point and password. * Configure by SSID for the captive portal access point and password.
*/ */
AutoConnectConfig(const char* ap, const char* password, const uint8_t channel = AUTOCONNECT_AP_CH) : AutoConnectConfig(const char* ap, const char* password, const unsigned long portalTimeout = 0, const uint8_t channel = AUTOCONNECT_AP_CH) :
apip(AUTOCONNECT_AP_IP), apip(AUTOCONNECT_AP_IP),
gateway(AUTOCONNECT_AP_GW), gateway(AUTOCONNECT_AP_GW),
netmask(AUTOCONNECT_AP_NM), netmask(AUTOCONNECT_AP_NM),
@ -93,6 +95,8 @@ class AutoConnectConfig {
autoReset(true), autoReset(true),
autoReconnect(false), autoReconnect(false),
immediateStart(false), immediateStart(false),
retainPortal(false),
portalTimeout(portalTimeout),
hostName(String("")), hostName(String("")),
homeUri(AUTOCONNECT_HOMEURI), homeUri(AUTOCONNECT_HOMEURI),
staip(0U), staip(0U),
@ -119,6 +123,8 @@ class AutoConnectConfig {
autoReset = o.autoReset; autoReset = o.autoReset;
autoReconnect = o.autoReconnect; autoReconnect = o.autoReconnect;
immediateStart = o.immediateStart; immediateStart = o.immediateStart;
retainPortal = o.retainPortal;
portalTimeout = o.portalTimeout;
hostName = o.hostName; hostName = o.hostName;
homeUri = o.homeUri; homeUri = o.homeUri;
staip = o.staip; staip = o.staip;
@ -144,6 +150,8 @@ class AutoConnectConfig {
bool autoReset; /**< Reset ESP8266 module automatically when WLAN disconnected. */ bool autoReset; /**< Reset ESP8266 module automatically when WLAN disconnected. */
bool autoReconnect; /**< Automatic reconnect with past SSID */ bool autoReconnect; /**< Automatic reconnect with past SSID */
bool immediateStart; /**< Skips WiFi.begin(), start portal immediately */ bool immediateStart; /**< Skips WiFi.begin(), start portal immediately */
bool retainPortal; /**< Even if the captive portal times out, it maintains the portal state. */
unsigned long portalTimeout; /**< Timeout value for stay in the captive portal */
String hostName; /**< host name */ String hostName; /**< host name */
String homeUri; /**< A URI of user site */ String homeUri; /**< A URI of user site */
IPAddress staip; /**< Station static IP address */ IPAddress staip; /**< Station static IP address */
@ -197,6 +205,7 @@ class AutoConnect {
bool _loadAvailCredential(); bool _loadAvailCredential();
void _stopPortal(); void _stopPortal();
bool _classifyHandle(HTTPMethod mothod, String uri); bool _classifyHandle(HTTPMethod mothod, String uri);
void _purgePages(void);
PageElement* _setupPage(String uri); PageElement* _setupPage(String uri);
#ifdef AUTOCONNECT_USE_JSON #ifdef AUTOCONNECT_USE_JSON
bool _load(JsonVariant& aux); bool _load(JsonVariant& aux);
@ -210,6 +219,7 @@ class AutoConnect {
/** For portal control */ /** For portal control */
bool _captivePortal(); bool _captivePortal();
bool _hasTimeout(unsigned long timeout);
bool _isIP(String ipStr); bool _isIP(String ipStr);
wl_status_t _waitForConnect(unsigned long timeout); wl_status_t _waitForConnect(unsigned long timeout);
void _disconnectWiFi(bool wifiOff); void _disconnectWiFi(bool wifiOff);
@ -242,7 +252,8 @@ class AutoConnect {
AutoConnectConfig _apConfig; AutoConnectConfig _apConfig;
struct station_config _credential; struct station_config _credential;
uint8_t _hiddenSSIDCount; uint8_t _hiddenSSIDCount;
unsigned long _portalTimeout; unsigned long _connectTimeout;
unsigned long _portalAccessPeriod;
/** The control indicators */ /** The control indicators */
bool _rfConnect; /**< URI /connect requested */ bool _rfConnect; /**< URI /connect requested */

@ -75,7 +75,6 @@
#ifndef AUTOCONNECT_MENU_TITLE #ifndef AUTOCONNECT_MENU_TITLE
#define AUTOCONNECT_MENU_TITLE "AutoConnect" #define AUTOCONNECT_MENU_TITLE "AutoConnect"
#endif // !AUTOCONNECT_MENU_TITLE #endif // !AUTOCONNECT_MENU_TITLE
#define AUTOCONNECT_MENU_TITLE_CONNETED "Connected"
// URIs of AutoConnect menu collection // URIs of AutoConnect menu collection
#define AUTOCONNECT_URI_CONFIG AUTOCONNECT_URI "/config" #define AUTOCONNECT_URI_CONFIG AUTOCONNECT_URI "/config"
@ -92,6 +91,11 @@
#define AUTOCONNECT_TIMEOUT 30000 #define AUTOCONNECT_TIMEOUT 30000
#endif // !AUTOCONNECT_TIMEOUT #endif // !AUTOCONNECT_TIMEOUT
// Captive portal timeout value
#ifndef AUTOCONNECT_CAPTIVEPORTAL_TIMEOUT
#define AUTOCONNECT_CAPTIVEPORTAL_TIMEOUT 0
#endif // !AUTOCONNECT_CAPTIVEPORTAL_TIMEOUT
// Advance wait time // Advance wait time
#ifndef AUTOCONNECT_STARTUPTIME #ifndef AUTOCONNECT_STARTUPTIME
#define AUTOCONNECT_STARTUPTIME (AUTOCONNECT_TIMEOUT/1000) #define AUTOCONNECT_STARTUPTIME (AUTOCONNECT_TIMEOUT/1000)

Loading…
Cancel
Save