4、BLE广播包类型:ADV_IND、ADV_DIRECT_IND、ADV_NONCONN_IND、SCAN_REQ/RSP
做蓝牙开发这么多年,我见过不少新手在广播包类型上栽跟头。说白了,BLE的广播包就那么几种,但每种都有自己的脾气。你选错了类型,设备可能连不上,或者功耗高得吓人。
今天咱们就把这四种核心广播包类型掰开揉碎了讲。嗯,先从最常见的说起。
4.1 ADV_IND:通用广播包
ADV_IND 的全称是 Connectable Undirected Advertising。这是最通用的广播包,也是我项目里用得最多的。
特点:
- 可被扫描(SCAN_REQ/RSP)
- 可被连接(CONNECT_REQ)
- 不指定目标设备,谁都能收到
说白了,这就是个「喊话」模式。你的设备在广播,周围所有扫描设备都能听到,并且可以发起连接。
我记得有一次做智能门锁项目,客户说手机有时候搜不到设备。排查了半天,发现是广播间隔设得太长,加上 ADV_IND 的发射功率没调好。后来把间隔从 100ms 调到 50ms,问题就解决了。
4.2 ADV_DIRECT_IND:定向广播包
ADV_DIRECT_IND 是 Connectable Directed Advertising。这个包有点特殊——它只发给一个指定的设备。
核心特征:
- 包含目标设备的 MAC 地址
- 只能被目标设备接收
- 不可被扫描(不能发 SCAN_REQ)
- 连接速度快
你想想看,为什么需要这种包?场景很明确:你已经知道要连哪个设备了,不想让其他设备打扰。
实际案例: 蓝牙耳机回连。手机和耳机之前配对过,耳机开机后直接发 ADV_DIRECT_IND 给手机,手机收到后立刻发起连接。整个过程不到 100ms,用户体验非常好。
我曾经踩过一个坑:ADV_DIRECT_IND 的广播间隔不能太长,否则目标设备可能错过。规范里建议用 3.75ms 的间隔,连续发 1.28 秒。如果没连上,再切回 ADV_IND 继续广播。
4.3 ADV_NONCONN_IND:不可连接广播包
ADV_NONCONN_IND 是 Non-connectable Undirected Advertising。听名字就知道——只能广播,不能连接。
适用场景:
- 信标(Beacon)设备
- 广播传感器数据(温度、湿度等)
- 不需要建立连接的场景
我做过一个温湿度监测项目,每个房间放一个传感器,用 ADV_NONCONN_IND 广播数据。网关只负责接收,不建立连接。这样传感器功耗极低,两节 AA 电池能用一年多。
为什么功耗低?因为 ADV_NONCONN_IND 不需要监听 SCAN_REQ 和 CONNECT_REQ,广播完就休眠。你想想看,省了多少监听窗口的时间。
| 广播类型 | 可扫描 | 可连接 | 典型应用 |
|---|---|---|---|
| ADV_IND | 是 | 是 | 通用设备、传感器 |
| ADV_DIRECT_IND | 否 | 是 | 快速回连、耳机 |
| ADV_NONCONN_IND | 否 | 否 | 信标、单向广播 |
4.4 SCAN_REQ 与 SCAN_RSP:扫描请求与响应
这两个不是广播包,而是扫描过程中的控制包。但我把它们放在一起讲,因为它们是广播数据解析里绕不开的环节。
SCAN_REQ: 扫描设备发起的请求,询问广播设备「你还有更多数据吗?」
SCAN_RSP: 广播设备回复的响应,包含额外的广播数据。
为什么要分两次?因为广播包(ADV_IND)最多只能放 31 字节数据。如果不够用,可以把一部分数据放到 SCAN_RSP 里。
我曾经遇到一个兼容性问题:某款手机在收到 ADV_IND 后,不发送 SCAN_REQ,直接发起连接。结果设备把关键配置信息放在 SCAN_RSP 里,手机没收到,导致连接后功能异常。后来我把所有必要数据都塞进了 ADV_IND,问题解决。
4.5 四种包类型的交互流程
下面这张图展示了广播者和扫描者之间的完整交互流程。我建议你仔细看看,理解每个包在什么时机出现。
4.6 实战选择建议
说了这么多,到底怎么选?我总结了几条经验:
- 需要连接 + 需要广播数据 → ADV_IND。这是最通用的选择,90% 的场景都适用。
- 需要快速连接 + 已知目标 → ADV_DIRECT_IND。回连场景首选,但注意它不能带数据。
- 只广播不连接 → ADV_NONCONN_IND。信标、传感器数据广播,功耗最低。
- 数据超过 31 字节 → 把部分数据放 SCAN_RSP。但要注意,不是所有扫描设备都会发 SCAN_REQ。
好了,这四种广播包类型就讲到这里。记住一点:没有最好的类型,只有最适合场景的类型。多在实际项目里试试,你自然就摸清它们的脾气了。