做一个网站只做前端怎么做/百度ai助手入口

做一个网站只做前端怎么做,百度ai助手入口,一个人值多少钱,各大房产网站前言 蓝牙作为一个庞大的知识体系,其学习和运用对于初学者来说显得有些复杂且凌乱。我整理了这段时间的学习笔记,涵盖了协议栈、工作流程、参数等内容。在实际应用中,我们主要使用 GAP 和 GATT,协议栈中的其他部分只需了解即可。…

前言

蓝牙作为一个庞大的知识体系,其学习和运用对于初学者来说显得有些复杂且凌乱。我整理了这段时间的学习笔记,涵盖了协议栈、工作流程、参数等内容。在实际应用中,我们主要使用 GAP 和 GATT,协议栈中的其他部分只需了解即可。因此,如果只是简单使用蓝牙,只要理清逻辑,学习难度其实并不高。

希望这篇笔记能够帮助你快速入门蓝牙技术。你可以结合 ESP-IDF 提供的 gatt_server_service_tablegatt_client 示例进行学习。同时,附件中还提供了协议栈和设备工作流程的思维导图,或许通过图示化的方式能更直观地理解这些概念。

需要注意的是,笔记中的某些内容(如特征值扩展部分)可能在初级使用中用不到,可以暂时跳过。

如果发现任何错误或是提出改进建议,欢迎与我联系。

AI 摘要

这篇笔记详细介绍了蓝牙技术的核心概念和实现,包括蓝牙网络的拓扑结构(如微微网、散射网和 Mesh 网络)、蓝牙连接流程(广播、扫描、连接建立等)、以及蓝牙协议栈的分层结构(GAP 和 GATT)。文中还深入解析了 BLE 的数据传输机制、MTU 配置、广播数据格式和特性描述符等内容,并结合 ESP32 的实际开发,提供了丰富的技术细节。


参考资料:

ESP-IDF 编程指南

蓝牙技术网站

Bluetooth - Wikipedia

Bilibili-Michael_ee

Assigned Numbers

BLE User Guide — Apache Mynewt latest documentation

附件链接:

Github_CodeFlashier


文章目录

    • 前言
    • AI 摘要
    • Brief
      • The classification of Bluetooth
      • Bluetooth terminology
        • Core Architecture
        • Bluetooth Roles
        • Bluetooth Network Configuration
        • Bluetooth Connection Process
    • Bluetooth Stack
    • GAP
      • Roles when Operating over BR/EDR Physical Transport
      • Roles when Operating over an LE Physical Transport
        • Defines compliance requirements
        • Device Connection Establishment Process
    • GATT
      • Configuration and Roles
      • GATT Profile Hierarchy
      • Service
        • Service Declaration
        • Service Include
          • Include Declaration
        • Characteristic
          • Characteristic Declaration
          • Characteristic Value Declaration
          • Characteristic Descriptor Declarations
            • Characteristic Extended Properties
            • Characteristic User Description
            • Client Characteristic Configuration
            • Server Characteristic Configuration
            • Characteristic Presentation Format
            • Characteristic Aggregate Format
        • GATT Profile Attribute Types
      • GATT Send Command
    • GATT Server
      • GATT Server Work Flow
        • Advertising
        • MTU
        • PDU
      • Advertising Flow
        • Advertising State
          • Undirected Advertising
          • Directed Advertising
        • Scanning State
          • Passive Scanning
          • Active Scanning
        • Callback Parameters
        • Advertising And Scanning Response Data Format
        • gatts_table_creat_demo
    • GATT Client
      • GATT Client Work Flow
    • Connection
      • Supervision Timeout
      • Peripheral Latency
      • MTU
    • Data Exchange
      • Write Data
      • Notification for Server
      • Notification for Client


Brief

蓝牙是一种支持设备短距离通信的无线通信技术,能够实现在短距离范围内实现信息的自由分享和传输,具有安全性高、自由连接等特性,工作在 2.4GHz ISM(工业、科学、医学) 频段

蓝牙可分为经典蓝牙和低功耗蓝牙

从整体结构上,蓝⽛可分为控制器 (Controller) 和主机 (Host) 两⼤部分:控制器包括了 PHY、Baseband、Link Controller、Link Manager、Device Manager、HCI 等模块,⽤于硬件接⼝管理、链路管理等等;主机则包括了 L2CAP、SMP、SDP、ATT、GATT、GAP 以及各种规范,构建了向应⽤层提供接⼝的基础,⽅便应⽤层对蓝⽛系统的访问。主机可以与控制器运⾏在同⼀个宿主上,也可以分布在不同的宿主上。


The classification of Bluetooth

Classic Bluetooth
经典蓝牙(BR/EDR)泛指支持蓝牙协议在 4.0 以下的模块,一般用于大数据量的传输(如语音、音乐),其协议包含个人局域网的各种规范,如:

  • Advanced Audio Distribution Profile (A2DP) ​适用于音频
  • Hands-Free Profiles/Hand-Set Profiles (HFP/HSP) ​ 适用于免提设备
  • Serial Port Profiles (SPP) ​ 适用于文本串口透传(可用于蓝牙调试)
  • HFP/HSP​、HID​ 等

Bluetooth Low Energy
一种超低功耗无线通信技术,主要针对低成本、低复杂度的无线体域网和无线各域网设计
来源:Bluetooth 技术概述 |Bluetooth® 技术网站

特性低功耗蓝牙 (LE)经典蓝牙 (Bluetooth Classic)
频段2.4GHz ISM 频段 (2.402 – 2.480 GHz 使用)2.4GHz ISM 频段 (2.402 – 2.480 GHz 使用)
频道40 个频道,2 MHz 间隔(3 个广播频道/37 个数据频道)79个频道,1 MHz间隔
频道使用频率跳变扩频 (FHSS)频率跳变扩频 (FHSS)
调制方式GFSKGFSK,π/4 DQPSK,8DPSK
数据速率LE 2M PHY:2 Mb/s
LE 1M PHY:1 Mb/s
LE Coded PHY (S=2):500 Kb/s
LE Coded PHY (S=8):125 Kb/s
EDR PHY (8DPSK):3 Mb/s
EDR PHY (π/4 DQPSK):2 Mb/s
BR PHY (GFSK):1 Mb/s
发射功率≤ 100 mW (+20 dBm)≤ 100 mW (+20 dBm)
接收灵敏度LE 2M PHY:≤-70 dBm
LE 1M PHY:≤-70 dBm
LE Coded PHY (S=2):≤-75 dBm
LE Coded PHY (S=8):≤-82 dBm
≤-70 dBm
数据传输异步面向连接
同步面向连接
异步无连接
同步无连接
等时无连接
异步面向连接
同步面向连接
通信拓扑点对点(包括个人区域网络(Piconet微微网))
广播
Mesh(网状)
点对点(包括个人区域网络(Piconet 微微网))
定位功能存在:广告
方向:测向(AoA/AoD)
距离:RSSI,信道探测

Bluetooth terminology

Core Architecture

蓝牙的核心系统

  • Host 主机​ 实现各种业务场景需求,大部分的开发工作基于此
  • Controller 控制器​ 用于蓝牙报文的收发、蓝牙物理连接等功能,由芯片厂商负责实现
  • Host Controller Interface(HCI) 主机控制接口​ Host 和 Controller 通过 HIC 进行通信

Bluetooth Roles

蓝牙通信是指两个或多个蓝牙设备之间的通信,通信双方必须一个是主机,另一个是从机,从机和从机之间不能直接通信
Master​ 工作在 Master 模式的设备,可以与一个 Slave 进行连接,在此模式下可以对周围的设备进行搜索并选择需要的 Slave 进行连接
Slave​ Slave 模式下的设备只能被 Master 搜索,不能主动搜索

Bluetooth Network Configuration

根据拓扑结构,蓝牙网络可分为

  • Piconet​微微网
  • Scatternet​散射网
  • Mesh

Piconet 微微网​每次建立的蓝牙无线链路,都处于微微网中,一个微微网由两个或更多占用相同物理信道的设备组成(表示这些设备是按照共用时钟和跳频序列进行同步的),其拓扑结构如下:

                                  从机3//   //从机1 -------------------- 主机\\\\                           \从机2

拓扑结构(Topology Structure)是指系统中各个节点及其连接关系的组织方式或布局。它广泛应用于网络、工程、数学等领域,用来描述元素之间的连接模式,而不关注实际的物理位置或距离

Scatternet 散射网​如果多个网存在重叠的区域,就可以构成散射网,其中各个 Piconet仍然具有自己的主机,但一个 Piconet 的主机可以同时是另一个 Piconet 的从机,这样该设备就具有双重身份

如下图,此时左侧的主机同时也是右侧的从机

                     从机1.3              从机2.1/                 //                 //                 //                 /
从机1.1 ---------- 主机/从机 ---------- 主机\                   \\                   \\                   \\                   \从机1.2             从机2.2

Mesh​蓝牙 4.0 之后诞生了蓝牙 Mesh,用于建立多对多设备通信的低能耗蓝牙网络,允许创建基于多个设备的大型网络,可以包含数十台、数百台甚至数千台蓝牙 Mesh 设备,设备之间可以相互进行数据传输

Bluetooth Connection Process

蓝牙首先需要通过广播或扫描发现周围设备,其次创建连接,最终组建网络传输数据

  1. 从机端广播
    1. 在大部分情况下,外围设备 (Peripheral,从机) 通过广播自己来让中心设备 (Central,主机) 发现自己,并建立 GATT (通用属性配置文件)连接,从而进行更多的消息交换
      1. 也有些情况是不需要连接的,只需要外围设备(外设)广播自己的信息即可,这种方式的主要目的是让外设把自己的消息发送给多个中心设备
    2. Peripheral 在进行广播时不断发送广播包,每发送一次广播包称为广播事件;每一次发送之间有长度为 t 的广播间隔,也称为广播事件间隔,每次广播事件都会持续一段时间,只有在此期间蓝牙芯片才会打开射频模块发送广播包,功耗较高,其余时间都处于空闲待机状态
      1. 当广播事件时,每一个事件包含三个广播包,分别在 37、38、39 三个信道同事广播相同的消息
  2. 主机端扫描
    1. 扫描是在一定范围内用来寻址其他 BLE 设备的过程,扫描者在扫描过程中会使用广播信道,但扫描并没有严格的时间定义和信道规则,其过程按照主机设定的扫描定时参数进行​
      1. 被动扫描​ 扫描者仅仅监听广播包,而不向广播者发送任何数据
        1. 在扫描过程中,如果控制器接收到符合过滤策略或其他规则的的广播包, 则向主机发送一个报告时间,其中包括广播者的设备地址、广播包中的数据、信号接收强度​
      2. 主动扫描​ Central 在扫描捕获广播包的同时捕获扫描响应包,并作出区分
        1. 广播包​主要用于设备发现和提供基本信息,适合所有设备接收
        2. 扫描响应包​用于增强广播包,满足需要获取更多信息的主动扫描设备需求
  3. 主机端连接
    1. 连接过程如下
      1. Peripheral(外设,外围设备)开始广播,在发送完一个广播包的T_IFS内,开启射频窗口接收来自中心设备的数据包
      2. Central 接收到广播,在接收后的 T_IFS 内如果开启了 Central 的扫描回复,则 Central 将向 Peripheral 发送回复
      3. Peripheral 收到中心设备的回复后,做好接收准备并返回 ACK 包
      4. 如果 Peripheral 发送的 ACK 没有被中心设备接收到,则 Central 将一直发送回复知道超时为止,在此期间内只要外设返回过一次 ACK 就算连接成功
      5. 开始建立通信,Central 以接收到外设广播的时间为原点,以连接间隔为周期向 Peripheral 数据包,数据包用于同步两个设备的时钟和建立主从模式的通信,其过程如下:​
        1. 同步两个设备的时钟​ Peripheral 每收到 Central 发送的一个数据包,就会重新设置自己的书序原点,以便于 Central 同步
        2. BLE 通信在建立成功后变成主从模式,Central 变成主机模式,Peripheral 变成从机,从机只能在 Central 向它发送一个数据包后才能在规定时间内把自己的数据回传给 Central
        3. 连接建立成功
        4. 外设自动停止广播,其他设备无法再查找到此外设
        5. 在中心设备发送数据包的间隔内,外设可以发送多个数据包

T_ISF 、 ACK 和同步时钟

T_ISF(Inter Frame Space)​同一信道上连续传输包之间的时间间隔

ACK​ACK在通信中是接收方对发送方的反馈,用于确认数据包已成功接收;如果没有ACK,发送方无法知道数据是否到达目标,从而无法保障通信的可靠性

ACK机制还可检测数据错误并触发重传,确保数据传输完整无误 同步时钟同步时钟在通信中用来协调双方的时间基准,确保数据的发送与接收按预期时序进行。如果没有同步时钟,数据可能因时序错乱而丢失或解析错误。在 BLE 中,同步时钟还能优化设备能耗,让设备在需要时准确唤醒,保持高效运行


断开连接

  • 在需要断开连接时,只要 Central 停止连接(停止发送数据包)即可

重新连接

  • 中心设备可以将外设的 MAC 地址写入 Flash 或是 SRAM 等存储器件,并保持监听此 MAC 地址,当再次收到 Peripheral 发送的广播包时就可以建立通信
  • 从机为了省电,当一段时间没有数据要发送时,可以不在发送广播包,双方就会因为连接超时 (Connection Timeout) 而断开,此时需要 Central 启动监听

MAC地址(Media Access Control Address)是一个设备的唯一硬件地址,用于标识蓝牙设备。每个蓝牙设备在出厂时都会分配一个全球唯一的MAC地址,一个48位(6字节)的数字,通常用16进制表示,格式为 XX:XX:XX:XX:XX:XX,例如 A1:B2:C3:D4:E5:F6


Bluetooth Stack

蓝牙 API - ESP32 - — ESP-IDF 编程指南 latest 文档

ESP-IDF 目前支持两个主机堆栈(蓝牙协议栈),基于 Bluedroid 的堆栈(默认)支持传统蓝牙和低功耗蓝牙 (Bluetooth® LE),而基于 Apache NimBLE 的堆栈仅支持低功耗蓝牙

  • 对于同时涉及传统蓝牙和低功耗蓝牙的用例,应该选用 Bluedroid
  • 对于仅涉及低功耗蓝牙的用例,建议选用 NimBLE,在代码占用和运行时,NimBLE 对内存的要求较低,因此适用于此类场景
    有关功能支持状态,详见 docs.espressif

Bluedroid 是 Android 平台和 ESP32 上常用的蓝牙协议栈。它提供了完整的蓝牙主机和控制器功能,支持蓝牙经典(BR/EDR)和蓝牙低功耗(BLE);Bluedroid 已被广泛应用于 Android 设备和 ESP32 系统,能够通过提供标准的 HCI 接口与硬件控制器通信;Bluedroid 是一个稳定的协议栈,但由于它具有较大的代码库和相对较高的资源需求,可能不适合资源有限的嵌入式设备

Apache MyNewt NimBLE 是一个轻量级、灵活、高度可配置且符合 Bluetooth® SIG 认证的蓝牙低功耗 (Bluetooth LE) 协议栈,提供主机和控制器功能,专注于低功耗蓝牙设备的高效能实现,与 Bluedroid 不同,NimBLE 更加简化,旨在提供更好的性能和更少的内存占用,适用于嵌入式应用和低功耗设备

ESP-IDF 支持专为 ESP32 平台和 FreeRTOS 移植的 NimBLE 主机栈,底层控制器与 Bluedroid 中使用的相同,提供 VHCI 接口

ESP-IDF 支持大多数 NimBLE 特性,包括蓝牙低功耗网状网络 (Bluetooth Low Energy Mesh),通过保留 NimBLE 所有现有 API 并提供一个统一的 ESP-NimBLE API 用于初始化,移植层变得更简洁,从而简化了应用开发者的工作

在这里插入图片描述

图源:NimBLE-based Host APIs - ESP32 - — ESP-IDF 编程指南 latest 文档
BLE User Guide — Apache Mynewt latest documentation


BLE 协议栈

  • 应用层 (Application Layer)

  • 主机层 (Host Layer)

  • 控制器层 (Controller Layer)
    在这里插入图片描述

  • Controller ​用于硬件接口管理、链路管理等功能

    • Physical Layer(PHY) 物理层 ​ 指定低功耗蓝牙所用的无线频段、调制解调方式等

    • Link Layer(LL) 链路层 ​ 负责数据发送和接收,但不负责数据解析,是蓝牙协议栈的核心

  • Host Controller Interface(HCI) 主机控制接口 ​ Host 和 Controller 之间的通信接口,可以是物理形式的(UART、USB 等,常见于双芯片架构),也可以用 API 实现(常见于单芯片架构)

  • Host ​构建了向应用层提供接口的基础,方便应用层对蓝牙系统的访问

    • Logical Link Control and Adaptation Protocol(L2CAP) 逻辑链路控制和适配协议 ​ 向上层协议(协议复用、分段、重组操作)提供连接导向和无连接的数据服务,并按通道进行流量控制和重传

    • Attribute Protocol(ATT) 属性协议 ​ 用来定义用户命令以及命令操作的数据(如读取或写入);BLE 协议栈引入了 Attribute 概念,用于描述一条条的数据;ATT 除了定义数据,也定义该数据可以使用的 ATT 命令

    • Security Manager Protocol(SMP) 安全管理器协议 ​ 负责管理 BLE 连接的加密和安全,在保证连接安全的同时不影响用户的体验

    • Generic Attribute Profile(GATT) 通用属性配置文件 ​ 规范 Attribute 中的数据内容,并运用分组 (Group) 的概念对 Attribute 进行分类管理

    • Generic Access Profile(GAP) 通用访问配置文件 ​ 对 LL 的有效数据包进行了一些规范和定义,是解析 LL 负载数据最简单的一种方式,一次 GAP 的功能及其有限,主要用来进行广播、扫描和发起连接等

作为应用开发者,在开发过程中主要使用主机层提供的 API 接口

BLUEDROID 内部⼤致分为 2 层:BTU 层和 BTC 层(除去 HCI ),每个层都有对应的任务来处理。BTU 层主要负责蓝⽛主机底层协议栈的处理,包括 L2CAP、GATT/ATT、SMP、GAP 以及部分规范等,并向上提供以“bta”为前缀的接⼝; BTC 层主要负责向应⽤层提供接⼝⽀持、处理基于 GATT 的规范、处理杂项等,并向应⽤ 层提供以“esp”为前缀的接⼝。所有的 API 都在 ESP_API 层,开发者应当使⽤“esp”为前缀的蓝⽛ API(特殊的除外)。


蓝牙核心规范 (Core Specification) 允许主机层和控制器层在物理上分离,此时 HCI 体现为物理接口,包括 SDIO、USB 以及 UART 等
在这里插入图片描述

图源:esp32_bluetooth_architecture_cn

通过软硬件分层的设计,底层不变,可以方便的切换上层程序(应用层软件)

场景一(ESP-IDF 默认)
在 ESP32 的系统上,选择 Bluedroid 为蓝牙主机,并通过 VHCI(软件实现的虚拟 HCI 接口)接口,访问控制器。此场景下,Bluedroid 和控制器都运行在同一宿主上(即 ESP32 芯片),不需要额外连接运行蓝牙主机的 PC 或其它主机设备

场景二
在 ESP32 上运行控制器(此时设备将单纯作为蓝牙控制器使用),外接一个运行蓝牙主机的设备(如运行 BlueZ 的 Linux PC、运行 Bluedroid 的 Android 等)

此场景下,控制器和主机运行在不同宿主上,与手机、PAD、PC 的使用方式比较类似

场景三
此场景与场景二类似,特别之处在于,在 BQB(或其它认证)的控制器测试下,可以将 ESP32 作为 DUT(Device Under Test),用 UART 作为 IO 接口,接上认证测试的 PC 机,即可完成认证

在这里插入图片描述

IDF 中的 host、controller 目录,其中存放有不同芯片型号相应的库文件及接口等

路径:idf 安装路径\v5.3.1\esp-idf\components\bt


ESP-IDF 的 component/bt/host/bluedroid 目录说明

子文件夹说明
apiAPI 目录,所有的 API(除 Controller 相关)都在此目录下
bta蓝牙适配层,适配一些主机层底层协议的接口
btc蓝牙控制层,控制主机上层协议(包括规范)以及杂项的处理
common协议栈的通用头文件
config为协议栈配置一些参数
device与蓝牙设备控制相关的,如控制器设备的配置的 HCI CMD 流程等
external与蓝牙自身无关,但又要使用的代码,如 SBC codec 设备程序等
hciHCI 层协议
Kconfig.inMenuconfig 文件
main主程序目录(主要为启动、关闭流程)
stack主机底层协议栈(GAP/ATT/GATT/SDP/SMP 等)

GAP

蓝牙协议栈中 GAP 和 GATT 部分各知识点之间联系

在这里插入图片描述

原图较大,由于网站压缩,图像画质可能较差,原图见Github_CodeFlashier

本部分的全部内容详见: Bluetooth Core Specification v5.0 Vol3 PartC,这里只做必要内容的介绍

通用访问配置文件(Generic Access Profile,GAP)的目的如下:

  1. 引入与运输和应用配置文件使用的模式和访问程序相关的定义、建议和通用要求
  2. 描述设备在待机和连接状态下的行为,以保证蓝牙设备之间始终能够建立连接和通道,并且支持多配置文件操作;特别关注设备发现、链路建立和安全程序
  3. 规定用户界面方面的要求,主要是编码方案和过程与参数的命名,以确保用户体验

该配置文件的目的是描述:

  • 配置文件角色
  • 可发现模式和程序
  • 连接模式和程序
  • 安全模式和程序

在这里插入图片描述

GAP 与蓝牙底层架构的关系

图源:Bluetooth Core Specification v5.0


Roles when Operating over BR/EDR Physical Transport

BR/EDRBluetooth Radio/Enhanced Data Rate 的缩写,指的是蓝牙技术中的两种主要通信模式:

  • BR (Basic Rate)​基本速率,是蓝牙 1.x 版本中使用的传输速率,最高为 1 Mbps​
  • EDR (Enhanced Data Rate)​增强数据传输速率,是蓝牙 2.x 版本及更高版本中引入的,提供更高的传输速率,最高为 3 Mbps

BR/EDR 是蓝牙经典(Bluetooth Classic)模式的一部分,适用于需要较高数据传输速率的应用,如音频传输(例如蓝牙耳机)和文件传输

在 GAP 协议中,为了描述发生在 BR/EDR GAP 角色的两个设备之间的蓝牙通信,使用以下两个通用符号描述设备:

  • A-party A 方 链路建立时的分页设备(发起连接请求的设备)
  • B-party B 方 ​接收连接请求的设备

在蓝牙的 GAP 协议中,“分页设备”(paging device)是指在进行蓝牙设备配对或连接时,发起连接请求的设备;分页设备通过广播其存在来寻找其他设备,并尝试建立一个连接

具体而言,“分页”(paging)指的是一种低功耗的搜索过程,设备会扫描特定的信道,并等待另一方设备响应以建立连接

在这里插入图片描述

该配置文件涵盖了由一个设备(A)发起,针对另一个设备(B)的程序,后者可能已经建立了蓝牙连接,也可能没有

图源:《Bluetooth Core Specification v5.0》

发起者和接受者通常根据此配置文件或引用此配置文件的其他配置文件执行通用程序;如果接受者同时根据多个配置文件操作,则此配置文件提供了处理这种情况的通用机制


Roles when Operating over an LE Physical Transport

LE 指的是 Bluetooth Low Energy(蓝牙低功耗)技术

GAP 中共定义了三种设备的连接状态以及五种不同的设备角色,如下

  • 空闲 (Idle)
    • 此时设备无角色,处于就绪状态 (Standby)
  • 设备发现 (Device Discovery)
    • 广播者 (Advertiser)
    • 扫描者 (Scanner)
    • 连接发起者 (Initiator)
  • 连接 (Connection)
    • 外围设备 (Peripheral)
    • 中央设备 (Central)

Bluetooth LE GAP 协议层采⽤ API 调⽤和事件 (Event) 返回的设计模式,通过事件返回来获取 API 在协议栈的处理结果。当对端设备主动发起请求时,也是通过事件返回获取对端设备的状态。Bluetooth LE 设备定义了四类 GAP ⻆⾊:
• ⼴播者 (Broadcaster):处于这种⻆⾊的设备通过发送⼴播 (Advertising) 让接收者发现⾃⼰。这种⻆⾊只能发⼴播,不能被连接。
• 观察者 (Observer):处于这种⻆⾊的设备通过接收⼴播事件并发送扫描 (Scan) 请求。这种⻆⾊只能发送扫描请求,不能被连接。
• 外围设备 (Peripheral):当⼴播者接受了观察者发来的连接请求后就会进⼊这种⻆ ⾊。当设备进⼊了这种⻆⾊之后,将会作为从设备 (Slave) 在链路中进⾏通信。
• 中央设备 (Central):当观察者主动进⾏初始化,并建⽴⼀个物理链路时就会进⼊这种⻆⾊。这种⻆⾊在链路中同样被称为主设备 (Master)。

在这里插入图片描述


同时在多个 GAP 角色下运行
如果控制器支持,设备可以同时在多个GAP角色下运行,主机应在使用任何程序或模式之前,先读取控制器支持的链路层状态和状态组合


Defines compliance requirements

在这里插入图片描述
在这里插入图片描述

在 LE 物理传输上操作时,每个 GAP 角色的物理层和链路层功能的 GAP 遵从性要求

图源:Bluetooth Core Specification v5.0

符号释义

  • M​强制支持的功能
  • O​可选支持的功能
  • C​条件支持的功能
  • E​在配置文件角色中排除的功能
  • N/A​不适用的功能
  • C1​如果支持被动扫描,则主动扫描是可选的,否则主动扫描是强制的
  • C2​如果支持连接参数请求过程,则必选,否则可选

Device Connection Establishment Process

设备连接过程

Sending data
Return data
A
Standby
Advertising
waiting
Connection
B
Standby
Scanning
Initiation
Connection
  1. 设备 A、B 进入空闲状态
  2. 在上层软件控制下,A 进入广播状态,向外界进入广播状态,B 进入扫描状态
  3. 当 B 扫描到数据后,进入初始化状态,发送请求连接的数据给 A
  4. 设备 A 返回数据给 B,进入连接状态
  5. B 收到返回的数据后,进入连接状态
  6. 两个设备相互交换数据

对于部分设备,可能不需要连接(如 BLE Beacon、BLE Sniffer)


GATT

蓝牙协议栈中 GAP 和 GATT 部分各知识点之间联系

在这里插入图片描述

原图较大由于网站压缩,图像画质可能较差,原图见Github_CodeFlashier

本部分的全部内容详见: Bluetooth Core Specification v5.0 Vol3 PartD,这里只做必要内容的介绍

通用属性配置文件(Generic Attribute Profile,GATT)通过使用属性协议(Attribute Protocol)定义了一个服务框架,该框架定义了服务及其特性的程序和格式,所定义的程序包括发现、读取、写入、通知和指示特性,以及配置特性广播

ATT 属性协议规定了在 Bluetooth LE 中的最⼩数据存储单位,⽽ GATT 规范则定义了如何 ⽤特性值和描述符表示⼀个数据,如何把相似的数据聚合成服务 (Service),以及如何发现对端设备拥有哪些服务和数据。

ATT 与 GATT 的关系

ATT 提供了一个基础的传输框架和操作机制(例如,读取、写入和通知),而 GATT 则是 ATT 的上层协议,定义了如何组织这些属性,使得设备能够通过结构化的方式进行通信

  • GATT 提供了一套服务(services)和特征(characteristics)的规范,指导如何通过 ATT 协议进行数据交换
  • GATT 使用 ATT 协议的读、写和通知操作来访问设备的属性

ATT 是 GATT 的数据传输载体,而 GATT 是 ATT 的应用框架,二者结合为蓝牙低功耗设备的通信提供了完整的协议支持


Configuration and Roles

GATT 将蓝牙设备分为两种:

  • Client 客户端发起命令和请求的设备,向服务器发送命令并接收服务器发送的响应、指示和通知
  • Server 服务端接受来自客户端的命令和请求的设备,并向客户端发送响应、指示和通知
  • 这些角色不是固定分配给设备的,角色是在设备发起定义的程序时确定的,并在程序结束时释放

此配置文件涵盖以下场景:

  • 配置交换
  • 设备上服务和特性的发现
  • 读取特性值
  • 写入特性值
  • 特性值通知
  • 特性值指示

数据以 profile(配置文件(规范))的形式存储在服务端

GATT 配置文件指定了配置文件数据交换的结构,该结构定义了配置文件中使用的基本元素,如服务(Service)和特性(Characteristic);所有这些元素都包含在属性中,属性协议中使用的属性是承载配置文件数据的容器

层次结构的顶层是配置文件,配置文件由一个或多个服务组成,这些服务是为了实现某个使用场景所必需的,一个服务由特性或对其他服务的引用组成;每个特性包含一个值,并且可能包含关于该值的可选信息


GATT Profile Hierarchy

GATT 配置文件的基本结构如下

  1. Profile 配置文件(规范) ​配置文件(规范)是最高层次,通常由一个或多个服务组成,它定义了完成某个特定使用场景所必需的所有元素
  2. Service 服务服务由一个或多个特性组成,并且可能包含对其他服务的引用; 服务是一个逻辑集合,用于组织和管理特性;在 GATT 配置文件中,服务是为了满足特定功能需求而设计的
  3. Characteristic 特性​特性是服务的基本组成部分,每个特性通常包含一个值,并且可能包含与该值相关的描述符(如用户描述符、客户端配置描述符等);这些特性承载着实际的配置文件数据
  4. Descriptor 描述符 ​描述符是与特性相关的附加信息,用于进一步解释特性的值或控制特性的行为,常见的描述符包括用户描述符、客户端配置描述符等

规范是一个预定义的服务集合,实现了某规范中所定义的所有服务的设备即满足该规范。例如 Heart Rate Profile 规范由 Heart Rate Service 和 Device Information Service 两个服务组成,那么可以称实现了 Heart Rate Service 和 Device Information Service 服务的设备符合 Heart Rate Profile 规范

在这里插入图片描述

GATT Profile 文件层次结构

图源:《Bluetooth Core Specification v5.0》


Service

在这里插入图片描述

Server 服务是一组数据和相关行为的集合,用于实现特定的功能或特性,在 GATT 中,服务由其服务定义(service definition)来定义

服务定义可以包含

  • 引用的服务
  • 必需的特性
  • 可选的特性

为了保持与早期客户端的向后兼容,服务定义的后续版本只能添加新的引用服务或可选特性,不能修改以前版本中的行为

  • Primary Service 主服务​是暴露设备主要功能的服务,主服务可以被其他服务包含,并且可以通过主服务发现程序进行发现
  • Secondary Service 次服务仅用于从主服务、另一个次服务或其他更高层规范中引用,次服务只在引用它的实体的上下文中相关

是否将一个服务定义为主服务或次服务,可能由更高层的规范进行规定,服务可以在一个或多个更高层的规范中使用,以实现特定的使用场景


Service 数据结构

  • Service Declaration
  • Service Include
  • Characteristic 01
  • Characteristic xx

特点

  • 服务定义在下一个服务声明之前结束,或者在达到最大属性句柄时结束;服务定义在服务器上按属性句柄的顺序出现
  • 服务定义必须包含一个服务声明(Service Declaration),并且可以包含包含定义和特性定义
  • 服务定义中包含的所有包含定义和特性定义都视为服务的一部分,所有包含定义必须紧跟在服务声明之后,并且在任何特性定义之前
  • 所有特性定义必须紧跟在最后一个包含定义之后,如果没有包含定义,则紧跟在服务声明之后
  • 一个服务定义可以有零个或多个包含定义和特性定义,包含定义和特性定义没有上限
  • 服务器上的所有属性要么包含服务声明,要么存在于服务定义内
  • 服务器中包含的服务定义可以按任意顺序出现,客户端不应假设服务器上服务定义的顺序

所有的定义均以属性 Attribute (ATT 属性协议)的形式存在,内容包括

  1. Attribute Handle 属性句柄​ 2 Octets
  2. Attribute Type 属性类型​ 2 or 16 Octets
  3. Attribute Value 属性值​ variable length
  4. Attribute Permissions 属性权限​ implementation specific(工具自定义)

‍属性的类型由 UUID 表示,可以分为 16 位、32 位与 128 位 UUID 三类。 16 位 UUID 由蓝牙技术联盟 (Bluetooth Special Interest Group, Bluetooth SIG) 统一定义,可以在其公开发布的 Assigned Numbers 文件中查询;其他两种长度的 UUID 用于表示厂商自定义的属性类型,其中 128 位 UUID 较为常用


Service Declaration

服务声明是一个属性(Attribute),

  • Attribute Type 属性类型​设置为 Primary Service 主服务 或 Secondary Service 次服务 的 UUID
  • Attribute Value 属性值 ​应为服务的 16 位或 128 位 UUID(参见 Assigned_Numbers.pdf),称为服务 UUID,客户端必须支持 16 位和 128 位 UUID 的使用,客户端可以忽略任何具有未知服务 UUID 的服务定义(未知服务 UUID 是指不支持的服务的 UUID)
    • SIG 定义的 16 位 UUID
    • 厂商自定义的 128 位 UUID (在 SIG 官方提供的 Assigned Numbers 标准文件中,给出了一些常用特征数据和服务的 UUID)
  • Attribute Permission 属性权限​应为只读,并且不要求身份验证或授权

UUID(通用唯一标识符) 是一种 128 位的标识符,广泛用于标识不同的对象、服务或数据元素,确保它们在全球范围内的唯一性

在蓝牙技术中,UUID 被用于区分和标识不同的服务、特性和描述符

UUID 可以是 16 位或 128 位格式,其中 16 位 UUID 常用于标准服务,而 128 位 UUID 通常用于自定义服务,UUID 的使用确保了设备间的兼容性和通信的准确性

Bluetooth UUID 是一种特定于蓝牙协议的 UUID,用于标识蓝牙设备中的服务、特性和描述符。与通用的 UUID(通用唯一标识符)相比,Bluetooth UUID 通常采用 16 位32 位128 位 格式,其中 16 位 UUID 用于标准蓝牙服务

规范-分配的编号-蓝牙®技术网站

在这里插入图片描述

服务声明结构

图源:《Bluetooth Core Specification v5.0》

当存在多个服务时,使用不同位数 UUID 的服务定义应当分组在一起(使用 16 位 Bluetooth UUID 的服务定义分组在一起(即按顺序列出),使用 128 位 UUID 的服务定义分组在一起)

一个设备或更高层规范可以有多个服务定义,且可以有多个服务定义使用相同的服务 UUID


Service Include

包含服务是一种将服务器上存在的另一个服务定义引用到当前定义的服务中的方法
要包含另一个服务,在服务定义的开始部分使用包含定义(include definition)

特点

  • 通过包含定义引用的服务的整个服务定义将成为新服务定义的一部分,这包括所有包含的服务和该服务的特性
  • 被包含的服务仍然是独立的服务
  • 一个被包含的服务不应因包含或包含的服务而被修改,服务定义中对包含定义或嵌套包含的数量没有限制

Include Declaration

一个 包含定义(include definition) 应仅包含一个包含声明(include declaration)

  • Attribute Type​ 设置为 Include 的 UUID
  • Attribute Value
    • 包含服务的属性句柄
    • 结束组句柄(每个服务或服务的一部分都有一个 开始句柄(Start Handle,即 Attribute Handle) 和 结束句柄(End Handle),它们定义了服务的范围)
    • 所包含服务的 UUID
    • Attribute Permission ​ 应为只读,并且不要求身份验证或授权

在这里插入图片描述

包含声明结构

图源:《Bluetooth Core Specification v5.0》


当 UUID 是 16 位 Bluetooth UUID 时,服务 UUID 必须被直接指定

GATT(Generic Attribute Profile) 中,当一个服务使用 16 位 Bluetooth UUID 时,服务 UUID 必须在服务的定义中明确指定

在某些情况下,如某些包含(Include)服务,UUID 可能通过引用的其他服务的 Attribute Handle 来隐式获得,但这并不等同于“未指定”UUID

服务定义中的包含声明不能指向自己,这适用于包含定义引用的每个服务(这被称为 循环引用(circular reference));如果客户端检测到循环引用或检测到嵌套包含声明超过其预期的层次,客户端应终止 ATT 承载通道(ATT Bearer)


Characteristic

Characteristic 特性是服务中使用的值,伴随有关于如何访问该值的属性和配置信息,以及关于如何显示或表示该值的信息

一个特性定义(Characteristic Definition)应包含

  • 特性声明(Characteristic Declaration)
  • 特性值声明(Characteristic Value Declaration)

并且可能包含

  • 特性描述符声明(Characteristic Descriptor Declarations)

特点

  • 特性值声明应紧随其后放置在特性声明之后,任何可选的特性描述符声明应放置在特性值声明之后,可选的特性描述符声明的顺序没有限制
  • 特性定义的结束位置是下一个特性声明、服务声明的开始,或者是最大 Attribute Handle,特性定义在服务器的服务定义中按 Attribute Handle 顺序出现
  • 特性定义可以通过将多个特性值合并为一个单独的聚合特性值来进行定义,这可以用于通过读取和写入单个聚合特性值来优化多个特性值的读取和写入;这类特性定义与普通的特性定义相同,特性声明应使用唯一的特性 UUID 来标识该聚合特性定义;聚合特性定义还可以包含一个特性聚合格式描述符,用于描述聚合特性值的显示格式

Characteristic Declaration

一个 特性声明(Characteristic Declaration) 是一个 Attribute

  • Attribute Type​ 设置为特性的 UUID
  • Attribute Value
    • 特性属性(Characteristic Properties)
    • 特性值属性句柄(Characteristic Value Attribute Handle)
    • 特性 UUID
    • Attribute Permission​ 应为可读,并且不要求身份验证或授权

特性声明的 Attribute Value 在服务器与任何客户端建立信任关系时不得更改

在这里插入图片描述

特征声明结构

图源:《Bluetooth Core Specification v5.0》


Attribute Value

Attribute ValueSizeDescription
Characteristic Properties1 octets(1 个 8 位数据)特性属性的位域
Characteristic Value Handle2 octets包含此特性值的属性的句柄
Characteristic UUID2 or 16 octets16 位 Bluetooth UUID 或 128 位 UUID,用于特性值

一个服务可以有多个具有相同特征 UUID特征定义

在服务定义中,某些特征可能是必需的,这些特性应位于包含声明(include declarations)之后、任何可选特性之前

客户端不应假设服务定义中必需特性或可选特性的顺序

尽可能地,并且在前述要求范围内,使用 16 位 Bluetooth UUID 的特性声明应当按顺序分组在一起(即按顺序列出),而使用 128 位 UUID 的特性声明应当分组在一起


Characteristic Properties
特性属性位域(Characteristic Properties)决定了特性值如何使用,或者如何访问特性描述符,可以设置多个 特性属性

这些位应根据该特性所允许的程序进行设置,并由更高层规范定义,而不考虑安全要求

PropertiesValue描述
Broadcast0x01如果设置,则允许使用服务器特性配置描述符广播特性值
如果设置,必须存在服务器特性配置描述符
Read0x02如果设置,则允许使用第 4.8 节中定义的程序读取特性值
Write Without Response0x04如果设置,则允许使用第 4.9.1 节中定义的程序写入特性值且不要求响应
Write0x08如果设置,则允许使用第 4.9.3 或第 4.9.4 节中定义的程序写入特性值并要求响应
Notify0x10如果设置,则允许在没有确认的情况下使用第 4.10 节中定义的程序通知特性值
如果设置,则必须存在客户端特性配置描述符
Indicate0x20如果设置,则允许在有确认的情况下使用第 4.11 节中定义的程序指示特性值
如果设置,则必须存在客户端特性配置描述符
Authenticated Signed Writes0x40如果设置,则允许使用第 4.9.2 节中定义的程序向特性值写入签名
Extended Properties0x80如果设置,则在第 3.3.3.1 节中定义的特性扩展属性描述符中定义附加特性属性
如果设置,则必须存在特性扩展属性描述符

见《Bluetooth Core Specification v5.0》 P2236

Characteristic Value Handle
特性值属性句柄字段(Characteristic Value Attribute Handle) 是指包含特性值(Characteristic Value) 的属性的属性句柄(Attribute Handle)

Characteristic UUID
特性 UUID 字段 是一个 16 位 Bluetooth UUID 或 128 位 UUID,用于描述特性值(Characteristic Value) 的类型。客户端必须支持使用 16 位 和 128 位 特性 UUID

如果客户端遇到一个具有未知 特性 UUID 的特性定义(不支持的特性所使用的 UUID),可以忽略该特性


Characteristic Value Declaration

特性值声明(Characteristic Value Declaration) 包含特性值,它是特性声明之后的第一个属性,所有特性定义必须具有特性值声明

特性值声明是一个 Attribute

  • Attribute Type​ 设置为在特性声明中使用的 16 位 Bluetooth UUID 或 128 位 UUID,用于标识特性值
  • Attribute Value​ 设置为特性值
  • Attribute Permissions​ 由服务指定,或者如果没有特别指定,则可以由实现决定

ESP32 IDF ⾥⾯规定 MTU 可以设置的范围是 23~517 字节,对属性值的总⻓度没有做限制

在这里插入图片描述

特征值声明结构

图源:《Bluetooth Core Specification v5.0》


Characteristic Descriptor Declarations

特性描述符(Characteristic Descriptors)用于包含与特性值(Characteristic Value)相关的信息
GATT 配置文件定义了一组标准的特性描述符,可以供更高层配置文件使用,更高层的配置文件可能会定义额外的特性描述符,这些描述符是特定于该配置文件的

每个特性描述符由特性描述符 UUID 标识,客户端必须支持使用 16 位 和 128 位 特性描述符 UUID;如果客户端遇到一个具有未知特性描述符 UUID 的特性描述符声明,可以忽略该描述符

如果特性描述符存在于特性定义中,它们应跟随特性值声明之后特性描述符声明可以按任意顺序出现在特性定义中,客户端不应假设特性描述符声明在特性值声明之后的顺序

特性描述符声明的权限由更高层的配置文件定义,或者如果未指定,则由实现决定

客户端不应假设所有的特性描述符声明都是可读的


Characteristic Extended Properties

特性扩展属性(Characteristic Extended Properties)声明是一个描述符,用于定义附加的特性属性;如果特性属性中的扩展属性位被设置,则该特性描述符必须存在

在一个特性定义中只能有一个特性扩展属性声明

特性描述符包含在一个 Attribute 中

  • Attribute Type​ 应设置为 “特性扩展属性(Characteristic Extended Properties)” 的 UUID
  • Attribute Value​ 应设置为特性扩展属性位域(Characteristic Extended Properties Bit Field)
  • Attribute Permissions ​ 应为可读,不需要身份验证和授权

在这里插入图片描述

特征扩展属性结构

图源:《Bluetooth Core Specification v5.0》

特性扩展属性位域描述了如何使用特性值(Characteristic Value) 或如何访问特性描述符
如果表中定义的位被设置,则表示允许执行相应的操作;可以设置多个 特性属性

PropertiesValueDescription
Reliable Write0x0001如果设置,则允许使用第 4.9.5 节中定义的程序进行可靠的特性值写入
Writable Auxiliaries0x0002如果设置,则允许写入第 3.3.3.2 节中定义的特性描述符
Reserved for Future Use0xFFFC保留供未来使用

Characteristic User Description

特性用户描述(Characteristic User Description) 声明是一个可选的特性描述符,用于定义一个可变大小的 UTF-8 字符串,它是对特性值(Characteristic Value) 的用户文本描述;如果特性属性(Characteristic Properties) 中的可写辅助位(Writable Auxiliary) 被设置,则该特性描述符可以被写入

在一个特性定义中只能有一个特性用户描述声明

特性描述符包含在一个 Attribute 中

  • Attribute Type​ 应设置为 “特性用户描述(Characteristic User Description)” 的 UUID
  • Attribute Value​ 应设置为特性用户描述的 UTF-8 字符串
  • Attribute Permissions​ 由配置文件指定,或者如果未特别指定,则可以由实现决定

在这里插入图片描述

特征用户描述结构

图源:《Bluetooth Core Specification v5.0》


Client Characteristic Configuration

客户端特性配置(Client Characteristic Configuration) 声明是一个可选的特性描述符,用于定义特性如何由特定客户端进行配置

客户端特性配置描述符的值应在已配对设备之间的连接中保持持久性;在与非配对设备的每次连接中,客户端特性配置描述符的值应设置为默认值

该特性描述符值是一个 位域(bit field),当某个位被设置时,相应的操作将被启用,否则将不使用

在一个特性定义中只能有一个客户端特性配置声明

客户端可以写入此配置描述符来控制服务器上该特性的配置,每个客户端都有自己独立的客户端特性配置 实例,读取客户端特性配置仅显示该客户端的配置,写入仅影响该客户端的配置

写入配置描述符时,服务器可能需要身份验证和授权

客户端特性配置声明应为可读和可写,该特性描述符包含在一个 Attribute 中

  • Attribute Type​ 应设置为 “客户端特性配置(Client Characteristic Configuration)” 的 UUID
  • Attribute Value​ 应设置为特性描述符值
  • Attribute Permissions​ 由配置文件指定,或如果未特别指定,则可以由实现决定

在这里插入图片描述

客户端特性配置结构

图源:《Bluetooth Core Specification v5.0》


客户端特性配置位定义

ConfigurationValueDescription
Notification0x0001特性值将被通知。只有在特性属性设置了通知位时,此值才可以设置
Indication0x0002特性值将被指示。只有在特性属性设置了指示位时,此值才可以设置
Reserved for Future Use0xFFFC保留供未来使用
  • 客户端特性配置描述符值 的默认值应为 0x0000
  • 如果 GATT 服务器 支持来自同一设备的多个 ATT 承载通道(ATT bearers),则每个 ATT 承载通道应视为具有独立的 GATT 客户端实例,因此,每个 GATT 客户端应拥有独立的 客户端特性配置

Notification 通知​是一种无确认的数据传输方式,服务器发送数据后无需等待客户端的响应;这使得通知在需要高效、频繁更新数据的场景中非常适用,但不能保证数据已经被客户端成功接收

Indication 指示​则是一种有确认的传输方式,服务器发送数据后会等待客户端的确认响应;这确保了客户端已经成功接收数据,因此适用于那些需要可靠传输和确保数据到达的场景,但相较通知,指示会增加一定的延迟和开销


Server Characteristic Configuration

服务器特性配置(Server Characteristic Configuration) 声明是一个可选的特性描述符,用于定义如何为服务器配置特性

特性描述符值是一个 位域(bit field),当某个位被设置时,相应的操作将被启用,否则将不使用

在一个特性定义中只能有一个服务器特性配置声明

服务器特性配置声明应为可读和可写,客户端可以写入该配置描述符来控制服务器上所有客户端的特性配置;对于所有客户端来说,服务器特性配置是单一实例,读取服务器特性配置显示的是所有客户端的配置,而写入则会影响所有客户端的配置

服务器可能需要身份验证和授权才能写入配置描述符

该特性描述符包含在一个 Attribute 中

  • Attribute Type​ 应设置为 “服务器特性配置(Server Characteristic Configuration)” 的 UUID
  • Attribute Value​ 应设置为特性描述符值
  • Attribute Permissions​ 由配置文件指定,或者如果没有特别指定,则可以由实现决定

在这里插入图片描述

服务器特性配置结构

图源:《Bluetooth Core Specification v5.0》


服务器特性配置位定义

ConfigurationValue描述
Broadcast0x0001当服务器处于广播过程并且广告数据资源可用时,特性值将被广播
只有在特性属性设置了广播位时,此值才可以设置
Reserved for Future Use0xFFFE保留供未来使用

Characteristic Presentation Format

特性展示格式(Characteristic Presentation Format) 声明是一个可选的特性描述符,用于定义特性值(Characteristic Value) 的格式,即如何解析特征值

如果一个特性定义中存在多个特性展示格式声明(Characteristic Presentation Format declarations),则必须存在特性聚合格式声明(Characteristic Aggregate Format declaration) 作为该特性定义的一部分

特性格式值由五个部分组成:

  • 格式(format)
  • 指数(exponent)
  • 单位(unit)
  • 命名空间(name space)
  • 描述(description)

该特性描述符包含在一个Attribute 中

  • Attribute Type​ 应设置为 “特性格式(Characteristic Format)” 的 UUID
  • Attribute Value​ 应设置为特性描述符值
  • Attribute Permissions​ 应为只读,并且不需要身份验证或授权

在这里插入图片描述

特征展示格式属性结构

图源:《Bluetooth Core Specification v5.0》


特性展示格式描述符属性值字段的定义

Field NameValue SizeDescription
Format1 octet该特性值的格式
Exponent1 octet指数字段,用于确定该特性值如何进一步格式化
Unit2 octets该特性的单位,如在《Assigned Number Specification》中定义
Name Space1 octet描述的命名空间,如在《Assigned Number Specification》中定义
Description2 octets该特性的描述,如在更高层配置文件中定义

位序
Characteristic Format descriptor 使用的位序应该是 小端序(little-endian)(低位字节存储在低地址,而高位字节存储在 高地址,即数据的 最低有效字节(LSB) 放在最前面)


格式
格式(Format) 字段决定了 特性值(Characteristic Value) 中单个值的格式

如果格式不是一个完整的字节数,则数据应以能够容纳该值的最小字节数进行存储;数据应占用每个字节的全部内容,除了最后一个字节的最高有效位;最后一个字节的其他位应预留供未来使用

带符号整数应使用二进制补码表示法(two’s-complement representation)

定义的格式值

FormatShort NameDescriptionExponent Value
0x00rfuReserved for Future UseNo
0x01booleanunsigned 1-bit; 0 = false, 1 = trueNo
0x022bitunsigned 2-bit integerNo
0x03nibbleunsigned 4-bit integerNo
0x04uint8unsigned 8-bit integerYes
0x05uint12unsigned 12-bit integerYes
0x06uint16unsigned 16-bit integerYes
0x07uint24unsigned 24-bit integerYes
0x08uint32unsigned 32-bit integerYes
0x09uint48unsigned 48-bit integerYes
0x0Auint64unsigned 64-bit integerYes
0x0Buint128unsigned 128-bit integerYes
0x0Csint8signed 8-bit integerYes
0x0Dsint12signed 12-bit integerYes
0x0Esint16signed 16-bit integerYes
0x0Fsint24signed 24-bit integerYes
0x10sint32signed 32-bit integerYes
0x11sint48signed 48-bit integerYes
0x12sint64signed 64-bit integerYes
0x13sint128signed 128-bit integerYes
0x14float32IEEE-754 32-bit floating pointNo
0x15float64IEEE-754 64-bit floating pointNo
0x16SFLOATIEEE-11073 16-bit SFLOATNo
0x17FLOATIEEE-11073 32-bit FLOATNo
0x18duint16IEEE-20601 formatNo
0x19utf8sUTF-8 stringNo
0x1Autf16sUTF-16 stringNo
0x1BstructOpaque structureNo
0x1C – 0xFFrfuReserved for Future UseNo
  • 当编码 IPv4 地址 时,应使用 uint32 格式类型
  • 当编码 IPv6 地址 时,应使用 uint128 格式类型
  • 当编码 蓝牙 BD_ADDR 时,应使用 uint48 格式类型
  • duint16 是由两个 uint16 值连接在一起组成的

Exponent
指数(Exponent) 字段与整数数据类型一起使用,用于确定值如何进一步格式化
指数字段仅在 格式字段(format field) 中指定为整数格式类型时使用,是二进制补码有符号整数
实际值 = 特性值 × 1 0 指数 \text{实际值} = \text{特性值} \times 10^{\text{指数}} 实际值=特性值×10指数
实际值是特性值10指数(Exponent) 次方的组合


Unit
单位(Unit) 是一个 UUID,如在 分配编号文档(Assigned Numbers document) 中定义


Name Space
命名空间(Name Space) 字段用于标识 负责定义描述字段枚举值的组织,该组织在分配编号文档中有定义


Description
描述(Description) 是一个枚举值,如在 分配编号文档(Assigned Numbers document)中定义,来自 命名空间字段(Name Space) 中标识的组织


Characteristic Aggregate Format

特性聚合格式(Characteristic Aggregate Format) 声明是一个可选的特性描述符,用于定义聚合的特性值(Characteristic Value) 的格式

在一个特性定义中只能有一个特性聚合格式声明

特性聚合格式值由特性展示格式声明(Characteristic Presentation Format declarations) 的属性句柄列表(Attribute Handles) 组成,每个属性句柄指向一个特性展示格式声明,Attribute Permissions 应为只读,并且不需要身份验证或授权

属性句柄列表是多个 16 位属性句柄(Attribute Handle) 值连接成一个 Attribute Value,该列表至少应包含两个特性展示格式声明(Characteristic Presentation Format declarations) 的属性句柄

特性值应根据每个由属性句柄指向的特性展示格式声明进行解构,列表中属性句柄的顺序是有意义的

如果在一个特性定义中存在多个特性展示格式声明,则必须有一个特性聚合格式声明;该声明应在属性句柄列表中包含特性定义中的每个特性展示格式声明;其他特性定义中的特性展示格式声明也可以被使用

在这里插入图片描述

特性聚合格式属性结构

图源:《Bluetooth Core Specification v5.0》


GATT Profile Attribute Types
Attribute TypeUUIDDescription
Primary Service0x2800Primary Service Declaration
Secondary Service0x2801Secondary Service Declaration
Include0x2802Include Declaration
Characteristic0x2803Characteristic Declaration
Characteristic Extended Properties0x2900Characteristic Extended Properties
Characteristic User Description0x2901Characteristic User Description Descriptor
Client Characteristic Configuration0x2902Client Characteristic Configuration Descriptor
Server Characteristic Configuration0x2903Server Characteristic Configuration Descriptor
Characteristic Format0x2904Characteristic Format Descriptor
Characteristic Aggregate Format0x2905Characteristic Aggregate Format Descriptor

GATT Send Command

在这里插入图片描述

命令代码 + 输入参数 + 授权


GATT Server

BLE 通信中 Server 和 Client 工作流程图解

在这里插入图片描述

原图较大由于网站压缩,图像画质可能较差,原图见Github_CodeFlashier

我们把存有数据(即属性)的设备叫做服务器 (Server),⽽将获取别⼈设备数据的设备叫做客户端 (Client)


GAP与GATT的关系

维度GAPGATT
层级控制层(决定设备可见性和连接方式)数据层(定义连接后的数据传输规则)
工作阶段连接前(广播、发现、配对)连接后(数据读写、服务交互)
依赖关系GATT依赖GAP建立的连接GAP为GATT提供通信基础
典型应用设备配对、广播信息传感器数据读取、设备控制

GATT Server Work Flow

此过程指的是初始化和启动 GATT 服务器所涉及的步骤,其中包括设置GATT服务、特征和描述符等任务,并使服务器准备好处理来自 GATT 客户端的请求

init
flash
controller
bluedriod
app_main
GATT Callback
GAP Callback
GATT App
Set MTU
gatts_event_handler
gap_event_handler

GAP Callback 处理客户端的连接、扫描等事件
GATT Callback 在客户端连接成功后,底层协议栈会发送 GATT 事件到上层程序进行处理,从而完成客户端对服务端数据的读写


GATT 客户端在与 GATT 服务器初次建立通信时,会从 GATT 服务器拉取属性表中的元信息,从而获取 GATT 服务器上可用的服务以及数据特征,这一过程被称为服务发现 (Service Discovery)
属性表中包含:

参数作用
auto_rsp控制谁处理读/写操作的响应
如果设置为 ESP_GATT_RSP_BY_APP,则由应用程序负责生成响应;如果设置为 ESP_GATT_AUTO_RSP,则 GATT 协议栈会自动生成响应。
uuid_lengthUUID 的长度(以字节为单位)
*uuid_p指向 UUID 值的指针
perm属性的权限,由 esp_gatt_perm_t 定义
max_length属性值的最大长度
length属性值的当前长度
*value指向属性值数组的指针

创建 GATT Profile 实例,用于后续功能实现

struct gatts_profile_inst // GATT Profile 实例  
{  esp_gatts_cb_t gatts_cb; // GATT 事件回调函数  uint16_t gatts_if; // GATT 接口  uint16_t app_id; // Application ID  uint16_t conn_id; // 连接 ID    uint16_t service_handle; // 服务句柄  esp_gatt_srvc_id_t service_id; // 服务 ID    uint16_t char_handle; // 特征值句柄  esp_bt_uuid_t char_uuid; // 特征值 UUID    esp_gatt_perm_t perm; // 特征值权限  esp_gatt_char_prop_t property; // 特征值属性  uint16_t descr_handle; // 描述符句柄  esp_bt_uuid_t descr_uuid; // 描述符 UUID};

BLE Server 设置主要步骤

  1. 定义服务和特征值:通过 gatt_db 属性表
  2. 创建服务:通过 esp_ble_gatts_create_attr_tab
  3. 启动服务:通过 esp_ble_gatts_start_service
  4. 注册服务:通过 esp_ble_gatts_app_register
  5. 处理事件:通过 gatts_event_handler
  6. 设置广播:通过 esp_ble_gap_config_adv_dataesp_ble_gap_config_adv_data_raw

Advertising

在 Bluetooth LE 4.2 标准中, RF 信道分为两种类型,如下

类型数量编号作用
广播信道 (Advertising Channel)337-39用于发送广播数据包和扫描响应数据包
数据信道 (Data Channel)370-36用于发送数据通道数据包

广播者在广播时,会在 37-39 这三个广播信道中进行广播数据包的发送
在三个广播信道的广播数据包均发送完毕后,可以认为一次广播结束,广播者会在下一次广播时刻到来时重复上述过程

广播数据包的最外层包含四个部分,分别是

序号名称字节数功能
1预置码 (Preamble)1特殊的比特序列,用于设备时钟同步
2访问地址 (Access Address)4标记广播数据包的地址
3协议数据单元 (Protocol Data Unit, PDU)2-39有效数据的存放区域
4循环冗余校验和 (Cyclic Redundancy Check, CRC)3用于循环冗余校验

广播参数配置结构体:

typedef struct {uint16_t adv_int_min; /*!< 无定向广播和低占空比定向广播的最小广播间隔。范围:0x0020 到 0x4000,默认值:N = 0x0800(1.28 秒)。时间 = N * 0.625 毫秒,时间范围:20 毫秒到 10.24 秒。 */uint16_t adv_int_max; /*!< 无定向广播和低占空比定向广播的最大广播间隔。范围:0x0020 到 0x4000,默认值:N = 0x0800(1.28 秒)。时间 = N * 0.625 毫秒,时间范围:20 毫秒到 10.24 秒。 */esp_ble_adv_type_t adv_type; /*!< 广播类型 */esp_ble_addr_type_t own_addr_type; /*!< 本地蓝牙设备地址类型 */esp_bd_addr_t peer_addr; /*!< 目标设备的蓝牙设备地址 */esp_ble_addr_type_t peer_addr_type; /*!< 目标设备的蓝牙设备地址类型,仅支持公共地址类型和随机地址类型 */esp_ble_adv_channel_t channel_map; /*!< 广播信道映射 */esp_ble_adv_filter_t adv_filter_policy; /*!< 广播过滤策略 */
} esp_ble_adv_params_t;---static esp_ble_adv_params_t adv_params = {  .adv_int_min = 0x20, // 广播间隔最小值,单位为 0.625ms    .adv_int_max = 0x40,  .adv_type = ADV_TYPE_IND, // 使用 ADV_IND 为蓝牙5.0以下的 PDUs    .own_addr_type = BLE_ADDR_TYPE_PUBLIC, // 自身地址类型,此处为公共地址  .channel_map = ADV_CHNL_ALL, // 广播通道,使用所有通道  .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, // 广播过滤策略,允许扫描和连接  
};

MTU

MTU ( Maximum Transmission Unit 最大传输单元)指定发送方在通道上能够接收的最大SDU(服务数据单元)大小

服务器和客户端之间的交互操作都是通过上述的消息 ATT PDU 实现的。每个设备可以指定⾃⼰设备⽀持的最⼤ ATT 消息⻓度,我们称之为 MTU。ESP32 IDF ⾥⾯规定 MTU 可以设置的范围是 23~517 字节,对属性值的总⻓度没有做限制

如果⽤户需要发送的数据包⻓度⼤于 (MTU-3)*,则需要调⽤准⼊写⼊请求 (Prepare Write Request) 来完成数据的写操作。同理,在读取⼀个数据时候,如果数据的⻓度超过 (MTU- 1),则需要通过⼤对象读取请求 (Read Blob Request) 来继续读取剩余的值。

其类型为 0x01,负载长度为 2 个八位字节(octet),并携带两个八位字节的 MTU 大小值;与 B 帧长度字段不同,I 帧长度字段可以大于配置的 MTU,因为它包括了控制字段、L2CAP SDU 长度(如果存在)、帧校验序列字段以及信息字节的长度

在这里插入图片描述

MTU 选项格式

图源:《Bluetooth Core Specification v5.0》

MTU不是协商值,它是一个信息性参数,每个设备可以独立指定;它向远程设备表明,当前设备能够在该通道中接收比最低要求更大的MTU

MTU 的默认值为 23 字节,恰为 Bluetooth LE 4.2 之前单个数据 PDU 的最大可承载 ATT 数据字节数

MTU 可以设定为更大的值,例如 140 字节。在 Bluetooth LE 4.2 以前,由于有效负载中最多只有 23 字节可以承载 ATT 数据,所以必须将完整的一包 ATT 数据包拆分成若干份,分散到多个数据 PDU 中。在 Bluetooth LE 4.2 以后,单个数据 PDU 最多可以承载 247 字节 ATT 数据,所以 MTU 为 140 字节时仍然可以使用单个数据 PDU 承载

Broadcast Frame B 帧用于传输控制信息或链路管理数据,包含控制字段和帧检查序列等额外的管理信息,不直接传输应用数据

Information Frame I 帧用于传输实际的应用数据,包含有效负载和控制信息,它通常包括L2CAP SDU长度、帧校验序列等,用于数据传输

L2CAP SDU (L2CAP Service Data Unit)​是L2CAP(逻辑链路控制和适配协议)中的一种数据单位,它指的是 L2CAP 协议层所处理的完整数据单元;L2CAP 用于蓝牙设备之间的通信,负责数据分段和重组、流量控制、错误检测等功能

在响应配置请求时,指定通道的 MTU 大小时应遵循以下规则:

  • 如果请求中指定的 MTU 大于或等于通道的最小 MTU ,则应接受该请求
  • 如果请求中指定的 MTU 小于通道的最小MTU,则该请求可能会被拒绝

PDU

PDU 段为有效数据存放的区域,其结构如下

序号名称字节数
1头 (Header)2
2有效负载 (Payload)0-37
PDU 头中含有较多信息,可以分为以下六个部分
序号名称比特位数备注
1PDU 类型 (PDU Type)4
2保留位 (Reserved for Future Use, RFU)1
3通道选择位 (Channel Selection Bit, ChSel)1标记广播者是否支持 LE Channel Selection Algorithm #2 通道选择算法
4发送地址类型 (Tx Address, TxAdd)10/1 分别表示公共地址/随机地址
5接收地址类型 (Rx Address, RxAdd)10/1 分别表示公共地址/随机地址
6有效负载长度 (Payload Length)8

PDU 类型位反映了设备的广播行为。在蓝牙标准中,共有以下三对广播行为

  • 可连接 (Connectable) 与 不可连接 (Non-connectable)
    • 是否接受其他设备的连接请求
  • 可扫描 (Scannable) 与 不可扫描 (Non-scannable)
    • 是否接受其他设备的扫描请求
  • 不定向 (Undirected) 与 定向 (Directed)
    • 是否发送广播数据至指定设备
      上述广播行为可以组合成以下四种常见的广播类型,对应四种不同的 PDU 类型
可连接?可扫描?不定向?PDU 类型作用
ADV_IND最常见的广播类型
ADV_DIRECT_IND常用于已知设备重连
ADV_NONCONN_IND作为信标设备,仅向外发送广播数据
ADV_SCAN_IND作为信标设备,一般用于广播数据包长度不足的情况,此时可以通过扫描响应向外发送额外的数据

PDU 有效负载也分为两部分

序号名称字节数备注
1广播地址 (Advertisement Address, AdvA)6广播设备的 48 位蓝牙地址
2广播数据 (Advertisement Data, AdvData)0-31由若干广播数据结构 (Advertisement Data Structure) 组成

蓝牙地址,可以分为

类型说明
公共地址 (Public Address)全球范围内独一无二的固定设备地址,厂商必须为此到 IEEE 组织注册并缴纳一定费用
随机地址 (Random Address)随机生成的地址

随机地址又根据用途分为两类

类型说明
随机静态地址 (Random Static Address)可以随固件固化于设备,也可以在设备启动时随机生成,但在设备运行过程中不得变更;常作为公共地址的平替
随机私有地址 (Random Private Address)可在设备运行过程中周期性变更,避免被其他设备追踪

若使用随机私有地址的设备要与其他受信任的设备通信,则应使用身份解析秘钥 (Identity Resolving Key, IRK) 生成随机地址,此时其他持有相同 IRK 的设备可以解析并得到设备的真实地址,此时,随机私有地址又可以分为两类

类型说明
可解析随机私有地址 (Resolvable Random Private Address)可通过 IRK 解析得到设备真实地址
不可解析随机私有地址 (Non-resolvable Random Private Address)完全随机的地址,仅用于防止设备被追踪,非常少用

广播数据
一个广播数据结构的格式定义如下

序号名称字节数备注
1数据长度 (AD Length)1
2数据类型 (AD Type)n大部分数据类型占用 1 字节
3数据 (AD Data)(AD Length - n)

在这里插入图片描述


Advertising Flow

设备在 2.4 GHz ISM 频段广播数据

2.4 GHz ISM 频段是一个全球可用的免费无线电频段,不被任何国家以军事用途等理由管控,也无需向任何组织支付许可费用,因此该频段的可用性极高,且没有任何使用成本
这也意味着 2.4 GHz ISM 频段非常拥挤,可能会与其他无线通信协议发生数据冲突,如 2.4 GHz WiFi
Bluetooth LE 应用了自适应跳频技术 (Adaptive Frequency Hopping, AFH) ,该技术可以判断 RF 信道的拥挤程度,通过跳频避开拥挤的 RF 信道,以提高通信质量

Bluetooth LE ⼴播主要有 5 种类型,分别为:可连接可扫描⾮定向⼴播 (Connectable scannable undirected mode)、⾼占空⽐定向⼴播 (High duty cycle directed event type)、可扫描⾮定向⼴播 (Scannable undirected mode)、不可连接⾮定向⼴播 (Non-connectable undirected mode)、可连接低占空⽐定向⼴播 (Connectable low duty cycle directed mode)。


Advertising State
Undirected Advertising

设备通过启用广播进入广播状态,在此之前必须先配置好广播参数

在这里插入图片描述

不定向广播

图源:《Bluetooth Core Specification v5.0》

Host A​ 蓝牙设备 A 的上层(主机)
LL A​ 蓝牙设备 A 的链接层(link layer)


Advertising Flow

  1. LE Set Advertising Parameters​ Host 发送广播参数命令到 LL
  2. Command Complete​ LL 设置成功后返回命令完成 Event 到 Host
  3. LE Read Advertising Channel Tx Power​ Host 读取广播 Tx 的功率
  4. Command Complete​ LL 返回命令完成 Event 到 Host
  5. LE Set Advertising Data​ Host 设置广播数据
  6. Command Complete​ LL 返回命令完成 Event 到 Host
  7. LE Set Scan Response Data​ Host 设置扫描应答数据
  8. Command Complete​ LL 返回命令完成 Event 到 Host
  9. LE Set Advertising Enable(Enable)​ Host 发送使能命令
  10. Command Complete​ LL 返回命令完成 Event 到 Host
  11. Advert ​ LL 开始广播数据(从 LL B 到 LL A)
  12. LE Set Advertising Enable(Disable)​ Host 发送停止广播命令
  13. Command Complete​ LL 返回命令完成 Event 到 Host
属性SAMPLE_DEVICE_NAME广播数据中的名字
设置方式esp_ble_gap_set_device_name()在广播数据中通过 0x09 字段设置
作用范围GAP 名称,全局标识设备广播包中的本地名称,广播时可见
是否必须是,设备必须有一个 GAP 名称否,广播包中可以不包含名字字段
是否可以不同不依赖广播数据,可以与广播数据中的名字不同可以与 GAP 名称不同
显示位置客户端扫描设备时显示客户端解析广播包时显示

Directed Advertising

设备可以使用定向广播允许发起方与其连接
高占空比定向广播在控制器中是时间有限的,因此在建立连接之前可能会失败
低占空比定向广播也必须启用才能进入广播状态,设备在此之前还应配置广播参数
在这里插入图片描述

高占空比循环定向广播失败情况

图源:《Bluetooth Core Specification v5.0》


在这里插入图片描述

低占空比循环定向广播失败情况

图源:《Bluetooth Core Specification v5.0》

占空比​ 指的是在一个周期内,信号处于“活动”状态的时间比例。它通常用百分比表示,计算公式为:

占空比 = 活动时间 总周期时间 × 100 % \text{占空比} = \frac{\text{活动时间}}{\text{总周期时间}} \times 100\% 占空比=总周期时间活动时间×100%

  • 高占空比意味着信号在大部分时间内处于“活动”状态,只有少部分时间处于“空闲”状态

    • 发送的信号较强,持续时间较长,适合需要高接入概率的场景
    • 由于广播持续时间较长,设备的功耗较高,因此适用于短时间内需要建立连接的情况
  • 低占空比意味着信号的“活动”时间较短,大部分时间处于“空闲”状态

    • 广播时间较短,信号的持续时间较低,适用于功耗敏感的场景
    • 这种方式会减少设备的功耗,但建立连接的概率较低,因为广播的时间较短,接收方可能错过广播


Scanning State
Passive Scanning

设备可以使用被动扫描来查找区域内的广播设备
该设备将接收来自对等设备的广播数据包,并将这些数据报告给主机
在这里插入图片描述

被动扫描

图源:《Bluetooth Core Specification v5.0》



Scanning Flow

  1. LE Set Scan Parameters (Passive Scanning)​ Host 设置被动扫描的扫描参数
  2. Command Complete​ LL 返回命令完成 Event 到 Host
  3. LE Set Scan Enable (Enable)​ Host 设置扫描允许命令
  4. Command Complete​ LL 返回命令完成 Event 到 Host
  5. Advert​ LL A 收到来自 LL B 的扫描
  6. LE Advertising Report​ LL 上报收到的广播数据
  7. LE Set Scan Enable (Disable)​ Host 发送停止扫描命令
  8. Command Complete​ LL 返回命令完成 Event 到 Host

Active Scanning

设备可以使用主动扫描获取更多关于设备的信息,这些信息可能对填充用户界面有帮助
主动扫描涉及更多的链路层广播消息
在这里插入图片描述

主动扫描

图源:《Bluetooth Core Specification v5.0》


Active Scanning Flow

  1. LE Set Scan Parameters (Passive Scanning)
  2. Command Complete
  3. LE Set Scan Enable (Enable)
  4. Command Complete
  5. Advert
  6. SCAN_REQ ​ LL A 发送扫描请求到 LL B (广播数据最大只有 32 个 Bytes,更多的数据需要放在扫描应答中)
  7. SCAN_RSP​ LL B 返回扫描请求应答数据
  8. LE Advertising Report 上报广播数据和扫描应答数据​
  9. LE Set Scan Enable (Disable)
  10. Command Complete


Callback Parameters

GATT Server Callback Parameters 详见 esp-idf_GATT Server
GAP Callback Parameter 详见 esp-idf_GATT Client


Advertising And Scanning Response Data Format

广播数据和扫描响应数据的格式由两个部分组成:重要部分非重要部分

  1. 重要部分
    • 包含一系列 AD 结构 ​,每个 AD 结构包含两个字段
      • 长度字段 ​ 1 字节,表示数据的长度,即后面的长度不能超过 0xff
      • 数据字段​ 长度由长度字段决定,数据字段的第一个字节是 AD 类型字段,剩余的长度 - 1 字节是 AD 数据,其内容取决于 AD 类型字段的值
  2. 非重要部分
    • 当需要时,用来扩展广播和扫描响应数据
    • 必须包含全零字节

在这里插入图片描述

广播数据和扫描响应数据的格式

图源:《Bluetooth Core Specification v5.0》

长度字段如果设置为零,则数据字段没有字节,这仅在需要提前终止广告或扫描响应数据时发生

只有重要部分的广告或扫描响应数据应通过无线信号发送

广播和扫描响应数据在广播事件中发送:

  • 广播数据放置在 ADV_INDADV_NONCONN_INDADV_SCAN_INDAUX_ADV_INDAUX_CHAIN_INDAUX_SYNC_IND 数据包的 AdvData 字段中
  • 扫描响应数据放置在 SCAN_RSP 数据包的 ScanRspData 字段中,或者放置在 AUX_SCAN_RSP 数据包的 AdvData 字段中

如果完整的广播或扫描响应数据无法容纳在 AUX_ADV_INDAUX_SCAN_RSP 数据包中,则使用 AUX_CHAIN_IND 数据包传送剩余的数据

AD 类型数据的格式和含义在 Core Specification Supplement 的 A 部分中定义,AD 类型标识符值在 Assigned_Numbers.pdf 文档中 2.3 Common Data Types 部分定义

对于蓝牙 5.0 及以下,广播可以携带 0~31 个字节
对蓝牙 5.0 及以上,广播可以携带 0~254 个字节,通过分组技术,可以携带更多数据(不超过 1650Bytes)
详见:Bluetooth Core Specification Vol6 PartB 2.3

These PDUs are sent by the Link Layer in the Advertising State and received by a Link Layer in the Scanning State or Initiating State. The ADV_IND, ADV_DIRECT_IND, ADV_NONCONN_IND, and ADV_SCAN_IND PDUs are called “legacy advertising PDUs”. The ADV_EXT_IND, AUX_ADV_IND, AUX_SYNC_IND, and AUX_CHAIN_IND PDUs are called “extended advertising PDUs”. Advertising events using legacy advertising PDUs are called “legacy advertising events”

来源:Bluetooth Core Specification v5.0, 页面 2,570


gatts_table_creat_demo

GATT APP 的工作流程:

  1. (app_main)esp_ble_gatts_app_register () 注册 profile ID,返回 ESP_GATTS_REG_EVT
  2. (gatts_profile_event_handler)当触发 ESP_GATTS_REG_EVT,设置设备名称、原始广播数据,触发 ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT
  3. (gatts_profile_event_handler)esp_ble_gap_config_scan_rsp_data_raw() (GATT)设置广播数据、扫描响应数据,触发 ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT
  4. (gap_event_handler)当触发 ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT 事件如果广播数据和扫描响应数据都设置了,则 (GAP) 调用 esp_ble_gap_start_advertising 开始广播,触发 ESP_GAP_BLE_ADV_START_COMPLETE_EVT 事件
  5. 设备广播数据
  6. 可以调用 esp_ble_gap_stop_advertising() 停止广播,返回 ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT

可以在 LightBlue 中读到广播数据

在这里插入图片描述

应用程序处理客户端读取特征值事件

case ESP_GATTS_READ_EVT: // 读事件,当客户端读取特征值时触发,如果设置为 AUTO_RSP,协议栈会自动处理,否则需要应用程序处理  ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_READ_EVT");  esp_gatt_rsp_t rsp;                         // 定义变量  memset(&rsp, 0, sizeof(esp_gatt_rsp_t));    // 初始化变量  rsp.attr_value.handle = param->read.handle; // 设置 handle    rsp.attr_value.len = 4;                     // 设置长度  rsp.attr_value.value[0] = 0xde;             // 设置值  rsp.attr_value.value[1] = 0xed;  rsp.attr_value.value[2] = 0xbe;  rsp.attr_value.value[3] = 0xef;  esp_ble_gatts_send_response(gatts_if, param->read.conn_id, param->read.trans_id,  ESP_GATT_OK, &rsp); // 返回数据至客户端  break;

GATT Client

GATT Client Work Flow

init
flash
controller
bluedriod
app_main
GAP Callback
GATT Callback
GATT App
Set MTU
esp_gap_cb
esp_gattc_cb

GATT Client 工作流程

  1. (app_main) 中初始化 NVS
  2. (app_main) 释放经典蓝牙模式
  3. (app_main) 初始化蓝牙控制器
  4. (app_main) 使能蓝牙控制器
  5. (app_main) 初始化 bluedroid
  6. (app_main) 使能 bluedroid
  7. (app_main) 注册 GAP 回调函数
  8. (app_main) 注册 GATT 回调函数
  9. (app_main) 注册 GATT APP ID,触发 ESP_GATTC_REG_EVT 事件
  10. (gattc_profile_event_handler)设置扫描参数,触发 ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT 事件
  11. (esp_gap_cb)当触发 ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT 事件时,开始扫描,触发 ESP_GAP_BLE_SCAN_START_COMPLETE_EVT 事件
  12. (esp_gap_cb)扫描结果触发 ESP_GAP_BLE_SCAN_RESULT_EVT 事件,它有两个子事件:ESP_GAP_SEARCH_INQ_RES_EVTESP_GAP_SEARCH_INQ_CMPL_EVT
    1. (esp_gap_cb)扫描到每一个蓝牙 Service 时,触发 ESP_GAP_SEARCH_INQ_RES_EVT,对扫描到的数据进行解析,如果扫描到的设备名和目标设备名相同,则停止扫描,打开 GATT 连接,触发 ESP_GATTC_CONNECT_EVTESP_GATTC_OPEN_EVT 事件
    2. (esp_gap_cb)扫描完所有的蓝牙 Service 时,触发 ESP_GAP_SEARCH_INQ_CMPL_EVT
  13. (gattc_profile_event_handler)当触发 ESP_GATTC_CONNECT_EVT 事件时,打印连接 ID,发送 MTU 请求,触发 ESP_GATTC_DIS_SRVC_CMPL_EVTESP_GATTC_CFG_MTU_EVT 事件
  14. (gattc_profile_event_handler)当触发 ESP_GATTC_CFG_MTU_EVT 事件时,检查 MTU 设置是否成功
  15. (gattc_profile_event_handler)当触发 ESP_GATTC_DIS_SRVC_CMPL_EVT 事件时,搜索服务,当找到服务时,会触发 ESP_GATTC_SEARCH_RES_EVT 事件;当搜索完所有服务时,会触发 ESP_GATTC_SEARCH_CMPL_EVT 事件
  16. (gattc_profile_event_handler)当触发 ESP_GATTC_SEARCH_RES_EVT 事件时,保存服务的起始句柄和结束句柄
  17. (gattc_profile_event_handler)当触发 ESP_GATTC_SEARCH_CMPL_EVT 事件,获取服务的特征数量和服务特征,注册通知,触发 ESP_GATTC_REG_FOR_NOTIFY_EVT 事件
  18. (gattc_profile_event_handler)当触发 ESP_GATTC_REG_FOR_NOTIFY_EVT 事件,写入描述符,触发 ESP_GATTC_WRITE_DESCR_EVT 事件
  19. (gattc_profile_event_handler)当触发 ESP_GATTC_WRITE_DESCR_EVT 事件,,输出写入成功或失败
  20. (gattc_profile_event_handler)如果 Service 发送通知,触发 ESP_GATTC_NOTIFY_EVT

特征读取函数

esp_ble_gattc_read_char(gattc_if,                        // 特征接口  p_data->search_cmpl.conn_id,     // 连接 ID                           char_elem_result[0].char_handle, // 特征句柄  ESP_GATT_AUTH_REQ_NONE);         // 无需授权  // 触发 ESP_GATTC_READ_CHAR_EVT 事件

特征输出函数

case ESP_GATTC_READ_CHAR_EVT:  ESP_LOGI(GATTC_TAG, "ESP_GATTC_READ_CHAR_EVT, len %d, value:",  p_data->read.value_len);  esp_log_buffer_hex(GATTC_TAG, p_data->read.value, p_data->read.value_len);  
break;

Connection

当扫描者在某一个广播信道接收到一个广播数据包时,若该广播者是可连接的,那么扫描者可以在同一广播信道发送连接请求 (Connection Request)
对广播者,它可以设置 接受列表 (Filter Accept List) 以过滤不受信任的设备,或接受任一扫描者的连接请求
随后,广播者转变为外围设备,扫描者转变为中央设备,两者之间可以在数据信道进行双向通信

在连接中,中央设备与外围设备会周期性地进行数据交换,这个数据交换的周期被称为连接间隔 (Connection Interval)

  • 连接间隔作为连接参数之一,在连接请求中被首次确定,后续也可以进行修改
  • 连接间隔的取值步长 (Step Size) 为 1.25 ms ,取值范围为 7.5 ms (6 steps) - 4.0 s (3200 steps)

一次数据交换的过程被称为连接事件 (Connection Event)
一次连接事件中,存在一次或多次数据包交换(数据量比较大时需分包发送)

  • 一次数据包交换的过程是,中央设备先给外围设备发送一个数据包,随后外围设备给中央设备发送一个数据包
  • 即便连接中任意一方在连接间隔开始时无需发送数据,也必须发送空数据包以维持连接
  • 若一次连接事件中需要发送的数据很多,导致连接事件时长超过了连接间隔,那么必须将一次连接事件拆分成多次连接事件(假如连接间隔的剩余时间不足以完成下一次数据包交换,那么下一次数据包交换必须等到下一次连接间隔开始时才能进行)

Supervision Timeout

连接超时参数 (Supervision Timeout) 规定了两次成功连接事件之间的最长时间
若在一次成功的连接事件之后,经过了连接超时时间却仍没有完成另一次成功的连接事件,则可以认为连接已断开


Peripheral Latency

外围设备延迟 (Peripheral Latency) 规定了外围设备在无需发送数据的前提下,最多可忽略的连接事件数量(即可以根据实际情况动态调整连接间隔,低间隔则高能耗,高间隔则高延迟)


MTU

详见本文MTU部分


Data Exchange

由客户端发起的操作有以下三种

  • 读 (Read)
    • 从 GATT 服务器上拉取某一特征数据的当前值
  • 写 (Write)
    • 普通的写操作要求 GATT 服务器在收到客户端的写请求以及对应数据以后,进行确认响应
  • 写(无需响应) (Write without response)
    • 快速写操作则不需要服务器进行确认响应

由服务器发起的操作分两种

  • 通知 (Notify)
    • 通知是 GATT 服务器主动向客户端推送数据的操作,不需要客户端回复确认响应
  • 指示 (Indicate)
    • 与通知相似,区别在于指示需要客户端回复确认,因此数据推送速度比通知慢

虽然通知和指示都是由服务器发起的操作,但是服务器发起操作的前提是,客户端启用了通知或指示
所以,本质上 GATT 的数据交换过程总是以客户端请求数据开始


Write Data

flowchart TB
A[Client] --write data--> B[Server]
B --> C{Data}
C --<=MTU-3-->D[ESP_GATTS_WRITE_EVT]
C --&gt;MTU-3-->D[ESP_GATTS_WRITE_EVT]
C --&gt;MTU-3-->E[ESP_GATTS_EXEC_WRITE_EVT]

当接收到的数据 > MTU - 3 时,会将超出的数据放入一个 buffer 中,接受完所有数据后,再进行处理

  1. 客户端发起写入请求
  2. 服务器接收并存储到属性数据库
  3. 服务器应用逻辑读取该值
  4. 服务器处理该值

Notification for Server

可以用于在触发 ESP_GATTS_WRITE_EVT 事件后回复 client


Notification for Client

  1. 客户端查找服务事件 ESP_GATTC_SEARCH_CMPL_EVT,即蓝牙客户端在查找完服务端后,会上报上层程序,如果找到了目标服务,则会调用 esp_ble_gattc_get_attr_count() 函数,取得属性数目
  2. 如果取得的数目 >0,则会调用 esp_ble_gattc_get_char_by_uuid() 函数,取得所用对应特征值的设置,同时取得通知值的设置,从而判断是 notification 还是 indication
  3. 之后调用 esp_ble_gattc_register_for_notify() 注册通知,触发 ESP_GATTC_REG_FOR_NOTIFY_EVT 事件
  4. 通过 esp_ble_gattc_get_descr_by_char_handle() 取得 describe 位
  5. 通过 esp_ble_gattc_write_char_descr() 函数将 notify_en 参数(0x0001-notification,0x0002-indication)写入 Server,触发 ESP_GATTC_WRITE_DESCR_EVT 事件(在服务端触发 ESP_GATTS_WRITE_EVT
  6. 检查写入是否成功,如果成功,则进行下一步流程
  7. Server 发送 notification,触发客户端的 ESP_GATTC_NOTIFY_EVT 事件
flowchart TDA[Register] --esp_ble_gattc_register_for_notify()--> B[ESP_GATTC_REG_FOR_NOTIFY_EVT]B --esp_ble_gattc_get_descr_by_char_handle(), esp_ble_gattc_write_char_descr() -->C[ESP_GATTC_WRITE_DESCR_EVT]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/898485.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录算法训练营第五十二天 |101. 孤岛的总面积102. 沉没孤岛103. 水流问题104.建造最大岛屿

101. 孤岛的总面积 卡码网&#xff1a;101. 孤岛的总面积(opens new window) 题目描述 给定一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的矩阵&#xff0c;岛屿指的是由水平或垂直方向上相邻的陆地单元格组成的区域&#xff0c;且完全被水域单…

Simple-BEV的bilinear_sample 作为view_transformer的解析,核心是3D-2D关联点生成

文件路径models/view_transformers 父类 是class BiLinearSample(nn.Module)基于https://github.com/aharley/simple_bev。 函数解析 函数bev_coord_to_feature_coord的功能 将鸟瞰图3D坐标通过多相机&#xff08;针孔/鱼眼&#xff09;内外参投影到图像特征平面&#xff0…

A/B测试入门指南

目录 一、什么是A/B测试1.1 A/A测试1.2 多变量测试 二、A/B测试应用场景三、A/B测试基本流程四、A/B测试面试真题4.1 【是什么】4.2 【为什么】4.3 【怎么做】 五、应用实战 一、什么是A/B测试 A/B 测试是一种常见的实验方法&#xff0c;用于比较两个或多个方案的效果&#xff…

自己构建的交叉编译器找不到PATH_MAX

接上篇centos6.10 编译gcc11.5 x64到aarch64交叉工具链 -CSDN博客 PATH_MAX找不到&#xff0c;不仅在编译gcc的过程中遇到&#xff0c;而且临时改gcc源码添加#define PATH_MAX 4096 宏定义后勉强通过gcc全量编译。这个新的gcc编译使用了PATH_MAX宏的代码还是会找不到。这个问题…

vscode查看文件历史git commit记录

方案一&#xff1a;GitLens 在vscode扩展商店下载GitLens 选中要查看的文件&#xff0c;vscode界面右上角点击GitLens的图标&#xff0c;选择Toggle File Blame 界面显示当前打开文件的所有修改历史记录 鼠标放到某条记录上&#xff0c;可以看到记录详情&#xff0c;选中O…

IREE AI编译器编译测试流程指南

iree onnx demo 计划协议系列博客,记录学习iree编译器的过程. 今天第一篇博客,记录安装和测试iree 文章目录 iree onnx demo下载安装ireepython环境安装编译测试1. [前端] onnx模型转MLIR文件2. [后端] MLIR文件转可执行文件3. [执行] 执行测试编译后的文件 关于后端设备的介…

破解验证码新利器:基于百度OCR与captcha-killer-modified插件的免费调用教程

破解验证码新利器&#xff1a;基于百度OCR与captcha-killer-modified插件的免费调用教程 引言 免责声明&#xff1a; 本文提供的信息仅供参考&#xff0c;不承担因操作产生的任何损失。读者需自行判断内容适用性&#xff0c;并遵守法律法规。作者不鼓励非法行为&#xff0c;保…

JSON 解析中需要清理的危险字符

在代码中 replace(chr(0), "") 的作用是删除 JSON 响应中可能存在的空字符&#xff08;Null character&#xff09;。以下是详细解释&#xff1a; 1. chr(0) 是什么&#xff1f; chr(0) 表示 ASCII 码为 0 的字符&#xff0c;即空字符&#xff08;Null Character&am…

ubuntu部署运行xinference全精度对话deepseek本地部署图文教程

前置环境搭建劳请移步往期 source activate 自己环境名启动python3.12环境安装xinference&#xff0c; 按教程敲命令&#xff0c;wheel包与wsl的通用&#xff0c;pip install 包名。 vllm引擎&#xff0c;transform引擎也会顺带自动装上了。 后续操作请参照往期教程。本地部署模…

技术分享 | MySQL内存使用率高问题排查

本文为墨天轮数据库管理服务团队第51期技术分享&#xff0c;内容原创&#xff0c;如需转载请联系小墨&#xff08;VX&#xff1a;modb666&#xff09;并注明来源。 一、问题现象 问题实例mysql进程实际内存使用率过高 二、问题排查 2.1 参数检查 mysql版本 &#xff1a;8.0.…

【vulhub/wordpress靶场】------获取webshell

1.进入靶场环境&#xff1a; 输入&#xff1a;cd / vulhub / wordpress / pwnscriptum 修改版本号&#xff1a; vim docker-compose.yml version: 3 保存退出 开启靶场环境&#xff1a; docker - compose up - d 开启成功&#xff0c;docker ps查看端口 靶场环境80…

微信小程序:用户拒绝小程序获取当前位置后的处理办法

【1】问题描述&#xff1a; 小程序在调用 wx.getLocation() 获取用地理位置时&#xff0c;如果用户选择拒绝授权&#xff0c;代码会直接抛出错误。如果再次调用 wx.getLocation() 时&#xff0c;就不会在弹窗询问用户是否允许授权。导致用户想要重新允许获取地理位置时&#x…

全网首创/纯Qt/C++实现国标GB28181服务/实时视频/云台控制/预置位/录像回放和下载/事件订阅/语音对讲

一、前言说明 用纯Qt来实现这个GB28181的想法很久了&#xff0c;具体可以追溯到2014年&#xff0c;一晃十年都过去了&#xff0c;总算是整体的框架和逻辑都打通了&#xff0c;总归还是杂七杂八的事情多&#xff0c;无法静下心来研究具体的协议&#xff0c;最开始初步了解协议后…

Django+celery+flower

Djangoceleryflower Django的定时任务及可视化监控Django Django的定时任务及可视化监控 Django的定时任务&#xff0c;以及可视化监控。 Django Django&#xff1b; 首先在python中新建虚拟环境并激活 pip install virtualenv python -m venv venv source venv/bin/activa…

组态王Kingview配置为OPCUA服务器的一些问题处理

一、问题描述 1、组态王【运行配置】界面没有【服务配置】的选项&#xff0c;无法将组态王Kingview配置为OPCUA服务器&#xff1b; 2、点击组态王【运行配置界面】的【服务配置】选项弹窗警告提示【试图执行的操作不受支持】&#xff0c;如下图所示&#xff1a; 二、问题分析 …

模块二 单元4 安装AD+DC

模块二 单元4 安装ADDC 两个任务&#xff1a; 1.安装AD活动目录 2.升级当前服务器为DC域控制器 安装前的准备工作&#xff1a; 确定你要操作的服务器系统&#xff08;Windows server 2022&#xff09;&#xff1b; 之前的服务器系统默认是工作组的模式workgroup模式&#xff08…

VMware主机换到高配电脑,高版本系统的问题

原来主机是i3 ,windows7系统&#xff0c;vmware 14.0,虚机系统是ubuntu 14.04。目标新机是i7 14700KF,windows11系统。原以为安装虚拟机&#xff0c;将磁盘文件&#xff0c;虚拟机配置文件拷贝过去可以直接用。 新目标主机先安装了vmware 15&#xff0c;运行原理虚机&#xff0…

MDG实现BP客商复杂逻辑校验的方法

引言 项目中可能常用的增强点是USMD_RULE_SERVICE来实现复杂的校验逻辑&#xff0c;除此之外&#xff0c;SAP对BP主数据还提供了以下的实现方式。 方法1-替换ERP校验类 众所周知&#xff0c;BP存在复杂的ERP校验&#xff0c;主要通过类CL_MDG_BS_FND_BP_CHECK&#xff08;子…

基于springboot的教务系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 这些年随着Internet的迅速发展&#xff0c;我们国家和世界都已经进入了互联网大数据时代&#xff0c;计算机网络已经成为了整个社会以及经济发展的巨大动能&#xff0c;各个高校的教务工作成为了学校管理事务的重要目标和任务&#xff0c;因此运用互联网技术来提高教务的…

TDengine 中的流式计算

简介 TDengine 中的流计算&#xff0c;功能相当于简化版的 FLINK &#xff0c; 具有实时计算&#xff0c;计算结果可以输出到超级表中存储&#xff0c;同时也可用于窗口预计算&#xff0c;加快查询速度。 创建流式计算 CREATE STREAM [IF NOT EXISTS] stream_name [stream_o…