ESP8266 NodeMCU OTA (Over-the-Air) Updates – ElegantOTA Library with Arduino IDE

This tutorial shows how to do OTA (over-the-air) updates to your ESP8266 NodeMCU boards using the ElegantOTA library (V3 version) with Arduino IDE. This library sets up a web server that lets you update the firmware (a new sketch) on your board wirelessly. This way, you don’t need a connection between the ESP8266 and your computer to upload a new sketch.

ESP8266 NodeMCU OTA (Over-the-Air) Updates – ElegantOTA Library with Arduino IDE

By the end of this tutorial, you’ll be able to easily add OTA capabilities to your web server projects with the ESP8266 to upload new firmware wirelessly in the future.

Table Of Contents

Throughout this tutorial, we’ll cover:

We recommend that you follow all the tutorial steps to understand how the ElegantOTA library works and how you can use it in your projects. To demonstrate how to do this, we’ll upload files to build different web server projects.

ESP8266 OTA (Over-the-Air) Programming

OTA (Over-the-Air) update is the process of loading new firmware to the ESP8266 board using a Wi-Fi connection rather than a serial communication. This functionality is extremely useful in case of no physical access to the ESP8266 board. You don’t need a connection between your computer and the board to upload new code.

Async ElegantOTA Web Server How it Works ESP8266

There are different ways to perform OTA updates. In this tutorial, we’ll cover how to do that using the ElegantOTA library (version V3 — this is the successor of the deprecated AsyncElegantOTA library). In our opinion, this is one of the best and easiest ways to perform OTA updates.

The ElegantOTA library creates a web server that you can access on your local network to upload new firmware or files to the filesystem (SPIFFS or LittleFS). The files you upload should be in .bin format. We’ll show you later in this tutorial how to convert your files to .bin format.

The only disadvantage of OTA programming is that you need to add the code for OTA in every sketch you upload so that you’re able to use OTA in the future. In case of the ElegantOTA library, it consists of just three lines of code.

ElegantOTA Library

ElegantOTA logo

Here are some great features of this library:

  • It is compatible with the built-in ESP8266WebServer.h library and with several forks of the ESPAsyncWebServer library.
  • You just need to add three lines of code to add OTA capabilities to your “regular” web server;
  • It allows you to update not only new firmware to the board but also files to the ESP8266 filesystem (LittleFS or SPIFFS);
  • It provides a beautiful and modern web server interface;
  • It is available as a pro paid version that adds more features.

OTA Updates with the ElegantOTA Library – Quick Summary

To add OTA capabilities to your projects using the ElegantOTA library, follow these steps:

1) Install the ElegantOTA, ESPAsyncTCP, and ESPAsyncWebServer libraries;

2) Include ElegantOTA library at the top of the Arduino sketch:

#include <ElegantOTA.h>;

3) Add the following line in the setup before server.begin();

ElegantOTA.begin(&server);

4) In the loop(), add the following line:

ElegantOTA.loop();

5) Open your browser and go to http://<IPAddress>/update, where <IPAddress> is your ESP8266 IP address to access the web server page for the OTA updates.

Continue reading the tutorial for more detailed steps.

How does OTA Web Updater Work?

The first sketch must be uploaded using a serial connection. This sketch should include the code to set up the OTA Web Updater, allowing you to upload new sketches through a web browser.

The OTA Web Updater creates a web server where you can upload sketches wirelessly.

If your code doesn’t include an OTA routine, you won’t be able to use the web server to upload new sketches wirelessly.

After that, make sure every sketch you upload includes OTA routines so you can continue updating the board wirelessly in the future.

Installing the ElegantOTA Library

To install the ElegantOTA library in the Arduino IDE go to Sketch > Include Library > Manage Libraries, search for ElegantOTA and install the ElegantOTA library by Ayush Sharma.

Installing ElegantOTA Library Arduino IDE

Enabling Async Mode

For the ElegantOTA library to work in async mode (with the ESPAsyncWebServer library), you need to do the following procedure.

1) Go to your Arduino libraries directory.

2) Open the ElegantOTA folder and then open the src folder.

3) Locate the ELEGANTOTA_USE_ASYNC_WEBSERVER macro in the ElegantOTA.h file, and set it to 1 as follows:

#define ELEGANTOTA_USE_ASYNC_WEBSERVER 1
elegantota library enable async mode

4) Save the changes to the ElegantOTA.h file.

5) Now you can use the ElegantOTA in async mode for your OTA updates and with the ESPAsyncWebServer library.

Install ESPAsyncTCP and ESPAsyncWebServer Libraries

To test the examples in this tutorial, you also need to install the ESPAsyncTCP and the ESPAsyncWebServer libraries.

Note: the ElegantOTA library works with different forked versions of the ESPAsyncWebServer and the ESPAsyncTCP web server libraries, so you don’t necessarily need to use the same ones that we’re using.

Follow the next instructions to install those libraries.

Click the links below to download the libraries’ .zip folders.

These libraries aren’t available to install through the Arduino Library Manager, so you need to copy the library .zip files to the Arduino Installation Libraries folder. Alternatively, in your Arduino IDE, you can go to Sketch Include Library > Add .zip Library and select the libraries you’ve just downloaded.

ElegantOTA ESP8266 Basic Example

Let’s start with a basic example (based on one of the library’s examples). The following code creates a simple web server with the ESP32. The root URL displays some text, and the /update URL displays the interface to update the firmware and the filesystem.

Copy the following code to your Arduino IDE.

/*********
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/esp8266-nodemcu-ota-elegantota-arduino/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Softwar
*********/

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ElegantOTA.h>

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

AsyncWebServer server(80);

void setup(void) {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
    request->send(200, "text/plain", "Hi! I am ESP8266.");
  });

  server.begin();
  Serial.println("HTTP server started");

  ElegantOTA.begin(&server);    // Start ElegantOTA
}

void loop(void) {
  ElegantOTA.loop();

}

View raw code

Insert your network credentials and the code should work straight away.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

How Does the Code Work?

Start by including the required libraries.

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ElegantOTA.h>

Insert your network credentials in the following variables so that the ESP32 can connect to the Wi-Fi on your local network.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Create an AsyncWebServer object on port 80:

AsyncWebServer server(80);

In the setup(), initialize the Serial Monitor:

Serial.begin(115200);

Initialize Wi-Fi:

WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");

// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());

Then, handle the client requests. The following lines, send some text Hi! I am ESP8266 when you access the root (/) URL:

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
  request->send(200, "text/plain", "Hi! I am ESP8266.");
});

If your web server needs to handle more requests you can add them (we’ll show you in the next example).

Initialize the server:

server.begin();

Then, add the next line to start ElegantOTA:

ElegantOTA.begin(&server);    // Start ElegantOTA

In the loop(), add the following line:

ElegantOTA.loop();

Accessing the Web Server

After uploading code to the board, open the Serial Monitor at a baud rate of 115200. Press the ESP8266 on-board RST button. It should display the ESP IP address as follows (yours may be different):

ESP8266 ElegantOTA Web Server Getting the IP Address Serial Monitor

In your local network, open your browser and type the ESP8266 IP address. You should get access the root (/) web page with some text displayed.

ESP8266 NodeMCU Web Server Basic OTA

Now, if you want to modify your web server code via OTA, go to the ESP IP address followed by /update. The following web page should load.

ElegantOTA Web Server Page ESP8266

To upload new code to your board or files to the filesystem, you need to upload them in .bin format. Follow the next section to learn how to generate a .bin file from your sketch in Arduino IDE.

Upload New Code to the ESP8266 via OTA

Every file that you upload via OTA should be in .bin format. You can generate a .bin file from your sketch using the Arduino IDE.

With your sketch opened, you just need to select the ESP8266 board you’re using in Tools > Board, and then go to Sketch Export Compiled Binary. A .bin file will be generated from your sketch.

Arduino IDE, expor bin file

The generated file will be saved under your project folder inside a series of other folders. The file with the .ino.bin extension is the one you should upload to your board using the ElegantOTA web page.

Upload a New Web Server Sketch via OTA – 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 this project. Here are the steps you need to follow:

1. Copy the following code to your Arduino IDE. Don’t forget to insert your network credentials.

/*********
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/esp8266-nodemcu-ota-elegantota-arduino/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Softwar
*********/

// Import required libraries
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ElegantOTA.h>

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

bool ledState = 0;
const int ledPin = 2;

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <title>ESP Web Server</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" href="data:,">
  <style>
  html {
    font-family: Arial, Helvetica, sans-serif;
    text-align: center;
  }
  h1 {
    font-size: 1.8rem;
    color: white;
  }
  h2{
    font-size: 1.5rem;
    font-weight: bold;
    color: #143642;
  }
  .topnav {
    overflow: hidden;
    background-color: #143642;
  }
  body {
    margin: 0;
  }
  .content {
    padding: 30px;
    max-width: 600px;
    margin: 0 auto;
  }
  .card {
    background-color: #F8F7F9;;
    box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
    padding-top:10px;
    padding-bottom:20px;
  }
  .button {
    padding: 15px 50px;
    font-size: 24px;
    text-align: center;
    outline: none;
    color: #fff;
    background-color: #0f8b8d;
    border: none;
    border-radius: 5px;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    -webkit-tap-highlight-color: rgba(0,0,0,0);
   }
   /*.button:hover {background-color: #0f8b8d}*/
   .button:active {
     background-color: #0f8b8d;
     box-shadow: 2 2px #CDCDCD;
     transform: translateY(2px);
   }
   .state {
     font-size: 1.5rem;
     color:#8c8c8c;
     font-weight: bold;
   }
  </style>
<title>ESP Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
</head>
<body>
  <div class="topnav">
    <h1>ESP WebSocket Server</h1>
  </div>
  <div class="content">
    <div class="card">
      <h2>Output - GPIO 2</h2>
      <p class="state">state: <span id="state">%STATE%</span></p>
      <p><button id="button" class="button">Toggle</button></p>
    </div>
  </div>
<script>
  var gateway = `ws://${window.location.hostname}/ws`;
  var websocket;
  window.addEventListener('load', onLoad);
  function initWebSocket() {
    console.log('Trying to open a WebSocket connection...');
    websocket = new WebSocket(gateway);
    websocket.onopen    = onOpen;
    websocket.onclose   = onClose;
    websocket.onmessage = onMessage; // <-- add this line
  }
  function onOpen(event) {
    console.log('Connection opened');
  }
  function onClose(event) {
    console.log('Connection closed');
    setTimeout(initWebSocket, 2000);
  }
  function onMessage(event) {
    var state;
    if (event.data == "1"){
      state = "ON";
    }
    else{
      state = "OFF";
    }
    document.getElementById('state').innerHTML = state;
  }
  function onLoad(event) {
    initWebSocket();
    initButton();
  }
  function initButton() {
    document.getElementById('button').addEventListener('click', toggle);
  }
  function toggle(){
    websocket.send('toggle');
  }
</script>
</body>
</html>)rawliteral";

void notifyClients() {
  ws.textAll(String(ledState));
}

void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {
  AwsFrameInfo *info = (AwsFrameInfo*)arg;
  if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
    data[len] = 0;
    if (strcmp((char*)data, "toggle") == 0) {
      ledState = !ledState;
      notifyClients();
    }
  }
}

void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type,
             void *arg, uint8_t *data, size_t len) {
  switch (type) {
    case WS_EVT_CONNECT:
      Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
      break;
    case WS_EVT_DISCONNECT:
      Serial.printf("WebSocket client #%u disconnected\n", client->id());
      break;
    case WS_EVT_DATA:
      handleWebSocketMessage(arg, data, len);
      break;
    case WS_EVT_PONG:
    case WS_EVT_ERROR:
      break;
  }
}

void initWebSocket() {
  ws.onEvent(onEvent);
  server.addHandler(&ws);
}

String processor(const String& var){
  Serial.println(var);
  if(var == "STATE"){
    if (ledState){
      return "ON";
    }
    else{
      return "OFF";
    }
  }
  return String();
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);

  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  // Print ESP Local IP Address
  Serial.println(WiFi.localIP());

  initWebSocket();

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });

  // Start server
  server.begin();
  ElegantOTA.begin(&server);    // Start ElegantOTA
}

void loop() {
  ws.cleanupClients();
  digitalWrite(ledPin, !ledState);
  ElegantOTA.loop();
}

View raw code

This is the same code used in this project, but it contains the needed lines of code to handle ElegantOTA:

#include <ElegantOTA.h>
ElegantOTA.begin(&server);
ElegantOTA.loop();

2. Save your sketch: File > Save and give it a name. For example: ESP8266_WebServer_LED_OTA.

3. Generate a .bin file from your sketch. First, select the board model you’re using in Tools > Board. Then, go to Sketch > Export Compiled Binary.

Arduino IDE, export bin file

Go to your sketch folder. You should have a build folder. Inside that folder, you’ll have another folder related to your board model. Open that folder. There’ll be several files. You should upload the file with the ino.bin extension.

bin file for ESP8266 OTA updates

4. Now, you need to upload that file using the ElegantOTA page. Go to your ESP IP address followed by /update. Make sure you have the firmware option selected. Click on Choose File and select the .ino.bin file you’ve just generated.

ESP8266 ElegantOTA Uploading new firmware

5. After a few seconds, you should get a success message. Then, click on the Back button.

ESP8266 ElegantOTA Upload new Firmware Success

6. Now, you can go to the root (/) URL to access the new web server. This is the page you should see when you access the ESP IP address on the root (/) URL.

ESP8266 Websocket server - control outputs

You can click on the button to turn the ESP8266 on-board LED on and off.

ESP8266 NodeMCU onboard LED on

Because we’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 ESP8266 IP address followed by /update.

Congratulations, you’ve uploaded new code to your ESP8266 via Wi-Fi using ElegantOTA.

Wrapping Up

In this tutorial you’ve learned how to add OTA capabilities to your Async Web Server projects using the ElegantOTA library on the ESP8266 board. This library is straightforward to use—you just need to add three lines of code to your project.

We hope you’ve found this tutorial useful.

Learn more about the ESP8266 with our resources:

Thanks for reading.



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our newsletter!

4 thoughts on “ESP8266 NodeMCU OTA (Over-the-Air) Updates – ElegantOTA Library with Arduino IDE”

  1. There is no code in the first code-block in this chapter: “ElegantOTA ESP8266 Basic Example” and the button “View raw code” leads only to the top of the page.

    Reply
  2. // Route for root / web page
    server.on(“/”, HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, “text/html”, index_html, processor);
    });
    need send_P

    Reply

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.