{"id":99568,"date":"2020-10-23T13:15:18","date_gmt":"2020-10-23T13:15:18","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=99568"},"modified":"2025-03-17T11:45:20","modified_gmt":"2025-03-17T11:45:20","slug":"esp8266-nodemcu-async-web-server-espasyncwebserver-library","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-async-web-server-espasyncwebserver-library\/","title":{"rendered":"ESP8266 NodeMCU Async Web Server \u2013 Control Outputs with Arduino IDE (ESPAsyncWebServer library)"},"content":{"rendered":"\n<p>In this tutorial you&#8217;ll learn how to build an asynchronous web server with the ESP8266 NodeMCU board to control its outputs. The board will be programmed using Arduino IDE, and we&#8217;ll use the ESPAsyncWebServer library.<\/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\/2020\/10\/ESP8266-NodeMCU-ESPAsyncWebServer-library-control-outputs-web-server-Arduino.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU Async Web Server Control Outputs with Arduino IDE ESPAsyncWebServer library\" class=\"wp-image-99577\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-ESPAsyncWebServer-library-control-outputs-web-server-Arduino.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-ESPAsyncWebServer-library-control-outputs-web-server-Arduino.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-ESPAsyncWebServer-library-control-outputs-web-server-Arduino.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-ESPAsyncWebServer-library-control-outputs-web-server-Arduino.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><strong>You might also like:<\/strong> <a href=\"https:\/\/randomnerdtutorials.com\/esp32-async-web-server-espasyncwebserver-library\/\">ESP32 Async Web Server \u2013 Control Outputs with Arduino IDE (ESPAsyncWebServer library)<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Asynchronous Web Server<\/h2>\n\n\n\n<p>To build the web server we\u2019ll use the\u00a0<a href=\"https:\/\/github.com\/ESP32Async\/ESPAsyncWebServer\" target=\"_blank\" rel=\"noopener\" title=\"\">ESPAsyncWebServer library<\/a>\u00a0that provides an easy way to build an asynchronous web server. Building an asynchronous web server has several advantages as mentioned in the library GitHub page, such as:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u201cHandle more than one connection at the same time\u201d;<\/li>\n\n\n\n<li>\u201cWhen you send the response, you are immediately ready to handle other connections while the server is taking care of sending the response in the background\u201d;<\/li>\n\n\n\n<li>\u201cSimple template processing engine to handle templates\u201d;<\/li>\n\n\n\n<li>And much more.<\/li>\n<\/ul>\n\n\n\n<p>Take a look at the\u00a0<a href=\"https:\/\/github.com\/ESP32Async\/ESPAsyncWebServer\/wiki\" target=\"_blank\" rel=\"noopener\" title=\"\">library documentation on its GitHub page<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Parts Required<\/h2>\n\n\n\n<p>In this tutorial we&#8217;ll control three outputs. As an example, we&#8217;ll control LEDs. So, you need the following parts:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/esp8266-esp-12e-nodemcu-wi-fi-development-board\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP8266<\/a>\u00a0(read\u00a0<a href=\"https:\/\/makeradvisor.com\/best-esp8266-wi-fi-development-board\/\" target=\"_blank\" rel=\"noreferrer noopener\">Best ESP8266 development boards<\/a>)<\/li>\n\n\n\n<li><span style=\"font-size: inherit; background-color: initial;\">3x <\/span><a style=\"font-size: inherit; background-color: initial;\" href=\"https:\/\/makeradvisor.com\/tools\/3mm-5mm-leds-kit-storage-box\/\" target=\"_blank\" rel=\"noreferrer noopener\">LEDs<\/a><\/li>\n\n\n\n<li>3x <a href=\"https:\/\/makeradvisor.com\/tools\/resistors-kits\/\" target=\"_blank\" rel=\"noreferrer noopener\">220 Ohm Resistor<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\" rel=\"noreferrer noopener\">Breadboard<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\" rel=\"noreferrer noopener\">Jumper wires<\/a><\/li>\n<\/ul>\n\n\n<p>You can use the preceding links or go directly to <a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\">MakerAdvisor.com\/tools<\/a> to find all the parts for your projects at the best price!<\/p><p style=\"text-align:center;\"><a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2017\/10\/header-200.png?w=1200&#038;quality=100&#038;strip=all&#038;ssl=1\"><\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Schematic<\/h2>\n\n\n\n<p>Before proceeding to the code, wire 3 LEDs to the ESP8266. We&#8217;re connecting the LEDs to GPIOs 5, 4 and 2, but you can use any other GPIOs (read <a href=\"https:\/\/randomnerdtutorials.com\/esp8266-pinout-reference-gpios\/\">ESP8266 NodeMCU GPIO Reference Guide<\/a>).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"534\" height=\"808\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Arduino-Outputs-Async-ESPAsyncWebServer-library-wiring-schematic-diagram.png?resize=534%2C808&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU Arduino Outputs Async ESPAsyncWebServer library wiring schematic diagram\" class=\"wp-image-99571\" style=\"width:500px;height:757px\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Arduino-Outputs-Async-ESPAsyncWebServer-library-wiring-schematic-diagram.png?w=534&amp;quality=100&amp;strip=all&amp;ssl=1 534w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Arduino-Outputs-Async-ESPAsyncWebServer-library-wiring-schematic-diagram.png?resize=198%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 198w\" sizes=\"(max-width: 534px) 100vw, 534px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Installing Libraries \u2013 ESP Async Web Server<\/h2>\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 by ESP32Async<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/ESP32Async\/ESPAsyncTCP\" target=\"_blank\" rel=\"noopener\" title=\"\">ESPAsyncTCP&nbsp;by ESP32Async<\/a><\/li>\n<\/ul>\n\n\n\n<p>You can install these libraries using the Arduino Library Manager. Go to&nbsp;<strong>Sketch&nbsp;<\/strong>&gt;&nbsp;<strong>Include Library<\/strong>&nbsp;&gt;&nbsp;<strong>Manage Libraries<\/strong>&nbsp;and search for the libraries&#8217; names.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Project Overview<\/h2>\n\n\n\n<p>To better understand the code, let&#8217;s see how the web server works.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"300\" height=\"595\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Control-Outputs.png?resize=300%2C595&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU Async Web Server Control Outputs\" class=\"wp-image-99573\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Control-Outputs.png?w=300&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Control-Outputs.png?resize=151%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 151w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/figure><\/div>\n\n\n<ul class=\"wp-block-list\">\n<li>The web server contains one heading &#8220;ESP Web Server&#8221; and three buttons (toggle switches) to control three outputs. Each slider button has a label indicating the GPIO output pin. You can easily remove\/add more outputs.<\/li>\n\n\n\n<li>When the slider is red, it means the output is on (its state is HIGH). If you toggle the slider, it turns off the output (change the state to LOW).<\/li>\n\n\n\n<li>When the slider is gray, it means the output is off (its state is LOW). If you toggle the slider, it turns on the output (change the state to HIGH).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">How it Works?<\/h3>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"900\" height=\"408\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Project-Overview-ESPAsyncWebServer-Library.png?resize=900%2C408&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU Async Web Server Project Overview ESPAsyncWebServer Library\" class=\"wp-image-99574\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Project-Overview-ESPAsyncWebServer-Library.png?w=900&amp;quality=100&amp;strip=all&amp;ssl=1 900w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Project-Overview-ESPAsyncWebServer-Library.png?resize=300%2C136&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Project-Overview-ESPAsyncWebServer-Library.png?resize=768%2C348&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 900px) 100vw, 900px\" \/><\/figure><\/div>\n\n\n<p>Let&#8217;s see what happens when you toggle the buttons. We&#8217;ll see the example for GPIO 2. It works similarly for the other buttons.<\/p>\n\n\n\n<p><strong>1.<\/strong> In the first scenario, you toggle the button to turn GPIO 2 on. When that happens, it makes an HTTP GET request on the <span class=\"rnthl rntliteral\">\/update?output=<strong>2<\/strong>&amp;state=<strong>1<\/strong><\/span> URL. Based on that URL, we change the state of GPIO 2 to 1 (<strong>HIGH<\/strong>) and turn the LED on.<\/p>\n\n\n\n<p><strong>2.<\/strong> In the second example, when you toggle the button to turn GPIO 2 off. When that happens, make an HTTP GET request on the <span class=\"rnthl rntliteral\">\/update?output=<strong>2<\/strong>&amp;state=<strong>0<\/strong><\/span> URL. Based on that URL, we change the state of GPIO 2 to 0 (<strong>LOW<\/strong>) and turn the LED off.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Code for ESP Async Web Server<\/h2>\n\n\n\n<p>Copy the following code to your Arduino IDE.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*********\n  Rui Santos &amp; Sara Santos - Random Nerd Tutorials\n  Complete project details at https:\/\/RandomNerdTutorials.com\/esp8266-nodemcu-async-web-server-espasyncwebserver-library\/\n  The above copyright notice and this permission notice shall be included in all\n  copies or substantial portions of the Software.\n*********\/\n\n\/\/ Import required libraries\n#include &lt;ESP8266WiFi.h&gt;\n#include &lt;ESPAsyncTCP.h&gt;\n#include &lt;ESPAsyncWebServer.h&gt;\n\n\/\/ Replace with your network credentials\nconst char* ssid = &quot;REPLACE_WITH_YOUR_SSID&quot;;\nconst char* password = &quot;REPLACE_WITH_YOUR_PASSWORD&quot;;\n\nconst char* PARAM_INPUT_1 = &quot;output&quot;;\nconst char* PARAM_INPUT_2 = &quot;state&quot;;\n\n\/\/ Create AsyncWebServer object on port 80\nAsyncWebServer server(80);\n\nconst char index_html[] PROGMEM = R&quot;rawliteral(\n&lt;!DOCTYPE HTML&gt;&lt;html&gt;\n&lt;head&gt;\n  &lt;title&gt;ESP Web Server&lt;\/title&gt;\n  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;\n  &lt;link rel=&quot;icon&quot; href=&quot;data:,&quot;&gt;\n  &lt;style&gt;\n    html {font-family: Arial; display: inline-block; text-align: center;}\n    h2 {font-size: 3.0rem;}\n    p {font-size: 3.0rem;}\n    body {max-width: 600px; margin:0px auto; padding-bottom: 25px;}\n    .switch {position: relative; display: inline-block; width: 120px; height: 68px} \n    .switch input {display: none}\n    .slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 6px}\n    .slider:before {position: absolute; content: &quot;&quot;; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 3px}\n    input:checked+.slider {background-color: #b30000}\n    input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}\n  &lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n  &lt;h2&gt;ESP Web Server&lt;\/h2&gt;\n  %BUTTONPLACEHOLDER%\n&lt;script&gt;function toggleCheckbox(element) {\n  var xhr = new XMLHttpRequest();\n  if(element.checked){ xhr.open(&quot;GET&quot;, &quot;\/update?output=&quot;+element.id+&quot;&amp;state=1&quot;, true); }\n  else { xhr.open(&quot;GET&quot;, &quot;\/update?output=&quot;+element.id+&quot;&amp;state=0&quot;, true); }\n  xhr.send();\n}\n&lt;\/script&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;\n)rawliteral&quot;;\n\n\/\/ Replaces placeholder with button section in your web page\nString processor(const String&amp; var){\n  \/\/Serial.println(var);\n  if(var == &quot;BUTTONPLACEHOLDER&quot;){\n    String buttons = &quot;&quot;;\n    buttons += &quot;&lt;h4&gt;Output - GPIO 5&lt;\/h4&gt;&lt;label class=\\&quot;switch\\&quot;&gt;&lt;input type=\\&quot;checkbox\\&quot; onchange=\\&quot;toggleCheckbox(this)\\&quot; id=\\&quot;5\\&quot; &quot; + outputState(5) + &quot;&gt;&lt;span class=\\&quot;slider\\&quot;&gt;&lt;\/span&gt;&lt;\/label&gt;&quot;;\n    buttons += &quot;&lt;h4&gt;Output - GPIO 4&lt;\/h4&gt;&lt;label class=\\&quot;switch\\&quot;&gt;&lt;input type=\\&quot;checkbox\\&quot; onchange=\\&quot;toggleCheckbox(this)\\&quot; id=\\&quot;4\\&quot; &quot; + outputState(4) + &quot;&gt;&lt;span class=\\&quot;slider\\&quot;&gt;&lt;\/span&gt;&lt;\/label&gt;&quot;;\n    buttons += &quot;&lt;h4&gt;Output - GPIO 2&lt;\/h4&gt;&lt;label class=\\&quot;switch\\&quot;&gt;&lt;input type=\\&quot;checkbox\\&quot; onchange=\\&quot;toggleCheckbox(this)\\&quot; id=\\&quot;2\\&quot; &quot; + outputState(2) + &quot;&gt;&lt;span class=\\&quot;slider\\&quot;&gt;&lt;\/span&gt;&lt;\/label&gt;&quot;;\n    return buttons;\n  }\n  return String();\n}\n\nString outputState(int output){\n  if(digitalRead(output)){\n    return &quot;checked&quot;;\n  }\n  else {\n    return &quot;&quot;;\n  }\n}\n\nvoid setup(){\n  \/\/ Serial port for debugging purposes\n  Serial.begin(115200);\n\n  pinMode(5, OUTPUT);\n  digitalWrite(5, LOW);\n  pinMode(4, OUTPUT);\n  digitalWrite(4, LOW);\n  pinMode(2, OUTPUT);\n  digitalWrite(2, LOW);\n  \n  \/\/ Connect to Wi-Fi\n  WiFi.begin(ssid, password);\n  while (WiFi.status() != WL_CONNECTED) {\n    delay(1000);\n    Serial.println(&quot;Connecting to WiFi..&quot;);\n  }\n\n  \/\/ Print ESP Local IP Address\n  Serial.println(WiFi.localIP());\n\n  \/\/ Route for root \/ web page\n  server.on(&quot;\/&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\n    request-&gt;send(200, &quot;text\/html&quot;, index_html, processor);\n  });\n\n  \/\/ Send a GET request to &lt;ESP_IP&gt;\/update?output=&lt;inputMessage1&gt;&amp;state=&lt;inputMessage2&gt;\n  server.on(&quot;\/update&quot;, HTTP_GET, [] (AsyncWebServerRequest *request) {\n    String inputMessage1;\n    String inputMessage2;\n    \/\/ GET input1 value on &lt;ESP_IP&gt;\/update?output=&lt;inputMessage1&gt;&amp;state=&lt;inputMessage2&gt;\n    if (request-&gt;hasParam(PARAM_INPUT_1) &amp;&amp; request-&gt;hasParam(PARAM_INPUT_2)) {\n      inputMessage1 = request-&gt;getParam(PARAM_INPUT_1)-&gt;value();\n      inputMessage2 = request-&gt;getParam(PARAM_INPUT_2)-&gt;value();\n      digitalWrite(inputMessage1.toInt(), inputMessage2.toInt());\n    }\n    else {\n      inputMessage1 = &quot;No message sent&quot;;\n      inputMessage2 = &quot;No message sent&quot;;\n    }\n    Serial.print(&quot;GPIO: &quot;);\n    Serial.print(inputMessage1);\n    Serial.print(&quot; - Set to: &quot;);\n    Serial.println(inputMessage2);\n    request-&gt;send(200, &quot;text\/plain&quot;, &quot;OK&quot;);\n  });\n\n  \/\/ Start server\n  server.begin();\n}\n\nvoid loop() {\n\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP8266\/ESPAsyncWebServer_library_example.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How the Code Works<\/h2>\n\n\n\n<p>In this section we\u2019ll explain how the code works. Keep reading if you want to learn more or jump to the Demonstration section to see the final result.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Importing libraries<\/h3>\n\n\n\n<p>First, import the required libraries. You need to include the <span class=\"rnthl rntliteral\">WiFi<\/span>, <span class=\"rnthl rntliteral\">ESPAsyncWebserver<\/span> and the <span class=\"rnthl rntliteral\">ESPAsyncTCP<\/span> libraries.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;ESP8266WiFi.h&gt;\n#include &lt;ESPAsyncTCP.h&gt;\n#include &lt;ESPAsyncWebServer.h&gt;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Setting your network credentials<\/h3>\n\n\n\n<p>Insert your network credentials in the following variables, so that the ESP8266 can connect to your local network.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const char* ssid = \"REPLACE_WITH_YOUR_SSID\";\nconst char* password = \"REPLACE_WITH_YOUR_PASSWORD\";<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Input Parameters<\/h3>\n\n\n\n<p>To check the parameters passed on the URL (GPIO number and its state), we create two variables, one for the output and other for the state. <\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const char* PARAM_INPUT_1 = \"output\";\nconst char* PARAM_INPUT_2 = \"state\";<\/code><\/pre>\n\n\n\n<p>Remember that the ESP8266 receives requests like this: <span class=\"rnthl rntliteral\">\/update?<strong>output<\/strong>=2&amp;<strong>state<\/strong>=0<\/span><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">AsyncWebServer object<\/h3>\n\n\n\n<p>Create an <span class=\"rnthl rntliteral\">AsyncWebServer<\/span> object on port 80.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>AsyncWebServer server(80);<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Building the Web Page<\/h3>\n\n\n\n<p>All the HTML text with styles and JavaScript is stored in the&nbsp;<span class=\"rnthl rntliteral\">index_html<\/span>&nbsp;variable. Now we\u2019ll go through the HTML text and see what each part does.<\/p>\n\n\n\n<p>The title goes inside the <span style=\"color: #333399;\">&lt;title&gt;<\/span> and <span style=\"color: #333399;\">&lt;\/tile&gt;<\/span> tags. The title is exactly what it sounds like: the title of your document, which shows up in your web browser\u2019s title bar. In this case, it is &#8220;ESP Web Server&#8221;.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;title&gt;ESP Web Server&lt;\/title&gt;<\/code><\/pre>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"365\" height=\"167\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/05\/ESP32-Web-Server-Title.png?resize=365%2C167&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Async Web Server web page title HTML\" class=\"wp-image-97038\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/05\/ESP32-Web-Server-Title.png?w=365&amp;quality=100&amp;strip=all&amp;ssl=1 365w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/05\/ESP32-Web-Server-Title.png?resize=300%2C137&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 365px) 100vw, 365px\" \/><\/figure><\/div>\n\n\n<p>The following <span style=\"color: #333399;\">&lt;meta&gt;<\/span> tag makes your web page responsive in any browser (laptop, tablet or smartphone).<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"&gt;<\/code><\/pre>\n\n\n\n<p>The next line prevents requests on the favicon. In this case, we don&#8217;t have a favicon. The favicon is the website icon that shows next to the title in the web browser tab. If we don&#8217;t add the following line, the ESP will receive a request for the favicon every time we access the web server.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;link rel=\"icon\" href=\"data:,\"&gt;<\/code><\/pre>\n\n\n\n<p>Between the <span style=\"color: #333399;\">&lt;style&gt;&lt;\/style&gt;&nbsp;<\/span>tags, we add some CSS to style the web page. We won&#8217;t go into detail on how this CSS styling works.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;style&gt;\n    html {font-family: Arial; display: inline-block; text-align: center;}\n    h2 {font-size: 3.0rem;}\n    p {font-size: 3.0rem;}\n    body {max-width: 600px; margin:0px auto; padding-bottom: 25px;}\n    .switch {position: relative; display: inline-block; width: 120px; height: 68px} \n    .switch input {display: none}\n    .slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 6px}\n    .slider:before {position: absolute; content: \"\"; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 3px}\n    input:checked+.slider {background-color: #b30000}\n    input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}\n&lt;\/style&gt;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">HTML Body<\/h4>\n\n\n\n<p>Inside the <span style=\"color: #333399;\">&lt;body&gt;&lt;\/body&gt;<\/span> tags is where we add the web page content.<\/p>\n\n\n\n<p>The&nbsp;<span style=\"color: #333399;\">&lt;h2&gt;&lt;\/h2&gt;<\/span>&nbsp;tags add a heading to the web page. In this case, the \u201cESP Web Server\u201d text, but you can add any other text.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;h2&gt;ESP Web Server&lt;\/h2&gt;<\/code><\/pre>\n\n\n\n<p>After the heading, we have the buttons. The way the buttons show up on the web page (red: if the GPIO is on; or gray: if the GPIO is off) varies depending on the current GPIO state. <\/p>\n\n\n\n<p>When you access the web server page, you want it to show the right current GPIO states. So, instead of adding the HTML text to build the buttons, we&#8217;ll add a placeholder <span class=\"rnthl rntliteral\">%BUTTONPLACEHOLDER%<\/span>. This palceholder will then be replaced with the actual HTML text to build the buttons with the right states, when the web page is loaded.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>%BUTTONPLACEHOLDER%<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">JavaScript<\/h3>\n\n\n\n<p>Then, there&#8217;s some JavaScript that is responsible to make an <a href=\"https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-http-get-open-weather-map-thingspeak-arduino\/\">HTTP GET request<\/a> when you toggle the buttons as we&#8217;ve explained previously.<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>&lt;script&gt;function toggleCheckbox(element) {\n  var xhr = new XMLHttpRequest();\n  if(element.checked){ xhr.open(\"GET\", \"\/update?output=\"+element.id+\"&amp;state=1\", true); }\n  else { xhr.open(\"GET\", \"\/update?output=\"+element.id+\"&amp;state=0\", true); }\n  xhr.send();\n}\n&lt;\/script&gt;<\/code><\/pre>\n\n\n\n<p>Here&#8217;s the line that makes the request:<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>if(element.checked){ xhr.open(\"GET\", \"\/update?output=\"+element.id+\"&amp;state=1\", true); }<\/code><\/pre>\n\n\n\n<p><span class=\"rnthl rntliteral\">element.id<\/span> returns the id of an HTML element. The id of each button will be the GPIO controlled as we&#8217;ll see in the next section:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>GPIO 5 button \u00bb element.id = 5<\/li>\n\n\n\n<li>GPIO 4 button \u00bb element.id = 4<\/li>\n\n\n\n<li>GPIO 2 button \u00bb element.id = 2<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Processor<\/h3>\n\n\n\n<p>Now, we need to create the&nbsp;<span class=\"rnthl rntliteral\">processor()<\/span>&nbsp;function, that replaces the placeholders in the HTML text with what we define. <\/p>\n\n\n\n<p>When the web page is requested, check if the HTML has any placeholders. If it finds the <span class=\"rnthl rntliteral\">%BUTTONPLACEHOLDER%<\/span> placeholder, it returns the HTML text to create the buttons.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String processor(const String&amp; var){\n  \/\/Serial.println(var);\n  if(var == \"BUTTONPLACEHOLDER\"){\n    String buttons = \"\";\n    buttons += \"&lt;h4&gt;Output - GPIO 5&lt;\/h4&gt;&lt;label class=\\\"switch\\\"&gt;&lt;input type=\\\"checkbox\\\" onchange=\\\"toggleCheckbox(this)\\\" id=\\\"5\\\" \" + outputState(5) + \"&gt;&lt;span class=\\\"slider\\\"&gt;&lt;\/span&gt;&lt;\/label&gt;\";\n    buttons += \"&lt;h4&gt;Output - GPIO 4&lt;\/h4&gt;&lt;label class=\\\"switch\\\"&gt;&lt;input type=\\\"checkbox\\\" onchange=\\\"toggleCheckbox(this)\\\" id=\\\"4\\\" \" + outputState(4) + \"&gt;&lt;span class=\\\"slider\\\"&gt;&lt;\/span&gt;&lt;\/label&gt;\";\n    buttons += \"&lt;h4&gt;Output - GPIO 2&lt;\/h4&gt;&lt;label class=\\\"switch\\\"&gt;&lt;input type=\\\"checkbox\\\" onchange=\\\"toggleCheckbox(this)\\\" id=\\\"2\\\" \" + outputState(2) + \"&gt;&lt;span class=\\\"slider\\\"&gt;&lt;\/span&gt;&lt;\/label&gt;\";\n    return buttons;\n  }\n  return String();\n}<\/code><\/pre>\n\n\n\n<p>You can easily delete or add more lines to create more buttons.<\/p>\n\n\n\n<p>Let&#8217;s take a look at how the buttons are created. We create a String variable called <span class=\"rnthl rntliteral\">buttons<\/span> that contains the HTML text to build the buttons. We concatenate the HTML text with the current output state so that the toggle button is either gray or red. The current output state is returned by the <span class=\"rnthl rntliteral\">outputState(&lt;GPIO&gt;)<\/span> function (it accepts as argument the GPIO number). See below:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>buttons += \"&lt;h4&gt;Output - GPIO 2&lt;\/h4&gt;&lt;label class=\\\"switch\\\"&gt;&lt;input type=\\\"checkbox\\\" onchange=\\\"toggleCheckbox(this)\\\" id=\\\"2\\\" \" + outputState(2) + \"&gt;&lt;span class=\\\"slider\\\"&gt;&lt;\/span&gt;&lt;\/label&gt;\";<\/code><\/pre>\n\n\n\n<p>The \\ is used so that we can pass &#8220;&#8221; inside the String.<\/p>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">outputState()<\/span> function returns either <span class=\"rnthl rntliteral\">&#8220;checked&#8221;<\/span> if the GPIO is on or and empty field <span class=\"rnthl rntliteral\">&#8220;&#8221;<\/span> if the GPIO is off.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String outputState(int output){\n  if(digitalRead(output)){\n    return \"checked\";\n  }\n  else {\n    return \"\";\n  }\n}<\/code><\/pre>\n\n\n\n<p>So, the HTML text for GPIO 2 when it is on, would be:<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;h4&gt;Output - GPIO 2&lt;\/h4&gt;\n&lt;label class=\"switch\"&gt;\n&lt;input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"2\" checked&gt;&lt;span class=\"slider\"&gt;&lt;\/span&gt;\n&lt;\/label&gt;<\/code><\/pre>\n\n\n\n<p>Let\u2019s break this down into smaller sections to understand how it works.<\/p>\n\n\n\n<p>In HTML, a toggle switch is an input type. The <span style=\"color: #333399;\">&lt;input&gt;<\/span> tag specifies an input field where the user can enter data. The toggle switch is an input field of type <span class=\"rnthl rntliteral\">checkbox<\/span>. There are many other input field types.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;input type=\"checkbox\"&gt;<\/code><\/pre>\n\n\n\n<p>The checkbox can be checked or not. When it is check, you have something as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;input type=\"checkbox\" checked&gt;<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">onchange<\/span> is an event attribute that occurs when we change the value of the element (the checkbox). Whenever you check or uncheck the toggle switch, it calls the <span class=\"rnthl rntliteral\">toggleCheckbox()<\/span> JavaScript function for that specific element id (<span class=\"rnthl rntliteral\">this<\/span>).<\/p>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">id<\/span> specifies a unique id for that HTML element. The id allows us to manipulate the element using JavaScript or CSS.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"2\" checked&gt;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">setup()<\/h3>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span> initialize the Serial Monitor for debugging purposes.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.begin(115200);<\/code><\/pre>\n\n\n\n<p>Set the GPIOs you want to control as outputs using the <span class=\"rnthl rntliteral\">pinMode()<\/span> function and set them to LOW when the ESP8266 first starts. If you&#8217;ve added more GPIOs, do the same procedure.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>pinMode(2, OUTPUT);\npinMode(5, OUTPUT);\ndigitalWrite(5, LOW);\npinMode(4, OUTPUT);\ndigitalWrite(4, LOW);\npinMode(2, OUTPUT);\ndigitalWrite(2, LOW);<\/code><\/pre>\n\n\n\n<p>Connect to your local network and print the ESP8266 IP address.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>WiFi.begin(ssid, password);\nwhile (WiFi.status() != WL_CONNECTED) {\n  delay(1000);\n  Serial.println(\"Connecting to WiFi..\");\n}\n\n\/\/ Print ESP Local IP Address\nSerial.println(WiFi.localIP());<\/code><\/pre>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, you need to handle what happens when the ESP8266 receives requests. As we&#8217;ve seen previously, you receive a request of this type:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>&lt;ESP_IP&gt;\/update?output=&lt;inputMessage1&gt;&amp;state=&lt;inputMessage2&gt;<\/code><\/pre>\n\n\n\n<p>So, we check if the request contains the <span class=\"rnthl rntliteral\">PARAM_INPUT1<\/span> variable value (<span class=\"rnthl rntliteral\">output<\/span>) and the <span class=\"rnthl rntliteral\">PARAM_INPUT2<\/span>(<span class=\"rnthl rntliteral\">state<\/span>) and save the corresponding values on the <span class=\"rnthl rntliteral\">input1Message<\/span> and <span class=\"rnthl rntliteral\">input2Message<\/span> variables.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (request-&gt;hasParam(PARAM_INPUT_1) &amp;&amp; request-&gt;hasParam(PARAM_INPUT_2)) {\n  inputMessage1 = request-&gt;getParam(PARAM_INPUT_1)-&gt;value();\n  inputMessage2 = request-&gt;getParam(PARAM_INPUT_2)-&gt;value();<\/code><\/pre>\n\n\n\n<p>Then, we control the corresponding GPIO with the corresponding state (the <span class=\"rnthl rntliteral\">inputMessage1<\/span> variable saves the GPIO number and the <span class=\"rnthl rntliteral\">inputMessage2<\/span> saves the state &#8211; 0 or 1)<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>digitalWrite(inputMessage1.toInt(), inputMessage2.toInt());<\/code><\/pre>\n\n\n\n<p>Here&#8217;s the complete code to handle the HTTP GET <strong>\/update<\/strong> request:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.on(\"\/update\", HTTP_GET, &#091;] (AsyncWebServerRequest *request) {\n  String inputMessage1;\n  String inputMessage2;\n  \/\/ GET input1 value on &lt;ESP_IP&gt;\/update?output=&lt;inputMessage1&gt;&amp;state=&lt;inputMessage2&gt;\n  if (request-&gt;hasParam(PARAM_INPUT_1) &amp;&amp; request-&gt;hasParam(PARAM_INPUT_2)) {\n    inputMessage1 = request-&gt;getParam(PARAM_INPUT_1)-&gt;value();\n    inputMessage2 = request-&gt;getParam(PARAM_INPUT_2)-&gt;value();\n    digitalWrite(inputMessage1.toInt(), inputMessage2.toInt());\n  }\n  else {\n    inputMessage1 = \"No message sent\";\n    inputMessage2 = \"No message sent\";\n  }\n  Serial.print(\"GPIO: \");\n  Serial.print(inputMessage1);\n  Serial.print(\" - Set to: \");\n  Serial.println(inputMessage2);\n  request-&gt;send(200, \"text\/plain\", \"OK\");\n});<\/code><\/pre>\n\n\n\n<p>Finally, start the server:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.begin();<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Demonstration<\/h2>\n\n\n\n<p>After uploading the code to your ESP8266, open the Serial Monitor at a baud rate of 115200. Press the on-board RST\/EN button. You should get its IP address.<\/p>\n\n\n\n<p>Open a browser and type the ESP IP address. You&#8217;ll get access to a similar web 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=\"894\" height=\"573\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Web-Browser-Switch-Buttons-Serial-Monitor.png?resize=894%2C573&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU Async Web Server Web Browser Switch Buttons\" class=\"wp-image-99575\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Web-Browser-Switch-Buttons-Serial-Monitor.png?w=894&amp;quality=100&amp;strip=all&amp;ssl=1 894w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Web-Browser-Switch-Buttons-Serial-Monitor.png?resize=300%2C192&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Web-Browser-Switch-Buttons-Serial-Monitor.png?resize=768%2C492&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 894px) 100vw, 894px\" \/><\/figure><\/div>\n\n\n<p>Press the toggle buttons to control the ESP GPIOs. At the same time, you should get the following messages in the Serial Monitor to help you debug your code.<\/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=\"859\" height=\"423\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Arduino-IDE-Serial-Monitor.png?resize=859%2C423&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU Async Web Server Arduino IDE Serial Monitor\" class=\"wp-image-99572\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Arduino-IDE-Serial-Monitor.png?w=859&amp;quality=100&amp;strip=all&amp;ssl=1 859w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Arduino-IDE-Serial-Monitor.png?resize=300%2C148&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Arduino-IDE-Serial-Monitor.png?resize=768%2C378&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 859px) 100vw, 859px\" \/><\/figure><\/div>\n\n\n<p>You can also access the web server from a browser in your smartphone. Whenever you open the web server, it shows the current GPIO states. Red indicates the GPIO is on, and gray that the GPIO is off.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"543\" height=\"735\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Web-Browser-Switch-Buttons-Serial-Monitor-Mobile-Responsive.png?resize=543%2C735&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU Async Web Server Web Browser Switch Buttons Mobile Responsive\" class=\"wp-image-99576\" style=\"width:336px;height:454px\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Web-Browser-Switch-Buttons-Serial-Monitor-Mobile-Responsive.png?w=543&amp;quality=100&amp;strip=all&amp;ssl=1 543w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-Async-Web-Server-Web-Browser-Switch-Buttons-Serial-Monitor-Mobile-Responsive.png?resize=222%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 222w\" sizes=\"(max-width: 543px) 100vw, 543px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>In this tutorial you&#8217;ve learned how to create an asynchronous web server with the ESP8266 NodeMCU to control its outputs using toggle switches. Whenever you open the web page, it shows the updated GPIO states.<\/p>\n\n\n\n<p>We have other web server examples using the ESPAsyncWebServer library that you may like:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a style=\"font-size: inherit; background-color: initial;\" href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-web-server-outputs-momentary-switch\/\">ESP8266 Web Server: Control Outputs with Momentary Switch<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-web-server-timer-pulse\/\">ESP8266 Web Server: Control Outputs with Timer<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-web-server-physical-button\/\">ESP8266 Web Server: Control Outputs with a Physical Button<\/a><\/li>\n<\/ul>\n\n\n\n<p>We hope you found this tutorial useful. If you have any questions, post a comment below and we\u2019ll try to get back to you.<\/p>\n\n\n\n<p>If you like ESP8266, you might consider enrolling in our eBook &#8220;<a href=\"https:\/\/randomnerdtutorials.com\/home-automation-using-esp8266\/\">Home Automation using ESP8266<\/a>&#8220;. You can also access our free&nbsp;<a href=\"https:\/\/randomnerdtutorials.com\/projects-esp8266\/\">ESP8266 resources here<\/a>.<\/p>\n\n\n\n<p>Thank you for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial you&#8217;ll learn how to build an asynchronous web server with the ESP8266 NodeMCU board to control its outputs. The board will be programmed using Arduino IDE, and &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP8266 NodeMCU Async Web Server \u2013 Control Outputs with Arduino IDE (ESPAsyncWebServer library)\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-async-web-server-espasyncwebserver-library\/#more-99568\" aria-label=\"Read more about ESP8266 NodeMCU Async Web Server \u2013 Control Outputs with Arduino IDE (ESPAsyncWebServer library)\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":1,"featured_media":99577,"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":[265,214,246,300,240,264],"tags":[],"class_list":["post-99568","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp8266-project","category-esp8266","category-esp8266-arduino-ide","category-0-esp8266","category-esp8266-projects","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP8266-NodeMCU-ESPAsyncWebServer-library-control-outputs-web-server-Arduino.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\/99568","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\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=99568"}],"version-history":[{"count":1,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/99568\/revisions"}],"predecessor-version":[{"id":168066,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/99568\/revisions\/168066"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/99577"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=99568"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=99568"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=99568"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}