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了。

BLE链路层状态机 Standby Advertising Scanning Initiating Connection 虚线箭头表示可随时返回Standby;实线箭头表示条件触发切换

4.3 数据包结构

链路层的数据包,结构很清晰。我把它拆成三部分:

  1. 前导码(Preamble):1字节,用于同步
  2. 访问地址(Access Address):4字节,广播包固定为0x8E89BED6,数据包随机
  3. PDU:2~257字节,真正的数据

PDU内部又分:

  • 报头(Header):2字节,包含PDU类型、长度、ChSel等
  • 有效载荷(Payload):0~255字节
  • MIC:4字节,加密连接时才有

我曾经踩过的坑:有一次广播包发不出去,抓包发现PDU长度字段写错了。BLE对长度校验很严格,多一个字节都不行。后来我习惯在代码里加断言检查长度。

4.4 白名单与黑名单

白名单和黑名单是链路层的“安检员”。

白名单:只允许列表中的设备连接或扫描。我常用在防蹭连场景——比如智能门锁只认自家App的手机。

黑名单:拒绝列表中的设备。嗯,这个用得少,因为BLE规范里黑名单不是强制功能。

特性 白名单 黑名单
默认行为 拒绝所有,允许指定 允许所有,拒绝指定
存储位置 控制器内部 控制器内部
典型应用 配对绑定、安全连接 屏蔽干扰设备

我建议:产品量产时,白名单大小要提前规划。BLE控制器最多支持几十个地址,别等到上线了才发现不够用。

白名单的过滤发生在链路层,比应用层过滤快得多。你想想看,如果每个广播包都跑到应用层再判断,功耗和延迟都受不了。

好了,链路层的核心就这些。角色、状态机、包结构、白名单——这四个东西搞明白,BLE底层你就通了八成。