1. GATT协议基础:BLE协议栈架构、GATT与GAP的区别、GATT的角色(Server/Client)、Attribute Protocol基础
各位同学,咱们今天正式开讲《GATT服务数据采集与模组联调实战》的第一章。说实话,我做了这么多年嵌入式开发,接触过的无线协议少说也有七八种,但BLE(蓝牙低功耗)这套东西,尤其是GATT(通用属性协议),是让我觉得「既简单又容易踩坑」的一个。为什么这么说?你往下看就知道了。
1.1 BLE协议栈架构:从物理层到应用层
先看整体。BLE协议栈分两层:Controller(控制器)和Host(主机)。中间有个HCI(主机控制器接口)把它们连起来。我刚开始学的时候,总觉得这分层有点多余——直接调API不就行了?后来做量产项目才发现,分层是为了解耦。芯片厂负责Controller,你做应用层,各管各的,互不干扰。
具体分层是这样的:
| 层级 | 归属 | 主要职责 |
|---|---|---|
| Physical Layer(物理层) | Controller | 2.4GHz ISM频段,40个信道,调制解调 |
| Link Layer(链路层) | Controller | 广播、扫描、连接建立、数据包重传 |
| HCI(主机控制器接口) | 边界 | Host与Controller之间的命令/事件通道 |
| L2CAP(逻辑链路控制与适配协议) | Host | 数据包分段重组、多路复用 |
| ATT(属性协议) | Host | 属性数据的读写、通知、指示 |
| GATT(通用属性协议) | Host | 基于ATT的服务/特征值/描述符框架 |
| GAP(通用访问协议) | Host | 广播、扫描、连接、安全、角色管理 |
你看,GATT和GAP都在Host层,但干的活完全不同。GAP管「怎么找到对方、怎么连上」,GATT管「连上之后怎么交换数据」。我见过不少新手把这两个搞混,调了半天GATT发现连广播都没配好——嗯,顺序很重要。
核心要点:GAP负责连接建立前的行为(广播、扫描、连接),GATT负责连接建立后的数据交互(读写、通知)。两者分工明确,互不重叠。
1.2 GATT与GAP的区别:一个管连接,一个管数据
咱们用个生活化的例子。GAP就像你去参加一个行业交流会——你得先找到会场(扫描),跟人打招呼(广播),交换名片(连接请求)。GATT呢,是你们交换完名片之后,坐下来聊具体业务——你问对方「你们公司做什么产品?」(读特征值),对方说「我们做传感器模组」(写响应),或者主动告诉你「我们刚发布了新品」(通知)。
具体区别我列了个表:
| 维度 | GAP | GATT |
|---|---|---|
| 核心功能 | 设备发现、连接建立、安全配对 | 数据交互、服务发现、特征值读写 |
| 角色 | Broadcaster/Observer/Peripheral/Central | Server/Client |
| 数据单元 | 广播包、扫描响应包 | 属性(Attribute) |
| 工作阶段 | 连接前 + 连接中(部分) | 连接建立后 |
| 典型API | gap_advertise_start(), gap_scan_start() | gatt_read_char(), gatt_write_cmd() |
我个人习惯是:先配GAP,再配GATT。GAP没配好,GATT根本跑不起来。有一次我在项目里调一个心率采集模组,死活连不上手机,折腾了两天——最后发现是广播间隔设得太短,手机端扫描窗口没对齐。你看,GAP的锅,别让GATT背。
1.3 GATT的角色:Server与Client
GATT只有两个角色:Server(服务端)和Client(客户端)。Server持有数据,Client读写数据。一个设备可以同时是Server和Client,但通常嵌入式模组扮演Server,手机App扮演Client。
举个例子。你做一个温湿度传感器模组,模组里存着温度和湿度的数值——它就是Server。手机App连上来,读取温度值——它就是Client。Server不能主动去读Client的数据,Client也不能被动等Server推送——除非Server用Notification(通知)或Indication(指示)主动发。
实战经验:我建议你在设计GATT服务时,把Server端的数据更新逻辑和Client端的读取逻辑分开考虑。Server只管「数据对不对、什么时候通知」,Client只管「怎么读、怎么解析」。这样联调时定位问题快得多。
角色关系可以用一张图来理解:
这张图里,实线箭头表示Client主动发起的读写请求,虚线箭头表示Server主动推送的通知。你想想看,如果Server想主动告诉Client「温度超标了」,它不能直接写Client的数据——只能用Notification。这个机制在数据采集场景里特别常用。
1.4 Attribute Protocol基础:GATT的基石
GATT不是凭空存在的,它建立在ATT(属性协议)之上。ATT定义了数据的基本单元——属性(Attribute)。每个属性包含四个要素:
- Attribute Handle(属性句柄):16位整数,唯一标识一个属性。Server内部用句柄索引属性,Client通过句柄读写属性。
- Attribute Type(属性类型):用UUID(通用唯一标识符)表示。16位UUID用于标准服务(如心率服务0x180D),128位UUID用于自定义服务。
- Attribute Permissions(属性权限):决定谁能读、谁能写、是否需要加密。权限配错了,Client读写就会失败。
- Attribute Value(属性值):实际数据,长度可变(最长512字节,但实际受MTU限制)。
避坑指南:我曾经在一个项目里把属性权限配成了「仅加密可读」,但配对流程没走完,结果手机App死活读不到数据。查了两天才发现是权限和配对顺序的问题。建议你在开发阶段先用「无加密可读可写」,调通后再加安全策略。
ATT协议定义了6种PDU(协议数据单元)类型,GATT主要用到其中4种:
| PDU类型 | 方向 | 用途 |
|---|---|---|
| Read Request / Response | Client → Server → Client | Client读取属性值,Server返回数据 |
| Write Request / Response | Client → Server → Client | Client写入属性值,Server确认写入成功 |
| Write Command | Client → Server | Client写入属性值,Server不回复(无确认) |
| Notification / Handle Value Notification | Server → Client | Server主动推送数据,Client不确认 |
| Indication / Handle Value Indication | Server → Client → Server | Server主动推送数据,Client必须确认 |
这里有个细节:Notification和Indication的区别在于是否需要Client确认。Notification快但不可靠(丢包不重传),Indication可靠但慢(有确认机制)。我在做数据采集项目时,高频数据用Notification(比如加速度计100Hz输出),关键事件用Indication(比如报警触发)。
1.5 GATT数据模型:Service、Characteristic、Descriptor
GATT在ATT的基础上,定义了三级数据模型:
- Service(服务):一组相关功能的集合。比如「心率服务」包含心率测量值、心率传感器位置等特征值。
- Characteristic(特征值):一个具体的数据点。包含一个值(Value)和若干描述符(Descriptor)。比如「心率测量值」特征值,值就是心率数值。
- Descriptor(描述符):描述特征值的元数据。比如「客户端特征配置描述符(CCCD)」用来开启或关闭Notification。
我画了个结构图,帮你理解这三层的关系:
你看,一个Service就像一个大抽屉,里面放着多个Characteristic(小盒子),每个小盒子里除了数据本身,还贴着标签(Descriptor)。CCCD(0x2902)是最常用的Descriptor——Client往里面写0x0001,Server就开始发Notification;写0x0000,就停止。
小技巧:调试GATT服务时,我习惯先用手机App(比如nRF Connect或LightBlue)扫描设备,看看Service和Characteristic有没有正确暴露出来。如果App里能看到UUID但读不到值,八成是权限或句柄映射的问题。
1.6 本章小结
咱们把这一章的核心内容捋一遍:
- BLE协议栈分Controller和Host两层,GATT和GAP都在Host层,但分工不同——GAP管连接,GATT管数据。
- GATT只有两个角色:Server(持有数据)和Client(读写数据)。嵌入式模组通常是Server。
- ATT是GATT的底层协议,属性由句柄、类型、权限、值四要素组成。
- GATT数据模型分三层:Service(服务)、Characteristic(特征值)、Descriptor(描述符)。
- Notification和Indication是Server主动推送数据的两种方式,前者快但不可靠,后者可靠但慢。