设备端OTA升级
OTA(Over-the-Air Technology)即空中下载技术。物联网平台支持通过OTA方式进行设备升级。本文以MQTT协议下的OTA升级为例,介绍OTA升级流程、数据流转使用的Topic和数据格式。
OTA升级流程
MQTT协议下OTA升级流程如下图所示。
OTA升级说明
- 差分升级前,设备必须上报OTA模块版本。整包升级前,设备可不上报OTA模块版本。如不上报,配置批量升级时不能针对指定版本进行升级,具体说明,请参见发起升级批次任务。
若设备需要在首次升级前上报版本号,建议只在系统启动过程中上报一次,不需要周期循环上报。设备升级成功后,需要第一时间上报版本。
- 从物联网平台控制台发起批量升级后,设备升级操作记录状态是待升级。
实际升级从物联网平台OTA系统,接收到设备上报的升级进度开始。设备升级操作记录状态是升级中。
说明 设备端接收到物联网平台推送的升级通知后,可立即下载升级包进行升级,也可在业务空闲后,主动获取升级信息进行升级。 - 物联网平台根据设备端上报的版本号来判断设备端OTA升级是否成功。
- 设备离线时,不能接收服务端推送的升级消息。
通过MQTT协议接入物联网平台的设备再次上线后,物联网平台自动检测到设备上线,OTA服务端验证该设备是否需要升级。如果需要升级,物联网平台再次推送升级消息给设备,否则不推送消息。
数据格式说明
设备端OTA开发流程和代码示例,请参见Link SDK文档中,各语言SDK文档的设备OTA开发章节。
OTA升级流程及使用的Topic和数据格式如下:
- (可选)设备连接OTA服务,上报版本号。
设备端通过MQTT协议推送当前设备OTA模块版本号到Topic:
/ota/device/inform/${productKey}/${deviceName}。消息格式如下:{ "id": "123", "params": { "version": "1.0.1", "module": "MCU" } }表 1. 参数说明 参数 类型 说明 id String 消息ID号。String类型的数字,取值范围0~4294967295,且每个消息ID在当前设备中具有唯一性。 version String OTA模块版本。 module String OTA模块名。 说明- 上报默认(default)模块的版本号时,可以不上报module参数。
- 设备的默认(default)模块的版本号代表整个设备的固件版本号。
- 在物联网平台控制台上,添加升级包、验证升级包并发起批量升级任务。
具体操作,请参见推送升级包到设备端。
- 您在控制台触发升级操作之后,设备会收到物联网平台OTA服务推送的升级包的URL地址。
设备端订阅Topic:
/ota/device/upgrade/${productKey}/${deviceName}。物联网平台对设备发起OTA升级请求后,设备端会通过该Topic收到升级包的存储地址URL。消息格式如下:
- 单个文件的OTA升级包信息:
- 升级包下载协议为HTTPS:
{ "id": "123", "code": 200, "data": { "size": 93796291, "sign": "f8d85b250d4d787a9f483d89a974***", "version": "10.0.1.9.20171112.1432", "isDiff": 1, "url": "https://the_firmware_url", "signMethod": "MD5", "md5": "f8d85b250d4d787a9f48***", "module": "MCU", "extData":{ "key1":"value1", "key2":"value2", "_package_udi":"{\"ota_notice\":\"升级底层摄像头驱动,解决视频图像模糊的问题。\"}" } } } - 升级包下载协议为MQTT:
{ "id": "123", "code": 200, "data":{ "size":432945, "digestsign":"A4WOP***SYHJ6DDDJD9***", "version":"2.0.0", "isDiff":1, "signMethod":"MD5", "dProtocol":"mqtt", "streamId":1397345, "streamFileId":1, "md5":"93230c3bde***", "sign":"93230c3bde42***", "module":"MCU", "extData":{ "key1":"value1", "key2":"value2" } } }
- 升级包下载协议为HTTPS:
- 多个文件的OTA升级包仅支持HTTP下载协议,信息如下:
{ "id": "123", "code": 200, "data": { "version": "2.0.0", "isDiff": 1, "signMethod": "MD5", "files":[ { "fileSize":432944, "fileName":"file1-name", "fileUrl":"https://iotx***.aliyuncs.com/nop***.tar.gz?Expires=1502955804&OSSAccessKeyId=***&Signature=XfgJu7***U%3D&security-token=CAISu***", "fileMd5":"93230c3bde425a9d7984a594ac55ea1e", "fileSign":"93230c3bde425a9d7984a594ac55****" }, { "fileSize":432945, "fileName":"file2-name", "fileUrl":"https://iotx-***.aliyuncs.com/no***.tar.gz?Expires=1502955804&OSSAccessKeyId=***&Signature=XfgJu7P***KU%3D&security-token=CAISuQJ***", "fileMd5":"93230c3bde425a9d7984a594ac56ea1f", "fileSign":"93230c3bde425a9d7984a594ac56****" } ], "module": "MCU", "extData":{ "key1":"value1", "key2":"value2", "_package_udi":"{\"ota_notice\":\"升级底层摄像头驱动,解决视频图像模糊的问题。\"}" } } }
表 2. 参数说明 参数 类型 说明 id Long 消息ID号。每个消息ID在当前设备中具有唯一性。 message String 结果信息。 code String 状态码。 version String 设备升级包的版本信息。 size Long 升级包文件大小,单位:字节。 OTA升级包中仅有一个升级包文件时,包含该参数。
url String 升级包在对象存储(OSS)上的存储地址。 OTA升级包中仅有一个升级包文件,且下载协议为HTTPS时,包含该参数。
dProtocol String 升级包下载协议。 仅升级包下载协议为MQTT时,包含该参数。
streamId Long 通过MQTT协议下载OTA升级包时的唯一标识。 仅升级包下载协议为MQTT时,包含该参数。
streamFileId Integer 单个升级包文件的唯一标识。 仅升级包下载协议为MQTT时,包含该参数。
isDiff Long 仅当升级包类型为差分时,消息包含此参数。 取值为1,表示仅包含新版本升级包与之前版本的差异部分,需要设备进行差分还原。
digestsign String OTA升级包文件安全升级后的签名。仅当OTA升级包开启安全升级功能,才有此参数。开启OTA升级包安全升级功能的方法,请参见安全升级。 sign String OTA升级包文件的签名。 OTA升级包中仅有一个升级包文件时,包含该参数。
signMethod String 签名方法。取值: SHA256MD5
md5 String 当签名方法为MD5时,除了会给sign赋值外还会给md5赋值。 OTA升级包中仅有一个升级包文件时,包含该参数。
module String 升级包所属的模块名。 说明 模块名为default时,物联网平台不下发module参数。extData Object 升级批次标签列表和推送给设备的自定义信息。 _package_udi表示自定义信息的字段。
单个标签格式:
"key":"value"。files Array 多个升级包文件的信息列表。 OTA升级包中有多个文件时,包含该参数。每个升级包文件信息如下:
- fileSize:升级包文件大小。
- fileName:升级包文件的名称。
- fileUrl、fileMd5、fileSign:含义与url、md5、sign相同。
- 单个文件的OTA升级包信息:
- (可选)设备端SDK接收到物联网平台推送的升级包URL后,若未在24小时内完成升级包下载,该URL失效。设备端可通过调用以下topic,重新向物联网平台主动请求获取升级任务。
设备端发起请求的Topic为
/sys/${productKey}/${deviceName}/thing/ota/firmware/get,消息格式如下。{ "id": "123", "version": "1.0", "params": { "module": "MCU" }, "method": "thing.ota.firmware.get" }表 4. 参数说明 参数 类型 说明 id String 消息ID号。String类型的数字,取值范围0~4294967295,且每个消息ID在当前设备中具有唯一性。 version String 协议版本,固定为1.0。 params Object 请求参数。 module String 升级包所属的模块名。 说明 不指定则表示请求默认(default)模块的升级包信息。method String 请求方法,取值thing.ota.firmware.get。 物联网平台收到请求后,通过响应Topic:
/sys/${productKey}/${deviceName}/thing/ota/firmware/get_reply,向设备端返回升级包信息。- 下发升级包信息。返回数据格式如下:
- 单个文件的OTA升级包信息:
- 升级包下载协议为HTTPS:
{ "id": "123", "code": 200, "data": { "size": 93796291, "sign": "f8d85b250d4d787a9f483d89a974***", "version": "10.0.1.9.20171112.1432", "isDiff": 1, "url": "https://the_firmware_url", "signMethod": "MD5", "md5": "f8d85b250d4d787a9f48***", "module": "MCU", "extData":{ "key1":"value1", "key2":"value2", "_package_udi":"{\"ota_notice\":\"升级底层摄像头驱动,解决视频图像模糊的问题。\"}" } } } - 升级包下载协议为MQTT:
{ "id": "123", "code": 200, "data":{ "size":432945, "digestsign":"A4WOP***SYHJ6DDDJD9***", "version":"2.0.0", "isDiff":1, "signMethod":"MD5", "dProtocol":"mqtt", "streamId":1397345, "streamFileId":1, "md5":"93230c3bde***", "sign":"93230c3bde42***", "module":"MCU", "extData":{ "key1":"value1", "key2":"value2" } } }
- 升级包下载协议为HTTPS:
- 多个文件的OTA升级包仅支持HTTP下载协议,信息如下:
{ "id": "123", "code": 200, "data": { "version": "2.0.0", "isDiff": 1, "signMethod": "MD5", "files":[ { "fileSize":432944, "fileName":"file1-name", "fileUrl":"https://iotx***.aliyuncs.com/nop***.tar.gz?Expires=1502955804&OSSAccessKeyId=***&Signature=XfgJu7***U%3D&security-token=CAISu***", "fileMd5":"93230c3bde425a9d7984a594ac55ea1e", "fileSign":"93230c3bde425a9d7984a594ac55****" }, { "fileSize":432945, "fileName":"file2-name", "fileUrl":"https://iotx-***.aliyuncs.com/no***.tar.gz?Expires=1502955804&OSSAccessKeyId=***&Signature=XfgJu7P***KU%3D&security-token=CAISuQJ***", "fileMd5":"93230c3bde425a9d7984a594ac56ea1f", "fileSign":"93230c3bde425a9d7984a594ac56****" } ], "module": "MCU", "extData":{ "key1":"value1", "key2":"value2", "_package_udi":"{\"ota_notice\":\"升级底层摄像头驱动,解决视频图像模糊的问题。\"}" } } }
表 1. 参数说明 参数 类型 说明 id String 消息ID号。String类型的数字,取值范围0~4294967295,且每个消息ID在当前设备中具有唯一性。 此处消息ID返回的是设备请求中的消息ID,即请求Topic
/sys/${productKey}/${deviceName}/thing/ota/firmware/get数据中的id。code Integer 状态码,200表示成功。 data String 升级包信息,其中参数说明,请参见物联网平台推送OTA升级包信息的参数表。 - 单个文件的OTA升级包信息:
- 无升级包信息下发。返回数据格式如下:
{ "id": "123", "code": 200, "data": { } }
- 下发升级包信息。返回数据格式如下:
- 设备端SDK收到物联网平台推送的升级包URL后,调用SDK提供的接口下载升级包。例如通过HTTPS协议下载升级包,C SDK中提供了接口aiot_download_send_request。具体操作,请参见设备OTA。 说明 设备端无法自动下载升级包,可通过调用SDK中接口进行下载。下载须在升级包URL下发后的24小时内完成,否则该URL失效。
升级包下载过程日志,请参见:
- 升级过程中,设备端向服务端推送升级进度到Topic:
/ota/device/progress/${productKey}/${deviceName}。说明 建议设置设备端上报进度频率为3秒内最多一次。若设备上报进度频繁,在物联网平台控制台的OTA升级包详情的批次详情中,可能无法查看到上报的全部进度。消息格式如下:
{ "id": "123", "params": { "step": "-1", "desc": "OTA升级失败,请求不到升级包信息。", "module": "MCU" } }表 3. 参数说明 参数 类型 说明 id String 消息ID号。String类型的数字,取值范围0~4294967295,且每个消息ID在当前设备中具有唯一性。 step String OTA升级进度。
取值范围:- 1~100的整数:升级进度百分比。
-1:升级失败。-2:下载失败。-3:校验失败。-4:烧写失败。
设备上报的进度值及其描述信息,可根据设备实际升级场景在设备端配置。设备端配置方法,请参见设备端Link SDK的OTA升级。
desc String 当前步骤的描述信息,长度不超过128个字符。如果发生异常,此字段可承载错误信息。 module String 升级包所属的模块名。模块的更多信息,请参见添加升级包。 说明 上报默认(default)模块的OTA升级进度时,可以不上报module参数。 - 设备端完成OTA升级后,推送新版本信息到Topic:
/ota/device/inform/${productKey}/${deviceName}。如果上报的版本与OTA服务要求的版本一致就认为升级成功,反之失败。说明 升级成功的唯一判断标志是设备上报正确的版本号。即使升级进度上报为100%,如果不上报新的版本号,会因超时导致升级失败。设备升级完成时,建议立即重启设备,设备上线后,立即上报新的版本号。设备上线请求和上报版本请求间隔不能超过2秒。
常见下载升级包错误
- 签名错误。如果设备端获取的升级包的URL不全或者手动修改了URL内容,就会出现如下错误:
<Error> <Code>SignatureDoesNotMatch</Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <RequestId>5995470683464D75xxx</RequestId> <HostId>iotx-ota-pre.xxx.aliyuncs.com</HostId> <OSSAccessKeyId>STS.Em9Qvxxx ZBvCXUR3</OSSAccessKeyId> <SignatureProvided>XfgJu7P6DWWejstKJgXJEH0qAKU=</SignatureProvided> <StringToSign> GET 1502955805 /iotx-ota-pre/nopoll_0.4.4.tar.gz?security- token=CAISuQJ1q6Ft5B2yf5jIPk6MGsyN1Jx5jo6MvnfBg1IPTvlvt5D5OTz2IHtIf3NpAusdsv03nWxT7v4flqFyTINVAEvYZJOPKGrGR0DzDbDasumZsJbo4f/MQBqBaEaXPS2MvVfJ+zLrf0ceusbFbpjzJ6xaCAGxypQ12iN+/r6/5gdc9FcQSkLO8BZrFsKxBl+tdUROFbIPKpKWSKuGfLC1dysQoQ1 </StringToSign> <StringToSignBytes> 47 45 54 0A 0A 0A 31 35 30 32 39 35 35 38 30 35 0A 2F 69 6F 74 78 2D 6F 74 61 2D 70 72 65 2F 6E 6F 70 6F 6C 6C 5F 30 2E 34 2E 34 2E 74 61 72 2E 67 7A 3F 73 65 63 75 72 69 74 79 2D 74 6F 6B 65 6E 3D 43 41 49 53 75 51 4A 31 71 36 46 74 35 42 32 79 66 53 6A 49 70 4B 36 4D 47 73 79 4E 31 4A 78 35 6A 6F 36 4D 76 6E 66 42 67 31 49 50 54 76 6C 76 74 35 44 35 4F 54 7A 32 49 48 74 49 66 33 4E 70 41 75 73 64 73 76 30 33 6E 57 78 54 37 76 34 66 6C 71 46 79 54 49 4E 56 41 45 76 59 5A 4A 4F 50 4B 47 72 47 52 30 44 7A 44 62 44 61 73 75 6D 5A 73 4A 62 6F 34 66 2F 4D 51 42 71 42 61 45 61 58 50 53 32 4D 76 56 66 4A 2B 7A 4C 72 66 30 63 65 75 73 62 46 62 70 6A 7A 4A 36 78 61 43 41 47 78 79 70 51 31 32 69 </StringToSignBytes> </Error> - 拒绝访问。URL过期导致。目前,URL有效期为24小时。
<Error> <Code>AccessDenied</Code> <Message>Request has expired.</Message> <RequestId>5995498D7444FA88Axxx</RequestId> <HostId>iotx-ota-pre.xxx.com</HostId> <Expires>2017-08-17T07:43:24.000Z</Expires> <ServerTime>2017-08-17T07:45:17.000Z</ServerTime> </Error>