Skip to content

AutoConnect WiFi connection control

AutoConnect aims to connect the ESP module as a station to a WiFi access point and equips with various APIs to maintain a WiFi connection as possible while sketch running. The main APIs are AutoConnect::begin and AutoConnect::handleClient. You can make sketches with flexible WiFi connection capability by properly using these two APIs and the settings by AutoConnectConfig.

Automatic reconnect

AutoConnect will change the WiFi mode depending on the situation. The AutoConnect::begin function starts the Web Server with WIFI_STA mode when the connection is successful with 1st-WiFi.begin. If the connection with the last access point fails, AutoConnect will switch the WiFi mode to WIFI_AP_STA, launching a DNS server and allowing the ESP module to launch the captive portal.

The captive portal launches SoftAP at its start and disconnects the STA. At this time, the ESP module discards its stored station configuration data (known as the SDK's station_config structure). This is the default behavior of AutoConnect.

On the other hand, AutoConnect can connect to an access point again that has disconnected once, and its control is allowed by AutoConnectConfig::autoReconnect that option specifies to attempt to reconnect to the past established access point using the saved credentials. If the autoReconnect is enabled, AutoConnect will not launch SoftAP immediately even if 1st-WiFi.begin fails. When AutoConnect fails WiFi connection, it will scan the WiFi signal and try to find the access point that the ESP module has connected to in the past. If AutoConnect finds one of the saved credentials from the broadcast with BSSID, it will explicitly apply the matching credential and attempt to reconnect while in WIFI_STA mode. (AutoReconnect works well even with hidden SSID access points)

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

The autoReconnect option is only available for AutoConnect::begin without SSID and PASSWORD parameter. If you use AutoConnect::begin with an SSID and PASSWORD, no reconnection attempt will be made if the 1st-WiFi.begin fails to connect to that SSID.

The autoReconnect is not autoreconnect

The WiFiSTAClass::disconnect 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 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 the arduino-esp32 core. AutoConnect's automatic reconnection is a mechanism independent from the automatic reconnection of the arduino-esp32 core.

Automatic reconnect (Background)

Combining autoReconnect with AutoConnectConfig::reconnectInterval allows you to periodically repeat connection attempts to known access points within AutoConnect::handleClient. This process is pseudo-asynchronous and does not block the Sketch process in the loop() function.

The reconnectInterval specifies the interval time to seek for known access points with saved credentials during the handleClient loop and attempt to connect to the AP.

AutoConnect       Portal;
AutoConnectConfig Config;

void setup() {
  Config.autoReconnect = true;    // Attempt automatic reconnection.
  Config.reconnectInterval = 6;   // Seek interval time is 180[s].
  Portal.config(Config);
  Portal.begin();
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) {
    // Here to do when WiFi is connected.
  }
  else {
    // Here to do when WiFi is not connected.
  }

  Portal.handleClient();
}

Above Sketch shows a configuration example that you want to keep connecting to known access points as long as possible. When the WiFi connection is lost, it will start seeking the WiFi network every 30 seconds during the handleClient loop.

Limitation for automatic reconnection to a specific access point

An access point that ESP module to reconnect automatically depends on whether the SSID and password argument existence with AutoConnect::begin. If the Sketch calls AutoConnect::begin without specifying an SSID or password, the autoReconnect will connect to one of the detected access points and cannot be pre-determined.
The other one, the case of the Sketch specifies SSID and password with AutoConnect::begin, the autoReconnect will try to reconnect to a specified access point periodically during the handleClient loop.

Also, you can combine the background automatic reconnect performing inside the loop function by handleClient with AutoConnectConfig::retainPortal and AutoConnectConfig::autoReset, to enable pop up the captive portal automatically on the client device each time the ESP module disconnects from the access point.

AutoConnect       Portal;
AutoConnectConfig Config;

void setup() {
  Config.autoReset = false;     // Not reset the module even by intentional disconnection using AutoConnect menu.
  Config.autoReconnect = true;  // Reconnect to known access points.
  Config.reconnectInterval = 6; // Reconnection attempting interval is 3[min].
  Config.retainPortal = true;   // Keep the captive portal open.
  Portal.config(Config);
  Portal.begin();
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) {
    // Here to do when WiFi is connected.
  }
  else {
    // Here to do when WiFi is not connected.
  }
}

The effective range of the reconnectInterval depending on the setting value

The range of values that reconnectInterval can take is 0 to 255. (Actual seconds are from 0 to 255×AUTOCONNECT_UNITTIME)
Reconnect behavior depends on the setting value. If it is 0, reconnection will work if the 1st-WiFi.begin in AutoConnect::begin fails and will suspend during the handleClient loop. If reconnectInterval is greater than 0, AutoConnect will attempt to reconnect both in AutoConnect::begin and during the handleClient loop.

Configure WiFi channel

Appropriately specifying the WiFi channel to use for ESP8266 and ESP32 is essential for a stable connection with the access point. AutoConnect remembers the WiFi channel with a credential of the access point once connected and reuses it.

The default channel when a captive portal starts and AutoConnect itself becomes an access point is the AutoConnectConfig::channel member. If this channel is different from the channel of the access point you will attempt to connect, WiFi.begin may fail. The cause is that the ESP module shares the same channel in AP mode and STA mode. If the connection attempt is not stable, specifying a proper channel using AutoConnectConfig::channel may result in a stable connection.

Connects depending on the WiFi signal strength

When the ESP module found the multiple available access points (i.e. AutoConnect has connected in the past), the default behavior AutoConnect will attempt to connect to the least recent one. However, If the ESP module can operate properly with any access point, it is advantageous to establish a connection with the best one of the reception sensitivity.

The AutoConnectConfig::principle parameter has the connection disposition, and specifying AC_PRINCIPLE_RSSI will attempt to connect to one of the highest RSSI value among multiple available access points. Also You can expect stable WiFi connection by specifying the lower limit of signal strength using AutoConnectConfig::minRSSI.
Combining these two parameters allows you to filter the destination AP when multiple available access points are found.

AutoConnectConfig::principle affects the behavior of both 1st-WiFi.begin and autoReconnect. If you specify AC_PRINCIPLE_RECENT for the principle, it will try according to the conventional connection rules, but if you specify AC_PRINCIPLE_RSSI, it will try to connect to the access point that is sending the strongest WiFi signal at that time instead of the last accessed AP. Also, the static IPs will be restored from a saved credential instead of AutoConnectConfig. (The values specified by AutoConnectConfig is ignored)

SSID &
Password
AutoConnectConfig
::principle
Which credentials would be selected Static IPs
AutoConnect
::begin
NULL specified AC_PRINCIPLE_RECENT Nothing, depends on SDK saves Use the specified value of AutoConnectConfig
AC_PRINCIPLE_RSSI Auto-selected credentials with max RSSI Restoring static IPs suitable for the SSID from saved credentials
Specified with the Sketch Not effective By AutoConnect::begin parameters Use the specified value of AutoConnectConfig
AutoReconnect Load from
saved credential
AC_PRINCIPLE_RECENT Recently saved SSID would be chosen Restoring static IPs suitable for the SSID from saved credentials
AC_PRINCIPLE_RSSI Auto-selected credentials with max RSSI

In ESP32, the difference between the AutoConnectConfig::principle and WIFI_ALL_CHANNEL_SCAN in WiFi.begin

In ESP32, if there are multiple access points with the same SSID and PW within reach, WiFi.begin with the SSID and PW explicitly specified will scan all radio channels and connect to the AP which has the highest signal strength. This feature has been enabled since ESP32 Arduino Release 1.0.6. The principle setting is slightly different from this feature.
AutoConnect does not specify the SSID and PW in the 1st-WiFi.begin. It leaves that to the contents stored in the SDK. Even if there is an AP with a stronger signal nearby, it will try to connect to an AP with a smaller channel number. However, in the case where autoReconnect setting will attempt to reconnect, AutoConnect will read the SSID and PW from the saved credentials and explicitly pass them to WiFi.begin. Therefore, in this case, the connection will be made to the AP with the highest signal strength by WIFI_ALL_CHANNEL_SCAN. But it is only valid across multiple APs with the same SSID and PW.
On the other hand, AC_PRINCIPLE_RSSI tries to connect the AP with the strongest signal from the connection candidates after selecting the SSID when multiple APs with different SSIDs are mixed in the reachable range.

Detects connection establishment to AP

The Sketch can detect that the ESP module has established a WiFi connection as a station to the access point. The AutoConnect::begin or AutoConnect::handleClient will transit the control temporarily to the function in the Sketch registered by AutoConnect::onConnect when the ESP module establish a WiFi connection.
The ConnectExit function registered with AutoConnect::onConnect should have the following types and arguments:

void ConnectExit(IPAddress& ip)

The ConnectExit function is of type void. The argument ip is the IP address assigned to the ESP module by the connected AP. AutoConnect::onConnect allows the Sketch registers a ConnectExit function to AutoConnect. Also, you can make the function using a lambda expression.

AutoConnect Portal;

void onConnect(IPAddress& ipaddr) {
  Serial.print("WiFi connected with ");
  Serial.print(WiFi.SSID());
  Serial.print(", IP:");
  Serial.println(ipaddr.toString());
}

void setup() {
  Serial.begin(115200);
  Portal.onConnect(onConnect);  // Register the ConnectExit function
  Portal.begin();
}

void loop() {
  Portal.handleClient();
}

In addition, a sketch that shuts down SoftAP when the ESP module connects to the access point can be described using a lambda expression as follows:

AutoConnect Portal;

void setup() {
  Serial.begin(115200);
  Portal.onConnect([](IPAddress& ipaddr){
    Serial.printf("WiiFi connected with %s, IP:%s\n", WiFi.SSID().c_str(), ipaddr.toString().c_str());
    if (WiFi.getMode() & WIFI_AP) {
      WiFi.softAPdisconnect(true);
      WiFi.enableAP(false);
      Serial.printf("SoftAP:%s shut down\n", WiFi.softAPSSID().c_str());
    }
  });
  Portal.begin();
}

void loop() {
  Portal.handleClient();
}

It is not an event

AutoConnect::onConnect has the same effect on the Sketch as the WiFi.onStationModeConnected, but AutoConnect does not use the event. Sketch can use WiFi.onEvent independently of AutoConnect.

Match with known access points by SSID

By default, AutoConnect uses the BSSID to search for known access points. (Usually, it's the MAC address of the device) By using BSSID as the key to finding the WiFi network, AutoConnect can find even if the access point is hidden. However BSSIDs can change on some mobile hotspots, the BSSID-keyed searches may not be able to find known access points.
If you operate inconvenience in aiming at the access point by BSSID, you can change the collation key from BSSID to SSID by uncommenting AUTOCONNECT_APKEY_SSID macro definition in AutoConnectDefs.h library source code.

#define AUTOCONNECT_APKEY_SSID

Allow you to use PlatformIO as a build system and give the following description to the platformio.ini, you can enable AUTOCONNECT_APKEY_SSID each build without modifying the library source code:

build_flags=-DAUTOCONNECT_APKEY_SSID

Can't be found hidden APs in SSID-keyed

The hidden access point's SSID will be blank on the broadcast. So if the seek key is an SSID, AutoConnect will not find it.

Preserve AP mode

Sketch using AutoConnect can open a gateway to the Internet by connecting to a WiFi router even through use Espressif's peculiar WiFi protocol (e.g. ESP-MESH or ESP-NOW). These specific communication protocols require to keeps AP + STA as the WiFi mode. That is, to apply these protocols, it needs to launch SoftAP by a sketch itself and then call AutoConnect::begin. But the default behavior of AutoConnect::begin will turn off SoftAP always then it will unable to open a connection.

AutoConnectConfig::preserveAPMode setting maintains WIFI_AP mode without disabling SoftAP inside AutoConnect::begin. The Sketch can utilize the WiFi connection via AutoConnect with ESP-MESH and ESP-NOW protocol by enabling this option.

The following diagram quoted from the ESP-MESH documentation that illustrates the typical topology of the MESH network. The module located at the Root Node bridges between the mesh network and the router by an application that handles two protocols, TCP/IP and ESP-MESH. Its SoftAP communicates with the internal mesh network as an interface of the mesh layer. On the other hand, STA performs station communication with the WiFi router as an interface of the TCP/IP layer. AutoConnect allows assists the connection between the router and the STA of the Root Node using AutoConnectConfig::preserveAPMode and starting the SoftAP via Sketch separately.

Also in general, the Sketch should set false to AutoConnectConfig::autoRise, true to AutoConnectConfig::immediateStart when applying to those protocols.

Timeout settings for a connection attempt

AutoConnect uses AutoConnectConfig::beginTimeout value to limit time to attempt when connecting the ESP module to the access point as a WiFi station. The default value is AUTOCONNECT_TIMEOUT defined in AutoConnectDefs.h and the initial value is 30 seconds. (actually specified in milliseconds)
For example, the following sketch sets the connection timeout to 15 seconds:

AutoConnect Portal;
AutoConnectConfig Config;

void setup() {
  Config.beginTimeout = 15000; // Timeout sets to 15[s]
  Portal.config(Config);
  Portal.begin();
}

void loop () {
  Portal.handleClient();
}

In addition, the limit of the waiting time for connection attempts can be specified by the AutoConnect::begin parameter too. The timeout parameter specified in AutoConnect::begin takes precedence over AutoConnectConfig::beginTimeout.

The beginTimeout has an effect on handleClient

The beginTimeout value will be applied with handleClient when requesting a connection from the captive portal and when attempting to reconnect with autoReconnect.

Verify the WiFi connection conditions

AutoConnect has the following indicators regarding WiFi connection attempts. These states are indicated as bitwise values and are the logical disjunction of multiple states. For example, if the 1st-WiFi.begin fails and the connection is restored by the AutoConnectConfig::autoReconnect setting, this status value will indicate both AC_AUTORECONNECT and AC_ESTABLISHED.

A sketch can get this status value using the AutoConnect::portalStatus function. AutoConnect::portalStatus returns a value of type uint8_t. The return value is a bitwise value that indicates each status in the table below. In the sketch, the WiFi connection status is detected by taking the AND of the return value and the enum value shown in the following table:

Values of the status indication WiFi connection situations
AutoConnect::AC_IDLE Initial state: This is the initial state, AutoConnect is not making any WiFi connection attempts. This state is reached immediately after AutoConnect::begin starts.
AutoConnect::AC_ESTABLISHED Connection successful: Successfully connected to the WiFi access point.
AutoConnect::AC_AUTORECONNECT The autoReconnect was applied: AutoConnectConfig::autoReconnect setting was applied during the WiFi connection attempt process. This flag does not indicate a successful connection. It only shows that a condition that triggers autoReconnect has occurred. Whether the connection was actually successful should be determined by WiFi.status()==WL_CONNECTED.
AutoConnect::AC_TIMEOUT Connection timeout: WiFi connection attempt timed out. Or, the captive portal was shut down by the AutoConnectConfig::portalTimeout setting.
AutoConnect::AC_INTERRUPT Connection interrupted due to an indication with the exit: The whileConnecting exit routine returned false. or the whileCaptivePortal exit routine returned false. AutoConnect aborted the WiFi connection attempt with those indications.
AutoConnect::AC_CAPTIVEPORTAL Captive portal is available: SoftAP mode is enabled, and the DNS server is available. AutoConnect will redirect connection requests to SoftAP from client devices to a captive portal site within AutoConnect. The state of this flag is equivalent to the return value of AutoConnect::isPortalAvailable function.
NOTE: AC_CAPTIVEPORTAL is false if only SoftAP is available and no DNS server is enabled.
AutoConnect::AC_INPROGRESS WiFi.begin in progress: AutoConnect requests WiFi.begin and is waiting for the connection to succeed or times out; this state will reset when terminating WiFi.begin attempts.
AutoConnect portal;
AutoConnectConfig config;

uint8_t state;

void setup() {
  // Configure automatic reconnection and captive portal retention, then start
  // AutoConnect. In subsequent steps, it will use the portalStatus function to
  // detect the WiFi connection status in this configuration.
  config.portalTimeout = 180000;
  config.autoReconnect = true;
  config.reconnectInterval = 1;
  config.retainPortal = true;
  portal.config(config);

  portal.begin();

  state = portal.portalStatus();
  if (WiFi.status() == WL_CONNECTED) {
    if (state & AutoConnect::AC_AUTORECONNECT)
      Serial.println("Auto reconnection applied");
  }
  else {
    if (state & AutoConnect::AC_TIMEOUT)
      Serial.println("Connection timeout");
  }

  if (state & AutoConnect::AC_CAPTIVEPORTAL)
    Serial.println("Captive portal is still alive");
  else
    Serial.println("Captive portal is not available");
}

void loop() {
  portal.handleClient();
  uint8_t transition = portal.portalStatus();

  if (transition != state) {
    if (transition & AutoConnect::AC_CAPTIVEPORTAL)
      Serial.println("Captive portal activated");
    if (transition & AutoConnect::AC_AUTORECONNECT)
      Serial.println("Auto reconnection applied");
    if (!(transition & AutoConnect::AC_ESTABLISHED))
      Serial.println("WiFi connection lost");

    state = transition;
  }
}

AutoConnect::portalStatus within the loop of AutoConnect::handleClient

AutoConnect::portalStatus function is also valid during the AutoConnect::handleClient loop inside the loop function. With the background reconnection enabled using the AutoConnectConfig::autoReconnect and AutoConnectConfig::reconnectInterval settings, the AutoConnect::portalStatus function will return a value indicating the reconnection status at every time AutoConnect::handleClient in the loop().