4、BLE链路层:设备角色与状态机
链路层是BLE协议栈的“心脏”。
我刚开始接触BLE时,总觉得应用层写写广播、配配对就完事了。直到有一次产品在复杂环境中频繁断连,我才意识到——不懂链路层,你根本不知道蓝牙在背后干了什么。
这一章,我们就把链路层扒开来看。
4.1 五种设备角色
BLE链路层定义了5种角色。注意,这不是“主从”那么简单。
| 角色 | 英文 | 核心行为 |
|---|---|---|
| 广播者 | Broadcaster | 只发广播包,不连接 |
| 扫描者 | Observer | 只收广播包,不连接 |
| 发起者 | Initiator | 收到广播后主动发起连接 |
| 从设备 | Slave | 连接后响应主设备 |
| 主设备 | Master | 连接后控制时序 |
说白了,前三个角色是“单身状态”,后两个是“连接状态”。
我见过不少新手把“广播者”和“从设备”混为一谈。其实广播者根本不参与连接,它就是个“小喇叭”。
关键点:一个设备可以同时扮演多个角色。比如手机既是扫描者(收广播),又是主设备(连手环)。这在BLE规范里叫“多角色并发”。
4.2 链路层状态机
链路层内部跑着一个有限状态机。嗯,一共5个状态。
- Standby:空闲态,啥也不干
- Advertising:广播态,发广播包
- Scanning:扫描态,收广播包
- Initiating:发起态,准备连接
- Connection:连接态,数据通信
状态切换有严格的规则。比如从Standby可以进任何状态,但从Advertising不能直接进Scanning——你得先回Standby。
我的习惯:调试时先确认设备当前在哪个状态。用抓包工具看广播包有没有发出来,就能判断是否卡在Standby了。
4.3 数据包结构
链路层的数据包,结构很清晰。我把它拆成三部分:
- 前导码(Preamble):1字节,用于同步
- 访问地址(Access Address):4字节,广播包固定为0x8E89BED6,数据包随机
- PDU:2~257字节,真正的数据
PDU内部又分:
- 报头(Header):2字节,包含PDU类型、长度、ChSel等
- 有效载荷(Payload):0~255字节
- MIC:4字节,加密连接时才有
我曾经踩过的坑:有一次广播包发不出去,抓包发现PDU长度字段写错了。BLE对长度校验很严格,多一个字节都不行。后来我习惯在代码里加断言检查长度。
4.4 白名单与黑名单
白名单和黑名单是链路层的“安检员”。
白名单:只允许列表中的设备连接或扫描。我常用在防蹭连场景——比如智能门锁只认自家App的手机。
黑名单:拒绝列表中的设备。嗯,这个用得少,因为BLE规范里黑名单不是强制功能。
| 特性 | 白名单 | 黑名单 |
|---|---|---|
| 默认行为 | 拒绝所有,允许指定 | 允许所有,拒绝指定 |
| 存储位置 | 控制器内部 | 控制器内部 |
| 典型应用 | 配对绑定、安全连接 | 屏蔽干扰设备 |
我建议:产品量产时,白名单大小要提前规划。BLE控制器最多支持几十个地址,别等到上线了才发现不够用。
白名单的过滤发生在链路层,比应用层过滤快得多。你想想看,如果每个广播包都跑到应用层再判断,功耗和延迟都受不了。
好了,链路层的核心就这些。角色、状态机、包结构、白名单——这四个东西搞明白,BLE底层你就通了八成。