BLE 协议之 GATT



在上一节讲了什么是 ATTATT 之所以称作 protocol,是因为它还比较抽象,仅仅定义了一套机制,允许 Client 和 Server 通过 Attribute 的形式共享信息。而具体共享哪些信息,ATT 并不关心,因为这是由 GATTGeneric Attribute Profile)来控制。

GATT 相对 ATT 只多了一个 G,但含义却大不同,因为 GATT 是一个 profile(更准确的说是 profile framework)。

在蓝牙协议中,profile 一直是一个比较抽象的概念,我们可以将其理解为“应用场景、功能、使用方式”都被规定好的 Application。传统的BR/EDR 如此,BLE 更甚。上面我们讲过,BLE很大一部分的应用场景是信息(Attribute)的共享,因此,BLE协议栈基于Attribute Protocol,定义了一个称作 GATTGeneric Attribute)的 profile framework(它本身也是一个 profile),用于提供通用的、信息的存储和共享等功能。

一、简介

GATTGeneric Attributes):通用属性, 低功耗蓝牙的设备之间的通信协议 。

GATT 使用 ATT 协议, 定义了一套服务框架,用于发现、读写、通知、广播信息的配置 。

角色的定义
为了更好的实现 GATT 的 profile 概要文件, GATT 定义了如下角色:

  • Client :主要向服务器发送命令和请求,接收服务器的响应
  • Server :接收命令和请求,发送响应

二、协议框架

GATT Profile 定义了用于通信的数据结构,包括 servicescharacteristics


由上图可知, GATT profile 的层次结构依次是: Profile —> Service —> characteristic。

  • 最顶层的是 profile,一个 profile 由一个或者多个 service 组成。
  • 一个 service 又由 characteristics 组成。
  • 每个 characteristicpropertyvaluedescriptor 组成。

1、Profile

GATT Profile 可以理解为一种规范,一个标准的通信协议 ,它存在于从机中。它定义了如何使用 ATT 协议去广播、发现、读写相关属性信息。

下面是 Attribute Type 的类型:

2、Service

2.1 Service 定义

Service 服务是完成特定功能或特性的数据和相关行为的集合 。

在 BLE 从机中,通过有多个服务,例如电量信息服务、系统信息服务等,每个 service 中又包含多个 characteristic 特征值。每个具体的 characteristic 特征值才是 BLE 通信的主题。

比如当前的电量是 80%,所以会通过电量的 characteristic 特征值存在从机的 profile 里,这样主机就可以通过这个 characteristic 来读取80%这个数据。

一个 Service 的定义包括了: Service 声明、(可选的) include 定义、(可选的) characteristic 定义。

2.2 Service 声明

  • Attribute Type :服务类型有两种,分别为 primary servicesecondary service ,即 首要服务和次要服务 ,对应的 Attribute Type 分别为 0x2800 或 0x2801 ,
  • Attribute Value :是一个16 位 UUID 或者 128 位的 UUID 。用来表示这是什么服务。
  • Attribute permission :表示这个该声明即这个 ATT 属性是只读的、无需验证的、无需授权的。

3、include

3.1 include 定义

include 用于去引用已定义存在的服务,相当于 C 语言中的 include 包含。

include 定义仅仅包含一个 include Declaration

3.2 include 声明

include Declaration 如下:

  • Attribute Type :服务类型为 include ,对应的 Attribute Type 为 0x2802 。
  • Attribute Value :设置为所要引用的服务的 Attribute HandleEnd Group HandleUUID
  • Attribute permission :表示这个该声明即这个ATT属性是只读的、无需验证的、无需授权的。

4、Characteristic

4.1 Characteristic 定义

characteristic 包含了特征的定义。

BLE 主从机的通信均是通过 characteristic 来实现,可以理解为一个标签,通过这个标签可以获取或者写入想要的内容。

characteristic 的定义包含了 characteristic declarationCharacteristic Value declarationcharacteristic descriptor declaration,其中前两个属性是必须的,最后一个属性是可选的。

characteristic = characteristic声明 + characteristic value声明 + 可选的descriptor声明

4.2 Characteristic 声明

Characteristic declaration 如下:

  • Attribute Type :服务类型为 Characteristic ,对应的 Attribute Type 为 0x2803 。
  • Attribute Value :设置为 Characteristic PropertiesCharacteristic Value Attribute HandleCharacteristic UUID
  • Attribute permission :表示这个该声明即这个 ATT 属性是只读的、无需验证的、无需授权的。

Attribute Value 字段如下 :


一个服务,可能有多个 characteristic definitions 用相同的 Characteristic UUID

Characteristic Properties 字段如下:

  • Characteristic Value Attribute Handle :包含了 characteristic value 的句柄
  • Characteristic UUID :是一个 16 位 UUID 或者 128 位的 UUID 。

4.3 Characteristic Value 声明

Characteristic Value Declaration 如下 :

Characteristic Valuecharacteristic 声明后的第一个属性。

  • Attribute Type :该字段的值设置为 Characteristic 声明时的 UUID
  • Attribute Value :为所声明的 Characteristic 中相同 UUID 的属性的值。
  • Attribute permission :由上层权限指定

4.4 Characteristic Descriptor 声明

Characteristic descriptors 主要用于包含一些与 Characteristic Value 相关的信息,GATT 定义了多种可选 descriptors ,如下:

  • Characteristic Extended Properties
  • Characteristic User Description
  • Client Characteristic Configuration
  • Server Characteristic Configuration
  • Characteristic Presentation Format
  • Characteristic Aggregate Format

每一种 descriptor 都有其特有的格式。

4.4.1 Characteristic Extended Properties

Characteristic Extended Properties declaration 是一个定义扩展特征属性的描述符。characteristic descriptor 可以出现在特征值之后的特征定义内的任何位置。在一个特征定义中只能存在一个特征扩展属性声明。

  • Attribute Type :应设置为 Characteristic Extended Properties 的 UUID,对应的值为 0x2900
  • Attribute Value :长度应为两个字节,并应包含特征扩展属性位字段
  • Attribute permission :只读,不需要身份验证和授权即可读取。

特征扩展属性位域描述了如何使用特征值或如何访问特征描述符的附加属性。如果设置了下表中定义的比特位,则允许描述的操作。可以设置多个附加属性。

4.4.2 Characteristic User Description

Characteristic User Description 是一个可选的特征描述符,它定义了一个可变大小的UTF-8字符串,该字符串是特征值的用户文本描述。

如果设置了特征扩展属性的可写辅助位,则可以写入该特征描述符。characteristic descriptor 可以出现在特征值之后的特征定义内的任何位置。在一个特征定义中只能存在一个特征用户描述声明。

  • Attribute Type :该字段的值设置为 Characteristic user description ,对应的值为 0x2901
  • Attribute Value :为定义的 UTF-8 字符串
  • Attribute permission :由上层权限指定
4.4.3 Client Characteristic Configuration

Client Characteristic Configuration 是一个可选的特征描述符,它定义了特定客户端如何配置特征。客户端特征配置描述符值应该在绑定设备的连接之间持久存在。客户端特征配置描述符值应设置为与非绑定设备的每个连接的默认值。特征描述符值是位域。当一个比特位被设置时,该操作将被启用,否则将不会被使用。客户端特征配置描述符可以出现在特征值之后的特征定义中的任何位置。在一个特征定义中只能存在一个客户端特征配置声明。

客户端可以编写这个配置描述符来控制服务器对客户端的这个特性的配置。每个客户端都有自己的客户端特征配置实例。客户端特性配置的读操作只显示该客户端的配置,而写操作只影响该客户端的配置。服务器可能需要身份验证和授权来编写配置描述符。客户端特性配置声明应该是可读可写的。

  • Attribute Type :该字段的值设置为 Client Characteristic Configuration ,对应的值为 0x2902
  • Attribute Value :长度为2个字节,设置为特征描述符值
  • Attribute permission :无需身份验证或授权即可读取。可写的身份验证和授权由更高的层规范定义或具体实现

下表定义了下列客户端特征配置位:


客户端特性配置描述符的默认值应该是 0x0000。

在客户端和服务器之间应该有一个单一的客户端特征配置描述符,而不管它们之间的ATT承载的数量。

4.4.4 Server Characteristic Configuration

Server Characteristic Configuration 声明是一个可选的特征描述符,它定义了如何为服务器配置特征。特征描述符值是位域。当一个比特位被设置时,该操作将被启用,否则将不会被使用。服务器特征配置描述符可以出现在特征值之后的特征定义内的任何位置。在一个特征定义中只能存在一个服务器特征配置声明。

  • Attribute Type :该字段的值设置为 Server Characteristic Configuration ,对应的值为 0x2903
  • Attribute Value :长度为2个字节,设置为特征描述符值
  • Attribute permission :无需身份验证或授权即可读取。可写的身份验证和授权由更高的层规范定义或具体实现

4.4.5 Characteristic Presentation Format

Characteristic Presentation Format 是一个可选的特征描述符,它定义了特征值的格式。特征描述子可以出现在特征值之后的特征定义内的任何位置。如果一个特征定义中存在多个特征表示格式声明,则一个特征聚合格式声明应作为该特征定义的一部分存在。

特征表示格式值由格式、指数、单位、名称空间和描述五个部分组成。

  • Attribute Type :该字段的值设置为 Characteristic Presentation Format ,对应的值为 0x2904

  • Attribute Value :特征描述符值

  • Attribute permission :只读的,不需要认证或授权

    Attribute Value 字段含义:

  • Format:确定特征值中包含的单个值的格式。该字段的值定义在分配的数字中

  • Exponent:用于整型数据类型,用于确定值的进一步格式化方式。该字段仅用于整数格式类型,指数字段的类型是 sint8。
    a c t u a l v a l u e = C h a r a c t e r i s t i c V a l u e ∗ 1 0 E x p o n e n t actual value = Characteristic Value * 10^{Exponent} actualvalue=CharacteristicValue10Exponent

由上式可以看出,实际值是特征值和 10 的幂指数的组合。这有时被称为定点数。

例:

  • 如果指数是 2,特征值是 23,那么实际值就是 2300。

  • 如果指数是 -3,特征值是 3892,那么实际值就是 3.892。

  • Unit:UUID,见 Assigned Numbers

  • Name Space:用于标识负责定义 Description 字段枚举的组织,见 Assigned Numbers

  • Description:一个枚举值,定义在由 Name Space 字段标识的组织分配的编号中。

4.4.6 Characteristic Aggregate Format

Characteristic Aggregate Format 是一个可选的特征描述符,它定义了聚合特征值的格式。特征描述子可以出现在特征值之后的特征定义内的任何位置。一个特征定义中只能存在一个特征集合格式声明。

  • Attribute Type :该字段的值设置为 Characteristic Aggregate Format ,对应的值为 0x2905
  • Attribute Value :由特征表示格式声明的属性句柄列表组成,其中每个属性句柄指向一个特征表示格式声明
  • Attribute permission :只读的,不需要认证或授权
### 使用蓝牙BLE GATT协议在Android应用中实现实时数据传输并进行图形绘制 #### 1. 准备工作 为了能够在Android设备上通过蓝牙低功耗(Bluetooth Low Energy, BLEGATT协议实现上位机绘图,首先需要确保已经安装了支持BLE的硬件和软件环境。nRF Connect作为一款功能强大、操作简便的蓝牙连接辅助工具,在蓝牙技术的不断发展和普及中扮演着越来越重要的角色[^1]。 #### 2. 建立BLE连接 建立BLE连接的过程主要包括扫描周边可用的BLE设备、发起连接请求以及处理服务发现流程。以下是简化版的代码片段用于初始化BLE管理器: ```java public class BluetoothLeService extends Service { private final static String TAG = BluetoothLeService.class.getSimpleName(); public void initialize() { // 初始化BluetoothManager 和 BluetoothAdapter. final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); // 检查设备是否支持BLE. if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show(); stopSelf(); } // 设备不支持Bluetooth,则无法继续执行. if (mBluetoothAdapter == null) { Log.e(TAG, "Unable to obtain a BluetoothAdapter."); stopSelf(); return; } } } ``` #### 3. 数据接收与解析 当成功建立了与目标设备之间的通信链路之后,就可以利用GATT特性来读取来自外设的数据流。这些接收到的信息通常会被编码成字节数组的形式传递给应用程序层,因此有必要定义一套清晰的消息格式以便于后续解码过程中的准确性。 #### 4. 实现图表绘制逻辑 对于实时数据显示的需求来说,推荐采用高效的Canvas API来进行动态图像渲染。每当有新的测量值到达时就触发一次重绘事件,并将最新的一系列坐标点连结起来形成连续曲线。下面给出了一段简单的例子展示如何基于View类创建自定义视图组件完成这一任务: ```java import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import androidx.annotation.Nullable; import android.util.AttributeSet; public class LineChartView extends View { private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); List<Float> dataPoints; @Override protected void onDraw(Canvas canvas){ super.onDraw(canvas); int width = getWidth(), height=getHeight(); float margin=50f; RectF bounds=new RectF(margin,margin,width-margin,height-margin); Path path=new Path(); if(dataPoints!=null && !dataPoints.isEmpty()){ Iterator iterator=dataPoints.iterator(); Float firstValue=(Float)iterator.next(); path.moveTo(bounds.left,bounds.bottom-firstValue*(bounds.height()/MAX_VALUE)); while(iterator.hasNext()){ Float value=(Float)iterator.next(); path.lineTo( ((float)dataPoints.indexOf(value)/dataPoints.size())*bounds.width()+bounds.left, bounds.bottom-value*(bounds.height()/MAX_VALUE) ); } }else{ // Handle empty dataset case here... } paint.setColor(Color.BLUE); paint.setStrokeWidth(8f); canvas.drawPath(path,paint); } public void updateData(List<Float> newData){ this.dataPoints=new ArrayList<>(newData); invalidate(); // Request redraw with updated values. } } ``` 此部分实现了基本线条图的功能,可以根据实际应用场景调整样式属性如颜色、线宽等参数以满足特定需求。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值