BLE之GATT原文
蓝牙核心规范 5.0 | 第 3 卷,G 部分
通用属性配置文件(GATT)
译自:BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G
Generic Attribute Profile (GATT)
日期:2016 年 12 月 6 日
版权所有 © 蓝牙技术联盟(Bluetooth SIG)
目录
1 简介
1.1 范围
本文档定义了通用属性配置文件(Generic Attribute Profile,GATT),该配置文件使用属性协议(Attribute Protocol,ATT)描述了一个服务框架,通过该框架可发现服务及服务相关特征(Characteristic)的配置和使用方式。
本文档适用于实现了属性协议的设备。
1.2 依赖
本文档依赖于以下蓝牙规范:
- ATT(属性协议):Vol 3,E 部分
- SDP(服务发现协议):Vol 3,B 部分
- L2CAP(逻辑链路控制和自适应协议):Vol 3,A 部分
- GAP(通用访问配置文件):Vol 3,C 部分
1.3 一致性
如果一个实现声明符合本文档,则该实现必须(shall)满足本文档中所有标注为强制性(Mandatory)的需求,并且应当(should)满足所有标注为推荐性(Recommended)的需求。
1.4 兼容性
本文档第 4 版(Version 4.0)中定义的特性与本文档完全兼容。
1.5 约定
本文档使用以下约定:
- 强制性(M):在所有实现中必须支持该特性或过程。
- 可选(O):该特性或过程的支持是可选的。
- 条件(C):该特性或过程的支持取决于是否支持某其他特性或过程。
- 排除(X):在该配置中该特性或过程不得被支持。
- 推荐(R):建议支持该特性或过程,但并非强制性要求。
- 禁止(P):该特性或过程不得被使用。
协议中用到的关键字含义如下:
- shall(应当/必须):绝对要求
- shall not(不得):绝对禁止
- should(应该):建议,但有理由时可以不遵守
- may(可以):可选行为
- can(能够):关于可能性和能力的陈述
2 配置文件概述
2.1 协议栈
通用属性配置文件(GATT)位于属性协议(ATT)之上。GATT 定义了一个框架,用于通过 ATT 发现、读写属性,如图 2.1 所示。
+---------------------------+
| 应用程序 |
+---------------------------+
| GATT(通用属性配置文件) |
+---------------------------+
| ATT(属性协议) |
+---------------------------+
| L2CAP(逻辑链路控制) |
+---------------------------+
| ACL(异步无连接链路) |
+---------------------------+
图 2.1:GATT 协议栈
2.2 GATT 角色
GATT 定义了两种角色:
| 角色 | 描述 |
|---|---|
| 服务器(Server) | 接收来自客户端的请求,接受、执行并响应任何 ATT 命令和请求。服务器包含用于存储数据的属性(Attribute) |
| 客户端(Client) | 向服务器发起命令和请求,并从服务器接收响应、通知和指示 |
注:GATT 角色独立于 BR/EDR 中的主/从角色,也独立于 LE 中的主/从角色。
2.3 用户需求
GATT 旨在满足以下用户需求场景:
- 体温计:测量并报告体温
- 血压计:测量并报告血压
- 运动/健康传感器:测量步速、步距、步数等
- 时间客户端/服务器:读取/写入当前时间
- 家庭自动化:控制家用电器
- 医疗设备:与医疗设备交互
- 电话:与手机交互
- 便携式媒体播放器:控制媒体播放
2.4 基础概念
2.4.1 属性(Attribute)
属性是可寻址的数据块,包含以下字段:
| 字段 | 长度 | 描述 |
|---|---|---|
| 属性句柄(Attribute Handle) | 2 字节 | 在服务器中唯一标识该属性 |
| 属性类型(Attribute Type) | 2 或 16 字节 | 使用 UUID 标识属性类型 |
| 属性值(Attribute Value) | 可变长度 | 属性的实际数据内容 |
| 属性权限(Attribute Permissions) | 由实现定义 | 控制属性的读/写访问权限及安全需求 |
2.4.2 属性句柄(Attribute Handle)
属性句柄是一个 16 位的非零值,范围为 0x0001 至 0xFFFF,用于在服务器中唯一标识一个属性。
- 句柄 0x0000 保留不用
- 句柄按升序分配
- 服务器上的属性句柄不得在连接断开后重新分配
2.4.3 属性类型(Attribute Type)
属性类型使用 UUID(通用唯一标识符)来标识,UUID 可以是:
- 16 位蓝牙 UUID:蓝牙技术联盟(Bluetooth SIG)分配的标准 UUID
- 128 位供应商自定义 UUID:供应商或应用开发者自定义的 UUID
标准蓝牙 UUID 的完整 128 位格式为:
xxxxxxxx-0000-1000-8000-00805F9B34FB
其中 xxxxxxxx 为 16 位或 32 位的蓝牙 UUID 值。
2.4.4 属性值(Attribute Value)
属性值是一个可变长度的字节序列,其含义由属性类型(UUID)决定,长度为 0 至 512 字节。
2.4.5 属性权限(Attribute Permissions)
属性权限不通过 ATT 协议直接暴露,但控制以下访问方式:
- 可读(Readable):允许读取属性值
- 可写(Writeable):允许写入属性值
- 读需要认证(Read Requires Authentication)
- 读需要授权(Read Requires Authorization)
- 读需要加密(Read Requires Encryption)
- 写需要认证(Write Requires Authentication)
- 写需要授权(Write Requires Authorization)
- 写需要加密(Write Requires Encryption)
2.5 属性协议(ATT)
GATT 使用 ATT 协议传输服务相关数据。ATT 定义了客户端和服务器之间的通信规则:
| 通信类型 | 描述 |
|---|---|
| 命令(Command) | 客户端发送给服务器,服务器不响应 |
| 请求(Request) | 客户端发送给服务器,服务器必须响应 |
| 响应(Response) | 服务器对请求的回复 |
| 通知(Notification) | 服务器主动发送给客户端,无需确认 |
| 指示(Indication) | 服务器主动发送给客户端,需要客户端确认 |
| 确认(Confirmation) | 客户端对指示的确认回复 |
2.6 GATT 层次结构
GATT 使用以下数据层次结构组织数据:
配置文件(Profile)
└── 服务(Service)
├── 包含的服务(Included Service)
└── 特征(Characteristic)
├── 特征值(Characteristic Value)
└── 特征描述符(Characteristic Descriptor)
2.6.1 配置文件(Profile)
配置文件定义了特定用途场景下一个或多个服务的使用方法,配置文件本身不存储在服务器上。
2.6.2 服务(Service)
服务是相关行为的集合,由特征(Characteristic)和关系(包含其他服务)组成。服务有两类:
- 主服务(Primary Service):提供主要功能,可被其他服务或客户端发现
- 次要服务(Secondary Service):被其他服务引用,一般不直接使用
2.6.3 包含的服务(Included Service)
包含关系允许一个服务引用另一个服务,实现服务的复用。
2.6.4 特征(Characteristic)
特征包含:
- 特征声明(Characteristic Declaration):定义特征的属性(Properties)、句柄和 UUID
- 特征值(Characteristic Value):实际的数据内容
- 特征描述符(Characteristic Descriptor)(可选):提供特征值的附加信息
2.6.5 特征属性(Characteristic Properties)
特征属性是一个位字段,定义了如何使用特征值及特征描述符:
| 位 | 属性名称 | 描述 |
|---|---|---|
| 0 | 广播(Broadcast) | 可将特征值通过服务器特征配置描述符广播 |
| 1 | 读(Read) | 可用 ATT 读操作读取特征值 |
| 2 | 无响应写入(Write Without Response) | 可用 ATT 写命令写入特征值 |
| 3 | 写(Write) | 可用 ATT 写请求写入特征值 |
| 4 | 通知(Notify) | 服务器可主动发送通知 |
| 5 | 指示(Indicate) | 服务器可主动发送需确认的指示 |
| 6 | 认证签名写入(Authenticated Signed Writes) | 可用 ATT 签名写命令写入特征值 |
| 7 | 扩展属性(Extended Properties) | 存在额外属性定义,详见特征扩展属性描述符 |
3 服务互操作性要求
本章描述服务和特征在服务器中的存储方式,以及如何被客户端读取和使用。
3.1 服务定义
服务定义包含一个服务声明(Service Declaration),以及零个或多个包含声明(Include Declaration)、特征定义(Characteristic Definition)。
服务声明属性(Service Declaration Attribute)
| 字段 | 要求 | 格式 | 描述 |
|---|---|---|---|
| 属性句柄 | 强制(M) | 0x0001 ~ 0xFFFF | 该服务声明的唯一句柄 |
| 属性类型 | 强制(M) | 0x2800(主服务)或 0x2801(次要服务) | 标识服务声明类型 |
| 属性值 | 强制(M) | UUID | 服务的 UUID(16 位或 128 位) |
| 属性权限 | 强制(M) | 可读,无需认证 | 可被任意客户端读取 |
主服务(Primary Service)使用 UUID 0x2800,次要服务(Secondary Service)使用 UUID 0x2801。
3.2 包含定义
包含定义允许一个服务内嵌引用另一个服务。
包含声明属性(Include Declaration Attribute)
| 字段 | 要求 | 格式 | 描述 |
|---|---|---|---|
| 属性句柄 | 强制(M) | 0x0001 ~ 0xFFFF | 该包含声明的句柄 |
| 属性类型 | 强制(M) | 0x2802 | 标识包含声明 |
| 属性值 | 强制(M) | 起始句柄、结束句柄(可选 UUID) | 被包含服务的句柄范围,若为 16 位 UUID 服务则附带 UUID |
| 属性权限 | 强制(M) | 可读,无需认证 | 可被任意客户端读取 |
注:若被包含的服务使用 128 位 UUID,则包含声明的属性值中不包含 UUID,需通过被包含服务的服务声明属性读取 UUID。
3.3 特征定义
特征定义由以下部分组成:
- 特征声明(Characteristic Declaration)
- 特征值声明(Characteristic Value Declaration)
- 特征描述符声明(Characteristic Descriptor Declarations)(可选)
3.3.1 特征声明属性(Characteristic Declaration Attribute)
| 字段 | 要求 | 格式 | 描述 |
|---|---|---|---|
| 属性句柄 | 强制(M) | 0x0001 ~ 0xFFFF | 该特征声明的句柄 |
| 属性类型 | 强制(M) | 0x2803 | 标识特征声明 |
| 属性值 | 强制(M) | 特征属性(1字节)+ 特征值句柄(2字节)+ 特征 UUID | 特征的属性、值句柄和类型 |
| 属性权限 | 强制(M) | 可读,无需认证 | 可被任意客户端读取 |
3.3.2 特征值声明(Characteristic Value Declaration)
特征值声明包含特征的实际数据,其属性类型 UUID 与特征声明中的 UUID 相同。
| 字段 | 要求 | 格式 | 描述 |
|---|---|---|---|
| 属性句柄 | 强制(M) | 特征声明属性值中的值句柄 | 特征值的句柄 |
| 属性类型 | 强制(M) | 特征 UUID | 与特征声明中的 UUID 相同 |
| 属性值 | 强制(M) | 特征值 | 实际数据内容 |
| 属性权限 | 由特征属性决定 | 可读/可写等 | 由具体实现定义 |
3.3.3 特征描述符
特征描述符(Characteristic Descriptor)提供特征的附加元数据。以下是标准定义的描述符:
3.3.3.1 特征扩展属性描述符(Characteristic Extended Properties Descriptor)
- UUID:0x2900
- 属性权限:可读,无需认证
- 属性值:2 字节位字段
| 位 | 属性名称 | 描述 |
|---|---|---|
| 0 | 可靠写入(Reliable Write) | 可以使用 ATT 可靠写入过程(Reliable Write Procedure)写入特征值 |
| 1 | 可写辅助信息(Writable Auxiliaries) | 特征用户描述符(Characteristic User Description Descriptor)可写 |
| 2~15 | 保留 | 保留供未来使用 |
3.3.3.2 特征用户描述符(Characteristic User Description Descriptor)
- UUID:0x2901
- 属性权限:可读(无需认证);若"可写辅助信息"位已设置则可写
- 属性值:UTF-8 编码字符串,对特征的用户可读描述
3.3.3.3 客户端特征配置描述符(Client Characteristic Configuration Descriptor,CCCD)
- UUID:0x2902
- 属性权限:可读(无需认证);可写(每个客户端独立)
- 属性值:2 字节位字段
| 位 | 名称 | 描述 |
|---|---|---|
| 0 | 通知(Notification) | 0 = 禁用通知;1 = 启用通知 |
| 1 | 指示(Indication) | 0 = 禁用指示;1 = 启用指示 |
| 2~15 | 保留 | 保留,应设为 0 |
重要:
- 一个特征只能有一个 CCCD
- 每个连接的客户端(通过地址区分)拥有独立的 CCCD 值
- 断开连接后,非绑定(Non-bonded)设备的 CCCD 值将恢复为默认值(0x0000);绑定设备的 CCCD 值将被保留
3.3.3.4 服务器特征配置描述符(Server Characteristic Configuration Descriptor,SCCD)
- UUID:0x2903
- 属性权限:可读(无需认证);可写(全局性,不区分客户端)
- 属性值:2 字节位字段
| 位 | 名称 | 描述 |
|---|---|---|
| 0 | 广播(Broadcast) | 0 = 不通过广播发送;1 = 在广播的服务器特征配置中发送 |
| 1~15 | 保留 | 保留,应设为 0 |
注:一个特征只能有一个 SCCD,且仅当特征属性中"广播"位被设置时才能使用。
3.3.3.5 特征展示格式描述符(Characteristic Presentation Format Descriptor)
- UUID:0x2904
- 属性权限:可读,无需认证
- 属性值:7 字节
| 字段 | 长度(字节) | 描述 |
|---|---|---|
| 格式(Format) | 1 | 特征值的数据格式(参见蓝牙分配号码) |
| 指数(Exponent) | 1 | 用于计算实际值:Actual Value = Characteristic Value × 10^Exponent(有符号整数) |
| 单位(Unit) | 2 | 值的单位,使用蓝牙 UUID(参见蓝牙分配号码) |
| 命名空间(Namespace) | 1 | 描述符命名空间(0x01 = 蓝牙技术联盟) |
| 描述(Description) | 2 | 在指定命名空间内的描述(0x0000 = 无描述) |
常见的格式值(Format)示例:
| 格式值 | 格式名称 | 描述 |
|---|---|---|
| 0x01 | boolean | 1 位布尔值 |
| 0x04 | uint8 | 8 位无符号整数 |
| 0x06 | uint16 | 16 位无符号整数 |
| 0x08 | uint32 | 32 位无符号整数 |
| 0x0C | sint8 | 8 位有符号整数 |
| 0x0E | sint16 | 16 位有符号整数 |
| 0x10 | sint32 | 32 位有符号整数 |
| 0x14 | float32 | 32 位 IEEE 754 浮点数 |
| 0x19 | utf8s | UTF-8 编码字符串 |
| 0x1B | struct | 不透明数据结构 |
若一个特征有多个展示格式描述符,则每个描述符描述特征值中一个字段的格式,且这些字段须按照句柄升序依次对应特征值中各字段。
3.3.3.6 特征聚合格式描述符(Characteristic Aggregate Format Descriptor)
- UUID:0x2905
- 属性权限:可读,无需认证
- 属性值:特征展示格式描述符句柄列表(每个句柄 2 字节),定义特征值多个字段的格式组合方式
注:只有当一个特征包含多个特征展示格式描述符时,才可使用聚合格式描述符。
4 GATT 功能需求
本章描述 GATT 服务器和客户端支持的功能及其具体过程(Procedure)。
4.1 服务器配置(Server Configuration)
4.1.1 交换 MTU 大小(Exchange MTU Size)
此过程允许客户端通知服务器其接收 ATT 协议数据单元(PDU)的最大大小(MTU)。
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 可选(O) |
过程描述:
- 客户端发送 ATT 交换 MTU 请求(Exchange MTU Request),携带客户端 MTU 值
- 服务器回复 ATT 交换 MTU 响应(Exchange MTU Response),携带服务器 MTU 值
- 连接使用两者中的较小值作为最终 MTU
注:此过程只能执行一次,且只有在 BR/EDR 连接上才需要执行;LE 连接中可使用 LE L2CAP 连接参数更新代替。
4.2 主服务发现(Primary Service Discovery)
4.2.1 发现所有主服务(Discover All Primary Services)
此过程用于发现服务器上所有主服务。
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 强制(M),若存在主服务 |
过程描述:
- 客户端发送 ATT 按类型读取属性组(Read By Group Type Request),属性类型为 主服务 UUID(0x2800),句柄范围为 0x0001 ~ 0xFFFF
- 服务器返回所有主服务的句柄范围和服务 UUID
- 客户端重复发送请求(从上次结束句柄 +1 开始),直到服务器返回错误响应(错误码:属性未找到)
4.2.2 按服务 UUID 发现主服务(Discover Primary Service by Service UUID)
此过程用于发现具有特定 UUID 的主服务。
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 强制(M),若存在主服务 |
过程描述:
- 客户端发送 ATT 按类型和值查找(Find By Type Value Request),属性类型为 0x2800,属性值为目标服务 UUID
- 服务器返回找到的服务句柄范围列表
- 客户端继续发送请求直到收到错误响应
4.3 关系发现(Relationship Discovery)
4.3.1 查找包含的服务(Find Included Services)
此过程用于发现服务中包含(Include)的其他服务。
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 强制(M),若存在包含声明 |
过程描述:
- 客户端发送 ATT 按类型读取(Read By Type Request),属性类型为 包含 UUID(0x2802),句柄范围为目标服务的范围
- 服务器返回找到的包含声明
- 若包含声明中未包含 UUID(即被包含服务使用 128 位 UUID),客户端再发送 ATT 读取请求(Read Request) 读取服务声明属性以获取 UUID
- 客户端重复操作直到遍历完服务范围
4.4 特征发现(Characteristic Discovery)
4.4.1 发现服务内所有特征(Discover All Characteristics of a Service)
此过程用于发现服务内的全部特征及其特征属性。
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 强制(M),若存在特征 |
过程描述:
- 客户端发送 ATT 按类型读取(Read By Type Request),属性类型为 特征 UUID(0x2803),句柄范围为目标服务的范围
- 服务器返回特征声明列表(包含特征属性、特征值句柄、特征 UUID)
- 客户端重复操作直到遍历完服务范围
4.4.2 按 UUID 发现特征(Discover Characteristics by UUID)
此过程用于发现具有特定 UUID 的特征。
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 强制(M),若存在特征 |
过程描述:
- 客户端发送 ATT 按类型读取(Read By Type Request),属性类型为目标特征的 UUID,句柄范围为目标服务的范围
- 服务器返回匹配的特征声明
- 客户端重复操作直到遍历完服务范围
4.5 特征描述符发现(Characteristic Descriptor Discovery)
4.5.1 发现所有特征描述符(Discover All Characteristic Descriptors)
此过程用于发现特征的所有描述符。
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 强制(M),若存在描述符 |
过程描述:
- 客户端使用特征声明的值句柄 + 1 至下一特征声明的句柄 - 1(或服务结束句柄)作为范围,发送 ATT 查找信息请求(Find Information Request)
- 服务器返回该范围内所有属性的句柄和 UUID(即特征描述符)
- 客户端重复操作直到遍历完描述符范围
4.6 特征值读取(Reading Characteristic Values)
4.6.1 读取特征值(Read Characteristic Value)
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 强制(M),若特征属性包含"读" |
过程描述:
- 客户端发送 ATT 读取请求(Read Request),携带特征值句柄
- 服务器返回特征值(若权限允许)
注:ATT 读取请求的响应受 MTU 限制,最多返回 MTU - 1 个字节。如需读取完整长值,使用"读取长特征值"过程。
4.6.2 使用 UUID 读取(Read Using Characteristic UUID)
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 强制(M),若特征属性包含"读" |
过程描述:
- 客户端发送 ATT 按类型读取(Read By Type Request),属性类型为目标特征 UUID,句柄范围为目标服务或所有句柄的范围
- 服务器返回匹配特征的值
4.6.3 读取长特征值(Read Long Characteristic Values)
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 强制(M),若特征属性包含"读" |
过程描述:
- 客户端首先发送 ATT 读取请求(Read Request) 获取起始数据
- 若数据不完整(响应填满了 MTU),继续发送 ATT 读取 Blob 请求(Read Blob Request),指定偏移量
- 重复直到获取完整数据(响应未填满 MTU,或收到错误)
4.6.4 读取多个特征值(Read Multiple Characteristic Values)
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 强制(M) |
过程描述:
- 客户端发送 ATT 读取多个(Read Multiple Request),携带多个特征值句柄列表
- 服务器将所有特征值拼接在一起返回(按句柄顺序)
注:不适用于可变长度的特征值,因为无法确定各值边界。
4.7 特征值写入(Writing Characteristic Values)
4.7.1 写入特征值(Write Characteristic Value)
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 强制(M),若特征属性包含"写" |
过程描述:
- 客户端发送 ATT 写入请求(Write Request),携带特征值句柄和数据
- 服务器写入数据后发送 ATT 写入响应(Write Response)
4.7.2 无响应写入特征值(Write Without Response)
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 强制(M),若特征属性包含"无响应写入" |
过程描述:
- 客户端发送 ATT 写入命令(Write Command),携带特征值句柄和数据
- 服务器写入数据,不发送响应
4.7.3 认证签名写入特征值(Signed Write Without Response)
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 强制(M),若特征属性包含"认证签名写入" |
过程描述:
- 客户端发送 ATT 签名写入命令(Signed Write Command),携带特征值句柄、数据和认证签名
- 服务器验证签名后写入数据,不发送响应
注:仅可用于未加密的连接;若连接已加密,应使用普通写入命令。
4.7.4 写入长特征值(Write Long Characteristic Values)
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 强制(M),若特征属性包含"写" |
过程描述:
- 客户端发送多个 ATT 预写请求(Prepare Write Request),每次指定句柄、偏移量和部分数据
- 服务器将数据缓存后回应 ATT 预写响应(Prepare Write Response)
- 所有数据发送完毕后,客户端发送 ATT 执行写入请求(Execute Write Request),标志为 0x01(执行)
- 服务器原子性地写入所有数据并回应 ATT 执行写入响应(Execute Write Response)
客户端也可发送执行写入请求(标志 0x00)取消所有预写操作。
4.7.5 可靠写入(Reliable Writes)
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 强制(M),若支持可靠写入 |
过程描述:
- 客户端发送 ATT 预写请求(Prepare Write Request)
- 服务器回应 ATT 预写响应(Prepare Write Response),响应中包含与请求相同的句柄、偏移量和数据
- 客户端验证响应中的数据与发送的数据一致(可靠性校验)
- 确认无误后,客户端发送 ATT 执行写入请求(标志 0x01)提交,或(标志 0x00)取消
4.8 通知(Notifications)
4.8.1 特征值通知(Notifications of Characteristic Values)
| 角色 | 要求 |
|---|---|
| 客户端 | 强制(M),若服务器支持通知 |
| 服务器 | 可选(O) |
过程描述:
- 客户端订阅通知:将 CCCD(0x2902) 中的通知位设置为 1
- 服务器在特征值变更时发送 ATT 句柄值通知(Handle Value Notification),携带特征值句柄和新值
- 客户端无需响应
4.9 指示(Indications)
4.9.1 特征值指示(Indications of Characteristic Values)
| 角色 | 要求 |
|---|---|
| 客户端 | 强制(M),若服务器支持指示 |
| 服务器 | 可选(O) |
过程描述:
- 客户端订阅指示:将 CCCD(0x2902) 中的指示位设置为 1
- 服务器在特征值变更时发送 ATT 句柄值指示(Handle Value Indication),携带特征值句柄和新值
- 客户端发送 ATT 句柄值确认(Handle Value Confirmation) 作为响应
- 服务器在收到确认前不得发送新的指示
4.10 特征描述符读写(Reading and Writing Characteristic Descriptors)
4.10.1 读取特征描述符(Read Characteristic Descriptors)
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 强制(M) |
过程描述:
- 客户端发送 ATT 读取请求(Read Request),携带描述符句柄
- 服务器返回描述符值
4.10.2 读取长特征描述符(Read Long Characteristic Descriptors)
(参见 4.6.3 读取长特征值,过程相同,将特征值替换为描述符)
4.10.3 写入特征描述符(Write Characteristic Descriptors)
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 强制(M) |
过程描述:
- 客户端发送 ATT 写入请求(Write Request),携带描述符句柄和数据
- 服务器写入后发送 ATT 写入响应(Write Response)
4.10.4 写入长特征描述符(Write Long Characteristic Descriptors)
(参见 4.7.4 写入长特征值,过程相同,将特征值替换为描述符)
4.11 服务器特征配置(Server Characteristics Configuration)
此功能允许客户端通过服务器特征配置描述符(SCCD)配置服务器行为,如启用特征值广播。
| 角色 | 要求 |
|---|---|
| 客户端 | 可选(O) |
| 服务器 | 可选(O) |
过程:客户端读写 SCCD(UUID 0x2903),设置广播位(Bit 0)以启用/禁用广播。
5 L2CAP 互操作性要求
本章描述 GATT 对 L2CAP 层的要求。
5.1 BR/EDR 上的 ATT
在 BR/EDR(经典蓝牙)连接上,ATT 协议使用 L2CAP 通道,PSM(协议/服务复用器)值为 0x001F。
- L2CAP 通道以 面向连接模式(Connection-oriented channel) 运行
- 默认 MTU:48 字节(BR/EDR ATT 连接的初始 MTU)
- 实现可以通过"交换 MTU 大小"过程协商更大的 MTU
5.2 LE 上的 ATT
在 LE(低功耗蓝牙)连接上,ATT 协议使用固定的 L2CAP 通道 ID 0x0004。
- L2CAP 通道以 不可靠模式(Unacknowledged mode) 运行(使用固定通道)
- 默认 MTU:23 字节(LE ATT 的默认 MTU)
- 实现可以通过"交换 MTU 大小"过程协商最大 517 字节 的 MTU
6 GAP 互操作性要求
本章描述 GATT 与通用访问配置文件(GAP)的关系及互操作性要求。
6.1 连接模式和过程
| GAP 角色 | GATT 角色 | 要求 |
|---|---|---|
| 外设(Peripheral) | 服务器(Server) | 通常担任此角色 |
| 中央(Central) | 客户端(Client) | 通常担任此角色 |
| 广播者(Broadcaster) | N/A | 仅发送广播数据,不使用 GATT |
| 观察者(Observer) | N/A | 仅接收广播数据,不使用 GATT |
注:设备可以同时担任 GATT 服务器和客户端。
6.2 安全模式
GATT 操作的安全级别:
| 安全级别 | 描述 |
|---|---|
| 1 级,模式 1 | 无安全要求(无需认证或加密) |
| 1 级,模式 2 | 未经认证的加密 |
| 2 级,模式 1 | 经认证的加密 |
| 2 级,模式 2 | 需要授权 |
7 GATT 服务定义
GATT 服务(Generic Attribute Service)本身也通过 GATT 协议暴露。
7.1 服务定义
- 服务 UUID:
0x1801(Generic Attribute) - 服务类型:主服务(Primary Service)
7.2 服务变更特征(Service Changed Characteristic)
| 字段 | 值 |
|---|---|
| 特征 UUID | 0x2A05 |
| 特征属性 | 指示(Indicate) |
| 特征值 | 两个 16 位无符号整数:受影响属性句柄范围的起始值和结束值 |
描述符:
| 描述符 | UUID | 要求 |
|---|---|---|
| 客户端特征配置描述符(CCCD) | 0x2902 | 强制(M) |
用途:
当服务器上的服务、包含关系或特征定义发生变更时,服务器应向已订阅指示的客户端发送"服务变更"特征的指示,通知客户端重新发现受影响范围内的属性。
- 如果客户端与服务器之间存在绑定(Bonded)关系,且在连接断开期间服务发生了变更,则服务器必须在下次连接时发送该指示
- 若设备不支持添加或删除服务,可以不包含此特征(可选)
8 安全考虑
8.1 概述
GATT 使用 ATT 协议传输数据,ATT 的安全性依赖于底层连接的安全模式。
8.2 属性权限与安全
属性的安全性由其权限决定:
- 服务和特征的声明属性(Service Declaration、Characteristic Declaration)可被任意客户端读取,无需认证或加密
- 特征值和描述符的访问安全性由具体配置文件定义
- 若客户端尝试访问需要更高安全级别的属性,服务器应返回相应的 ATT 错误码(如"读取不允许"、"写入不允许"、"权限不足"等)
8.3 隐私与随机地址
当设备使用可解析随机私有地址(Resolvable Private Address)时:
- GATT 客户端应在建立连接后检查 CCCD 等配置,确认是否为之前认识的设备
- 若是已绑定设备,应恢复之前存储的配置
8.4 服务器安全建议
- 对敏感数据的特征值,应要求加密和/或认证
- 对可改变设备行为的特征(如写操作),应要求认证
- 推荐使用 LE 安全连接(LE Secure Connections)以获得更高安全级别
9 SDP 互操作性要求
本章描述 GATT 与 SDP(服务发现协议)的互操作性要求,适用于支持 BR/EDR 的设备。
9.1 服务记录
支持 BR/EDR 连接的 GATT 服务器应在 SDP 数据库中包含一条 GATT 服务的记录,以便 BR/EDR 客户端发现 GATT 服务。
| SDP 属性 | 值 |
|---|---|
| ServiceClassIDList | 0x1801(Generic Attribute Profile) |
| ProtocolDescriptorList | L2CAP(PSM = 0x001F)、ATT(起始句柄、结束句柄) |
| BrowseGroupList | PublicBrowseRoot(0x1002) |
| ProfileDescriptorList | Generic Attribute Profile(版本 0x0100) |
9.2 句柄范围
SDP 记录中的 ATT 句柄范围(起始句柄和结束句柄)指定了通过 BR/EDR 连接可访问的 GATT 属性范围。
10 参考文献
-
蓝牙核心规范 5.0(BLUETOOTH SPECIFICATION Version 5.0)
- Vol 3, Part E: Attribute Protocol (ATT)
- Vol 3, Part C: Generic Access Profile (GAP)
- Vol 3, Part A: Logical Link Control and Adaptation Protocol (L2CAP)
- Vol 3, Part B: Service Discovery Protocol (SDP)
-
蓝牙分配号码(Bluetooth Assigned Numbers)
- GATT 特征 UUID 列表
- 展示格式(Format)值定义
- 单位 UUID 列表
-
IEEE 802.11:无线局域网媒体访问控制(MAC)和物理层(PHY)规范
-
IEEE 754:IEEE 浮点运算标准
附录 A:示例属性服务器属性
本附录提供了一个示例,展示一个属性服务器可能包含的属性组织结构。
A.1 示例场景描述
本示例模拟一个环境传感设备(如户外气象站/背包传感器),该设备安装于瑞典北博滕省(Norrbottens Län)阿比斯科旅游站(Abisko Turiststation)一侧,具有以下特性:
- 设备名称:"Example Device"(示例设备)
- 支持全部 ATT 操作码
- 支持最多两个预写值(Prepare Write 队列容量为 2)
A.2 服务列表与数据
该设备包含以下服务:
主服务 1:Generic Access Service(通用访问服务)
| 句柄 | 属性类型 | 属性值 |
|---|---|---|
| 0x0001 | «Primary Service» | «Generic Access» |
| 0x0002 | «Characteristic» | |
| 0x0003 | «Device Name» | "Example Device" |
| 0x0004 | «Characteristic» | |
| 0x0005 | «Appearance» | 0x0000 |
主服务 2:Generic Attribute Service(通用属性服务)
| 句柄 | 属性类型 | 属性值 |
|---|---|---|
| 0x0010 | «Primary Service» | «Generic Attribute» |
| 0x0011 | «Characteristic» | |
| 0x0012 | «Service Changed» | — |
| 0x0013 | «Client Characteristic Configuration» | 0x0000 |
主服务 3:Device Information Service(设备信息服务)
| 句柄 | 属性类型 | 属性值 |
|---|---|---|
| 0x0020 | «Primary Service» | «Device Information» |
| 0x0021 | «Characteristic» | |
| 0x0022 | «System ID» | 0x123456FFFE9ABCDE |
| 0x0023 | «Characteristic» | |
| 0x0024 | «PnP ID» |
主服务 4:Battery Service(电池服务)
| 句柄 | 属性类型 | 属性值 |
|---|---|---|
| 0x0030 | «Primary Service» | «Battery Service» |
| 0x0031 | «Characteristic» | |
| 0x0032 | «Battery Level State» | 0x0604(电量良好,正在放电) |
| 0x0033 | «Client Characteristic Configuration» | 0x0000 |
电量状态值
0x04表示电池正在放电(Discharging)。
次要服务 1:Manufacturer Service(制造商服务)—— 用于温度传感器
| 句柄 | 属性类型 | 属性值 |
|---|---|---|
| 0x0500 | «Secondary Service» | «Manufacturer Service» |
| 0x0501 | «Characteristic» | |
| 0x0502 | «Manufacturer Name» | "ACME Temperature Sensor" |
| 0x0503 | «Characteristic» | |
| 0x0504 | «Serial Number» | "237495-3282-A" |
次要服务 2:Manufacturer Service(制造商服务)—— 用于称重传感器
| 句柄 | 属性类型 | 属性值 |
|---|---|---|
| 0x0505 | «Secondary Service» | «Manufacturer Service» |
| 0x0506 | «Characteristic» | |
| 0x0507 | «Manufacturer Name» | "ACME Weighing Scales" |
| 0x0508 | «Characteristic» | |
| 0x0509 | «Serial Number» | "11267-2327A00239" |
次要服务 3:Vendor Specific Service(厂商自定义服务)
| 句柄 | 属性类型 | 属性值 |
|---|---|---|
| 0x0550 | «Secondary Service» | «Vendor Specific Service» |
| 0x0560 | «Characteristic» | |
| 0x0568 | «Vendor Specific Type» | 0x56656E646F72 |
主服务 5:Environment Service(环境服务)
| 句柄 | 属性类型 | 属性值 |
|---|---|---|
| 0x00A0 | «Primary Service» | «Environment Service» |
| 0x00A1 | «Included Service» | |
| 0x00A2 | «Characteristic» | |
| 0x00A3 | «Temperature Measurement» | 0x0041(表示 6.5 °C) |
| 0x00A4 | «Client Characteristic Configuration» | 0x0000 |
| 0x00A5 | «Characteristic Presentation Format» | {0x0E, -1, 0x272F, 0x01, 0x0000}(sint16,× 0.1,摄氏度) |
| 0x00A6 | «Characteristic User Description» | "Outside Temperature" |
| 0x00A7 | «Characteristic» | |
| 0x00A8 | «Humidity» | 0x27(39%) |
| 0x00A9 | «Client Characteristic Configuration» | 0x0000 |
| 0x00AA | «Characteristic Presentation Format» | {0x04, 0, 0x27AD, 0x01, 0x0000}(uint8,百分比) |
| 0x00AB | «Characteristic User Description» | "Outside Relative Humidity" |
主服务 6:Weight Service(称重服务)
| 句柄 | 属性类型 | 属性值 |
|---|---|---|
| 0x0200 | «Primary Service» | «Weight Service» |
| 0x0201 | «Included Service» | |
| 0x0202 | «Included Service» | |
| 0x0203 | «Characteristic» | |
| 0x0204 | «Weight» | 0x088D(2189,实际值 21.89 kg) |
| 0x0205 | «Client Characteristic Configuration» | 0x0000 |
| 0x0206 | «Characteristic Presentation Format» | {0x06, -2, 0x27A8, 0x01, 0x0000}(uint16,× 0.01,千克) |
| 0x0207 | «Characteristic User Description» | "Hanging Weight" |
| 0x0280 | «Characteristic» | |
| 0x0281 | «Rucksack Weight» | 0x088D(2189,实际值 21.89 kg) |
| 0x0282 | «Characteristic Presentation Format» | {0x06, -2, 0x27A8, 0x01, 0x0000}(uint16,× 0.01,千克) |
| 0x0283 | «Characteristic» | {0x02, 0x0284, «Rucksack Weight»}(称重传感器读数) |
| 0x0284 | «Rucksack Weight» | 0x088D |
| 0x0285 | «Characteristic User Description» | "Rucksack Weight" |
主服务 7:Position Service(位置服务)
| 句柄 | 属性类型 | 属性值 |
|---|---|---|
| 0x0300 | «Primary Service» | «Position Service» |
| 0x0301 | «Characteristic» | |
| 0x0302 | «Latitude Longitude» | 0x28BEAFA40B320FCE(纬度 68.3585444°N,经度 18.7830222°E) |
| 0x0304 | «Characteristic» | |
| 0x0305 | «Latitude Longitude Elevation» | 0x28BEAFA40B320FCE0176(纬度、经度,海拔 374 米) |
主服务 8:Alert Service(告警服务)
| 句柄 | 属性类型 | 属性值 |
|---|---|---|
| 0x0400 | «Primary Service» | «Alert Service» |
| 0x0401 | «Characteristic» | |
| 0x0402 | «Alert Enumeration» | 0x00(无告警) |
A.3 服务器信息摘要
上述服务器包含如下信息:
- 设备名称特征值为 "Example Device"
- 支持全部属性操作码,且预写缓冲区支持最多 2 个条目
- 电池状态值为
0x04,表示正在放电 - 室外温度值为 6.5 °C
- 室外相对湿度值为 39%
- 挂载重量值为 21.89 kg
- 设备位置:北纬 68.3585444°,东经 18.7830222°,海拔 374 米
- 温度传感器制造商:ACME Temperature Sensor,序列号:237495-3282-A
- 称重传感器制造商:ACME Weighing Scales,序列号:11267-2327A00239
该设备位于瑞典北博滕省阿比斯科旅游站侧面,电池状态良好,当天气温较高、湿度较低,背包较重。
——翻译自 BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G: Generic Attribute Profile (GATT),2016 年 12 月 6 日版本
浙公网安备 33010602011771号