In this guide, you’ll create and set up a Wi-Fi Manager with the ESPAsyncWebServer library that you can modify to use with your web server projects or with any project that needs a connection to a Wi-Fi network. The Wi-Fi Manager allows you to connect the ESP8266 board to different Access Points (networks) without hard-coding network credentials (SSID and password) and upload new code to your board. Your ESP will automatically join the last saved network or set up an Access Point that you can use to configure the network credentials.
To better understand how this project works, we recommend taking a look at the following tutorials:
- Input Data on HTML Form ESP32/ESP8266 Web Server using Arduino IDE
- ESP8266 NodeMCU Access Point (AP) for Web Server
- ESP8266 Static/Fixed IP Address
How it Works
Take a look at the following diagram to understand how the Wi-Fi Manager we’ll create works.
- When the ESP first starts, it tries to read the ssid.txt, pass.txt and ip.txt files* (1);
- If the files are empty (2) (the first time you run the board, the files are empty), your board is set as an access point (3);
- Using any Wi-Fi enabled device with a browser, you can connect to the newly created Access Point (default name ESP-WIFI-MANAGER);
- After establishing a connection with the ESP-WIFI-MANAGER, you can go to the default IP address 192.168.4.1 to open a web page that allows you to configure your SSID and password (4);
- The SSID, password, and IP address inserted in the form are saved in the corresponding files: ssid.txt, pass.txt, and ip.txt (5);
- After that, the ESP board restarts (6);
- This time, after restarting, the files are not empty, so the ESP will try to connect to the network in station mode using the settings you’ve inserted in the form (7);
- If it establishes a connection, the process is completed successfully, and you can access the main web server page that can do whatever you want (control sensor readings, control outputs, display some text, etc.) (9). Otherwise, it will set the Access Point (3), and you can access the default IP address (192.168.4.1) to add another SSID/password combination.
* we also created a gateway field and a gateway.txt file to save the IP address gateway (this is not shown in the diagram).
To show you how to set the Wi-Fi Manager, we’ll set up a web server that controls one output (GPIO2—the built-in LED). You can apply the Wi-Fi Manager to any web server project built with the ESPAsyncWebServer library or to any project that requires the ESP to be connected to a wi-fi network.
Prerequisites
We’ll program the ESP8266 board using Arduino IDE. So make sure you have the ESP8266 board add-on installed.
If you want to program the ESP8266 using VS Code + PlatformIO, follow the next tutorial:
Installing Libraries (Arduino IDE)
You need to install the following libraries in your Arduino IDE to build the web server for this project.
- ESPAsyncWebServer (.zip folder)
- ESPAsyncTCP (.zip folder)
The ESPAsyncWebServer, and ESPAsyncTCP libraries aren’t available to install through the Arduino Library Manager, so you need to copy the library files to the Arduino installation Libraries folder. Alternatively, in your Arduino IDE, you can go to Sketch > Include Library > Add .zip Library and select the libraries you’ve just downloaded.
Installing Libraries (VS Code + PlatformIO)
If you’re programming the ESP8266 using PlatformIO, copy the following to the platformio.ini to include the ESPAsyncWebServer library (it will automatically include any dependencies like the ESPAsyncTCP libraries), change the baud rate to 115200 and set the filesystem to LittleFS:
monitor_speed = 115200
lib_deps = ESP Async WebServer
board_build.filesystem = littlefs
Filesystem Uploader
Before proceeding, you need to have the ESP8266 Uploader Plugin installed in your Arduino IDE.
If you’re using VS Code with PlatformIO, follow the next tutorial to learn how to upload files to the filesystem:
Organizing your Files
To keep the project organized and make it easier to understand, we’ll create four different files to build the web server:
- Arduino sketch that handles the web server;
- index.html: to define the content of the web page in station mode to control the output (or any other web page you want to build);
- style.css: to style the web pages;
- wifimanager.html: to define the web page’s content to display the Wi-Fi Manager when the ESP is in access point mode.
You should save the HTML and CSS files inside a folder called data inside the Arduino sketch folder, as shown in the previous diagram. We’ll upload these files to the ESP8266 filesystem (LittleFS).
You can download all project files:
Creating the HTML Files
For this project, you need two HTML files. One to build the main page that controls the output (index.html) and another to build the Wi-Fi Manager page (wifimanager.html).
index.html
Here’s the text you should copy to your index.html file.
<!DOCTYPE html>
<html>
<head>
<title>ESP WEB SERVER</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="style.css">
<link rel="icon" type="image/png" href="favicon.png">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
</head>
<body>
<div class="topnav">
<h1>ESP WEB SERVER</h1>
</div>
<div class="content">
<div class="card-grid">
<div class="card">
<p class="card-title"><i class="fas fa-lightbulb"></i> GPIO 2</p>
<p>
<a href="on"><button class="button-on">ON</button></a>
<a href="off"><button class="button-off">OFF</button></a>
</p>
<p class="state">State: %STATE%</p>
</div>
</div>
</div>
</body>
</html>
We won’t explain how this HTML file works because that’s not the purpose of this tutorial. The purpose of this tutorial is to explain the parts related to the Wi-Fi Manager.
wifimanager.html
The Wi-Fi Manager web page looks like this:
Copy the following to the wifimanager.html file. This creates a web page with a form with four input fields and a Submit button.
<!DOCTYPE html>
<html>
<head>
<title>ESP Wi-Fi Manager</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="topnav">
<h1>ESP Wi-Fi Manager</h1>
</div>
<div class="content">
<div class="card-grid">
<div class="card">
<form action="/" method="POST">
<p>
<label for="ssid">SSID</label>
<input type="text" id ="ssid" name="ssid"><br>
<label for="pass">Password</label>
<input type="text" id ="pass" name="pass"><br>
<label for="ip">IP Address</label>
<input type="text" id ="ip" name="ip" value="192.168.1.200"><br>
<label for="gateway">Gateway Address</label>
<input type="text" id ="gateway" name="gateway" value="192.168.1.1"><br>
<input type ="submit" value ="Submit">
</p>
</form>
</div>
</div>
</div>
</body>
</html>
In this HTML file, we create an HTML form that will make an HTTP POST request with the data submitted to the server.
<form action="/" method="POST">
The form contains four input fields and corresponding labels: SSID, password, IP address, and gateway.
This is the input field for the SSID:
<label for="ssid">SSID</label>
<input type="text" id ="ssid" name="ssid"><br>
This is the input field for the password.
<label for="pass">Password</label>
<input type="text" id ="pass" name="pass"><br>
There is an input field for the IP address that you want to attribute to the ESP in station mode. As default, we set it to 192.168.1.200 (you can set another default IP address, or you can delete the value parameter—it won’t have a default value).
<input type="text" id ="ip" name="ip" value="192.168.1.200">
Finally, there’s an input field for the gateway address. If the default IP address is 192.168.1.200, the gateway can be 192.168.1.1 by default.
<input type="text" id ="gateway" name="gateway" value="192.168.1.1"><br>
CSS File
Copy the following styles to your style.css file. We won’t explain how these styles work. We have already explained how similar styles work in other ESP Web Server projects.
html {
font-family: Arial, Helvetica, sans-serif;
display: inline-block;
text-align: center;
}
h1 {
font-size: 1.8rem;
color: white;
}
p {
font-size: 1.4rem;
}
.topnav {
overflow: hidden;
background-color: #0A1128;
}
body {
margin: 0;
}
.content {
padding: 5%;
}
.card-grid {
max-width: 800px;
margin: 0 auto;
display: grid;
grid-gap: 2rem;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.card {
background-color: white;
box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
}
.card-title {
font-size: 1.2rem;
font-weight: bold;
color: #034078
}
input[type=submit] {
border: none;
color: #FEFCFB;
background-color: #034078;
padding: 15px 15px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
width: 100px;
margin-right: 10px;
border-radius: 4px;
transition-duration: 0.4s;
}
input[type=submit]:hover {
background-color: #1282A2;
}
input[type=text], input[type=number], select {
width: 50%;
padding: 12px 20px;
margin: 18px;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
label {
font-size: 1.2rem;
}
.value{
font-size: 1.2rem;
color: #1282A2;
}
.state {
font-size: 1.2rem;
color: #1282A2;
}
button {
border: none;
color: #FEFCFB;
padding: 15px 32px;
text-align: center;
font-size: 16px;
width: 100px;
border-radius: 4px;
transition-duration: 0.4s;
}
.button-on {
background-color: #034078;
}
.button-on:hover {
background-color: #1282A2;
}
.button-off {
background-color: #858585;
}
.button-off:hover {
background-color: #252524;
}
Setting Up the Web Server
If you’re using VS Code with the platformIO extension, you need to edit the platformio.ini file to look as shown below. If you’re using Arduino IDE, you can ignore this.
platformio.ini ESP8266:
[env:esp12e]
platform = espressif8266
board = esp12e
framework = arduino
monitor_speed = 115200
lib_deps = ESP Async WebServer
board_build.filesystem = littlefs
Code
Copy the following code to your Arduino IDE or to the main.cpp file if you’re using VS Code.
/*********
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete instructions at https://RandomNerdTutorials.com/esp8266-nodemcu-wi-fi-manager-asyncwebserver/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*********/
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <ESPAsyncTCP.h>
#include "LittleFS.h"
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
// Search for parameter in HTTP POST request
const char* PARAM_INPUT_1 = "ssid";
const char* PARAM_INPUT_2 = "pass";
const char* PARAM_INPUT_3 = "ip";
const char* PARAM_INPUT_4 = "gateway";
//Variables to save values from HTML form
String ssid;
String pass;
String ip;
String gateway;
// File paths to save input values permanently
const char* ssidPath = "/ssid.txt";
const char* passPath = "/pass.txt";
const char* ipPath = "/ip.txt";
const char* gatewayPath = "/gateway.txt";
IPAddress localIP;
//IPAddress localIP(192, 168, 1, 200); // hardcoded
// Set your Gateway IP address
IPAddress localGateway;
//IPAddress localGateway(192, 168, 1, 1); //hardcoded
IPAddress subnet(255, 255, 0, 0);
// Timer variables
unsigned long previousMillis = 0;
const long interval = 10000; // interval to wait for Wi-Fi connection (milliseconds)
// Set LED GPIO
const int ledPin = 2;
// Stores LED state
String ledState;
boolean restart = false;
// Initialize LittleFS
void initFS() {
if (!LittleFS.begin()) {
Serial.println("An error has occurred while mounting LittleFS");
}
else{
Serial.println("LittleFS mounted successfully");
}
}
// Read File from LittleFS
String readFile(fs::FS &fs, const char * path){
Serial.printf("Reading file: %s\r\n", path);
File file = fs.open(path, "r");
if(!file || file.isDirectory()){
Serial.println("- failed to open file for reading");
return String();
}
String fileContent;
while(file.available()){
fileContent = file.readStringUntil('\n');
break;
}
file.close();
return fileContent;
}
// Write file to LittleFS
void writeFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Writing file: %s\r\n", path);
File file = fs.open(path, "w");
if(!file){
Serial.println("- failed to open file for writing");
return;
}
if(file.print(message)){
Serial.println("- file written");
} else {
Serial.println("- frite failed");
}
file.close();
}
// Initialize WiFi
bool initWiFi() {
if(ssid=="" || ip==""){
Serial.println("Undefined SSID or IP address.");
return false;
}
WiFi.mode(WIFI_STA);
localIP.fromString(ip.c_str());
localGateway.fromString(gateway.c_str());
if (!WiFi.config(localIP, localGateway, subnet)){
Serial.println("STA Failed to configure");
return false;
}
WiFi.begin(ssid.c_str(), pass.c_str());
Serial.println("Connecting to WiFi...");
delay(20000);
if(WiFi.status() != WL_CONNECTED) {
Serial.println("Failed to connect.");
return false;
}
Serial.println(WiFi.localIP());
return true;
}
// Replaces placeholder with LED state value
String processor(const String& var) {
if(var == "STATE") {
if(!digitalRead(ledPin)) {
ledState = "ON";
}
else {
ledState = "OFF";
}
return ledState;
}
return String();
}
void setup() {
// Serial port for debugging purposes
Serial.begin(115200);
initFS();
// Set GPIO 2 as an OUTPUT
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
// Load values saved in LittleFS
ssid = readFile(LittleFS, ssidPath);
pass = readFile(LittleFS, passPath);
ip = readFile(LittleFS, ipPath);
gateway = readFile (LittleFS, gatewayPath);
Serial.println(ssid);
Serial.println(pass);
Serial.println(ip);
Serial.println(gateway);
if(initWiFi()) {
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(LittleFS, "/index.html", "text/html", false, processor);
});
server.serveStatic("/", LittleFS, "/");
// Route to set GPIO state to HIGH
server.on("/on", HTTP_GET, [](AsyncWebServerRequest *request) {
digitalWrite(ledPin, LOW);
request->send(LittleFS, "/index.html", "text/html", false, processor);
});
// Route to set GPIO state to LOW
server.on("/off", HTTP_GET, [](AsyncWebServerRequest *request) {
digitalWrite(ledPin, HIGH);
request->send(LittleFS, "/index.html", "text/html", false, processor);
});
server.begin();
}
else {
// Connect to Wi-Fi network with SSID and password
Serial.println("Setting AP (Access Point)");
// NULL sets an open Access Point
WiFi.softAP("ESP-WIFI-MANAGER", NULL);
IPAddress IP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(IP);
// Web Server Root URL
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/wifimanager.html", "text/html");
});
server.serveStatic("/", LittleFS, "/");
server.on("/", HTTP_POST, [](AsyncWebServerRequest *request) {
int params = request->params();
for(int i=0;i<params;i++){
const AsyncWebParameter* p = request->getParam(i);
if(p->isPost()){
// HTTP POST ssid value
if (p->name() == PARAM_INPUT_1) {
ssid = p->value().c_str();
Serial.print("SSID set to: ");
Serial.println(ssid);
// Write file to save value
writeFile(LittleFS, ssidPath, ssid.c_str());
}
// HTTP POST pass value
if (p->name() == PARAM_INPUT_2) {
pass = p->value().c_str();
Serial.print("Password set to: ");
Serial.println(pass);
// Write file to save value
writeFile(LittleFS, passPath, pass.c_str());
}
// HTTP POST ip value
if (p->name() == PARAM_INPUT_3) {
ip = p->value().c_str();
Serial.print("IP Address set to: ");
Serial.println(ip);
// Write file to save value
writeFile(LittleFS, ipPath, ip.c_str());
}
// HTTP POST gateway value
if (p->name() == PARAM_INPUT_4) {
gateway = p->value().c_str();
Serial.print("Gateway set to: ");
Serial.println(gateway);
// Write file to save value
writeFile(LittleFS, gatewayPath, gateway.c_str());
}
//Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
}
}
restart = true;
request->send(200, "text/plain", "Done. ESP will restart, connect to your router and go to IP address: " + ip);
});
server.begin();
}
}
void loop() {
if (restart){
delay(5000);
ESP.restart();
}
}
How The Code Works
Let’s take a look at the code and see how the Wi-Fi Manager works.
The following variables are used to search for the SSID, password, IP address, and gateway on the HTTP POST request made when the form is submitted.
// Search for parameter in HTTP POST request
const char* PARAM_INPUT_1 = "ssid";
const char* PARAM_INPUT_2 = "pass";
const char* PARAM_INPUT_3 = "ip";
const char* PARAM_INPUT_4 = "gateway";
The ssid, pass, ip, and gateway variables save the values of the SSID, password, IP address, and gateway submitted in the form.
//Variables to save values from HTML form
String ssid;
String pass;
String ip;
String gateway;
The SSID, password, IP address, and gateway when submitted are saved in files in the ESP filesystem. The following variables refer to the path of those files.
// File paths to save input values permanently
const char* ssidPath = "/ssid.txt";
const char* passPath = "/pass.txt";
const char* ipPath = "/ip.txt";
const char* gatewayPath = "/gateway.txt";
The station IP address and gateway are submitted in the Wi-Fi Manager form. The subnet is hardcoded but you can easily modify this project with another field to include the subnet, if needed.
IPAddress localIP;
//IPAddress localIP(192, 168, 1, 200); // hardcoded
// Set your Gateway IP address
IPAddress localGateway;
//IPAddress localGateway(192, 168, 1, 1); //hardcoded
IPAddress subnet(255, 255, 0, 0);
initWiFi()
The initWiFi() function returns a boolean value (either true or false) indicating if the ESP board connected successfully to a network.
bool initWiFi() {
if(ssid=="" || ip==""){
Serial.println("Undefined SSID or IP address.");
return false;
}
WiFi.mode(WIFI_STA);
localIP.fromString(ip.c_str());
localGateway.fromString(gateway.c_str());
if (!WiFi.config(localIP, localGateway, subnet)){
Serial.println("STA Failed to configure");
return false;
}
WiFi.begin(ssid.c_str(), pass.c_str());
Serial.println("Connecting to WiFi...");
delay(20000);
if(WiFi.status() != WL_CONNECTED) {
Serial.println("Failed to connect.");
return false;
}
Serial.println(WiFi.localIP());
return true;
}
First, it checks if the ssid and ip variables are empty. If they are, it won’t be able to connect to a network, so it returns false.
if(ssid=="" || ip==""){
If that’s not the case, we’ll try to connect to the network using the SSID and password saved in the ssid and pass variables and set the IP address.
WiFi.mode(WIFI_STA);
localIP.fromString(ip.c_str());
localGateway.fromString(gateway.c_str());
if (!WiFi.config(localIP, localGateway, subnet)){
Serial.println("STA Failed to configure");
return false;
}
WiFi.begin(ssid.c_str(), pass.c_str());
Serial.println("Connecting to WiFi...");
If it cannot connect to Wi-Fi after 20 seconds, it will return false.
delay(20000);
if(WiFi.status() != WL_CONNECTED) {
Serial.println("Failed to connect.");
return false;
}
If none of the previous conditions are met, it means that the ESP successfully connected to the network in station mode (returns true).
return true;
setup()
In the setup(), start reading the files to get the previously saved SSID, password, IP address, and gateway.
ssid = readFile(LittleFS, ssidPath);
pass = readFile(LittleFS, passPath);
ip = readFile(LittleFS, ipPath);
gateway = readFile (LittleFS, gatewayPath);
If the ESP connects successfully in station mode (initWiFi() function returns true), we can set the commands to handle the web server requests (or any other code that requires the ESP to be connected to the internet):
if(initWiFi()) {
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(LittleFS, "/index.html", "text/html", false, processor);
});
server.serveStatic("/", LittleFS, "/");
// Route to set GPIO state to HIGH
server.on("/on", HTTP_GET, [](AsyncWebServerRequest *request) {
digitalWrite(ledPin, LOW);
request->send(LittleFS, "/index.html", "text/html", false, processor);
});
// Route to set GPIO state to LOW
server.on("/off", HTTP_GET, [](AsyncWebServerRequest *request) {
digitalWrite(ledPin, HIGH);
request->send(LittleFS, "/index.html", "text/html", false, processor);
});
server.begin();
}
If that’s not the case, the initWiFi() function returns false. The ESP will set an access point:
else {
// Connect to Wi-Fi network with SSID and password
Serial.println("Setting AP (Access Point)");
// NULL sets an open Access Point
WiFi.softAP("ESP-WIFI-MANAGER", NULL);
IPAddress IP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(IP);
To set an access point, we use the softAP() method and pass as arguments the name for the access point and the password. We want the access point to be open, so we set the password to NULL. You can add a password if you wish. To learn more about setting up an Access Point, read one of the following tutorials:
When you access the Access Point, it shows the web page to enter the network credentials in the form. So, the ESP must send the wifimanager.html file when it receives a request on the root / URL.
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/wifimanager.html", "text/html");
});
We must also handle what happens when the form is submitted via an HTTP POST request. The following lines save the submitted values in the ssid, pass, ip, and gateway variables and save those variables in the corresponding files.
server.on("/", HTTP_POST, [](AsyncWebServerRequest *request) {
int params = request->params();
for(int i=0;i<params;i++){
AsyncWebParameter* p = request->getParam(i);
if(p->isPost()){
// HTTP POST ssid value
if (p->name() == PARAM_INPUT_1) {
ssid = p->value().c_str();
Serial.print("SSID set to: ");
Serial.println(ssid);
// Write file to save value
writeFile(LittleFS, ssidPath, ssid.c_str());
}
// HTTP POST pass value
if (p->name() == PARAM_INPUT_2) {
pass = p->value().c_str();
Serial.print("Password set to: ");
Serial.println(pass);
// Write file to save value
writeFile(LittleFS, passPath, pass.c_str());
}
// HTTP POST ip value
if (p->name() == PARAM_INPUT_3) {
ip = p->value().c_str();
Serial.print("IP Address set to: ");
Serial.println(ip);
// Write file to save value
writeFile(LittleFS, ipPath, ip.c_str());
}
// HTTP POST gateway value
if (p->name() == PARAM_INPUT_4) {
gateway = p->value().c_str();
Serial.print("Gateway set to: ");
Serial.println(gateway);
// Write file to save value
writeFile(LittleFS, gatewayPath, gateway.c_str());
}
//Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
}
}
After submitting the form, send a response with some text so that we know that the ESP received the form details:
request->send(200, "text/plain", "Done. ESP will restart, connect to your router and go to IP address: " + ip);
Set the restart variable to true.
restart = true;
In the loop(), we’ll check the value of the restart variable and proceed accordingly.
void loop() {
if (restart){
delay(5000);
ESP.restart();
}
}
That’s a quick summary of how the code works.
You can apply this idea to any of the other web server projects built with the ESPAsyncWebServer library.
Uploading Code and Files
Upload the files in the data folder to your ESP8266. Go to Tools > ESP8266 LittleFS Data Upload.
If you’re using VS Code with the PlatformIO extension, follow one of the next tutorials to learn how to upload files to your boards:
After successfully uploading the files, upload the code to your board.
Demonstration
After successfully uploading all files and sketch, you can open the Serial Monitor. If it is running the code for the first time, it will try to read the ssid.txt, pass.txt, and ip.txt files, and it won’t succeed because those files weren’t created yet. So, it will start an Access Point.
On your computer or smartphone, go to your network settings and connect to the ESP-WIFI-MANAGER access point.
Then, open your browser and go to 192.168.4.1. The Wi-Fi Manager web page should open.
Enter your network credentials: SSID and Password and an available IP address and gateway on your local network.
After that, you’ll be redirected to the following page:
At the same time, the ESP should print something in the Serial Monitor indicating that the parameters you’ve inserted were successfully saved in the corresponding files.
After a few seconds, the ESP will restart. And if you’ve inserted the correct SSID and password, it will start in station mode:
This time, open a browser on your local network and insert the ESP IP address. You should get access to the web page to control the outputs:
Wrapping Up
In this tutorial, you’ve learned how to set up a Wi-Fi Manager for your web server projects or for any other project that requires the ESP to be connected to the internet. With the Wi-Fi Manager, you can easily connect your ESP boards to different networks without the need to hard-code network credentials. You can apply the Wi-Fi Manager to any web server project built with the ESPAsyncWebServer library.
If you want to learn more about building web servers with the ESP32 and ESP8266 boards, make sure you take a look at our eBook:
Learn more about the ESP8266 with our resources:
We hope you’ve found this tutorial useful.
Thanks for reading.
ESPAsyncWebServer.h and ESPAsyncTCP.h run concurrently. One benefit is that when coding in the arduino ide, my home’s wifi location doesn’t have to write the IP:name and password to control the device. It can also be controlled outdoors. As long as my phone is on mobile data (wifi), share to esp8266, it can be used anywhere in the world. Thanks for sharing good article 👍
Great code…sadly I ran into a problem: at the end it will not connect and restarts the WiFimanager.
If I ‘cheat’ a bit and just hard code the ssid and pw then it will connect so I know they are correct.
But if I print the (ssid.c_str()); and (pass.c_str()); values…that are read from memory…then they are also correct…at least, as far as I can see.
So…I will have some further digging to do.
take care
Solved: re-uploading with ‘Erase Sketch and WiFi settings’ seemed to do the trick
Thank you very much. That is exactly what I currently needed in my actual project.
That’s great!
Simply Perfect ! Just two questions.
– Will it be possible to fill a dropdown listbox with all available Wi-Fi SSIDs to make it easy for the user ?
– Secondly, How to store the password encrypted in the file for security ?
Hi, simple question.
If I want to load other SSID and PASWORD values, once I have obtained a correct connection, how do I delete (empty) the text files (that are not visible)?
For example, to switch to another available network within the place of use.
Thanks
Thanks for this wonderful project.
Hello Sara, how can I do this if I want to enter another SSID and password while the device is running in this project. So how can I change the SSID information. Thank you.
Hi.
With the current code it just saves one ssid and password combination,
When the board can’t find the network, for example, the ESP is now in another house, it will create an access point that you can connect to to enter another SSID and password combination.
I hope this answers your question.
Regards,
Sara
Thanks. I want to edit ssid.txt and pass.txt. Is this possible. How can I do it.
Hi.
Yes, you can use the function used in the code to write to the file: the writeFile() function.
You can also check this example that provides several functions to handle the files: https://github.com/esp8266/Arduino/blob/master/libraries/LittleFS/examples/LittleFS_Timestamp/LittleFS_Timestamp.ino
Regards,
Sara
Hi Sara. Thanks for your help. I have a question. Is esp8266’s flash memory suitable for a datalogger. What is your prefer? Thanks.
Hi.
It depends on the amount of data. But, preferably use an SD card or send your data to somewhere in the cloud: thingspeak, google sheets, your own database, firebase, etc…
Regards,
Sara
Hi Sara,
after endless tries to start the WebServer we are at the point of “give-up”.
As mentioned above there is a restart-trap in the following condition:
Als works fine an the server starts. On the first try we got the WiFi-Manager-Form and type in ssid, password an gateway and save those inputs. Server sends on serial the following:
13:16:20.171 -> Dateisystem erfolgreich initialisiert!
13:16:20.171 ->
13:16:20.171 -> Lese Daten von: /ssid.txt
13:16:21.174 -> Lese Daten von: /pass.txt
13:16:22.164 -> Lese Daten von: /ip.txt
13:16:23.171 -> Lese Daten von: /gateway.txt
13:16:24.212 -> Lese Daten von: /subnet.txt
13:16:25.200 -> SSID: (correct, but disabled for safety in this post!)
13:16:25.200 -> Passwort: (disabled for safety in this post!)
13:16:25.200 -> IP-Adresse: 192.168.178.50
13:16:25.200 -> Gateway: 192.168.178.1
13:16:25.200 -> Subnet: 255.255.255.0
13:16:25.200 -> WiFi-Verbindung mit …
13:16:45.223 -> Verbunden mit WLAN-Adresse: 192.168.178.50
13:16:45.223 -> Nutze Access-Point-Modus!
13:16:45.223 -> Access-Point IP-Adresse: 192.168.4.1
As you can see it seems that all is right. But directly after connecting to Router he switched back to access-point-adress 192.168.4.1 and lost connection to router on 192.168.178.50. This is a never ending loop …..
The only qestion left is: How can we delete the files in LittleFS to set all to zero? This should be done as the fastet solution to go ahead with programming and testing. As long as the wrong file-content (maybe wrong passwort e.g.) is in the file-system, there is no chance to start up again.
Hope you can help to solve this endless-Loop-trap.
Thanks and stay healthy,
Manfred
Hi.
When you type the wrong password, or when the board cannot connect to the network, it will initialize in access point mode.
Then, you should connect to that access point again and the form web page will load. Then, you can insert new details that will overwrite the previous.
Regards,
Sara
Hi Manfred, I had the same issue you describe, please connect the esp8266 to the USB without cables and make sure has enough power supply, restarting loop means not enough power.
Hi Sara,
as a beginner i use this code-example and it works fine. I have one question as follow:
I like to extend the wifimanager.html with one more input-field named “router-name”. Coding is simple and writing from variable “routername” to file on “POST-Event” to a coresponding file “routername.txt” works fine.
In setup-routine i read the stored value back in corresponding variable “routername” same way as other values – works also fine. But how can i write the value from the variable to the input-field in wifimanager.html at HTTP_GET-Routine ??? (processor-routine, using innerHTML() or ….)
Thanks for suggestions or a short code-line/sample to do this.
Greetings,
Valentine
Has anyone built this project around a esp32? If so what changes need to be made?
Hi.
Here’s the ESP32 version: https://randomnerdtutorials.com/esp32-wi-fi-manager-asyncwebserver/
Regards,
Sara
Hello,
I want to add WiFi Manager to my project.
I would like to use a time server with the following lines:
configTime(0, 0, “za.pool.ntp.org”, “time.nist.gov”);
setenv(“TZ”, “GMT-1”,1);
Time_format = “M”;
Unfortunately I don’t know where I have to insert the code shown in the WiFi manager code.
I tried to insert the code at the beginning of setup() or at the beginning of loop(). Unfortunately or success (no current time). Could you give me a hint about this?
Hi, Sara, show me an example of working with a telegram bot?
Hi.
We have several tutorials with Telegram bots: https://randomnerdtutorials.com/?s=telegram
Regards,
Sara
Thanks. The question is, how do I launch telegram bot using a Wi-Fi manager (AsyncWebServer library)?
The WiFi manager from this article works great for me, the telegram bot also works separately, but they don work together. What needs to be changed in the code to make bat work?
Hi.
Can you provide more details?
Do you get any errors? What exactly happens?
I never tried using both at the same time, but in theory, it should work. Maybe you need some adjustments in your code.
Regards,
Sara
Hi. Sarah
This works with a Telegram bot.
WiFi.mode(WIFI_STA);
//localIP.fromString(ip.c_str());
//localGateway.fromString(gateway.c_str());
//if (!WiFi.config(localIP, localGateway, subnet)){
//Serial.println(“STA не удалось настроить”);
//return false;
//}
WiFi.begin(ssid.c_str(), pass.c_str());
Serial.println(“подключение к WiFi…”);
delay(20000);
I send a dynamic ID to the telegram bot and go to the WEB page from the telegram.
It would be really nice if someone could let me know how to modify the code so I can revisit wifimanager.html and change the settings later on.
wifimanager.html is available after setting everything up, but submitting the form throws error 500.
What do I have to modify so I am able to resubmit the form with new settings?
Hi Sara, thanks for your tutorial. Is the last step have some kind way can jump to the login page automatically?
olá tudo bem ele funciona do ESP8266 01 TENHO MUITO DELE AQUI
Seria ótimos.
Eu ate fiz um compilação normal nele ele funciona não da o cesso ap
Obrigado
I’ve been successful to the point where it’s time to connect to 192.168.1.200 but at that point my browser times out. If anyone has any suggestions I’d be appreciative.
I’ve tried connecting to both my iPhone hotspot & router in my shed and both connect just fine. LittleFS appears to have uploaded the the package from the tools folder created during this tutorial just fine.
LittleFS has thrown a few access denied errors trying to write to COM port however these clear if you disconnect, reconnect the usb & try again.
So I’m a bit lost how to diagnose. Is there a way of reading the content of the flash memory to see that the index.html file is there?
I realise this is to 63 not 200 and I’d changed that in a futile attempt to see if I had a printer or something with a fixed address that clashed.
Message on web browser attempting to access – This site can’t be reached192.168.1.63 took too long to respond.
Cheers,
Dave
There’s a key bit of information missing in this “How to..” page.
You need to know the Default Gateway address of the network that you want to connect to if you use this message.
In my case it was 192.168.20.1 so when it connected to the WiFi, the next step to enter the 192.168.1.200 didn’t work. It just hung and the browser timed out looking for it.
Run IPCONFIG from a command prompt and look at what your default gateway is. Use that address in the default gateway field.
Change the IP address you want the NodeMCU to appear at after you connect it to the SSID to match eg. 192.168.20.200 in my case.
Make sure your subnet mask in the code matches the subnet mask in IPCONFIG.
Then you might get somewhere when you connect. Mine is working now.
All I have to do now is work out how to find the default gateway and subnet mask of an iPhone hotspot and whether they are the same for all iPhones. Otherwise when I’m out of the development environment here in my shed, and trying to use this on a hotspot it’s going to fail too.
Wasted a lot of time finding this solution which really should have been covered in the article above.
Hope this helps someone else.
Dave