{"id":88264,"date":"2019-08-22T13:28:05","date_gmt":"2019-08-22T13:28:05","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=88264"},"modified":"2019-08-26T14:57:39","modified_gmt":"2019-08-26T14:57:39","slug":"esp8266-web-server-spiffs-nodemcu","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp8266-web-server-spiffs-nodemcu\/","title":{"rendered":"ESP8266 Web Server using SPIFFS (SPI Flash File System) &#8211; NodeMCU"},"content":{"rendered":"\n<p>This tutorial shows how to build a web server that serves HTML and CSS files stored on the ESP8266 NodeMCU filesystem (SPIFFS) using Arduino IDE. Instead of having to write the HTML and CSS text into the Arduino sketch, we\u2019ll create separate HTML and CSS files.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-SPIFFS-Web-Server-HTML-CSS-Files-outputs-sensor-readings.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 Web Server using SPIFFS (SPI Flash File System) HTML CSS files\" class=\"wp-image-88332\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-SPIFFS-Web-Server-HTML-CSS-Files-outputs-sensor-readings.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-SPIFFS-Web-Server-HTML-CSS-Files-outputs-sensor-readings.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-SPIFFS-Web-Server-HTML-CSS-Files-outputs-sensor-readings.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-SPIFFS-Web-Server-HTML-CSS-Files-outputs-sensor-readings.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n\n<p>The web server we&#8217;ll build shows how to control the ESP8266 outputs and how to display sensor readings. As an example, we&#8217;ll control an LED and display sensor readings from a BME280 sensor. <\/p>\n\n\n\n<p>You can use the concepts learned in this tutorial to control any output or display sensor readings from other sensors.<\/p>\n\n\n\n<p><strong>Recommended reading:<\/strong> <a href=\"https:\/\/randomnerdtutorials.com\/esp32-web-server-spiffs-spi-flash-file-system\/\">ESP32 Web Server using SPIFFS<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Project Overview<\/h2>\n\n\n\n<p>Before going straight to the project, it\u2019s important to outline what our web server will do, so that it&#8217;s easier to understand.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"356\" height=\"571\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-SPIFFS-Web-Server-HTML-CSS-Demonstration-smartphone.png?resize=356%2C571&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 Web Server using SPIFFS page HTML CSS Demonstration smartphone\" class=\"wp-image-88336\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-SPIFFS-Web-Server-HTML-CSS-Demonstration-smartphone.png?w=356&amp;quality=100&amp;strip=all&amp;ssl=1 356w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-SPIFFS-Web-Server-HTML-CSS-Demonstration-smartphone.png?resize=187%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 187w\" sizes=\"(max-width: 356px) 100vw, 356px\" \/><\/figure><\/div>\n\n\n\n<ul class=\"wp-block-list\"><li>The web server controls an LED connected to the ESP8266 GPIO 2. This is the ESP8266 on-board LED. You can control any other GPIO;<\/li><li>The web server page shows two buttons: ON and OFF \u2013 to turn GPIO 2 on and off;<\/li><li>The web server page also shows the current GPIO state;<\/li><li>You&#8217;ll also use a BME280 sensor to display sensor readings (temperature, humidity, and pressure).<\/li><\/ul>\n\n\n\n<p>The following figure shows a simplified diagram to demonstrate how everything works.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><a href=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-NodeMCU-SPIFFS-Web-Server-Project-Overview.png?quality=100&#038;strip=all&#038;ssl=1\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"1000\" height=\"506\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-NodeMCU-SPIFFS-Web-Server-Project-Overview.png?resize=1000%2C506&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU SPIFFS Web Server Project Overview\" class=\"wp-image-88354\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-NodeMCU-SPIFFS-Web-Server-Project-Overview.png?w=1000&amp;quality=100&amp;strip=all&amp;ssl=1 1000w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-NodeMCU-SPIFFS-Web-Server-Project-Overview.png?resize=300%2C152&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-NodeMCU-SPIFFS-Web-Server-Project-Overview.png?resize=768%2C389&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 1000px) 100vw, 1000px\" \/><\/a><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>Before proceeding with this project, make sure you check all the following prerequisites.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. Install ESP8266 Board in Arduino IDE<\/h3>\n\n\n\n<p>We&#8217;ll program the ESP8266 using Arduino IDE, so you must have the ESP8266 add-on installed. Follow the next tutorial to install it:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/how-to-install-esp8266-board-arduino-ide\/\">Install ESP8266 Board in Arduino IDE (Windows, Mac OS X, Linux)<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2. Filesystem Uploader Plugin<\/h3>\n\n\n\n<p>To upload files to the ESP8266 SPI Flash Filesystem (SPIFFS), we&#8217;ll use the Filesystem Uploader Plugin. Install the plugin in your Arduino IDE:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/install-esp8266-filesystem-uploader-arduino-ide\/\">Install ESP8266 Filesystem Uploader in Arduino IDE<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">3. Installing Libraries<\/h3>\n\n\n\n<p>One of the easiest ways to build a web server using files from the filesystem is using the <a rel=\"noreferrer noopener\" aria-label=\"ESPAsyncWebServer  (opens in a new tab)\" href=\"https:\/\/github.com\/me-no-dev\/ESPAsyncWebServer\" target=\"_blank\">ESPAsyncWebServer <\/a>library.&nbsp;<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Installing the ESPAsyncWebServer library<\/h4>\n\n\n\n<p>This library is not available to download through the Arduino IDE libraries manager. So, you need to follow the next steps to install the library:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><a rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\" href=\"https:\/\/github.com\/me-no-dev\/ESPAsyncWebServer\/archive\/master.zip\" target=\"_blank\">Click here to download&nbsp;the ESPAsyncWebServer library<\/a>. You should have a .zip folder in your Downloads folder<\/li><li>Unzip the .zip folder and you should get ESPAsyncWebServer-master folder<\/li><li>Rename your folder from&nbsp;<del>ESPAsyncWebServer-master<\/del>&nbsp;to ESPAsyncWebServer<\/li><li>Move the ESPAsyncWebServer&nbsp;folder to your Arduino IDE installation libraries folder<\/li><\/ol>\n\n\n\n<p>Alternatively, you can go to <strong>Sketch<\/strong> &gt; <strong>Include Library<\/strong> &gt; <strong>.zip Library<\/strong> and select the previously downloaded library. <\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Installing the&nbsp;ESPAsyncTCP<\/h4>\n\n\n\n<p>The ESPAsyncWebServer library also needs the <a rel=\"noreferrer noopener\" aria-label=\"ESPAsyncTCP library (opens in a new tab)\" href=\"https:\/\/github.com\/me-no-dev\/ESPAsyncTCP\" target=\"_blank\">ESPAsyncTCP library<\/a> to operate properly. Follow the next steps to install the ESPAsyncTCP library:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><a href=\"https:\/\/github.com\/me-no-dev\/ESPAsyncTCP\/archive\/master.zip\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">Click here to download&nbsp;the ESPAsyncTCP library<\/a>. You should have a .zip folder in your Downloads folder<\/li><li>Unzip the .zip folder and you should get ESPAsyncTCP-master folder<\/li><li>Rename your folder from&nbsp;<del>ESPAsyncTCP-master<\/del>&nbsp;to ESPAsyncTCP<\/li><li>Move the ESPAsyncTCP folder to your Arduino IDE installation libraries folder<\/li><li>Finally, re-open your Arduino IDE<\/li><\/ol>\n\n\n\n<p>Alternatively, you can go to <strong>Sketch<\/strong> &gt; <strong>Include Library<\/strong> &gt; <strong>.zip Library<\/strong> and select the previously downloaded library.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Installing BME280 libraries<\/h4>\n\n\n\n<p>In this tutorial, we&#8217;ll display readings from a BME280 sensor (<a href=\"https:\/\/randomnerdtutorials.com\/esp8266-bme280-arduino-ide\/\">Guide with ESP8266<\/a>). You need to install the following libraries:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a rel=\"noreferrer noopener\" aria-label=\"Adafruit_BME280_Library (opens in a new tab)\" href=\"https:\/\/github.com\/adafruit\/Adafruit_BME280_Library\" target=\"_blank\">Adafruit_BME280_Library<\/a><\/li><li><a rel=\"noreferrer noopener\" aria-label=\"Adafruit_Sensor (opens in a new tab)\" href=\"https:\/\/github.com\/adafruit\/Adafruit_Sensor\" target=\"_blank\">Adafruit_Sensor<\/a><\/li><\/ul>\n\n\n\n<p>You can install these libraries through the Arduino IDE Libraries Manager. Go to <strong>Sketch <\/strong>&gt; <strong>Include Libraries<\/strong> &gt; <strong>Manage Libraries<\/strong>. Then, search for the libraries&#8217; name to install them.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Parts Required<\/h2>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"421\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-SPIFFS-Web-Server-HTML-CSS-Files.jpg?resize=750%2C421&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU BME280 Temperature Humidity Pressure Sensor LED Circuit\" class=\"wp-image-88331\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-SPIFFS-Web-Server-HTML-CSS-Files.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-SPIFFS-Web-Server-HTML-CSS-Files.jpg?resize=300%2C168&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<p>To proceed with this project, you need the following parts:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/tools\/esp8266-esp-12e-nodemcu-wi-fi-development-board\/\" target=\"_blank\">ESP8266<\/a> (read&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/best-esp8266-wi-fi-development-board\/\" target=\"_blank\">Best ESP8266 development boards<\/a>)<\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/tools\/bme280-sensor-module\/\" target=\"_blank\">BME280 sensor module<\/a> (<a href=\"https:\/\/randomnerdtutorials.com\/esp8266-bme280-arduino-ide\/\">Guide for BME280<\/a>)<\/li><li><a rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\" href=\"https:\/\/makeradvisor.com\/tools\/3mm-5mm-leds-kit-storage-box\/\" target=\"_blank\">5 mm LED<\/a><\/li><li><a rel=\"noreferrer noopener\" aria-label=\"330 Ohm resistor\u2028 (opens in a new tab)\" href=\"https:\/\/makeradvisor.com\/tools\/resistors-kits\/\" target=\"_blank\">330 Ohm resistor<\/a><\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\">Breadboard<\/a><\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\">Jumper wires<\/a> <\/li><\/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 Diagram<\/h2>\n\n\n\n<p>Connect all the components by following the next schematic diagram.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-BME280-LED.png?resize=563%2C753&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU BME280 LED Wiring Schematic Diagram\" class=\"wp-image-88311\" width=\"563\" height=\"753\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-BME280-LED.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-BME280-LED.png?resize=224%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 224w\" sizes=\"(max-width: 563px) 100vw, 563px\" \/><\/figure><\/div>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td><strong>BME280<\/strong><\/td><td><strong>ESP8266<\/strong><\/td><\/tr><tr><td>Vin<\/td><td><span class=\"rnthl rntcred\">3.3V<\/span><\/td><\/tr><tr><td>GND<\/td><td><span class=\"rnthl rntcblack\">GND<\/span><\/td><\/tr><tr><td>SCL<\/td><td><span class=\"rnthl rntcgreen\">GPIO 5<\/span><\/td><\/tr><tr><td>SDA<\/td><td><span class=\"rnthl rntclblue\">GPIO 4<\/span><\/td><\/tr><\/tbody><\/table>\n\n\n\n<h2 class=\"wp-block-heading\">Organizing Your Files<\/h2>\n\n\n\n<p>To build the web server you need three different files. The Arduino sketch, the HTML file and the CSS file. The HTML and CSS files should be saved inside a folder called&nbsp;<strong>data<\/strong>&nbsp;inside the Arduino sketch folder, as shown below: <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"410\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-SPIFFS-Web-Server-Organizing-Files.png?resize=750%2C410&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU SPIFFS Web Server Files Directories\" class=\"wp-image-88266\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-SPIFFS-Web-Server-Organizing-Files.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-SPIFFS-Web-Server-Organizing-Files.png?resize=300%2C164&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Creating the HTML File<\/h2>\n\n\n\n<p>Create an&nbsp;<em>index.html<\/em>&nbsp;file with the following content or&nbsp;<a rel=\"noreferrer noopener\" aria-label=\"download all the project files her (opens in a new tab)\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP8266\/ESP8266_SPIFFS\/ESP8266_SPIFFS.zip\" target=\"_blank\">download all project files here<\/a>: <\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-html\">&lt;!DOCTYPE html&gt;\n&lt;!-- \n  Rui Santos\n  Complete project details at https:\/\/RandomNerdTutorials.com  \n--&gt;\n&lt;html&gt;\n&lt;head&gt;\n  &lt;title&gt;ESP8266 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;link rel=&quot;stylesheet&quot; type=&quot;text\/css&quot; href=&quot;style.css&quot;&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n  &lt;h1&gt;ESP8266 Web Server&lt;\/h1&gt;\n  &lt;p&gt;GPIO state&lt;strong&gt; %STATE%&lt;\/strong&gt;&lt;\/p&gt;\n  &lt;p&gt;\n    &lt;a href=&quot;\/on&quot;&gt;&lt;button class=&quot;button&quot;&gt;ON&lt;\/button&gt;&lt;\/a&gt;\n    &lt;a href=&quot;\/off&quot;&gt;&lt;button class=&quot;button button2&quot;&gt;OFF&lt;\/button&gt;&lt;\/a&gt;\n  &lt;\/p&gt;\n  &lt;p&gt;\n    &lt;span class=&quot;sensor-labels&quot;&gt;Temperature&lt;\/span&gt;\n    &lt;span id=&quot;temperature&quot;&gt;%TEMPERATURE%&lt;\/span&gt;\n    &lt;sup class=&quot;units&quot;&gt;&amp;deg;C&lt;\/sup&gt;\n  &lt;\/p&gt;\n  &lt;p&gt;\n    &lt;span class=&quot;sensor-labels&quot;&gt;Humidity&lt;\/span&gt;\n    &lt;span id=&quot;humidity&quot;&gt;%HUMIDITY%&lt;\/span&gt;\n    &lt;sup class=&quot;units&quot;&gt;&amp;#37;&lt;\/sup&gt;\n  &lt;\/p&gt;\n  &lt;p&gt;\n    &lt;span class=&quot;sensor-labels&quot;&gt;Pressure&lt;\/span&gt;\n    &lt;span id=&quot;pressure&quot;&gt;%PRESSURE%&lt;\/span&gt;\n    &lt;sup class=&quot;units&quot;&gt;hPa&lt;\/sup&gt;\n  &lt;\/p&gt;\n&lt;\/body&gt;\n&lt;script&gt;\n  setInterval(function ( ) {\n    var xhttp = new XMLHttpRequest();\n    xhttp.onreadystatechange = function() {\n      if (this.readyState == 4 &amp;&amp; this.status == 200) {\n        document.getElementById(&quot;temperature&quot;).innerHTML = this.responseText;\n      }\n    };\n    xhttp.open(&quot;GET&quot;, &quot;\/temperature&quot;, true);\n    xhttp.send();\n  }, 10000 ) ;\n\n  setInterval(function ( ) {\n    var xhttp = new XMLHttpRequest();\n    xhttp.onreadystatechange = function() {\n      if (this.readyState == 4 &amp;&amp; this.status == 200) {\n        document.getElementById(&quot;humidity&quot;).innerHTML = this.responseText;\n      }\n    };\n    xhttp.open(&quot;GET&quot;, &quot;\/humidity&quot;, true);\n    xhttp.send();\n  }, 10000 ) ;\n\n  setInterval(function ( ) {\n    var xhttp = new XMLHttpRequest();\n    xhttp.onreadystatechange = function() {\n      if (this.readyState == 4 &amp;&amp; this.status == 200) {\n        document.getElementById(&quot;pressure&quot;).innerHTML = this.responseText;\n      }\n    };\n    xhttp.open(&quot;GET&quot;, &quot;\/pressure&quot;, true);\n    xhttp.send();\n  }, 10000 ) ;\n&lt;\/script&gt;\n&lt;\/html&gt;\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\/ESP8266_SPIFFS\/data\/index.html\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>Because we\u2019re using CSS and HTML in different files, we need to reference the CSS file on the HTML text.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;link rel=\"stylesheet\" type=\"text\/css\" href=\"style.css\"><\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">&lt;link&gt;<\/span> tag tells the HTML file that you\u2019re using an external style sheet to format how the page looks. The <span class=\"rnthl rntliteral\">rel<\/span> attribute specifies the nature of the external file, in this case that it is a stylesheet\u2014the CSS file\u2014that will be used to alter the appearance of the page.<\/p>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">type<\/span> attribute is set to <span class=\"rnthl rntliteral\">\u201ctext\/css\u201d<\/span> to indicate that you\u2019re using a CSS file for the styles. The <span class=\"rnthl rntliteral\">href<\/span> attribute indicates the file location; since both the CSS and HTML files will be in the same folder, you just need to reference the filename: <em>style.css<\/em>.<\/p>\n\n\n\n<p>In the following line, we write the first heading of our web page. In this case we have \u201cESP8266 Web Server\u201d. You can change the heading to any text:<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;h1>ESP8266 Web Server&lt;\/h1><\/code><\/pre>\n\n\n\n<p>Then, add a paragraph with the text \u201cGPIO state: \u201d followed by the GPIO state. Because the GPIO state changes accordingly to the state of the GPIO, we can add a placeholder that will then be replaced for whatever value we set on the Arduino sketch.<\/p>\n\n\n\n<p>To add placeholder use <strong>%<\/strong> signs. To create a placeholder for the state, you can use <span class=\"rnthl rntliteral\">%STATE%<\/span>, for example.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;p>GPIO state&lt;strong> %STATE%&lt;\/strong>&lt;\/p><\/code><\/pre>\n\n\n\n<p>You attribute a value to the STATE placeholder in the Arduino sketch.<\/p>\n\n\n\n<p>Then, create an ON and an OFF buttons. When you click the on button, we redirect the web page to to root followed by <span class=\"rnthl rntliteral\">\/on<\/span> url. When you click the off button you are redirected to the <span class=\"rnthl rntliteral\">\/off<\/span> url.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;a href=\"\/on\">&lt;button class=\"button\">ON&lt;\/button>&lt;\/a>\n&lt;a href=\"\/off\">&lt;button class=\"button button2\">OFF&lt;\/button>&lt;\/a><\/code><\/pre>\n\n\n\n<p>Finally, create three paragraphs to display the temperature, humidity and pressure.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;p>\n  &lt;span class=\"sensor-labels\">Temperature&lt;\/span>\n  &lt;span id=\"temperature\">%TEMPERATURE%&lt;\/span>\n  &lt;sup class=\"units\">\u00b0C&lt;\/sup>\n&lt;\/p>\n&lt;p>\n  &lt;span class=\"sensor-labels\">Pressure&lt;\/span>\n  &lt;span id=\"pressure\">%PRESSURE%&lt;\/span>\n  &lt;sup class=\"units\">hPa&lt;\/sup>\n&lt;\/p>\n&lt;p>\n  &lt;span class=\"sensor-labels\">Humidity&lt;\/span>\n  &lt;span id=\"humidity\">%HUMIDITY%&lt;\/span>\n  &lt;sup class=\"units\">%&lt;\/sup>\n&lt;\/p><\/code><\/pre>\n\n\n\n<p>We use the <span class=\"rnthl rntliteral\">%TEMPERATURE%<\/span>, <span class=\"rnthl rntliteral\">%HUMIDITY%<\/span> and <span class=\"rnthl rntliteral\">%PRESSURE%<\/span> placeholders. These will then be replaced by the actual temperature readings in the Arduino sketch. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Automatic Updates<\/h3>\n\n\n\n<p>We also add a bit of JavaScript in our HTML file that is responsible for updating the temperature readings without the need to refresh the web page. <\/p>\n\n\n\n<p>The following snipet of code is responsible for the temperature.<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>setInterval(function ( ) {\n  var xhttp = new XMLHttpRequest();\n  xhttp.onreadystatechange = function() {\n    if (this.readyState == 4 &amp;&amp; this.status == 200) {\n      document.getElementById(\"temperature\").innerHTML = this.responseText;\n    }\n  };\n  xhttp.open(\"GET\", \"\/temperature\", true);\n  xhttp.send();\n}, 10000 ) ;<\/code><\/pre>\n\n\n\n<p>To update the temperature, we have a <span class=\"rnthl rntliteral\">setInterval()<\/span> function that runs every 10 seconds.<\/p>\n\n\n\n<p>Basically, it makes a request in the <span class=\"rnthl rntliteral\"><em>\/temperature<\/em><\/span> URL to get the latest temperature reading.<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>  xhttp.open(\"GET\", \"\/temperature\", true);\n  xhttp.send();\n}, 10000 ) ;<\/code><\/pre>\n\n\n\n<p>When it receives that value, it updates the HTML element with <span class=\"rnthl rntliteral\">temperature<\/span> id.<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>if (this.readyState == 4 &amp;&amp; this.status == 200) {\n  document.getElementById(\"temperature\").innerHTML = this.responseText;\n}<\/code><\/pre>\n\n\n\n<p>In summary, this previous section is responsible for updating the temperature asynchronously. The same process is repeated for the humidity and pressure readings.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating the CSS File<\/h2>\n\n\n\n<p>Create the<em>&nbsp;style.css <\/em>file&nbsp;with the following content or&nbsp;<a rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP8266\/ESP8266_SPIFFS\/ESP8266_SPIFFS.zip\" target=\"_blank\">download all project files here<\/a>: <\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-css\">\/***\n   Rui Santos\n   Complete project details at https:\/\/RandomNerdTutorials.com\n***\/\n\nhtml {\n  font-family: Arial;\n  display: inline-block;\n  margin: 0px auto;\n  text-align: center;\n}\nh1 {\n  color: #0F3376;\n  padding: 2vh;\n}\np {\n  font-size: 1.5rem;\n}\n.button {\n  display: inline-block;\n  background-color: #008CBA;\n  border: none;\n  border-radius: 4px;\n  color: white;\n  padding: 16px 40px;\n  text-decoration: none;\n  font-size: 30px;\n  margin: 2px;\n  cursor: pointer;\n}\n.button2 {\n  background-color: #f44336;\n}\n.units {\n  font-size: 1.2rem;\n }\n.sensor-labels {\n  font-size: 1.5rem;\n  vertical-align:middle;\n  padding-bottom: 15px;\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\/ESP8266_SPIFFS\/data\/style.css\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>This is just a basic CSS file to set the font size, style and color of the buttons and align the page. We won\u2019t explain how CSS works. A good place to learn about CSS is the&nbsp;<a rel=\"noreferrer noopener nofollow\" href=\"https:\/\/www.w3schools.com\/css\/default.asp\" target=\"_blank\">W3Schools website<\/a>. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">ESP8266 Asynchronous Web Server Sketch<\/h2>\n\n\n\n<p>Copy the following code to the Arduino IDE or&nbsp;<strong><a href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP8266\/ESP8266_SPIFFS\/ESP8266_SPIFFS.zip\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">download all project files here<\/a><\/strong>. Then, you need to type your network credentials (SSID and password) to connect the ESP8266 to your local network.<\/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\n  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.\n  The above copyright notice and this permission notice shall be included in all 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#include &lt;FS.h&gt;\n#include &lt;Wire.h&gt;\n#include &lt;Adafruit_Sensor.h&gt;\n#include &lt;Adafruit_BME280.h&gt;\n\nAdafruit_BME280 bme; \/\/ I2C\n\/\/Adafruit_BME280 bme(BME_CS); \/\/ hardware SPI\n\/\/Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); \/\/ software SPI\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\n\/\/ Set LED GPIO\nconst int ledPin = 2;\n\/\/ Stores LED state\nString ledState;\n\n\/\/ Create AsyncWebServer object on port 80\nAsyncWebServer server(80);\n\nString getTemperature() {\n  float temperature = bme.readTemperature();\n  \/\/ Read temperature as Fahrenheit (isFahrenheit = true)\n  \/\/float temperature = 1.8 * bme.readTemperature() + 32;\n  Serial.println(temperature);\n  return String(temperature);\n}\n  \nString getHumidity() {\n  float humidity = bme.readHumidity();\n  Serial.println(humidity);\n  return String(humidity);\n}\n\nString getPressure() {\n  float pressure = bme.readPressure()\/ 100.0F;\n  Serial.println(pressure);\n  return String(pressure);\n}\n\n\/\/ Replaces placeholder with LED state value\nString processor(const String&amp; var){\n  Serial.println(var);\n  if(var == &quot;STATE&quot;){\n    if(digitalRead(ledPin)){\n      ledState = &quot;ON&quot;;\n    }\n    else{\n      ledState = &quot;OFF&quot;;\n    }\n    Serial.print(ledState);\n    return ledState;\n  }\n  else if (var == &quot;TEMPERATURE&quot;){\n    return getTemperature();\n  }\n  else if (var == &quot;HUMIDITY&quot;){\n    return getHumidity();\n  }\n  else if (var == &quot;PRESSURE&quot;){\n    return getPressure();\n  }\n  return String();\n}\n \nvoid setup(){\n  \/\/ Serial port for debugging purposes\n  Serial.begin(115200);\n  pinMode(ledPin, OUTPUT);\n\n  \/\/ Initialize the sensor\n  if (!bme.begin(0x76)) {\n    Serial.println(&quot;Could not find a valid BME280 sensor, check wiring!&quot;);\n    while (1);\n  }\n\n  \/\/ Initialize SPIFFS\n  if(!SPIFFS.begin()){\n    Serial.println(&quot;An Error has occurred while mounting SPIFFS&quot;);\n    return;\n  }\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 ESP32 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(SPIFFS, &quot;\/index.html&quot;, String(), false, processor);\n  });\n  \n  \/\/ Route to load style.css file\n  server.on(&quot;\/style.css&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\n    request-&gt;send(SPIFFS, &quot;\/style.css&quot;, &quot;text\/css&quot;);\n  });\n\n  \/\/ Route to set GPIO to HIGH\n  server.on(&quot;\/on&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\n    digitalWrite(ledPin, HIGH);    \n    request-&gt;send(SPIFFS, &quot;\/index.html&quot;, String(), false, processor);\n  });\n  \n  \/\/ Route to set GPIO to LOW\n  server.on(&quot;\/off&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\n    digitalWrite(ledPin, LOW);    \n    request-&gt;send(SPIFFS, &quot;\/index.html&quot;, String(), false, processor);\n  });\n\n  server.on(&quot;\/temperature&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\n    request-&gt;send(200, &quot;text\/plain&quot;, getTemperature().c_str());\n  });\n  \n  server.on(&quot;\/humidity&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\n    request-&gt;send(200, &quot;text\/plain&quot;, getHumidity().c_str());\n  });\n  \n  server.on(&quot;\/pressure&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\n    request-&gt;send(200, &quot;text\/plain&quot;, getPressure().c_str());\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\/ESP8266_SPIFFS\/ESP8266_SPIFFS.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>Continue reading to learn how the code works, or skip to the next section.<\/p>\n\n\n\n<p>First, include the necessary libraries:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;ESP8266WiFi.h>\n#include &lt;ESPAsyncTCP.h>\n#include &lt;ESPAsyncWebServer.h>\n#include &lt;FS.h>\n#include &lt;Wire.h>\n#include &lt;Adafruit_Sensor.h>\n#include &lt;Adafruit_BME280.h><\/code><\/pre>\n\n\n\n<p>You need to type your network credentials in the following variables:<\/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<p>Create an instance that refers to the BME280 sensor called <span class=\"rnthl rntliteral\">bme<\/span>:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Adafruit_BME280 bme; \/\/ I2C<\/code><\/pre>\n\n\n\n<p>Next, create a variable that refers to GPIO 2 called <span class=\"rnthl rntliteral\">ledPin<\/span>, and a String variable to hold the led state: <span class=\"rnthl rntliteral\">ledState<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const int ledPin = 2;\nString ledState;<\/code><\/pre>\n\n\n\n<p>Create an <span class=\"rnthl rntliteral\">AsynWebServer<\/span> object called <span class=\"rnthl rntliteral\">server<\/span> that is listening 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<h4 class=\"wp-block-heading\">Get Sensor Readings<\/h4>\n\n\n\n<p>We create three functions to return the sensor readings as strings: the <span class=\"rnthl rntliteral\">getTemperature()<\/span>, <span class=\"rnthl rntliteral\">getHumidity()<\/span> and <span class=\"rnthl rntliteral\">getPressure()<\/span> functions.<\/p>\n\n\n\n<p>Here&#8217;s how the <span class=\"rnthl rntliteral\">getTemperature()<\/span> function looks like (the other functions are similar).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String getTemperature() {\n  float temperature = bme.readTemperature();\n  \/\/ Read temperature as Fahrenheit (isFahrenheit = true)\n  \/\/float temperature = 1.8 * bme.readTemperature() + 32;\n  Serial.println(temperature);\n  return String(temperature);\n}<\/code><\/pre>\n\n\n\n<p>If you want to display temperature in Fahrenheit degrees, you just need to uncomment the corresponding line in the <span class=\"rnthl rntliteral\">getTemperature()<\/span> function:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>float temperature = 1.8 * bme.readTemperature() + 32;<\/code><\/pre>\n\n\n\n<p>To learn more about interfacing the BME280 sensor with the ESP8266, you can read the following tutorial:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/esp8266-bme280-arduino-ide\/\">ESP8266 with BME280 using Arduino IDE (Pressure, Temperature, Humidity)<\/a><\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">processor()<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">processor()<\/span> function attributes a value to the placeholders we\u2019ve created on the HTML file. It accepts as argument the placeholder and should return a String that will replace the placeholder. The <span class=\"rnthl rntliteral\">processor()<\/span> function should have the following structure:<\/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 == \"STATE\"){\n    if(digitalRead(ledPin)){\n      ledState = \"ON\";\n    }\n    else{\n      ledState = \"OFF\";\n    }\n    Serial.print(ledState);\n    return ledState;\n  }\n  else if (var == \"TEMPERATURE\"){\n    return getTemperature();\n  }\n  else if (var == \"HUMIDITY\"){\n    return getHumidity();\n  }\n  else if (var == \"PRESSURE\"){\n    return getPressure();\n  }\n}<\/code><\/pre>\n\n\n\n<p>This function first checks if the placeholder is the <span class=\"rnthl rntliteral\">STATE<\/span> we\u2019ve created on the HTML file.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if(var == \"STATE\"){<\/code><\/pre>\n\n\n\n<p>If it is, then, accordingly to the LED state, we set the <span class=\"rnthl rntliteral\">ledState<\/span> variable to either ON or OFF.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if(digitalRead(ledPin)){\n  ledState = \"ON\";\n}\nelse{\n  ledState = \"OFF\";\n}<\/code><\/pre>\n\n\n\n<p>Finally, we return the <span class=\"rnthl rntliteral\">ledState<\/span> variable. This replaces the <span class=\"rnthl rntliteral\">STATE<\/span> placeholder with the <span class=\"rnthl rntliteral\">ledState<\/span> string value.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>return ledState;<\/code><\/pre>\n\n\n\n<p>If it finds the <span class=\"rnthl rntliteral\"><strong>%TEMPERATURE%<\/strong><\/span> placeholder, we return the temperature by calling the <span class=\"rnthl rntliteral\">getTemperature()<\/span> function created previously. <\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>else if (var == \"TEMPERATURE\"){\n  return getTemperature();\n}<\/code><\/pre>\n\n\n\n<p>The same happens for the <span class=\"rnthl rntliteral\">%HUMIDITY%<\/span> and <span class=\"rnthl rntliteral\">%PRESSURE%<\/span> placeholders by calling the corresponding functions:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>else if (var == \"TEMPERATURE\"){\n  return getTemperature();\n}\nelse if (var == \"HUMIDITY\"){\n  return getHumidity();\n}\nelse if (var == \"PRESSURE\"){\n  return getPressure();\n}  <\/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 by initializing the Serial Monitor and setting the GPIO as an output.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.begin(115200);\npinMode(ledPin, OUTPUT);<\/code><\/pre>\n\n\n\n<p>Initialize the BME280 sensor:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (!bme.begin(0x76)) {\n  Serial.println(\"Could not find a valid BME280 sensor, check wiring!\");\n  while (1);\n}<\/code><\/pre>\n\n\n\n<p>Initialize SPIFFS:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if(!SPIFFS.begin()){\n  Serial.println(\"An Error has occurred while mounting SPIFFS\");\n  return;\n}<\/code><\/pre>\n\n\n\n<p><strong>Wi-Fi connection<\/strong><\/p>\n\n\n\n<p>Connect to Wi-Fi and print the ESP8266 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}\nSerial.println(WiFi.localIP());<\/code><\/pre>\n\n\n\n<p><strong>Async Web Server<\/strong><\/p>\n\n\n\n<p>The ESPAsyncWebServer library allows us to configure the routes where the server will be listening for incoming HTTP requests and execute functions when a request is received on that route. For that, use the <span class=\"rnthl rntliteral\">on<\/span> method on the <span class=\"rnthl rntliteral\">server<\/span> object as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.on(\"\/\", HTTP_GET, [](AsyncWebServerRequest *request){\n  request->send(SPIFFS, \"\/index.html\", String(), false, processor);\n});<\/code><\/pre>\n\n\n\n<p>When the server receives a request on the root \u201c<strong>\/<\/strong>\u201d URL, it will send the&nbsp;<em>index.html<\/em>file to the client. The last argument of the&nbsp;<span class=\"rnthl rntliteral\">send()<\/span>&nbsp;function is the processor, so that we can replace the placeholder with the value we want \u2013 in this case the <span class=\"rnthl rntliteral\">ledState<\/span>.<\/p>\n\n\n\n<p>Because we\u2019ve referenced the CSS file on the HTML file, the client will make a request for the CSS file. When that happens, the CSS file is sent to the client:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.on(\"\/style.css\", HTTP_GET, [](AsyncWebServerRequest *request){\n  request->send(SPIFFS, \"\/style.css\",\"text\/css\");\n});<\/code><\/pre>\n\n\n\n<p>You also need to define what happens on the&nbsp;<span class=\"rnthl rntliteral\">\/on<\/span>&nbsp;and&nbsp;<span class=\"rnthl rntliteral\">\/off<\/span>&nbsp;routes. When a request is made on those routes, the LED is either turned on or off, and the ESP32 serves the HTML file.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.on(\"\/on\", HTTP_GET, [](AsyncWebServerRequest *request){\n  digitalWrite(ledPin, HIGH);\n  request->send(SPIFFS, \"\/index.html\", String(),false, processor);\n});\nserver.on(\"\/off\", HTTP_GET, [](AsyncWebServerRequest *request){\n  digitalWrite(ledPin, LOW);\n  request->send(SPIFFS, \"\/index.html\", String(),false, processor);\n});<\/code><\/pre>\n\n\n\n<p>In the HTML file, we&#8217;ve written a JavaScript code that requests the temperature, humidity and pressure on the <span class=\"rnthl rntliteral\">\/temperature<\/span>, <span class=\"rnthl rntliteral\">\/humidity<\/span>, <span class=\"rnthl rntliteral\">\/pressure<\/span> routes, respectively, every 10 seconds. So, we also need to handle what happens when we receive a request on those routes.<\/p>\n\n\n\n<p>We simply need to send the updated sensor readings. The updated sensor readings are returned by the <span class=\"rnthl rntliteral\">getTemperature()<\/span>, <span class=\"rnthl rntliteral\">getHumidity()<\/span> and <span class=\"rnthl rntliteral\">getPressure()<\/span> functions we&#8217;ve created previously.<\/p>\n\n\n\n<p>The readings are plain text, and should be sent as a char, so, we use the <span class=\"rnthl rntliteral\">c_str()<\/span> method.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.on(\"\/temperature\", HTTP_GET, [](AsyncWebServerRequest *request){\n  request->send_P(200, \"text\/plain\", getTemperature().c_str());\n});\n  \nserver.on(\"\/humidity\", HTTP_GET, [](AsyncWebServerRequest *request){\n  request->send_P(200, \"text\/plain\", getHumidity().c_str());\n});\n  \nserver.on(\"\/pressure\", HTTP_GET, [](AsyncWebServerRequest *request){\n  request->send_P(200, \"text\/plain\", getPressure().c_str());\n});<\/code><\/pre>\n\n\n\n<p>In the end, we use the <span class=\"rnthl rntliteral\">begin()<\/span> method on the <span class=\"rnthl rntliteral\">server<\/span> object, so that the server starts listening for incoming clients.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.begin();<\/code><\/pre>\n\n\n\n<p>Because this is an asynchronous web server, you can define all the requests in the <span class=\"rnthl rntliteral\">setup()<\/span>. Then, you can add other code to the <span class=\"rnthl rntliteral\">loop()<\/span> while the server is listening for incoming clients.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Uploading Code and Files<\/h2>\n\n\n\n<p>Save the Arduino sketch as <em>ESP8266_SPIFFS_Web_Server<\/em> or <a rel=\"noreferrer noopener\" aria-label=\"download all project files here (opens in a new tab)\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP8266\/ESP8266_SPIFFS\/ESP8266_SPIFFS.zip\" target=\"_blank\">download all project files here<\/a>.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Go to <strong>Sketch<\/strong> &gt; <strong>Show Sketch folder<\/strong>, and create a folder called <strong>data<\/strong>. Save the HTML and CSS files inside that folder;<\/li><li>In <strong>Tools <\/strong>&gt; <strong>Board<\/strong>, select the ESP8266 board you&#8217;re using;<\/li><li>Then, go to <strong>Tools <\/strong>&gt; <strong>Flash size<\/strong> and select <strong>4M (1M SPIFFS)<\/strong>.<\/li><\/ul>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"609\" height=\"585\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/seleccionar-flash-size.png?resize=609%2C585&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Select ESP8266 NodeMCU board with SPIFFS Arduino IDE\" class=\"wp-image-88305\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/seleccionar-flash-size.png?w=609&amp;quality=100&amp;strip=all&amp;ssl=1 609w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/seleccionar-flash-size.png?resize=300%2C288&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 609px) 100vw, 609px\" \/><\/figure><\/div>\n\n\n\n<p>Finally, upload the files to your board. Go to <strong>Tools<\/strong> &gt; <strong>ESP8266 Data Sketch Upload<\/strong> and wait for the files to be uploaded.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"385\" height=\"582\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP8266-Sketch-Data-Upload-Arduino-IDE-SPIFFS-FS-Filesystem.png?resize=385%2C582&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Upload Files to ESP8266 NodeMCU SPIFFS ESP8266 Sketch Data Upload\" class=\"wp-image-86807\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP8266-Sketch-Data-Upload-Arduino-IDE-SPIFFS-FS-Filesystem.png?w=385&amp;quality=100&amp;strip=all&amp;ssl=1 385w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP8266-Sketch-Data-Upload-Arduino-IDE-SPIFFS-FS-Filesystem.png?resize=198%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 198w\" sizes=\"(max-width: 385px) 100vw, 385px\" \/><\/figure><\/div>\n\n\n\n<p>Then, press the Arduino IDE upload button to upload the code to the ESP8266.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"34\" height=\"29\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2016\/12\/arduino-ide-upload-button.png?resize=34%2C29&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Upload Code Arduino IDE to ESP8266 NodeMCU\" class=\"wp-image-65439\"\/><\/figure><\/div>\n\n\n\n<p>When everything is successfully uploaded, open the Serial Monitor at a baud rate of 115200. Press the ESP8266 on-board RST button, and it should print the ESP8266 IP address.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"692\" height=\"272\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-IP-address.png?resize=692%2C272&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU IP address Serial Monitor Arduino IDE\" class=\"wp-image-88308\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-IP-address.png?w=692&amp;quality=100&amp;strip=all&amp;ssl=1 692w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-IP-address.png?resize=300%2C118&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 692px) 100vw, 692px\" \/><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Demonstration<\/h2>\n\n\n\n<p>Open a browser and type your ESP8266 IP address. The following web page should load.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"421\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-SPIFFS-Web-Server-HTML-CSS-Demonstration.jpg?resize=750%2C421&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 Web Server using SPIFFS page HTML CSS Demonstration\" class=\"wp-image-88334\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-SPIFFS-Web-Server-HTML-CSS-Demonstration.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-SPIFFS-Web-Server-HTML-CSS-Demonstration.jpg?resize=300%2C168&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<p>Press the ON and OFF buttons to control the ESP8266 on-board LED. You can also visualize the latest sensor readings. The sensor readings are updated automatically without the need to refresh the web page.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>Using the ESP8266 SPI Flash File System (SPIFFS) is specially useful to store HTML and CSS files to serve to a client \u2013 instead of having to write all the code in the Arduino sketch. <\/p>\n\n\n\n<p>We have other related projects that you may like:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-web-server-spiffs-spi-flash-file-system\/\">ESP32 Web Server using SPIFFS<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/esp8266-dht11dht22-temperature-and-humidity-web-server-with-arduino-ide\/\">ESP8266 DHT Temperature and Humidity Web Server<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/hack-pir-motion-sensor-esp8266-hlk-pm03\/\">Hack a PIR Motion Sensor with an ESP8266<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/esp8266-wi-fi-button-diy-amazon-dash-button-clone\/\">ESP8266 Wi-Fi Button \u2013 DIY Amazon Dash Button Clone<\/a><\/li><\/ul>\n\n\n\n<p>Learn more about the ESP8266:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/home-automation-using-esp8266\/\">Home Automation using ESP8266<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/micropython-programming-with-esp32-and-esp8266\/\">MicroPython Programming with ESP32 and ESP8266<\/a><\/li><li><a rel=\"noreferrer noopener\" aria-label=\"Free ESP8266 Projects and Tutorials (opens in a new tab)\" href=\"https:\/\/randomnerdtutorials.com\/projects-esp8266\/\" target=\"_blank\">Free ESP8266 Projects and Tutorials<\/a><\/li><\/ul>\n\n\n\n<p>Thanks for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to build a web server that serves HTML and CSS files stored on the ESP8266 NodeMCU filesystem (SPIFFS) using Arduino IDE. Instead of having to write &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP8266 Web Server using SPIFFS (SPI Flash File System) &#8211; NodeMCU\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp8266-web-server-spiffs-nodemcu\/#more-88264\" aria-label=\"Read more about ESP8266 Web Server using SPIFFS (SPI Flash File System) &#8211; NodeMCU\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":88332,"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-88264","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\/2019\/08\/ESP8266-SPIFFS-Web-Server-HTML-CSS-Files-outputs-sensor-readings.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\/88264","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=88264"}],"version-history":[{"count":0,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/88264\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/88332"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=88264"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=88264"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=88264"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}