物联网OTA服务

介绍

腾讯云天工OTA服务平台是致力为物联网智能设备系统安全保驾护航的固件升级服务。我们为广大设备厂商提供稳定、快速、易用、高效的固件下发服务,以保证在洞察到设备系统安全隐患后能迅速响应,降低潜在损失。

除常规的下发服务外,腾讯云物联网OTA服务将逐步整合腾讯自主研发,业内领先的智能设备硬件安全检测与修复能力,为所覆盖的智能设备群打造安全护城河,是设备厂商最佳的智能设备系统升级和漏洞安全修复解决方案。

云端OTA操作

1. 账号体系

腾讯云物联网OTA作为腾讯云天工腾讯云物联网产品的功能,沿用腾讯账号体系,如何注册和登录详见腾讯云物联网产品文档。

2. 使用前准备

在创建物模型时需要选择是否开启OTA远程升级,只有开启服务后,该物模型下面的设备才可以进行固件升级。在创建时未开启服务的物模型,也可以在物模型编辑页面开启服务。

开启OTA远程升级服务后,用户需要选择下发协议。

  • HTTPS协议:目前只有Android和Linux操作系统的设备才可以选择https。

注意: 设备的操作系统和芯片类型,这两个字段在填写后将无法修改,请慎重填写。

  • 对于Linux操作系统的设备,您可以提工单把交叉编译的环境和参数给我们,我们将针对您的设备编译相应的SDK,详情请查看跨平台OTA SDK接入文档。
  • 对于Android和Linux操作系统的设备的升级任务,在设备端我们提供刷写固件、重启等功能。选择了https协议之后,您还需要填写设备的操作系统和芯片类型。
  • MQTT协议:对所有操作系统的设备都适用。设备可直接集成SDK,具体的SDK配置方法请阅读设备SDK集成指南。

3. 上传升级包

OTA升级服务的入口在物设备型项目详情页中,左侧选择 OTA,主界面:

具体操作方法如下:

a. 登录腾讯云官网,点击右上角的“管理控制台”,快速进入控制台界面。

b. 选择“产品服务>物联网服务>腾讯云物联网 腾讯云物联网”,进入“天工物联网”控制台。

c. 点击设备型项目的项目名称,选择选择“OTA远程升级”,进入OTA页面;点击“添加升级包”进入添加升级包页面。

按照要求填写升级包创建信息,各字段的填写规则如下表:

字段填写方式说明备注物模型下拉框-必填选择升级包选择文件文件大小不超过50M必选版本号填空为了便于管理,版本号有严格的形式,只能以x.x.x的形式命名必填版本描述下拉框可填写128字以内的版本备注选填

完成填写后,点击“确定”即可上传升级包。

上传成功后能在升级包列表页看到新创建的升级包。点击版本号可以查看升级包详情。点击物模型会跳到物模型详情页。点击“升级”可以用该升级包创建升级任务。

在升级包的详情页可以看到该升级包上传的时间、已用该升级包创建的升级任务等信息。点击具体的任务可以跳转到任务详情页。

4. 创建升级任务

在升级包列表页或者升级任务页均可以创建升级任务,进入任务信息填写:

字段填写方式说明备注任务名称填空3-32位字符,支持中英文和数字必填物模型下拉框选择升级哪个物模型下的设备必选版本号下拉框选择升级包的版本号必填任务描述填空128个字符以内可选设备筛选单选框全量下发、版本号筛选和上传升级设备列表三种。
全量下发:升级该物模型下的所有设备;
版本号筛选:可以选择特定版本号的设备进行升级,支持多选;
上传升级设备列表:用户可上传一个 .txt 文件,文件中罗列需要升级的设备的ID必选

完成填写后,点击“确定”完成创建。

5. 追踪升级任务进度

在升级任务详情页可以追踪任务进度,可以看到升级耗时、升级设备总数、升级成功数和升级失败数。在设备信息栏有每台设备的任务进度。

设备端使用MQTT OTA

MQTT OTA的功能

  • 云端向设备推送固件升级信息,包括固件包的URL
  • 设备向云端上报固件升级的结果

用户需要适配自己的设备,实现固件刷写、重启等功能。

通过BAIDU IoT EDGE SDK使用MQTT OTA

说明:推荐用户优先使用腾讯云提供的SDK。腾讯云提供的SDK封装了MQTT客户端SDK,屏蔽了MQTT客户端SDK的细节和topic信息,可以帮助用户实现业务的快速部署。

用户可以在设备端安装腾讯云提供的SDK,并配置连接信息,实现设备与腾讯云腾讯云物联网的快速对接。

有关IoT Edge SDK的下载和安装,请查看:https://github.com/baidu/iot-edge-c-sdk

通过MQTT客户端使用MQTT OTA

有些情况下,设备<—>云的交互需要立刻返回某种结果,或者立刻给予确认。比如设备向云查询最新的固件版本、云请求设备端开始固件升级。

除了用shadow做交互,腾讯云物联网还使用了一种直接的Method调用。Method调用代表着一种请求–响应式的交互,与HTTP调用很类似。它支持设备->云和云->设备这两种请求方向。

Method的MQTT主题

设备请求腾讯云物联网(cloud method)

$baidu/iot/shadow/{deviceName}/method/cloud/req // 设备向该主题发布请求,腾讯云物联网订阅

$baidu/iot/shadow/{deviceName}/method/cloud/resp // 腾讯云物联网向该主题发布响应,设备订阅

腾讯云物联网请求设备(device method)

$baidu/iot/shadow/{deviceName}/method/device/req // 腾讯云物联网向该主题发布请求,设备订阅

$baidu/iot/shadow/{deviceName}/method/device/resp // 设备向该主题发布响应,腾讯云物联网订阅

作为设备端,在建立MQTT连接后,应当即刻订阅上面腾讯云物联网向该主题发布响应,设备订阅腾讯云物联网向该主题发布请求,设备订阅 这2个主题。

METHOD 的MQTT载荷

载荷是以Json序列化的字符串。请求和响应的格式分别如下:

请求参数

参数名称参数类型是否必须说明methodNameString必选Method名字requestIdString必选请求IDpayloadObject可选Method的参数

请求示例

{ "methodName": "updateFirmware", "requestId": "993ff7e9-018b-4246-a7ba-5dddac970054", "payload": { "someField": "someOutput" }}

响应参数

参数名称参数类型是否必须说明methodNameString必选Method名字requestIdString必选请求IDstatusint必选状态码,200-299表示正常payloadObject可选Method的结果

响应示例

{ "methodName": "updateFirmware", "requestId": "993ff7e9-018b-4246-a7ba-5dddac970054", "status": 200, "payload": { "someField": "someOutput" }}

设备与腾讯云物联网交互过程简介

上报设备版本(REPORTCURRENTFIRMWAREINFO)

通过腾讯云物联网OTA进行过固件升级的设备,腾讯云物联网知晓它的固件版本。而对于那些从未升级过的设备,应当至少使用它一次,以让腾讯云物联网知晓它的版本。

请求示例

pub $baidu/iot/shadow/{deviceName}/method/cloud/req{ "requestId": "12345", "methodName": "reportCurrentFirmwareInfo", "payload": { "firmwareVersion": "1.1.1" }}

返回如下结果:

rcv $baidu/iot/shadow/{deviceName}/method/cloud/resp{"requestId": "12345","methodName": "reportCurrentFirmwareInfo","status": 204,}

请求参数

参数名称参数类型是否必须说明firmwareVersionString必选当前版本

返回参数

上报设备OTA开始事件(REPORTFIRMWAREUPDATESTART)

在真正开始固件刷写之前,设备应当向腾讯云物联网汇报固件升级开始,作为整个固件升级流程跟踪的一部分。

请求示例

pub $baidu/iot/shadow/{deviceName}/method/cloud/req{"requestId": "12345","methodName": "reportFirmwareUpdateStart","payload": {"jobId": "9476da26-8cf3-497d-9959-c2017a248901" }}

返回示例

recv $baidu/iot/shadow/{deviceName}/method/cloud/resp{"requestId": "12345","methodName": "reportFirmwareUpdateStart","status": 204}

请求参数

参数名称参数类型是否必须说明jobIdString必选任务ID

上报设备OTA结果(REPORTFIRMWAREUPDATERESULT)

在固件升级完成之后,设备向腾讯云物联网汇报升级结果。Result字段可以是”success”表示成功,或者“failure”表示失败。

请求示例

pub $baidu/iot/shadow/{deviceName}/method/cloud/req{ "requestId": "12345", "methodName": "reportFirmwareUpdateResult", "payload": { "result": "success", "jobId": "9476da26-8cf3-497d-9959-c2017a248901" }}

返回示例

recv $baidu/iot/shadow/{deviceName}/method/cloud/resp{"requestId": "12345","methodName": "reportFirmwareUpdateResult","status": 204}

请求参数

参数名称参数类型是否必须说明jobIdString必选任务IDfirmwareUrlString必选名称firmwareVersionString必选描述
跨平台OTA SDK(HTTPS)接入

跨平台 OTA 特指控制台中 HTTPS 方式所支持的 Android、Linux 系统 OTA。

术语介绍

OTA完整包:OTA包中包含了目标版本中所有文件的完整内容

OTA差分包:OTA包使用差分算法生成,其中对于目标版本和源版本中有变化的同一文件,差分包中只包含该文件的差分patch文件(.p文件)

说明:1、特殊情况下差分包中不存在.p文件,此时表示目标版本和源版本中没有相同文件(同名、同路径)

2、完整包中只包含目标版本信息,差分包中包含源版本和目标版本信息,只有原版本与当前系统版本相同时才能执行升级

文件分段:将单个大文件按照一定的大小切分成多个小文件的过程,切分成的小文件称为分段文件

说明:1、当待升级设备上剩余空间很小,不允许存放过大的完整升级文件时,可对大文件分段,然后依此升级每个分段文件2、升级包制作时,对文件分段后,生成的每个分段文件对于整个升级包来说是一个独立文件,执行分片操作后,每个分段文件会单独生成一个分片OTA升级包

OTA升级包分片:使用ota生成工具的div命令,将完整OTA升级包切分成若干个分片OTA升级包的过程

完整的OTA升级包:OTA升级包中包含了本次升级中的所有升级文件及元信息

说明:1、完整的OTA升级包是以.bdota为后缀的升级文件2、完整的OTA升级包可以是“OTA完整包”也可以是“OTA差分包”3、完整的OTA升级包中的升级文件可以分段,也可以不分段

分片OTA升级包:完整OTA包经过OTA升级包分片操作后生成,一个分片OTA升级包中只包含一个文件

说明:分片OTA升级包中包含的文件可以是单个完整文件,也可以是单个差分文件(.p文件),也可以是一个分段文件

OTA包结构

注意: 以下OTA包结构图均为示意图,其中不包括文件的元信息和整个OTA包的头部信息。

OTA升级包分片操作过程,及其前后的OTA升级包结构示意图如下:

OTA SDK接入流程

  1. 获取SDK的方式对于Android和Linux操作系统的设备的升级任务,在设备端我们提供刷写固件、重启等功能。相关SDK目前还未开源。您需要提工单把交叉编译的环境和参数给我们,我们将针对您的设备编译相应的SDK。
  2. 在腾讯云物联网中创建物模型,在物模型的创建页面选择下发协议为https协议,并填写好操作系统、芯片类型和相关的属性,点击“创建”即可创建物模型。在物模型的详情页可以得到“OTA ID”和“OTA Secret”,:OTA ID是当前项目的唯一标识,在 ota_set_query_paramstr API中对应 QUERY_PARAM_PID 字段OTA Secret是用于SDK对数据加密的密钥,在 ota_set_query_paramstr API中对应 QUERY_PARAM_SECRET 字段
  3. 代码中接入SDK API根据实际需求,依此调用相应API,网络升级调用流程如下:

OTA SDK接口说明

include/bdota 目录下的头文件包含的接口均可使用,其中,与升级任务相关的SDK接口定义于 include/bdota/bdota.h 头文件,其中主要接口介绍如下:

ota_global_set_temp_path

  • 函数定义int ota_global_set_temp_path(const char* path);
  • 功能设置临时目录,该目录内容重启后可能丢失,被用作存储会被删除的临时文件。

ota_global_set_persistent_path

  • 函数定义int ota_global_set_persistent_path(const char* path);
  • 功能设置持久性目录,改目录内容重启后不会丢失,被用作存储预下载升级包、上报缓存文件等。

ota_create_update_manager

  • 函数定义pota_update_manager ota_create_update_manager();
  • 功能创建更新管理器对象指针pota_update_manager,该指针用于后续系列函数的调用。

ota_register_event_func

  • 函数定义

    int ota_register_event_func (pota_update_manager manger,const char event_name, // 事件名称func_event_callback event_func, // 事件发生时的回调函数void user_data // 透传给event_func的参数);

  • 功能

    为更新管理器设置回调函数

  • 参数说明

    manger : 更新管理器对象;

    event_name : 事件名称,详细说明请参见func_event_callback回调事件部分;

    event_func : 注册的事件被触发时,该回调函数会被调用;

    user_data : 用户自定义数据,该参数会作为参数透传给event_func回调函数;

  • 返回值说明

    返回0表示成功,非0表示失败。

func_event_callback

  • 函数定义

    typedef int(func_event_callback)(void user_data, // 透传参数,注册回调时指定的参数pbdstring params, // 事件的参数列表指针size_t size, // 事件参数的个数pbdstring out); // 传出参数);

  • 功能

ota_register_event_func函数中的回调函数接口定义

  • 参数说明

user_data : 用户自定义数据,即ota_register_event_func函数调用时的user_data参数,会通过该参数透传回来;

params : 事件的参数内容,不同事件类型对应不同类型的参数内容;

size : 事件的参数内容的数量;

out : 传出参数,预留位,传null即可;

  • 返回值说明

返回OTAR_OK升级继续,其它将终止升级

  • 回调事件

支持的事件名称使用宏定义,已定义的事件宏包括:

#define OTA_UPDATE_EVENT_START "start"#define OTA_UPDATE_EVENT_END "end"#define OTA_UPDATE_EVENT_PROCESS_FILE "process_file"#define OTA_UPDATE_EVENT_DELETE_FILE "delete_file"#define OTA_UPDATE_EVENT_GET_LOCAL_FILE_PATH "get_local_file_path"#define OTA_UPDATE_EVENT_SHOW_PROGRESS "show_progress"

不同回调事件,对应的回调函数参数含义不同,具体各事件对应的参数含义说明如下:

事件名称事件含义触发时机params参数含义out参数含义OTA_UPDATE_EVENT_START升级开始SDK解析升级包,第一次遇到全局头时将调用该函数,如果没有注册,则不调用无无OTA_UPDATE_EVENT_END升级结束升级包的全部文件都已经处理完毕后调用,业务放可以在该回调中修改写入设备的启动信息。例如对于AB系统,则要在该回调中完成切换启动主分区的操作参数一: “0”:使用的是分段升级,当前段处理完成,但还有后续段需要处理。“1”:升级包中的所有文件已经处理完成。无OTA_UPDATE_EVENT_PROCESS_FILE处理文件解析升级包时,当一个文件已经在本地准备好时(该文件可能来之网络、本地升级包、本地分片升级包)调用参数一:升级包中指定的当前文件的路径。参数二:偏移,当前文件内容在原始文件中的偏移。参数三:文件内容在本地硬盘上的路径,如果启用了分段功能,该内容可能为原始文件的一部分。参数四:当前文件内容大小。参数五:总文件大小。无OTA_UPDATE_EVENT_DELETE_FILE删除文件或文件夹当需要删除文件或文件夹时,调用该函数参数一:升级包中指定的待删除的文件路径。参数二:路径标识的是文件还是目录,文件用字符串0表示,目录用字符串1表示。无OTA_UPDATE_EVENT_GET_LOCAL_FILE_PATH返回本地文件系统中对应与升级包中的文件的全路径升级过程中任何需要获取本地路径完整路径的时候均可能回调次函数参数一:升级包中的文件路径本地系统中的完整文件路径OTA_UPDATE_EVENT_SHOW_PROGRESS显示进度当前版本暂未触发该事件,为后续版本保留无无

ota_set_query_paramstr

  • 函数定义

int ota_set_query_paramstr(pota_update_manager manager, const char* key, const char* value);

  • 功能

设置升级请求参数

  • 参数说明

manger : 更新管理器对象;

key:升级请求字段名称;

value:升级请求字段内容。

  • 返回值说明

    返回0表示成功,非0表示失败。

  • 已支持字段

#define QUERY_PARAM_PID "pid" // 产品ID#define QUERY_PARAM_SECRET "acckey" // 产品密钥 #define QUERY_PARAM_DID "did" // 设备唯一标识符#define QUERY_PARAM_VER "ver" // 系统版本号,格式必须为a.b.c.d#define QUERY_PARAM_MANUAL_CHECK "mchk" // 请求类型, value设置字符串1表示手动升级,其它为自动升级

ota_query_update_info

  • 函数定义

int ota_query_update_info(pota_update_manager manager);

  • 功能

执行升级请求

  • 参数说明

manger : 更新管理器对象;

  • 返回值说明

返回0表示成功,非0表示失败。

ota_download_update_pkg

  • 函数定义

int ota_download_update_pkg(pota_update_manager manager);

  • 功能

执行预下载,此函数需要在ota_query_update_info函数调用以后被调用

  • 参数说明

manger : 更新管理器对象;

  • 返回值说明

返回0表示成功,非0表示失败。

ota_set_update_param

  • 函数定义

int ota_set_update_param(pota_update_manager manager, const char* key, const char* value);

  • 功能

设置更新程序参数

  • 参数说明

manger : 更新管理器对象;

key:参数字段名称;

value:参数字段内容。

  • 返回值说明

返回0表示成功,非0表示失败。

  • 已支持字段

// 设置了该key,将执行本地升级,该key的value指明了本地包的文件路径#define OTA_UPDATE_PARAM_KEY_LOCAL_FILE "local_file"// 指定本地分段升级时当前处理的分片文件路径#define OTA_UPDATE_PARAM_KEY_SEG_FILE "seg_file"// 设置用于校验升级包的公钥路径#define OTA_UPDATE_PARAM_KEY_PUBLIC_KEY_PATH "pk"// 指定本地升级信息存取的文件,如果指定从本地查询升级,则读取该文件// 如果指定从网络查询升级,则存在升级时保存升级信息到该文件#define OTA_UPDATE_PARAM_KEY_LOCAL_UPDATE_INFO_PATH "localupdate_info_path"// 设置服务地址,一般不用使用#define OTA_UPDATE_PARAM_KEY_SERVICE_URL "service_url"// 指示升级请求是从服务器问询或者是从本地文件读取#define OTA_UPDATE_PARAM_KEY_SERVER_TYPE "server_type"// 升级请求从文件中读取,文件路径通过ota_set_update_param设置#define OTA_UPDATE_PARAM_KEY_SERVER_TYPE_LOCAL "local"// 升级请求从网络读取,服务器地址通过ota_set_update_param设置#define OTA_UPDATE_PARAM_KEY_SERVER_TYPE_LOCAL "net"

ota_do_udpate

  • 函数定义

int ota_do_udpate(pota_update_manager manager, uint32_t flag);

  • 功能

执行实际升级功能,调用此函数前需要调用ota_set_update_param函数设置更新参数

  • 参数说明

manger : 更新管理器对象;

  • 返回值说明

返回0表示成功,非0表示失败。

ota_release_update_manager

  • 函数定义

int ota_release_update_manager(pota_update_manager manager);

  • 功能

释放更新管理器对象

  • 参数说明

manger : 更新管理器对象;

  • 返回值说明

返回0表示成功,非0表示失败。

OTA SDK跨平台支持

OTA SDK v1.1

v1.1版本SDK支持Windows、Linux、Mac操作系统,其中依赖的第三方开源库包括:C标准库 、 libcurl 和 openssl。如果目标平台无法使用上述开源库,则暂不支持使用v1.1版本OTA SDK

OTA SDK v2.x

v2.x版本SDK在v1.1版本基础上,为了能够适配只有C标准库的IOT设备,将使用 libcurl 和 openssl库的部分封装成的单独的静态库,并提供了默认的实现 platform_adapter_default.a,默认实现中使用了libcurl和openssl开源库。

  • SDK接入方法

    • 针对可以使用libcurl和openssl的设备:直接链接otasdk.a、libcurl.a、libssl.a、libcrypto.a和platform_adapter_default.a文件即可使用。
    • 针对无法使用libcurl和openssl的设备:需要接入方根据includedotadapter 目录中的头文件ota_cipher.h和ota_http_stream.h文件定义的接口实现一个静态库,然后与otasdk.a一起静态链接即可。

OTA SDK示例程序

程序名称

otaupdate_explain

功能

本示例程序用于测试和体验SDK,其中使用一系列命令行参数,实现对OTA SDK中主要接口的调用。

参数介绍

用法:otaupdate_explain COMMAND [args] COMMAND: net-update 通过网络进行升级write 通过本地升级文件升级net-update命令:-pid 指定product ID -key 用于指定验证升级包的公钥文件路径-pidpass base64编码的密钥,用于连接升级服务器-ver [可选] 指定当前系统版本号,默认为0.0.0.0 -did [可选] 指定设备唯一id,默认为“bdtestdev” -temp [可选] 设置临时目录-persistent [可选] 设置持久性目录 -predownload [可选] 指定使用预下载功能 -url [可选] 设置升级服务器url-reporturl [可选] 设置上报服务器url write命令: 用法:otaupdate_explain write -key firstsegfile [segfile] 参数介绍:-key <key_path> 用于指定验证升级包的公钥文件路径firstsegfile 如果使用本地分片OTA升级包升级:此参数为第一个分片升级包路径 如果使用本地完整包升级,此参数为完整包路径segfile 如果使用本地分片OTA升级包升级:此参数为需要升级的分片升级包路径 如果使用本地完整包升级,不传入此参数</key_path>

常用功能示例

  • 网络正式环境升级otaupdate_explain net-update -pid -key -pidpass
  • 网络测试环境升级otaupdate_explain net-update -pid -key -pidpass -url -reporturl
  • 使用预下载功能升级otaupdate_explain net-update -pid -key -pidpass -persistent -predownload

    示例程序中使用预下载文件升级时,会在查询完成后预下载完整升级包到指定的持久性目录下predownload.bdota文件,然后使用该文件进行升级,若不指定persistent参数,则下载到当前目录

  • 使用本地完整包升级otaupdate_explain write -key
  • 使用本地分片升级包升级

    升级包分片后所有分片OTA升级包路径表示为:seg_1 ~ seg_N ,i 从2至N,循环调用以下命令:otaupdate_explain write -key seg_1 seg_i

制作升级包工具

命令行参数说明

ota_gen <PARAM...> [OPTION...]COMMAND (选择一个): gen (*default) // 根据目录生成ota包 div// 根据ota升级包,切分成片段升级包

gen命令支持参数:

-t, --target <path>对于完整包:表示准备生成ota包的目标目录对于差分包:表示新版本所在目录 -o, --output <path>设置输出ota包的文件路径 -d, --desc <path> [可选]设置信息描述文件路径 -i, --incremental_from <path>指定进行差分升级,path表示进行差分升级时旧版本所在目录 -s, --segment <size> 设置分段升级中要求的最大文件大小支持k/K/m/M为单位的参数 -k, --key <path> [可选]设置数字签名私钥路径</path></size></path></path></path></path>

div命令支持参数:

-t, --target <path>设置ota包路径 -o, --output <path>设置存储分片OTA包目录</path></path>

其他参数:

-c, --compress对ota包中数据进行压缩 -h, --help显示帮助信息

主要功能

本命令行工具包括两个主要功能:生成OTA升级包和OTA升级包分片

  • 生成OTA升级包:可以生成完整升级包和差分升级包两类OTA升级包。生成OTA包时,可通过参数控制以下特性:文件分段、数据压缩。
  • OTA升级包分片:将完整升级包按照其中包含的文件(单个完整文件、分段后的分段文件、差分文件),切分成若干个分片OTA升级包。

常用功能示例

  • 生成完整OTA升级包

    ota_pkg_gen gen -t <target_path> -o <output_path> -d <desc_path> -k <public_key_path>

  • 生成完整OTA升级包,对数据压缩,并对文件按照1M大小分段

    ota_pkg_gen gen -t <target_path> -o <output_path> -d <desc_path> -k <public_key_path> -c -s 1M

  • 生成差分包

    ota_pkg_gen gen -t <target_path> -o <output_path> -d <desc_path> -k <public_key_path> -i <old_ver_path>

  • OTA包切分成分片升级包

    ota_pkg_gen div -t <ota_pkg_path> -o <output_dir_path>

标签