{"id":101731,"date":"2021-03-16T15:37:54","date_gmt":"2021-03-16T15:37:54","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=101731"},"modified":"2024-06-14T16:47:28","modified_gmt":"2024-06-14T16:47:28","slug":"esp32-ota-over-the-air-vs-code","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-ota-over-the-air-vs-code\/","title":{"rendered":"ESP32 OTA (Over-the-Air) Updates &#8211; AsyncElegantOTA (VS Code + PlatformIO)"},"content":{"rendered":"\n<p>In this guide, you&#8217;ll learn how to do over-the-air (OTA) updates to your ESP32 boards using the AsyncElegantOTA library and <a href=\"https:\/\/randomnerdtutorials.com\/vs-code-platformio-ide-esp32-esp8266-arduino\/\">VS Code with PlatformIO<\/a>. The Async Elegant OTA library creates a web server that allows you to update new firmware (a new sketch) to your board without the need to make a serial connection between the ESP32 and your computer.<\/p>\n\n\n\n<p>Additionally, with this library, you can also upload new files to the ESP32 filesystem (SPIFFS). The library is very easy to use and it&#8217;s compatible with the ESPAsyncWebServer library that we use often to build web server projects.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/Async-WebOTA-Updates-ESP32-VS-Code-PlatformIO.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 OTA Over-the-Air Updates AsyncElegantOTA VS Code  PlatformIO\" class=\"wp-image-101740\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/Async-WebOTA-Updates-ESP32-VS-Code-PlatformIO.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/Async-WebOTA-Updates-ESP32-VS-Code-PlatformIO.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/Async-WebOTA-Updates-ESP32-VS-Code-PlatformIO.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/Async-WebOTA-Updates-ESP32-VS-Code-PlatformIO.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>By the end of this tutorial, you&#8217;ll be able to easily add OTA capabilities to your web server projects with the ESP32 to upload new firmware and files to the filesystem wirelessly in the future.<\/p>\n\n\n\n<p class=\"rntbox rntclblue\">Recommended reading: <a href=\"https:\/\/randomnerdtutorials.com\/vs-code-platformio-ide-esp32-esp8266-arduino\/\">Getting Started with VS Code and PlatformIO IDE for ESP32 and ESP8266<\/a><\/p>\n\n\n\n<p>We have a similar tutorial for the ESP8266 NodeMCU board: <a href=\"https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-ota-over-the-air-vs-code\/\">ESP8266 NodeMCU OTA (Over-the-Air) Updates \u2013 AsyncElegantOTA (VS Code + PlatformIO)<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Overview<\/h2>\n\n\n\n<p>This tutorial covers:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"#1-basic-elegantota\">Add the ElegantOTA feature to your ESP32 web server <\/a><\/li>\n\n\n\n<li><a href=\"#2-update-firware-ota\">Upload new firmware via OTA to ESP32 board<\/a><\/li>\n\n\n\n<li><a href=\"#3-update-filesystem-ota\">Upload files to SPIFFS via OTA to ESP32 board<\/a><\/li>\n<\/ul>\n\n\n\n<p>We recommend that you follow all the steps in this tutorial to understand how ElegantOTA works and how you can use it in your projects. To demonstrate how to do this, we&#8217;ll upload files to build different web server projects.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">ESP32 OTA (Over-the-Air) Programming<\/h2>\n\n\n\n<p>OTA (Over-the-Air) update is the process of loading new firmware to the ESP32 board using a Wi-Fi connection rather than a serial communication. This functionality is extremely useful in case of no physical access to the ESP32 board.<\/p>\n\n\n\n<p>There are different ways to perform OTA updates. In this tutorial, we&#8217;ll cover how to do that using the <a href=\"https:\/\/github.com\/ayushsharma82\/AsyncElegantOTA\" target=\"_blank\" rel=\"noreferrer noopener\">AsyncElegantOTA library<\/a>. In our opinion, this is one of the best and easiest ways to perform OTA updates.<\/p>\n\n\n\n<p>The AsyncElegantOTA library creates a web server that you can access on your local network to upload new firmware or files to the filesystem (SPIFFS). The files you upload should be in <em>.bin<\/em> format. We&#8217;ll show you later in the tutorial how to get your files to <em>.bin<\/em> format.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"751\" height=\"370\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Async-Elegant-OTA-Web-Server-ESP32-How-it-Works.png?resize=751%2C370&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Async ElegantOTA Web Server How it Works ESP32\" class=\"wp-image-101670\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Async-Elegant-OTA-Web-Server-ESP32-How-it-Works.png?w=751&amp;quality=100&amp;strip=all&amp;ssl=1 751w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Async-Elegant-OTA-Web-Server-ESP32-How-it-Works.png?resize=300%2C148&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 751px) 100vw, 751px\" \/><\/figure><\/div>\n\n\n<p>The only disadvantage of OTA programming is that you need to add the code for OTA in every sketch you upload so that you\u2019re able to use OTA in the future. In the case of the AsyncElegantOTA library, it consists of just three lines of code.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">AsyncElegantOTA Library<\/h2>\n\n\n\n<p>As mentioned previously, there are different alternatives for OTA programming with the ESP32 boards. For example, in the Arduino IDE, under the <em>Examples <\/em>folder, there is the <em>BasicOTA<\/em> example (that never worked well for us); the <em><a href=\"https:\/\/randomnerdtutorials.com\/esp32-over-the-air-ota-programming\/\" target=\"_blank\" rel=\"noreferrer noopener\">OTA Web Updater<\/a><\/em> (works well, but it is difficult to integrate with web servers using the ESPAsyncWebServer library); and many other examples from different libraries.<\/p>\n\n\n\n<p>Most of our web server projects with the ESP32 use the <a href=\"https:\/\/github.com\/me-no-dev\/ESPAsyncWebServer\" target=\"_blank\" rel=\"noreferrer noopener\">ESPAsyncWebServer library<\/a>. So, we wanted a solution that was compatible with that library. The <a href=\"https:\/\/github.com\/ayushsharma82\/AsyncElegantOTA\" target=\"_blank\" rel=\"noreferrer noopener\">AsyncElegantOTA library<\/a> is just perfect for what we want:<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"500\" height=\"97\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Async-ElegantOTA-logo.png?resize=500%2C97&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"AsyncElegantOTA Library\" class=\"wp-image-101648\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Async-ElegantOTA-logo.png?w=500&amp;quality=100&amp;strip=all&amp;ssl=1 500w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Async-ElegantOTA-logo.png?resize=300%2C58&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 500px) 100vw, 500px\" \/><\/figure><\/div>\n\n\n<ul class=\"wp-block-list\">\n<li>It is compatible with the ESPAsyncWebServer library;<\/li>\n\n\n\n<li>You just need to add three lines of code to add OTA capabilities to your &#8220;regular&#8221; Async Web Server;<\/li>\n\n\n\n<li>It allows you to update not only new firmware to the board, but also files to the ESP32 filesystem (SPIFFS);<\/li>\n\n\n\n<li>It provides a beautiful and modern web server interface;<\/li>\n\n\n\n<li>It works extremely well.<\/li>\n<\/ul>\n\n\n\n<p class=\"rntbox rntclblue\">If you like this library and you&#8217;ll use it in your projects, consider supporting the <a href=\"https:\/\/github.com\/ayushsharma82\/AsyncElegantOTA#contributions\" target=\"_blank\" rel=\"noreferrer noopener\">developer&#8217;s work<\/a>. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">OTA Updates with AsyncElegantOTA Library &#8211; Quick Summary<\/h2>\n\n\n\n<p>To add OTA capabilities to your projects using the AsyncElegantOTA library, follow these steps:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Iclude the <a href=\"https:\/\/github.com\/ayushsharma82\/AsyncElegantOTA\" target=\"_blank\" rel=\"noreferrer noopener\">AsyncElegantOTA<\/a>, <a href=\"https:\/\/github.com\/me-no-dev\/AsyncTCP\" target=\"_blank\" rel=\"noreferrer noopener\">AsyncTCP<\/a> and <a href=\"https:\/\/github.com\/me-no-dev\/ESPAsyncWebServer\" target=\"_blank\" rel=\"noreferrer noopener\">ESPAsyncWebServer <\/a>libraries in the <em>platformio.ini<\/em> file of your project;<\/li>\n\n\n\n<li>Include AsyncElegantOTA library at the top of the code: <span class=\"rnthl rntliteral\">#include &lt;AsyncElegantOTA.h>;<\/span><\/li>\n\n\n\n<li>Add this line <span class=\"rnthl rntliteral\">AsyncElegantOTA.begin(&amp;server);<\/span> before <span class=\"rnthl rntliteral\">server.begin();<\/span><\/li>\n\n\n\n<li>Open your browser and go to <span class=\"rnthl rntliteral\">http:\/\/&lt;IPAddress>\/update<\/span>, where <span class=\"rnthl rntliteral\">&lt;IPAddress><\/span> is your ESP32 IP address.<\/li>\n<\/ol>\n\n\n\n<p>Continue reading the tutorial for more detailed steps.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How does OTA Web Updater Work?<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The first sketch should be uploaded via the serial port. This sketch should contain the code to create the OTA Web Updater so that you are able to upload code later using your browser.<\/li>\n\n\n\n<li>The OTA Web Updater sketch creates a web server you can access to upload a new sketch via a web browser.<\/li>\n\n\n\n<li>Then, you need to implement OTA routines in every sketch you upload, so that you&#8217;re able to do the next updates\/uploads over-the-air.<\/li>\n\n\n\n<li>If you upload a code without an OTA routine you&#8217;ll no longer be able to access the web server and upload a new sketch over-the-air.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Install AsyncElegantOTA Library (VS Code + PIO)<\/h2>\n\n\n\n<p>In this tutorial, we&#8217;ll use VS Code + PIO to program the ESP32. If you want to use Arduino IDE, follow the next tutorial: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-ota-over-the-air-arduino\/\">ESP32 OTA (Over-the-Air) Updates \u2013 AsyncElegantOTA using Arduino IDE<\/a>.<\/p>\n\n\n\n<p>To use the AsyncElegantOTA library, include it in your <em>platformio.ini<\/em> file. You also need to include the ESPAsyncWebServer library. Add these libraries as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lib_deps = ESP Async WebServer\n  ayushsharma82\/AsyncElegantOTA @ ^2.2.5<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"1-basic-elegantota\">AsyncElegantOTA ESP32 Basic Example<\/h2>\n\n\n\n<p class=\"rntbox rntcred\">If you\u2019re using an ESP32, you need to downgrade your ESP32 boards\u2019 add-on to version 2.0.X. At the moment, the AsyncElegantOTA library is not compatible with version 3.X. If you want to use version 3.X, please use the newest version of the library:\u00a0<a href=\"https:\/\/github.com\/ayushsharma82\/ElegantOTA\" target=\"_blank\" rel=\"noreferrer noopener\">ElegantOTA V3<\/a>.<\/p>\n\n\n\n<p>Let&#8217;s start with the basic example provided by the library. This example creates a simple web server with the ESP32. The root URL displays some text, and the <span class=\"rnthl rntliteral\">\/update<\/span> URL displays the interface to update the firmware and the filesystem.<\/p>\n\n\n\n<p>Edit your <em>platformio.ini<\/em> file so that it looks as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>&#091;env:esp32doit-devkit-v1]\nplatform = espressif32\nboard = esp32doit-devkit-v1\nframework = arduino\nmonitor_speed = 115200\nlib_deps = ESP Async WebServer\n  ayushsharma82\/AsyncElegantOTA @ ^2.2.5<\/code><\/pre>\n\n\n\n<p>Copy the following code to the main.cpp file. <\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*\r\n  Rui Santos\r\n  Complete project details\r\n   - Arduino IDE: https:\/\/RandomNerdTutorials.com\/esp32-ota-over-the-air-arduino\/\r\n   - VS Code: https:\/\/RandomNerdTutorials.com\/esp32-ota-over-the-air-vs-code\/\r\n  \r\n  This sketch shows a Basic example from the AsyncElegantOTA library: ESP32_Async_Demo\r\n  https:\/\/github.com\/ayushsharma82\/AsyncElegantOTA\r\n*\/\r\n\r\n#include &lt;Arduino.h&gt;\r\n#include &lt;WiFi.h&gt;\r\n#include &lt;AsyncTCP.h&gt;\r\n#include &lt;ESPAsyncWebServer.h&gt;\r\n#include &lt;AsyncElegantOTA.h&gt;\r\n\r\nconst char* ssid = &quot;REPLACE_WITH_YOUR_SSID&quot;;\r\nconst char* password = &quot;REPLACE_WITH_YOUR_PASSWORD&quot;;\r\n\r\nAsyncWebServer server(80);\r\n\r\nvoid setup(void) {\r\n  Serial.begin(115200);\r\n  WiFi.mode(WIFI_STA);\r\n  WiFi.begin(ssid, password);\r\n  Serial.println(&quot;&quot;);\r\n\r\n  \/\/ Wait for connection\r\n  while (WiFi.status() != WL_CONNECTED) {\r\n    delay(500);\r\n    Serial.print(&quot;.&quot;);\r\n  }\r\n  Serial.println(&quot;&quot;);\r\n  Serial.print(&quot;Connected to &quot;);\r\n  Serial.println(ssid);\r\n  Serial.print(&quot;IP address: &quot;);\r\n  Serial.println(WiFi.localIP());\r\n\r\n  server.on(&quot;\/&quot;, HTTP_GET, [](AsyncWebServerRequest *request) {\r\n    request-&gt;send(200, &quot;text\/plain&quot;, &quot;Hi! I am ESP32.&quot;);\r\n  });\r\n\r\n  AsyncElegantOTA.begin(&amp;server);    \/\/ Start ElegantOTA\r\n  server.begin();\r\n  Serial.println(&quot;HTTP server started&quot;);\r\n}\r\n\r\nvoid loop(void) {\r\n\r\n}\r\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/AsyncElegantOTA\/ESP32_ElegantOTA_Demo\/ESP32_ElegantOTA_Demo.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>Insert your network credentials and the code should work straight away:<\/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<h2 class=\"wp-block-heading\">How the Code Works<\/h2>\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;Arduino.h&gt;\n#include &lt;WiFi.h&gt;\n#include &lt;AsyncTCP.h&gt;\n#include &lt;ESPAsyncWebServer.h&gt;\n#include &lt;AsyncElegantOTA.h&gt;<\/code><\/pre>\n\n\n\n<p>Insert your network credentials in the following variables so that the ESP32 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<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<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, initialize the Serial Monitor:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.begin(115200);<\/code><\/pre>\n\n\n\n<p>Initialize Wi-Fi:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>WiFi.mode(WIFI_STA);\nWiFi.begin(ssid, password);\nSerial.println(\"\");\n\n\/\/ Wait for connection\nwhile (WiFi.status() != WL_CONNECTED) {\n  delay(500);\n  Serial.print(\".\");\n}\nSerial.println(\"\");\nSerial.print(\"Connected to \");\nSerial.println(ssid);\nSerial.print(\"IP address: \");\nSerial.println(WiFi.localIP());<\/code><\/pre>\n\n\n\n<p>Then, handle the client requests. The following lines, send some text <span class=\"rnthl rntliteral\">Hi! I am ESP32.<\/span> when you access the root (<span class=\"rnthl rntliteral\">\/<\/span>) URL:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.on(\"\/\", HTTP_GET, &#091;](AsyncWebServerRequest *request) {\n  request-&gt;send(200, \"text\/plain\", \"Hi! I am ESP32.\");\n});<\/code><\/pre>\n\n\n\n<p>If your web server needs to handle more requests you can add them (we&#8217;ll show you in the next example).<\/p>\n\n\n\n<p>Then, add the next line to start ElegantOTA:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>AsyncElegantOTA.begin(&amp;server); \/\/ Start ElegantOTA<\/code><\/pre>\n\n\n\n<p>Finally, initialize 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\">Access the Web Server<\/h2>\n\n\n\n<p>After uploading code to the board, open the Serial Monitor at a baud rate of 115200. Press the ESP32 on-board RST button. It should display the ESP IP address as follows (yours may be different):<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"900\" height=\"244\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/VS-Code-PlatformIO-Get-ESP-Board-IP-Address.png?resize=900%2C244&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"VS Code with PlatformIO Get Board IP Address\" class=\"wp-image-101732\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/VS-Code-PlatformIO-Get-ESP-Board-IP-Address.png?w=900&amp;quality=100&amp;strip=all&amp;ssl=1 900w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/VS-Code-PlatformIO-Get-ESP-Board-IP-Address.png?resize=300%2C81&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/VS-Code-PlatformIO-Get-ESP-Board-IP-Address.png?resize=768%2C208&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 900px) 100vw, 900px\" \/><\/figure><\/div>\n\n\n<p>In your local network, open your browser and type the ESP32 IP address. You should get access the root (<span class=\"rnthl rntliteral\">\/<\/span>) web page with some text displayed.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"603\" height=\"304\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Elegant-OTA-Demo-Example-Root-URL.png?resize=603%2C304&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"AsyncElegantOTA Demo Example Web Server Root URL\" class=\"wp-image-101651\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Elegant-OTA-Demo-Example-Root-URL.png?w=603&amp;quality=100&amp;strip=all&amp;ssl=1 603w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Elegant-OTA-Demo-Example-Root-URL.png?resize=300%2C151&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 603px) 100vw, 603px\" \/><\/figure><\/div>\n\n\n<p>Now, imagine that you want to modify your web server code. To do that via OTA, go to the ESP IP address followed by <span class=\"rnthl rntliteral\">\/update<\/span>. The following web page should load.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"789\" height=\"499\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Async-ElegantOTA-Update-Page.png?resize=789%2C499&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Async ElegantOTA Update Page\" class=\"wp-image-101652\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Async-ElegantOTA-Update-Page.png?w=789&amp;quality=100&amp;strip=all&amp;ssl=1 789w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Async-ElegantOTA-Update-Page.png?resize=300%2C190&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Async-ElegantOTA-Update-Page.png?resize=768%2C486&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 789px) 100vw, 789px\" \/><\/figure><\/div>\n\n\n<p>Follow the next sections to learn how to upload new firmware using the AsyncElegantOTA.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"2-update-firware-ota\">Upload New Firmware OTA (Over-the-Air) Updates &#8211; ESP32<\/h2>\n\n\n\n<p>Every file that you upload via OTA should be in&nbsp;<em>.bin<\/em>&nbsp;format. VS Code automatically generates the <em>.bin<\/em> file for your project when you compile the code. The file is called <em><strong>firmware.bin<\/strong><\/em> and it is saved on your project folder on the following path (or similar depending on the board you\u2019re using):<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">.pio\/build\/esp32doit-devkit-v1\/<strong>firmware.bin<\/strong><\/pre>\n\n\n\n<p>That\u2019s that&nbsp;<em>.bin<\/em>&nbsp;file you should upload using the AsyncElegantOTA web page if you want to upload new firmware.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Upload a New Web Server Sketch<\/h3>\n\n\n\n<p>Let&#8217;s see a practical example. Imagine that after uploading the previous sketch, you want to upload a new one that allows you to control an LED via a web interface like <a href=\"https:\/\/randomnerdtutorials.com\/esp32-websocket-server-arduino\/\">this project<\/a>. Here&#8217;s the steps you need to follow:<\/p>\n\n\n\n<p>1. Copy the following code to your <em>main.cpp<\/em> file. Don&#8217;t forget to insert your network credentials.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*\r\n  Rui Santos\r\n  Complete project details\r\n   - Arduino IDE: https:\/\/RandomNerdTutorials.com\/esp32-ota-over-the-air-arduino\/\r\n   - VS Code: https:\/\/RandomNerdTutorials.com\/esp32-ota-over-the-air-vs-code\/\r\n\r\n  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.\r\n  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\r\n*\/\r\n\r\n\/\/ Import required libraries\r\n#include &lt;Arduino.h&gt;\r\n#include &lt;WiFi.h&gt;\r\n#include &lt;AsyncTCP.h&gt;\r\n#include &lt;ESPAsyncWebServer.h&gt;\r\n#include &lt;AsyncElegantOTA.h&gt;\r\n\r\n\/\/ Replace with your network credentials\r\nconst char* ssid = &quot;REPLACE_WITH_YOUR_SSID&quot;;\r\nconst char* password = &quot;REPLACE_WITH_YOUR_PASSWORD&quot;;\r\n\r\nbool ledState = 0;\r\nconst int ledPin = 2;\r\n\r\n\/\/ Create AsyncWebServer object on port 80\r\nAsyncWebServer server(80);\r\nAsyncWebSocket ws(&quot;\/ws&quot;);\r\n\r\nconst char index_html[] PROGMEM = R&quot;rawliteral(\r\n&lt;!DOCTYPE HTML&gt;&lt;html&gt;\r\n&lt;head&gt;\r\n  &lt;title&gt;ESP Web Server&lt;\/title&gt;\r\n  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;\r\n  &lt;link rel=&quot;icon&quot; href=&quot;data:,&quot;&gt;\r\n  &lt;style&gt;\r\n  html {\r\n    font-family: Arial, Helvetica, sans-serif;\r\n    text-align: center;\r\n  }\r\n  h1 {\r\n    font-size: 1.8rem;\r\n    color: white;\r\n  }\r\n  h2{\r\n    font-size: 1.5rem;\r\n    font-weight: bold;\r\n    color: #143642;\r\n  }\r\n  .topnav {\r\n    overflow: hidden;\r\n    background-color: #143642;\r\n  }\r\n  body {\r\n    margin: 0;\r\n  }\r\n  .content {\r\n    padding: 30px;\r\n    max-width: 600px;\r\n    margin: 0 auto;\r\n  }\r\n  .card {\r\n    background-color: #F8F7F9;;\r\n    box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);\r\n    padding-top:10px;\r\n    padding-bottom:20px;\r\n  }\r\n  .button {\r\n    padding: 15px 50px;\r\n    font-size: 24px;\r\n    text-align: center;\r\n    outline: none;\r\n    color: #fff;\r\n    background-color: #0f8b8d;\r\n    border: none;\r\n    border-radius: 5px;\r\n    -webkit-touch-callout: none;\r\n    -webkit-user-select: none;\r\n    -khtml-user-select: none;\r\n    -moz-user-select: none;\r\n    -ms-user-select: none;\r\n    user-select: none;\r\n    -webkit-tap-highlight-color: rgba(0,0,0,0);\r\n   }\r\n   \/*.button:hover {background-color: #0f8b8d}*\/\r\n   .button:active {\r\n     background-color: #0f8b8d;\r\n     box-shadow: 2 2px #CDCDCD;\r\n     transform: translateY(2px);\r\n   }\r\n   .state {\r\n     font-size: 1.5rem;\r\n     color:#8c8c8c;\r\n     font-weight: bold;\r\n   }\r\n  &lt;\/style&gt;\r\n&lt;title&gt;ESP Web Server&lt;\/title&gt;\r\n&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;\r\n&lt;link rel=&quot;icon&quot; href=&quot;data:,&quot;&gt;\r\n&lt;\/head&gt;\r\n&lt;body&gt;\r\n  &lt;div class=&quot;topnav&quot;&gt;\r\n    &lt;h1&gt;ESP WebSocket Server&lt;\/h1&gt;\r\n  &lt;\/div&gt;\r\n  &lt;div class=&quot;content&quot;&gt;\r\n    &lt;div class=&quot;card&quot;&gt;\r\n      &lt;h2&gt;Output - GPIO 2&lt;\/h2&gt;\r\n      &lt;p class=&quot;state&quot;&gt;state: &lt;span id=&quot;state&quot;&gt;%STATE%&lt;\/span&gt;&lt;\/p&gt;\r\n      &lt;p&gt;&lt;button id=&quot;button&quot; class=&quot;button&quot;&gt;Toggle&lt;\/button&gt;&lt;\/p&gt;\r\n    &lt;\/div&gt;\r\n  &lt;\/div&gt;\r\n&lt;script&gt;\r\n  var gateway = `ws:\/\/${window.location.hostname}\/ws`;\r\n  var websocket;\r\n  window.addEventListener('load', onLoad);\r\n  function initWebSocket() {\r\n    console.log('Trying to open a WebSocket connection...');\r\n    websocket = new WebSocket(gateway);\r\n    websocket.onopen    = onOpen;\r\n    websocket.onclose   = onClose;\r\n    websocket.onmessage = onMessage; \/\/ &lt;-- add this line\r\n  }\r\n  function onOpen(event) {\r\n    console.log('Connection opened');\r\n  }\r\n  function onClose(event) {\r\n    console.log('Connection closed');\r\n    setTimeout(initWebSocket, 2000);\r\n  }\r\n  function onMessage(event) {\r\n    var state;\r\n    if (event.data == &quot;1&quot;){\r\n      state = &quot;ON&quot;;\r\n    }\r\n    else{\r\n      state = &quot;OFF&quot;;\r\n    }\r\n    document.getElementById('state').innerHTML = state;\r\n  }\r\n  function onLoad(event) {\r\n    initWebSocket();\r\n    initButton();\r\n  }\r\n  function initButton() {\r\n    document.getElementById('button').addEventListener('click', toggle);\r\n  }\r\n  function toggle(){\r\n    websocket.send('toggle');\r\n  }\r\n&lt;\/script&gt;\r\n&lt;\/body&gt;\r\n&lt;\/html&gt;)rawliteral&quot;;\r\n\r\nvoid notifyClients() {\r\n  ws.textAll(String(ledState));\r\n}\r\n\r\nvoid handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {\r\n  AwsFrameInfo *info = (AwsFrameInfo*)arg;\r\n  if (info-&gt;final &amp;&amp; info-&gt;index == 0 &amp;&amp; info-&gt;len == len &amp;&amp; info-&gt;opcode == WS_TEXT) {\r\n    data[len] = 0;\r\n    if (strcmp((char*)data, &quot;toggle&quot;) == 0) {\r\n      ledState = !ledState;\r\n      notifyClients();\r\n    }\r\n  }\r\n}\r\n\r\nvoid onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type,\r\n             void *arg, uint8_t *data, size_t len) {\r\n  switch (type) {\r\n    case WS_EVT_CONNECT:\r\n      Serial.printf(&quot;WebSocket client #%u connected from %s\\n&quot;, client-&gt;id(), client-&gt;remoteIP().toString().c_str());\r\n      break;\r\n    case WS_EVT_DISCONNECT:\r\n      Serial.printf(&quot;WebSocket client #%u disconnected\\n&quot;, client-&gt;id());\r\n      break;\r\n    case WS_EVT_DATA:\r\n      handleWebSocketMessage(arg, data, len);\r\n      break;\r\n    case WS_EVT_PONG:\r\n    case WS_EVT_ERROR:\r\n      break;\r\n  }\r\n}\r\n\r\nvoid initWebSocket() {\r\n  ws.onEvent(onEvent);\r\n  server.addHandler(&amp;ws);\r\n}\r\n\r\nString processor(const String&amp; var){\r\n  Serial.println(var);\r\n  if(var == &quot;STATE&quot;){\r\n    if (ledState){\r\n      return &quot;ON&quot;;\r\n    }\r\n    else{\r\n      return &quot;OFF&quot;;\r\n    }\r\n  }\r\n  return String();\r\n}\r\n\r\nvoid setup(){\r\n  \/\/ Serial port for debugging purposes\r\n  Serial.begin(115200);\r\n\r\n  pinMode(ledPin, OUTPUT);\r\n  digitalWrite(ledPin, LOW);\r\n  \r\n  \/\/ Connect to Wi-Fi\r\n  WiFi.begin(ssid, password);\r\n  while (WiFi.status() != WL_CONNECTED) {\r\n    delay(1000);\r\n    Serial.println(&quot;Connecting to WiFi..&quot;);\r\n  }\r\n\r\n  \/\/ Print ESP Local IP Address\r\n  Serial.println(WiFi.localIP());\r\n\r\n  initWebSocket();\r\n\r\n  \/\/ Route for root \/ web page\r\n  server.on(&quot;\/&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\r\n    request-&gt;send(200, &quot;text\/html&quot;, index_html, processor);\r\n  });\r\n\r\n  \/\/ Start ElegantOTA\r\n  AsyncElegantOTA.begin(&amp;server);\r\n  \/\/ Start server\r\n  server.begin();\r\n}\r\n\r\nvoid loop() {\r\n  ws.cleanupClients();\r\n  digitalWrite(ledPin, ledState);\r\n}\r\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/AsyncElegantOTA\/ESP32_Web_Server_LED_OTA\/ESP32_Web_Server_LED_OTA.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>This is the same code used in <a href=\"https:\/\/randomnerdtutorials.com\/esp32-websocket-server-arduino\/\">this project<\/a>, but it contains the required lines of code to handle ElegantOTA:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;AsyncElegantOTA.h&gt;<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>AsyncElegantOTA.begin(&amp;server);<\/code><\/pre>\n\n\n\n<p>2. Edit your <em>platformio.ini<\/em> file as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>&#091;env:esp32doit-devkit-v1]\nplatform = espressif32\nboard = esp32doit-devkit-v1\nframework = arduino\nmonitor_speed = 115200\nlib_deps = ESP Async WebServer\n  ayushsharma82\/AsyncElegantOTA @ ^2.2.5<\/code><\/pre>\n\n\n\n<p><strong>2.<\/strong> Save and compile your code &#8211; click on the <strong>Build<\/strong> icon.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"578\" height=\"89\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/VS-Code-PlatformIO-Compile-Code-ESP32-ESP8266.png?resize=578%2C89&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"VS Code + PlatformIO Compile (Build) Code\" class=\"wp-image-101733\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/VS-Code-PlatformIO-Compile-Code-ESP32-ESP8266.png?w=578&amp;quality=100&amp;strip=all&amp;ssl=1 578w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/VS-Code-PlatformIO-Compile-Code-ESP32-ESP8266.png?resize=300%2C46&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 578px) 100vw, 578px\" \/><\/figure><\/div>\n\n\n<p><strong>3<\/strong>. Now, in the Explorer tab of VS Code, you can check that you have a <em>firmware.bin<\/em> file under the project folder on the following path&nbsp;(or similar):<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">.pio\/build\/esp32doit-devkit-v1\/<strong>firmware.bin<\/strong><\/pre>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"352\" height=\"545\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/bin-file-directory-vs-code.png?resize=352%2C545&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"VS Code with PlatformIO Bin File Directory ESP32 ESP8266\" class=\"wp-image-101734\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/bin-file-directory-vs-code.png?w=352&amp;quality=100&amp;strip=all&amp;ssl=1 352w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/bin-file-directory-vs-code.png?resize=194%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 194w\" sizes=\"(max-width: 352px) 100vw, 352px\" \/><\/figure><\/div>\n\n\n<p><strong>4.<\/strong> Now, you just need to upload that file using the ElegantOTA page. Go to your ESP IP address followed by <span class=\"rnthl rntliteral\">\/update<\/span>. Make sure you have the <strong>firmware<\/strong> option selected.<\/p>\n\n\n\n<p><strong>5.<\/strong> Click on&nbsp;<strong>Choose File<\/strong>, navigate through the folder on your computer&nbsp;and select the file of your project.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"639\" height=\"359\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/firmware-bin-file-location-platformio-VS-Code-ESP32-ESP8266.png?resize=639%2C359&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Firmware Bin File Directory VS Code PlatformIO IDE\" class=\"wp-image-101735\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/firmware-bin-file-location-platformio-VS-Code-ESP32-ESP8266.png?w=639&amp;quality=100&amp;strip=all&amp;ssl=1 639w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/firmware-bin-file-location-platformio-VS-Code-ESP32-ESP8266.png?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 639px) 100vw, 639px\" \/><\/figure><\/div>\n\n\n<p><strong>6.<\/strong> Wait until the progress bar reaches 100%.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"988\" height=\"589\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Uploading-new-firmware-elegantOTA.png?resize=988%2C589&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Update New Firmware Elegant OTA\" class=\"wp-image-101659\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Uploading-new-firmware-elegantOTA.png?w=988&amp;quality=100&amp;strip=all&amp;ssl=1 988w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Uploading-new-firmware-elegantOTA.png?resize=300%2C179&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Uploading-new-firmware-elegantOTA.png?resize=768%2C458&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 988px) 100vw, 988px\" \/><\/figure><\/div>\n\n\n<p><strong>7.<\/strong> When it&#8217;s finished, click on the <strong>Back <\/strong>button. <\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"789\" height=\"532\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/upload-new-firmware-elegantOTA-success.png?resize=789%2C532&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Upload New Firmware Elegant OTA success\" class=\"wp-image-101660\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/upload-new-firmware-elegantOTA-success.png?w=789&amp;quality=100&amp;strip=all&amp;ssl=1 789w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/upload-new-firmware-elegantOTA-success.png?resize=300%2C202&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/upload-new-firmware-elegantOTA-success.png?resize=768%2C518&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 789px) 100vw, 789px\" \/><\/figure><\/div>\n\n\n<p><strong>8.<\/strong> Then, you can go to the root (<span class=\"rnthl rntliteral\">\/<\/span>) URL to access the new web server. This is the page that you should see when you access the ESP IP address on the root (<span class=\"rnthl rntliteral\">\/<\/span>) URL. <\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"789\" height=\"532\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/WebSocket-Server-ESP32-Control-Outputs.png?resize=789%2C532&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Websocket Server Control Outputs\" class=\"wp-image-101661\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/WebSocket-Server-ESP32-Control-Outputs.png?w=789&amp;quality=100&amp;strip=all&amp;ssl=1 789w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/WebSocket-Server-ESP32-Control-Outputs.png?resize=300%2C202&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/WebSocket-Server-ESP32-Control-Outputs.png?resize=768%2C518&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 789px) 100vw, 789px\" \/><\/figure><\/div>\n\n\n<p>You can click on the button to turn the ESP32 on-board LED on and off.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-on-HIGH.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 board Built in LED turned on HIGH\" class=\"wp-image-96167\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-on-HIGH.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-on-HIGH.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>Because we&#8217;ve also added OTA capabilities to this new web server, we can upload a new sketch in the future if needed. You just need to go to the ESP32 IP address followed by <span class=\"rnthl rntliteral\">\/update<\/span>.<\/p>\n\n\n\n<p>Congratulations, you&#8217;ve uploaded new code to your ESP32 via Wi-Fi using ElegantOTA.<\/p>\n\n\n\n<p>Continue reading if you want to learn how to upload files to the ESP32 filesystem (SPIFFS) using AsyncElegantOTA.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"3-update-filesystem-ota\">Upload Files to Filesystem OTA (Over-the-Air) Updates &#8211; ESP32<\/h2>\n\n\n\n<p>In this section you&#8217;ll learn to upload files to the ESP32 filesystem (SPIFFS) using AsyncElegantOTA.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Web Server with Files from SPIFFS<\/h3>\n\n\n\n<p>Imagine the scenario that you need to upload files to the ESP32 filesystem, for example: configuration files; HTML, CSS and JavaScript files to update the web server page; or any other file that you may want to save in SPIFFS via OTA.<\/p>\n\n\n\n<p>To show you how to do this, we&#8217;ll create a new web server that serves files from SPIFFS: HTML, CSS and JavaScript files to build a web page that controls the ESP32 GPIOs remotely.<\/p>\n\n\n\n<p>Copy the following code to your <em>main.cpp<\/em> file.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*\r\n  Rui Santos\r\n  Complete project details\r\n   - Arduino IDE: https:\/\/RandomNerdTutorials.com\/esp32-ota-over-the-air-arduino\/\r\n   - VS Code: https:\/\/RandomNerdTutorials.com\/esp32-ota-over-the-air-vs-code\/\r\n  \r\n  Permission is hereby granted, free of charge, to any person obtaining a copy\r\n  of this software and associated documentation files.\r\n  \r\n  The above copyright notice and this permission notice shall be included in all\r\n  copies or substantial portions of the Software.\r\n*\/\r\n\r\n\/\/ Import required libraries\r\n#include &lt;Arduino.h&gt;\r\n#include &lt;WiFi.h&gt;\r\n#include &lt;AsyncTCP.h&gt;\r\n#include &lt;ESPAsyncWebServer.h&gt;\r\n#include &quot;SPIFFS.h&quot;\r\n#include &lt;Arduino_JSON.h&gt;\r\n#include &lt;AsyncElegantOTA.h&gt;\r\n\r\n\/\/ Replace with your network credentials\r\nconst char* ssid = &quot;REPLACE_WITH_YOUR_SSID&quot;;\r\nconst char* password = &quot;REPLACE_WITH_YOUR_PASSWORD&quot;;\r\n\r\n\/\/ Create AsyncWebServer object on port 80\r\nAsyncWebServer server(80);\r\n\r\n\/\/ Create a WebSocket object\r\nAsyncWebSocket ws(&quot;\/ws&quot;);\r\n\r\n\/\/ Set number of outputs\r\n#define NUM_OUTPUTS  4\r\n\r\n\/\/ Assign each GPIO to an output\r\nint outputGPIOs[NUM_OUTPUTS] = {2, 4, 12, 14};\r\n\r\n\/\/ Initialize SPIFFS\r\nvoid initSPIFFS() {\r\n  if (!SPIFFS.begin(true)) {\r\n    Serial.println(&quot;An error has occurred while mounting SPIFFS&quot;);\r\n  }\r\n  Serial.println(&quot;SPIFFS mounted successfully&quot;);\r\n}\r\n\r\n\/\/ Initialize WiFi\r\nvoid initWiFi() {\r\n  WiFi.mode(WIFI_STA);\r\n  WiFi.begin(ssid, password);\r\n  Serial.print(&quot;Connecting to WiFi ..&quot;);\r\n  while (WiFi.status() != WL_CONNECTED) {\r\n    Serial.print('.');\r\n    delay(1000);\r\n  }\r\n  Serial.println(WiFi.localIP());\r\n}\r\n\r\nString getOutputStates(){\r\n  JSONVar myArray;\r\n  for (int i =0; i&lt;NUM_OUTPUTS; i++){\r\n    myArray[&quot;gpios&quot;][i][&quot;output&quot;] = String(outputGPIOs[i]);\r\n    myArray[&quot;gpios&quot;][i][&quot;state&quot;] = String(digitalRead(outputGPIOs[i]));\r\n  }\r\n  String jsonString = JSON.stringify(myArray);\r\n  return jsonString;\r\n}\r\n\r\nvoid notifyClients(String state) {\r\n  ws.textAll(state);\r\n}\r\n\r\nvoid handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {\r\n  AwsFrameInfo *info = (AwsFrameInfo*)arg;\r\n  if (info-&gt;final &amp;&amp; info-&gt;index == 0 &amp;&amp; info-&gt;len == len &amp;&amp; info-&gt;opcode == WS_TEXT) {\r\n    data[len] = 0;\r\n    if (strcmp((char*)data, &quot;states&quot;) == 0) {\r\n      notifyClients(getOutputStates());\r\n    }\r\n    else{\r\n      int gpio = atoi((char*)data);\r\n      digitalWrite(gpio, !digitalRead(gpio));\r\n      notifyClients(getOutputStates());\r\n    }\r\n  }\r\n}\r\n\r\nvoid onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client,AwsEventType type,\r\n             void *arg, uint8_t *data, size_t len) {\r\n  switch (type) {\r\n    case WS_EVT_CONNECT:\r\n      Serial.printf(&quot;WebSocket client #%u connected from %s\\n&quot;, client-&gt;id(), client-&gt;remoteIP().toString().c_str());\r\n      break;\r\n    case WS_EVT_DISCONNECT:\r\n      Serial.printf(&quot;WebSocket client #%u disconnected\\n&quot;, client-&gt;id());\r\n      break;\r\n    case WS_EVT_DATA:\r\n      handleWebSocketMessage(arg, data, len);\r\n      break;\r\n    case WS_EVT_PONG:\r\n    case WS_EVT_ERROR:\r\n      break;\r\n  }\r\n}\r\n\r\nvoid initWebSocket() {\r\n    ws.onEvent(onEvent);\r\n    server.addHandler(&amp;ws);\r\n}\r\n\r\nvoid setup(){\r\n  \/\/ Serial port for debugging purposes\r\n  Serial.begin(115200);\r\n\r\n  \/\/ Set GPIOs as outputs\r\n  for (int i =0; i&lt;NUM_OUTPUTS; i++){\r\n    pinMode(outputGPIOs[i], OUTPUT);\r\n  }\r\n  initSPIFFS();\r\n  initWiFi();\r\n  initWebSocket();\r\n\r\n  \/\/ Route for root \/ web page\r\n  server.on(&quot;\/&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\r\n    request-&gt;send(SPIFFS, &quot;\/index.html&quot;, &quot;text\/html&quot;,false);\r\n  });\r\n\r\n  server.serveStatic(&quot;\/&quot;, SPIFFS, &quot;\/&quot;);\r\n\r\n  \/\/ Start ElegantOTA\r\n  AsyncElegantOTA.begin(&amp;server);\r\n  \r\n  \/\/ Start server\r\n  server.begin();\r\n}\r\n\r\nvoid loop() {\r\n  ws.cleanupClients();\r\n}\r\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/AsyncElegantOTA\/ESP32_Web_Server_OTA_SPIFFS\/ESP32_Web_Server_OTA_SPIFFS.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>Insert your network credentials in the following variables and save the code.<\/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>Edit your<em> platformio.ini<\/em> file so that it looks as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>&#091;env:esp32doit-devkit-v1]\nplatform = espressif32\nboard = esp32doit-devkit-v1\nframework = arduino\nmonitor_speed = 115200\nlib_deps  =  ESP Async WebServer\n    arduino-libraries\/Arduino_JSON @ 0.1.0\n    ayushsharma82\/AsyncElegantOTA @ ^2.2.5<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Update Firmware<\/h3>\n\n\n\n<p>After inserting your network credentials, save and compile the code.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><a href=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/VS-Code-PlatformIO-Compile-Code-ESP32-ESP8266.png?quality=100&#038;strip=all&#038;ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"578\" height=\"89\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/VS-Code-PlatformIO-Compile-Code-ESP32-ESP8266.png?resize=578%2C89&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"VS Code + PlatformIO Compile (Build) Code\" class=\"wp-image-101733\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/VS-Code-PlatformIO-Compile-Code-ESP32-ESP8266.png?w=578&amp;quality=100&amp;strip=all&amp;ssl=1 578w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/VS-Code-PlatformIO-Compile-Code-ESP32-ESP8266.png?resize=300%2C46&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 578px) 100vw, 578px\" \/><\/a><\/figure><\/div>\n\n\n<p>Go to the ESP IP address followed by <span class=\"rnthl rntliteral\">\/update<\/span> and upload the new firmware as shown previously.<\/p>\n\n\n\n<p>Next, we\u2019ll see how to upload the files to the filesystem.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Update Filesystem<\/h3>\n\n\n\n<p>Under the project folder create a folder called <em>data <\/em>and paste the following HTML, CSS and JavaScript files (click on the links to download the files):<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/raw.githubusercontent.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/master\/Projects\/ESP32\/AsyncElegantOTA\/ESP32_Web_Server_OTA_SPIFFS\/data\/index.html\" target=\"_blank\" rel=\"noreferrer noopener\">HTML file: <em>index.html<\/em><\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/raw.githubusercontent.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/master\/Projects\/ESP32\/AsyncElegantOTA\/ESP32_Web_Server_OTA_SPIFFS\/data\/style.css\" target=\"_blank\" rel=\"noreferrer noopener\">CSS file: <em>style.css<\/em><\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/raw.githubusercontent.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/master\/Projects\/ESP32\/AsyncElegantOTA\/ESP32_Web_Server_OTA_SPIFFS\/data\/script.js\" target=\"_blank\" rel=\"noreferrer noopener\">JavaScript file: <em>script.js<\/em><\/a><\/li>\n\n\n\n<li><strong><a href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/AsyncElegantOTA\/ESP32_Web_Server_OTA_SPIFFS\/data.zip\" target=\"_blank\" rel=\"noreferrer noopener\">Download all files<\/a><\/strong><\/li>\n<\/ul>\n\n\n\n<p>In VS Code, click on to the <strong>PIO<\/strong> icon and go to <strong>Project Tasks<\/strong> &gt; <strong>env:esp32doit-devkit-v1<\/strong> (or similar) &gt;<strong>Platform <\/strong>&gt; <strong>Build Filesystem Image<\/strong>. This will create a <em>.bin<\/em> file from the files saved in the <em>data <\/em>folder.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><a href=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/Build-Filesystem-Image-VS-Code-PlatformIO.png?quality=100&#038;strip=all&#038;ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"411\" height=\"433\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/Build-Filesystem-Image-VS-Code-PlatformIO.png?resize=411%2C433&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Build Filesystem Image VS Code PlatformIO ESP32\" class=\"wp-image-101736\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/Build-Filesystem-Image-VS-Code-PlatformIO.png?w=411&amp;quality=100&amp;strip=all&amp;ssl=1 411w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/Build-Filesystem-Image-VS-Code-PlatformIO.png?resize=285%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 285w\" sizes=\"(max-width: 411px) 100vw, 411px\" \/><\/a><\/figure><\/div>\n\n\n<p>After building the filesystem image, you should have a <em>spiffs.bin<\/em> file in the following path (or similar):<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">.pio\/build\/esp32doit-devkit-v1\/<strong>spiffs.bin<\/strong><\/pre>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"354\" height=\"617\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/SPIFFS-Bin-File-Directory-VS-Code-PlatformIO.png?resize=354%2C617&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"SPIFFS Bin File Directory VS Code + PlatformIO ESP32\" class=\"wp-image-101737\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/SPIFFS-Bin-File-Directory-VS-Code-PlatformIO.png?w=354&amp;quality=100&amp;strip=all&amp;ssl=1 354w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/SPIFFS-Bin-File-Directory-VS-Code-PlatformIO.png?resize=172%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 172w\" sizes=\"(max-width: 354px) 100vw, 354px\" \/><\/figure><\/div>\n\n\n<p>That\u2019s that file that you should upload to update the filesystem.<\/p>\n\n\n\n<p>Go to your ESP IP address followed by&nbsp;<span class=\"rnthl rntliteral\">\/update<\/span>. Make sure you have the&nbsp;<strong>Filesystem<\/strong>&nbsp;option selected and select the <em>spiffs.bin<\/em> file.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"789\" height=\"532\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Upload-Files-Filesystem-Elegant-OTA.png?resize=789%2C532&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Upload Files to Filesystem Elegant OTA\" class=\"wp-image-101664\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Upload-Files-Filesystem-Elegant-OTA.png?w=789&amp;quality=100&amp;strip=all&amp;ssl=1 789w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Upload-Files-Filesystem-Elegant-OTA.png?resize=300%2C202&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Upload-Files-Filesystem-Elegant-OTA.png?resize=768%2C518&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 789px) 100vw, 789px\" \/><\/figure><\/div>\n\n\n<p>After successfully uploading, click the <strong>Back <\/strong>button. And go to the root (<span class=\"rnthl rntliteral\">\/<\/span>) URL again. <\/p>\n\n\n\n<p>You should get access to the following web page that controls the ESP32 outputs using <a href=\"https:\/\/randomnerdtutorials.com\/esp32-websocket-server-arduino\/\">Web Socket protocol<\/a>. <\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"900\" height=\"674\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Control-Multiple-Outputs-Web-Socket-Web-Server-ESP32.png?resize=900%2C674&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Control Multiple ESP32 ESP8266 Outputs Websocket Web Server\" class=\"wp-image-101665\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Control-Multiple-Outputs-Web-Socket-Web-Server-ESP32.png?w=900&amp;quality=100&amp;strip=all&amp;ssl=1 900w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Control-Multiple-Outputs-Web-Socket-Web-Server-ESP32.png?resize=300%2C225&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/01\/Control-Multiple-Outputs-Web-Socket-Web-Server-ESP32.png?resize=768%2C575&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 900px) 100vw, 900px\" \/><\/figure><\/div>\n\n\n<p>To see the web server working, you can connect 4 LEDs to your ESP32 on GPIOS: 2, 4, 12 and 14. You should be able to control those outputs from the web server.<\/p>\n\n\n\n<p>If you need to update something on your project, you just need to go to your ESP32 IP address followed by <span class=\"rnthl rntliteral\">\/update<\/span>. <\/p>\n\n\n\n<p>Congratulations! You&#8217;ve successfully uploaded files to the ESP32 filesystem using ElegantOTA.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Watch the Video Demonstration<\/h2>\n\n\n<p style=\"text-align:center\"><iframe width=\"720\" height=\"405\" src=\"https:\/\/www.youtube.com\/embed\/LUcKoJGX38M?rel=0\" frameborder=\"0\" allowfullscreen><\/iframe><\/p>\n\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 add OTA capabilities to your Async Web Servers using the <a href=\"https:\/\/github.com\/ayushsharma82\/ElegantOTA\" target=\"_blank\" rel=\"noreferrer noopener\">AsyncElegantOTA library<\/a>. This library is super simple to use and allows you to upload new firmware or files to the filesystem effortlessly using a web page. In our opinion, the AsyncElegantOTA library is one of the best options to handle OTA web updates.<\/p>\n\n\n\n<p>We hope you&#8217;ve found this tutorial useful. <\/p>\n\n\n\n<p>Learn everything you need to know about building web servers with the ESP32:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><a href=\"https:\/\/randomnerdtutorials.com\/build-web-servers-esp32-esp8266-ebook\/\">Build ESP32 Web Servers with Arduino IDE (eBook)<\/a><\/strong><\/li>\n<\/ul>\n\n\n\n<p>Learn more about the ESP32 with our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a style=\"font-size: inherit; background-color: initial;\" href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\">Learn ESP32 with Arduino IDE<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32\/\">More ESP32 Projects and Tutorials&#8230; <\/a><\/li>\n<\/ul>\n\n\n\n<p>Thanks for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this guide, you&#8217;ll learn how to do over-the-air (OTA) updates to your ESP32 boards using the AsyncElegantOTA library and VS Code with PlatformIO. The Async Elegant OTA library creates &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32 OTA (Over-the-Air) Updates &#8211; AsyncElegantOTA (VS Code + PlatformIO)\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-ota-over-the-air-vs-code\/#more-101731\" aria-label=\"Read more about ESP32 OTA (Over-the-Air) Updates &#8211; AsyncElegantOTA (VS Code + PlatformIO)\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":101740,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[281,276,277,299,264],"tags":[],"class_list":["post-101731","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32-project","category-esp32","category-esp32-arduino-ide","category-0-esp32","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/Async-WebOTA-Updates-ESP32-VS-Code-PlatformIO.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\/101731","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=101731"}],"version-history":[{"count":5,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/101731\/revisions"}],"predecessor-version":[{"id":159032,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/101731\/revisions\/159032"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/101740"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=101731"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=101731"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=101731"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}