ESP8266 OTA方法二 本地升级

继上篇介绍利用巴法云来实现ota,有朋友表示服务器不稳,故搜索本地实现过程,在网上找到这篇介绍,原本是esp32,现修改为esp8266.

1、本地电脑执行py,将bin放到同级目录


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()

2、arduino加入如下代码

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266httpUpdate.h>
#include <Preferences.h>
// #include <HTTPUpdate.h>
#include "ESPAsyncWebServer.h"
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>

String getUpDateName;                                         // 获取的升级包名
String upDateName;                                            // 上次的升级包名
bool UpdateVersionIsOk;                                       // 包名判断可以升级的标志位
String getUpdateUrl = "http://192.168.31.69:8989/getFile";     // 获取升级包名的URL
String downLoadUpdateUrl = "http://192.168.31.69: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("升级记录已保存");
}

// 当升级开始时,打印日志
void update_started()
{
    Serial.println("CALLBACK:  HTTP update process started");
}

// 当升级结束时,打印日志
void update_finished()
{
    Serial.println("CALLBACK:  HTTP update process finished");
    // u8g2.clearBuffer();
    // u8g2.drawStr(u8g2.getWidth() / 2, u8g2.getHeight() / 2, "Restart");
    // u8g2.sendBuffer();
}

// 当升级中,打印日志
void update_progress(int cur, int total)
{
    Serial.printf("CALLBACK:  HTTP update process at %d of %d bytes...%d%% \n", cur, total, cur / (total / 100));
    //ota_OLED_onProgress(4, 32, 120, 8, cur / (total / 100));
}

// 当升级失败时,打印日志
void update_error(int err)
{
    Serial.printf("CALLBACK:  HTTP update fatal error code %d\n", err);
}

// OTA升级检查线程
void seachUpdate()
{
    while (true)
    {
        if (WiFi.status() == WL_CONNECTED)
        {
            WiFiClient client;
            HTTPClient http;
            http.begin(client, 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;
            ESPhttpUpdate.onStart(update_started);     // 当升级开始时
            ESPhttpUpdate.onEnd(update_finished);      // 当升级结束时
            ESPhttpUpdate.onProgress(update_progress); // 当升级中
            ESPhttpUpdate.onError(update_error);       // 当升级失败时
            if (UpdateVersionIsOk)
            {
                ESPhttpUpdate.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);
}

以上作为记录

猜你喜欢

转载自blog.csdn.net/yyandad/article/details/130323400