GAP与广播机制:角色、模式与数据格式

GAP(Generic Access Profile)是BLE协议栈的“门面”。说白了,它决定了你的设备怎么被发现、怎么跟别人建立连接。我刚开始做BLE项目时,总觉得GAP就是个配置参数,后来踩了不少坑才明白——GAP角色选错了,广播数据配不对,设备可能根本连不上。

GAP角色与模式

BLE设备在GAP层有四种角色,每种角色对应不同的行为模式。我习惯把它们分成两组:

角色 典型设备 核心行为
Broadcaster(广播者) 信标、温度传感器 只发广播,不接收连接
Observer(观察者) 扫描仪、网关 只收广播,不发起连接
Peripheral(外设) 手环、心率带 发广播,等待连接
Central(中心) 手机、平板 扫描广播,发起连接

这里有个容易混淆的点:Broadcaster和Peripheral都会发广播,但前者不响应连接请求,后者会。我在项目中遇到过客户把信标设成Peripheral角色,结果手机一直弹配对框——其实人家只想收个UUID而已。

我的习惯:纯数据上报场景(如温湿度传感器)用Broadcaster,需要双向通信的场景(如智能锁)用Peripheral。别混用,否则功耗和连接行为都会出问题。

广播类型:三种核心模式

BLE广播分三种类型,每种类型决定了扫描者能做什么。嗯,这里直接看表:

广播类型 可连接 可扫描 典型场景
可连接广播 是 是 外设等待中心连接
不可连接广播 否 否 信标、广播数据
可扫描广播 否 是 需要扫描响应的场景

你可能会问:可扫描广播有什么用?它允许扫描者发送扫描请求,广播者回复扫描响应数据。这样可以在不建立连接的情况下,多传一些数据。我曾经用这个模式做室内定位——广播包放主要UUID,扫描响应放附加的RSSI校准值,省了一次连接开销。

注意:不可连接广播不代表扫描者收不到数据,只是不能发连接请求。我见过有人把信标设成可连接广播,结果功耗翻了一倍——因为芯片一直在监听连接请求。

广播数据格式:AD Structure

广播数据不是随便塞的。BLE协议规定,广播数据由若干个AD Structure组成,每个AD Structure的结构如下:

Length (1 byte) | AD Type (1 byte) | AD Data (Length-1 bytes)

举个例子,假设你要广播一个16位Service UUID 0x180D(心率服务):

0x03 0x03 0x0D 0x18
|    |    |____|
|    |       └─ UUID (小端序)
|    └─ AD Type = 0x03 (完整16位UUID列表)
└─ Length = 3 (包含Type和Data)

常见的AD Type我列一下:

  • 0x01 — Flags(广播标志,必填)
  • 0x02/0x03 — 16位Service UUID(不完整/完整)
  • 0x06/0x07 — 128位Service UUID
  • 0x08/0x09 — 本地名称(缩短/完整)
  • 0xFF — 厂商自定义数据
关键点:广播包最大31字节,扫描响应也是31字节。你想想看,一个Flags占3字节,一个UUID占2或16字节,名字再占几个——空间很紧张。我习惯把核心信息放广播包,辅助信息放扫描响应。

广播间隔与占空比

广播间隔决定了设备多久发一次广播包。间隔越短,被发现越快,但功耗越高。间隔越长,省电,但扫描者可能要等更久才能发现你。

广播间隔的范围是20ms到10.24s,步进0.625ms。实际项目中,我常用的几个值:

场景 推荐间隔 占空比 说明
快速发现(配对) 20~50ms 高 用户等待时用,功耗大
常规广播 100~500ms 中 日常连接场景
低功耗广播 1~5s 低 电池供电设备
信标 100ms~1s 中低 根据定位精度调整

占空比 = 广播包发送时间 / 广播间隔。举个例子,一个广播包大约376μs(37字节@1Mbps),间隔100ms时占空比约0.376%。间隔20ms时占空比约1.88%——功耗差了5倍。

避坑指南:我曾经把广播间隔设成20ms,结果设备发热严重。后来发现是广播信道(37/38/39)三个信道都在发,实际占空比是3倍。建议非必要场景只用主信道(ch37)广播,或者延长间隔。

GAP与广播机制知识体系

下面这张图把GAP角色、广播类型、数据格式和间隔的关系串起来了:

GAP与广播机制知识体系 GAP与广播机制知识体系 GAP角色 Broadcaster Observer Peripheral Central 广播类型 可连接广播 不可连接广播 可扫描广播 广播数据格式 (AD Structure) Length (1B) AD Type (1B) AD Data (N-1B) 最大31字节/包 广播间隔:20ms ~ 10.24s | 占空比 = 广播时长 / 间隔

这张图从顶层GAP角色开始,往下分广播类型,再到底层数据格式和间隔参数。你想想看,选角色决定了广播类型,广播类型决定了数据怎么封装,而间隔和占空比直接影响功耗和发现速度——环环相扣。

最后提醒:广播数据里的Flags字段(AD Type 0x01)是必填的,它告诉扫描者设备是否支持BR/EDR、是否处于有限可发现模式。我见过有人漏了这个字段,结果iOS设备死活扫不到。别省这3个字节。