3、广播数据包格式:AD Structure、AD Type详解与构造解析
广播数据包,说白了就是BLE设备在“喊话”时发出的数据帧。你想想看,一个设备要告诉别人“我是谁”、“我能干什么”,总得有个统一的格式吧?不然大家各说各话,谁也听不懂。
这一节,我们就来拆解这个格式。我会结合自己调试过的几个项目,把AD Structure和AD Type讲透。最后再带大家手撕一个数据包,看看它到底长什么样。
3.1 AD Structure:广播数据的最小单元
广播数据包的核心结构,其实特别简单。它由若干个AD Structure(广播数据单元)拼接而成。每个AD Structure又包含三个部分:
| 字段 | 长度 | 说明 |
|---|---|---|
| Length | 1字节 | 表示后续Data的长度(不包含自身) |
| AD Type | 1字节 | 标识数据的类型(如设备名、UUID等) |
| AD Data | Length - 1字节 | 真正的数据内容 |
嗯,这里要注意:Length字段只算AD Type + AD Data的长度,不包括它自己。我刚开始做BLE开发时,就因为这个理解偏差,抓包解析时数据总对不上。后来才反应过来——协议栈就是这么规定的。
举个例子:如果Length = 0x05,那么AD Type占1字节,AD Data占4字节。总共5字节,没错。
3.2 AD Type:广播数据的“身份证”
AD Type决定了这段数据是什么含义。BLE规范里定义了几十种AD Type,但实际开发中常用的就那么几种。我整理了一张表,大家可以直接拿来用:
| AD Type值 | 名称 | 用途 |
|---|---|---|
| 0x01 | Flags | 广播模式标志(可连接、可扫描等) |
| 0x02/0x03 | Incomplete/Complete 16-bit UUID | 服务UUID列表(16位) |
| 0x06/0x07 | Incomplete/Complete 128-bit UUID | 服务UUID列表(128位) |
| 0x08/0x09 | Short/Local Name | 设备名称 |
| 0x0A | Tx Power Level | 发射功率(用于距离估算) |
| 0xFF | Manufacturer Specific Data | 厂商自定义数据 |
我个人习惯,在项目初期一定会把Flags和Local Name这两个AD Type加上。Flags告诉手机“我是可连接的”,Name让用户一眼认出设备。少了这两个,很多手机扫描APP根本不会显示你的设备。
3.3 广播数据包构造实战
理论讲完了,我们来动手构造一个完整的广播数据包。假设我们要广播以下信息:
- 设备是可连接、可发现的(Flags)
- 设备名称叫“MySensor”
- 包含一个16位服务UUID:0x180F(电池服务)
- 发射功率为0 dBm
一步步来:
- 构造Flags AD Structure:Length = 0x02(AD Type + AD Data),AD Type = 0x01,AD Data = 0x06。结果:
02 01 06 - 构造Name AD Structure:Name = “MySensor”共8字节,Length = 0x09,AD Type = 0x09,AD Data = “MySensor”的ASCII码。结果:
09 09 4D 79 53 65 6E 73 6F 72 - 构造UUID AD Structure:Length = 0x03,AD Type = 0x02(Complete 16-bit UUID),AD Data = 0x0F 0x18(小端序)。结果:
03 02 0F 18 - 构造Tx Power AD Structure:Length = 0x02,AD Type = 0x0A,AD Data = 0x00(0 dBm)。结果:
02 0A 00
把它们拼起来,完整的广播数据就是:
02 01 06 09 09 4D 79 53 65 6E 73 6F 72 03 02 0F 18 02 0A 00
总长度19字节。BLE广播包最多可承载31字节,所以完全够用。
3.4 广播数据包解析实战
解析就是构造的逆过程。假设我们从空中抓到一个广播包,原始数据如下:
02 01 06 03 02 0F 18 05 09 48 65 6C 6C 6F 02 0A 04
我们来手动解析:
- 第一个字节0x02 → Length = 2,表示后续2字节是AD Type + AD Data。
- 第二个字节0x01 → AD Type = Flags。
- 第三个字节0x06 → AD Data = 0x06(可连接+可发现)。
- 跳到第四个字节0x03 → Length = 3,后续3字节。
- 第五个字节0x02 → AD Type = Complete 16-bit UUID。
- 第六、七字节0x0F 0x18 → UUID = 0x180F(电池服务)。
- 跳到第八个字节0x05 → Length = 5,后续5字节。
- 第九个字节0x09 → AD Type = Complete Local Name。
- 第十到十四字节0x48 0x65 0x6C 0x6C 0x6F → “Hello”。
- 跳到第十五字节0x02 → Length = 2。
- 第十六字节0x0A → AD Type = Tx Power。
- 第十七字节0x04 → 发射功率 = 4 dBm。
解析结果:这是一个名为“Hello”的设备,支持电池服务,发射功率4 dBm,可连接可发现。
3.5 广播数据包结构总览
为了让大家更直观地理解整个广播数据包的构成,我画了一张结构图。它展示了从PDU到AD Structure的完整层级关系。
从这张图可以看得很清楚:广播数据包是层层嵌套的。最外层是PDU,里面包含地址和数据;数据部分又由多个AD Structure组成;每个AD Structure再拆成Length、Type和Data。理解了这个层级关系,你就能轻松应对任何广播数据包的构造和解析。
好了,这一节的内容就到这里。记住:构造时按规范拼装,解析时按循环拆解。掌握了这个核心思路,广播数据包对你来说就不再是黑盒了。