属性是一个离散值,由下面四部分组成:
Attribute Handle
属性句柄是 server 给属性分配的一个 16-bit 的数值,client 可以通过该值访问属性。server 上同一属性类型的属性可能存在多个,可通过属性句柄进行区分。
任何给定服务器上的属性句柄都应具有唯一的非零值。 属性按属性句柄排序。
取值范围:0x0000(保留,无法使用)-0xFFFF(最大值)
Attribute Type
universally unique identifier(UUID) 用于标识每种属性类型。 在所有空间和时间上,UUID 被认为是唯一的。
UUID 是一个 128-bit 的数值。为了减轻存储和传输 128 位 UUID 值的负担,已预先分配了一系列 UUID 值,用于分配给经常使用的、注册的用途。 此预分配范围内的第一个 UUID 称为蓝牙基础 UUID(Bluetooth base UUID),其值为 00000000-0000-1000-8000-00805F9B34FB。
预分配范围内的 UUID 值具有16-bit 或 32-bit UUID 的别名,但需要注意的是,每个别名实际上代表一个 128-bit UUID 值。
16-bit 或 32-bit UUID 的完整 128-bit 可以通过简单的算术运算来计算。
Attribute Value
属性值是一个八位字节数组(octet array),可以是固定长度或可变长度。例如,它可以是一个八位字节(octet)的值、四字节的整数或可变长度的字符串。
Attribute Permissions
属性权限是属性的一部分,不能使用属性协议读取或写入。 服务器使用它来确定是否允许客户端对给定属性进行读取或写入访问。 属性权限由 GATT 配置文件、更高层配置文件建立,或者如果未指定,则具体实现。
属性权限是访问权限(access permissions)、加密权限(encryption permissions)、认证权限(authentication permissions)和授权权限(authorization permissions)的组合。
access permissions
ReadableWriteableReadable and writable encryption permissions
Encryption requiredNo encryption required authentication permissions
Authentication RequiredNo Authentication Required authorization permissions
Authorization RequiredNo Authorization Required
逻辑属性表示如下:
属性 PDU 有六种类型,如下表所示:
Attribute Protocol PDU 格式如下:
属性协议中的多字节字段应首先发送最低有效字节(least significant octet)(小端(little endian)),但属性值字段除外。 属性值字段的字节顺序由更高层规范定义。
属性操作码由三个字段组成,分别为:
认证签名标志(Authentication Signature Flag)
如果属性操作码的认证签名标志设置为 1,则认证签名值应附加到属性 PDU 的末尾,X 为 13。
如果属性操作码的认证签名标志设置为零,则不附加认证签名值,X 为 1。命令标志(Command Flag)
如果属性操作码的命令标志设置为 1,则 PDU 应被视为命令。方法(Method)
方法是一个 6-bit 值,用于确定属性参数的格式和含义。
属性操作码总结如下:
顺序协议
许多属性协议 PDU 使用顺序请求-响应(request-response)协议。
一旦客户端向服务器发送请求,在收到响应 PDU 之前,该客户端不得向同一服务器发送其他请求。从服务器发送的指示也使用顺序指示确认(indication-/confirm/iation)协议。 在收到确认 PDU 之前,不得从该服务器向同一客户端发送其他指示。 但是,客户端可以在发送确认之前自由发送命令和请求。对于没有响应 PDU 的通知,没有流量控制,可以随时发送通知。不需要响应的命令没有任何流控制。 注意:服务器可以被命令淹没,更高层的规范可以定义如何防止这种情况发生 属性协议 PDU Reading Attributes
读属性包含 10 个 PDU,分别为 Read By Type Request 、Read By Type Response、 Read Request、 Read Response 、Read Blob Request 、Read Blob Response、 Read Multiple Request、 Read Multiple Response、 Read by Group Type Request、 Read by Group Type Response。
Read Request
读取请求(Read Request)用于向服务器请求读取属性的值,并在读取响应( Read Response)中返回该值。
读取请求的格式如下:
Read Response
读取响应(Read Response)是作为对接收到的读取请求(Read Request)的回复而发送的,其中包含已读取的属性值。
读取响应的格式如下:
使用 ESP32 作 server,手机端作 client 抓取到的数据包为例:
手机对特征 0xff01进行读取操作:
Writing Attributes
写属性包含四个 PDU,分别为 Write Request、Write Response、Write Command 和 Signed Write Command。
本文主要对前三个 PDU 进行说明:
Write Request
写入请求(Write Request)用于向服务器请求写入属性的值,并在写入响应(Write Response)中确认这已实现。
写入请求的格式如下:
Write Response
写入响应(Write Response)是作为对有效写入请求(Write Response)的回复而发送的,并且确认属性已成功写入。
写入响应的格式如下:
Write Command
写入命令(Write Command)用于向服务器请求写入属性的值。
写入命令的格式如下:
手机端对特征 0xff01 进行写操作:
手机端使能特征 0xff01 的描述符 0x2902:
服务器发送通知数据给客户端:
通用属性配置文件 (GATT) 使用属性协议定义了服务框架。 该框架定义了服务及其特征的过程和格式。 定义的过程(procedures)包括发现、读取、写入、通知和指示特征,以及配置特征的广播。
GATT Profile 使用属性协议在设备之间以命令(commands)、请求(requests)、响应(responses)、指示(indications)、通知(notifications)和确认(/confirm/iations)的形式传输数据。 该数据包含在属性协议 PDU 中。
GATT 涵盖以下场景:
交换配置发现设备上的服务和特征读取特征值写入特征值特征值通知特征值指示 GATT 层次结构
GATT 配置文件(profile)指定交换配置文件数据的结构。
此结构定义了配置文件中使用的基本元素,例如服务和特征。 所有元素都包含在属性中。 属性协议中使用的属性是承载此配置文件数据的容器。
该层次结构的顶层是配置文件。 配置文件由实现用例所需的一项或多项服务组成。 服务由特征或对其他服务的引用组成。 每个特征都包含一个值,并且可能包含有关该值的可选信息。 服务和特征以及特征的组件(即值和描述符)包含配置文件数据,并且都存储在服务器上的属性中。
服务声明(Service Declaration)
特征定义包含特征声明( characteristic declaration)、特征值声明(Characteristic Value declaration),可能包含特征描述符声明(characteristic descriptor declaration)。
特征声明
特征值声明
特征描述符声明
GATT 配置文件属性类型总结 下表总结了 GATT 配置文件定义的属性类型:
下表描述了 ATT 协议操作码到 GATT 过程和子过程的映射。