ESP32 OTA (Over-the-Air) обновления — AsyncElegantOTA (VS Code + PlatformIO)

В этом руководстве вы узнаете, как выполнять OTA-обновления (обновления по воздуху) на платах ESP32 с помощью библиотеки AsyncElegantOTA и VS Code с PlatformIO. Библиотека Async Elegant OTA создаёт веб-сервер, который позволяет загружать новую прошивку (новый скетч) на плату без необходимости последовательного подключения между ESP32 и компьютером.

Кроме того, с помощью этой библиотеки вы также можете загружать новые файлы в файловую систему ESP32 (SPIFFS). Библиотека очень проста в использовании и совместима с библиотекой ESPAsyncWebServer, которую мы часто используем для создания проектов веб-серверов.

Смотрите видеоурок

ESP32 OTA обновления по воздуху AsyncElegantOTA VS Code PlatformIO

К концу этого руководства вы сможете легко добавлять возможности OTA в свои проекты веб-серверов на ESP32 для беспроводной загрузки новой прошивки и файлов в файловую систему.

Рекомендуем прочитать: Начало работы с VS Code и PlatformIO IDE для ESP32 и ESP8266

У нас есть аналогичное руководство для платы ESP8266 NodeMCU: ESP8266 NodeMCU OTA (Over-the-Air) Updates — AsyncElegantOTA (VS Code + PlatformIO)

Обзор

Это руководство охватывает:

Мы рекомендуем выполнить все шаги этого руководства, чтобы понять, как работает ElegantOTA и как вы можете использовать его в своих проектах. Для демонстрации мы загрузим файлы для создания различных проектов веб-серверов.

ESP32 OTA (Over-the-Air) программирование

OTA (Over-the-Air) обновление — это процесс загрузки новой прошивки на плату ESP32 по Wi-Fi-соединению, а не через последовательное подключение. Эта функция чрезвычайно полезна в случае отсутствия физического доступа к плате ESP32.

Существуют различные способы выполнения OTA-обновлений. В этом руководстве мы рассмотрим, как это сделать с помощью библиотеки AsyncElegantOTA. На наш взгляд, это один из лучших и простейших способов выполнения OTA-обновлений.

Библиотека AsyncElegantOTA создаёт веб-сервер, к которому вы можете обратиться в локальной сети для загрузки новой прошивки или файлов в файловую систему (SPIFFS). Загружаемые файлы должны быть в формате .bin. Мы покажем вам далее в руководстве, как получить файлы в формате .bin.

Как работает Async ElegantOTA веб-сервер ESP32

Единственным недостатком OTA-программирования является то, что вам нужно добавлять код для OTA в каждый загружаемый скетч, чтобы иметь возможность использовать OTA в будущем. В случае библиотеки AsyncElegantOTA это всего три строки кода.

Библиотека AsyncElegantOTA

Как упоминалось ранее, существуют различные альтернативы для OTA-программирования плат ESP32. Например, в Arduino IDE в папке Examples есть пример BasicOTA (который у нас никогда не работал хорошо); OTA Web Updater (работает хорошо, но его сложно интегрировать с веб-серверами, использующими библиотеку ESPAsyncWebServer); и множество других примеров из различных библиотек.

Большинство наших проектов веб-серверов для ESP32 используют библиотеку ESPAsyncWebServer. Поэтому нам нужно было решение, совместимое с этой библиотекой. Библиотека AsyncElegantOTA идеально подходит для наших нужд:

Логотип библиотеки AsyncElegantOTA
  • Она совместима с библиотекой ESPAsyncWebServer;

  • Вам нужно добавить всего три строки кода для добавления возможностей OTA в ваш «обычный» Async Web Server;

  • Она позволяет загружать не только новую прошивку на плату, но и файлы в файловую систему ESP32 (SPIFFS);

  • Она предоставляет красивый и современный интерфейс веб-сервера;

  • Она работает превосходно.

Если вам нравится эта библиотека и вы будете использовать её в своих проектах, рассмотрите возможность поддержки работы разработчика.

OTA-обновления с библиотекой AsyncElegantOTA — краткое описание

Чтобы добавить возможности OTA в ваши проекты с помощью библиотеки AsyncElegantOTA, выполните следующие шаги:

  1. Включите библиотеки AsyncElegantOTA, AsyncTCP и ESPAsyncWebServer в файл platformio.ini вашего проекта;

  2. Подключите библиотеку AsyncElegantOTA в начале кода: #include <AsyncElegantOTA.h>;

  3. Добавьте строку AsyncElegantOTA.begin(&server); перед server.begin();

  4. Откройте браузер и перейдите по адресу http://<IPAddress>/update, где <IPAddress> — IP-адрес вашего ESP32.

Продолжайте читать руководство для получения более подробных инструкций.

Как работает OTA Web Updater?

  • Первый скетч должен быть загружен через последовательный порт. Этот скетч должен содержать код для создания OTA Web Updater, чтобы в дальнейшем вы могли загружать код через браузер.

  • Скетч OTA Web Updater создаёт веб-сервер, к которому вы можете обратиться для загрузки нового скетча через веб-браузер.

  • Затем вам нужно реализовать процедуры OTA в каждом загружаемом скетче, чтобы иметь возможность выполнять следующие обновления/загрузки по воздуху.

  • Если вы загрузите код без процедуры OTA, вы больше не сможете получить доступ к веб-серверу и загрузить новый скетч по воздуху.

Установка библиотеки AsyncElegantOTA (VS Code + PIO)

В этом руководстве мы будем использовать VS Code + PIO для программирования ESP32. Если вы хотите использовать Arduino IDE, следуйте следующему руководству: ESP32 OTA (Over-the-Air) Updates — AsyncElegantOTA using Arduino IDE.

Чтобы использовать библиотеку AsyncElegantOTA, включите её в файл platformio.ini. Вам также нужно включить библиотеку ESPAsyncWebServer. Добавьте эти библиотеки следующим образом:

lib_deps = ESP Async WebServer
  ayushsharma82/AsyncElegantOTA @ ^2.2.5

AsyncElegantOTA — базовый пример для ESP32

Если вы используете ESP32, вам необходимо понизить версию дополнения для плат ESP32 до версии 2.0.X. На данный момент библиотека AsyncElegantOTA несовместима с версией 3.X. Если вы хотите использовать версию 3.X, используйте новейшую версию библиотеки: ElegantOTA V3.

Начнём с базового примера, предоставленного библиотекой. Этот пример создаёт простой веб-сервер на ESP32. Корневой URL отображает текст, а URL /update отображает интерфейс для обновления прошивки и файловой системы.

Отредактируйте файл platformio.ini следующим образом:

[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

Скопируйте следующий код в файл main.cpp.

/*
  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) {

}

Посмотреть исходный код

Вставьте свои сетевые учётные данные, и код должен сразу заработать:

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

Как работает код

Сначала подключите необходимые библиотеки:

#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.h>

Вставьте свои сетевые учётные данные в следующие переменные, чтобы ESP32 мог подключиться к вашей локальной сети.

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

Создайте объект AsyncWebServer на порту 80:

AsyncWebServer server(80);

В setup() инициализируйте Serial Monitor:

Serial.begin(115200);

Инициализируйте 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());

Затем обработайте запросы клиента. Следующие строки отправляют текст «Hi! I am ESP32.» при обращении к корневому (/) URL:

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

Если ваш веб-сервер должен обрабатывать больше запросов, вы можете добавить их (мы покажем это в следующем примере).

Затем добавьте следующую строку для запуска ElegantOTA:

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

Наконец, инициализируйте сервер:

server.begin();

Доступ к веб-серверу

После загрузки кода на плату откройте Serial Monitor с скоростью передачи 115200 бод. Нажмите кнопку RST на плате ESP32. Должен отобразиться IP-адрес ESP (ваш может отличаться):

VS Code с PlatformIO получение IP-адреса платы

В вашей локальной сети откройте браузер и введите IP-адрес ESP32. Вы должны получить доступ к корневой (/) веб-странице с отображённым текстом.

Демо-пример AsyncElegantOTA корневой URL веб-сервера

Теперь представьте, что вы хотите изменить код своего веб-сервера. Чтобы сделать это через OTA, перейдите по IP-адресу ESP с добавлением /update. Должна загрузиться следующая веб-страница.

Страница обновления Async ElegantOTA

Следуйте следующим разделам, чтобы узнать, как загружать новую прошивку с помощью AsyncElegantOTA.

Загрузка новой прошивки OTA (Over-the-Air) — ESP32

Каждый файл, который вы загружаете через OTA, должен быть в формате .bin. VS Code автоматически генерирует файл .bin для вашего проекта при компиляции кода. Файл называется firmware.bin и сохраняется в папке проекта по следующему пути (или аналогичному в зависимости от используемой платы):

.pio/build/esp32doit-devkit-v1/firmware.bin

Это тот файл .bin, который вы должны загрузить через веб-страницу AsyncElegantOTA, если хотите обновить прошивку.

Загрузка нового скетча веб-сервера

Рассмотрим практический пример. Представьте, что после загрузки предыдущего скетча вы хотите загрузить новый, который позволяет управлять светодиодом через веб-интерфейс, как в этом проекте. Вот шаги, которые нужно выполнить:

  1. Скопируйте следующий код в файл main.cpp. Не забудьте вставить свои сетевые учётные данные.

/*
  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;
  }
  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').textContent = 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(200, "text/html", index_html, processor);
  });

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

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

Посмотреть исходный код

Это тот же код, что используется в этом проекте, но он содержит необходимые строки кода для работы с ElegantOTA:

#include <AsyncElegantOTA.h>
AsyncElegantOTA.begin(&server);
  1. Отредактируйте файл platformio.ini следующим образом:

[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. Сохраните и скомпилируйте код — нажмите на иконку Build.

VS Code + PlatformIO компиляция (сборка) кода

3. Теперь на вкладке Explorer в VS Code вы можете убедиться, что у вас есть файл firmware.bin в папке проекта по следующему пути (или аналогичному):

.pio/build/esp32doit-devkit-v1/firmware.bin
VS Code с PlatformIO директория файла Bin ESP32 ESP8266

4. Теперь вам просто нужно загрузить этот файл через страницу ElegantOTA. Перейдите по IP-адресу ESP с добавлением /update. Убедитесь, что выбрана опция firmware.

5. Нажмите Choose File, перейдите к папке на компьютере и выберите файл вашего проекта.

Расположение файла Firmware Bin в VS Code PlatformIO IDE

6. Подождите, пока индикатор прогресса достигнет 100%.

Загрузка новой прошивки Elegant OTA

7. Когда загрузка завершится, нажмите кнопку Back.

Успешная загрузка новой прошивки Elegant OTA

8. Затем вы можете перейти к корневому (/) URL для доступа к новому веб-серверу. Это страница, которую вы должны увидеть при обращении к IP-адресу ESP по корневому (/) URL.

ESP32 WebSocket Server управление выходами

Вы можете нажать на кнопку, чтобы включить и выключить встроенный светодиод ESP32.

Встроенный светодиод платы ESP32 включён

Поскольку мы также добавили возможности OTA в этот новый веб-сервер, мы можем загрузить новый скетч в будущем при необходимости. Вам просто нужно перейти по IP-адресу ESP32 с добавлением /update.

Поздравляем, вы загрузили новый код на ESP32 по Wi-Fi с помощью ElegantOTA.

Продолжайте читать, если хотите узнать, как загружать файлы в файловую систему ESP32 (SPIFFS) с помощью AsyncElegantOTA.

Загрузка файлов в файловую систему OTA (Over-the-Air) — ESP32

В этом разделе вы узнаете, как загружать файлы в файловую систему ESP32 (SPIFFS) с помощью AsyncElegantOTA.

Веб-сервер с файлами из SPIFFS

Представьте сценарий, когда вам нужно загрузить файлы в файловую систему ESP32, например: конфигурационные файлы; HTML, CSS и JavaScript файлы для обновления страницы веб-сервера; или любой другой файл, который вы хотите сохранить в SPIFFS через OTA.

Чтобы показать, как это сделать, мы создадим новый веб-сервер, который обслуживает файлы из SPIFFS: HTML, CSS и JavaScript файлы для создания веб-страницы, управляющей GPIO ESP32 удалённо.

Скопируйте следующий код в файл main.cpp.

/*
  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();
}

Посмотреть исходный код

Вставьте свои сетевые учётные данные в следующие переменные и сохраните код.

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

Отредактируйте файл platformio.ini следующим образом:

[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

Обновление прошивки

После вставки сетевых учётных данных сохраните и скомпилируйте код.

VS Code + PlatformIO компиляция (сборка) кода

Перейдите по IP-адресу ESP с добавлением /update и загрузите новую прошивку, как показано ранее.

Далее мы рассмотрим, как загружать файлы в файловую систему.

Обновление файловой системы

В папке проекта создайте папку с именем data и поместите в неё следующие HTML, CSS и JavaScript файлы (нажмите на ссылки для скачивания файлов):

В VS Code нажмите на иконку PIO и перейдите в Project Tasks > env:esp32doit-devkit-v1 (или аналогичный) > Platform > Build Filesystem Image. Это создаст файл .bin из файлов, сохранённых в папке data.

Создание образа файловой системы VS Code PlatformIO ESP32

После создания образа файловой системы у вас должен появиться файл spiffs.bin по следующему пути (или аналогичному):

.pio/build/esp32doit-devkit-v1/spiffs.bin
Директория файла SPIFFS Bin VS Code + PlatformIO ESP32

Это тот файл, который вы должны загрузить для обновления файловой системы.

Перейдите по IP-адресу ESP с добавлением /update. Убедитесь, что выбрана опция Filesystem, и выберите файл spiffs.bin.

Загрузка файлов в файловую систему Elegant OTA

После успешной загрузки нажмите кнопку Back. И снова перейдите к корневому (/) URL.

Вы должны получить доступ к следующей веб-странице, которая управляет выходами ESP32 с помощью протокола WebSocket.

Управление множеством выходов ESP32 ESP8266 WebSocket веб-сервер

Чтобы увидеть работу веб-сервера, вы можете подключить 4 светодиода к ESP32 на GPIO: 2, 4, 12 и 14. Вы сможете управлять этими выходами с веб-сервера.

Если вам нужно что-то обновить в проекте, просто перейдите по IP-адресу ESP32 с добавлением /update.

Поздравляем! Вы успешно загрузили файлы в файловую систему ESP32 с помощью ElegantOTA.

Заключение

В этом руководстве вы узнали, как добавить возможности OTA в ваши асинхронные веб-серверы с помощью библиотеки AsyncElegantOTA. Эта библиотека очень проста в использовании и позволяет легко загружать новую прошивку или файлы в файловую систему через веб-страницу. На наш взгляд, библиотека AsyncElegantOTA — один из лучших вариантов для OTA-обновлений через веб.

Мы надеемся, что это руководство было полезным.

Узнайте больше о ESP32 с нашими ресурсами:


Источник: Random Nerd Tutorials — ESP32 OTA (Over-the-Air) Updates — AsyncElegantOTA (VS Code + PlatformIO)