In this guide, you’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 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.
Additionally, with this library, you can also upload new files to the ESP32 filesystem (SPIFFS). The library is very easy to use and it’s compatible with the ESPAsyncWebServer library that we use often to build web server projects.
By the end of this tutorial, you’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.
Recommended reading: Getting Started with VS Code and PlatformIO IDE for ESP32 and ESP8266
We have a similar tutorial for the ESP8266 NodeMCU board: ESP8266 NodeMCU OTA (Over-the-Air) Updates – AsyncElegantOTA (VS Code + PlatformIO)
Overview
This tutorial covers:
- Add the ElegantOTA feature to your ESP32 web server
- Upload new firmware via OTA to ESP32 board
- Upload files to SPIFFS via OTA to ESP32 board
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’ll upload files to build different web server projects.
ESP32 OTA (Over-the-Air) Programming
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.
There are different ways to perform OTA updates. In this tutorial, we’ll cover how to do that using the AsyncElegantOTA library. In our opinion, this is one of the best and easiest ways to perform OTA updates.
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 .bin format. We’ll show you later in the tutorial how to get 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 the case of the AsyncElegantOTA library, it consists of just three lines of code.
AsyncElegantOTA Library
As mentioned previously, there are different alternatives for OTA programming with the ESP32 boards. For example, in the Arduino IDE, under the Examples folder, there is the BasicOTA example (that never worked well for us); the OTA Web Updater (works well, but it is difficult to integrate with web servers using the ESPAsyncWebServer library); and many other examples from different libraries.
Most of our web server projects with the ESP32 use the ESPAsyncWebServer library. So, we wanted a solution that was compatible with that library. The AsyncElegantOTA library is just perfect for what we want:
- It is compatible with the ESPAsyncWebServer library;
- You just need to add three lines of code to add OTA capabilities to your “regular” Async Web Server;
- It allows you to update not only new firmware to the board, but also files to the ESP32 filesystem (SPIFFS);
- It provides a beautiful and modern web server interface;
- It works extremely well.
If you like this library and you’ll use it in your projects, consider supporting the developer’s work.
OTA Updates with AsyncElegantOTA Library – Quick Summary
To add OTA capabilities to your projects using the AsyncElegantOTA library, follow these steps:
- Iclude the AsyncElegantOTA, AsyncTCP and ESPAsyncWebServer libraries in the platformio.ini file of your project;
- Include AsyncElegantOTA library at the top of the code: #include <AsyncElegantOTA.h>;
- Add this line AsyncElegantOTA.begin(&server); before server.begin();
- Open your browser and go to http://<IPAddress>/update, where <IPAddress> is your ESP32 IP address.
Continue reading the tutorial for more detailed steps.
How does OTA Web Updater Work?
- 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.
- The OTA Web Updater sketch creates a web server you can access to upload a new sketch via a web browser.
- Then, you need to implement OTA routines in every sketch you upload, so that you’re able to do the next updates/uploads over-the-air.
- If you upload a code without an OTA routine you’ll no longer be able to access the web server and upload a new sketch over-the-air.
Install AsyncElegantOTA Library (VS Code + PIO)
In this tutorial, we’ll use VS Code + PIO to program the ESP32. If you want to use Arduino IDE, follow the next tutorial: ESP32 OTA (Over-the-Air) Updates – AsyncElegantOTA using Arduino IDE.
To use the AsyncElegantOTA library, include it in your platformio.ini file. You also need to include the ESPAsyncWebServer library. Add these libraries as follows:
lib_deps = ESP Async WebServer
ayushsharma82/AsyncElegantOTA @ ^2.2.5
AsyncElegantOTA ESP32 Basic Example
If you’re using an ESP32, you need to downgrade your ESP32 boards’ 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: ElegantOTA V3.
Let’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 /update URL displays the interface to update the firmware and the filesystem.
Edit your platformio.ini file so that it looks as follows:
[env:esp32doit-devkit-v1]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
monitor_speed = 115200
lib_deps = ESP Async WebServer
ayushsharma82/AsyncElegantOTA @ ^2.2.5
Copy the following code to the main.cpp file.
/*
Rui Santos
Complete project details
- Arduino IDE: https://RandomNerdTutorials.com/esp32-ota-over-the-air-arduino/
- VS Code: https://RandomNerdTutorials.com/esp32-ota-over-the-air-vs-code/
This sketch shows a Basic example from the AsyncElegantOTA library: ESP32_Async_Demo
https://github.com/ayushsharma82/AsyncElegantOTA
*/
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.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 ESP32.");
});
AsyncElegantOTA.begin(&server); // Start ElegantOTA
server.begin();
Serial.println("HTTP server started");
}
void loop(void) {
}
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 the Code Works
First, include the necessary libraries:
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.h>
Insert your network credentials in the following variables so that the ESP32 can connect to 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 ESP32. when you access the root (/) URL:
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(200, "text/plain", "Hi! I am ESP32.");
});
If your web server needs to handle more requests you can add them (we’ll show you in the next example).
Then, add the next line to start ElegantOTA:
AsyncElegantOTA.begin(&server); // Start ElegantOTA
Finally, initialize the server:
server.begin();
Access the Web Server
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):
In your local network, open your browser and type the ESP32 IP address. You should get access the root (/) web page with some text displayed.
Now, imagine that you want to modify your web server code. To do that via OTA, go to the ESP IP address followed by /update. The following web page should load.
Follow the next sections to learn how to upload new firmware using the AsyncElegantOTA.
Upload New Firmware OTA (Over-the-Air) Updates – ESP32
Every file that you upload via OTA should be in .bin format. VS Code automatically generates the .bin file for your project when you compile the code. The file is called firmware.bin and it is saved on your project folder on the following path (or similar depending on the board you’re using):
.pio/build/esp32doit-devkit-v1/firmware.bin
That’s that .bin file you should upload using the AsyncElegantOTA web page if you want to upload new firmware.
Upload a New Web Server Sketch
Let’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 this project. Here’s the steps you need to follow:
1. Copy the following code to your main.cpp file. Don’t forget to insert your network credentials.
/*
Rui Santos
Complete project details
- Arduino IDE: https://RandomNerdTutorials.com/esp32-ota-over-the-air-arduino/
- VS Code: https://RandomNerdTutorials.com/esp32-ota-over-the-air-vs-code/
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 Software.
*/
// Import required libraries
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.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 ElegantOTA
AsyncElegantOTA.begin(&server);
// Start server
server.begin();
}
void loop() {
ws.cleanupClients();
digitalWrite(ledPin, ledState);
}
This is the same code used in this project, but it contains the required lines of code to handle ElegantOTA:
#include <AsyncElegantOTA.h>
AsyncElegantOTA.begin(&server);
2. Edit your platformio.ini file as follows:
[env:esp32doit-devkit-v1]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
monitor_speed = 115200
lib_deps = ESP Async WebServer
ayushsharma82/AsyncElegantOTA @ ^2.2.5
2. Save and compile your code – click on the Build icon.
3. Now, in the Explorer tab of VS Code, you can check that you have a firmware.bin file under the project folder on the following path (or similar):
.pio/build/esp32doit-devkit-v1/firmware.bin
4. Now, you just 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.
5. Click on Choose File, navigate through the folder on your computer and select the file of your project.
6. Wait until the progress bar reaches 100%.
7. When it’s finished, click on the Back button.
8. Then, you can go to the root (/) 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 (/) URL.
You can click on the button to turn the ESP32 on-board LED on and off.
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 ESP32 IP address followed by /update.
Congratulations, you’ve uploaded new code to your ESP32 via Wi-Fi using ElegantOTA.
Continue reading if you want to learn how to upload files to the ESP32 filesystem (SPIFFS) using AsyncElegantOTA.
Upload Files to Filesystem OTA (Over-the-Air) Updates – ESP32
In this section you’ll learn to upload files to the ESP32 filesystem (SPIFFS) using AsyncElegantOTA.
Web Server with Files from SPIFFS
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.
To show you how to do this, we’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.
Copy the following code to your main.cpp file.
/*
Rui Santos
Complete project details
- Arduino IDE: https://RandomNerdTutorials.com/esp32-ota-over-the-air-arduino/
- VS Code: https://RandomNerdTutorials.com/esp32-ota-over-the-air-vs-code/
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 Software.
*/
// Import required libraries
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include "SPIFFS.h"
#include <Arduino_JSON.h>
#include <AsyncElegantOTA.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
// Create a WebSocket object
AsyncWebSocket ws("/ws");
// Set number of outputs
#define NUM_OUTPUTS 4
// Assign each GPIO to an output
int outputGPIOs[NUM_OUTPUTS] = {2, 4, 12, 14};
// Initialize SPIFFS
void initSPIFFS() {
if (!SPIFFS.begin(true)) {
Serial.println("An error has occurred while mounting SPIFFS");
}
Serial.println("SPIFFS mounted successfully");
}
// Initialize WiFi
void initWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi ..");
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(1000);
}
Serial.println(WiFi.localIP());
}
String getOutputStates(){
JSONVar myArray;
for (int i =0; i<NUM_OUTPUTS; i++){
myArray["gpios"][i]["output"] = String(outputGPIOs[i]);
myArray["gpios"][i]["state"] = String(digitalRead(outputGPIOs[i]));
}
String jsonString = JSON.stringify(myArray);
return jsonString;
}
void notifyClients(String state) {
ws.textAll(state);
}
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, "states") == 0) {
notifyClients(getOutputStates());
}
else{
int gpio = atoi((char*)data);
digitalWrite(gpio, !digitalRead(gpio));
notifyClients(getOutputStates());
}
}
}
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);
}
void setup(){
// Serial port for debugging purposes
Serial.begin(115200);
// Set GPIOs as outputs
for (int i =0; i<NUM_OUTPUTS; i++){
pinMode(outputGPIOs[i], OUTPUT);
}
initSPIFFS();
initWiFi();
initWebSocket();
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/index.html", "text/html",false);
});
server.serveStatic("/", SPIFFS, "/");
// Start ElegantOTA
AsyncElegantOTA.begin(&server);
// Start server
server.begin();
}
void loop() {
ws.cleanupClients();
}
Insert your network credentials in the following variables and save the code.
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Edit your platformio.ini file so that it looks as follows:
[env:esp32doit-devkit-v1]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
monitor_speed = 115200
lib_deps = ESP Async WebServer
arduino-libraries/Arduino_JSON @ 0.1.0
ayushsharma82/AsyncElegantOTA @ ^2.2.5
Update Firmware
After inserting your network credentials, save and compile the code.
Go to the ESP IP address followed by /update and upload the new firmware as shown previously.
Next, we’ll see how to upload the files to the filesystem.
Update Filesystem
Under the project folder create a folder called data and paste the following HTML, CSS and JavaScript files (click on the links to download the files):
In VS Code, click on to the PIO icon and go to Project Tasks > env:esp32doit-devkit-v1 (or similar) >Platform > Build Filesystem Image. This will create a .bin file from the files saved in the data folder.
After building the filesystem image, you should have a spiffs.bin file in the following path (or similar):
.pio/build/esp32doit-devkit-v1/spiffs.bin
That’s that file that you should upload to update the filesystem.
Go to your ESP IP address followed by /update. Make sure you have the Filesystem option selected and select the spiffs.bin file.
After successfully uploading, click the Back button. And go to the root (/) URL again.
You should get access to the following web page that controls the ESP32 outputs using Web Socket protocol.
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.
If you need to update something on your project, you just need to go to your ESP32 IP address followed by /update.
Congratulations! You’ve successfully uploaded files to the ESP32 filesystem using ElegantOTA.
Watch the Video Demonstration
Wrapping Up
In this tutorial, you’ve learned how to add OTA capabilities to your Async Web Servers using the AsyncElegantOTA library. 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.
We hope you’ve found this tutorial useful.
Learn everything you need to know about building web servers with the ESP32:
Learn more about the ESP32 with our resources:
Thanks for reading.
Great!
It’s a shame it doesn’t work with BT.
I found this to be more work, locating the bin file and uploading over the web page.
I use the Basic OTA format and added two lines to the platformio.ini file.
upload_protocol = espota
upload_port = 192.168.4.1
I just hit build and then upload from PlatformIO and it works perfectly .
before I added the two lines I had trouble also with the Basic OTA .
Hope the info above helps others having Basic OTA upload problems.
Thanks for posting the PlatformIO instructions! I hadn’t heard of AsyncElegantOTA before.
Though not so much of a problem for hobby projects, it’s too bad AsyncElegantOTA has no security, so anyone can modify the firmware. It seems to be a common problem, though ArduinoOTA at least allows a password. Ideally a verified digital signature would be required to complete an update.
The ESP32 supposedly has secure boot, but I’ve never tried it. But if an OTA library changes the firmware, I don’t know that it validates an update, so possibly could brick the device.
The trouble with these easy/elegant libraries is that they hide the behavior along with complexity. So it’s unclear if they use the Espressif OTA APIs. Perhaps security is just too complex for the usual RNT reader, but seems like a nice topic to cover.
These days we should be including security as part of the design, and if hobbyists know about security (and integrity) then the professional developers and generic IoT manufacturers will be less likely to make stupid security mistakes.
Hey Carl.
AsyncElegantOTA does come with a username and password authentication 🙂
You will just have to dig through the source code. I’ll add it in the documentation too.
AsyncElegantOTA.begin(&server, “username”, “password”);
Hey, thanks for following and thanks for the work on AsyncElegantOTA!
Ah, I see it uses the http authentication via the browser– easier than adding extra form fields.
Yes, it would be good to show the optional begin() on the main README.md
This example does not work for me at the moment. I am getting library errors so it looks the current library versions are not compatible anymore.
Hi.
What errors do you get?
Regards,
Sara
.pio/libdeps/esp32-c3-devkitm-1/ESP Async WebServer/src/ESPAsyncWebServer.h:33:10: fatal error: AsyncTCP.h: No such file or directory
How does your platformio.ini file look like?
[env:esp32-c3-devkitm-1]
platform = espressif32
board = esp32-c3-devkitm-1
framework = arduino
lib_deps = ESP Async WebServer
ayushsharma82/AsyncElegantOTA @ ^2.2.5
monitor_speed = 115200
Try to also include the AsynTCP library on the platformio.ini file.
Regards,
Sara
In that case I am getting the error:
.pio/libdeps/esp32-c3-devkitm-1/ESP Async WebServer/src/AsyncWebSocket.cpp:840:28: error: call of overloaded ‘IPAddress(unsigned int)’ is ambiguous
In your platformio-ini file change platform = espressif32
to platform = [email protected]
Yes, now it is working with my WROVER chip! However with the C3 I am getting a message that Elegant OTA is not supported.
Can the suffix “update” be user changeable to a user code. Then the OTA page is reached only by using this user set code word.
As a new user of ESP the Ayush Elegant code is too complex for me presently to try the change myself.
Thanks for this elegant code and for the tutorial
The “/update” in src/AsyncElegantOTA.h (3 places) can be easily changed in the source code, but I presume the HTML in src/elegantWebpage.h also has “/update” for the form URL, and this is gzipped. So you have to write a script to convert the uint8_t decimal numbers to bytes, then use gunzip, edit, then gzip, and convert bytes back to uint8_t decimal numbers.
If you want to change the HTML layout on the update form, you’d need to do the same on src/elegantWebpage.h.
I don’t know if there is a utility to convert the decimal array to/from bytes. For me, it’s faster to write a perl script than search for a command.
Usually, programmers are too lazy to gzip the static HTML, even though it’s faster and saves space. Nice that Ayush does that, but maybe knows a nice utility.
I’ll considered adding the custom url at earlier stages but soon went into a rabbit hole of “how the compressed webpage can know the URL too?”
I’ve included the source code of the webpage in the ‘ui’ folder of the repository. The webpage is based on vuejs so you will have to compile it to reflect the changes in the code as well.
For my projects where I use Vuejs, I’ve a custom compress & conversion utility bundled with it.
It will automatically update the elegantWebpage.h upon running
npm run build
.For general purpose uses:
I do have a utility where people can gzip and convert their own webpage into bytes:
https://ayushsharma82.github.io/file2raw/
Have fun!
Hi Ayush Sharma,
Can I use your WebSerial with the above AsyncElegantOTA they both appear to point to the same server, I was wonder if there is any know conflicts .
AsyncElegantOTA.begin(&server);
WebSerial.begin(&server);
PlatformIO.ini
ayushsharma82/WebSerial@^1.1.0
ayushsharma82/AsyncElegantOTA @ ^2.2.5
Thanks !
Yes, you can.
You can use my whole suite of ESP libraries with each other.
AsyncElegantOTA
WebSerial
ESP-DASH
Excellent Thank you !
Could anyone comment on using this solution if I already have EspNow in use, which is a requirement for my project? Thanks.
It works perfect with “standard” ESP32 modules, but it fails for ESP32 CAM ( AI thinker). Or got s.o. else it running with ESP32 CAM?
For OTA upload with ESP32-CAM, it is necessary to change the partition table, according to the guidance on this website: husarnet.com/blog/internet-ota-esp32/.
Thanks so much for this info.
But, have you tried yourself to burn a firmware on ESP32 CAM Al-thinker yourself?
I’m using the Arduino IDE. So I modified the default.csv in espressif/esp32/tools/patititions with the parameters listet in https://husarnet.com/blog/internet-ota-esp32/ — without success. What else needs to be modified? Maybe I have to use platformio?
I could solve it with the Arduino IDE. I just used the “ESP32 Dev Module” as board instead of “AI Thinker” and selected “Minimal SPIFFS (1.9MB APP with OTA/190kB SPIFFS)” as partition scheme. That’s all. No problems uploading 1 MB bon code.
Thank you very much. You gave an vital information.
I changed this line in the example code, to make it automatically redirect to the “/update” page:
server.on("/",[]() {
server.sendContent("<html><head><meta http-equiv=\"Refresh\" content=\"0; url='/update'\"/></head></html>");
});
How can I enable ElegantOTA to work over the internet. I want to be able to update the ESP8266 on a different network, a place that is miles away from my computer. How can I achieve this?
Also, if updating over the internet is possible, how can I update multiple ESP8266 at once?
I just got the sketch to work, and i can see the “Hi! I am ESP32” when i type the ESP IP, but if I add “/update” the webpage doesn’t load.
anyideas on why this coud happen?
Great tutorial, thanks so far, but I have a basic difficulty that I would appreciate some help with.
I’m stuck on step 5 of the ‘Upload a New Web Server Sketch’ section of this tutorial. It says “Click on Choose File, navigate through the folder on your computer and select the file of your project.”
My computer is an iMac, running MacOS Big Sur version 11.3, and I cannot find a file with the name ‘firmware.bin’ anywhere in my project directory, or anywhere else on the computer. I do however see firmware.bin, and all the other files listed, in the EXPLORER column under PIO Home in the Visual Studio Code window. Hence I cannot choose it from the ElegantOTA window which opens as expected on the Web client. The code example does work if I upload it to my Nodemcu-32s board over the USB link.
Could there be some irregularities here with this particular Mac OS version, does anyone know?
Thanks,
John.
Hi John.
MacOS Big Sur might have some incompatibilities, but I’m not sure about this problem.
Maybe it is better to try to post an issue on the PlatformIO forum: https://community.platformio.org/
Regards,
Sara
Thanks Sara, I did that and the answer is of course obvious ….
firmware.bin is a hidden file on Mac, so in the ElegantOTA window one needs to use the command, shift and dot keys (simultaneously) in the Choose File procedure. All works well now, thanks!
Great!
Thanks for sharing the solution. It may be useful for other readers.
Regards,
Sara
Hello, I will like to implement this in my project but my question is… the ssid and password defined in the sketch have to be “my home network” ?
in other words, the ESP32 is not creating their own network, isn’t it?
Also I would like to know if the server is everytime accessible because I’m not using Wifi anymore in the project so maybe there are a way to turn off the server after a time and save battery?
Hi.
In this particular project, it is not creating its network. It is set as a station.
Yes, you can turn off wi-fi if you don’t need it: https://github.com/espressif/arduino-esp32/issues/1077
You can also take a look at this tutorial to learn more about WiFi: https://randomnerdtutorials.com/esp32-useful-wi-fi-functions-arduino/
Regards,
Sara
Hi, how to put a physical button to also activate the led?
Hi.
You can check this tutorial: https://randomnerdtutorials.com/esp32-esp8266-web-server-physical-button/
It uses a different method, but it works.
Regards,
Sara
Sara/Rui,
Are you aware that
is a copy of your tutorial?
Hi.
Unfortunately, that website copies a lot of our tutorials.
There’s nothing we can do. We hope that people understand that ours are the original tutorials.
Thanks for reporting.
Regards,
Sara
Ethernet – Does OTA works also via Ethernet ?
I have an ESP32 PoE from Olimex and would
love to do OTA via Ethernet.
Anybody did this before ?
btw – great web site !
brgds Mike
Thanks.
Unfortunately, I never tried it.
You’ll have to try it yourself and see if it works.
Regards,
Sara
Hi,
It would appear that “AsyncElegantOTA.loop();” is no longer required in the main loop.
Thoughts?
Is there a way to use the ElegantOTA framework with an SD filesystem rather than SPIFFS? I ask because I’m working on a project where we have a 16GB SD card available and the web interface uses some rather large javascript libraries.
Thanks!
Hi.
I’m not sure, but you can ask on the library Github page: https://github.com/ayushsharma82/ElegantOTA
Regards,
Sara
Rui, Sara,
Great tutorial thanks for that. It works very well and your explanations help a lot.
I am getting following warning when I build it in VS-Code with platformio:
“warning: #warning AsyncElegantOTA.loop(); is deprecated, please remove it from loop() if defined. This function will be removed in a future release. [-Wcpp]”
Will there be a future replacement for that?
Cheers Roger
Hi.
You don’t need to worry about that.
Just make sure you’re not using that command AsyncElegantOTA.loop() in the loop() and it will be removed in future releases of the library.
If you don’t have that line in your code, you’re just fine. You can ignore the warning.
Regards,
Sara
Hi I had a problem with this warning too, it compiles but the warning stays on there – The warning is actually a line of code clearly marked at the top of
AsyncElegantOTA.h in the library I removed it and the warning went away.
I’m using VS-Code with platformio also.
Cheers
Green
Hello. May I know if there’s tutorial to get data transfer from ESP32 to our device via WiFi/Bluetooth?
Hi !
Thank you for the tutorial ! Your entire work helps me a lot on my projects!
I never had a problem before while following your tutorials, but now I have one! :p
My .bin file does not upload correctly. The upload never reaches 100%. The upload purcentage updates once i click the update button (10%) , but nothing more after that. I tried with several browser and several sketches. It looks like the transfer is quickly aborted. I also tried the previous tutorial :https://randomnerdtutorials.com/esp32-over-the-air-ota-programming/ which leads to the same problem.
Any ideas of what is going wrong?
I am having the same problem except that my upload stops at 7%. Any ideas??
Also, I think I read somewhere that the partition table might be an issue??
My environment:
[env:featheresp32]
platform = espressif32
board = featheresp32
framework = arduino
board_build.partitions = no_ota.csv
monitor_speed = 115200
lib_deps =
me-no-dev/ESP Async WebServer@^1.2.3
me-no-dev/AsyncTCP@^1.1.1
ayushsharma82/AsyncElegantOTA@^2.2.6
neptune2/simpleDSTadjust@^1.2.0
milesburton/DallasTemperature@^3.9.1
itead/Nextion@^0.9.0
blynkkk/Blynk@^1.0.1
bblanchon/ArduinoJson@^6.19.4
plerup/EspSoftwareSerial@^6.16.1
I was able to solve my problem by creating the custom partition table listed at https://husarnet.com/blog/internet-ota-esp32/ that was mentioned in one of the above messages. So the line above, “board_build.partitions = no_ota.csv” should be changed to “board_build.partitions = partitions_custom.csv”. The csv file contents are:
Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x180000,
app1, app, ota_1, 0x190000,0x180000,
spiffs, data, spiffs, 0x310000,0xF0000,
Hello,
This webpage is great. I’m widely using your examples.
I’m completely stuck (general beginner but with Pascal/Delphi background) how to modify the program – Websocket – multiple GPIOS to control multiple bolean variables like ProgramRun, Program Stop etc. The best is 4 GPIOS and 4 Variables – then it will be easy understand how it works. i sopent about week to try but unfortunately.
Piotr
Hi. Can I add upload port to file platform.ini for upload Firmware from VSCode?
How can I do this?
Hi.
Here’s everything you need to know to add a port to the platformio.ini file: https://docs.platformio.org/en/stable/projectconf/section_env_upload.html#upload-port
Regards,
Sara
What version of espressif32 are you using? With version above 3.5.0 I have an error:
collect2: error: ld returned 1 exit status
My solution to the problem:
platform = expressif32 @ 3.5.0
Which version of espressif32 are you using? With version above 3.5.0 I have an error:
collect2: error: ld returned 1 exit status
My solution to the problem:
platform = expressif32 @ 3.5.0
Finally solved by another library:
lib_deps = https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.4
// https://github.com/me-no-dev/ESPAsyncWebServer.git
Hello,
is it possible to update the binary with a command line or through an HTTP POST request via an Application ?
Cheers.
This is available in Platformio but I’m unable to get it working.
A one button click in Platform io as per USB programming would be great.
Perhaps Sara or others can shed light on making this work.
thanks, but what I’m looking for is a firmware OTA update that could be sent by an App (http post).
Cheers.
Hi!
I followed the instructions but it doesn’t work!!!!
Linking .pio\build\featheresp32\firmware.elf
c:/users/lechi/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld.exe: .pio\build\featheresp32\libb70\libESP Async WebServer.a(WebAuthentication.cpp.o):(.literal._ZL6getMD5PhtPc+0x4): undefined reference to
mbedtls_md5_starts'
getMD5(unsigned char*, unsigned short, char*)’:c:/users/lechi/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld.exe: .pio\build\featheresp32\libb70\libESP Async WebServer.a(WebAuthentication.cpp.o): in function
D:\Code\ESP32_C\F_OTA/.pio/libdeps/featheresp32/ESP Async WebServer/src/WebAuthentication.cpp:74: undefined reference to `mbedtls_md5_starts’
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\featheresp32\firmware.elf] Error 1
Hi.
On the platformio.ini file, change the platform to [email protected] instead espressif.
Let me know if this solves the issue.
Regards,
Sara
Thank you very much, it worked!
Thank you, it worked,
Regards,
Mohammed Yasar Dudhwala,
Embedded Software Intern, Prayosha Food Services Pvt Ltd,
Prahladnagar, Ahmedabad, Gujarat, India.
I use settings (platformio.ini):
– platform = [email protected]
– lib_deps =
me-no-dev/AsyncTCP@^1.1.1
me-no-dev/ESP Async WebServer@^1.2.3
ayushsharma82/AsyncElegantOTA@^2.2.6
and get error “.pio/libdeps/esp32dev/AsyncElegantOTA/src/AsyncElegantOTA.h:17:24: fatal error: Update.h: No such file or directory”
Any idea ?
I have the same problem. Why is the Update.h file not present in the lindeps?
Hello,
There is a small glitch in WebAuthentication.cpp during compiling. With ESP Async WebServer library added through Platformio library manager, a compiler error shows up as: “…..libdeps/esp32dev/ESP Async WebServer/src/WebAuthentication.cpp:74: undefined reference to `mbedtls_md5_starts'”. It appears that this is outdated, but modifying platform.ini to: https://github.com/me-no-dev/ESPAsyncWebServer.git, everything works beautifully.
I hope this helps some save some time.
Hi.
Yes.
There’s currently an issue with the AsyncWebServer Library when using PlatformIO.
That’s one of the possible workarounds.
Regards,
Sara
To resolve a lot of webserver warnings, and more specifically the error prventing compiling in PlatformIO I simply added #include<Webserver.h> in the main.cpp file.
Can’t say it solved the actual problem as I have only gotten a success in compiling, waiting to try with ESP32.
Thanks for this excellent tutorial. My sensors are coded using Esp32 with 100% esp-now. Is it possible to update the firmware using OTA with esp-now ?
After I upload the spiffs.bin file into filesystem in elegantOTA dashboard and again visited to root URL but I couldn’t get the page like multiple GPIO’s instead I get webpage for the past code used in firmware.
I use vscode platformIO and used necessary libraries and have correct network credentials, I use windows 11. what might be the problem, I’m hanging in this stage past 3 days. all the codes and instructions followed int his page https://randomnerdtutorials.com/esp32-ota-over-the-air-vs-code/#1-basic-elegantota
can any one sort out the problem.