GATT协议简介
在蓝牙的世界里,GATT(通用属性配置文件)就是这套“交接规则”。它专门负责在两个蓝牙设备连接之后,数据该如何组织和传输。
📊 GATT的核心概念
GATT把数据组织得像一个严格的表格,你可以把它想象成一个带目录和标签的文件柜。
为了让你看得更清楚,我们用“一个带心率监测功能的智能手环”举个例子:
| 概念 | 大白话解释 | 手环例子 |
|---|---|---|
| 服务 (Service) | 一个功能模块,包含一组相关的数据。 | “心率服务”(UUID:0x180D),所有和心率相关的数据都在这里。 |
| 特征 (Characteristic) | 服务里一个具体的“数据项”,它包含实际数值和访问权限(可读/可写/通知等)。 | “心率测量值”特征(UUID:0x2A37),里面就是具体的每分钟心跳次数。 |
| 描述符 (Descriptor) | 特征的“说明书”,用来描述或配置这个特征。 | 客户端特征配置描述符(CCCD),手机通过修改它来“订阅”心率通知。这样一旦心跳变化,手环就会主动推送,不用手机反复来问。 |
UUID就像每个服务和特征的唯一身份证号,有全球统一的标准(16位短ID),也可以用自定义的(128位长ID)。
🔄 客户端与服务器
在GATT里,只有两个角色:
GATT服务器 (GATT Server):数据的提供方。它负责存储数据并响应请求。你的智能手环就是服务器,它存着你的心率数据。每个蓝牙设备至少得能当个基本的服务器。
GATT客户端 (GATT Client):数据的使用方。它主动去服务器读写数据。你的手机App就是客户端,它去手环上读取心率。
连接后,客户端必须先“服务发现”,才能知道服务器提供了哪些服务和特征,就像拿到一份文件柜的目录。
✉️ 四种数据操作方式
角色定好后,它们通过这四种方式“对话”:
读 (Read):客户端主动向服务器“要”数据(例如:手机读取当前心率)。
写 (Write):客户端主动向服务器“写”数据(例如:手机设置手环的时间)。
通知 (Notify):服务器主动“推送”数据给客户端,不需要客户端回复确认。这种方式最省电、最常用(例如:心跳变了,手环就自动推给手机)。
指示 (Indicate):服务器主动“推送”数据,但需要客户端回复确认,更可靠但稍慢。
一个常见的误解是:GATT的客户端/服务器角色,和负责连接建立的GAP(通用访问配置文件)里的中央/外围设备角色是两套独立的体系。一个中央设备(手机)可以是GATT客户端,而一个外围设备(手环)也可以是GATT客户端。
简单来说,GAP负责“怎么连上”,而GATT负责“连上后怎么聊”。
COC协议简介
目前是open Harmony6.1统一互联共建3.0版本,我看项目里面目前用的是BLE4.2,但还没有实现coc协议连接的,不过也要铺垫一下。
CoC”在蓝牙BLE里的全称是L2CAP 面向连接的通道 (Connection-Oriented Channel),它和 GATT 是两种完全不同的数据传输思路。
如果拿寄送物品来比喻,GATT 和 CoC 的区别就像寄包裹和修一条管道:
GATT(寄包裹):你想给对方东西,得按规定的格式打包好(属性协议),贴上标签(UUID),在“快递点”(固定通道)等着对方来取件(读)或叫快递员送过去(写/通知)。每次只能送一个标准大小的包裹,比较适合传递心率这种小数据。
CoC(修管道):为了高效地传送大量数据(比如音频流或大文件),你们直接在两个设备间修了一条专用的“管道”。一旦接通,数据就可以像流水一样持续、双向地传输。
COC 与 GATT 的关键区别:
| 特性 | GATT | COC (L2CAP) |
|---|---|---|
| 传输可靠性 | 基于 ATT 协议 | 基于 L2CAP 面向连接通道 |
| 数据格式 | 必须符合 GATT Profile | 更灵活的字节流 |
| 适用场景 | 设备发现、服务读写 | 高可靠性的字节流传输 |
| MTU | 较小(默认 512) | 可更大 |
| 实现复杂度 | 较复杂 | 较简单 |
🌊 “管道”内部是怎么工作的?
这条“管道”有几个很实用的设计:
容量更大 (MTU更大):相比于GATT,CoC的“管道”一次能承载更大的数据包,最高可支持到512字节,传输效率更高。
自带调节阀 (基于信用的流量控制):为了防止“管道”里的数据太多把接收方冲垮,CoC采用了一种“信用”机制。发送方只有收到接收方给的“信用”才能发送数据,从而实现了流控,确保传输的可靠性。
独立“阀门” (PSM):要连接到不同的CoC“管道”,需要知道一个叫PSM (协议/服务复用器)的“阀门编号”作为服务识别码。这就像GATT里用UUID来找到特定服务一样,但层级更底层。
🎯 什么时候用CoC?
正因为CoC高效且可靠,它在很多对实时性和数据传输量要求较高的场景里非常适用:
音频传输:这是CoC最典型的应用。比如助听器通过BLE传输音频流,就是利用CoC通道来保证稳定、低延迟的声音质量。
批量数据同步:传输文件、日志记录等较大块的数据时,CoC的效率要远高于GATT。
总结来说,GATT适合“查字典”式的小数据查询,而CoC适合“拉专线”式的流数据传输。它们是互补的关系,各司其职。
软总线 BLE GATT 连接模块设计实现分析
总述
GATT(Generic Attribute Profile)是软总线(dsoftbus)在BLE(蓝牙低功耗)场景下的核心连接协议。它负责设备发现、连接建立、数据传输等完整生命周期管理。
从架构视角看,GATT 模块处于软总线连接层的最底层,承上启下:
- 对上:为
Connection Manager、Bus Center、Transmission等上层模块提供统一的 BLE 连接和数据传输能力 - 对下:通过
Adapter层调用华为自研的 BLE 协议栈(HDI)接口,完成实际的蓝牙操作
一、整体架构
二、核心数据结构
2.1 BLE 连接对象(ConnBleConnection)
这是 GATT 连接的核心实体,贯穿整个连接生命周期:
typedef struct { ListNode node; // 链表节点(用于全局管理) BleProtocolType protocol; // 协议类型:BLE_GATT = 0 uint32_t connectionId; // 连接ID(全局唯一) ConnSideType side; // 角色:CLIENT 或 SERVER bool fastestConnectEnable; // 是否启用快速连接 char addr[BT_MAC_LEN]; // 蓝牙地址 uint32_t sequence; // 数据包序列号 // 接收缓冲(支持分包组包) ConnBleReadBuffer buffer; // 线程安全锁 SoftBusMutex lock; // 连接状态机 enum ConnBleConnectionState state; // 底层句柄(对应对端设备) int32_t underlayerHandle; // MTU 大小(默认 512) uint32_t mtu; // 设备标识 char udid[UDID_BUF_LEN]; // 唯一设备ID char networkId[NETWORK_ID_BUF_LEN]; // 网络ID // 特性集 ConnBleFeatureBitSet featureBitSet; // 引用计数(业务计数 + 内存计数) int32_t connectionRc; int32_t objectRc; } ConnBleConnection;2.2 连接状态机(ConnBleConnectionState)
enum ConnBleConnectionState { // 客户端专用状态 BLE_CONNECTION_STATE_CONNECTING = 0, // 初始连接中 BLE_CONNECTION_STATE_CONNECTED, // 底层已连接 BLE_CONNECTION_STATE_SERVICE_SEARCHING, // GATT 服务发现中 BLE_CONNECTION_STATE_SERVICE_SEARCHED, // 服务发现完成 BLE_CONNECTION_STATE_CONN_NOTIFICATING, // 通知特征订阅中 BLE_CONNECTION_STATE_CONN_NOTIFICATED, // 通知订阅完成 // 服务端/共用状态 BLE_CONNECTION_STATE_NET_NOTIFICATING, // 网络特征通知中 BLE_CONNECTION_STATE_NET_NOTIFICATED, // 网络特征通知完成 BLE_CONNECTION_STATE_MTU_SETTING, // MTU 协商中 BLE_CONNECTION_STATE_MTU_SETTED, // MTU 协商完成 BLE_CONNECTION_STATE_EXCHANGING_BASIC_INFO, // 交换基本信息 BLE_CONNECTION_STATE_EXCHANGED_BASIC_INFO, // 基本信息交换完成 // 结束状态 BLE_CONNECTION_STATE_NEGOTIATION_CLOSING, // 协商关闭 BLE_CONNECTION_STATE_CLOSING, // 关闭中 BLE_CONNECTION_STATE_CLOSED, // 已关闭 BLE_CONNECTION_STATE_INVALID, };三、核心模块设计与实现
3.1 BLE Manager(连接管理器)
职责:统一管理所有 BLE 连接,负责连接的创建、查找、释放和消息路由。
typedef struct { SoftBusList *connections; // 所有活跃连接 ConnBleState *state; // BLE 模块状态 ListNode waitings; // 等待连接的设备队列 ConnBleDevice *connecting; // 正在连接的设备 SoftBusList *prevents; // 阻止连接的设备(防冲突) } BleManager;关键能力:
- 防冲突机制:防止多个模块同时对同一设备发起连接
- 连接复用:已存在的连接被新请求复用,而非重复建立
- 延迟清理:空闲超时(60秒)后才真正释放连接
3.2 GATT Client(客户端)
职责:作为 GATT Client,发起连接请求并与 GATT Server 通信。
核心 UUID 定义:
#define SOFTBUS_SERVICE_UUID "11C8B310-80E4-4276-AFC0-F81590B2177F" #define SOFTBUS_CHARA_BLENET_UUID "00002B00-0000-1000-8000-00805F9B34FB" #define SOFTBUS_CHARA_BLECONN_UUID "00002B01-0000-1000-8000-00805F9B34FB" #define SOFTBUS_DESCRIPTOR_CONFIGURE_UUID "00002902-0000-1000-8000-00805F9B34FB"客户端连接流程:
3.3 GATT Server(服务端)
职责:作为 GATT Server,发布服务并响应 Client 的读写请求。
服务状态机:
enum GattServerState { BLE_SERVER_STATE_INITIAL = 0, BLE_SERVER_STATE_SERVICE_ADDING, // 添加服务中 BLE_SERVER_STATE_SERVICE_ADDED, // 服务已添加 BLE_SERVER_STATE_NET_CHARACTERISTIC_ADDING, // 添加网络特征 BLE_SERVER_STATE_NET_CHARACTERISTIC_ADDED, BLE_SERVER_STATE_NET_DISCRIPTOR_ADDING, // 添加描述符 BLE_SERVER_STATE_NET_DISCRIPTOR_ADDED, BLE_SERVER_STATE_CONN_CHARACTERISTIC_ADDING, // 添加连接特征 BLE_SERVER_STATE_CONN_CHARACTERISTIC_ADDED, BLE_SERVER_STATE_CONN_DISCRIPTOR_ADDING, BLE_SERVER_STATE_CONN_DISCRIPTOR_ADDED, BLE_SERVER_STATE_SERVICE_STARTING, // 服务启动中 BLE_SERVER_STATE_SERVICE_STARTED, // 服务已启动 // ... 停止/删除状态 };GATT 服务结构:
两个特征值的作用:
| 特征值 | UUID | 用途 |
|---|---|---|
| NET | 0x2B00 | 网络数据传输通道 |
| CONN | 0x2B01 | 连接控制/引用计数消息 |
3.4 BLE Trans(传输层)
职责:处理分包/组包、流量控制、数据收发。
传输帧格式:
typedef struct { uint32_t seq; // 序列号 uint32_t size; // 当前包大小 uint32_t offset; // 数据偏移 uint32_t total; // 总数据大小 } BleTransHeader;分包组包机制:
流量控制:采用滑动窗口控制器,防止发送过快导致接收端缓冲区溢出。
四、关键流程解析
4.1 设备发现与连接建立
4.2 引用计数机制(Reference Counting)
连接采用引用计数来管理生命周期,支持连接复用和延迟释放:
// 连接建立后,初始 connectionRc = 0 // 每次业务模块使用连接时 +1,使用完毕后 -1 // 当 connectionRc = 0 且空闲超时时,连接才真正释放 int32_t ConnBleUpdateConnectionRc( ConnBleConnection *connection, uint16_t challengeCode, // 挑战码(用于配对) int32_t delta // 增量:+1 或 -1 )4.3 防冲突机制
当多个业务模块同时请求连接同一设备时:
五、模块间协作关系
六、总结
设计亮点
| 特性 | 实现方式 | 优势 |
|---|---|---|
| 状态机驱动 | 详细的状态定义和状态转换检查 | 确保连接流程正确性,避免意外状态 |
| 引用计数 | connectionRc+objectRc双计数 | 支持连接复用,防止提前释放 |
| 防冲突队列 | waitings+prevents双队列 | 避免多模块同时连接同一设备 |
| 分包组包 | BleTransHeader+ 滑动窗口 | 支持大数据传输,保证可靠性 |
| 超时机制 | 各阶段独立超时定时器 | 快速失败,避免无限等待 |
| 快速连接 | fastestConnectEnable | 减少连接延迟 |
核心价值
GATT 连接模块是 dsoftbus 实现BLE 近场设备间高速通信的基石,它:
- 屏蔽了 BLE 协议的复杂性,为上层提供简洁的连接和数据传输接口
- 实现了企业级的可靠性,包括状态机校验、引用计数、超时机制
- 适配了华为自研 BLE 协议栈,通过 Adapter 层抽象了平台差异