蓝牙(二)GATT规范
GATT(通用属性规范)是蓝牙低功耗(BLE,Bluetooth Low Energy)协议的核心部分,伴随蓝牙4.0(2010年发布)首次推出。其设计初衷是解决传统蓝牙协议(BR/EDR)在物联网设备中的高功耗和复杂性问题,提供轻量级、标准化的数据交互框架。
GATT是规范(Profile),而非底层协议,其核心是定义如何基于ATT协议构建标准化服务。术语定义:
协议(Protocol):规定数据通信的规则与格式,例如ATT协议定义了属性读写、通知等操作的数据包格式。
规范(Profile/Service):基于协议构建的应用层标准,规定设备如何利用协议实现特定功能(如心率监测).
优点
-
灵活的数据结构与扩展性
GATT 通过 服务(Service)、特征(Characteristic)和描述符(Descriptor) 的层级结构组织数据,使得设备能够灵活定义多种功能模块。例如,心率监测设备可以通过一个服务包含“心率值”和“传感器位置”两个特征,实现数据的模块化管理。这种设计便于开发者根据需求定制功能,且支持动态扩展。
-
高效的低功耗通信
GATT 基于 ATT 协议,采用 请求-响应模型 和 通知/指示机制,减少不必要的广播能耗。例如,智能手表仅在心率变化时通过通知(Notify)发送数据,而非持续广播,显著降低功耗。
-
标准化与跨平台兼容性
GATT 定义了标准化的 UUID(通用唯一标识符) 和预配置服务(如心率服务 0x180D),确保不同厂商设备间的互操作性。例如,苹果、安卓设备均可通过统一的心率服务读取数据。
-
安全与权限控制
GATT 支持 加密连接 和 权限管理(如读写权限、加密要求)。例如,医疗设备可通过 ENCRYPT_READ 权限限制敏感数据的访问,防止未授权操作。
-
支持多场景应用
从智能家居到工业物联网,GATT 的结构化数据模型可适配多种场景。例如,工业传感器通过 聚合格式描述符 将温度、湿度数据打包传输,简化数据处理流程
缺点
-
规范复杂性与实现差异
GATT 的层级结构虽灵活,但配置复杂度高。不同协议栈(如 Nordic、ESP32)对描述符的支持可能存在差异,导致跨平台调试困难。
-
权限管理漏洞
若权限配置不当(如未限制 WRITE 权限),可能导致恶意写入攻击。例如,某智能锁因未加密 WRITE 权限,被黑客篡改开锁指令。 -
连接独占性限制
GATT 连接为 一对一模式,设备连接后停止广播,无法同时服务多个客户端。例如,健身手环连接手机后,其他设备无法同步获取数据。
-
数据长度限制
ATT 协议单次数据传输上限为 23 字节(BLE 4.0/4.1),长数据需分片传输,增加处理复杂度。例如,传输 100 字节的固件需拆分为 5 个数据包。
-
安全机制的依赖性
GATT 的安全性依赖于底层蓝牙协议栈的实现。若设备未启用加密或认证,即使配置权限也可能被中间人攻击
规范定义
通信角色模型
GATT基于ATT(Attribute Protocol)构建,采用客户端-服务器模型
- 服务器(Server):存储数据(属性表),如传感器数据、设备状态
- 客户端(Client):发起读写请求,如手机、网关。
交互规则:所有操作由客户端发起,服务端仅被动响应。
分层数据结构
ATT通过服务(Service)、特征(Characteristic)、描述符(Descriptor)三层结构组织数据,形成树状属性表
-
服务(Service):
- 定义:功能模块的集合(如心率监测、电池状态)。
- UUID标识:使用16位或128位UUID(如心率服务UUID=0x180D)。
- 结构要求:每个服务必须包含至少一个特征。
-
特征(Characteristic):
- 定义:服务中的具体数据点(如心率测量值)。
- 组成:包含声明(声明权限与UUID)、值(数据)、描述符(附加配置)。
- 权限:通过属性标志(如READ、NOTIFY)定义操作权限。
-
描述符(Descriptor)
- 定义:特征的附加信息(如启用通知、文本描述)。
- 典型用例:客户端特征配置描述符(CCCD,UUID=0x2902)用于启用/禁用通知
标准化服务与自定义扩展
-
官方预定义服务:
蓝牙技术联盟(SIG)定义了标准服务UUID,如心率服务(0x180D)、设备信息服务(0x180A),确保跨厂商兼容。
-
自定义服务:
开发者可创建128位UUID的服务与特征,满足私有协议需求
GATT数据结构
GATT的数据结构基于分层属性表设计,所有数据以属性(Attribute)为最小单元,按服务(Service)、特征(Characteristic)、描述符(Descriptor)的层次组织。
属性表
所有数据存储在服务端的属性表中,每个属性由以下字段组成
字段 | 长度 | 说明 |
---|---|---|
句柄(Handle) | 2字节 | 唯一标识符(0x0001~0xFFFF),按顺序递增,用于定位属性。 |
类型(UUID) | 2/16字节 | 标准UUID(16位短格式)或自定义UUID(128位)。 |
权限(Permissions) | 1字节 | 读/写/通知等权限标志(如READ、WRITE_WITHOUT_RESPONSE、NOTIFY)。 |
值(Value) | 可变长度 | 实际数据(如温度值、设备名称) |
Service
服务是功能的逻辑集合,代表设备的一种能力(如心率监测、电池状态
-
UUID(唯一标识符)
Service通过16位或128位UUID唯一标识其功能类型
-
标准UUID:一般为16为,0000xxxx-0000-1000-8000-00805F9B34FB
其中xxxx就是表中16为值,其他部分为蓝牙技术联盟(SIG)固定定义定义
-
. 自定义UUID:开发者可生成128位UUID
-
-
句柄(Handle)
每个Service在设备属性表中通过16位句柄唯一标识,用于定位服务在GATT表中的起始位置。例如,句柄0x0001可能对应心率服务的声明
注意: Android端无法获取句柄(Handle)
-
包含的特征(Characteristics)
Service必须包含至少一个Characteristic(特征),以实际存储和操作数据。例如,心率服务包含心率测量值、传感器位置等特征
Characteristic
每个 Characteristic 的声明属性定义了其基本信息和操作权限
-
UUID(唯一标识符)
-
标准UUID:一般为16为,0000xxxx-0000-1000-8000-00805f9b34fb
其中xxxx就是表中16为值,其他部分为蓝牙技术联盟(SIG)固定定义定义
-
. 自定义UUID:开发者可生成128位UUID
-
-
Properties(属性权限)
十六进制值 二进制位 权限名称 描述 0x01 00000001 BROADCAST 允许通过广播发送特征值(无需连接)。 0x02 00000010 READ 允许客户端读取特征值。 0x04 00000100 WRITE_WITHOUT_RESPONSE 允许客户端写入数据且无需服务器响应(低延迟写入)。 0x08 00001000 WRITE 允许客户端写入数据并要求服务器响应(可靠写入)。 0x10 00010000 NOTIFY 允许服务器主动向客户端发送通知(无需客户端确认)。 0x20 00100000 INDICATE 允许服务器主动向客户端发送指示(需客户端确认,可靠性更高)。 0x40 01000000 SIGNED_WRITE 允许客户端使用签名写入数据(需加密认证)。 0x80 10000000 EXTENDED_PROPERTIES 表示存在扩展属性(需通过描述符0x2900定义额外权限) -
Permission
目前有主要有以下四种:
- 访问权限(Access Permission):只读、只写、读写;服务器使用访问权限来确定客户端是否可以读取和/或写入属性值;
- 加密权限(Encryption Permission):加密、不加密;
- 认证权限(Authentication Permission) :需要认证、无需认证;服务器使用身份验证权限来确定当客户端试图访问某个属性时是否需要经过身份验证的物理链接。在向客户端发送- 通知或指示之前,服务器还使用身份验证权限来确定是否需要经过身份验证的物理链接;
- 授权权限(Authorization Permission):需要授权、无需授权;授权权限决定在访问属性值之前是否需要对客户端进行授权。
权限类别 位掩码(十六进制) 含义 访问权限 0x01、0x02 控制客户端对特征值的读写能力:0x01:可读(READ)0x02:可写(WRITE)0x03:可读可写(`READ 加密权限 0x40、0x80 要求数据传输需加密: 0x40:读需加密(ENCRYPT_READ) 0x80:写需加密(ENCRYPT_WRITE) 认证权限 0x04、0x08 要求客户端与服务器完成配对认证: 0x04:读需认证(AUTHEN_READ) 0x08:写需认证(AUTHEN_WRITE) 授权权限 0x10、0x20 要求客户端被标记为可信任设备(Trusted): 0x10:读需授权(AUTHOR_READ) 0x20:写需授权(AUTHOR_WRITE) -
value
实际传输的数据,例如心率值、温度读数等
-
Descriptor
描述符提供额外的元数据,用于扩展 Characteristic 的功能:
descriptor
Descriptors 作为 Characteristic 的附加属性,主要用于:
- 功能扩展:为 Characteristic 添加额外的配置或说明信息,例如启用通知、定义数据格式等。
- 权限管理:约束客户端对特征值的访问方式(如是否可读/写)。
- 数据解释:提供人类可读的文本描述或数据格式定义,便于理解和使用
-
UUID(唯一标识符)
-
标准UUID:一般为16为,0000xxxx-0000-1000-8000-00805f9b34fb
其中xxxx就是表中16为值,其他部分为蓝牙技术联盟(SIG)固定定义定义
-
. 自定义UUID:开发者可生成128位UUID
-
-
句柄(Handle)
- 作用:唯一标识描述符在 GATT表 中的存储位置,用于协议层的快速寻址。
- 分配规则:由协议栈自动生成,通常与所属特征的句柄连续
-
. 权限(Permissions)
访问权限:定义客户端对描述符的操作权限:
- 可读(Read):允许客户端读取描述符值。
- 可写(Write):允许客户端修改描述符值(如CCCD启用通知)。
- 加密(Encrypted):需加密连接才能访问。
- 认证(Authenticated):需配对认证后才能操作
-
value
数据类型:根据描述符类型动态定义- CCCD:16位无符号整数,表示通知/指示的启用状态。
- 用户描述符:UTF-8字符串,长度可变(如“Temperature Sensor”)。
- 特征呈现格式描述符:结构化数据,包含以下字段:
- 格式类型(1字节):如无符号整数(0x01)、浮点数(0x04)。
- 指数(1字节):数值的缩放因子(如 0xFA 表示 ×10⁻²)。
- 单位(2字节):遵循蓝牙单位规范(如摄氏度 0x27AD)。
- 命名空间(1字节):厂商自定义或标准命名空间。
- 描述符扩展(可选):附加元数据。
使用 GATT 规范的建议与注意事项
-
设计阶段优化数据结构
- 建议:按功能划分服务,避免单一服务包含过多特征。例如,智能灯泡可拆分为“开关控制”和“亮度调节”两个服务。
- 注意:优先使用 SIG 标准 UUID,自定义 UUID 需确保全局唯一性。
-
严格配置安全策略
- 建议:敏感特征(如门锁控制)需启用 ENCRYPT_WRITE 和 AUTHEN_WRITE 权限,并配合 LE Secure Connections 加密。
- 注意:定期更新加密密钥,防止长期连接被破解。
-
优化通信性能
- 建议:高频数据(如传感器实时数据)使用 NOTIFY 而非 INDICATE,避免确认开销。
- 注意:合理设置连接间隔(Connection Interval),平衡功耗与实时性。
-
兼容性测试与错误处理
- 建议:在不同协议栈(如 Android、iOS)中测试服务发现与数据读写。
- 注意:处理 ATT 错误码(如 Insufficient Encryption)并提供用户友好提示。
-
动态权限与资源管理
- 建议:根据设备状态动态调整权限。例如,未配对时禁用写操作,配对后开放。
- 注意:嵌入式设备需优化内存占用,避免因过多描述符导致资源耗尽
评论区