目录
前言
蓝牙的分类
BLE协议框架
关键术语及概念
GAT
简介
广播数据格式
广播网络拓扑
GATT
简介
GATT 连接的网络拓扑
GATT 通讯事务
服务和特征
简介
Service
Characteristic
参考鸣谢
最近由于项目需求在学习 BLE,网上Android BLE开发 的资料相比其他 Android 资料显得有些匮乏,在此记录学习例程,希望能能对学习 BLE 的童鞋有所帮助。
在上手 Android 之前我们需要先搞清楚蓝牙的协议及通讯过程,才不会在调用 Google 提供的 API 时似懂非懂。
当前的蓝牙协议分为 基础率 / 增强数据率(BR/EDR)和 低耗能(BLE)两种类型。
当然现在 BLE蓝牙模块 还有单模和双模之分,单模指的是 仅支持BLE ,双模即 Bluetooth Classic + BLE。
蓝牙BD/EDR和蓝牙BLE主要区别
蓝牙协议规定了两个层次的协议,分别为 蓝牙核心协议(Bluetooth Core)和 蓝牙使用层协议(Bluetooth Application)。
蓝牙核心协议关心对蓝牙核心技术的描述和规范,它只提供基础的机制,并不关心如何运用这些机制;
蓝牙使用层协议,是在蓝牙核心协议的基础上,根据具体的使用需要定义出各种各样的策略,如 FTP、文件传输、局域网...
蓝牙核心协议(Bluetooth Core)又包含 BLE Controller 和 BLE Host 两部分。
这两部分在不一样的蓝牙技术中(BR/EDR、AMP、BLE),承担角色略有不一样,但大致的功能是相同的。
Controller 负责定义 RF、Baseband 等偏硬件的规范,并在这之上抽象出用于通信的逻辑链路(Logical Link);
Host 负责在逻辑链路的基础上,进行更为友好的封装,这样就可以屏蔽掉蓝牙技术的细节,让 Bluetooth Application 更为方便的运用。
BLE 低功耗蓝牙核心协议层详解(Bluetooth Core)
物理层(Physical Layer,简写 PHY):PHY层 用来指定 BLE 所用的 无线频段,调制解调方式等。例如 1Mbps 自适应跳频的 GFSK 射频,工作于免许可证的 2.4GHz ISM(工业、科学与医疗)频段。
链路层(Link Layer,简写 LL):LL层 是整个 BLE 协议栈 的核心。LL 层 要做的事情非常多,比如 选择射频通道 ,怎么 识别空中数据包,具体在 哪个时间点把数据包发送出去,怎么 保证数据的完整性,ACK 如何接收,如何进行重传,以及 如何对链路进行管理和控制 等等。
ps:LL 层只负责把数据发出去或者收回来,对数据进行怎样的解析则交给上面的 GAP 或者 ATT。
主机控制接口层(Host Controller Interface,简写 HCI):HCI 是 可选的,HCI 主要用于 2 颗芯片实现 BLE 协议栈 的场合,用来规范两者之间的通信协议和通信命令等。
通用访问配置文件层(Generic access profile,简写 GAP):GAP 是对 LL 层 payload(有效数据包)进行 解析 的两种方式中的一种,而且是最简单的那一种。GAP 简单的对 LL payload 进行一些规范和定义,因此 GAP 能实现的功能极其有限。
ps:GAP 现在主要用来进行广播,扫描和发起连接等。
逻辑链路控制及自适应协议层(Logical Link Control and Adaptation Protocol,简写 L2CAP):L2CAP 对 LL 进行了一次简单封装,LL 只关心传输的数据本身,L2CAP 就要 区分是加密通道还是普通通道,同时还要 对连接间隔进行管理。
安全管理层(Security Manager,简写 SM):SMP 用来管理 BLE 连接的加密和安全的,如何保证连接的安全性,同时不影响用户的体验,这些都是 SMP 要考虑的工作。
属性协议层(Attribute protocol,简写 ATT):简单来说,ATT 层用来定义用户命令及命令操作的数据,比如读取某个数据或者写某个数据。BLE 协议栈中,开发者接触最多的就是 ATT。BLE 引入了 attribute(属性) 概念,用来描述一条一条的数据。Attribute 除了定义数据,同时定义该数据可以运用的 ATT 命令。
通用属性配置文件层(Generic Attribute profile,简写 GATT):GATT 用来规范 attribute 中的数据内容,并运用 group(分组)的概念对 attribute 进行分类管理。没有 GATT,BLE 协议栈 也能跑,但互联互通就会出问题,也正是因为有了 GATT 和各种各样的使用 profile,BLE 摆脱了 ZigBee 等无线协议的兼容性困境,成了出货量最大的 2.4G 无线通信产品。
GATT 是一个在蓝牙连接之上的发送和接收很短的数据段的通用规范,这些很短的数据段被称为属性(Attribute)。
安卓官方文档中显示:目前所有低能耗应用配置文件均基于 GATT。
介绍 GATT 之前,需要了解 GAP(Generic Access Profile),它在用来 控制设备连接和广播 。GAP 使你的设备被其他设备可见,并决定了你的设备是否可以或者怎样与其他设备进行交互。例如 Beacon 设备就只是向外广播,不支持连接,小米手环就等设备就可以与中心设备连接。
GAP 给设备定义了若干角色,其中主要的两个是:外围设备(Peripheral)和中心设备(Central)。
在 GAP 中外围设备通过两种方式向外广播数据: Advertising Data Payload(广播数据)和 Scan Response Data Payload(扫描回复),每种数据最长可以包含 31 byte。这里广播数据是必需的,因为外设必需不停的向外广播,让中心设备知道它的存在。广播间隔越长,越省电,同时也不太容易扫描到。扫描回复是可选的,中心设备可以向外设请求扫描回复,扫描回复可以包含一些额外的数据,例如设备的名字。
说明
Flags: TYPE = 0x01。这个数据用来标识设备 LE 物理连接的功能。VALUE 是 0 到多个字节的 Flag 值,每个 bit 上用 0 或者 1 来表示是否为 True。如果有任何一个 bit 不为 0,并且广播包是可连接的,就必须包含此数据。各 bit 的定义如下:
Service UUID: 广播数据中一般都会把设备支持的 GATT Service 广播出来,用来告诉外面本设备所支持的 Service。有三种类型的 UUID:16 bit, 32bit, 128 bit。广播中,每种类型类型有有两个类别:完整和非完整的。这样就共有 6 种 Type。
Local Name: 设备名字,VALUE是名字的字符串。Local Name 可以是设备的全名,也可以是设备名字的缩写,其中缩写必须是全名的前面的若干字符。
TX Power Level: TYPE = 0x0A,表示设备发送广播包的信号强度。VALUE部分是一个字节,表示 -127 到 + 127 dBm。
带外安全管理(Security Manager Out of Band):TYPE = 0x11。VALUE也是 Flag,每个 bit 表示一个功能:
外设(Slave)连接间隔范围:TYPE = 0x12。数据中定义了 从设备 Slave 最大和最小连接间隔,数据包含 4 个字节:
服务搜寻:外围设备可以要请中心设备提供相应的 Service。其数据定义和前面的 Service UUID 类似:
Service Data: Service 对应的数据。
公开目标地址:TYPE = 0x17,表示希望这个广播包被指定的目标设备处理,此设备绑定了公开地址,VALUE 是目标地址列表,每个地址 6 字节。
随机目标地址:TYPE = 0x18,定义和前一个类似,表示希望这个广播包被指定的目标设备处理,此设备绑定了随机地址,VALUE 是目标地址列表,每个地址 6 字节。
Appearance:TYPE = 0x19,VALUE是表示了设备的外观。
厂商自定义数据: TYPE = 0xFF,厂商自定义的数据中,前两个字节表示 厂商ID,剩下的是厂商自己按照需求添加,里面的数据内容可以自己定义。
其他说明可查看 官方文档 BLE广播类型定义
大部分情况下,外设通过广播自己来让中心设备发现自己,并建立 GATT 连接,从而进行更多的数据交换。但是也有些情况是不需要连接的,只要外设广播自己的数据即可。用这种方式主要目的是让外围设备,把自己的信息发送给多个中心设备。而基于 GATT 连接的方式中,只能是一个外设连接一个中心设备。使用广播这种方式最典型的应用就是苹果的 iBeacon。它将自定义数据插入 Manufacturer Specific Data 中。其网络拓扑如下:
在外围设备和中央设备之间建立连接后,广播通常会停止,并使用 GATT 的服务和特征实现双向的通信。
GATT 的全名是 Generic Attribute Profile(普通属性协议),它定义两个 BLE 设备通过叫做 Service 和 Characteristic 的东西进行通信。GATT 就是使用了 ATT(Attribute Protocol)协议,ATT 协议 把 Service, Characteristic 对应的数据保存在一个查找表中,查找表使用 16 bit ID 作为每一项的索引。这个 ID 貌似就是后面的 UUID 。
一旦两个设备建立起了连接,GATT 就开始起作用了,这也意味着,你必需完成前面的 GAP 协议。
GATT 连接,必需先经过 GAP 协议。实际上,我们在 Android 开发中,可以直接使用设备的 MAC 地址,发起连接,可以不经过扫描的步骤。这并不意味不需要经过 GAP,实际上这只是为我们提供的接口。蓝牙芯片发起连接,总是先扫描设备,扫描到了才会发起连接。
GATT 连接需要特别注意的是:GATT 连接是独占的。这意味着 BLE 外围设备一次只能连接到一个中心设备(手机等)一旦外设被连接,它就会马上停止广播,这样它就对其他设备不可见了。当设备断开,它又开始广播。而中央设备是可以连接到多个外围设备的。
中心设备和外设需要双向通信的话,唯一的方式就是建立 GATT 连接。
一个外设只能连接一个中心设备,而一个中心设备可以连接多个外设。
一旦建立起了连接,通信就是双向的了,对比前面的 GAP 广播的网络拓扑,GAP 通信是单向的。如果你要让两个设备外设能通信,就只能通过中心设备中转。
GATT 通信的双方是 C/S 关系。外设作为GATT 服务端(Server),它维持了 ATT 的查找表以及 service 和 characteristic 的定义。中心设备是 GATT 客户端(Client),它向 Server 发起请求。需要注意的是,所有的通信事件,都是由客户端(也叫主设备,Master)发起,并且接收服务端(也叫从设备,Slave)的响应。
一旦连接建立,外设将会给中心设备建议一个连接间隔(Connection Interval), 这样,中心设备就会在每个连接间隔尝试去重新连接,检查是否有新的数据。但是,这个连接间隔只是一个建议,你的中心设备可能并不会严格按照这个间隔来执行,例如你的中心设备正在忙于连接其他的外设,或者中心设备资源太忙。
下图应说明外围设备(GATT 服务器)和中央设备(GATT 客户端)之间的数据交换过程:
可以看到,每个时间间隔中,都说是由中央设备(GATT 客户端)首先发起请求,外围设备(GATT 服务器)给予响应。
BLE 中的 GATT 事务 基于名为 Profiles,Services 和 Characteristics 的高级嵌套对象,而每一个Characteristic 还包含了一个 value和 n 个描述符Descripter。其嵌套结构如下:
BLE 外设本身实际上不存在配置文件,它是由 Bluetooth SIG 或外围设计人员编译的预定义Service 集合。可在此处查看官方采用的基于 GATT 的配置文件的完整列表 配置文件概述 。
Service 用于将数据拆分为逻辑实体,它包含称为“Characteristic”的数据块。 Service 可以具有一个或多个Characteristic;每个Service 以 UUID 作为唯一数字 ID 以此将其自身与其他Service 区分开来。UUID 可以是 16 位(官方正式采用的 BLE Service )或 128 位(自定义Service ) )。
可以在 Bluetooth Developer Portal 的 “ Service ” 页面上看到正式采用的 BLE Service 的完整列表。
UUID 形如 0x18xx 都是 BLE自身定义的Service ;而 128 位的是厂商自定义的 Service
GATT 事务中的最低级别概念是 Characteristic ,其作用是封装单个数据点。当然它可能包含一个组关联的数据,例如加速度计的 X/Y/Z 三轴值。
与 Service 类似,每个Characteristic 通过预定义的 16 位或 128 位 UUID 进行区分,我们可以使用官方蓝牙 SIG 定义的标准特性(确保可互操作和支持 BLE 的硬件 / 软件)也可以自行定义Characteristic 。
Characteristic 是与 BLE 外设交互的要点,我们读写操作是通过读写 Characteristic 来完成的。实际上,和 BLE 外设打交道,主要是通过 Characteristic。我们可以从 Characteristic 读取数据,也可以往 Characteristic 写数据。这样就实现了双向的通信。
例如:我们定义了一个具有读写权限的Characteristic
Bluetooth 官方BLE介绍
Android 官方BLE介绍
简书系列——Aandroid蓝牙BLE
协议讲解--GATT Profile 简介