如何使用HTTPS协议下载OTA升级包实现设备升级

您所在的位置:网站首页 物联网平台下载 如何使用HTTPS协议下载OTA升级包实现设备升级

如何使用HTTPS协议下载OTA升级包实现设备升级

2024-07-09 11:58| 来源: 网络整理| 查看: 265

本文以C Link SDK中的Demo文件./demo/fota_posix_demo.c为例,介绍如何调用Link SDK的API,帮助设备端使用HTTPS协议,下载仅含单个升级文件的OTA升级包,实现设备的OTA升级。

背景信息OTA升级功能的更多信息,请参见OTA升级概述。OTA升级功能基于MQTT接入,开发过程中涉及MQTT接入的代码说明,请参见MQTT接入。步骤一:初始化OTA功能添加头文件。…… …… #include "aiot_ota_api.h" ……配置底层依赖和日志输出。 aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile); aiot_state_set_logcb(demo_state_logcb);调用aiot_ota_init,创建OTA客户端实例,并初始化默认参数。 ota_handle = aiot_ota_init(); if (NULL == ota_handle) { printf("aiot_ota_init failed\r\n"); aiot_mqtt_deinit(&mqtt_handle); return -2; }步骤二:配置OTA功能

调用aiot_ota_setopt,配置以下功能。

关联MQTT连接的句柄。重要 在配置OTA参数前,请确保已配置设备认证信息等相关参数。具体操作,请参见MQTT配置连接参数。示例代码: aiot_ota_setopt(ota_handle, AIOT_OTAOPT_MQTT_HANDLE, mqtt_handle);相关参数:配置项示例说明AIOT_OTAOPT_MQTT_HANDLEmqtt_handleOTA功能的请求基于MQTT连接,通过该配置项,关联MQTT连接句柄。配置OTA升级指令消息的回调。示例代码: aiot_ota_setopt(ota_handle, AIOT_OTAOPT_RECV_HANDLER, demo_ota_recv_handler);相关参数:配置项示例说明AIOT_OTAOPT_MQTT_HANDLERdemo_ota_recv_handler当设备收到来自物联网平台的OTA升级指令,调用该回调函数。步骤三:上报设备当前版本号

设备建立MQTT连接后,调用aiot_ota_report_version,上报当前设备的版本号。物联网平台根据版本号,判断是否需要升级。

以下示例代码中,OTA升级前设备上报的版本号为1.0.0,在实际业务中,您需从设备的配置区获取实际的版本号,并执行编写代码。

重要

设备进行OTA升级前,需至少上报一次版本号。

cur_version = "1.0.0"; res = aiot_ota_report_version(ota_handle, cur_version); if (res < STATE_SUCCESS) { printf("aiot_ota_report_version failed: -0x%04X\r\n", -res); }步骤四:接收升级指令在物联网平台添加升级包,并发起升级任务后,物联网平台向设备端下发升级指令。具体操作,请参见添加升级包。设备端调用aiot_mqtt_recv接收消息,当消息被识别为OTA升级指令后,调用回调函数demo_ota_recv_handler。编写回调函数的处理逻辑。您可以参考以下内容,编写回调函数的处理逻辑:物联网平台通过Topic /ota/device/upgrade/${ProductKey}/${DeviceName},向设备下发OTA升级包指令。

${ProductKey}和${DeviceName}的详细说明,请参见获取设备认证信息。

OTA升级指令的类型为AIOT_OTARECV_FOTA。void demo_ota_recv_handler(void *ota_handle, aiot_ota_recv_t *ota_msg, void *userdata) { switch (ota_msg->type) { case AIOT_OTARECV_FOTA: { uint32_t res = 0; uint16_t port = 443; uint32_t max_buffer_len = (8 * 1024); aiot_sysdep_network_cred_t cred; void *dl_handle = NULL; void *last_percent = NULL; if (NULL == ota_msg->task_desc) { break; } …… …… }OTA升级指令消息的Alink数据格式说明,请参见物联网平台推送OTA升级包信息。OTA升级指令消息的数据结构类型为aiot_ota_recv_t,Link SDK自动解析收到的升级指令消息。您可以参考示例代码,编写回调函数的处理逻辑,请参见步骤五:下载升级包,进行OTA升级。步骤五:下载升级包,进行OTA升级重要 设备端收到物联网平台推送的升级包消息后,不会自动下载升级包,您需要调用Link SDK提供的API启动下载。

触发函数demo_ota_recv_handler后,基于HTTPS协议,下载器发起下载请求,然后接收升级包,实现OTA升级。

初始化下载器。调用aiot_download_init,创建download客户端实例,并初始化默认参数。 dl_handle = aiot_download_init(); if (NULL == dl_handle) { break; } printf("OTA target firmware version: %s, size: %u Bytes \r\n", ota_msg->task_desc->version, ota_msg->task_desc->size_total); if (NULL != ota_msg->task_desc->extra_data) { printf("extra data: %s\r\n", ota_msg->task_desc->extra_data); } memset(&cred, 0, sizeof(aiot_sysdep_network_cred_t)); cred.option = AIOT_SYSDEP_NETWORK_CRED_SVRCERT_CA; cred.max_tls_fragment = 16384; cred.x509_server_cert = ali_ca_cert; cred.x509_server_cert_len = strlen(ali_ca_cert);配置下载参数。调用aiot_download_setopt,配置下载任务的相关参数。 /* 设置下载时为TLS下载 */ aiot_download_setopt(dl_handle, AIOT_DLOPT_NETWORK_CRED, (void *)(&cred)); /* 设置下载时访问的服务器端口号 */ aiot_download_setopt(dl_handle, AIOT_DLOPT_NETWORK_PORT, (void *)(&port)); /* 设置下载的任务信息, 通过输入参数 ota_msg 中的 task_desc 成员得到, 内含下载地址, 固件大小, 固件签名等 */ aiot_download_setopt(dl_handle, AIOT_DLOPT_TASK_DESC, (void *)(ota_msg->task_desc)); /* 设置下载内容到达时, SDK将调用的回调函数 */ aiot_download_setopt(dl_handle, AIOT_DLOPT_RECV_HANDLER, (void *)(demo_download_recv_handler)); /* 设置单次下载最大的缓存长度, 每当这个长度的内存读满了后会通知用户 */ aiot_download_setopt(dl_handle, AIOT_DLOPT_BODY_BUFFER_MAX_LEN, (void *)(&max_buffer_len)); /* 设置 AIOT_DLOPT_RECV_HANDLER 的不同次调用之间共享的数据, 比如例程把进度存在这里 */ last_percent = malloc(sizeof(uint32_t)); if (NULL == last_percent) { aiot_download_deinit(&dl_handle); break; } memset(last_percent, 0, sizeof(uint32_t)); aiot_download_setopt(dl_handle, AIOT_DLOPT_USERDATA, (void *)last_percent);发起下载请求。启动下载线程demo_ota_download_thread。 res = pthread_create(&g_download_thread, NULL, demo_ota_download_thread, dl_handle); if (res != 0) { printf("pthread_create demo_ota_download_thread failed: %d\r\n", res); aiot_download_deinit(&dl_handle); free(last_percent); } else { /* 将下载线程设置为detach类型, 固件内容获取完毕后可自主退出 */ pthread_detach(g_download_thread); }通过下载线程demo_ota_download_thread,调用aiot_download_send_request,向指定的升级包存储服务器,发起HTTPS协议的GET请求, 请求下载升级包。示例代码:void *demo_ota_download_thread(void *dl_handle) { int32_t ret = 0; printf("starting download thread in 2 seconds ......\n"); sleep(2); /* 向升级包存储服务器请求下载。 */ /* * TODO: 以下示例代码,以1个请求获取升级包全部内容。 * 设备资源比较少, 或者网络较差时, 也可以分段下载, 需要组合 * * aiot_download_setopt(dl_handle, AIOT_DLOPT_RANGE_START, ...); * aiot_download_setopt(dl_handle, AIOT_DLOPT_RANGE_END, ...); * aiot_download_send_request(dl_handle); * * 在该情况下, 需要把以上组合语句放置到循环中, 多次 send_request 和 recv * */ …… …… }相关参数:

通过AIOT_DLOPT_RANGE_START和AIOT_DLOPT_RANGE_END,可以分段下载升级包。

例如,一个1024字节的升级包分两次下载,两次的参数可分别设置为:第一次:AIOT_DLOPT_RANGE_START=0,AIOT_DLOPT_RANGE_END=511第二次:AIOT_DLOPT_RANGE_START=512,AIOT_DLOPT_RANGE_END=1023接收升级包。下载请求发送后,通过下载线程demo_ota_download_thread,调用aiot_download_recv, 接收升级包消息。接收的应答消息触发回调函数demo_download_recv_handler, 您需将下载的升级包保存至设备的本地存储或文件系统。void *demo_ota_download_thread(void *dl_handle) { …… …… while (1) { /* 从网络收取服务器回应的升级包内容 */ ret = aiot_download_recv(dl_handle); /* 升级包全部下载完时, aiot_download_recv() 的返回值会等于 STATE_DOWNLOAD_FINISHED, 否则是当次获取的字节数。 */ if (STATE_DOWNLOAD_FINISHED == ret) { printf("download completed\n"); break; } } …… …… }定义回调函数demo_download_recv_handler,编写升级包下载后的存放和升级逻辑。说明 示例代码仅做打印处理,未配置升级包的存储和烧录逻辑,您需根据环境自行保存升级包,最后运行升级包,完成OTA升级。void demo_download_recv_handler(void *handle, const aiot_download_recv_t *packet, void *userdata) { uint32_t data_buffer_len = 0; uint32_t last_percent = 0; int32_t percent = 0; /* 目前只支持 packet->type 为 AIOT_DLRECV_HTTPBODY 的情况 */ if (!packet || AIOT_DLRECV_HTTPBODY != packet->type) { return; } percent = packet->data.percent; /* userdata可以存放 demo_download_recv_handler() 的不同次进入之间, 需要共享的数据 */ /* 这里用来存放上一次进入本回调函数时, 下载的固件进度百分比 */ if (userdata) { last_percent = *((uint32_t *)(userdata)); } data_buffer_len = packet->data.len; /* 如果percent为负数, 说明发生了收包异常或者digest校验错误 */ if (percent < 0) { printf("exception: percent = %d\r\n", percent); if (userdata) { free(userdata); } return; } …… …… }上报下载进度。

通过定义回调函数demo_download_recv_handler,调用aiot_download_report_progress,向物联网平台上报下载进度,以及升级过程中发生的异常(例如:烧录失败、网络断开等)。

查看上报进度:

会直接显示在物联网平台控制台。更多信息,请参见查看升级情况。

正常和异常下载时上报进度:如果下载正常,则以整数的形式,向物联网平台上报下载情况。Link SDK会自动计算出percent参数值,并在回调中,将其返回至物联网平台。如果下载异常,或下载之后固件的烧录异常,则将异常发送至物联网平台。设备和物联网平台的协议错误码,请参见aiot_ota_protocol_errcode_t 。void demo_download_recv_handler(void *handle, const aiot_download_recv_t *packet, void *userdata) { …… …… /* * TODO: 下载一段升级包成功后, 用户应该将 * 起始地址为packet->data.buffer, 长度为packet->data.len的内存,保存至设备本地存储位置或文件系统。 * * 如果烧写失败, 还应该调用aiot_download_report_progress(handle, -4),将失败信息上报至物联网平台。 */ /* 当percent入参的值为100时, 说明升级包已全部下载成功。 */ if (percent == 100) { /* * TODO: 此时, 应该完成所有的固件烧录, 保存当前工作, 重启设备, 切换到新的固件上启动。 并且, 新的固件必须要以 aiot_ota_report_version(ota_handle, new_version); 将升级后的新版本号(比如从1.0.0升到1.1.0, 则new_version的值为1.1.0)上报给物联网平台。 物联网平台收到了新的版本号上报后, 才会判定升级成功, 否则会认定升级失败。 */ } /* 简化输出, 只有距离上次的下载进度增加5%以上时, 才会打印进度, 并把进度上报给云端 */ if (percent - last_percent >= 5 || percent == 100) { printf("download %03d%% done, +%d bytes\n", percent, data_buffer_len); aiot_download_report_progress(handle, percent); if (userdata) { *((uint32_t *)(userdata)) = percent; } } }退出下载器。

升级包内容下载完成后,调用aiot_download_deinit,销毁download会话,下载线程自行退出。

aiot_download_deinit(&dl_handle); printf("download thread exit\n");步骤六:上报升级后版本号

具体操作,请参见步骤三:上报设备当前版本号。

说明

设备完成OTA升级后,需上报最新版本号,否则物联网平台视该OTA升级任务为失败。

如果设备升级后需重启,则设备重启后需上报最新的版本号。

示例代码中不包含升级完成后重新上报版本号的过程,您需自行实现。步骤七:断开连接说明

MQTT接入常应用于长连接的设备,程序通常不会运行至此。

例程的主线程任务为配置参数并成功建立连接。连接建立后,主线程可进入休眠。

调用aiot_mqtt_disconnect,向物联网平台发送断开连接的报文,然后断开网络连接。

res = aiot_mqtt_disconnect(mqtt_handle); if (res < STATE_SUCCESS) { aiot_mqtt_deinit(&mqtt_handle); printf("aiot_mqtt_disconnect failed: -0x%04X\n", -res); return -1; }步骤八:退出OTA程序

调用aiot_ota_deinit,销毁OTA客户端实例,释放资源。

aiot_ota_deinit(&ota_handle);后续步骤

例程文件配置完成后,需进行编译,生成可执行文件./output/fota-posix-demo。

更多信息,请参见编译与运行。

关于运行结果的详细说明,请参见运行日志。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3