ESP-IDF项目中的BLE数据交换指南

ESP-IDF项目中的BLE数据交换指南

esp-idf Espressif IoT Development Framework. Official development framework for Espressif SoCs. esp-idf 项目地址: https://gitcode.com/gh_mirrors/es/esp-idf

概述

本文是ESP-IDF项目中蓝牙低功耗(BLE)入门系列的第四篇教程,将深入讲解BLE连接中的数据交换过程。我们将重点介绍GATT服务器的代码实现,基于NimBLE主机层栈的示例项目。

学习目标

  • 理解特征数据和服务的数据结构细节
  • 了解GATT中的不同数据访问操作
  • 掌握GATT服务器示例的代码结构

GATT数据特征与服务

GATT服务是BLE连接中两个设备间数据交换的基础设施,最小数据单元是属性。在数据表示与交换部分,我们简要介绍了ATT层的属性和GATT层的特征数据、服务及规范。

属性结构

一个属性包含以下四个部分:

  1. 句柄(Handle):16位无符号整数,表示属性在属性表中的索引
  2. 类型(Type):使用UUID(通用唯一标识符)来区分类型
  3. 访问权限(Access Permission):指示是否需要加密/授权,是否可读或可写
  4. 值(Value):实际的用户数据或另一个属性的元数据

BLE中有两种UUID类型:

  • SIG定义的16位UUID
  • 制造商自定义的128位UUID

常见特征和服务UUID可在SIG的"Assigned Numbers"标准文档中找到,例如:

  • 血压服务:0x1810
  • 通用音频服务:0x1853
  • 年龄特征:0x2A80
  • 外观特征:0x2A01

特征数据

一个特征数据项通常由以下属性组成:

  1. 特征声明(Characteristic Declaration)

    • 包含特征值的属性、句柄和UUID信息
    • UUID为0x2803,只读
  2. 特征值(Characteristic Value)

    • 用户数据
    • UUID标识特征类型
  3. 特征描述符(Characteristic Descriptor)

    • 特征数据的附加描述
    • 可选属性
特征声明与特征值的关系

以心率测量为例,特征声明与特征值的关系如下表所示:

| 句柄 | UUID | 权限 | 值 | 属性类型 | |------|---------|----------|-----------------------------|-----------------------| | 0 | 0x2803 | 只读 | 属性=只读 | 特征声明 | | | | | 句柄=1 | | | | | | UUID=0x2A37 | | | 1 | 0x2A37 | 只读 | 标志位 | 特征值 | | | | | 测量值 | |

特征描述符

特征描述符提供关于特征数据的补充信息。最常见的是客户端特征配置描述符(CCCD)。当特征支持服务器发起的数据操作(通知或指示)时,必须使用CCCD来描述相关信息。

CCCD的UUID是0x2902,其属性值仅包含2位信息:

  • 第一位表示是否启用通知
  • 第二位表示是否启用指示

添加CCCD后,完整的心率测量特征数据如下:

| 句柄 | UUID | 权限 | 值 | 属性类型 | |------|---------|--------------|-----------------------------|-----------------------| | 0 | 0x2803 | 只读 | 属性=读/指示 | 特征声明 | | | | | 句柄=1 | | | | | | UUID=0x2A37 | | | 1 | 0x2A37 | 读/指示 | 标志位 | 特征值 | | | | | 测量值 | | | 2 | 0x2902 | 读/写 | 通知状态 | 特征描述符 | | | | | 指示状态 | |

服务结构

服务的数据结构大致可分为两部分:

  1. 服务声明属性
  2. 特征定义属性

服务声明属性的UUID为0x2800,是只读的,保存着标识服务类型的UUID。例如心率服务的UUID是0x180D,其服务声明属性可表示为:

| 句柄 | UUID | 权限 | 值 | 属性类型 | |------|---------|----------|----------|----------------| | 0 | 0x2800 | 只读 | 0x180D | 服务声明 |

属性表示例

以下是一个GATT服务器可能的属性表示例,包含两个服务:心率服务和自动化IO服务。前者包含一个心率测量特征,后者包含一个LED特征。

完整属性表如下:

| 句柄 | UUID | 权限 | 值 | 属性类型 | |------|----------------------------------------|--------------|-----------------------------|-----------------------| | 0 | 0x2800 | 只读 | UUID=0x180D | 服务声明 | | 1 | 0x2803 | 只读 | 属性=读/指示 | 特征声明 | | | | | 句柄=2 | | | | | | UUID=0x2A37 | | | 2 | 0x2A37 | 读/指示 | 标志位 | 特征值 | | | | | 测量值 | | | 3 | 0x2902 | 读/写 | 通知状态 | 特征描述符 | | | | | 指示状态 | | | 4 | 0x2800 | 只读 | UUID=0x1815 | 服务声明 | | 5 | 0x2803 | 只读 | 属性=只写 | 特征声明 | | | | | 句柄=6 | | | | | | 自定义UUID | | | 6 | 自定义UUID | 只写 | LED状态 | 特征值 |

当GATT客户端首次与GATT服务器建立通信时,它会从服务器的属性表中拉取元数据以发现可用的服务和特征,这个过程称为"服务发现"。

GATT数据操作

数据操作指的是访问GATT服务器上的特征数据,主要可分为两种类型:

  1. 客户端发起的操作
  2. 服务器发起的操作

客户端发起的操作

包括以下三种类型:

  1. 读取(Read)

    • 从GATT服务器拉取特定特征的当前值
  2. 写入(Write)

    • 标准写入操作需要GATT服务器在收到客户端的写入请求和数据后确认
  3. 无响应写入(Write without response)

    • 另一种形式的写入操作,不需要服务器确认

服务器发起的操作

分为两种类型:

  1. 通知(Notify)

    • GATT服务器主动将数据推送到客户端,不需要确认响应
  2. 指示(Indicate)

    • 类似于通知,但需要客户端确认,这使得指示比通知慢

虽然通知和指示都是由服务器发起的,但这些操作的前提是客户端已启用通知或指示。因此,GATT中的数据交换过程本质上始于客户端对数据交换的请求。

实际应用建议

  1. 选择合适的UUID

    • 对于标准特征和服务,使用SIG定义的16位UUID
    • 对于自定义功能,使用128位UUID确保唯一性
  2. 权限设置

    • 根据安全需求合理设置读写权限
    • 敏感数据应设置加密要求
  3. 性能考虑

    • 频繁更新的数据使用通知(Notify)而非指示(Indicate)以提高效率
    • 关键数据使用指示(Indicate)确保可靠性
  4. 服务设计

    • 将相关特征组织在同一服务中
    • 保持属性表的逻辑清晰和结构合理

通过本文的介绍,开发者应该能够理解ESP-IDF项目中BLE数据交换的基本原理和实现方法,为开发基于BLE的应用打下坚实基础。

esp-idf Espressif IoT Development Framework. Official development framework for Espressif SoCs. esp-idf 项目地址: https://gitcode.com/gh_mirrors/es/esp-idf

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周风队

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值