蓝牙学习系列(七):BLE GATT 数据模型详解
目录
在前几篇中,我们为蓝牙通信铺好了所有“基础设施”:设备如何被发现(广播/扫描),如何建立私密连接,以及如何确保连接安全(配对/绑定)。现在,是时候让应用程序在这条安全、可靠的“专属车道”上运送“货物”了。
GATT 就是定义这些“货物”该如何打包、贴标、寄送和签收的通用规则。它让手机上的“健康”应用能读懂手环的心率,让音乐APP能控制耳机的音量。可以说,不理解GATT,就无法进行任何有意义的BLE应用开发。
今天,我们将深入这套规则,通过具体的例子,看看BLE设备如何通过一个精妙的“分层数据库”模型,向世界宣告自己的能力,并与人交互。
一、 GATT 是什么?为什么需要它?
从“暗语”到“普通话”。GATT 的全称是 Generic Attribute Profile,即通用属性配置文件。它是构建在 ATT 协议 之上的一套数据组织与访问框架。
为了理解其必要性,我们可以设想一个没有GATT的混乱世界:
- 你的手机连接上一个新的智能手环,它发出一串神秘的十六进制代码
0xAB0123CD。 - 手环回复
0x0064。 - 手机如何知道
0xAB0123CD是“请求心率”的指令,而0x0064代表心率是100次/分钟?手环又如何知道手机发来的0x08是“请求电池电量”?
这就像两个人没有共同语言,只能靠事先私下约定好的、独一无二的“暗语”交流。每对接一个新设备,APP就需要学习一套新的“暗语”,生态无法建立,用户体验极差。
GATT 的出现,就是为了让所有BLE设备说同一种“普通话”。 它定义了一套标准化的方法:
- 如何组织数据:将设备的功能抽象为标准的、可发现的“服务”和“特征值”。就像图书馆使用“杜威十进制分类法”给所有书籍编号,任何人都能按图索骥。
- 如何访问数据:定义了对这些数据进行“读”、“写”、“通知”、“指示”等操作的通用命令。就像去图书馆只有“借书”、“还书”、“预约”几种标准操作。
- 如何描述数据:定义了数据的类型、单位、权限等元信息。
二、 GATT 的核心:三层数据结构
GATT 将BLE设备的功能组织成一个清晰的三层数据库。理解这个结构,就掌握了与任何BLE设备对话的“地图”。
下图2-1 展示了GATT数据库的标准层级,从最顶层的服务开始,逐级向下分解到具体的特征值及其控制开关:
2.1. 服务 —— 功能模块
服务是GATT数据库的顶层容器,代表一个独立的功能模块。
- 标识:每个服务有唯一的UUID
- 16位UUID:蓝牙联盟定义的标准服务
0x180D- 心率服务0x180F- 电池服务0x180A- 设备信息服务
- 128位UUID:厂商自定义的私有服务
- 16位UUID:蓝牙联盟定义的标准服务
- 实例:智能手环通常包含
- 心率服务(监测心率)
- 电池服务(报告电量)
- 设备信息服务(提供厂商、型号等)
2.2. 特征值 —— 数据端点
特征值是服务内部的具体数据点,是与设备交互的基本单元。
- 结构:每个特征值包含两部分
- 特征值声明:描述元信息(权限、UUID)
- 特征值数值:存储实际数据
- 属性:定义客户端能做什么
- 可读:可读取当前值
- 可写:可写入新值
- 可通知:可订阅实时更新
- 可指示:可订阅需确认的更新
2.3. 描述符 —— 控制开关
描述符是特征值的配置项。最重要的描述符是CCCD。
- CCCD:客户端特征配置描述符
- 是通知/指示功能的开关
- 客户端写入
0x0001→ 启用通知 - 客户端写入
0x0000→ 禁用通知
- 工作原理:服务器在数据变化时检查CCCD值,如果为
0x0001则自动推送更新
2.4. 核心要点总结
- 服务是容器,特征值是内容
- 特征值声明描述元信息,特征值数值存储实际数据
- CCCD是通知开关,控制是否自动推送数据
- UUID是唯一标识,16位=标准,128位=私有
这个三层结构是所有BLE设备交互的基础框架。无论设备多复杂,功能都通过这种标准化的方式组织,客户端(如手机)只需按此框架发现、读取、订阅即可使用设备功能。
三、 实战推演:手机如何获取手环的实时心率?
现在,我们带入一个真实场景:手机APP要获取智能手环的实时心率。
3.1. 流程步骤详解
第1-2步:发现
客户端必须首先了解服务器有什么。这通过两次“发现”完成:
-
服务发现:获取设备所有服务的列表及其在数据库中的地址范围(句柄范围)。
-
特征值发现:在感兴趣的服务内,获取所有特征值的详细信息,特别是特征值数值的属性和具体句柄。
第3步:读取(可选)
客户端可以直接读取特征值的当前值。这是一种“拉”模式,适用于获取不需要实时更新的静态信息(如设备序列号)。
第4步:订阅(关键)
为了实时获取数据(如心率),客户端需要启用“推”模式。这是通过找到目标特征值对应的CCCD描述符(其句柄通常紧随特征值句柄之后),并向其写入 0x0001(启用通知)来实现的。此操作是后续服务器主动发送数据的开关。
第5-6步:推送
启用通知后,每当特征值的数据更新,服务器(手环)的协议栈会自动检查对应的CCCD是否已被启用。如果是,它会立即构造一个 Handle Value Notification 数据包,其中包含特征值的句柄和新的数据,并发送给客户端。客户端无需任何请求即可收到更新。
3.2. 流程核心总结
- 客户端驱动:流程由客户端(手机)的发现和配置请求启动。
- 句柄是地址:服务、特征值、描述符在数据库中的唯一索引称为“句柄”,所有读写操作都针对句柄进行。
- CCCD是开关:通知功能必须由客户端通过写入CCCD显式开启。这是实现低功耗实时通信的基础,服务器仅在数据变化且有订阅者时才发送数据。
- 通知是异步的:一旦开关打开,数据推送由服务器在数据更新时自动、主动发起,效率极高。
这个流程是GATT通信的通用模板,适用于从读取电池电量到接收传感器数据、发送控制命令等各种场景。理解此流程,就掌握了使用或开发BLE应用功能的核心交互逻辑。
这个流程揭示了GATT的精髓:客户端主导发现,并通过配置CCCD来建立一种高效的、服务器驱动的数据推送通道。“通知”机制是BLE传感器设备实现超低功耗的关键,设备大部分时间可以睡眠,仅在数据变化时醒来发送一个很小的数据包。
四、 总结
GATT 通过标准化的分层模型,在灵活性和互操作性之间取得了完美平衡:
- 对开发者:它提供了设计产品的清晰蓝图。你需要思考你的设备提供哪些“服务”,每个服务下有哪些“特征值”(数据或命令),它们各自该有什么权限。
- 对用户和应用:它提供了发现和使用设备功能的通用方法。一个通用的蓝牙调试APP(如 nRF Connect 或 LightBlue)可以连接任何BLE设备,浏览其GATT表,读写数据,正是因为大家都遵循同一套GATT“语言”。
由于个人水平有限,文中若有任何疏漏或表述不清之处,欢迎在评论区指正与交流。
后续更新预告:我将持续更新ble系列的技术科普,下一篇计划《BLE L2CAP 协议详解》。如果本文对你有帮助,欢迎点赞、收藏、关注,这是对我最大的鼓励!
📚 蓝牙学习系列专栏
本系列是系统性的蓝牙低功耗(BLE)技术教程,从协议栈原理到实战开发,适合嵌入式开发者、物联网工程师和所有对蓝牙技术感兴趣的读者。
🎯 **系列导航**:本文是《蓝牙学习系列》第7篇
🔗 **完整专栏**: 蓝牙学习系列专栏
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)