ESP32使用阿里云OTA远程升级

1. 前言
之前的esp32c3模组的flash太小了,做不了ota测试,目前更换为esp32s3可以很方便进行ota测试了,之后的例程会一直使用s3模组进行练习。
有了ota可以很方便进行调试烧录,即使设备不在我手上,也能烧录程序。遇到最难的一部分是没有使用阿里云的sdk,所以在使用https的签名认证上一直卡着,但是可以取消验证就能OTA成功了。
2. 使用ESP32-S3-N16R8模组
修改:
1.flash size为16M.
2.启用psram(OCT8线模式,auto-detect,选择自动检测容量大小)
3.启用自定义分区表partition,分配两个ota分区
3. 文件服务器
局域网部署测试:telnet 192.168.10.1 8027 #测试端口是否通,防火墙没有阻止
3.1 公网部署nginx
version: "3.8"
services:
nginx:
image: nginx:alpine
container_name: web_static
restart: unless-stopped
volumes:
- ./web_static/html:/usr/share/nginx/html:ro
- ./web_static/conf/nginx.conf:/etc/nginx/nginx.conf:ro
networks:
- my_npm_prj_npm_network
expose:
- "80" #端口声明
networks:
my_npm_prj_npm_network:
external: true
# nginx配置
events {}
http {
server {
listen 80;
root /usr/share/nginx/html/esp-ota;
index index.html
location / {
try_files $uri $uri/ =404;
}
}
server {
listen 80;
location /love {
root /usr/share/nginx/html;
try_files /blog/love.html =404;
}
}
}

3.2 公网下载bin文件
https://test.eehaiou.com/prj-v1_0_1.bin
使用自己搭建的文件服务器,用于ota测试
4. OTA流程

启用ESP HTTPS OTA 的 Allow HTTP for OTA,仅仅测试使用
可选:上报进度到云端
4.1 设置ota分区
复制partitions_two_ota.csv(双 OTA 分区,无加密 / 无large分区优化/coredump 分区)到自己工程目录下
重命名为partitions.csv
# Name, Type, SubType, Offset, Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
nvs, data, nvs, , 0x4000,
otadata, data, ota, , 0x2000,
phy_init, data, phy, , 0x1000,
# factory, app, factory, , 1M, #删除了factory默认分区
ota_0, app, ota_0, , 4M,
ota_1, app, ota_1, , 4M,
# 剩余空间作为文件存储分区
storage, data, spiffs, , 7M,
idf.py partition-table #打印验证
4.2 上报版本
1.创建version.c、version.h 统一管理版本:

2.使用CMakeList设置版本号,写入固件头部:
set(PROJECT_VER "1.0.6")
使用ota函数获取字段:
esp_ota_get_running_partition();
esp_ota_get_partition_description(running_part, &app_desc);
snprintf(app_version, sizeof(app_version), "%s", app_desc.version);

4.3 发布版本号
向主题topic=/ota/device/inform/{product}/esp32-mini-dev01发上行消息
{
"id": "123",
"params": {
"version": "1.0.1",
"module": "MCU" #上报默认(default)模块的版本号时,可以不上报module参数;设备的默认(default)模块的版本号代表整个设备的固件版本号
}
}
版本号上报成功,回应状态200:

上报版本号后报可以查看到设备目前的版本分布情况:

4.4 在平台添加升级任务并下发通知
在mqtt成功连接到服务器事件之后,订阅/ota/device/upgrade/${productName}/${deviceName}主题,接收下行通知
上传升级包bin文件:

手动在云端下发的ota升级通知:
设备收到通知并打印消息payload:

4.5 使用HTTP协议测试,避开TLS层
ESP HTTPS OTA → Allow HTTP for OTA #使能HTTP下载
ESP-TLS → Allow potentially insecure options #避开TLS证书签名
ESP-TLS → Skip server certificate verification by default (WARNING: ONLY FOR TESTING PURPOSE, READ HELP) #避开TLS证书签名
4.6 触发OTA任务
关键代码部分:
// HTTPS OTA 配置, 跳过证书验证
esp_http_client_config_t http_cfg = {
.url = g_ota_url, // 阿里云下发的动态 URL
.timeout_ms = 120000,
.keep_alive_enable = true,
.skip_cert_common_name_check = true, // 显式跳过证书域名校验
.cert_pem = NULL, // 不使用证书
.use_global_ca_store = false, // 不使用全局 CA 存储
};
esp_https_ota_config_t ota_config = {
.http_config = &http_cfg,
.partial_http_download = true, // 启用分块下载
.max_http_request_size = 8192, // 每块大小(字节)
};
// 执行OTA升级
esp_err_t ret = esp_https_ota(&ota_config);
if (ret == ESP_OK) {
ESP_LOGI(TAG, "OTA upgrade has been successful! The system is about to restart.");
esp_restart();
} else {
ESP_LOGE(TAG, "OTA upgrade failed: %s", esp_err_to_name(ret));
}
vTaskDelete(NULL);
使用json解析出下载地址URL,配置好ota_config对象,调用esp_https_ota抽象接口:

OTA成功了,在新版本的软件中上报了目标版本号,云平台就标记通过了验证:

5. 最后
代码仓库:
git clone -b v1.2 --single-branch https://github.com/haiou1220/esp32c3-mini-mqtt.git
#git checkout tags/v1.2
总结:
对比 OneNET OTA 的需要手动设置 Header(认证、内容类型等)和 设置 POST Body(设备信息、当前版本)等信息,最后post一个请求并在事件回调中接收OTA数据的下发,要完成要主动拉取并处理 HTTP 交互。设备主动拉取模式。
阿里云 OTA 显得更加简单,只需关注 MQTT 指令解析出URL地址并调用esp_https_ota,即可完成。云端主动推送模式。
自动回滚功能:
IDF可以开启OTA 回滚机制( CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE),但是默认是关闭的。
尝试使用回顾机制:
在MQTT 连接成功后,马上标记。一般先上报版本,再标记合法。
异常重启或者长时间未标记,引导加载程序会自动回滚到上一个可用的 OTA 分区
使用esp_ota_mark_app_valid_cancel_rollback()标记为合法,可以防止因新固件启动后出现异常而导致的自动回滚