【ESP32学习笔记】-- OTA升级2_远程升级(适用Arduino、PlatformIO)+ 完整代码

1、背景

上一篇文章:《【ESP32学习笔记】-- OTA升级(适用Arduino、PlatformIO)+ 完整代码》讲了esp32通过Web页面的方式进行OTA升级,这种方法简单高效,但是缺点也很明显,我们需要告诉使用者去哪里下载固件,并要手动操作才能完成固件更新。若我们把固件放到云服务器上,由程序自己去下载并更新,那岂不是方便很多,而且这样也能减少固件被盗取的风险。因此,这篇文章应运而生。

2、实现方法

远程升级的访问方式有两种,一种是http,另一种是https。这两者的主要区别是安全性不同,前者是明文传输,后者是加密传输,也就是说https更具安全性。也正因为https的这一加密特性,在访问https时需要网站的证书,否则无法访问,所以处理上会有些繁琐。而http则简单很多,只需要访问固件下载的链接即可进行固件下载。本文主要讲解使用https的方式,因为现如今大部分网站都是https的方式访问,具备通用性,而使用http方式可参考《ESP32 系列教程之空中升级 OTA》这篇文章。

3、实现步骤

3.1 准备服务器

要实现远程升级,就需要把固件放到云端,因此需要一个云服务器,这里以阿里云为例。

3.1.1 注册一个阿里云账号,并登录,进入控制台。

在这里插入图片描述

3.1.2 接着进入物联网 -> 物联网平台

在这里插入图片描述

3.1.3 点击公共实例(没开通要进行开通)

在这里插入图片描述

3.1.4 OTA升级需要和产品挂钩,没有产品需要创建一个产品,有产品可跳过。

在这里插入图片描述

在这里插入图片描述

3.1.5 选择OTA升级 -> 添加升级包,并将升级包上传。

在这里插入图片描述

3.1.6 创建好后进入升级包详情页面,点击下载。

在这里插入图片描述

3.1.7下载后在浏览器中打开下载记录,选中固件右键,复制下载链接(保存好链接,后面步骤要用到)。

在这里插入图片描述

3.1.8 进入此处,获取阿里云mqtt证书,保存好证书,后续步骤要使用。

在这里插入图片描述
至此,服务器已准备完成。

3.2 esp32端代码编写

根据完整代码进行修改,主要修改wifi的名称、wifi密码、固件链接和证书,其他的不用修改。
完整代码

#include <WiFi.h>
#include <HTTPUpdate.h>

/**********根据实际修改**********/
const char *wifi_ssid = "ssid";        // WIFI名称,区分大小写,不要写错
const char *wifi_password = "password"; // WIFI密码

//远程固件链接,粘贴3.1.7步的下载链接
const char *ota_url = "https://ota-cn-shanghai.iot-thing.aliyuncs.com/ota/5085ca32629a3c9b1ffcd8013f827122/cmhlq6k9r00023j9tghejto6c.bin?auth_key=1762415464-4ca466fb654146e785e8121a5157be8a-0-db8b8584083fee1b10c489de ...";

//网站证书,用记事本打开3.1.8步下载的证书,并按如下格式调整。
static const char *server_certificate = "-----BEGIN CERTIFICATE-----\n"
"MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\n"
"A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\n"
"b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw\n"
"MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\n"
"YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT\n"
"aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ\n"
"jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp\n"
"xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp\n"
"1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\n"
"snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ\n"
"U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8\n"
"9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E\n"
"BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B\n"
"AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz\n"
"yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE\n"
"38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP\n"
"AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad\n"
"DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\n"
"HMUfpIBvFSDJ3gyICh3WZlXi/...==\n"
"-----END CERTIFICATE-----\n";

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

//当升级结束时,打印日志
void update_finished()
{
    Serial.println("CALLBACK:  HTTP update process finished");
}

//当升级中,打印日志
void update_progress(int cur, int total)
{
    Serial.printf("CALLBACK:  HTTP update process at %d of %d bytes[%.1f%%]...\r\n", cur, total, cur * 100.0 / total);
}

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

/**
* @brief 固件升级函数,通过http请求获取远程固件,实现升级
*
* @param update_url 待升级远程固件bin文件的地址
* @return t_httpUpdate_return 升级最终状态
*/
t_httpUpdate_return updateBin(const char *update_url)
{
    Serial.println("start update");
        WiFiClientSecure UpdateClient;
    UpdateClient.setCACert(server_certificate);
    // WiFiClient UpdateClient;

    httpUpdate.onStart(update_started);     //当升级开始时
    httpUpdate.onEnd(update_finished);      //当升级结束时
    httpUpdate.onProgress(update_progress); //当升级中
    httpUpdate.onError(update_error);       //当升级失败时

    t_httpUpdate_return ret = httpUpdate.update(UpdateClient, update_url);

    return ret;
}

void setup()
{
    Serial.begin(115200); //波特率115200
    Serial.print("Connection WIFI");
    WiFi.begin(wifi_ssid, wifi_password); //连接wifi
    while (WiFi.status() != WL_CONNECTED)
        { //等待连接wifi
            delay(500);
            Serial.print(".");
        }
    Serial.println("");
    t_httpUpdate_return ret = updateBin(ota_url); //开始升级
    switch (ret)
        {
            case HTTP_UPDATE_FAILED: //当升级失败
                Serial.println("[update] Update failed.");
                break;
            case HTTP_UPDATE_NO_UPDATES: //当无升级
                Serial.println("[update] Update no Update.");
                break;
            case HTTP_UPDATE_OK: //当升级成功
                Serial.println("[update] Update ok.");
                break;
        }
}

void loop()
{
}

3.3 验证

在PlatformIO中先执行一边擦除,再执行烧录,以保证flash区是干净的。

3.3.1 设备连上wifi之后,就开始下载固件。

在这里插入图片描述

3.3.2 固件下载完成,复位重启,运行新固件。

在这里插入图片描述

结语

本章内容到此结束啦,若本文对你有帮助或是你觉得不错的话,能否点个赞呢!
咱们下期再见!

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐