Output - GPIO 2
state: %STATE%
在本指南中,您将学习如何使用 AsyncElegantOTA 库对 ESP8266 NodeMCU 板进行无线 (OTA) 更新。该库创建了一个网络服务器,允许您将新固件(新草图)更新到您的电路板,而无需在 ESP8266 和您的计算机之间建立串行连接。
此外,您还可以将新文件上传到 ESP8266 文件系统 (LittleFS)。该库非常易于使用,并且与我们经常用于构建 Web 服务器项目的 ESPAsyncWebServer 库兼容。
在本教程结束时,您将能够使用 ESP8266 轻松地将 OTA 功能添加到您的网络服务器项目中,以便将来以无线方式将新固件和文件上传到文件系统。
我们为 ESP32 开发板提供了类似的教程:
本教程涵盖:
我们建议您按照本教程中的所有步骤来了解 ElegantOTA 的工作原理以及如何在您的项目中使用它。为了演示如何执行此操作,我们将上传文件以构建不同的 Web 服务器项目。
OTA(空中下载)更新是使用 Wi-Fi 连接而不是串行通信将新固件加载到 ESP8266 NodeMCU 板的过程。在无法物理访问 ESP8266 开发板的情况下,此功能非常有用。
有多种方法可以执行 OTA 更新。在本教程中,我们将介绍如何使用AsyncElegantOTA 库来做到这一点。在我们看来,这是执行 OTA 更新的最佳和最简单的方法之一。
AsyncElegantOTA 库创建了一个 Web 服务器,您可以在本地网络上访问该服务器以将新固件或文件上传到文件系统 (LittleFS)。您上传的文件应为.bin格式。我们稍后将在本教程中向您展示如何将您的文件转换为.bin格式。
OTA 编程的唯一缺点是您需要在您上传的每个草图中添加 OTA 代码,以便您将来可以使用 OTA。对于 AsyncElegantOTA 库,它仅包含三行代码。
如前所述,使用 ESP8266 板进行 OTA 编程有很多替代方案。例如,在 Arduino IDE 中,Examples文件夹下有BasicOTA示例(对我们来说从来都不是很好);以及来自不同库的许多其他示例。
我们使用ESP8266 的大多数 Web 服务器项目都使用ESPAsyncWebServer 库。因此,我们想要一个与该库兼容的解决方案。该AsyncElegantOTA库仅仅是完美的,我们想要的东西:
如果您喜欢这个库并且将在您的项目中使用它,请考虑支持开发人员的工作。
要使用 AsyncElegantOTA 库向您的项目添加 OTA 功能,请执行以下步骤:
继续阅读教程以获取更详细的步骤。
在本教程中,ESP8266 将使用 Arduino IDE 进行编程。如果你想学习如何使用 VS Code + PlatformIO 来做同样的事情,请按照下一个教程: ESP8266 NodeMCU OTA(空中)更新 – AsyncElegantOTA(VS Code + PlatformIO)。
您可以使用 Arduino 库管理器安装 AsyncElegantOTA 库。在您的 Arduino IDE 中,转到Sketch > Include Library > Manage Libraries...搜索“ AsyncElegantOTA ”并安装它。
您还需要安装 ESPAsyncTCP 和 ESPAsyncWebServer 库。单击下面的链接下载库。
这些库无法通过 Arduino 库管理器安装,因此您需要将库文件复制到 Arduino 安装库文件夹。或者,在您的 Arduino IDE 中,您可以转到 Sketch > Include Library > Add .zip Library 并选择您刚刚下载的库。
让我们从库提供的基本示例开始。此示例使用 ESP8266 创建一个简单的 Web 服务器。根 URL 显示一些文本,并且/更新 URL 显示更新固件和文件系统的界面。
将以下代码复制到您的 Arduino IDE。
/*
Rui Santos
Complete project details
- Arduino IDE: https://RandomNerdTutorials.com/esp8266-nodemcu-ota-over-the-air-arduino/
- VS Code: https://RandomNerdTutorials.com/esp8266-nodemcu-ota-over-the-air-vs-code/
This sketch shows a Basic example from the AsyncElegantOTA library: ESP8266_Async_Demo
https://github.com/ayushsharma82/AsyncElegantOTA
*/
#include
#include
#include
#include
#include
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.");
});
AsyncElegantOTA.begin(&server); // Start ElegantOTA
server.begin();
Serial.println("HTTP server started");
}
void loop(void) {
AsyncElegantOTA.loop();
}
插入您的网络凭据,代码应立即生效:
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
首先,包括必要的库:
#include
#include
#include
#include
在以下变量中插入您的网络凭据,以便 ESP8266 可以连接到您的本地网络。
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
创建一个 异步网络服务器 端口 80 上的对象:
AsyncWebServer server(80);
在里面 设置(),初始化串口监视器:
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());
然后,处理客户端请求。以下几行,发送一些文本你好!我是ESP8266。 当您访问根 (/) 网址:
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(200, "text/plain", "Hi! I am ESP8266.");
});
如果您的 Web 服务器需要处理更多请求,您可以添加它们(我们将在下一个示例中向您展示)。
然后,添加下一行以启动 ElegantOTA:
AsyncElegantOTA.begin(&server); // Start ElegantOTA
最后,初始化服务器:
server.begin();
最后在里面添加以下内容 loop():
void loop(void) {
AsyncElegantOTA.loop();
}
上传代码到板子后,以115200的波特率打开串口监视器,按下ESP8266板载RST按钮。它应该显示 ESP IP 地址如下(你的可能不同):
在本地网络中,打开浏览器并输入 ESP8266 IP 地址。您应该可以访问根目录(/) 显示一些文本的网页。
现在,假设您要修改 Web 服务器代码。要通过 OTA 执行此操作,请转到 ESP IP 地址,然后是/更新. 应加载以下网页。
按照下一节了解如何使用 AsyncElegantOTA 上传新固件。
您通过 OTA 上传的每个文件都应为.bin格式。您可以使用 Arduino IDE 从您的草图中生成一个.bin文件。
打开草图后,您需要转到Sketch > Export Compiled Binary。一个名为.bin文件将从您的草图生成。生成的文件将保存在您的项目文件夹下。
如果您想上传新固件,您应该使用 AsyncElegantOTA 网页上传那个.bin文件。
让我们看一个实际的例子。想象一下,在上传之前的草图后,您想上传一个新的草图,该草图允许您通过网络界面控制 LED,例如这个项目。以下是您需要遵循的步骤:
1. 将以下代码复制到您的 Arduino IDE。不要忘记插入您的网络凭据。
/*
Rui Santos
Complete project details
- Arduino IDE: https://RandomNerdTutorials.com/esp8266-nodemcu-ota-over-the-air-arduino/
- VS Code: https://RandomNerdTutorials.com/esp8266-nodemcu-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
#include
#include
#include
#include
// 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(
ESP Web Server
ESP Web Server
ESP WebSocket Server
Output - GPIO 2
state: %STATE%
)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() {
AsyncElegantOTA.loop();
ws.cleanupClients();
digitalWrite(ledPin, ledState);
}
查看原始代码
这与此项目中使用的代码相同,但它包含处理 ElegantOTA 所需的代码行:
#include
AsyncElegantOTA.begin(&server);
AsyncElegantOTA.loop();
2. 保存您的草图:文件>保存并为其命名。例如:Web_Server_LED_OTA_ESP8266。
3.从你的草图中生成一个.bin文件。转到Sketch > Export Compiled Binary。应该在项目文件夹下创建一个新的.bin文件。
4. 现在您只需要使用 ElegantOTA 页面上传该文件。转到您的 ESP IP 地址,然后是/更新. 确保您选择了固件选项。单击“选择文件”并选择您刚刚生成的.bin文件。
5. 完成后,单击“返回”按钮。
6.然后,你可以去根(/) 访问新 Web 服务器的 URL。这是访问根目录上的 ESP IP 地址时应该看到的页面 (/) 网址。
您可以单击按钮来打开和关闭 ESP8266 板载 LED。
因为我们还为这个新的 Web 服务器添加了 OTA 功能,所以我们可以在未来根据需要上传新的草图。您只需要转到 ESP8266 IP 地址,然后/更新.
恭喜,您已使用 ElegantOTA 通过 Wi-Fi 将新代码上传到您的 ESP8266。
如果您想了解如何使用 AsyncElegantOTA 将文件上传到 ESP8266 文件系统 (LittleFS),请继续阅读。
在本节中,您将学习使用 AsyncElegantOTA 将文件上传到 ESP8266 文件系统 (LittleFS)。
在继续之前,您需要在 Arduino IDE 中安装 ESP8266 LittleFS Uploader Plugin。在继续之前,请按照下一个教程进行操作:
想象一下您需要将文件上传到 ESP8266 文件系统的场景,例如配置文件、HTML、CSS 和 JavaScript 文件以更新 Web 服务器页面或您可能希望通过 OTA 保存在 LittleFS 中的任何其他文件。
为了向您展示如何执行此操作,我们将创建一个新的 Web 服务器,该服务器提供来自文件系统 (LittleFS) 的文件:HTML、CSS 和 JavaScript 文件,以构建一个远程控制 ESP8266 GPIO 的网页。
在继续之前,请确保您已安装Arduino 0.1.0 版的Arduino_JSON 库。您可以在 Arduino IDE 库管理器中安装此库。只需转到 Sketch > Include Library > Manage Libraries 并按如下方式搜索库名称:Arduino_JSON。
将以下代码复制到您的 Arduino IDE。
/*
Rui Santos
Complete project details
- Arduino IDE: https://RandomNerdTutorials.com/esp8266-nodemcu-ota-over-the-air-arduino/
- VS Code: https://RandomNerdTutorials.com/esp8266-nodemcu-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
#include
#include
#include
#include "LittleFS.h"
#include
#include
// 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 LittleFS
void initLittleFS() {
if (!LittleFS.begin()) {
Serial.println("An error has occurred while mounting LittleFS");
}
Serial.println("LittleFS 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; ifinal && 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; isend(LittleFS, "/index.html", "text/html",false);
});
server.serveStatic("/", LittleFS, "/");
// Start ElegantOTA
AsyncElegantOTA.begin(&server);
// Start server
server.begin();
}
void loop() {
AsyncElegantOTA.loop();
ws.cleanupClients();
}
查看原始代码
在以下变量中插入您的网络凭据并保存代码。
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
从此草图创建一个.bin文件,如前所示(此草图包括提供 OTA 功能所需的代码行)。
转到 ESP8266 IP 地址,然后是 /更新 并上传新固件。
接下来,我们将看到如何上传文件。
在项目文件夹下创建一个名为data的文件夹并粘贴以下 HTML、CSS 和 JavaScript 文件(单击链接下载文件):
ESP IOT DASHBOARD
ESP WEB SERVER - Control Multiple Outputs WebSocket
GPIO 2
State:
GPIO 4
State:
GPIO 14
State:
GPIO 12
State:
html {
font-family: Arial, Helvetica, sans-serif;
text-align: center;
}
h1 {
font-size: 1.8rem;
color: white;
}
.topnav {
overflow: hidden;
background-color: #0A1128;
}
body {
margin: 0;
}
.content {
padding: 50px;
}
.card-grid {
max-width: 600px;
margin: 0 auto;
display: grid;
gap: 2rem;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.card {
background-color: white;
box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
}
.card-title {
font-size: 1.2rem;
font-weight: bold;
color: #034078
}
.state {
font-size: 1.2rem;
color:#1282A2;
}
.switch {
position: relative;
display: inline-block;
width: 120px;
height: 68px
}
.switch input {
display: none
}
.slider {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background-color: #ccc;
border-radius: 50px
}
.slider:before {
position: absolute;
content: "";
height: 52px;
width: 52px;
left: 8px;
bottom: 8px;
background-color: #fff;
-webkit-transition: .4s;
transition: .4s;
border-radius: 50px;
}
input:checked+.slider {
background-color: #b30000;
}
input:checked+.slider:before {
-webkit-transform: translateX(52px);
-ms-transform: translateX(52px);
transform: translateX(52px);
}
var gateway = `ws://${window.location.hostname}/ws`;
var websocket;
window.addEventListener('load', onLoad);
function onLoad(event) {
initWebSocket();
}
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');
websocket.send("states");
}
function onClose(event) {
console.log('Connection closed');
setTimeout(initWebSocket, 2000);
}
function onMessage(event) {
var myObj = JSON.parse(event.data);
console.log(myObj);
for (i in myObj.gpios){
var output = myObj.gpios[i].output;
var state = myObj.gpios[i].state;
console.log(output);
console.log(state);
if (state == "1"){
document.getElementById(output).checked = true;
document.getElementById(output+"s").innerHTML = "ON";
}
else{
document.getElementById(output).checked = false;
document.getElementById(output+"s").innerHTML = "OFF";
}
}
console.log(event.data);
}
// Send Requests to Control GPIOs
function toggleCheckbox (element) {
console.log(element.id);
websocket.send(element.id);
if (element.checked){
document.getElementById(element.id+"s").innerHTML = "ON";
}
else {
document.getElementById(element.id+"s").innerHTML = "OFF";
}
}
要找到您的项目文件夹,您可以转到Sketch > Show Sketch Folder。
这是您的数据文件夹应位于的位置及其外观:
在此之后,将 ESP8266 与您的计算机断开连接(这就是 OTA 的全部目的),点击ESP8266 LittleFS Data Upload。
您会收到错误消息,因为没有任何 ESP8266 板连接到您的计算机 - 别担心。
在调试窗口上向上滚动,直到找到.mklittlefs.bin文件位置。那就是您应该上传的文件(在我们的例子中,该文件名为Web_Server_OTA_ESP8266_Example_2.mklittlefs.bin。
这是我们文件所在的路径:
C:\Users\sarin\AppData\Local\Temp\arduino_build_375940\Web_server_OTA_ESP8266_Example_2.mklittlefs.bin
要在我的计算机上访问该文件,我需要使隐藏文件可见(AppData文件夹不可见)。检查这是否也是你的情况。
到达文件夹路径后,您希望获取扩展名为.mklittlefs.bin的文件。
为方便起见,您可以将该文件复制到您的项目文件夹中。
现在我们有来自数据文件夹的.bin文件,我们可以上传该文件。转到您的 ESP8266 IP 地址,然后是/更新. 确保您选择了文件系统选项。
然后,选择扩展名为.mklittlefs.bin的文件。
上传成功后,点击返回按钮。并转到根 (/) 网址。您应该可以访问以下使用Web Socket 协议控制 ESP8266 输出的网页。
要查看网络服务器的工作情况,您可以将 4 个 LED 连接到 GPIOS 上的 ESP8266:2、4、12 和 14。您应该能够控制来自网络服务器的这些输出。
如果您需要更新项目中的某些内容,只需转到您的 ESP8266 IP 地址,然后输入 /更新.
恭喜!您已使用 ElegantOTA 成功将文件上传到 ESP8266 文件系统。