第1章 GATT协议核心模型:属性、服务、特征、描述符、UUID体系
1.1 本章边界与定位
GATT(Generic Attribute Profile)是BLE(Bluetooth Low Energy)协议栈中最高层的应用层规范,定义了两个BLE设备之间如何通过属性(Attribute)进行结构化数据交换。本章边界限定在逻辑抽象层,不涉及L2CAP、HCI、链路层等底层传输细节。模型由以下5个核心构件组成:
- 属性(Attribute):最小的数据单元,对应一个句柄、UUID、权限和值。
- 服务(Service):一组相关属性的集合,用于完成特定功能。
- 特征(Characteristic):服务内的数据点,包含一个值属性及若干描述符。
- 描述符(Descriptor):描述特征属性的元数据。
- UUID:全局唯一标识符,用于识别服务、特征、描述符的类型。
| 构件 | 层级 | 示例 | UUID长度 |
|---|---|---|---|
| 属性 | 底层原子单元 | 句柄0x000E,值“温度25.3°C” | 16位/128位 |
| 服务 | 集合容器 | 电池服务(0x180F) | 16位/128位 |
| 特征 | 数据出入口 | 电池电量特征(0x2A19) | 16位/128位 |
| 描述符 | 特征元数据 | 用户描述(0x2901) / 客户端特征配置(0x2902) | 16位/128位 |
架构师视角:GATT模型本质是一个键值对(句柄→属性)的扁平数据库,服务/特征/描述符只是对该数据库的逻辑分组约束。理解这一点是后续依赖注入边界设计的前提。
1.2 分层职责与数据流
BLE协议栈从下往上分为:物理层 → 链路层 → HCI → L2CAP → ATT → GATT。ATT负责基本读写操作(Read/Write/Notify/Indicate),GATT在此基础上加上了角色(Client/Server)和结构化组织。
- GATT Server:持有属性数据库的设备,响应读写请求、主动发送通知。
- GATT Client:向Server发起请求,接收响应或通知的设备。
- 信任链路:Client通过UUID查找服务→特征→描述符的树形路径,再通过句柄直接访问属性。
典型数据流(温度读取):
1. Client发送“按UUID发现服务”ATT请求 → Server返回服务声明属性句柄
2. Client发送“发现特征”ATT请求 → Server返回特征声明属性(包含特征UUID、值句柄)
3. Client发送“读特征值”ATT请求 → Server返回属性值(温度数据)
控制流则涉及连接参数更新、MTU协商、安全认证等,这些由GAP和SM层控制,但GATT模型依赖这些下层服务才能正确收发属性PDU。
1.3 SVG:GATT核心模型结构图
下图展示一个典型BLE设备(Server)中的属性数据库逻辑结构,突出服务、特征、描述符的嵌套关系以及UUID标识体系。
1.4 选型权衡与风险点
| 决策维度 | 推荐方案 | 权衡与风险 |
|---|---|---|
| UUID长度 | 标准服务使用16位UUID,自定义服务使用128位UUID | 128位UUID占用更多属性表空间,但避免与标准服务冲突;风险:若未向Bluetooth SIG注册,可能破坏互操作性 |
| 服务组织结构 | 每个物理功能独立封装为服务 | 服务过多会增加发现时长;风险:过度拆分导致MTU超限和句柄碎片化 |
| 特征数量 | 每个服务不超过12个特征 | 超限可能导致ATT分段错误;风险:深层次描述符链使GATT缓存失效 |
| 描述符使用 | 仅对需配置的必选描述符(CCCD、用户描述)使用 | 非必要描述符增加属性数据库大小和连接建立时间 |
常见陷阱:将业务逻辑直接耦合到特征值属性(如把状态机状态编码到属性句柄中)。GATT本质是无状态字节流,复杂状态需在应用层或服务层构建,而非利用属性句柄的数字大小表达逻辑。
1.5 落地步骤与验收标准
落地步骤(以nRF Connect SDK为例):
- 定义UUID分配表:区分标准UUID和自定义128位UUID,确保无冲突。
- 设计属性树:按功能划分服务,每个服务内排列特征和描述符,确定句柄顺序。
- 实现属性数据库:使用BT_GATT_SERVICE_DEFINE等宏定义服务表。
- 分配权限:设置读/写/通知/指示的权限,匹配GAP安全等级。
- 验证一致性:通过Bluetooth规范兼容性检视(如使用nRF Connect App查看属性树)。
验收标准:
- 属性数据库句柄连续且无空洞。
- 服务声明句柄的UUID与设计一致。
- 特征声明结构符合规范(包含特征属性、值句柄、特征UUID)。
- 所有描述符的UUID在标准库中有定义(或已在自定义UUID清单中登记)。
- MTU大小为247时,单次通知/指示能传输最大有效载荷长度。
- 不存在两个不同服务使用相同UUID(除规格允许的重复引用外)。
效率建议:在开发早期使用BT_GATT_DB_DUMP工具或日志输出属性树全貌,避免后期集成时因句柄偏移导致的读写出错。