赞
踩
前篇博文Generic Access Profile介绍了蓝牙设备之间是如何发现彼此、建立连接、实现配对与绑定的,同时描述了设备如何实现无需连接的数据传输、如何实现等时同步数据传输、如何建立ACL和CIS 连接、如何加密认证通信链路等。
本篇文章主要介绍蓝牙设备建立连接后,如何提供或响应服务、如何发现或请求服务,这就要靠GATT(Generic Attribute Profile)来定义了,GATT 为蓝牙设备定义了Server role 和Client role 两种角色(角色并不固定在设备上,同一设备不同时刻充当的角色可能不同):
Server 根据设计需求会实现并向外公开一个或多个服务,Client 则根据需要发现Server 公开的部分或全部服务。Client 发现Server 提供的服务后,就可以向其请求相应的服务数据(既可以读取服务器状态信息比如温度传感器的值,又可以改变服务器的状态比如控制LED灯的亮灭),Server 接收到服务请求后会向Client 响应对应的服务数据(Server 可能需要Client 通过认证与授权)。
BLE 采用“Server – Client” 架构,Server 专注于定义如何使用一个或多个属性来实现某种特定的服务(包括可以提供的状态信息、可以执行的状态切换等)以及如何访问并使用这些服务(比如客户端请求可读取/可写入状态信息、服务器可通知状态更新信息、访问服务是否需要加密/认证/授权等);Client 专注于定义如何使用一个或多个服务来满足某种特定的应用需求(比如可以使用光强感应服务、人体感应服务、照明服务等协同实现智能照明服务)。
Server 定义的每个单独服务十分简单、而且是原子化的(表示一种服务只执行不可分割的特定操作),可以让每个服务的行为更简单明确,同时让不同服务之间的组合更丰富多样。Client 使用不同的原子服务组合,可以满足丰富多样的场景需求,相同的服务可以在不同应用中复用,满足高内聚、低耦合的设计原则。
为何说明Client 请求服务、Server 响应服务的工作原理,下面扩展前篇博文谈到的用户场景:
用户购买的心率带设备为了安全传输心率数据,是可以被发现并连接的,对外公开的主要有心率服务、电池电量服务、设备名服务等。用户的智能手机通过GAP 规范发现并连接了心率带设备(可以通过公开的设备名服务从设备列表中选出目标设备),由于用户需求是获得心率值,心率带对外提供该服务,因此心率带处于Server role,智能手机处于Client role。
Client role 与Server role 建立连接后,Client role 首先需要知道Server role 能提供哪些服务,然后再根据应用规范去使用这些服务。Client role 发现Server role 公开服务的过程主要有四个:Primary Service Discovery(可以发现所有主要服务或者某一特定主要服务)、Relationship Discovery(该服务引用的其它服务)、Characteristic Discovery(可以发现所有特性或者某一特定特性)、Characteristic Descriptor Discovery。 智能手机先发现心率带公开的心率服务和电池电量服务,再发现心率服务引用的时间服务(Secondary Service),接着发现心率服务包含的HRM Characteristic(Heart Rate Measurement) 和BSL Characteristic(Body Sensor Location),最后发现HRM Characteristic 包含的CCCD(Client Characteristic Configuration Descriptor)。Heart Rate Service、Characteristic、Descriptor 之间的关系如下图示,每一行四个字段Handle、UUID、Permissions、Value 共同构成一个属性,Characteristic 与Descriptor 都是由一个或多个属性构成的。
Client role 已经发现了Server role 公开的所有Primary Service及其相关的Characteristic 和Descriptor,接下来看Client role 如何使用Server role 提供的服务。智能手机可通过特定APP向心率带发起服务请求读取心率值,心率带将当前采集到的心率值返回给智能手机(也可以配置为允许心率带主动通知智能手机当前的心率值),如果再为心率带增加时间服务,智能手机APP 就可以借助心率服务和时间服务为用户绘制心电图,并给出心率健康评估结果。Handle 0x0021 属性是Heart Rate Service 的declaration(声明服务类型为心率服务),Handle 0x0024 和0x002A 属性分别是HRM Characteristic 和BSL Characteristic 的declaration(声明特性性质为只读,特性数值属性句柄分别为0x0027和0x002C),Handle 0x0027 和0x002C 属性分别是HRM Characteristic 和BSL Characteristic 的Value(描述特性数值的表示格式,心率测量值单位bpm – beats per minute,身体测量位置为手指),Handle 0x0028 属性是HRM Characteristic 的Descriptor(客户端特性配置为启用通知,允许服务端主动通知客户端更新后的心率值)。
GATT 使用属性协议定义了服务框架,方便Client 与Server 之间实现基于服务请求/响应的通信,简化了蓝牙设备应用程序的开发。一个服务通常包含多个属性,GATT 定义了如何使用属性协议来发现、读取、写入这些属性数据。
最上层的Application 应用层在Server 服务端主要是基于属性协议定义各种服务的GATT 规范,在Client 客户端主要是定义如何发现并使用这些服务来满足某种特定的应用需求或实现某种特定的业务逻辑,本文主要介绍如何定义、发现、使用服务的GATT 规范。Attribute protocol 相当于GATT 的承载层,GATT 定义的服务是由多个属性组成的,Attribute protocol 定义了属性的报文格式和支持的操作方法。L2CAP 逻辑链路控制适配协议定义了报文的分片重组、重传流控,上层GATT 或Attribute protocol 层数据封装为SDU(Service Data Unit),下层Controller 数据封装为PDU(Protocol Data Unit)。
在继续介绍GATT Profile 之前,先介绍一个蓝牙协议中比较重要的两个概念UUID(Universally Unique Identifier) 和Attributes。
UUID(Universally Unique Identifier) 通用唯一识别码是一个128位(16字节)的数字,可以保证在所有空间和所有时间都是唯一的。除了蓝牙之外,UUID 还用于许多协议和应用中(特别是分布式计算领域),它们的格式、用法在IETF(Internet Engineering Task Force)公布的标准 RFC 4122 中定义(技术上等同于 ITU-T Rec. X.667 | ISO / IEC 9834-8:2005 规范)。
完整的UUID 需要占用16字节,这对于链路层27字节的有效数据载荷长度算是不小的负担,为了减轻存储、传输128位UUID 的负担,BLE 规范添加了两个附加的UUID 格式:16位UUID 和32位UUID。这些16位或32位的UUID 可以看作是基于Bluetooth Base UUID (00000000-0000-1000-8000-00805F9B34FB) 的偏移量,因此只能与Bluetooth 规范中定义的UUID 一起使用,也可以称为标准Bluetooth UUID。这些标准Bluetooth UUID 可以借助Bluetooth Base UUID 重建为完整的128位UUID,只需要经过如下的运算即可:
128_bit_value = 16_bit_value * 296 + Bluetooth_Base_UUID
128_bit_value = 32_bit_value * 296 + Bluetooth_Base_UUID
16位UUID 可以通过高位补零转换为32位UUID 格式,当UUID 包含在ATT PDU 中时,所有32位UUID 都应转换为128位UUID。
16位UUID 虽然已经比较简短了,为了增加可读性,通常不直接使用数值,而是起一个名称并加上书名号来表示,比如用《Include》 来表示数值为0x2802 的UUID。UUID 并没有定义自身的用法,为了增加人工调试时的可读性,BLE 常用的那部分UUID 被分为以下几组:
- 0x1800 ~ 0x26FF 用作 Service UUIDs
- 0x2700 ~ 0x27FF 用于标识计量单位 Units
- 0x2800 ~ 0x28FF 用于区分 Attribute Types
- 0x2900 ~ 0x29FF 用作 Characteristic Descriptors
- 0x2A00 ~ 0x7FFF 用于区分 Characteristic Types
Attribute 是ATT(Attribute protocol)定义的最小数据实体,也是构成GATT 中Service、Characteristic、Descriptor 的基本元素。每个Attribute 都包含有关属性本身的信息和实际数据,客户端与服务器之间进行的服务交互,最终都是对这些属性的操作访问。从前文GATT Heart Rate Service 图示了解到,Attribute 由Handle、UUID、Permissions、Value 四部分构成,其逻辑表示如下:
下面给出某BLE 设备属性服务器定义的部分属性供参考,支持的服务属性包括:GAP Service、GATT Service、Battery State Service、Thermometer Humidity Service、Weight Service、Position Service、Alert Service、Manufacturer Service和Vendor Specific Service等(下图用《》括起来的名字是UUID 的另一种表示方式,Attribute Value 中被{ } 括起来的部分表示该属性值由多个字段组成,被“ ” 括起来的部分表示字符串)。
GATT 中定义了的Profile 由一个或多个Service 组成,每个Service 可以看作是完成特定功能或特性的数据和相关行为的集合,由一个或多个Characteristic 构成。每个Characteristic 一般都包含一个数据或者一个公开行为,以及该数据的单位或者公开行为的单位。GATT Profile 的数据层级结构如下图示:
上述介绍的构成GATT Profile 的Service、Include Service、Characteristic、Characteristic Descriptor 等元素的属性汇总如下:
前面介绍了如何使用Attribute 构成GATT Profile 数据层级结构,这里介绍如何使用Attribute protocol 来完成GATT Profile 定义的各种功能。GATT Profile 主要定义了如下11 个功能(feature),每个功能都映射到过程(procedure)和子过程(sub-procedure),这些过程和子过程描述了如何使用Attribute protocol 来完成相应的功能(下表中的M:Mandatory,O:Optional )。
上述介绍的每个GATT 功能及其子过程到ATT 属性协议操作指令之间的映射关系汇总如下(属性协议操作指令将会在下文介绍):
前面已经介绍了Attribute 的逻辑结构,这里主要介绍Attribute 的报文格式和支持的操作指令或方法。
Attribute PDU 包含三个部分:1 字节长度的指令操作码、可变长度的属性参数、可选的12 字节长度认证签名信息,属性PDU 格式如下:
Attribute PDU 中的Attribute Parameters 字段通常包含前面介绍的属性逻辑结构中Attribute Handle、Attribute Type、Attribute Value、Attribute Permissions 四个字段中的零个或多个,只有Server 与Client 之间需要交互的字段信息才会包含在Attribute PDU 中。
GATT Profile 的Procedure 描述了如何使用Attribute protocol 来完成相应的Feature,Client 通过Attribute protocol 可以发现并获取或更改属性服务器上的属性。按照Client 与Server 之间的交互方式划分,Attribute protocol 由以下六种基本操作构成(也即Attribute PDU 有六种基本类型,由后缀区分):
Attribute protocol 支持的操作指令汇总如下(对照GATT procedure 到ATT protocol opcodes 的映射关系更容易理解):
本文开头已经介绍了在Attribute protocol 与LE Controller 之间还有一层L2CAP(Logical Link Control and Adaptation Protocol and Adaptation Protocol) 协议层,L2CAP 协议层的功能架构图如下(可以将L2CAP 协议与TCP 协议对比理解):
L2CAP 既然起到多协议复用器的作用,可以将多个逻辑信道映射到同一个物理信道,为了便于区分不同的逻辑信道,L2CAP 报文需要包含Channel ID 字段,下面给出L2CAP 的基本报文格式如下(为了实现更多上述功能,L2CAP 还有更复杂的报文格式):
BLE 协议栈中L2CAP 支持的CID (Channel ID) 类型如下:
上述CID 主要分为两类:一类是固定信道,比如为Attribute protocol 分配的CID 是0x0004、为L2CAP LE Signaling channel 分配的CID 是0x0005、为Security Manager protocol 分配的CID 是0x0006;另一类是使用过程中动态分配的可变信道。下文将分别对BLE 支持的三个L2CAP 固定信道报文及指令做简单介绍。
前面介绍的只是Basic L2CAP Mode下的报文格式,L2CAP 为Flow Control Mode、(Enhanced) Retransmission Mode、Streaming Mode、LE (Enhanced) Credit Based Flow Control Mode 提供了更复杂的报文结构如下(本文不展开介绍了,可以参考Core_v5.2 手册的[Vol 3] Part A, Section 3 ):
从L2CAP architectural blocks 图中可以看到两种数据流:红色的Controls frame 和黑色的Data/packet flow,其中Controls frame 用于L2CAP 信道管理,传输Controls frame 信道为signaling channel,在signaling channel 上传输的Controls frame(C-frame) 格式如下:
对于BLE 协议,在signaling channel 上传输的Controls frame 的CID 为0x0005(对于BR/EDR 协议,C-frame 的CID 为0x0001)。Controls frame 的Information payload 部分是signaling command format,包括信令操作码Code、信令标识符Identifier、数据长度Length、数据信息data 四个部分,这里只列出BLE 协议常用的信令操作码及其描述如下(这里删去了BR/EDR支持而BLE不支持的信令操作码):
前篇博文介绍了Security Manager protocol 的配对过程,两个设备之间要完成配对也需要双方交互相关的指令或报文,SMP 配对和安全管理相关的指令或报文格式如下:
L2CAP 为Security Manager protocol 分配的Channel ID 为0x0006,SMP command Information payload 包含指令操作码Code 和数据Data 两部分,这里列出BLE 支持的SMP 指令操作码如下:
下面依然按照BLE 配对过程的三个阶段简单介绍SMP 指令:
Attribute protocol 的报文格式前面已经介绍过了,在L2CAP 层加上一个L2CAP Header,其中Channel ID 为0x0004,报文格式如下:
Attribute protocol 支持的操作指令前面已经介绍过了,这里不再赘述。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。