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根本不会显示你的设备。

避坑提醒:我曾经在一个项目中,只加了Manufacturer Specific Data,没加Flags。结果iPhone死活扫不到设备,折腾了两天。后来加上Flags 0x06(LE General Discoverable + BR/EDR Not Supported),问题立刻解决。所以,Flags不是可选项,是必选项。

3.3 广播数据包构造实战

理论讲完了,我们来动手构造一个完整的广播数据包。假设我们要广播以下信息:

  • 设备是可连接、可发现的(Flags)
  • 设备名称叫“MySensor”
  • 包含一个16位服务UUID:0x180F(电池服务)
  • 发射功率为0 dBm

一步步来:

  1. 构造Flags AD Structure:Length = 0x02(AD Type + AD Data),AD Type = 0x01,AD Data = 0x06。结果:02 01 06
  2. 构造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
  3. 构造UUID AD Structure:Length = 0x03,AD Type = 0x02(Complete 16-bit UUID),AD Data = 0x0F 0x18(小端序)。结果:03 02 0F 18
  4. 构造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字节,所以完全够用。

小技巧:如果你用nRF Connect或LightBlue这类APP扫描,可以直接看到解析后的结果。但如果你想自己写代码解析,记住一个原则:从第一个字节开始,先读Length,再读AD Type,然后根据Length取AD Data,接着跳到下一个AD Structure。循环直到数据结束。

3.4 广播数据包解析实战

解析就是构造的逆过程。假设我们从空中抓到一个广播包,原始数据如下:

02 01 06 03 02 0F 18 05 09 48 65 6C 6C 6F 02 0A 04

我们来手动解析:

  1. 第一个字节0x02 → Length = 2,表示后续2字节是AD Type + AD Data。
  2. 第二个字节0x01 → AD Type = Flags。
  3. 第三个字节0x06 → AD Data = 0x06(可连接+可发现)。
  4. 跳到第四个字节0x03 → Length = 3,后续3字节。
  5. 第五个字节0x02 → AD Type = Complete 16-bit UUID。
  6. 第六、七字节0x0F 0x18 → UUID = 0x180F(电池服务)。
  7. 跳到第八个字节0x05 → Length = 5,后续5字节。
  8. 第九个字节0x09 → AD Type = Complete Local Name。
  9. 第十到十四字节0x48 0x65 0x6C 0x6C 0x6F → “Hello”。
  10. 跳到第十五字节0x02 → Length = 2。
  11. 第十六字节0x0A → AD Type = Tx Power。
  12. 第十七字节0x04 → 发射功率 = 4 dBm。

解析结果:这是一个名为“Hello”的设备,支持电池服务,发射功率4 dBm,可连接可发现。

核心要点:解析广播数据包时,不要假设AD Structure的顺序。不同厂商、不同协议栈可能按不同顺序排列。一定要按“Length → AD Type → AD Data”的循环逻辑来解析,才能保证兼容性。

3.5 广播数据包结构总览

为了让大家更直观地理解整个广播数据包的构成,我画了一张结构图。它展示了从PDU到AD Structure的完整层级关系。

广播数据包结构总览 广播信道PDU PDU类型(4bit) | RFU(2bit) | ChSel(1bit) | TxAdd(1bit) | 长度(6bit) | RFU(2bit) AdvA(广播设备地址) AdvData(广播数据) AD Structure 1 AD Structure 2 AD Structure N Length (1B) AD Type (1B) AD Data (Length-1 字节) 注意:Length字段只包含AD Type + AD Data的长度,不包含自身

从这张图可以看得很清楚:广播数据包是层层嵌套的。最外层是PDU,里面包含地址和数据;数据部分又由多个AD Structure组成;每个AD Structure再拆成Length、Type和Data。理解了这个层级关系,你就能轻松应对任何广播数据包的构造和解析。

好了,这一节的内容就到这里。记住:构造时按规范拼装,解析时按循环拆解。掌握了这个核心思路,广播数据包对你来说就不再是黑盒了。