蓝牙GATT协议介绍

news2024/12/23 1:33:05

前言

现在低功耗蓝牙(BLE)连接都是建立在 GATT (Generic Attribute Profile) 协议之上。GATT 是一个在蓝牙连接之上的发送和接收很短的数据段的通用规范,这些很短的数据段被称为属性(Attribute)。

  1. GAP

详细介绍 GATT 之前,需要了解 GAP(Generic Access Profile),它在用来控制设备连接和广播。GAP 使你的设备被其他设备可见,并决定了你的设备是否可以或者怎样与合同设备进行交互。例如 Beacon 设备就只是向外广播,不支持连接,小米手环就等设备就可以与中心设备连接。
设备角色
GAP 给设备定义了若干角色,其中主要的两个是:外围设备(Peripheral)和中心设备(Central)。

  • 外围设备:这一般就是非常小或者简单的低功耗设备,用来提供数据,并连接到一个更加相对强大的中心设备。例如小米手环。
  • 中心设备:中心设备相对比较强大,用来连接其他外围设备。例如手机等。
  1. 广播数据

在 GAP 中外围设备通过两种方式向外广播数据: Advertising Data Payload(广播数据)和 Scan Response Data Payload(扫描回复),每种数据最长可以包含 31 byte。这里广播数据是必需的,因为外设必需不停的向外广播,让中心设备知道它的存在。扫描回复是可选的,中心设备可以向外设请求扫描回复,这里包含一些设备额外的信息,例如设备的名字。

  1. 广播流程

GAP 的广播工作流程如下图所示。
在这里插入图片描述
从图中我们可以清晰看出广播数据和扫描回复数据是怎么工作的。外围设备会设定一个广播间隔,每个广播间隔中,它会重新发送自己的广播数据。广播间隔越长,越省电,同时也不太容易扫描到。

  1. 广播的网络拓扑结构

大部分情况下,外设通过广播自己来让中心设备发现自己,并建立 GATT 连接,从而进行更多的数据交换。也有些情况是不需要连接的,只要外设广播自己的数据即可。用这种方式主要目的是让外围设备,把自己的信息发送给多个中心设备。因为基于 GATT 连接的方式的,只能是一个外设连接一个中心设备。使用广播这种方式最典型的应用就是苹果的 iBeacon。广播工作模式下的网络拓扑图如下:
在这里插入图片描述

介绍

GATT 的全名是 Generic Attribute Profile(姑且翻译成:普通属性协议),它定义两个 BLE 设备通过叫做 Service 和 Characteristic 的东西进行通信。GATT 就是使用了 ATT(Attribute Protocol)协议,ATT 协议把 Service, Characteristic遗迹对应的数据保存在一个查找表中,次查找表使用 16 bit ID 作为每一项的索引。
一旦两个设备建立起了连接,GATT 就开始起作用了,这也意味着,你必需完成前面的 GAP 协议。这里需要说明的是,GATT 连接,必需先经过 GAP 协议。实际上,我们在 Android 开发中,可以直接使用设备的 MAC 地址,发起连接,可以不经过扫描的步骤。这并不意味不需要经过 GAP,实际上在芯片级别已经给你做好了,蓝牙芯片发起连接,总是先扫描设备,扫描到了才会发起连接。
GATT 连接需要特别注意的是:GATT 连接是独占的。也就是一个 BLE 外设同时只能被一个中心设备连接。一旦外设被连接,它就会马上停止广播,这样它就对其他设备不可见了。当设备断开,它又开始广播。
中心设备和外设需要双向通信的话,唯一的方式就是建立 GATT 连接。

GATT可以被Application或其他Profile使用,其协议栈如下图
在这里插入图片描述
GATT可以配置为如下两种角色(Role)

 - Client : 命令、请求发起方 
 - Server : 命令、请求接收方

角色配置实例如下:
在这里插入图片描述
Computer是一个温度服务客户端, Sensor是温度服务服务器
Computer向Sensor发起Procedure来读Sensor的值

GATT对蓝牙协议下层的需求如下

 - Physical Link 	: 使用GAP Channel Establishment建立的ATT Bearer 
 - GATT Role		: 不依赖于Coontroller角色(Master/Slave) 
 - Security		: 对于LE,Security Features(Authorization、Authentication、Encryption)是可选的 
                  对于BR/EDR, Encryption是强制的 
 - TX order		: GATT中的多字节字段,采用Little Endian

相关概念

  1. GATT Profile Hierarchy
    GATT指定了数据交互的结构(Structure);这个结构体定义了一些基本元素,如Service、Characteristic
    这些元素存在于Attribute中
    在这里插入图片描述
    Profile并不是实际存在于 BLE 外设上的,它只是一个被 Bluetooth SIG 或者外设设计者预先定义的 Service 的集合,由一个或多个服务(Service)组成。服务是由Characteristics组成,或是其他服务的引用(Include),Characteristic包含一个值(Value),可能还包含该Value的相关信息。
    Service
    Service是[数据]和与之关联的[完成某个特定功能的行为]or[特性]的集合,在GATT中,一个服务由服务定义(Service Defintion)来实现,一个服务定义可能包含引用服务(referenced Service)、必要Characteristic和可选Characteristic。
    Server有两类
- Primary Service   : 拥有基本功能的服务,可被其他服务包含,可以通过Primary Service Discovery过程来发现 
- Secondary Service : 仅用来被Primary/Other Secondary Service、高层协议引用的服务

Service definition如下:
Service必须包括一个服务声明(service declaration),可能包含包含零个或者多个Include和Characteristic。服务定义中的Include Definitions和Characteristic Definitions被认为是服务的一部分。服务定义中的顺序为

Service Declaration ~ Include Definitions(>=0) ~ Characteristic Definitions(>=0)

服务声明是一个Attribute,其中Attribute type是一个UUID,分别是0x2800(Primary Service)或者0x2801(Secondary Service)。从服务声明0x2800开始到下一个0x2800属性(即新的服务声明)之间的内容都属于同一个Service,也就是说它没有一个Length来直接说明它多长或多少个数据项。在上图Profile中,一个Profile至少包含一个Service,Gatt discover过程会以0x2800为界限,将两个0x2800中的所有属性划归为前后一个以0x2800开始的Service。服务声明的Attribute Value是第一个服务的UUID。
每个 Service 有一个 UUID 唯一标识。 UUID 有 16 bit 的,或者 128 bit 的。16 bit 的 UUID 是官方通过认证的(参考《16-bit UUID Numbers Document.pdf》),需要花钱购买,也可以自己随便设置。

Included Service(referenced Service)

一个Included Service是一种引用已存在服务的方法,具体办法为在服务定义的开始加上Included Service的引用,这样整个Included Service定义成为新服务定义的一部分。
在这里插入图片描述
它是一个Attribute,Attribute Type=0x2802。Attribute Type存储了Attribute Handle或服务的UUID,注意Handle并不真实存在和存储,它只是在远程蓝牙设备里面的程序构建GATTService时创建的、被程序识别和使用。
如果一个Service的Include Definition(A)是引用其他Server的Include Definition(B),那么Include Definition(B)不应该引用Include Definition(A),否则就是循环引用(Circular Reference),当一个Client检测到循环引用或detects nested include declarations to a greater level than it expects,Client应当终止本次通信(ATT Bearer)

Characteristic
由Characteristic Definition定义,包含一个Characteristic声明、Characteristic属性、值、值的描述(Optional)

- Characteristic Declaration                       : First 
- Characteristic Value declaration                 : Second 
- Characteristic Descriptor Declarations(Optional) : Last(含多个时顺序不关紧要)

Characteristic:在 GATT 事务中的最低界别的是 Characteristic,它是最小的逻辑数据单元,当然它可能包含几个关联的数据,例如加速度计的 X/Y/Z 三轴值。
Characteristic声明,Attribute Type=0x2803,与 Service 类似,从特性声明0x2803开始到下一个0x2803之间的内容都同属于一个特性。
在这里插入图片描述
Characteristic声明Attribute Value是特性Value的“特性Properties+属性Handle+特性UUID”(注意Properties和Handle是程序添加的,不是真实存在,实际存储中Characteristic声明Attribute Value只有特性UUID)。
特性Properties的用法,比如可用于广播、可读、可写等。
属性Handle是程序用来标识一个属性,它指向定特性里面的第一个属性值得Handle。因GATT是基于ATT的,所以Profile实际就是属性列表,成为为每个属性用一个Handle标识,制作成一个表,Handle值是按顺序生成的:
在这里插入图片描述
上面表格中,Handle为0x0012和0x0013才是一个正常的Characteristic的Value。它也是一个Attribute,可以免费使用 Bluetooth SIG 官方定义的标准 Characteristic,Attribute Type是个UUID,由官方定义的(参考《16-bit UUID Numbers Document.pdf》),可以确保 BLE 的软件和硬件能相互理解。当然,你可以自定义 Characteristic,这样的话,就只有你自己的软件和外设能够相互理解。
以上面表格为例:表中是一个Service,Service UUID=0x180F,查《16-bit UUID Numbers Document.pdf》知道这是电池服务。电池服务特性声明是0x2803,Value指出首个特性的UUID是0x2A19。查《16-bit UUID Numbers Document.pdf》知道特性0x2A19是电量计数,Value域中包含了电池的当前电量。
特性描述配置(这里只是简单介绍)的属性类型0x2902(查《16-bit UUID Numbers Document.pdf》),这样客户端在discover时能知道这个特性描述配置是从属于当前特性的,因为两个特性之间的所有属性同属于前一个特性。特性配置描述支持客户端的订阅,并存储客户端的订阅Handle。当特性值发生变化时,通知客户端的订阅者。针对电池服务来说,当电量发生改变时,通知客户端。
实际上,和 BLE 外设打交道,主要是通过 Characteristic。你可以从 Characteristic 读取数据,也可以往 Characteristic 写数据。这样就实现了双向的通信。所以你可以自己实现一个类似串口(UART)的 Sevice,这个 Service 中包含两个 Characteristic,一个被配置只读的通道(RX),另一个配置为只写的通道(TX)。

  1. Configured Broadcast
    对于LE物理链路,在Server广播模式过程中,Client通过Configured Broadcast告知Server应该在advertising data加入Characteristic Value,方法是Client设置指定bit位;广播频率则是Service、Characteristic行为定义的一部分

  2. Summary of GATT Profile Attribute Types
    在这里插入图片描述

  3. GATT 连接的网络拓扑
    下图展示了 GTT 连接网络拓扑结构。这里很清楚的显示,一个外设只能连接一个中心设备,而一个中心设备可以连接多个外设。ConnectedTopology一旦建立起了连接,通信就是双向的了,对比前面的 GAP 广播的网络拓扑,GATT 通信是双向的。如果你要让两个设备外设能通信,就只能通过中心设备中转。
    在这里插入图片描述

  4. GATT 通信事务
    ATT 通信的双方是 C/S 关系。外设作为 GATT 服务端(Server),它维持了 ATT 的查找表以及 service 和 characteristic 的定义。中心设备是 GATT 客户端(Client),它向 Server 发起请求。需要注意的是,所有的通信事件,都是由客户端(也叫主设备,Master)发起,并且接收服务端(也叫从设备,Slave)的响应。
    一旦连接建立,外设将会给中心设备建议一个连接间隔(Connection Interval),这样,中心设备就会在每个连接间隔尝试去重新连接,检查是否有新的数据。但是,这个连接间隔只是一个建议,你的中心设备可能并不会严格按照这个间隔来执行,例如你的中心设备正在忙于连接其他的外设,或者中心设备资源太忙。
    下图展示一个外设(GATT 服务端)和中心设备(GATT 客户端)之间的数据交换流程,可以看到的是,每次都是主设备发起请求:
    在这里插入图片描述

功能要求

  1. Overview
    GATT中定义了11项Feature
.  Server Configuration
.  Primary Service Discovery
.  Relationship Discovery
.  Characteristic Discovery
.  Characteristic Descriptor Discovery
.  Reading a Characteristic Value
.  Writing a Characteristic Value
.  Notification of a Characteristic Value
.  Indication of a Characteristic Value
. Reading a Characteristic Descriptor
. Writing a Characteristic Descriptor

每个Feature都有对应的过程和子过程,这些过程描述了如何使用ATT来实现各自的功能。

  1. Feature Support and Procedure Mapping
    本节内容省略,请参阅协议。

  2. Server Configuration
    该过程可被Client用来配置Attribute Protocol的MTU大小
    Exchange MTU
    Client使用该子过程来设置适配双方均支持的最大ATT_MTU,在BR/EDR物理链路中不应该使用该过程,而应该使用L2CAP Channel Configuration Procedures。该过程对应于ATT的MTU Exchange Request/Response,见<Bluetooth ATT介绍 - 4.2 MTU Exchange>

  3. Primary Service Discovery
    Client使用该过程来发现服务端的Primary Services。一旦发现服务存在,可通过其他过程来访问Primary Services的附加信息(关联主服务和次服务),可使用的其他过程包括Characteristic Discovery和Relationship Discovery。
    该过程包括两个子过程:

- Discover All Primary Services
- Discover Primary Services by Service UUID

在BR/EDR物理链路上则使用SDP service discovery来发现服务

  • Discover All Primary Services

Client使用该子过程来发现服务端的所有Primary Services。该子过程使用ATT的Read By Group Type Request,同时设置如下参数

- Starting Handle : 0x0001
- Ending Handle   : 0xFFFF
- Attribute Type  : UUID for <Primary Service>

可能的回应有

- Read By Group Type Response
- Error Response

Read By Group Type Response返回三元组列表,三元组包括

- Attribute Handle : 服务声明的Handle
- End Group Handle : 服务定义中最后一个Attribute的Handle
- Attribute Value  : 服务端支持的服务的Service UUID

当收到Error Response时;则表明该过程已经完成。
当Client找到自己所需要的服务时,可以终止该过程。
Note: 3.1中已指出Service Declaration是可读,并且不需要认证或授权;因此权限相关的错误不会发生

下图是一个实例图
在这里插入图片描述

  • Discover Primary Service by UUID

当Client知道了Service UUID时,可以使用该子过程来发现对应的主服务
该子过程使用ATT的Find By Type Value Request,同时设置参数如下

- Starting Handle : 0x0001
- Ending Handle   : 0xFFFF
- Attribute Value : 16-bit Bluetooth UUID or 128-bit UUID
- Attribute Type  : UUID for <Primary Service>

可能的回应有

- Find By Type Value Response
- Error Response

Find By Type Value Response返回Attribute Handle ranges列表,Attribute Handle range即服务定义的Starting Handle和Ending Handle,如果Attribute Handle range中的End Found Handle不是0xFFFF;那么Client将会再请求一次Req,同时将Starting Handle设置为收到的最后一个Attribute Handle+1
终止规则和权限问题同Discover All Primary Services
下图是一个实例图
在这里插入图片描述

  1. Relationship Discovery
    Client使用该过程来发现和其他服务的服务关系
  • Find Include Services

Client使用该子过程来发现一个服务定义包含的服务申明
该子过程使用ATT的Read By Type Request,同时设置参数如下

- Starting Handle : 所要查找服务的Starting Handle
- Ending Handle   : 所要查找服务的Ending Handle
- Attribute Type  : UUID for <Include>

可能的回应有

- Find By Type Response
- Error Response

Find By Type Response返回[Attribute Handle, Attribute Value]集合对,Attribute Value由所包含服务申明的Attribute Handle和End Group Handle组成,当UUID为16-bit Bluetooth UUID时,那么它也将包含在Rsp中
该Req应该被再次请求,同时设置Starting Handle为为收到的最后一个Attribute Handle+1
当Rsp中包含的服务申明中Attribute Handle等于Req的Ending Handle时,该子过程被认为完成(当然Attribute Not Found-Error Rsp也是)
当Include Service使用128-bit UUID时,使用Read Request来获取Include Service UUID,其中Attribute Handle参数设置为Include Service的Attribute Handle
权限规则同上面
下图是一个实例图
在这里插入图片描述

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

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

相关文章

鉴源论坛丨汽车电子ISO 26262:2018标准概述(一)

作者 | 郭建 上海控安可信软件创新研究院特聘专家 版块 | 鉴源论坛 观模 摘要&#xff1a;安全在汽车研发中是关键要素之一&#xff0c;辅助驾驶、车辆的动态控制等功能的研发和集成都需要加强安全系统研发&#xff0c;同时&#xff0c;需要为满足所有预期的安全目标提供证据…

牛客网最新890道大厂 Java 八股文面试题整理

程序员真的是需要将终生学习贯彻到底的职业&#xff0c;一旦停止学习&#xff0c;离被淘汰&#xff0c;也就不远了。 面试跳槽季&#xff0c;这是一个千年不变的话题&#xff0c;每到这个时候&#xff0c;很多人都会临阵磨枪&#xff0c;相信不快也光。于是&#xff0c;大家都…

2023 最新版navicat 下载与安装 步骤及演示 (图示版)

2023 最新版navicat 下载与安装 步骤演示 -图示版 1. 下载Navicat2 .安装navicat 博主 默语带您 Go to New World. ✍ 个人主页—— 默语 的博客&#x1f466;&#x1f3fb; 《java 面试题大全》 &#x1f369;惟余辈才疏学浅&#xff0c;临摹之作或有不妥之处&#xff0c;还请…

三子棋小游戏【C语言】

目录 前言 一、基本实现逻辑 二、实现步骤 1.实现进入游戏后的选择菜单——》这个实现起来较为容易&#xff0c;我们约定为&#xff1a;1是玩游戏&#xff0c; 0 是退出游戏&#xff01; 2.要玩完了一局后接着玩&#xff0c;很容易想到要用循环。 3.采用多文件编程---》我…

0011-TIPS-pawnyable : Heap-Overflow

原文 Linux Kernel PWN | 040202 Pawnyable之堆溢出 Holstein v2: Heap Overflowの悪用 题目下载 漏洞代码 #include <linux/module.h> #include <linux/kernel.h> #include <linux/cdev.h> #include <linux/fs.h> #include <linux/uaccess.h>…

【Nginx介绍和安装与升级】

文章目录 Nginx网站服务一、nginx服务基础1. Nginx简介2. Tengine3. Nginx 相对于 Apache 的优点4. 阻塞与非阻塞 同步与异步5. nginx 应用场景 二、编译安装nginx 服务1. 在线安装nginx2. nginx编译安装1. 关闭防火墙&#xff0c;将安装nginx所需软件包传到/opt目录下2. 安装依…

二维码标签制作教程

如今二维码已被广泛应用在了许多场景中&#xff0c;譬如设备巡检、固定资产盘点、隐患上报、人员管理等&#xff0c;在二维码投入使用前需要为设备、物品、人员等制作一物一码标签。为了让标签快速落地&#xff0c;可使用草料二维码的标签制作功能&#xff0c;只需选择心仪的标…

Cortext-M3系统:中断的具体行为(6)

1、中断/异常的响应序列 当CM3开始响应一个中断时&#xff0c;会在它小小的体内奔涌起三股暗流&#xff1a; ​ 入栈&#xff1a;把8个寄存器的值压入栈 ​ 取向量&#xff1a;从向量表中找出对应的服务程序入口地址 ​ 选择堆栈指针MSP/PSP&#xff0c;更新堆栈指针SP&#xf…

数据恢复技巧:如何恢复已删除的手机短信

短信包含大量重要信息&#xff0c;例如个人联系人、密码和重要业务数据。丢失有价值的数据可能会令人失望&#xff0c;但很高兴知道可以使用多种方法恢复短信。 在本文中&#xff0c;我们将探讨您可以采取哪些步骤来恢复 Android 或 iOS 设备上丢失或删除的短信。 第 1 部分…

chatgpt赋能python:Python指定区域截图:优化截图流程的最佳方式

Python指定区域截图&#xff1a;优化截图流程的最佳方式 在网络时代&#xff0c;图片作为一种重要的信息传播方式&#xff0c;扮演着举足轻重的角色。截图作为最常见的图片处理方式之一&#xff0c;也时常被我们用于记录屏幕内容、报告问题及展示操作流程。 若想提高截图的效…

操作系统-I/O管理-磁盘和固态硬盘

目录 一、磁盘结构 二、磁盘调度算法 ​编辑 2.1先来先服务(FCFS) 2.2最短寻找时间优先(SSTF) 2.3扫描算法(SCAN) 2.4LOOK调度算法 2.5循环扫描算法(C-SCAN) 2.6 C-LOOK调度算法 三、减少延迟时间方法 交替编号 ​磁盘地址结构的设计 错位命名 四、磁盘的管理 4.1磁盘…

JDK自带的构建线程池的方式之newFixedThreadPool

在Java中基于Executors提供了很多种线程池供开发者使用&#xff0c;在Java的并发包下&#xff0c;由并发编程大佬到隔离创建。 newFixedThreadPool 这个线程池的特点是线程数是固定的&#xff0c;下面这个是在Executors类中提供的一种静态方法。在使用的时候需要向方法提供一个…

Excel VBA 语法基础

VBA&#xff08;Visual Basic for Applications&#xff09;是一种用于宏编程和自动化任务的编程语言&#xff0c;广泛应用于 Microsoft Office 套件中的各种应用程序&#xff0c;如 Excel、Word 和 PowerPoint。掌握 VBA 基础语法可以帮助您通过编写自定义的宏来增强和自动化这…

python:使用Scikit-image对遥感影像进行角点检测特征提取(corner)

作者:CSDN @ _养乐多_ 本文将介绍使用Scikit-image对遥感影像进行角点检测特征(corner)提取的一些方法及其代码。方法包括 Harris角点检测(corner_harris),Shi-Tomasi角点检测(corner_shi_tomasi),Foerstner角点检测(corner_foerstner),FAST角点检测(corner_fast…

VUE 2X 计算监视属性 ⑥

目录 文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持✨ V u e j s Vuejs Vuejs计算属性 C o m p u t e d Computed Computed监视属性 W a t c h Watch Watch总结 文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;…

Apache Superset产品调研

Apache Superset产品调研 调研报告&#xff1a;Apache Superset 一、概述 Apache Superset是一个开源的数据可视化和数据探索平台&#xff0c;它提供了一个用户友好的界面&#xff0c;可以轻松地创建和分享仪表板。它支持多种数据源&#xff0c;包括SQLAlchemy兼容的数据库、…

io.netty学习(九)Netty 如何实现零拷贝

目录 前言 Java 实现零拷贝 1、Java提供 mmap/write 方式 2、Java 提供 sendfile 方式 Netty 实现零拷贝 1、CompositeByteBuf 方式 2、wrap 方式 3、slice 方式 4、 FileRegion 方式 总结 前言 本篇文章我们就来讲讲 Netty 的零拷贝&#xff0c;在这之前&#xff0…

数据结构练习题1:基本概念

练习题1&#xff1a;基本概念 1 抽象数据类型概念分析2. 逻辑结构与存储结构概念分析3.综合选择题4.综合判断题5.时间复杂度相关习题 1 抽象数据类型概念分析 1.可以用&#xff08;抽象数据类型&#xff09;定义一个完整的数据结构。 分析&#xff1a; 1&#xff09;抽象数据…

【Leetcode -617.合并二叉树 -1022.从根到叶的二进制数之和】

Leetcode Leetcode -617.合并二叉树Leetcode -1022.从根到叶的二进制数之和 Leetcode -617.合并二叉树 题目&#xff1a;给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#x…

ESP32-IDF VS Code进行开发

ESP32-C3 入门篇&#xff08;二&#xff09;使用VS Code进行开发 文章目录 前言 总结STM32的成功&#xff0c;除了Cortex M3的性能强之外&#xff0c;也离不开ST推出的标准库及简单易用的MDK IDE。完善的开发配套&#xff0c;极大的降低了开发门槛&#xff0c;让开发者更专注…