当前位置: 首页 > news >正文

蓝牙应用层协议GATT

文章目录

      • 一、GATT 是什么?
      • 二、GATT 在 BLE 通信中的位置
      • 三、GATT 的关键角色:客户端 vs. 服务器
      • 四、GATT 的数据结构:层层嵌套
        • 1. **Profile(配置文件)**
        • 2. **Service(服务)**
        • 3. **Characteristic(特征值)**
      • 五、一个实际的通信流程(以心率手环为例)
      • 总结
      • 图表关键点解读
      • 总结:Handle vs UUID
      • 核心要点
      • 详细解释与类比
      • 标准 UUID vs. 自定义 UUID
      • 总结

一、GATT 是什么?

GATT的全称是Generic Attribute Profile,即通用属性协议

简单来说,它是低功耗蓝牙(BLE)设备之间进行通信的核心数据交换协议。它定义了两个 BLE 设备在建立连接后,如何组织和传输数据

一个非常形象的比喻是:

GATT 就像是我们去图书馆借书所遵循的一整套规则。

  • 图书馆本身就是你的 BLE 设备。
  • 书架的分类(比如“计算机类”、“文学类”)就是Service(服务)
  • 具体的每一本书(比如《蓝牙开发入门》)就是Characteristic(特征值),书里的内容就是特征值所包含的数据
  • 图书馆的目录检索系统借阅流程就是GATT协议本身。

这套规则(GATT)规定了书如何摆放、如何查找、如何借阅和归还。没有这套规则,你就无法有效地从图书馆获取信息。


二、GATT 在 BLE 通信中的位置

为了理解 GATT 的角色,我们看一下简化的 BLE 通信栈:

+------------------------------------+ | 你的手机 App | <-- 你交互的应用层 +------------------------------------+ | GATT 客户端 | <-- 发起请求的一方(如手机) +------------------------------------+ | ATT 协议层 | <-- 负责数据封装的底层协议 +------------------------------------+ | L2CAP 逻辑层 | +------------------------------------+ | PHY 物理层 (无线电波) | +------------------------------------+
  • ATT(Attribute Protocol): 是 GATT 的基础,它定义了数据的格式(即“属性”)。GATT 是在 ATT 之上构建的高级别规范,它赋予了这些属性具体的含义和组织结构。
  • GATT 依赖于连接: GATT 通信必须在两个设备建立 BLE 连接之后才能进行。它不像广播那样可以一对多。

三、GATT 的关键角色:客户端 vs. 服务器

在 GATT 通信中,有两个明确的角色,这与我们熟悉的客户端-服务器模型(如网页浏览)非常相似:

角色GATT 服务器GATT 客户端
比喻图书馆读者
描述数据的持有者和提供者数据的请求者和使用者
典型设备心率手环、智能门锁、传感器手机、平板、电脑
职责存储数据,并响应客户端的请求发现服务器上的数据,并读写它们
主动/被动被动(等待命令)主动(发起命令)
  • 一个 BLE 连接中,一方是 GATT 服务器,另一方是 GATT 客户端。
  • 手机 App 通常作为GATT 客户端,而去读写手环等外设,外设就是GATT 服务器

四、GATT 的数据结构:层层嵌套

这是 GATT 最核心的概念。数据是以一种层级化、嵌套的方式组织的,如下图所示,它清晰地展示了从配置文件(Profile)到特征值(Characteristic)的包含关系:

Profile

Service 2

Characteristic C

Value

Properties

Service 1

Characteristic B

Value

Properties

Characteristic A

Value

Properties

Descriptors e.g., CCCD

下面我们来详细解释图中的每一层:

1.Profile(配置文件)
  • 这不是一个实际在总线上传输的数据实体,而是一个功能规范文档
  • 它定义了一个具体的应用场景需要哪些Service的组合。
  • 例如,心率 Profile规定:一个设备必须包含心率 Service,并且该 Service 必须包含心率测量 Characteristic
2.Service(服务)
  • 服务是一个相关功能的数据集合。它像一个容器,里面装着多个实现某种功能的 Characteristic。
  • 每个 Service 都有一个唯一的 128 位 UUID来标识。
  • 标准 Service(如电池服务、设备信息服务)使用蓝牙技术联盟定义的16位短UUID(如0x180F代表电池服务)。
  • 设备制造商也可以定义自己的自定义 Service,使用 128 位的长 UUID。
  • 例子:电池服务(0x180F)里包含了“电池电量”这个特征值。
3.Characteristic(特征值)
  • 特征值是 GATT 数据库中的最小数据单元,是你实际读写数据的地方。
  • 一个 Characteristic 包含三个部分:
    1. Value(值)实际的数据本身(例如,心率数值、电池电量百分比)。这就是你读取和写入的对象。
    2. Properties(属性):定义了可以对这个 Characteristic 进行什么操作。它是一个位掩码,常见的有:
      • Broadcast:广播
      • Read:可读
      • Write Without Response:无响应写
      • Write:带响应写
      • Notify:通知(不需要客户端 ACK,主动上报) Indicate:指示(需要客户端 ACK 确认)
      • Authenticated Signed Writes:签名写
    3. Descriptors(描述符):描述 Characteristic 的元信息。最最重要的是:
      • CCCD(客户端特征配置描述符):当 Characteristic 的属性包含NotifyIndicate时,必须存在。开启 Notify/Indicate 就是往这个描述符写值。
        • 0x0000:关闭上报
        • 0x0001:开启 Notify
        • 0x0002:开启 Indicate
      • Characteristic User Description(0x2901):可读字符串,特征的文字说明
      • Characteristic Format(0x2904):说明 value 数据类型、单位

五、一个实际的通信流程(以心率手环为例)

  1. 手机(客户端)手环(服务器)建立 BLE 连接。
  2. 手机发起:发现服务(“嘿,你有什么功能?”)。
  3. 手环回复:我这里有心率服务(0x180D)电池服务(0x180F)
  4. 手机针对心率服务:发现特征(“你的心率服务里有什么数据?”)。
  5. 手环回复:我有心率测量特征(0x2A37),它的属性是Notify
  6. 手机心率测量特征下面的CCCD 描述符写入0x0001(“请在有新心率数据时通知我”)。
  7. 手环的心率数据发生变化时,就会主动向手机发送一个包含新数据的“通知”包,而无需手机再次询问。
  8. 手机的 GATT 客户端回调函数(如onCharacteristicChanged)会收到这个数据并更新界面。

具体层级关系如下:

Service: Heart Rate (0x180D) └─ Characteristic: Heart Rate Measurement (0x2A37) ├─ Value: [0x00, 0x4B] # 心率 75 bpm ├─ Properties: Notify └─ Descriptor: CCCD └─ 用于开启/关闭心率通知

总结

  • GATT是 BLE 通信的数据交互规则
  • 它基于客户端-服务器模型。
  • 数据采用Profile -> Service -> Characteristic的层级结构组织。
  • Characteristic是数据操作的基本单元,通过Notify/Indicate属性实现服务器主动推送,这是 BLE 应用中最常见的模式。

理解了 GATT,你就掌握了 BLE 应用开发的精髓。

这张图清晰地展示了层级关系中每一个关键元素的标识符:

渲染错误:Flowchart 渲染失败: Cannot set properties of undefined (setting 'next')

图表关键点解读

  1. 服务层 (Service Level)

    • 服务声明 (Service Declaration):
      • Handle0x0001: 这是整个服务的"门牌号"。
      • UUID0x2800: 这是一个固定的类型,表示"这是一个主服务声明"。
      • Value UUID0x180D: 这是服务声明所包含的,它定义了这是一个什么样的服务。0x180D代表"心率服务"。
  2. 特征层 (Characteristic Level)

    • 特征声明 (Characteristic Declaration):
      • Handle0x0002: 特征声明的门牌号。
      • UUID0x2803: 固定的类型,表示"这是一个特征声明"。
      • Value: 这个声明包含的值比较复杂,它打包了三个信息:该特征的操作属性、该特征的句柄、该特征的UUID。
    • 特征值 (Characteristic Value):
      • Handle0x0003:这是核心!读/写/通知操作的实际数据对象。
      • UUID0x2A37: 定义了这是什么数据,这里是"心率测量值"。
      • Properties: 定义了允许的操作,这里是NotifyRead
  3. 描述符层 (Descriptor Level)

    • CCCD 描述符:
      • Handle0x0004: 描述符的门牌号。
      • UUID0x2902: 固定的类型,表示"这是一个客户端特征配置描述符"。

总结:Handle vs UUID

通过这张图,我们可以清晰地总结:

元素Handle (句柄)UUID (通用唯一识别码)
是什么数据的内存地址数据的类型说明
特点简短的数字,在设备连接后动态发现较长的字符串,用于静态定义功能
作用定位: “数据在哪里?”识别: “这是什么数据?”
类比图书馆的索书号书的ISBN号分类

通信过程
当手机App想要读取身体传感器位置时,底层发生的其实是:

  1. 应用层通过UUID 0x2A38请求。
  2. 蓝牙栈查找之前发现的"地图",找到UUID 0x2A38对应的Handle0x0006
  3. 蓝牙栈向设备发送一个ATT协议命令:READ_REQ(handle=0x0006)
  4. 设备回复:READ_RSP(handle=0x0006, value=0x03)(0x03代表"胸部")。

希望这张综合了handleUUID的图,能让您对GATT数据库的结构有更透彻的理解!

是的,特征值(Characteristic)绝对有 UUID,而且这是它的核心身份标识!

在上面的图表中,0x2A370x2A38就是特征值的 UUID。可能之前的解释有些绕,让我们抛开复杂的结构,直接聚焦于特征值本身。

核心要点

每一个特征值都有两个非常重要的 UUID:

  1. 用于“特征声明”的 UUID

    • 它的值是固定的0x2803。这个 UUID 就像一个大声的宣告:“大家好,这里是一个特征值的开始!”。
    • 它所在的这个“声明”本身,有一个句柄(比如0x0002)。
  2. 特征值本身的 UUID

    • 这是真正定义这个特征值功能的 UUID。它告诉我们这个特征值是什么,能干什么
    • 它存储在特征声明所指向的特征值对象中,这个对象有自己的句柄(比如0x0003)。

为了更清晰地理解这一点,下图直观地展示了这两个 UUID 如何共同定义一个特征值:

渲染错误:Flowchart 渲染失败: Cannot set properties of undefined (setting 'next')

详细解释与类比

让我们用公司职位来类比,这更容易理解:

  • 服务(Service)=部门(如:销售部0x180D
  • 特征声明(Declaration)=职位公告牌(上面写着“这里是销售部的一个职位”,牌子编号是0x0002
  • 特征值的 UUID=具体的职位名称(如:“销售总监”0x2A37
  • 特征值的句柄=该职位人员的工位位置(如:3号工位0x0003

当你需要和“销售总监”沟通(读写数据)时,你最终需要找到的是他的工位(句柄),而“销售总监”这个职位名称(特征值UUID)是帮助你找到正确工位的依据。


标准 UUID vs. 自定义 UUID

和服務一样,特征值的 UUID 也分为标准值和自定义值:

类型示例 UUID示例功能说明
标准特征值0x2A37心率测量由蓝牙技术联盟定义,确保不同厂商设备互通。
标准特征值0x2A19电池电量一个百分比(0-100%)的数字。
自定义特征值XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX厂商特定功能由设备制造商自定义,用于实现特殊功能。

总结

是的,特征值有UUID,而且至关重要:

  • 特征声明 UUID (0x2803):是一个固定的信号,标志着“这里有一个特征”。
  • 特征值 UUID (如0x2A37):是特征的核心身份,定义了它的数据类型和功能
  • 句柄 (如0x0003):是特征值在设备上的实际地址,用于高效通信。

在应用开发中,你通过特征值的 UUID(如0x2A37) 来寻找和操作它,底层蓝牙栈会帮你找到对应的句柄来完成实际的读写操作。

http://www.jsqmd.com/news/1334003/

相关文章:

  • 2026年8月最新消息廊坊玻璃钢生活水箱生产厂家储水难题别发愁,咱家水箱能兜底 - 行业甄选汇
  • 虚拟演出视频技术解析:从实时渲染到AI处理全链路实践
  • 上海全屋定制怎么选?别只看效果图,先看工厂直供、工期透明和售后响应 - 中国远见品牌企业资讯
  • 武汉中考志愿滑档不用愁 | 特色职校学技术,升学就业创业多出路 - 升学择校早知道
  • react-native-youtube-iframe高级功能:显示播放时间与进度控制
  • Elixir-Slack高级技巧:处理Slack事件、团队数据与用户状态
  • 打造专业视频墙:使用Brave实现多画面分割与无缝切换
  • 钉钉助手终极指南:5分钟实现灵活打卡的完整教程
  • 5大核心功能解锁B站视频智能管理:BiliTools完全使用指南
  • 2026少儿编程择校测评:编程猫、核桃编程适配人群与竞赛实力全解析 - 产品推荐官
  • 2026 湖南全屋定制环保工艺实测|ENF 板材真假辨别 + 10 家品牌工艺核验,母婴家庭必看 - 互联网科技品牌测评
  • Flutter开发自定义番剧采集与播放应用实践
  • C/C++结构体内存的问题
  • 5大核心修复技术:SilentPatch让经典GTA游戏在现代系统上重生
  • 高效在线考试怎么选?告别组卷阅卷耗时长难题 2026 年 08 月 - 讲清楚了
  • iview table columns.js 表头 带* 带星 renderHeader
  • AssetStudio极速入门:3分钟掌握Unity资源提取与导出
  • 三级心理咨询师报考实证解析:从课程设计看职业化路径 - 资讯报道
  • mir_eval性能优化:处理大规模音频数据集的高效方法
  • 2026 年金华沙发翻新沙发换皮,家具维修避坑实测分享 - LYL仔仔
  • EuroSAT遥感数据集:从入门到精通的完整实践指南
  • Lunalytics路线图详解:即将推出的5大重磅功能预览
  • react-native-youtube-iframe播放商店兼容性:避免应用被拒的关键技巧
  • forensictools实战演示:如何通过命令行无缝调用取证工具
  • 数据接口实战:从HTTP API到硬件I2S的采集策略与反反爬技巧
  • 赋能高分子颗粒高效包装,广州恒尔高分子颗粒全自动吨袋包装机以全自动化流程,提升企业核心竞争力 - 品牌速递
  • 辽宁粉笔凭什么更强:一套体系与三种模式的差距 - 资讯报道
  • 解决GIS数据与3D可视化集成的BlenderGIS实战指南
  • 2026景德镇珠山区防水维保一站式服务指南 - 超人防水
  • Kronos:基于项目级上下文理解的AI编程代理实战指南