蓝牙设备通常需要空中升级(OTA)的能力进行固件更新,本规范定义了空中升级(OTA)的基本流程和指令集。

背景信息

本规范基于蓝牙BLE基础规范

交互流程

为了保证OTA的的安全性,在进行设备OTA之前,必须完成安全认证流程。若认证失败则不允许进行OTA。安全认证详情参考蓝牙BLE基础规范

手机与蓝牙设备OTA流程如下:

BLE OTA

基础规范使用

  • 广播规范

    空中升级(OTA)是可选功能,如果蓝牙设备实现了此功能,需要在广播规范的FMSK字段中标示。

  • 服务规范

    传输过程使用基础规范已定义的Service和Characteristics,采用指令类型区分。手机App发送固件时,采用WriteWithNoRsp Characteristics(0xFED7),用于加快传输速度。同时蓝牙设备收到数据包后,采用Notify Characteristics(0xFED8)对App应答。接收固件过程中,发现数据序号错误的时候,蓝牙设备上报最后一次正确的序号。

  • 数据传输规范

    数据传输使用基础规范定义的数据格式和规则。

版本格式

固件类型为一个1字节数字,用来区分同一个设备不同类型固件。版本格式为一个4字节数字,如:0x00010302,表示固件版本号为:“1.3.2”,版本号只允许递增,最大版本号为:“99.99.99”。版本格式规则如下:

字节序 说明 取值范围 示例
0 修订号 0x00~0x63 “1.3.2”,修订号为0x02
1 次版本号 0x00~0x63 “1.3.2”,次版本号为0x03
2 主版本号 0x00~0x63 “1.3.2”,主版本号为0x01
3 保留

升级规则

  • 待升级的固件推送到服务端,并填写固件版本信息和升级原因。
  • 当服务端确认推送的固件版本比设备端上报的固件版本新时,服务端推送升级通知到手机App。
  • 手机App转发升级请求及固件版本信息(仅包含应用版本信息)和固件大小,CRC。
  • 蓝牙设备检查固件的应用版本信息,当App下发的应用版本信息比设备运行的固件的应用版本新时,蓝牙设备进入升级模式,否则退出升级模式。
  • 协议设计支持固件断点续传能力,参考“交互流程”第12步,蓝牙设备可以回复上次传输固件的中断的位置,手机App会从指定位置续传。断点续传非强制要求能力,可根据情况实现。
  • 协议设计支持快速传输模式,即手机App会连续传输TotalFrame(0<TotalFrame<=16)个数据包而不需要对每个数据包等待蓝牙设备的回复,TotalFrame个数据包发送完成后,蓝牙设备才给予回复,然后手机App进行下一轮数据的传输。
  • 除了0x2F指令(下发固件分包)不需要加密外,其余指令通过鉴权流程后均需要加密。

OTA指令集

  • CMD 0x20:手机查询设备固件版本。

    Payload为1字节:固件类型为1字节,默认填0x00。设备端根据固件类型从 0x21 返回对应类型固件的版本号信息。

    Header(1字节) CmdType(1字节) Total Frame & Seq(1字节) Length(1字节) Payload(1字节)
    0x00 0x20 0x00 0x01 0x00
    说明 Total Frame & Seq字段值为0x00表示共1帧数据且当前数据为第1帧。
  • CMD 0x21: 设备上报设备固件版本。
    Payload为5字节:
    • 固件类型(1字节):默认填0x00,遇到不支持的固件类型,固件类型上报 0xFF。
    • 固件版本号(4字节):例如0x00000002。
    Header(1字节) CmdType(1字节) Total Frame & Seq(1字节) Length(1字节) Payload(5字节)
    0x00 0x21 0x00 0x05 0x00 0x00000002
    说明 0x21指令Msg ID要求与0x20指令中数据一致。
  • CMD 0x22:设备上报设备固件版本。
    Payload为12字节:
    • 固件类型(1字节):默认填0x00;
    • 固件版本号(4字节):例如0x00000001;
    • 固件大小(4字节):例如 0x00123456;
    • CRC16(2字节):采用CRC16_CCITT;
    • 升级标示符(1个字节):0-全量升级,1-增量升级,2-静默升级。
    Header(1字节) CmdType(1字节) Total Frame & Seq(1字节) Length(1字节) Payload(12字节)
    0x00 0x22 0x00 0x0c 0x00 0x00000001 0x00123456 0x7890 0x00
  • CMD 0x23:设备应答升级请求。
    Payload(6字节):
    • 是否允许升级(1字节): 0-不可以升级,1-允许升级;
    • 上次传输字节数(4字节);
    • 允许一次循环可传输的包个数(1字节):取值范围0x00~0x0F,表示1~16包;
    Header(1字节) CmdType(1字节) Total Frame & Seq(1字节) Length(1字节) Payload(6字节)
    0x00 0x23 0x00 0x06 0x01 0x00000000 0x0F
    说明 0x23指令Msg ID要求与0x22指令中数据一致;如设备支持断点续传,则上次传输的字节上报已经接收到的固件长度。
  • CMD 0x24: 设备上报当前已接收的帧序号和接收的数据长度。
    Payload(5字节):
    • 接收的帧数(1字节):totalFrame 4bit + frameSeq 4bit;
    • 数据长度(4字节):例如0x0000020。
    Header(1字节) CmdType(1字节) Total Frame & Seq(1字节) Length(1字节) Payload(5字节)
    0x00 0x24 0x00 0x05 0x20 0x00000200

    当设备发现有丢帧时,设备端上报最后一次收到正确的帧序和数据长度。手机端重新从丢失的帧开始发送,并且发送完本次循环的剩余帧。

  • CMD 0x25:手机通知设备固件下发结束,可以做固件检查。
    Header(1字节) CmdType(1字节) Total Frame & Seq(1字节) Length(1字节) Payload(1字节)
    0x00 0x25 0x00 0x01 0x01
  • CMD 0x26:设备收完包后,上报固件检查结果。

    固件检查结果(1字节): 0-固件检查失败,1-固件检查成功。

    Header(1字节) CmdType(1字节) Total Frame & Seq(1字节) Length(1字节) Payload(1字节)
    0x00 0x26 0x00 0x01 0x01
    说明 0x26指令Msg ID要求与0x25指令中数据一致。
  • CMD 0x2F:手机下发固件的分包数据。
    Header(1字节) CmdType(1字节) Total Frame & Seq(1字节) Length(1字节) Payload(N字节)
    0x00 0x2F 0xF0 0x10 0x00 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 0x99 0xAA 0xBB 0xCC 0xDD 0xEE 0xFF

    固件按规范的数据长度分包,发送16包作为一次循环,Header中帧序号(Msg ID)按照0~15循环。

    说明 Total Frame & Seq字段值为0xF0表示共16帧数据且当前数据为第1帧。

OTA数据传输与Characteristic对应关系

指令类型 说明 传输使用的Characteristic Characteristics UUID
0x20 查询设备固件版本 WriteWithNoRsp Characteristics 0xFED7
0x21 上报设备固件版本 Notify Characteristics 0xFED8
0x22 下发升级请求 WriteWithNoRsp Characteristics 0xFED7
0x23 应答升级请求 Notify Characteristics 0xFED8
0x24 上报设备最后接收到的帧序号和实际保存的数据长度 Notify Characteristics 0xFED8
0x25 开始进行固件校验 WriteWithNoRsp Characteristics 0xFED7
0x26 上报固件校验结果 Notify Characteristics 0xFED8
0x2F 固件分包数据 WriteWithNoRsp Characteristics 0xFED7

重传周期

在一个重传周期内如果连续出现同一错误,则只需发送一次0x24指令。重传周期的时间计算方式为500ms*TotalFrame;例如每次循环最大允许发送的数据帧数为10,则重传周期为500ms*10=5秒。

异常处理逻辑

  • 当设备发现期望接收的数据包seq与当前收到的数据包seq不相同时,设备回复0x24指令,上报最后一次接收到的连续的数据包的seq和已接收的数据总长度;手机APP或天猫精灵在接收到0x24指令后,使用0x2F指令重新下发丢失的数据包,内容与之前的一致(包括Header和Payload);设备在接收到剩余的数据包之后需要回复一次0x24指令;然后手机APP或天猫精灵继续传输剩余的固件信息。OTA异常1OTA异常2
  • 设备端如果发现接收数据错误,在重传周期内只允许上报一次0x24指令;如果正确接收到期望的数据则不受此规则限制。OTA异常3
  • 当设备回复0x24指令之后,如果在重传周期内没有收到期望的数据包,则再次回复0x24指令。OTA异常4
  • 当设备端重复发送同一0x24指令超过5次时,则断开连接。OTA异常5
  • 当传输的固件末尾最后剩余的数据小于TotalFrame*MTU时,根据实际的拆包个数确定本轮传输的TotalFrame。当设备端发现已经接收到的数据等于固件总长度时,需要直接回复0x24指令。

异常处理小结

设备端在以下情况下需要回复0x24指令:

  • 当设备收齐单次循环发送的所有数据包时,需要回复0x24指令。
  • 当设备收到与期望的seq不同的数据包时,需要回复0x24指令,当数据错误时每个重传周期内只允许发送1次0x24指令。
  • 当设备收齐重发的单次循环发送的所有数据包时,需要回复0x24指令。
  • 当设备在一个重传周期内未接收到期望的seq的数据包,需要回复0x24指令。
  • 当设备收到完整固件后,需要回复0x24指令。

参考资料

CRC16算法参数模型:

  • CRC-16/CCITT-FALSE;
  • 宽度 16位;
  • 多项式POLY 0x1021;
  • 初始值INIT 0xFFFF;
  • 结果异或值XOROUT 0x0000;
  • 输入数据反转 REFIN false;
  • 输出数据反转 REFOUT false。