第1章:GAP(通用访问规范)——蓝牙设备的“社交礼仪”
各位同学,咱们开始聊GAP。说实话,GAP这个词听起来挺唬人的——“通用访问规范”,感觉像是什么高深莫测的协议。但说白了,它就是蓝牙设备之间怎么打招呼、怎么互相发现、怎么建立连接的一套规则。
我当年刚接触BLE时,也把GAP和GATT搞混过。后来在做一个共享单车的项目时,才真正体会到:GAP管的是“设备怎么被发现”,GATT管的是“发现之后能干什么”。今天咱们先搞定GAP。
1.1 广播模式:设备在“喊话”
想象一下,你走进一个共享单车停车场。每辆车都在喊:“我在这儿!我的编号是XXX!我支持这些服务!”——这就是广播。
在BLE里,广播模式分四种。我直接给你列个表,项目里选哪种,心里要有数:
| 广播模式 | 说明 | 典型场景 |
|---|---|---|
| 可连接广播 | 设备可被发现,也能被连接 | 共享单车、智能锁 |
| 可扫描广播 | 设备可被发现,但不能连接 | 信标(Beacon) |
| 不可连接广播 | 只发数据,不响应扫描 | 广播传感器数据 |
| 定向广播 | 只对特定设备广播 | 快速重连 |
我在做共享单车项目时,用的就是可连接广播。因为用户扫码后,手机需要连上车锁,然后开锁。如果用了不可连接广播,那手机就永远连不上车了——嗯,这个坑我见过有人踩过。
重要:广播间隔(Advertising Interval)直接影响功耗和发现速度。我建议共享单车场景用 100ms-200ms,太短费电,太长用户扫码后半天连不上。
1.2 扫描模式:手机在“监听”
广播是车在喊,扫描就是手机在听。手机有两种扫描模式:
- 被动扫描:只听,不回复。手机只接收广播包,不发送任何请求。省电,但信息有限。
- 主动扫描:听到广播后,手机发一个“扫描请求”,设备回复“扫描响应”。能拿到更多数据,比如设备名称、支持的Service UUID。
你想想看,用户打开App扫码时,App用的是主动扫描还是被动扫描?答案是主动扫描。因为App需要拿到车锁的完整信息,才能判断这辆车能不能用、是不是在服务区。
我记得有一次,客户反馈说“有些车扫不到”。排查了半天,发现是车锁的广播间隔设得太长(1秒一次),手机扫描窗口又短,刚好错过。后来我把广播间隔调到150ms,问题就解决了。这种细节,项目里真的要注意。
1.3 连接建立流程:从“打招呼”到“握手”
广播和扫描只是前戏。真正的连接建立,分三步走:
- 广播阶段:车锁持续广播,包含设备地址、是否可连接等信息。
- 扫描阶段:手机收到广播,发起扫描请求(如果是主动扫描),拿到更多数据。
- 连接请求:手机决定连接,发送CONNECT_REQ。车锁收到后,双方进入连接状态。
这里有个关键点:连接参数。手机在CONNECT_REQ里会带上连接间隔、延迟、超时时间等参数。我建议共享单车场景用以下参数:
| 参数 | 推荐值 | 说明 |
|---|---|---|
| 连接间隔 | 30ms - 50ms | 太短费电,太长响应慢 |
| 从机延迟 | 0 | 共享单车不需要延迟 |
| 超时时间 | 4秒 - 6秒 | 超过这个时间没收到包,就断开 |
避坑指南:我曾经遇到过一个情况——连接间隔设成10ms,结果车锁功耗飙升,电池两天就耗光了。后来改成30ms,功耗降了60%。别为了追求“快”而牺牲续航。
1.4 广播数据包结构(AD Structure)
广播包不是随便塞数据的。它遵循一个固定的结构——AD Structure。每个AD Structure由三部分组成:
- 长度(Length):1字节,表示后面AD Type + AD Data的总长度。
- 类型(AD Type):1字节,表示数据类型。比如0x01表示Flags,0x09表示完整设备名称。
- 数据(AD Data):长度不固定,具体内容由AD Type决定。
举个例子,一个最简单的广播包,包含Flags和完整设备名称:
// 广播数据示例
0x02 // 长度:后面2字节
0x01 // AD Type: Flags
0x06 // Flags值:LE General Discoverable + BR/EDR Not Supported
0x0A // 长度:后面10字节
0x09 // AD Type: Complete Local Name
0x42 0x69 0x6B 0x65 0x5F 0x30 0x30 0x31 // "Bike_001" 的ASCII码
你看,就是这么简单。但实际项目中,广播包能塞的数据有限——最多31字节。所以你得精打细算。我一般会放:
- Flags(1字节)
- 设备名称(看长度)
- Service UUID(2或4字节)
- 自定义数据(比如电量、锁状态)
小技巧:如果设备名称太长,可以用缩短的设备名称(AD Type 0x08),只放前几个字符。剩下的信息通过扫描响应补全。这样广播包能省出空间放更重要的数据。
1.5 实战经验总结
好了,这一章的内容差不多就这些。最后我分享几点实战经验:
- 广播间隔别乱设:共享单车场景,100ms-200ms是黄金区间。太短费电,太长用户连不上。
- 主动扫描是标配:别用被动扫描,否则拿不到设备名称,用户体验差。
- 连接参数要权衡:30ms-50ms的连接间隔,兼顾响应速度和功耗。
- 广播包要精打细算:31字节很宝贵,优先放关键数据。
下一章,咱们聊GATT——设备连上之后,怎么读写数据。到时候我会拿共享单车的开锁流程举例,保证你一听就懂。
公众号:蓝海资料掘金营,微信deep3321