目录

一、 GATT 是什么?为什么需要它?

二、 GATT 的核心:三层数据结构

2.1. 服务 —— 功能模块

2.2. 特征值 —— 数据端点

2.3. 描述符 —— 控制开关

2.4. 核心要点总结

三、 实战推演:手机如何获取手环的实时心率?

3.1. 流程步骤详解

3.2. 流程核心总结

四、 总结

📚 蓝牙学习系列专栏


在前几篇中,我们为蓝牙通信铺好了所有“基础设施”:设备如何被发现(广播/扫描),如何建立私密连接,以及如何确保连接安全(配对/绑定)。现在,是时候让应用程序在这条安全、可靠的“专属车道”上运送“货物”了。

GATT​ 就是定义这些“货物”该如何打包、贴标、寄送和签收的通用规则。它让手机上的“健康”应用能读懂手环的心率,让音乐APP能控制耳机的音量。可以说,不理解GATT,就无法进行任何有意义的BLE应用开发。

今天,我们将深入这套规则,通过具体的例子,看看BLE设备如何通过一个精妙的“分层数据库”模型,向世界宣告自己的能力,并与人交互。


一、 GATT 是什么?为什么需要它?

从“暗语”到“普通话”GATT​ 的全称是 Generic Attribute Profile,即通用属性配置文件。它是构建在 ATT 协议​ 之上的一套数据组织与访问框架

为了理解其必要性,我们可以设想一个没有GATT的混乱世界:

  • 你的手机连接上一个新的智能手环,它发出一串神秘的十六进制代码 0xAB0123CD
  • 手环回复 0x0064
  • 手机如何知道 0xAB0123CD是“请求心率”的指令,而 0x0064代表心率是100次/分钟?手环又如何知道手机发来的 0x08是“请求电池电量”?

这就像两个人没有共同语言,只能靠事先私下约定好的、独一无二的“暗语”交流。每对接一个新设备,APP就需要学习一套新的“暗语”,生态无法建立,用户体验极差。

GATT 的出现,就是为了让所有BLE设备说同一种“普通话”。​ 它定义了一套标准化的方法:

  1. 如何组织数据:将设备的功能抽象为标准的、可发现的“服务”和“特征值”。就像图书馆使用“杜威十进制分类法”给所有书籍编号,任何人都能按图索骥。
  2. 如何访问数据:定义了对这些数据进行“读”、“写”、“通知”、“指示”等操作的通用命令。就像去图书馆只有“借书”、“还书”、“预约”几种标准操作。
  3. 如何描述数据:定义了数据的类型、单位、权限等元信息。

二、 GATT 的核心:三层数据结构

GATT 将BLE设备的功能组织成一个清晰的三层数据库。理解这个结构,就掌握了与任何BLE设备对话的“地图”。

下图2-1 展示了GATT数据库的标准层级,从最顶层的服务开始,逐级向下分解到具体的特征值及其控制开关:

图2-1 GATT数据结构

2.1. 服务 —— 功能模块

服务是GATT数据库的顶层容器,代表一个独立的功能模块。

  • 标识:每个服务有唯一的UUID
    • 16位UUID:蓝牙联盟定义的标准服务
      • 0x180D- 心率服务
      • 0x180F- 电池服务
      • 0x180A- 设备信息服务
    • 128位UUID:厂商自定义的私有服务
  • 实例:智能手环通常包含
    • 心率服务(监测心率)
    • 电池服务(报告电量)
    • 设备信息服务(提供厂商、型号等)

2.2. 特征值 —— 数据端点

特征值是服务内部的具体数据点,是与设备交互的基本单元

  • 结构:每个特征值包含两部分
    • 特征值声明:描述元信息(权限、UUID)
    • 特征值数值:存储实际数据
  • 属性:定义客户端能做什么
    • 可读:可读取当前值
    • 可写:可写入新值
    • 可通知:可订阅实时更新
    • 可指示:可订阅需确认的更新

2.3. 描述符 —— 控制开关

描述符是特征值的配置项。最重要的描述符是CCCD

  • CCCD:客户端特征配置描述符
    • 通知/指示功能的开关
    • 客户端写入0x0001→ 启用通知
    • 客户端写入0x0000→ 禁用通知
  • 工作原理服务器在数据变化时检查CCCD值,如果为0x0001则自动推送更新

2.4. 核心要点总结

  1. 服务是容器,特征值是内容
  2. 特征值声明描述元信息,特征值数值存储实际数据
  3. CCCD是通知开关,控制是否自动推送数据
  4. UUID是唯一标识,16位=标准,128位=私有

这个三层结构是所有BLE设备交互的基础框架。无论设备多复杂,功能都通过这种标准化的方式组织,客户端(如手机)只需按此框架发现、读取、订阅即可使用设备功能。


三、 实战推演:手机如何获取手环的实时心率?

现在,我们带入一个真实场景:手机APP要获取智能手环的实时心率

图3-1 手机获取手环数据流程图

3.1. 流程步骤详解

第1-2步:发现

客户端必须首先了解服务器有什么。这通过两次“发现”完成:

  1. 服务发现:获取设备所有服务的列表及其在数据库中的地址范围(句柄范围)。

  2. 特征值发现:在感兴趣的服务内,获取所有特征值的详细信息,特别是特征值数值的属性具体句柄

第3步:读取(可选)

客户端可以直接读取特征值的当前值。这是一种“拉”模式,适用于获取不需要实时更新的静态信息(如设备序列号)。

第4步:订阅(关键)

为了实时获取数据(如心率),客户端需要启用“推”模式。这是通过找到目标特征值对应的CCCD描述符(其句柄通常紧随特征值句柄之后),并向其写入 0x0001(启用通知)来实现的。此操作是后续服务器主动发送数据的开关。

第5-6步:推送

启用通知后,每当特征值的数据更新,服务器(手环)的协议栈会自动检查对应的CCCD是否已被启用。如果是,它会立即构造一个 Handle Value Notification​ 数据包,其中包含特征值的句柄和新的数据,并发送给客户端。客户端无需任何请求即可收到更新。


3.2. 流程核心总结

  1. 客户端驱动:流程由客户端(手机)的发现和配置请求启动。
  2. 句柄是地址:服务、特征值、描述符在数据库中的唯一索引称为“句柄”,所有读写操作都针对句柄进行。
  3. CCCD是开关通知功能必须由客户端通过写入CCCD显式开启。这是实现低功耗实时通信的基础,服务器仅在数据变化且有订阅者时才发送数据。
  4. 通知是异步的:一旦开关打开,数据推送由服务器在数据更新时自动、主动发起,效率极高。

这个流程是GATT通信的通用模板,适用于从读取电池电量到接收传感器数据、发送控制命令等各种场景。理解此流程,就掌握了使用或开发BLE应用功能的核心交互逻辑。

这个流程揭示了GATT的精髓:客户端主导发现,并通过配置CCCD来建立一种高效的、服务器驱动的数据推送通道。“通知”机制是BLE传感器设备实现超低功耗的关键,设备大部分时间可以睡眠,仅在数据变化时醒来发送一个很小的数据包。


四、 总结

GATT 通过标准化的分层模型,在灵活性互操作性之间取得了完美平衡:

  • 对开发者:它提供了设计产品的清晰蓝图。你需要思考你的设备提供哪些“服务”,每个服务下有哪些“特征值”(数据或命令),它们各自该有什么权限。
  • 对用户和应用:它提供了发现和使用设备功能的通用方法。一个通用的蓝牙调试APP(如 nRF Connect​ 或 LightBlue)可以连接任何BLE设备,浏览其GATT表,读写数据,正是因为大家都遵循同一套GATT“语言”。

由于个人水平有限,文中若有任何疏漏或表述不清之处,欢迎在评论区指正与交流。

后续更新预告:我将持续更新ble系列的技术科普,下一篇计划《BLE L2CAP 协议详解》。如果本文对你有帮助,欢迎点赞、收藏、关注,这是对我最大的鼓励!


📚 蓝牙学习系列专栏

本系列是系统性的蓝牙低功耗(BLE)技术教程,从协议栈原理到实战开发,适合嵌入式开发者、物联网工程师和所有对蓝牙技术感兴趣的读者。

🎯 **系列导航**:本文是《蓝牙学习系列》第7篇  

🔗 **完整专栏**: 蓝牙学习系列专栏

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐