前几天找这个标题的资料,必应搜索只有这篇:
链接: esp32使用httpupdate批量自动化程序升级 arduino IDE
看完这篇文章,升级连接写死在程序上,每次升级都要改,不太优雅。
所以我改进了下。
先贴代码:
Arduino部分(HttpClient):
#include
#include
#include
#include
#include "ESPAsyncWebServer.h"
String getUpDateName; //获取的升级包名
String upDateName; //上次的升级包名
bool UpdateVersionIsOk; //包名判断可以升级的标志位
String getUpdateUrl = "http://172.17.99.99:8989/getFile"; //获取升级包名的URL
String downLoadUpdateUrl = "http://172.17.99.99:8989/update"; //下载升级包的URL
// OTA升级开始回调函数
void update_started()
{
Serial.println("CALLBACK: HTTP update process started");
}
// OTA升级完成回调函数
void update_finished()
{
Serial.println("CALLBACK: HTTP update process finished");
Preferences prefs; // NVS读写实例化
prefs.begin("WiFiConfig");
prefs.putString("Version", getUpDateName);
prefs.end();
upDateName = getUpDateName;
UpdateVersionIsOk = false;
Serial.println("升级记录已保存");
}
// OTA升级中回调函数
void update_progress(int cur, int total)
{
Serial.printf("CALLBACK: HTTP update process at %d of %d bytes...\n", cur, total);
}
// OTA升级错误回调函数
void update_error(int err)
{
Serial.printf("CALLBACK: HTTP update fatal error code %d\n", err);
}
// OTA升级检查线程
void seachUpdate(void *xTaskParameters)
{
while (true)
{
if (WiFi.status() == WL_CONNECTED)
{
HTTPClient http;
http.begin(getUpdateUrl);
int httpCode = http.GET();
delay(500);
if (httpCode > 0)
{
if (httpCode == HTTP_CODE_OK)
{
getUpDateName = http.getString();
Serial.println(getUpDateName);
//判断get的字符串和nvs存储的升级包名不一致
if (getUpDateName != "" && getUpDateName != upDateName)
{
UpdateVersionIsOk = true;
}
else
{
UpdateVersionIsOk = false;
}
}
}
else
{
Serial.println("HTTP GET... failed, error: " + http.errorToString(httpCode));
}
http.end();
WiFiClient upDateClient;
httpUpdate.onStart(update_started);
httpUpdate.onEnd(update_finished);
httpUpdate.onProgress(update_progress);
httpUpdate.onError(update_error);
if (UpdateVersionIsOk)
{
httpUpdate.update(upDateClient, downLoadUpdateUrl);
}
}
delay(5000);
}
}
void setup()
{
Preferences prefs; // NVS读写实例化
prefs.begin("WiFiConfig");
if (prefs.isKey("Version"))
{
upDateName = prefs.getString("Version");
}
xTaskCreatePinnedToCore(seachUpdate, "seachUpdate", 10000, NULL, 1, NULL, 0);
}
void loop()
{
delay(10);
}
Python(HttpServer):
from http.server import BaseHTTPRequestHandler, HTTPServer
import os
class MyHttpRequestHandler(BaseHTTPRequestHandler):
def __init__(self,request, client_address, server, folderPath):
self.folderPath = folderPath
self.UpDateFileName = self.getFileExtensionPath(self.folderPath, '.bin')
self.UpDateFilePath = self.folderPath + "\\" + self.getFileExtensionPath(self.folderPath, '.bin')
super().__init__(request, client_address, server)
@classmethod
def Creator(cls, *args, **kwargs):
def _HandlerCreator(request, client_address, server):
cls(request, client_address, server, *args, **kwargs)
return _HandlerCreator
def do_GET(self):
# 处理逻辑
path = str(self.path)
if path == "/getFile":
self.send_response(200)
self.send_header(
"Content-type", "text/plain")
self.end_headers()
self.wfile.write(bytes(self.UpDateFileName, "utf-8"))
elif path == "/update":
with open(self.UpDateFilePath, 'rb') as resultf:
buf = resultf.read()
length = resultf.tell()
self.send_response(200) # 文件存在返回状态码
# 返回请求格式为"application/octet-stream"
self.send_header("Content-type", "application/octet-stream")
self.send_header("Content-Length", str(length))
self.send_header("Content-Disposition",
"attachment; filename=\"%s\"" % self.UpDateFileName)
self.end_headers()
# 读取文件发送给客户端
self.wfile.write(buf)
def do_POST(self):
pass
def getFileExtensionPath(self, path, name):
for root, dirs, files in os.walk(path): # 遍历该文件夹
for file in files: # 遍历刚获得的文件名files
(filename, extension) = os.path.splitext(file) # 将文件名拆分为文件名与后缀
if (extension == name):
return file
if __name__ == '__main__':
ts = HTTPServer(('0.0.0.0', 8989), MyHttpRequestHandler.Creator(os.getcwd()))
ts.serve_forever()
说一下流程:
ESP32发起get请求:
ESP32 →(http://172.17.99.99:8989/getFile)→ Python
ESP32收到python的响应文本信息(升级包文件名):
升级包名由python程序搜索自身目录下的 .bin 后缀的文件获得。
ESP32 ←(“ota.0.0.0.0.bin”)← Python
ESP32判断nvs区域有无储存这个信息,无就请求真正的升级链接。
ESP32 →(http://172.17.99.99:8989/update)→ Python
Python响应,发送文件给esp32
ESP32 ←(ota.0.0.0.0.bin)← Python
下次打开Python来给ESP32升级前,记得改一下文件名,要和上一次OTA时不一致就可以了。
PlaformIO的编译文件位置:.pio\build\esp32dev\firmware.bin