Skip to content

数据包格式

本文档定义蓝牙协议 V2 的数据包结构。

包结构总览

每个数据包由 HeaderPayload 两部分组成:

+----------------+------------------+
|     Header     |     Payload      |
|   (固定长度)    |    (变长)        |
+----------------+------------------+

Header 结构

Header 采用固定长度设计,便于解析和分包处理。

+----------+----------+----------+----------+----------+----------+
|  magic   | version  |  flags   |  cmd_id  |  seq_id  |  length  |
|  2 bytes |  1 byte  |  1 byte  | 2 bytes  |  2 bytes |  2 bytes |
+----------+----------+----------+----------+----------+----------+

总长度:10 字节

字段总览

字段长度说明
magic2 字节魔数,固定为 0x5A5A
version1 字节协议版本号,当前为 0x02
flags1 字节标志位
cmd_id2 字节指令码,小端序
seq_id2 字节序列号,小端序
length2 字节Payload 长度,小端序

Header 字段

魔数

字段名:magic

固定值 0x5A5A,用于识别协议包边界和过滤无效数据。

接收方应检查 magic 值,不匹配时丢弃该数据。

协议版本

字段名:version

协议版本号,用于兼容性判断:

版本
0x01V1 协议(已废弃)
0x02V2 协议(当前)

标志位

字段名:flags

+-----+-----+-----+-----+-----+-----+-----+-----+
| bit7| bit6| bit5| bit4| bit3| bit2| bit1| bit0|
+-----+-----+-----+-----+-----+-----+-----+-----+
|        reserved       | enc |  format   | dir |
+-----+-----+-----+-----+-----+-----+-----+-----+
名称说明
bit0dir方向:0=请求,1=响应
bit1-2format序列化格式
bit3enc加密标志:0=明文,1=加密
bit4-7reserved保留,必须为 0

format 序列化格式:

格式
0Protobuf
1JSON
2原始字节
3保留

指令码

字段名:cmd_id

指令码,标识本次通信的操作类型。采用分块编号,高字节表示模块,低字节表示具体操作。

详见 指令表

序列号

字段名:seq_id

用于匹配请求和响应:

  • 请求方生成唯一序列号
  • 响应方原样返回该序列号
  • 取值范围 0-65535,循环使用

载荷长度

字段名:length

Payload 部分的字节长度,不包含 Header。

  • 最大值受 MTU 限制
  • length=0 表示无 Payload(如心跳包)

Payload 载荷

Payload 为业务数据,根据 flags.format 字段选择序列化方式:

format内容
ProtobufProtobuf 二进制编码
JSONUTF-8 编码的 JSON 字符串
原始字节按消息定义的字节序列

详细序列化规范参见 序列化规范

加密

flags.enc = 1 时,Payload 部分需要加密:

+----------------+---------------------------+
|     Header     |   Encrypted Payload       |
|   (明文)       |   (AES-CCM 加密)          |
+----------------+---------------------------+
  • Header 始终为明文,便于解析
  • 仅 Payload 部分加密
  • 加密算法和密钥管理参见加密规范(待补充)

分包传输

当数据长度超过蓝牙 MTU 时,需要分包传输。

分包扩展字段

分包时在标准 Header 后追加分包信息:

+----------------+----------+----------+------------------+
|  标准 Header   |  total   |  index   |     Payload      |
|   10 bytes     |  1 byte  |  1 byte  |                  |
+----------------+----------+----------+------------------+
字段长度说明
total1 字节总分包数
index1 字节当前分包索引(从 0 开始)

分包规则

  1. 第一个分包包含完整 Header + 分包信息
  2. 后续分包仅包含分包信息 + Payload 片段
  3. 接收方按 seq_idindex 组装
  4. 超时未收齐则丢弃

分包示例

发送 500 字节数据,MTU=200:

分包0: [Header:10B][total:1][index:0][Payload:187B]  = 199B
分包1: [total:1][index:1][Payload:198B]              = 199B
分包2: [total:1][index:2][Payload:115B]              = 116B

完整示例

请求包示例

获取设备信息请求(无 Payload):

Header:
  magic:   5A 5A
  version: 02
  flags:   00        (请求, Protobuf, 明文)
  cmd_id:  00 01     (0x0100 GetDeviceInfo, 小端序)
  seq_id:  01 00     (序列号 1)
  length:  00 00     (无 Payload)

完整: 5A 5A 02 00 00 01 01 00 00 00 (10 字节)

响应包示例

获取设备信息响应:

Header:
  magic:   5A 5A
  version: 02
  flags:   01        (响应, Protobuf, 明文)
  cmd_id:  00 01     (0x0100 GetDeviceInfo)
  seq_id:  01 00     (匹配请求序列号)
  length:  20 00     (Payload 32 字节)

Payload:
  [32 字节 Protobuf 编码的 DeviceInfo]

完整: 5A 5A 02 01 00 01 01 00 20 00 [Payload...] (10 + 32 = 42 字节)

错误处理

无效包处理

情况处理方式
magic 不匹配丢弃,继续扫描
version 不支持返回错误响应
cmd_id 未知返回错误响应
length 超限返回错误响应
解密失败丢弃,不响应
反序列化失败返回错误响应

超时处理

  • 请求超时:5 秒无响应,可重试
  • 分包超时:2 秒未收齐,丢弃已收分包

物联网设备通信协议文档