3、BLE关键概念:广播、扫描、连接、GATT、GAP、服务与特征值、MTU与ATT
可穿戴设备(手表、手环、体脂秤、血糖仪等)与手机之间的数据同步,绝大多数基于BLE(Bluetooth Low Energy,低功耗蓝牙)协议栈。BLE之所以能在极低功耗下完成可靠传输,是因为它定义了一套与经典蓝牙完全不同的工作模式:设备不总是保持连接,而是通过广播宣告存在、通过扫描发现彼此、按需建立连接,再通过GATT(Generic Attribute Profile)规范组织数据。理解广播、扫描、连接、GAP、GATT、服务与特征值、MTU与ATT这八个核心概念,是进行可穿戴设备蓝牙开发、功耗调优和兼容性排障的基础。下图展示了BLE协议栈中这些关键概念的分层关系与数据流向。
上图展示了BLE协议栈中GAP与GATT的分工:GAP负责设备发现与连接管理,GATT负责连接建立后的数据交互。下面逐一拆解这些关键概念。
3.1 GAP:广播与扫描
核心原理
GAP(Generic Access Profile)定义了BLE设备如何被发现、如何建立连接。它规定了四种角色:Broadcaster(仅广播)、Observer(仅扫描)、Peripheral(从机,可广播可连接)、Central(主机,可扫描可连接)。可穿戴设备通常作为Peripheral,手机作为Central。广播是单向的、无连接的通信方式,外设以固定间隔(广播间隔,典型值100ms~1s)在三个广播信道(37/38/39)上发送广播包。广播包包含设备地址、设备名称、服务UUID、发射功率等。扫描是Central侧的行为,它在广播信道上监听广播包,并可能发送扫描请求获取更多信息。
判断方法与操作流程
在实际开发中,判断广播是否正常,可使用手机App(如nRF Connect)扫描查看设备是否出现。广播参数设置需注意:广播间隔越短,发现越快,但功耗越高;广播数据包最大31字节,若需广播更多数据,可使用扫描响应(Scan Response)额外提供31字节。操作流程为:初始化协议栈→配置广播参数(类型、间隔、数据)→启动广播→等待扫描请求→(可选)发送扫描响应。
| 参数 | 典型值 | 影响 |
|---|---|---|
| 广播间隔 | 100ms~1s | 间隔越短,发现越快,功耗越高 |
| 广播类型 | 可连接非定向广播 | 最常用,允许Central发起连接 |
| 广播数据 | 31字节 | 包含设备名、服务UUID、外观等 |
| 扫描响应 | 31字节 | 需Central发送扫描请求才返回 |
案例拆解:手环广播异常排查
某手环项目反馈手机扫描不到设备。使用nRF Connect扫描,发现设备偶尔出现但很快消失。分析广播包发现,广播间隔设置为20ms(远低于规范最小值100ms),且广播数据包含完整的设备名称(20字节)+ 服务UUID(16字节),导致广播包超过31字节上限,协议栈自动丢弃部分数据。解决:将广播间隔调整为200ms,将设备名称截断为8字节,服务UUID使用16位短UUID。修改后设备稳定可见。
3.2 连接参数与连接管理
核心原理
当Central扫描到Peripheral并发起连接请求后,双方进入连接状态。连接由三个关键参数定义:连接间隔(Connection Interval,7.5ms~4s,步进1.25ms)、从机延迟(Slave Latency,0~499)、超时时间(Supervision Timeout,100ms~32s)。连接间隔决定两个设备之间的通信频率,从机延迟允许从机跳过若干次连接事件以省电,超时时间用于检测连接丢失。可穿戴设备通常使用30~50ms的连接间隔,从机延迟设为4~9,超时时间设为5~10s。
判断方法与操作流程
连接参数由Central决定,但Peripheral可以发起连接参数更新请求。判断连接质量,可查看实际连接间隔与协商值是否一致,以及丢包率。操作流程:连接建立→Peripheral发送连接参数更新请求→Central接受或拒绝→(若拒绝)Peripheral可再次请求或维持默认参数。iOS对连接参数有严格限制:连接间隔必须为15ms的整数倍,从机延迟必须为0或偶数。
案例拆解:连接不稳定导致数据丢失
某体脂秤设备与手机连接后,经常在传输数据过程中断开。通过抓取HCI日志发现,实际连接间隔为7.5ms(最小值),从机延迟为0,导致空口过于拥挤,且设备功耗飙升。进一步分析,是Central(手机)在连接时使用了默认参数,未考虑外设能力。解决:Peripheral在连接建立后立即发送连接参数更新请求,将连接间隔调整为30ms,从机延迟设为4,超时时间设为10s。修改后连接稳定,数据完整率从92%提升至99.8%。
3.3 GATT:服务与特征值
核心原理
GATT(Generic Attribute Profile)定义了连接建立后数据的组织方式。数据以服务(Service)和特征值(Characteristic)的形式组织。一个服务包含多个特征值,每个特征值有属性(读、写、通知、指示)和值。例如,心率服务(0x180D)包含心率测量特征值(0x2A37),支持通知属性。特征值还可以包含描述符(Descriptor),用于配置通知开关(CCCD,Client Characteristic Configuration Descriptor)。
判断方法与操作流程
开发时,需先定义服务UUID和特征值UUID。标准服务使用16位UUID(如0x180D),自定义服务使用128位UUID。操作流程:创建GATT服务→添加特征值→设置属性(读/写/通知)→启动服务→等待Central发现。Central侧流程:发现服务→发现特征值→(如需通知)写入CCCD→接收数据。
| 属性 | 权限 | 典型用途 |
|---|---|---|
| Read | Central读 | 读取静态信息(设备型号、固件版本) |
| Write | Central写 | 发送命令(开始测量、同步时间) |
| Notify | Peripheral主动推送 | 实时数据(心率、步数) |
| Indicate | Peripheral主动推送(需确认) | 重要数据(血糖结果) |
案例拆解:自定义服务设计
某血压计需要传输血压值(收缩压、舒张压、脉搏)和测量时间。设计服务UUID为0xFFE0,包含三个特征值:血压数据(0xFFE1,Notify)、测量时间(0xFFE2,Read)、控制点(0xFFE3,Write)。血压数据特征值使用Notify属性,测量时间使用Read属性,控制点用于触发测量。实际测试中,发现血压数据特征值通知频率过高(每次心跳都通知),导致手机端处理不过来。优化:将多次测量结果合并为一次通知,或增加数据缓冲。
3.4 ATT与MTU
核心原理
ATT(Attribute Protocol)是GATT的底层传输协议,负责属性(Attribute)的读写、通知等操作。MTU(Maximum Transmission Unit)是ATT层最大传输单元,默认值为23字节(其中ATT头3字节,有效载荷20字节)。MTU决定了单次传输的数据量。在BLE 4.2及以上版本,MTU可协商至247字节(Android)或185字节(iOS)。MTU越大,传输效率越高,但功耗也相应增加。
判断方法与操作流程
MTU协商发生在连接建立后,由Central发起(或Peripheral请求)。操作流程:连接建立→Central发送MTU协商请求(Exchange MTU Request)→Peripheral回复自己的最大MTU→双方取较小值。判断当前MTU,可通过抓包或API查询。在Android中,可使用BluetoothGatt.requestMtu();在iOS中,系统自动协商,开发者无法直接控制。
// Android端MTU协商示例
BluetoothGatt gatt = device.connectGatt(context, false, callback);
gatt.requestMtu(247); // 请求247字节MTU
// 回调中获取实际MTU
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
Log.d("BLE", "MTU changed to " + mtu);
}
案例拆解:MTU对传输速率的影响
某血氧仪需要传输连续的血氧波形数据,每帧数据50字节。使用默认MTU(23字节)时,每帧需要分3次传输(20+20+10),且每次传输间隔至少一个连接间隔(30ms),总耗时90ms。协商MTU至247字节后,每帧只需1次传输,耗时30ms,传输速率提升3倍。但注意,MTU协商需要双方支持,且协商过程本身需要一次连接事件。实测中,Android设备协商成功率约95%,iOS设备约100%。
3.5 综合实战:健康数据同步链路设计
核心原理
一个完整的健康数据同步链路,需要将上述概念串联起来。以智能手环同步心率数据为例:手环作为Peripheral,广播心率服务;手机作为Central,扫描并连接;连接后,手机发现心率服务,配置通知;手环通过Notify属性持续推送心率数据;手机接收并解析。整个过程涉及GAP(广播/扫描/连接)、GATT(服务/特征值)、ATT(MTU/读写操作)。
操作流程
- 手环启动广播,广播数据包含心率服务UUID(0x180D)和设备名称。
- 手机扫描到设备,发起连接请求。
- 连接建立后,手机执行服务发现,获取心率服务及其特征值。
- 手机写入CCCD(0x2902)启用通知。
- 手环开始以1Hz频率发送心率数据(每包2字节心率值)。
- 手机接收数据,解析并显示。
案例拆解:多设备连接场景
某用户同时佩戴手环和心率带,手机需要同时接收两路数据。手环使用心率服务(0x180D),心率带使用自定义服务(0xFFE0)。手机分别连接两个设备,各自维护独立的GATT连接。问题:两个设备同时通知时,可能出现数据交错。解决:在应用层为每个设备分配独立的缓冲区,并根据设备地址区分数据来源。实测中,双设备同时传输时,丢包率低于0.1%。