GATT 服务的核心函数bt_gatt_discover的介绍

目录

概述

[1 GATT 基本概念](#1 GATT 基本概念)

[1.1 GATT 的介绍](#1.1 GATT 的介绍)

[1.2 GATT 的角色](#1.2 GATT 的角色)

[1.3 核心组件](#1.3 核心组件)

[1.4 客户端操作](#1.4 客户端操作)

[2 bt_gatt_discover函数的功能和应用](#2 bt_gatt_discover函数的功能和应用)

[2.1 函数介绍](#2.1 函数介绍)

[2.1 发现类型(Discover Type)](#2.1 发现类型(Discover Type))

[3 典型使用流程](#3 典型使用流程)

[3.1 服务发现示例](#3.1 服务发现示例)

[3.2 级联发现模式](#3.2 级联发现模式)

[3.3 按UUID过滤发现](#3.3 按UUID过滤发现)

[3.4 发现描述符](#3.4 发现描述符)

[4 错误处理](#4 错误处理)

[4.1 常见错误码](#4.1 常见错误码)

[4.2 错误处理示例](#4.2 错误处理示例)

[5 性能优化建议](#5 性能优化建议)

[6 资源管理注意事项](#6 资源管理注意事项)

[6.1 参数生命周期](#6.1 参数生命周期)

[6.2 取消发现](#6.2 取消发现)


概述

本文介绍了蓝牙低功耗(BLE)中的GATT协议及其核心功能。GATT定义了BLE设备通过服务和特征交换数据的标准框架,包含服务器和客户端两种角色。文章详细解析了GATT的核心组件(服务、特性、描述符)及其层级结构,并以Zephyr协议栈中的bt_gatt_discover函数为例,说明其参数配置、发现类型和使用流程,包括服务发现、级联发现、UUID过滤等典型应用场景。最后还列举了常见错误码及处理方法,为BLE应用的开发提供了实用指导。

1 GATT 基本概念

1.1 GATT的介绍

GATT (Generic Attribute Profile) 是 Bluetooth Low Energy (BLE) 的核心协议,定义了 数据通信的标准框架 ,使BLE设备能够通过 服务(Services)特征(Characteristics) 交换数据。

1.2 GATT 的角色

角色 说明 典型设备
GATT 服务器(Server) 存储并提供数据(如传感器数据) 心率带、温度计
GATT 客户端(Client) 读取或写入服务器数据 手机、中央设备

1.3 核心组件

1)层级结构

cpp 复制代码
GATT Profile
├── Services (服务)
│   ├── Characteristics (特性)
│   │   ├── Value (值)
│   │   ├── Descriptors (描述符)
│   │   │   └── Client Characteristic Configuration (CCC)
│   │   └── Properties (属性)
│   └── Includes (包含服务)
└── Attributes (属性)

2) 关键组件说明

组件 说明 示例UUID
服务(Service) 功能逻辑集合 0x180A (设备信息服务)
特性(Characteristic) 服务中的数据项 0x2A29 (厂商名称)
描述符(Descriptor) 特性的元数据 0x2902 (CCC描述符)
属性(Attribute) 数据库基本单元 由协议栈管理

1.4 客户端操作

操作 函数(Zephyr示例) 说明
发现服务 bt_gatt_discover() 扫描远程设备的GATT表
读取特征值 bt_gatt_read() 读取数据(如电池电量)
写入特征值 bt_gatt_write() 发送命令或配置
启用通知 bt_gatt_subscribe() 订阅实时数据(如心率)

2 bt_gatt_discover函数的功能和应用

2.1 函数介绍

bt_gatt_discover 是 Zephyr BLE 协议栈中用于发现远程设备 GATT 服务的核心函数,下面我将从多个维度进行详细说明:

  1. 函数原型与参数
cpp 复制代码
int bt_gatt_discover(
    struct bt_conn *conn,
    struct bt_gatt_discover_params *params
);

2)参数说明:

  • conn:已建立的BLE连接句柄

  • params:发现参数结构体,包含以下关键字段:

cpp 复制代码
struct bt_gatt_discover_params {
    const struct bt_uuid *uuid;      // 目标UUID(可选过滤条件)
    uint16_t start_handle;           // 起始属性句柄(通常0x0001)
    uint16_t end_handle;             // 结束属性句柄(通常0xFFFF)
    enum bt_gatt_discover_type type; // 发现类型
    void (*func)(struct bt_conn *conn,
                const struct bt_gatt_attr *attr,
                struct bt_gatt_discover_params *params);
};

2.1 发现类型(Discover Type)

类型枚举值 说明 对应ATT操作
BT_GATT_DISCOVER_PRIMARY 发现主服务 ATT Read By Group Type Req
BT_GATT_DISCOVER_SECONDARY 发现次要服务 ATT Read By Group Type Req
BT_GATT_DISCOVER_INCLUDE 发现包含的服务 ATT Read By Type Req
BT_GATT_DISCOVER_CHARACTERISTIC 发现特性 ATT Read By Type Req
BT_GATT_DISCOVER_DESCRIPTOR 发现描述符 ATT Find Information Req
BT_GATT_DISCOVER_STD_CHAR_DESC 发现标准特性描述符 ATT Read By Type Req

3 典型使用流程

3.1 服务发现示例

cpp 复制代码
static struct bt_gatt_discover_params discover_params;

static void discover_cb(struct bt_conn *conn,
                      const struct bt_gatt_attr *attr,
                      struct bt_gatt_discover_params *params)
{
    if (!attr) {
        printk("Discovery complete\n");
        return;
    }

    switch (params->type) {
    case BT_GATT_DISCOVER_PRIMARY: {
        struct bt_gatt_service_val *svc = attr->user_data;
        printk("Service found: start_handle=0x%04X, end_handle=0x%04X\n",
              attr->handle, svc->end_handle);
        break;
    }
    case BT_GATT_DISCOVER_CHARACTERISTIC: {
        struct bt_gatt_chrc *chrc = attr->user_data;
        printk("Characteristic: handle=0x%04X, properties=0x%02X\n",
              chrc->value_handle, chrc->properties);
        break;
    }
    }
}

void start_discovery(struct bt_conn *conn)
{
    discover_params.uuid = NULL;  // 发现所有主服务
    discover_params.start_handle = 0x0001;
    discover_params.end_handle = 0xFFFF;
    discover_params.type = BT_GATT_DISCOVER_PRIMARY;
    discover_params.func = discover_cb;

    int err = bt_gatt_discover(conn, &discover_params);
    if (err) {
        printk("Discovery failed to start (err %d)\n", err);
    }
}

3.2 级联发现模式

cpp 复制代码
static void discover_chars(struct bt_conn *conn, uint16_t start, uint16_t end)
{
    static struct bt_gatt_discover_params params;
    
    params.start_handle = start;
    params.end_handle = end;
    params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
    params.func = discover_cb;
    
    bt_gatt_discover(conn, &params);
}

static void discover_cb(...)
{
    if (params->type == BT_GATT_DISCOVER_PRIMARY) {
        // 发现主服务后继续发现特性
        struct bt_gatt_service_val *svc = attr->user_data;
        discover_chars(conn, attr->handle + 1, svc->end_handle);
    }
}

3.3 按UUID过滤发现

cpp 复制代码
static struct bt_uuid_16 find_uuid = BT_UUID_INIT_16(0x180F); // 电池服务

void find_battery_service(struct bt_conn *conn)
{
    discover_params.uuid = &find_uuid.uuid;
    discover_params.type = BT_GATT_DISCOVER_PRIMARY;
    bt_gatt_discover(conn, &discover_params);
}

3.4 发现描述符

cpp 复制代码
void discover_descriptors(struct bt_conn *conn, uint16_t start, uint16_t end)
{
    discover_params.start_handle = start;
    discover_params.end_handle = end;
    discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
    bt_gatt_discover(conn, &discover_params);
}

4 错误处理

4.1 常见错误码

错误码 说明
0 成功
-ENOTCONN 未建立连接
-EINVAL 无效参数
-ENOMEM 内存不足
-EOPNOTSUPP 操作不支持

4.2 错误处理示例

cpp 复制代码
int err = bt_gatt_discover(conn, &params);
if (err) {
    printk("Error %d during discovery\n", err);
    switch (err) {
    case -ENOTCONN:
        // 处理连接问题
        break;
    case -EINVAL:
        // 检查参数有效性
        break;
    }
}

5 性能优化建议

  1. 分阶段发现:先发现服务,再根据需要发现特性和描述符

  2. 缓存发现结果:避免重复发现

  3. 合理设置句柄范围:缩小start_handle/end_handle范围

  4. 使用UUID过滤:减少不必要的发现操作

6 资源管理注意事项

6.1 参数生命周期

cpp 复制代码
// 错误:使用栈变量(函数返回后失效)
void start_temp_discovery(struct bt_conn *conn) {
    struct bt_gatt_discover_params temp_params = {...};
    bt_gatt_discover(conn, &temp_params); // 危险!
}

// 正确:使用静态或动态分配
static struct bt_gatt_discover_params persistent_params;

6.2 取消发现

cpp 复制代码
void cancel_discovery(struct bt_conn *conn) {
    bt_gatt_discover_cancel(conn, &discover_params);
}
相关推荐
mftang10 天前
Zephyr OS 中的 FIFO 接口应用介绍
嵌入式硬件·zephyr架构蓝牙应用笔记
mftang1 个月前
Zephyr RTOS架构下的固件升级
mcu·zephyr架构蓝牙应用笔记
mftang1 个月前
zephyr架构下Bluetooth advertising接口
zephyr架构蓝牙应用笔记