{"id":107818,"date":"2021-12-23T17:16:11","date_gmt":"2021-12-23T17:16:11","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=107818"},"modified":"2025-03-14T16:05:25","modified_gmt":"2025-03-14T16:05:25","slug":"esp32-wi-fi-manager-asyncwebserver","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-wi-fi-manager-asyncwebserver\/","title":{"rendered":"ESP32: Create a Wi-Fi Manager (AsyncWebServer library)"},"content":{"rendered":"\n<p>In this guide, you&#8217;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 ESP32 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.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/12\/ESP32-Wi-Fi-Manager-Web-Server.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32: Create a Simple Wi-Fi Manager (AsyncWebServer library)\" class=\"wp-image-108563\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/12\/ESP32-Wi-Fi-Manager-Web-Server.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/12\/ESP32-Wi-Fi-Manager-Web-Server.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/12\/ESP32-Wi-Fi-Manager-Web-Server.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/12\/ESP32-Wi-Fi-Manager-Web-Server.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<p>To better understand how this project works, we recommend taking a look at the following tutorials:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-input-data-html-form\/\">Input Data on HTML Form ESP32\/ESP8266 Web Server using Arduino IDE<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-access-point-ap-web-server\/\">How to Set an ESP32 Access Point (AP) for Web Server<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-static-fixed-ip-address-arduino-ide\/\">ESP32 Static\/Fixed IP Address<\/a><\/li>\n<\/ul>\n\n\n\n<p>We also use this Wi-Fi Manager approach on the following project:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-status-indicator-sensor-pcb\/\">ESP32 Neopixel Status Indicator and Sensor PCB Shield with Wi-Fi Manager<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">How it Works<\/h2>\n\n\n\n<p>Take a look at the following diagram to understand how the Wi-Fi Manager we&#8217;ll create works.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"735\" height=\"827\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/ESP32-ESP8266-wi-fi-manager-web-server-how-it-works.png?resize=735%2C827&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 Wi-Fi Manager Web Server How it Works\" class=\"wp-image-107839\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/ESP32-ESP8266-wi-fi-manager-web-server-how-it-works.png?w=735&amp;quality=100&amp;strip=all&amp;ssl=1 735w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/ESP32-ESP8266-wi-fi-manager-web-server-how-it-works.png?resize=267%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 267w\" sizes=\"(max-width: 735px) 100vw, 735px\" \/><\/figure><\/div>\n\n\n<ul class=\"wp-block-list\">\n<li>When the ESP first starts, it tries to read the <span class=\"rnthl rntliteral\">ssid.txt<\/span>, <span class=\"rnthl rntliteral\">pass.txt<\/span> and <span class=\"rnthl rntliteral\">ip.txt<\/span> files* (<strong>1<\/strong>);<\/li>\n\n\n\n<li>If the files are empty (<strong>2<\/strong>) (the first time you run the board, the files are empty), your board is set as an access point (<strong>3<\/strong>);<\/li>\n\n\n\n<li>Using any Wi-Fi enabled device with a browser, you can connect to the newly created Access Point (default name <span class=\"rnthl rntliteral\">ESP-WIFI-MANAGER<\/span>);<\/li>\n\n\n\n<li>After establishing a connection with the ESP-WIFI-MANAGER, you can go to the default IP address <span class=\"rnthl rntliteral\">192.168.4.1<\/span> to open a web page that allows you to configure your SSID and password (<strong>4<\/strong>);<\/li>\n\n\n\n<li>The SSID, password, and IP address inserted in the form are saved in the corresponding files: <span class=\"rnthl rntliteral\">ssid.txt<\/span>, <span class=\"rnthl rntliteral\">pass.txt<\/span>, and <span class=\"rnthl rntliteral\">ip.txt<\/span> (<strong>5<\/strong>);<\/li>\n\n\n\n<li>After that, the ESP board restarts (<strong>6<\/strong>);<\/li>\n\n\n\n<li>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\u2019ve inserted in the form (<strong>7<\/strong>);<\/li>\n\n\n\n<li>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.) (<strong>9<\/strong>). Otherwise, it will set the Access Point (<strong>3<\/strong>), and you can access the default IP address (<span class=\"rnthl rntliteral\">192.168.4.1<\/span>) to add another SSID\/password combination.<\/li>\n<\/ul>\n\n\n\n<p> <strong>*<\/strong> we also created a <em>gateway<\/em> field and a <span class=\"rnthl rntliteral\">gateway.txt<\/span> file to save the IP address gateway (this is not shown in the diagram).<\/p>\n\n\n\n<p>To show you how to set the Wi-Fi Manager, we&#8217;ll set up a web server that controls one output (GPIO2\u2014the 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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>We&#8217;ll program the ESP32 board using Arduino IDE. So make sure you have the ESP32 board add-on installed.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/installing-esp32-arduino-ide-2-0\/\" title=\"\">Installing ESP32 Board in Arduino IDE (Windows, Mac OS X, and Linux)<\/a><\/li>\n<\/ul>\n\n\n\n<p>If you want to program the ESP32 using VS Code + PlatformIO, follow the next tutorial:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/vs-code-platformio-ide-esp32-esp8266-arduino\/\">Getting Started with VS Code and PlatformIO IDE for ESP32 and ESP8266 (Windows, Mac OS X, Linux Ubuntu)<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Installing Libraries (Arduino IDE)<\/h3>\n\n\n\n<p>We&#8217;ll build the web server using the following libraries:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/ESP32Async\/ESPAsyncWebServer\" target=\"_blank\" rel=\"noopener\" title=\"\">ESPAsyncWebServer&nbsp;<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/ESP32Async\/AsyncTCP\" target=\"_blank\" rel=\"noopener\" title=\"\">AsyncTCP<\/a><\/li>\n<\/ul>\n\n\n\n<p>You can install these libraries in the Arduino Library Manager. Open the Library Manager by clicking the Library icon at the left sidebar.<\/p>\n\n\n\n<p>Search for <span class=\"rnthl rntliteral\">ESPAsyncWebServer<\/span> and install the <strong>ESPAsyncWebServer by ESP32Async<\/strong>.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"666\" height=\"586\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/Install-ESPAsyncWebServer-Library-ArduinoIDE-2-f.png?resize=666%2C586&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Installing ESPAsyncWebServer ESP32 Arduino IDE\" class=\"wp-image-167890\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/Install-ESPAsyncWebServer-Library-ArduinoIDE-2-f.png?w=666&amp;quality=100&amp;strip=all&amp;ssl=1 666w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/Install-ESPAsyncWebServer-Library-ArduinoIDE-2-f.png?resize=300%2C264&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 666px) 100vw, 666px\" \/><\/figure><\/div>\n\n\n<p>Then, install the AsyncTCP library. Search for <span class=\"rnthl rntliteral\">AsyncTCP<\/span> and install the <strong>AsyncTCP by ESP32Async<\/strong>.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"722\" height=\"586\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/Install-AsyncTCP-Library-ArduinoIDE.png?resize=722%2C586&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Installing AsyncTCP ESP32 Arduino IDE\" class=\"wp-image-167886\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/Install-AsyncTCP-Library-ArduinoIDE.png?w=722&amp;quality=100&amp;strip=all&amp;ssl=1 722w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/Install-AsyncTCP-Library-ArduinoIDE.png?resize=300%2C243&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 722px) 100vw, 722px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">Filesystem Uploader<\/h3>\n\n\n\n<p>Before proceeding, you need to have the ESP32 Uploader Plugin installed in your Arduino IDE.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/arduino-ide-2-install-esp32-littlefs\/\">Arduino IDE 2: Install ESP32 LittleFS Uploader (Upload Files to the Filesystem)<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Organizing your Files<\/h2>\n\n\n\n<p>To keep the project organized and make it easier to understand, we&#8217;ll create four different files to build the web server:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Arduino sketch <\/strong>that handles the web server;<\/li>\n\n\n\n<li><strong>index.html<\/strong>: to define the content of the web page in station mode to control the output (or any other web page you want to build);<\/li>\n\n\n\n<li><strong>style.css<\/strong>: to style the web pages;<\/li>\n\n\n\n<li><strong>wifimanager.html<\/strong>: to define the web page&#8217;s content to display the Wi-Fi Manager when the ESP is in access point mode.<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"613\" height=\"346\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/ESP32-ESP8266-Web-Server-Wi-Fi-Manager-Files.png?resize=613%2C346&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 Wi-Fi Manager Project Files\" class=\"wp-image-107840\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/ESP32-ESP8266-Web-Server-Wi-Fi-Manager-Files.png?w=613&amp;quality=100&amp;strip=all&amp;ssl=1 613w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/ESP32-ESP8266-Web-Server-Wi-Fi-Manager-Files.png?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 613px) 100vw, 613px\" \/><\/figure><\/div>\n\n\n<p>You should save the HTML and CSS files inside a folder called&nbsp;<em><strong>data<\/strong>&nbsp;<\/em>inside the Arduino sketch folder, as shown in the previous diagram. We&#8217;ll upload these files to the ESP32 filesystem (LittleFS).<\/p>\n\n\n\n<p><strong>You can download all project files:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/ESP32_WiFi_Manager\/ESP32_WiFi_Manager.zip\" target=\"_blank\" rel=\"noreferrer noopener\">Download All the Arduino Project Files<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Creating the HTML Files<\/h2>\n\n\n\n<p>For this project, you need two HTML files. One to build the main page that controls the output (<span class=\"rnthl rntliteral\">index.html<\/span>) and another to build the Wi-Fi Manager page (<span class=\"rnthl rntliteral\">wifimanager.html<\/span>).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">index.html<\/h3>\n\n\n\n<p>Here&#8217;s the text you should copy to your <span class=\"rnthl rntliteral\">index.html<\/span> file.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-html\">&lt;!DOCTYPE html&gt;\r\n&lt;html&gt;\r\n  &lt;head&gt;\r\n    &lt;title&gt;ESP WEB SERVER&lt;\/title&gt;\r\n    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;\r\n    &lt;link rel=&quot;stylesheet&quot; type=&quot;text\/css&quot; href=&quot;style.css&quot;&gt;\r\n    &lt;link rel=&quot;icon&quot; type=&quot;image\/png&quot; href=&quot;favicon.png&quot;&gt;\r\n    &lt;link rel=&quot;stylesheet&quot; href=&quot;https:\/\/use.fontawesome.com\/releases\/v5.7.2\/css\/all.css&quot; integrity=&quot;sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr&quot; crossorigin=&quot;anonymous&quot;&gt;\r\n  &lt;\/head&gt;\r\n  &lt;body&gt;\r\n    &lt;div class=&quot;topnav&quot;&gt;\r\n      &lt;h1&gt;ESP WEB SERVER&lt;\/h1&gt;\r\n    &lt;\/div&gt;\r\n    &lt;div class=&quot;content&quot;&gt;\r\n      &lt;div class=&quot;card-grid&quot;&gt;\r\n        &lt;div class=&quot;card&quot;&gt;\r\n          &lt;p class=&quot;card-title&quot;&gt;&lt;i class=&quot;fas fa-lightbulb&quot;&gt;&lt;\/i&gt; GPIO 2&lt;\/p&gt;\r\n          &lt;p&gt;\r\n            &lt;a href=&quot;on&quot;&gt;&lt;button class=&quot;button-on&quot;&gt;ON&lt;\/button&gt;&lt;\/a&gt;\r\n            &lt;a href=&quot;off&quot;&gt;&lt;button class=&quot;button-off&quot;&gt;OFF&lt;\/button&gt;&lt;\/a&gt;\r\n          &lt;\/p&gt;\r\n          &lt;p class=&quot;state&quot;&gt;State: %STATE%&lt;\/p&gt;\r\n        &lt;\/div&gt;\r\n      &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n  &lt;\/body&gt;\r\n&lt;\/html&gt;<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/ESP32_WiFi_Manager\/data\/index.html\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>We won&#8217;t explain how this HTML file works because that&#8217;s not the purpose of this tutorial. The purpose of this tutorial is to explain the parts related to the Wi-Fi Manager.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">wifimanager.html<\/h3>\n\n\n\n<p>The Wi-Fi Manager web page looks like this:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"714\" height=\"643\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/02\/ESP32-ESP8266-Wi-Fi-Manager-Fields.png?resize=714%2C643&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 Wi-Fi Manager Fields\" class=\"wp-image-109212\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/02\/ESP32-ESP8266-Wi-Fi-Manager-Fields.png?w=714&amp;quality=100&amp;strip=all&amp;ssl=1 714w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/02\/ESP32-ESP8266-Wi-Fi-Manager-Fields.png?resize=300%2C270&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 714px) 100vw, 714px\" \/><\/figure><\/div>\n\n\n<p>Copy the following to the <span class=\"rnthl rntliteral\">wifimanager.html<\/span> file. This creates a web page with a form with three input fields and a <strong>Submit<\/strong> button.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-html\">&lt;!DOCTYPE html&gt;\r\n&lt;html&gt;\r\n&lt;head&gt;\r\n  &lt;title&gt;ESP Wi-Fi Manager&lt;\/title&gt;\r\n  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;\r\n  &lt;link rel=&quot;icon&quot; href=&quot;data:,&quot;&gt;\r\n  &lt;link rel=&quot;stylesheet&quot; type=&quot;text\/css&quot; href=&quot;style.css&quot;&gt;\r\n&lt;\/head&gt;\r\n&lt;body&gt;\r\n  &lt;div class=&quot;topnav&quot;&gt;\r\n    &lt;h1&gt;ESP Wi-Fi Manager&lt;\/h1&gt;\r\n  &lt;\/div&gt;\r\n  &lt;div class=&quot;content&quot;&gt;\r\n    &lt;div class=&quot;card-grid&quot;&gt;\r\n      &lt;div class=&quot;card&quot;&gt;\r\n        &lt;form action=&quot;\/&quot; method=&quot;POST&quot;&gt;\r\n          &lt;p&gt;\r\n            &lt;label for=&quot;ssid&quot;&gt;SSID&lt;\/label&gt;\r\n            &lt;input type=&quot;text&quot; id =&quot;ssid&quot; name=&quot;ssid&quot;&gt;&lt;br&gt;\r\n            &lt;label for=&quot;pass&quot;&gt;Password&lt;\/label&gt;\r\n            &lt;input type=&quot;text&quot; id =&quot;pass&quot; name=&quot;pass&quot;&gt;&lt;br&gt;\r\n            &lt;label for=&quot;ip&quot;&gt;IP Address&lt;\/label&gt;\r\n            &lt;input type=&quot;text&quot; id =&quot;ip&quot; name=&quot;ip&quot; value=&quot;192.168.1.200&quot;&gt;&lt;br&gt;\r\n            &lt;label for=&quot;gateway&quot;&gt;Gateway Address&lt;\/label&gt;\r\n            &lt;input type=&quot;text&quot; id =&quot;gateway&quot; name=&quot;gateway&quot; value=&quot;192.168.1.1&quot;&gt;&lt;br&gt;\r\n            &lt;input type =&quot;submit&quot; value =&quot;Submit&quot;&gt;\r\n          &lt;\/p&gt;\r\n        &lt;\/form&gt;\r\n      &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n  &lt;\/div&gt;\r\n&lt;\/body&gt;\r\n&lt;\/html&gt;\r\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/ESP32_WiFi_Manager\/data\/wifimanager.html\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>In this HTML file, we create an HTML form that will make an HTTP POST request with the data submitted to the server.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;form action=\"\/\" method=\"POST\"&gt;<\/code><\/pre>\n\n\n\n<p>The form contains three input fields and corresponding labels: SSID, password, and IP address.<\/p>\n\n\n\n<p>This is the input field for the SSID:<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;label for=\"ssid\"&gt;SSID&lt;\/label&gt;\n&lt;input type=\"text\" id =\"ssid\" name=\"ssid\"&gt;&lt;br&gt;<\/code><\/pre>\n\n\n\n<p>This is the input field for the password.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;label for=\"pass\"&gt;Password&lt;\/label&gt;\n&lt;input type=\"text\" id =\"pass\" name=\"pass\"&gt;&lt;br&gt;<\/code><\/pre>\n\n\n\n<p>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 <span class=\"rnthl rntliteral\">192.168.1.200<\/span> (you can set another default IP address, or you can delete the <span class=\"rnthl rntliteral\">value<\/span> parameter\u2014it won&#8217;t have a default value).<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;input type=\"text\" id =\"ip\" name=\"ip\" value=\"192.168.1.200\"&gt;<\/code><\/pre>\n\n\n\n<p>Finally, there&#8217;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.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;input type=\"text\" id =\"gateway\" name=\"gateway\" value=\"192.168.1.1\"&gt;&lt;br&gt;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">CSS File<\/h2>\n\n\n\n<p>Copy the following styles to your <span class=\"rnthl rntliteral\">style.css<\/span> file. We won&#8217;t explain how these styles work. We have already explained how similar styles work in <a href=\"https:\/\/randomnerdtutorials.com\/?s=web+server\">other ESP Web Server projects<\/a>.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-css\">html {\r\n  font-family: Arial, Helvetica, sans-serif; \r\n  display: inline-block; \r\n  text-align: center;\r\n}\r\n\r\nh1 {\r\n  font-size: 1.8rem; \r\n  color: white;\r\n}\r\n\r\np { \r\n  font-size: 1.4rem;\r\n}\r\n\r\n.topnav { \r\n  overflow: hidden; \r\n  background-color: #0A1128;\r\n}\r\n\r\nbody {  \r\n  margin: 0;\r\n}\r\n\r\n.content { \r\n  padding: 5%;\r\n}\r\n\r\n.card-grid { \r\n  max-width: 800px; \r\n  margin: 0 auto; \r\n  display: grid; \r\n  grid-gap: 2rem; \r\n  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));\r\n}\r\n\r\n.card { \r\n  background-color: white; \r\n  box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);\r\n}\r\n\r\n.card-title { \r\n  font-size: 1.2rem;\r\n  font-weight: bold;\r\n  color: #034078\r\n}\r\n\r\ninput[type=submit] {\r\n  border: none;\r\n  color: #FEFCFB;\r\n  background-color: #034078;\r\n  padding: 15px 15px;\r\n  text-align: center;\r\n  text-decoration: none;\r\n  display: inline-block;\r\n  font-size: 16px;\r\n  width: 100px;\r\n  margin-right: 10px;\r\n  border-radius: 4px;\r\n  transition-duration: 0.4s;\r\n  }\r\n\r\ninput[type=submit]:hover {\r\n  background-color: #1282A2;\r\n}\r\n\r\ninput[type=text], input[type=number], select {\r\n  width: 50%;\r\n  padding: 12px 20px;\r\n  margin: 18px;\r\n  display: inline-block;\r\n  border: 1px solid #ccc;\r\n  border-radius: 4px;\r\n  box-sizing: border-box;\r\n}\r\n\r\nlabel {\r\n  font-size: 1.2rem; \r\n}\r\n.value{\r\n  font-size: 1.2rem;\r\n  color: #1282A2;  \r\n}\r\n.state {\r\n  font-size: 1.2rem;\r\n  color: #1282A2;\r\n}\r\nbutton {\r\n  border: none;\r\n  color: #FEFCFB;\r\n  padding: 15px 32px;\r\n  text-align: center;\r\n  font-size: 16px;\r\n  width: 100px;\r\n  border-radius: 4px;\r\n  transition-duration: 0.4s;\r\n}\r\n.button-on {\r\n  background-color: #034078;\r\n}\r\n.button-on:hover {\r\n  background-color: #1282A2;\r\n}\r\n.button-off {\r\n  background-color: #858585;\r\n}\r\n.button-off:hover {\r\n  background-color: #252524;\r\n} <\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/ESP32_WiFi_Manager\/data\/style.css\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Setting Up the Web Server<\/h1>\n\n\n\n<p>If you&#8217;re using VS Code with the platformIO extension, you need to edit the <span class=\"rnthl rntliteral\">platformio.ini<\/span> file to look as shown below. If you&#8217;re using Arduino IDE, you can ignore this.<\/p>\n\n\n\n<p><strong>platformio.ini<\/strong> <strong>ESP32:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>&#091;env:esp32doit-devkit-v1]\nplatform = espressif32\nboard = esp32doit-devkit-v1\nframework = arduino\nmonitor_speed=115200\nlib_deps = ESP Async WebServer<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Code<\/h2>\n\n\n\n<p>Copy the following code to your Arduino IDE or to the <span class=\"rnthl rntliteral\">main.cpp<\/span> file if you&#8217;re using VS Code.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*********\r\n  Rui Santos &amp; Sara Santos - Random Nerd Tutorials\r\n  Complete instructions at https:\/\/RandomNerdTutorials.com\/esp32-wi-fi-manager-asyncwebserver\/\r\n  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.\r\n  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\r\n*********\/\r\n#include &lt;Arduino.h&gt;\r\n#include &lt;WiFi.h&gt;\r\n#include &lt;ESPAsyncWebServer.h&gt;\r\n#include &lt;AsyncTCP.h&gt;\r\n#include &quot;LittleFS.h&quot;\r\n\r\n\/\/ Create AsyncWebServer object on port 80\r\nAsyncWebServer server(80);\r\n\r\n\/\/ Search for parameter in HTTP POST request\r\nconst char* PARAM_INPUT_1 = &quot;ssid&quot;;\r\nconst char* PARAM_INPUT_2 = &quot;pass&quot;;\r\nconst char* PARAM_INPUT_3 = &quot;ip&quot;;\r\nconst char* PARAM_INPUT_4 = &quot;gateway&quot;;\r\n\r\n\/\/Variables to save values from HTML form\r\nString ssid;\r\nString pass;\r\nString ip;\r\nString gateway;\r\n\r\n\/\/ File paths to save input values permanently\r\nconst char* ssidPath = &quot;\/ssid.txt&quot;;\r\nconst char* passPath = &quot;\/pass.txt&quot;;\r\nconst char* ipPath = &quot;\/ip.txt&quot;;\r\nconst char* gatewayPath = &quot;\/gateway.txt&quot;;\r\n\r\nIPAddress localIP;\r\n\/\/IPAddress localIP(192, 168, 1, 200); \/\/ hardcoded\r\n\r\n\/\/ Set your Gateway IP address\r\nIPAddress localGateway;\r\n\/\/IPAddress localGateway(192, 168, 1, 1); \/\/hardcoded\r\nIPAddress subnet(255, 255, 0, 0);\r\n\r\n\/\/ Timer variables\r\nunsigned long previousMillis = 0;\r\nconst long interval = 10000;  \/\/ interval to wait for Wi-Fi connection (milliseconds)\r\n\r\n\/\/ Set LED GPIO\r\nconst int ledPin = 2;\r\n\/\/ Stores LED state\r\n\r\nString ledState;\r\n\r\n\/\/ Initialize LittleFS\r\nvoid initLittleFS() {\r\n  if (!LittleFS.begin(true)) {\r\n    Serial.println(&quot;An error has occurred while mounting LittleFS&quot;);\r\n  }\r\n  Serial.println(&quot;LittleFS mounted successfully&quot;);\r\n}\r\n\r\n\/\/ Read File from LittleFS\r\nString readFile(fs::FS &amp;fs, const char * path){\r\n  Serial.printf(&quot;Reading file: %s\\r\\n&quot;, path);\r\n\r\n  File file = fs.open(path);\r\n  if(!file || file.isDirectory()){\r\n    Serial.println(&quot;- failed to open file for reading&quot;);\r\n    return String();\r\n  }\r\n  \r\n  String fileContent;\r\n  while(file.available()){\r\n    fileContent = file.readStringUntil('\\n');\r\n    break;     \r\n  }\r\n  return fileContent;\r\n}\r\n\r\n\/\/ Write file to LittleFS\r\nvoid writeFile(fs::FS &amp;fs, const char * path, const char * message){\r\n  Serial.printf(&quot;Writing file: %s\\r\\n&quot;, path);\r\n\r\n  File file = fs.open(path, FILE_WRITE);\r\n  if(!file){\r\n    Serial.println(&quot;- failed to open file for writing&quot;);\r\n    return;\r\n  }\r\n  if(file.print(message)){\r\n    Serial.println(&quot;- file written&quot;);\r\n  } else {\r\n    Serial.println(&quot;- write failed&quot;);\r\n  }\r\n}\r\n\r\n\/\/ Initialize WiFi\r\nbool initWiFi() {\r\n  if(ssid==&quot;&quot; || ip==&quot;&quot;){\r\n    Serial.println(&quot;Undefined SSID or IP address.&quot;);\r\n    return false;\r\n  }\r\n\r\n  WiFi.mode(WIFI_STA);\r\n  localIP.fromString(ip.c_str());\r\n  localGateway.fromString(gateway.c_str());\r\n\r\n\r\n  if (!WiFi.config(localIP, localGateway, subnet)){\r\n    Serial.println(&quot;STA Failed to configure&quot;);\r\n    return false;\r\n  }\r\n  WiFi.begin(ssid.c_str(), pass.c_str());\r\n  Serial.println(&quot;Connecting to WiFi...&quot;);\r\n\r\n  unsigned long currentMillis = millis();\r\n  previousMillis = currentMillis;\r\n\r\n  while(WiFi.status() != WL_CONNECTED) {\r\n    currentMillis = millis();\r\n    if (currentMillis - previousMillis &gt;= interval) {\r\n      Serial.println(&quot;Failed to connect.&quot;);\r\n      return false;\r\n    }\r\n  }\r\n\r\n  Serial.println(WiFi.localIP());\r\n  return true;\r\n}\r\n\r\n\/\/ Replaces placeholder with LED state value\r\nString processor(const String&amp; var) {\r\n  if(var == &quot;STATE&quot;) {\r\n    if(digitalRead(ledPin)) {\r\n      ledState = &quot;ON&quot;;\r\n    }\r\n    else {\r\n      ledState = &quot;OFF&quot;;\r\n    }\r\n    return ledState;\r\n  }\r\n  return String();\r\n}\r\n\r\nvoid setup() {\r\n  \/\/ Serial port for debugging purposes\r\n  Serial.begin(115200);\r\n\r\n  initLittleFS();\r\n\r\n  \/\/ Set GPIO 2 as an OUTPUT\r\n  pinMode(ledPin, OUTPUT);\r\n  digitalWrite(ledPin, LOW);\r\n  \r\n  \/\/ Load values saved in LittleFS\r\n  ssid = readFile(LittleFS, ssidPath);\r\n  pass = readFile(LittleFS, passPath);\r\n  ip = readFile(LittleFS, ipPath);\r\n  gateway = readFile (LittleFS, gatewayPath);\r\n  Serial.println(ssid);\r\n  Serial.println(pass);\r\n  Serial.println(ip);\r\n  Serial.println(gateway);\r\n\r\n  if(initWiFi()) {\r\n    \/\/ Route for root \/ web page\r\n    server.on(&quot;\/&quot;, HTTP_GET, [](AsyncWebServerRequest *request) {\r\n      request-&gt;send(LittleFS, &quot;\/index.html&quot;, &quot;text\/html&quot;, false, processor);\r\n    });\r\n    server.serveStatic(&quot;\/&quot;, LittleFS, &quot;\/&quot;);\r\n    \r\n    \/\/ Route to set GPIO state to HIGH\r\n    server.on(&quot;\/on&quot;, HTTP_GET, [](AsyncWebServerRequest *request) {\r\n      digitalWrite(ledPin, HIGH);\r\n      request-&gt;send(LittleFS, &quot;\/index.html&quot;, &quot;text\/html&quot;, false, processor);\r\n    });\r\n\r\n    \/\/ Route to set GPIO state to LOW\r\n    server.on(&quot;\/off&quot;, HTTP_GET, [](AsyncWebServerRequest *request) {\r\n      digitalWrite(ledPin, LOW);\r\n      request-&gt;send(LittleFS, &quot;\/index.html&quot;, &quot;text\/html&quot;, false, processor);\r\n    });\r\n    server.begin();\r\n  }\r\n  else {\r\n    \/\/ Connect to Wi-Fi network with SSID and password\r\n    Serial.println(&quot;Setting AP (Access Point)&quot;);\r\n    \/\/ NULL sets an open Access Point\r\n    WiFi.softAP(&quot;ESP-WIFI-MANAGER&quot;, NULL);\r\n\r\n    IPAddress IP = WiFi.softAPIP();\r\n    Serial.print(&quot;AP IP address: &quot;);\r\n    Serial.println(IP); \r\n\r\n    \/\/ Web Server Root URL\r\n    server.on(&quot;\/&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\r\n      request-&gt;send(LittleFS, &quot;\/wifimanager.html&quot;, &quot;text\/html&quot;);\r\n    });\r\n    \r\n    server.serveStatic(&quot;\/&quot;, LittleFS, &quot;\/&quot;);\r\n    \r\n    server.on(&quot;\/&quot;, HTTP_POST, [](AsyncWebServerRequest *request) {\r\n      int params = request-&gt;params();\r\n      for(int i=0;i&lt;params;i++){\r\n        const AsyncWebParameter* p = request-&gt;getParam(i);\r\n        if(p-&gt;isPost()){\r\n          \/\/ HTTP POST ssid value\r\n          if (p-&gt;name() == PARAM_INPUT_1) {\r\n            ssid = p-&gt;value().c_str();\r\n            Serial.print(&quot;SSID set to: &quot;);\r\n            Serial.println(ssid);\r\n            \/\/ Write file to save value\r\n            writeFile(LittleFS, ssidPath, ssid.c_str());\r\n          }\r\n          \/\/ HTTP POST pass value\r\n          if (p-&gt;name() == PARAM_INPUT_2) {\r\n            pass = p-&gt;value().c_str();\r\n            Serial.print(&quot;Password set to: &quot;);\r\n            Serial.println(pass);\r\n            \/\/ Write file to save value\r\n            writeFile(LittleFS, passPath, pass.c_str());\r\n          }\r\n          \/\/ HTTP POST ip value\r\n          if (p-&gt;name() == PARAM_INPUT_3) {\r\n            ip = p-&gt;value().c_str();\r\n            Serial.print(&quot;IP Address set to: &quot;);\r\n            Serial.println(ip);\r\n            \/\/ Write file to save value\r\n            writeFile(LittleFS, ipPath, ip.c_str());\r\n          }\r\n          \/\/ HTTP POST gateway value\r\n          if (p-&gt;name() == PARAM_INPUT_4) {\r\n            gateway = p-&gt;value().c_str();\r\n            Serial.print(&quot;Gateway set to: &quot;);\r\n            Serial.println(gateway);\r\n            \/\/ Write file to save value\r\n            writeFile(LittleFS, gatewayPath, gateway.c_str());\r\n          }\r\n          \/\/Serial.printf(&quot;POST[%s]: %s\\n&quot;, p-&gt;name().c_str(), p-&gt;value().c_str());\r\n        }\r\n      }\r\n      request-&gt;send(200, &quot;text\/plain&quot;, &quot;Done. ESP will restart, connect to your router and go to IP address: &quot; + ip);\r\n      delay(3000);\r\n      ESP.restart();\r\n    });\r\n    server.begin();\r\n  }\r\n}\r\n\r\nvoid loop() {\r\n\r\n}\r\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/ESP32_WiFi_Manager\/ESP32_WiFi_Manager.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How The Code Works<\/h3>\n\n\n\n<p>Let&#8217;s take a look at the code and see how the Wi-Fi Manager works.<\/p>\n\n\n\n<p> 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.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Search for parameter in HTTP POST request\nconst char* PARAM_INPUT_1 = \"ssid\";\nconst char* PARAM_INPUT_2 = \"pass\";\nconst char* PARAM_INPUT_3 = \"ip\";\nconst char* PARAM_INPUT_4 = \"gateway\";<\/code><\/pre>\n\n\n\n<p> The <span class=\"rnthl rntliteral\">ssid<\/span>, <span class=\"rnthl rntliteral\">pass,<\/span> <span class=\"rnthl rntliteral\">ip<\/span>, and <span class=\"rnthl rntliteral\">gateway<\/span> variables save the values of the SSID, password, IP address, and gateway submitted in the form.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/Variables to save values from HTML form\nString ssid;\nString pass;\nString ip;\nString gateway;<\/code><\/pre>\n\n\n\n<p>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.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ File paths to save input values permanently\nconst char* ssidPath = \"\/ssid.txt\";\nconst char* passPath = \"\/pass.txt\";\nconst char* ipPath = \"\/ip.txt\";\nconst char* gatewayPath = \"\/gateway.txt\";<\/code><\/pre>\n\n\n\n<p>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.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>IPAddress localIP;\n\/\/IPAddress localIP(192, 168, 1, 200); \/\/ hardcoded\n\n\/\/ Set your Gateway IP address\nIPAddress localGateway;\n\/\/IPAddress localGateway(192, 168, 1, 1); \/\/hardcoded\nIPAddress subnet(255, 255, 0, 0);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">initWiFi()<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">initWiFi()<\/span> function returns a boolean value (either <span class=\"rnthl rntliteral\">true<\/span> or <span class=\"rnthl rntliteral\">false<\/span>) indicating if the ESP board connected successfully to a network.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>bool initWiFi() {\n  if(ssid==\"\" || ip==\"\"){\n    Serial.println(\"Undefined SSID or IP address.\");\n    return false;\n  }\n\n  WiFi.mode(WIFI_STA);\n  localIP.fromString(ip.c_str());\n\n  if (!WiFi.config(localIP, gateway, subnet)){\n    Serial.println(\"STA Failed to configure\");\n    return false;\n  }\n  WiFi.begin(ssid.c_str(), pass.c_str());\n  Serial.println(\"Connecting to WiFi...\");\n\n  unsigned long currentMillis = millis();\n  previousMillis = currentMillis;\n\n  while(WiFi.status() != WL_CONNECTED) {\n    currentMillis = millis();\n    if (currentMillis - previousMillis &gt;= interval) {\n      Serial.println(\"Failed to connect.\");\n      return false;\n    }\n  }\n\n  Serial.println(WiFi.localIP());\n  return true;\n}<\/code><\/pre>\n\n\n\n<p>First, it checks if the <span class=\"rnthl rntliteral\">ssid<\/span> and <span class=\"rnthl rntliteral\">ip<\/span> variables are empty. If they are, it won&#8217;t be able to connect to a network, so it returns <span class=\"rnthl rntliteral\">false<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if(ssid==\"\" || ip==\"\"){<\/code><\/pre>\n\n\n\n<p>If that&#8217;s not the case, we&#8217;ll try to connect to the network using the SSID and password saved in the <span class=\"rnthl rntliteral\">ssid<\/span> and <span class=\"rnthl rntliteral\">pass<\/span> variables and set the IP address.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>WiFi.mode(WIFI_STA);\nlocalIP.fromString(ip.c_str());\n\nif (!WiFi.config(localIP, gateway, subnet)){\n  Serial.println(\"STA Failed to configure\");\n  return false;\n}\nWiFi.begin(ssid.c_str(), pass.c_str());\nSerial.println(\"Connecting to WiFi...\");<\/code><\/pre>\n\n\n\n<p>If it cannot connect to Wi-Fi after 10 seconds (<span class=\"rnthl rntliteral\">interval<\/span> variable), it will return <span class=\"rnthl rntliteral\">false<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>unsigned long currentMillis = millis();\npreviousMillis = currentMillis;\n\nwhile(WiFi.status() != WL_CONNECTED) {\n  currentMillis = millis();\n  if (currentMillis - previousMillis &gt;= interval) {\n    Serial.println(\"Failed to connect.\");\n    return false;\n  }<\/code><\/pre>\n\n\n\n<p>If none of the previous conditions are met, it means that the ESP successfully connected to the network in station mode (returns <span class=\"rnthl rntliteral\">true<\/span>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>return true;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">setup()<\/h4>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, start reading the files to get the previously saved SSID, password, IP address, and gateway.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>ssid = readFile(LittleFS, ssidPath);\npass = readFile(LittleFS, passPath);\nip = readFile(LittleFS, ipPath);\ngateway = readFile (LittleFS, gatewayPath);<\/code><\/pre>\n\n\n\n<p>If the ESP connects successfully in station mode (<span class=\"rnthl rntliteral\">initWiFi()<\/span> function returns <span class=\"rnthl rntliteral\">true<\/span>), 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):<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if(initWiFi()) {\n  \/\/ Route for root \/ web page\n  server.on(\"\/\", HTTP_GET, &#091;](AsyncWebServerRequest *request) {\n    request-&gt;send(LittleFS, \"\/index.html\", \"text\/html\", false, processor);\n  });\n  server.serveStatic(\"\/\", LittleFS, \"\/\");\n    \n  \/\/ Route to set GPIO state to HIGH\n  server.on(\"\/on\", HTTP_GET, &#091;](AsyncWebServerRequest *request) {\n    digitalWrite(ledPin, HIGH);\n    request-&gt;send(LittleFS, \"\/index.html\", \"text\/html\", false, processor);\n  });\n\n  \/\/ Route to set GPIO state to LOW\n  server.on(\"\/off\", HTTP_GET, &#091;](AsyncWebServerRequest *request) {\n    digitalWrite(ledPin, LOW);\n    request-&gt;send(LittleFS, \"\/index.html\", \"text\/html\", false, processor);\n  });\n  server.begin();\n}<\/code><\/pre>\n\n\n\n<p>If that&#8217;s not the case, the <span class=\"rnthl rntliteral\">initWiFi()<\/span> function returns <span class=\"rnthl rntliteral\">false<\/span>. The ESP will set an access point:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>else {\n  \/\/ Connect to Wi-Fi network with SSID and password\n  Serial.println(\"Setting AP (Access Point)\");\n  \/\/ NULL sets an open Access Point\n  WiFi.softAP(\"ESP-WIFI-MANAGER\", NULL);\n\n  IPAddress IP = WiFi.softAPIP();\n  Serial.print(\"AP IP address: \");\n  Serial.println(IP); <\/code><\/pre>\n\n\n\n<p>To set an access point, we use the <span class=\"rnthl rntliteral\">softAP()<\/span> 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 <span class=\"rnthl rntliteral\">NULL<\/span>. You can add a password if you wish. To learn more about setting up an Access Point, read one of the following tutorials:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-access-point-ap-web-server\/\">How to Set an ESP32 Access Point (AP) for Web ServerStatic IP Address<\/a><\/li>\n<\/ul>\n\n\n\n<p>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 <span class=\"rnthl rntliteral\">wifimanager.html<\/span> file when it receives a request on the root <span class=\"rnthl rntliteral\">\/<\/span> URL.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Web Server Root URL\nserver.on(\"\/\", HTTP_GET, &#091;](AsyncWebServerRequest *request){\n  request-&gt;send(LittleFS, \"\/wifimanager.html\", \"text\/html\");\n});<\/code><\/pre>\n\n\n\n<p>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 <span class=\"rnthl rntliteral\">ssid<\/span>, <span class=\"rnthl rntliteral\">pass,<\/span> and <span class=\"rnthl rntliteral\">ip<\/span> variables and save those variables in the corresponding files.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.on(\"\/\", HTTP_POST, &#091;](AsyncWebServerRequest *request) {\n  int params = request-&gt;params();\n  for(int i=0;i&lt;params;i++){\n    AsyncWebParameter* p = request-&gt;getParam(i);\n    if(p-&gt;isPost()){\n      \/\/ HTTP POST ssid value\n      if (p-&gt;name() == PARAM_INPUT_1) {\n        ssid = p-&gt;value().c_str();\n        Serial.print(\"SSID set to: \");\n        Serial.println(ssid);\n        \/\/ Write file to save value\n        writeFile(LittleFS, ssidPath, ssid.c_str());\n      }\n      \/\/ HTTP POST pass value\n      if (p-&gt;name() == PARAM_INPUT_2) {\n        pass = p-&gt;value().c_str();\n        Serial.print(\"Password set to: \");\n        Serial.println(pass);\n        \/\/ Write file to save value\n        writeFile(LittleFS, passPath, pass.c_str());\n      }\n      \/\/ HTTP POST ip value\n      if (p-&gt;name() == PARAM_INPUT_3) {\n        ip = p-&gt;value().c_str();\n        Serial.print(\"IP Address set to: \");\n        Serial.println(ip);\n        \/\/ Write file to save value\n        writeFile(LittleFS, ipPath, ip.c_str());\n      }\n     \/\/ HTTP POST gateway value\n      if (p-&gt;name() == PARAM_INPUT_4) {\n        gateway = p-&gt;value().c_str();\n        Serial.print(\"Gateway set to: \");\n        Serial.println(gateway);\n        \/\/ Write file to save value\n        writeFile(LittleFS, gatewayPath, gateway.c_str());\n      }\n      \/\/Serial.printf(\"POST&#091;%s]: %s\\n\", p-&gt;name().c_str(), p-&gt;value().c_str());\n    }\n  }<\/code><\/pre>\n\n\n\n<p>After submitting the form, send a response with some text so that we know that the ESP received the form details:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>request-&gt;send(200, \"text\/plain\", \"Done. ESP will restart, connect to your router and go to IP address: \" + ip);<\/code><\/pre>\n\n\n\n<p>After three seconds, restart the ESP board with <span class=\"rnthl rntliteral\">ESP.restart()<\/span>:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>delay(3000);\nESP.restart();<\/code><\/pre>\n\n\n\n<p>That&#8217;s a quick summary of how the code works.<\/p>\n\n\n\n<p>You can apply this idea to any of the other web server projects built with the ESPAsyncWebServer library.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Uploading Code and Files<\/h1>\n\n\n\n<p>Upload the files in the <em>data <\/em>folder to your ESP32. On the Arduino IDE, press [<strong>Ctrl<\/strong>] + [<strong>Shift<\/strong>] + [<strong>P<\/strong>] on Windows or [<strong>\u2318<\/strong>] + [<strong>Shift<\/strong>] + [<strong>P<\/strong>] on MacOS to open the command palette. Search for the&nbsp;<strong>Upload LittleFS to Pico\/ESP8266\/ESP32<\/strong>&nbsp;command and click on it.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"744\" height=\"401\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/upload-files-little-fs-esp32-arduino-ide.png?resize=744%2C401&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Upload LittleFS to Pico ESP8266 ESP32 Arduino IDE\" class=\"wp-image-158893\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/upload-files-little-fs-esp32-arduino-ide.png?w=744&amp;quality=100&amp;strip=all&amp;ssl=1 744w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/upload-files-little-fs-esp32-arduino-ide.png?resize=300%2C162&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 744px) 100vw, 744px\" \/><\/figure><\/div>\n\n\n<p>If you don\u2019t have this option is because you didn\u2019t install the filesystem uploader plugin.<a href=\"https:\/\/randomnerdtutorials.com\/arduino-ide-2-install-esp32-littlefs\/\">&nbsp;Check this tutorial<\/a>.<\/p>\n\n\n\n<p class=\"rntbox rntcred\"><strong>Important:&nbsp;<\/strong>make sure the Serial Monitor is closed before uploading to the filesystem. Otherwise, the upload will fail.<\/p>\n\n\n\n<p>If you&#8217;re using VS Code with the PlatformIO extension, follow one of the next tutorials to learn how to upload files to your boards:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-vs-code-platformio-littlefs\/\">ESP32 with VS Code and PlatformIO: Upload Files to LittleFS Filesystem<\/a><\/li>\n<\/ul>\n\n\n\n<p>After successfully uploading the files, upload the code to your board.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"36\" height=\"39\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/arduino-ide-2-upload-button.png?resize=36%2C39&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Arduino IDE 2 Upload Button\" class=\"wp-image-146269\"\/><\/figure><\/div>\n\n\n<h1 class=\"wp-block-heading\">Demonstration<\/h1>\n\n\n\n<p>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 <span class=\"rnthl rntliteral\">ssid.txt<\/span>, <span class=\"rnthl rntliteral\">pass.txt<\/span>, and <span class=\"rnthl rntliteral\">ip.txt<\/span> files, and it won&#8217;t succeed because those files weren&#8217;t created yet. So, it will start an Access Point.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"601\" height=\"619\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/ESP-Wi-Fi-Manager-Sets-Access-Point-Serial-Monitor.png?resize=601%2C619&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-Wi-Fi Manager Sets Access Point Serial Monitor\" class=\"wp-image-107853\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/ESP-Wi-Fi-Manager-Sets-Access-Point-Serial-Monitor.png?w=601&amp;quality=100&amp;strip=all&amp;ssl=1 601w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/ESP-Wi-Fi-Manager-Sets-Access-Point-Serial-Monitor.png?resize=291%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 291w\" sizes=\"(max-width: 601px) 100vw, 601px\" \/><\/figure><\/div>\n\n\n<p>On your computer or smartphone, go to your network settings and connect to the <strong>ESP-WIFI-MANAGER<\/strong> access point.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"466\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/03\/Connect-to-ESP32-Wi-Fi-Manager.png?resize=750%2C466&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Connect to ESP32 ESP8266 Access Point Wi-Fi Manager\" class=\"wp-image-102724\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/03\/Connect-to-ESP32-Wi-Fi-Manager.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/03\/Connect-to-ESP32-Wi-Fi-Manager.png?resize=300%2C186&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>Then, open your browser and go to <span class=\"rnthl rntliteral\">192.168.4.1<\/span>. The Wi-Fi Manager web page should open.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"714\" height=\"643\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/02\/ESP32-ESP8266-Wi-Fi-Manager-Fields.png?resize=714%2C643&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 Wi-Fi Manager Fields\" class=\"wp-image-109212\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/02\/ESP32-ESP8266-Wi-Fi-Manager-Fields.png?w=714&amp;quality=100&amp;strip=all&amp;ssl=1 714w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/02\/ESP32-ESP8266-Wi-Fi-Manager-Fields.png?resize=300%2C270&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 714px) 100vw, 714px\" \/><\/figure><\/div>\n\n\n<p>Enter your network credentials: SSID and Password and an available IP address on your local network.<\/p>\n\n\n\n<p>After that, you&#8217;ll be redirected to the following page:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"643\" height=\"309\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/03\/ESP32-connected-to-station-success-Wi-Fi-Manager.png?resize=643%2C309&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 connected to station success Wi-Fi Manager\" class=\"wp-image-102725\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/03\/ESP32-connected-to-station-success-Wi-Fi-Manager.png?w=643&amp;quality=100&amp;strip=all&amp;ssl=1 643w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/03\/ESP32-connected-to-station-success-Wi-Fi-Manager.png?resize=300%2C144&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 643px) 100vw, 643px\" \/><\/figure><\/div>\n\n\n<p>At the same time, the ESP should print something in the Serial Monitor indicating that the parameters you&#8217;ve inserted were successfully saved in the corresponding files.<\/p>\n\n\n\n<p>After a few seconds, the ESP will restart. And if you&#8217;ve inserted the correct SSID and password, it will start in station mode:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"601\" height=\"619\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/ESP32-EPS8266-Connected-to-Access-Point-Wi-Fi-Manager.png?resize=601%2C619&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 Connected Successfully to Wi-Fi Station\" class=\"wp-image-107841\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/ESP32-EPS8266-Connected-to-Access-Point-Wi-Fi-Manager.png?w=601&amp;quality=100&amp;strip=all&amp;ssl=1 601w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/ESP32-EPS8266-Connected-to-Access-Point-Wi-Fi-Manager.png?resize=291%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 291w\" sizes=\"(max-width: 601px) 100vw, 601px\" \/><\/figure><\/div>\n\n\n<p>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:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"687\" height=\"424\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/ESP32-ESP8266-Control-Output-Web-Server.png?resize=687%2C424&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 Control Outputs Web Server\" class=\"wp-image-107842\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/ESP32-ESP8266-Control-Output-Web-Server.png?w=687&amp;quality=100&amp;strip=all&amp;ssl=1 687w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/ESP32-ESP8266-Control-Output-Web-Server.png?resize=300%2C185&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 687px) 100vw, 687px\" \/><\/figure><\/div>\n\n\n<h1 class=\"wp-block-heading\">Wrapping Up<\/h1>\n\n\n\n<p>In this tutorial, you&#8217;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 <a href=\"https:\/\/randomnerdtutorials.com\/esp32-status-indicator-sensor-pcb\/\">apply the Wi-Fi Manager to any web server project<\/a> built with the ESPAsyncWebServer library.<\/p>\n\n\n\n<p>One of our readers created a more advanced version of this project with more fields and features, <a href=\"https:\/\/github.com\/ldijkman\/randomnerd_esp32_wifi_manager\" target=\"_blank\" rel=\"noreferrer noopener\">you can check his project here<\/a>. <\/p>\n\n\n\n<p>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:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/build-web-servers-esp32-esp8266-ebook\/\">Build Web Servers with ESP32 and ESP8266 eBook (2nd Edition)<\/a><\/li>\n<\/ul>\n\n\n\n<p>We hope you&#8217;ve found this tutorial useful.<\/p>\n\n\n\n<p>Thanks for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this guide, you&#8217;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 &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32: Create a Wi-Fi Manager (AsyncWebServer library)\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-wi-fi-manager-asyncwebserver\/#more-107818\" aria-label=\"Read more about ESP32: Create a Wi-Fi Manager (AsyncWebServer library)\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":108563,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[281,276,277,299,264],"tags":[],"class_list":["post-107818","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32-project","category-esp32","category-esp32-arduino-ide","category-0-esp32","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/12\/ESP32-Wi-Fi-Manager-Web-Server.jpg?fit=1280%2C720&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/107818","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=107818"}],"version-history":[{"count":29,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/107818\/revisions"}],"predecessor-version":[{"id":167926,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/107818\/revisions\/167926"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/108563"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=107818"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=107818"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=107818"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}