3、BLE关键概念:广播、扫描、连接、GATT、GAP、服务与特征值、MTU与ATT

可穿戴设备(手表、手环、体脂秤、血糖仪等)与手机之间的数据同步,绝大多数基于BLE(Bluetooth Low Energy,低功耗蓝牙)协议栈。BLE之所以能在极低功耗下完成可靠传输,是因为它定义了一套与经典蓝牙完全不同的工作模式:设备不总是保持连接,而是通过广播宣告存在、通过扫描发现彼此、按需建立连接,再通过GATT(Generic Attribute Profile)规范组织数据。理解广播、扫描、连接、GAP、GATT、服务与特征值、MTU与ATT这八个核心概念,是进行可穿戴设备蓝牙开发、功耗调优和兼容性排障的基础。下图展示了BLE协议栈中这些关键概念的分层关系与数据流向。

BLE关键概念分层与数据流 GAP(通用访问规范) • 广播(Advertising) • 扫描(Scanning) • 连接建立(Connection) • 设备角色:Broadcaster/ Observer/Peripheral/Central 负责设备发现与连接 ATT/GATT层 • ATT(属性协议) • GATT(通用属性规范) • 服务(Service) • 特征值(Characteristic) • MTU(最大传输单元) 负责数据组织与读写 连接(Connection) 连接间隔(Connection Interval) 从机延迟(Slave Latency) 超时时间(Supervision Timeout) 建立 传输 MTU与ATT操作 ATT操作:Read / Write / Notify / Indicate / Write Command MTU:默认23字节(ATT_MTU),可协商至247字节(Android/iOS) 数据流:Characteristic Value → ATT PDU → L2CAP → 空口 典型同步流程 ① 外设广播 → ② 主机扫描 → ③ 连接建立 → ④ 发现服务 ⑤ 配置MTU → ⑥ 使能通知 → ⑦ 接收健康数据 → ⑧ 断开连接

上图展示了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。修改后设备稳定可见。

常见误区:广播间隔并非越小越好。过小的广播间隔(<50ms)会导致信道拥塞,且部分手机扫描策略会忽略高频广播的设备。建议广播间隔设置在100ms~500ms之间,兼顾发现速度与功耗。

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或偶数。

经验提示:在iOS上,若连接间隔不是15ms的整数倍,系统会强制使用最接近的合法值。例如请求30ms,实际可能变为30ms或45ms。Android则相对宽松,但部分厂商(如小米)也有类似限制。开发时建议使用标准值:30ms、45ms、60ms。

案例拆解:连接不稳定导致数据丢失

某体脂秤设备与手机连接后,经常在传输数据过程中断开。通过抓取HCI日志发现,实际连接间隔为7.5ms(最小值),从机延迟为0,导致空口过于拥挤,且设备功耗飙升。进一步分析,是Central(手机)在连接时使用了默认参数,未考虑外设能力。解决:Peripheral在连接建立后立即发送连接参数更新请求,将连接间隔调整为30ms,从机延迟设为4,超时时间设为10s。修改后连接稳定,数据完整率从92%提升至99.8%。

风险提示:连接参数更新请求可能被Central拒绝。若被拒绝,Peripheral应等待一段时间(建议5s)后再次请求,最多尝试3次。不要频繁发送请求,否则可能被系统拉黑。

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→接收数据。

属性权限典型用途
ReadCentral读读取静态信息(设备型号、固件版本)
WriteCentral写发送命令(开始测量、同步时间)
NotifyPeripheral主动推送实时数据(心率、步数)
IndicatePeripheral主动推送(需确认)重要数据(血糖结果)

案例拆解:自定义服务设计

某血压计需要传输血压值(收缩压、舒张压、脉搏)和测量时间。设计服务UUID为0xFFE0,包含三个特征值:血压数据(0xFFE1,Notify)、测量时间(0xFFE2,Read)、控制点(0xFFE3,Write)。血压数据特征值使用Notify属性,测量时间使用Read属性,控制点用于触发测量。实际测试中,发现血压数据特征值通知频率过高(每次心跳都通知),导致手机端处理不过来。优化:将多次测量结果合并为一次通知,或增加数据缓冲。

设计建议:特征值数量不宜过多,建议控制在5个以内。每个特征值都有独立的句柄和配置,过多会增加发现时间和内存占用。对于需要频繁传输的数据,优先使用Notify而非Indicate,因为Indicate需要应用层确认,吞吐量较低。

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

注意事项:MTU并非越大越好。过大的MTU会增加单次传输的出错概率,且需要更大的缓冲区。对于可穿戴设备,建议MTU设置在100~185字节之间,兼顾效率与稳定性。同时,MTU协商应在连接建立后尽快完成,避免影响后续数据传输。

3.5 综合实战:健康数据同步链路设计

核心原理

一个完整的健康数据同步链路,需要将上述概念串联起来。以智能手环同步心率数据为例:手环作为Peripheral,广播心率服务;手机作为Central,扫描并连接;连接后,手机发现心率服务,配置通知;手环通过Notify属性持续推送心率数据;手机接收并解析。整个过程涉及GAP(广播/扫描/连接)、GATT(服务/特征值)、ATT(MTU/读写操作)。

操作流程

  1. 手环启动广播,广播数据包含心率服务UUID(0x180D)和设备名称。
  2. 手机扫描到设备,发起连接请求。
  3. 连接建立后,手机执行服务发现,获取心率服务及其特征值。
  4. 手机写入CCCD(0x2902)启用通知。
  5. 手环开始以1Hz频率发送心率数据(每包2字节心率值)。
  6. 手机接收数据,解析并显示。

案例拆解:多设备连接场景

某用户同时佩戴手环和心率带,手机需要同时接收两路数据。手环使用心率服务(0x180D),心率带使用自定义服务(0xFFE0)。手机分别连接两个设备,各自维护独立的GATT连接。问题:两个设备同时通知时,可能出现数据交错。解决:在应用层为每个设备分配独立的缓冲区,并根据设备地址区分数据来源。实测中,双设备同时传输时,丢包率低于0.1%。

总结复盘:BLE健康数据同步的核心在于理解GAP和GATT的分工。GAP解决“设备如何被发现和连接”,GATT解决“连接后数据如何组织”。MTU和ATT决定了传输效率。开发时,应优先确定服务模型(GATT),再配置广播参数(GAP),最后优化MTU和连接参数。常见问题中,80%与广播参数配置不当或连接参数不匹配有关,15%与MTU协商失败有关,5%与GATT服务设计不合理有关。