本文将介绍 OTA 接入流程,包括配置当前固件版本、处理升级通知、发起固件下载、固件刷写以及上报升级进度和结果等。
前提条件
接入前需完成以下准备工作:
1. 按照 登录与注册 文档跑通
tc_iot_login 登录功能。2. 按照 OTA 升级包 文档在后台为需要升级的模块创建并发布固件版本,确保模块名称与 OTA 初始化配置中的
module_name 完全一致。3. 确认下载目录可写且有足够空间;设备没有文件系统时,可联系技术支持。
接入步骤
步骤 1:配置当前固件信息并初始化 OTA
SDK 登录成功后,填写各模块当前运行的固件版本,注册回调,并调用
tc_iot_ota_init。SDK 上报各模块当前版本,并在有可用升级时通过回调通知升级任务。字段 | 说明 |
module_name | 固件模块名称,以 \\0 结尾;须与后台固件模块名称一致。 |
module_version | 当前运行的固件版本,以 \\0 结尾。 |
firmware_info | 各模块当前固件信息数组。 |
firmware_info_count | firmware_info 数组中的模块数量。 |
#include <stdio.h>#include <string.h>#include "tc_iot.h"#include "tc_iot_ota.h"static void on_receive_firmware_upgrade_notify(const tc_iot_ota_firmware_info_t *firmware_info, void *user_data);static void on_download_firmware_progress(const tc_iot_ota_firmware_info_t *firmware_info, uint32_t current_size,uint32_t total_size, void *user_data);static void on_download_firmware_result(const tc_iot_ota_firmware_info_t *firmware_info, tc_iot_error_e error_code,const char *error_message, const char *file_path, void *user_data);tc_iot_ota_firmware_info_t firmware_info[] = {{.module_name = "mcu",.module_version = "1.0.0",},{.module_name = "wifi",.module_version = "1.1.0",}}; // 示例版本;实际接入时填写当前运行的固件版本。tc_iot_ota_config_t ota_config = {.firmware_info = firmware_info,.firmware_info_count = sizeof(firmware_info) / sizeof(firmware_info[0]),};tc_iot_ota_observer_t ota_observer;memset(&ota_observer, 0, sizeof(ota_observer));ota_observer.on_receive_firmware_upgrade_notify =on_receive_firmware_upgrade_notify;ota_observer.on_download_firmware_progress = on_download_firmware_progress;ota_observer.on_download_firmware_result = on_download_firmware_result;tc_iot_error_e error = tc_iot_ota_init(&ota_config, &ota_observer, NULL);if (error != TC_IOT_ERR_SUCCESS) {printf("tc_iot_ota_init failed: %d\\n", error);}
on_receive_firmware_upgrade_notify 和 on_download_firmware_result 必须注册;不需要处理下载进度时,on_download_firmware_progress 可设为 NULL。注意:
同一个
module_name 只能注册一次。user_data 为自定义回调上下文,其指向的对象须在 OTA 反初始化及相关回调完成前保持有效。步骤 2:处理升级通知,检查更新条件并发起下载
有可用升级时,SDK 调用
on_receive_firmware_upgrade_notify,通知目标模块和目标版本。设备检查本地状态,确认满足更新条件后,调用 tc_iot_ota_download_firmware 发起下载。以下示例假设本地更新条件已满足,在回调中发起下载:
#define OTA_DOWNLOAD_DIRECTORY "./ota_firmware"static void on_receive_firmware_upgrade_notify(const tc_iot_ota_firmware_info_t *firmware_info, void *user_data) {(void)user_data;printf("[ota] receive upgrade: module=%s, target_version=%s\\n",firmware_info->module_name, firmware_info->module_version);tc_iot_error_e error =tc_iot_ota_download_firmware(firmware_info, OTA_DOWNLOAD_DIRECTORY);if (error != TC_IOT_ERR_SUCCESS) {printf("[ota] submit download failed: %d\\n", error);}}
download_directory 指定固件保存目录。下载成功后,使用结果回调提供的 file_path 读取固件。注意:
firmware_info 的模块名称和目标版本须与本次升级通知一致;延后下载时须先复制该信息。SDK 同一时间只能处理一个 OTA 任务,下载进行中不得重复调用下载接口。
OTA 回调中不得执行耗时或阻塞操作。
步骤 3:处理固件下载进度(可选)
下载期间,SDK 通过
on_download_firmware_progress 通知已下载字节数和固件总字节数。示例按字节数计算下载百分比:static void on_download_firmware_progress(const tc_iot_ota_firmware_info_t *firmware_info, uint32_t current_size,uint32_t total_size, void *user_data) {(void)user_data;uint32_t progress =total_size == 0 ? 0 : (uint32_t)(((uint64_t)current_size * 100u) / total_size);printf("[ota] downloading: module=%s, version=%s, progress=%u%% (%u/%u)\\n",firmware_info->module_name, firmware_info->module_version, progress,current_size, total_size);}
tc_iot_ota_report_upgrade_progress 用于上报固件刷写进度。步骤 4:处理下载结果并执行固件刷写
SDK 通过
on_download_firmware_result 通知下载结果。仅在 error_code 为 TC_IOT_ERR_SUCCESS 时执行固件刷写:场景 | error_code | error_message | file_path |
下载并校验成功 | TC_IOT_ERR_SUCCESS | NULL | 固件文件路径 |
下载或校验失败 | 非 TC_IOT_ERR_SUCCESS | 失败原因 | NULL |
static void on_download_firmware_result(const tc_iot_ota_firmware_info_t *firmware_info, tc_iot_error_e error_code,const char *error_message, const char *file_path, void *user_data) {ota_demo_context_t *context = (ota_demo_context_t *)user_data;if (error_code != TC_IOT_ERR_SUCCESS) {printf("[ota] download failed: module=%s, version=%s, error=%d, message=%s\\n",firmware_info->module_name, firmware_info->module_version, error_code,error_message ? error_message : "");return;}printf("[ota] firmware ready: module=%s, version=%s, path=%s\\n",firmware_info->module_name, firmware_info->module_version, file_path);/* 复制回调参数并通知升级线程执行固件刷写,不能长期持有回调中的指针。 */schedule_firmware_install(context, firmware_info, file_path);}
示例中的
schedule_firmware_install 由接入方实现,用于复制固件信息和文件路径,并通知独立升级线程执行固件刷写。注意:
firmware_info、error_message 和 file_path 仅在回调期间有效,延后使用时必须复制内容。步骤 5:上报固件刷写进度和结果
设备在固件刷写过程中,按实际进度调用
tc_iot_ota_report_upgrade_progress。固件刷写失败,或成功后无需重启时,调用 tc_iot_ota_report_upgrade_result 上报结果。如果固件刷写成功后需要重启,设备在新固件启动并登录后,将实际运行的新版本填入
tc_iot_ota_init 配置。SDK 会上报新版本,后台据此确认升级完成。以下示例演示固件刷写函数返回后主动上报结果的用法:
static void install_firmware(const tc_iot_ota_firmware_info_t *firmware_info,const char *file_path) {tc_iot_error_e error =tc_iot_ota_report_upgrade_progress(firmware_info, 0);if (error != TC_IOT_ERR_SUCCESS) {printf("[ota] report upgrade progress failed: %d\\n", error);}/* 平台固件刷写过程中,应继续按实际固件刷写进度调用进度上报接口。 */bool install_success = platform_install_firmware(file_path);if (install_success) {error = tc_iot_ota_report_upgrade_progress(firmware_info, 100);if (error != TC_IOT_ERR_SUCCESS) {printf("[ota] report upgrade progress failed: %d\\n", error);}}int32_t result_code = install_success ? 0 : -1;const char *description = install_success ? "upgrade_success" : "upgrade_failed";error = tc_iot_ota_report_upgrade_result(firmware_info, result_code, description);if (error != TC_IOT_ERR_SUCCESS) {printf("[ota] report upgrade result failed: %d\\n", error);}}
接口 | 说明 |
tc_iot_ota_report_upgrade_progress(firmware_info, progress) | 上报固件刷写进度, progress 取值范围为 0~100。 |
tc_iot_ota_report_upgrade_result(firmware_info, 0, description) | 上报升级成功。 |
tc_iot_ota_report_upgrade_result(firmware_info, -1, description) | 上报升级失败。 |
注意:
下载成功后才能上报固件刷写进度或结果。
上报时使用下载成功回调中的目标模块和目标版本。
步骤 6:反初始化 OTA
设备退出登录或释放 SDK 前,调用
tc_iot_ota_deinit 停止下载并释放 OTA 资源:tc_iot_error_e error = tc_iot_ota_deinit();if (error != TC_IOT_ERR_SUCCESS) {printf("tc_iot_ota_deinit failed: %d\\n", error);}tc_iot_logout();tc_iot_deinit();
常见问题
现象 | 排查建议 |
tc_iot_ota_init 返回 TC_IOT_ERR_NOT_INITIALIZED | 先调用 tc_iot_init 初始化 SDK,并调用 tc_iot_login 登录。 |
tc_iot_ota_init 返回 TC_IOT_ERR_NOT_CONNECTED | 等待 tc_iot_login 回调通知登录成功后,再初始化 OTA。 |
tc_iot_ota_init 返回 TC_IOT_ERR_OTA_INIT_PARAM_INVALID | 检查 firmware_info 和 firmware_info_count 是否正确;模块名称不可重复,名称和版本字符串以 \\0 结尾。 |
tc_iot_ota_init 返回 TC_IOT_ERR_OTA_INIT_OBSERVER_NULL | 需要传入合法的 observer,至少包含必填的 on_receive_firmware_upgrade_notify 和 on_download_firmware_result。 |
on_download_firmware_result 回调中的 error_code 为 TC_IOT_ERR_OTA_START_FAILED | 检查模块名称和目标版本是否与本次升级通知一致,以及是否重复调用下载接口。 |
烧录完成重启后仍收到相同升级通知 | 确认新固件已生效,并在 tc_iot_ota_init 中使用实际运行的新版本初始化 |