连接模块中的BLE方式GATT协议分析

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 ManagerBus CenterTransmission 等上层模块提供统一的 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 近场设备间高速通信 的基石,它:

  1. 屏蔽了 BLE 协议的复杂性,为上层提供简洁的连接和数据传输接口
  2. 实现了企业级的可靠性,包括状态机校验、引用计数、超时机制
  3. 适配了华为自研 BLE 协议栈,通过 Adapter 层抽象了平台差异
相关推荐
想你依然心痛4 天前
【共创季稿事节】HarmonyOS 7.0 分布式软总线架构演进与多端协同前瞻
超级终端·零信任安全·分布式软总线·harmonyos 7.0·多端协同·意图驱动发现·星闪协议
六bring个六6 天前
open Harmony中分布式软总线的学习任务清单
分布式·学习·c/c++·open harmony
奔跑吧 android7 天前
【Bluetooth-SIG】【CoreV6.2】【Vol3 Part G】【GATT】【零】【GATT 逐句逐段学习计划 2】
ble·bluetooth·att·gatt·core_v6.2·sig
六bring个六9 天前
文件互传在传输层的操作分析
分布式·p2p·c/c++·open harmony
六bring个六10 天前
文件互传功能实现
c/c++·open harmony·文件互传
HiDev_12 天前
BLE Legacy 连接【读取当前连接所使用 PHY 类型 HCI_LE_Read_PHY command】
蓝牙·ble·蓝牙连接·ble 蓝牙广播·蓝牙hci command
HiDev_13 天前
BLE Legacy 连接【断开连接 Disconnect command】
蓝牙·ble·蓝牙连接·ble 蓝牙广播·蓝牙hci command
K成长日志14 天前
BLE协议之设备地址
网络·物联网·网络协议·嵌入式·蓝牙·ble
奔跑吧 android15 天前
【Bluetooth-SIG】【CoreV6.2】【Vol3 Part F】【十三】【Error Handling——ATT_ERROR_RSP】
ble·bluetooth·att·gatt·蓝牙协议·bt·core_v6.2