WiFiManager with ESP8266 – Autoconnect, Custom Parameter and Manage your SSID and Password
In this guide you’ll learn how to use WiFiManager with the ESP8266 board. WiFiManager allows you to connect your ESP8266 to different Access Points (AP) without having to hard-code and upload new code to your board. Additionally, you can also add custom parameters (variables) and manage multiple SSID connections with the WiFiManager library.
How WiFiManager Works with ESP8266
The WiFiManager is a great library do add to your ESP8266 projects, because using this library you no longer have to hard-code your network credentials (SSID and password). Your ESP will automatically join a known network or set up an Access Point that you can use to configure the network credentials. Here’s how this process works:
- When your ESP8266 boots, it is set up in Station mode, and tries to connect to a previously saved Access Point (a known SSID and password combination);
- If this process fails, it sets the ESP into Access Point mode;
- Using any Wi-Fi enabled device with a browser, connect to the newly created Access Point (default name AutoConnectAP);
- After establishing a connection with the AutoConnectAP, 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;
- Once a new SSID and password is set, the ESP reboots and tries to connect;
- If it establishes a connection, the process is completed successfully. Otherwise, it will be set up as an Access Point.
RECOMMENDED: Read our Home Automation using ESP8266 Course
This blog post illustrates two different use cases for the WiFiManager library:
- Example #1 – Autoconnect: Web Server Example
- Example #2 – Adding Custom Parameters
Prerequisites
Before proceeding with this tutorial we recommend reading the following resources:
Installing WiFiManager and ArduinoJSON
You also need to install the WiFiManager Library and ArduinoJSON Library. Follow these next instructions.
Installing the WiFiManager Library
- Click here to download the WiFiManager library. You should have a .zip folder in your Downloads
- Unzip the .zip folder and you should get WiFiManager-master folder
- Rename your folder from
WiFiManager-masterto WiFiManager - Move the WiFiManager folder to your Arduino IDE installation libraries folder
- Finally, re-open your Arduino IDE
Installing the ArduinoJSON Library
- Click here to download the ArduinoJSON library. You should have a .zip folder in your Downloads
- Unzip the .zip folder and you should get ArduinoJSON-master folder
- Rename your folder from
ArduinoJSON-masterto ArduinoJSON - Move the ArduinoJSON folder to your Arduino IDE installation libraries folder
- Finally, re-open your Arduino IDE
DOWNLOAD FREE PDF: ESP8266 Web Server with Arduino IDE
Example #1 – WiFiManager with ESP8266: Autoconnect Example
This first example is based on the ESP8266 Web Server post, where you build a web server with an ESP8266 to control two outputs (watch the video tutorial below).
For Example #1 we’ll use the previous project, but instead of hard-coding the SSID and password, you’ll be able to configure it with the WiFiManager library.
Code
Having the ESP8266 add-on for the Arduino IDE installed (How to Install the ESP8266 Board in Arduino IDE), go to Tools and select “ESP-12E” (or choose the development board that you’re using). Here’s the code that you need to upload to your ESP8266:
/********* Rui Santos Complete project details at http://randomnerdtutorials.com *********/ #include <ESP8266WiFi.h> #include <DNSServer.h> #include <ESP8266WebServer.h> #include <WiFiManager.h> // https://github.com/tzapu/WiFiManager // Set web server port number to 80 WiFiServer server(80); // Variable to store the HTTP request String header; // Auxiliar variables to store the current output state String output5State = "off"; String output4State = "off"; // Assign output variables to GPIO pins const int output5 = 5; const int output4 = 4; void setup() { Serial.begin(115200); // Initialize the output variables as outputs pinMode(output5, OUTPUT); pinMode(output4, OUTPUT); // Set outputs to LOW digitalWrite(output5, LOW); digitalWrite(output4, LOW); // WiFiManager // Local intialization. Once its business is done, there is no need to keep it around WiFiManager wifiManager; // Uncomment and run it once, if you want to erase all the stored information //wifiManager.resetSettings(); // set custom ip for portal //wifiManager.setAPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0)); // fetches ssid and pass from eeprom and tries to connect // if it does not connect it starts an access point with the specified name // here "AutoConnectAP" // and goes into a blocking loop awaiting configuration wifiManager.autoConnect("AutoConnectAP"); // or use this for auto generated name ESP + ChipID //wifiManager.autoConnect(); // if you get here you have connected to the WiFi Serial.println("Connected."); server.begin(); } void loop(){ WiFiClient client = server.available(); // Listen for incoming clients if (client) { // If a new client connects, Serial.println("New Client."); // print a message out in the serial port String currentLine = ""; // make a String to hold incoming data from the client while (client.connected()) { // loop while the client's connected if (client.available()) { // if there's bytes to read from the client, char c = client.read(); // read a byte, then Serial.write(c); // print it out the serial monitor header += c; if (c == '\n') { // if the byte is a newline character // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println("Connection: close"); client.println(); // turns the GPIOs on and off if (header.indexOf("GET /5/on") >= 0) { Serial.println("GPIO 5 on"); output5State = "on"; digitalWrite(output5, HIGH); } else if (header.indexOf("GET /5/off") >= 0) { Serial.println("GPIO 5 off"); output5State = "off"; digitalWrite(output5, LOW); } else if (header.indexOf("GET /4/on") >= 0) { Serial.println("GPIO 4 on"); output4State = "on"; digitalWrite(output4, HIGH); } else if (header.indexOf("GET /4/off") >= 0) { Serial.println("GPIO 4 off"); output4State = "off"; digitalWrite(output4, LOW); } // Display the HTML web page client.println("<!DOCTYPE html><html>"); client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"); client.println("<link rel=\"icon\" href=\"data:,\">"); // CSS to style the on/off buttons // Feel free to change the background-color and font-size attributes to fit your preferences client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}"); client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;"); client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}"); client.println(".button2 {background-color: #77878A;}</style></head>"); // Web Page Heading client.println("<body><h1>ESP8266 Web Server</h1>"); // Display current state, and ON/OFF buttons for GPIO 5 client.println("<p>GPIO 5 - State " + output5State + "</p>"); // If the output5State is off, it displays the ON button if (output5State=="off") { client.println("<p><a href=\"/5/on\"><button class=\"button\">ON</button></a></p>"); } else { client.println("<p><a href=\"/5/off\"><button class=\"button button2\">OFF</button></a></p>"); } // Display current state, and ON/OFF buttons for GPIO 4 client.println("<p>GPIO 4 - State " + output4State + "</p>"); // If the output4State is off, it displays the ON button if (output4State=="off") { client.println("<p><a href=\"/4/on\"><button class=\"button\">ON</button></a></p>"); } else { client.println("<p><a href=\"/4/off\"><button class=\"button button2\">OFF</button></a></p>"); } client.println("</body></html>"); // The HTTP response ends with another blank line client.println(); // Break out of the while loop break; } else { // if you got a newline, then clear currentLine currentLine = ""; } } else if (c != '\r') { // if you got anything else but a carriage return character, currentLine += c; // add it to the end of the currentLine } } } // Clear the header variable header = ""; // Close the connection client.stop(); Serial.println("Client disconnected."); Serial.println(""); } }
This code needs to include the following libraries for the WiFiManager:
#include <DNSServer.h> #include <ESP8266WebServer.h> #include <WiFiManager.h>
You also need to create a WiFiManager object:
WiFiManager wifiManager;
And run the autoConnect() method:
wifiManager.autoConnect("AutoConnectAP");
That’s it! By adding these new lines of code to your ESP8266 projects, you’re able to configure Wi-Fi credentials using the WiFiManager.
Accessing the WiFiManager AP
If it’s your first time running the WiFiManager code with your ESP8266 board, you’ll see the next messages being printed in your Arduino IDE Serial Monitor.
You can either use your computer/laptop to connect to the AutoConnectAP Access point:
Then, open your browser and type the following IP address: 192.168.4.1. This loads the next web page, where you can set your Wi-Fi credentials:
Alternatively, you can use your smartphone, activate Wi-Fi and connect to AutoConnectAP as follows:
You should see a a window similar to the one shown in the figure below. Then, press the “SIGN IN” button:
Configuring the WiFi page
You’ll be redirected to a web page at 192.168.4.1 that allows you to configure your ESP’s WiFi credentials. Press the “Configure WiFi” button:
Choose your desired network by tapping its name and the SSID should be filled instantly (in my case “MEO-620B4B”):
After that, type your password and press “save“:
You’ll see a similar message saying “Credentials Saved“:
In the meanwhile, the Serial Monitor displays the scan results of the available Access Points and message stating that Wi-Fi credentials were saved.
Accessing your web server
Now, if you RESET your ESP board, it will print the IP address in the Serial Monitor (in my case it’s 192.168.1.132):
Open your browser and type the IP address. You should see the web server shown below, that allows you to control two GPIOs on and off:
Parts required and schematic
If you want to make this project work, here’s the parts that you need:
- ESP8266 12-E – read Best ESP8266 Wi-Fi Development Boards
- 2x LEDs
- 2x Resistors (220 or 330 ohms should work just fine)
- Breadboard
- Jumper wires
You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!
Follow this schematic:
How to Erase Credentials From Your ESP8266
This next line is commented by default, otherwise you would need to configure your ESP8266 every time it boots up.
// Uncomment and run it once, if you want to erase all the stored information //wifiManager.resetSettings();
If for some reason you want to erase all the saved credentials:
- Uncomment the preceding line;
- Upload the code to the ESP8266;
- Let it run once (reset your board);
- Comment that line again;
- Upload the code to the ESP8266 with the line commented.
Example #2 – WiFiManager with ESP8266 and Custom Parameters
The WiFiManager has a useful feature that allows you to add custom parameters to the “Configure WiFi” web page. This is extremely useful, because in some applications you might want to add a different API Key, an MQTT broker IP Address, assign a different GPIO, activate a sensor, etc..
In Example #2, you’ll make a web server to control an ESP8266 GPIO pin that is defined with a custom parameter set through the WiFiManager.
Code
Having the ESP8266 add-on for the Arduino IDE installed (How to Install the ESP8266 Board in Arduino IDE), go to Tools and select “ESP-12E” (or choose the development board that you’re using). Here’s the code that you need to upload to your ESP8266:
/********* Rui Santos Complete project details at http://randomnerdtutorials.com *********/ #include <FS.h> //this needs to be first, or it all crashes and burns... #include <ESP8266WiFi.h> #include <DNSServer.h> #include <ESP8266WebServer.h> #include <WiFiManager.h> // https://github.com/tzapu/WiFiManager #include <ArduinoJson.h> // https://github.com/bblanchon/ArduinoJson // Set web server port number to 80 WiFiServer server(80); // Variable to store the HTTP request String header; // Auxiliar variables to store the current output state String outputState = "off"; // Assign output variables to GPIO pins char output[2] = "5"; //flag for saving data bool shouldSaveConfig = false; //callback notifying us of the need to save config void saveConfigCallback () { Serial.println("Should save config"); shouldSaveConfig = true; } void setup() { Serial.begin(115200); //clean FS, for testing //SPIFFS.format(); //read configuration from FS json Serial.println("mounting FS..."); if (SPIFFS.begin()) { Serial.println("mounted file system"); if (SPIFFS.exists("/config.json")) { //file exists, reading and loading Serial.println("reading config file"); File configFile = SPIFFS.open("/config.json", "r"); if (configFile) { Serial.println("opened config file"); size_t size = configFile.size(); // Allocate a buffer to store contents of the file. std::unique_ptr<char[]> buf(new char[size]); configFile.readBytes(buf.get(), size); DynamicJsonBuffer jsonBuffer; JsonObject& json = jsonBuffer.parseObject(buf.get()); json.printTo(Serial); if (json.success()) { Serial.println("\nparsed json"); strcpy(output, json["output"]); } else { Serial.println("failed to load json config"); } } } } else { Serial.println("failed to mount FS"); } //end read WiFiManagerParameter custom_output("output", "output", output, 2); // WiFiManager // Local intialization. Once its business is done, there is no need to keep it around WiFiManager wifiManager; //set config save notify callback wifiManager.setSaveConfigCallback(saveConfigCallback); // set custom ip for portal //wifiManager.setAPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0)); //add all your parameters here wifiManager.addParameter(&custom_output); // Uncomment and run it once, if you want to erase all the stored information //wifiManager.resetSettings(); //set minimu quality of signal so it ignores AP's under that quality //defaults to 8% //wifiManager.setMinimumSignalQuality(); //sets timeout until configuration portal gets turned off //useful to make it all retry or go to sleep //in seconds //wifiManager.setTimeout(120); // fetches ssid and pass from eeprom and tries to connect // if it does not connect it starts an access point with the specified name // here "AutoConnectAP" // and goes into a blocking loop awaiting configuration wifiManager.autoConnect("AutoConnectAP"); // or use this for auto generated name ESP + ChipID //wifiManager.autoConnect(); // if you get here you have connected to the WiFi Serial.println("Connected."); strcpy(output, custom_output.getValue()); //save the custom parameters to FS if (shouldSaveConfig) { Serial.println("saving config"); DynamicJsonBuffer jsonBuffer; JsonObject& json = jsonBuffer.createObject(); json["output"] = output; File configFile = SPIFFS.open("/config.json", "w"); if (!configFile) { Serial.println("failed to open config file for writing"); } json.printTo(Serial); json.printTo(configFile); configFile.close(); //end save } // Initialize the output variables as outputs pinMode(atoi(output), OUTPUT); // Set outputs to LOW digitalWrite(atoi(output), LOW);; server.begin(); } void loop(){ WiFiClient client = server.available(); // Listen for incoming clients if (client) { // If a new client connects, Serial.println("New Client."); // print a message out in the serial port String currentLine = ""; // make a String to hold incoming data from the client while (client.connected()) { // loop while the client's connected if (client.available()) { // if there's bytes to read from the client, char c = client.read(); // read a byte, then Serial.write(c); // print it out the serial monitor header += c; if (c == '\n') { // if the byte is a newline character // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println("Connection: close"); client.println(); // turns the GPIOs on and off if (header.indexOf("GET /output/on") >= 0) { Serial.println("Output on"); outputState = "on"; digitalWrite(atoi(output), HIGH); } else if (header.indexOf("GET /output/off") >= 0) { Serial.println("Output off"); outputState = "off"; digitalWrite(atoi(output), LOW); } // Display the HTML web page client.println("<!DOCTYPE html><html>"); client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"); client.println("<link rel=\"icon\" href=\"data:,\">"); // CSS to style the on/off buttons // Feel free to change the background-color and font-size attributes to fit your preferences client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}"); client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;"); client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}"); client.println(".button2 {background-color: #77878A;}</style></head>"); // Web Page Heading client.println("<body><h1>ESP8266 Web Server</h1>"); // Display current state, and ON/OFF buttons for the defined GPIO client.println("<p>Output - State " + outputState + "</p>"); // If the outputState is off, it displays the ON button if (outputState=="off") { client.println("<p><a href=\"/output/on\"><button class=\"button\">ON</button></a></p>"); } else { client.println("<p><a href=\"/output/off\"><button class=\"button button2\">OFF</button></a></p>"); } client.println("</body></html>"); // The HTTP response ends with another blank line client.println(); // Break out of the while loop break; } else { // if you got a newline, then clear currentLine currentLine = ""; } } else if (c != '\r') { // if you got anything else but a carriage return character, currentLine += c; // add it to the end of the currentLine } } } // Clear the header variable header = ""; // Close the connection client.stop(); Serial.println("Client disconnected."); Serial.println(""); } }
Adding custom parameters
To add a custom parameter, you need to add a bunch of code (see the preceding sketch) that allows you to manipulate the /config.json file stored in the ESP. For this tutorial we won’t explain how the custom parameters feature works, but basically if you wanted to create another custom parameter follow these next steps.
In this example, we’ll create a variable to store an MQTT broker server IP address. First, create a char variable:
char output[2]; char mqtt_server[40];
Then, if it’s already saved in the /config.json, you can copy it:
strcpy(output, json["output"]); strcpy(mqtt_server, json["mqtt_server"]);
Create a WiFiManagerParameter (so, the parameter is displayed in the “Configure WiFi” web page:
WiFiManagerParameter custom_output("output", "output", output, 2); WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40);
Add the variable as a parameter:
wifiManager.addParameter(&custom_output); wifiManager.addParameter(&custom_mqtt_server);
Check and update the char variables with the latest value:
strcpy(output, custom_output.getValue()); strcpy(mqtt_server, custom_mqtt_server.getValue());
Finally, if the user submits a new value to one of the parameters, this line updates the/config.json file:
json["output"] = output; json["mqtt_server"] = mqtt_server;
You could repeat this process to add more custom parameters.
Accessing the WiFiManager AP
Use your smartphone, computer or tablet and connect to the AutoConnectAP Access Point:
You should see a a window similar to the one shown in the figure below. Then, press the “SIGN IN” button:
Configuring the WiFi page
You’ll be redirected to a web page at 192.168.4.1 that allows you to configure your ESP’s WiFi credentials. Press the “Configure WiFi” button:
Choose your desired network by tapping its name and the SSID should be filled instantly (in my case “MEO-620B4B”):
After that, type your password, your desired GPIO number (in my case it’s GPIO 5, so I’ve entered 5) and press “save“:
In the meanwhile, the Serial Monitor displays:
- Scan results of the available Access Points;
- Message stating that Wi-Fi credentials were saved;
- Confirmation that the output parameter (that refers to the GPIO) was set to 5: {“output”:”5″}.
Accessing your web server
Now, if you RESET your ESP board, it will print the IP address in the Serial Monitor (in my case it’s 192.168.1.132):
Open your browser and type the IP address. You should see the web server shown below, that allows you to control the GPIO you’ve defined on and off:
Parts required and schematic
If you want to make this project work, here’s the parts that you need:
- ESP8266 12-E – read Best ESP8266 Wi-Fi Development Boards
- 1x LED
- 1x Resistor (220 or 330 ohms should work just fine)
- Breadboard
- Jumper wires
You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!
Note: if you’ve defined a GPIO number different than GPIO 5 (which is D1 with the NodeMCU board), you need to make a different circuit.
Wrapping Up
That’s it for now, I hope you found this project useful and you can use the WiFiManager library in your projects!
If you like the ESP8266, you may also like:
沒有留言:
張貼留言