BLE协议栈架构如下所示:
用户开发应用程序或者说service的时候,调用的都是GATT API,而GATT又调用了ATT API。
BLE client/server(C/S) 架构
1、上图所示的Request和Response其实就是我们经常说的ATT命令(ATT PDU),也就是说Client和Server之间通过ATT PDU进行交互。
2、在BLE中,数据是通过characteristic进行包装的,而且多个characteristic组成一个service,service是一个独立的服务单元,或者说service是一个基本的BLE应用。
3、如果某个service是一个蓝牙联盟定义的标准服务,也可以称其为profile,比如HID/心率计/体温计/血糖仪等,都是标准蓝牙服务,因此都有相应的profile规格书。
一个characteristic包含三种条目:characteristic声明,characteristic的值以及characteristic的描述符(可以有多个描述符),如下所示:
1、characteristic declaration就是每个characteristic的分界符,包含value的读写属性等。
2、Characteristic value就是数据的值。
3、Characteristic descriptor就是数据的额外信息,比如温度的单位是什么,数据是用小数表示还是百分比表示等之类的数据描述信息。
4、CCCD是一种特殊的characteristic descriptor,可以使用CCCD来关闭characteristic的notify或者indicate功能。
5、client访问server的characteristic,我们把这种操作称为读或者写。
6、server可以直接把自己的characteristic的值告诉client,我们称其为notify或者indicate。
7、当characteristic具有notify或者indicate操作功能时,那么必须为其添加相应CCCD,以方便client来使能或者禁止notify或者indicate功能。
不管是characteristic declaration,characteristic value还是characteristic descriptor,实现的时候,我们都是用attribute来表达的,也就是说,他们每一个都是一个attribute,attribute可以用下图来表示:
1、Attribute handle,Attribute句柄,16-bit长度。Client要访问Server的Attribute,都是通过这个句柄来访问的,也就是说ATT PDU一般都包含handle的值。用户在软件代码添加characteristic的时候,系统会自动按顺序地为相关attribute生成句柄。
2、Attribute type,Attribute类型,2字节或者16字节长。在BLE中我们使用UUID来定义数据的类型,UUID是128 bit的,所以我们有足够的UUID来表达万事万物。其中有一个UUID非常特殊,它被蓝牙联盟采用为官方UUID,这个UUID如下所示:
3、Attribute value,就是数据真正的值,0到512字节长。
4、Attribute permissions,Attribute的权限属性,权限属性不会直接在空中包中体现,而是隐含在ATT命令的操作结果中。假设一个attribute read属性设为open(即读操作不需要任何权限),那么client去读这个attribute时server将直接返回attribute的值;如果这个attribute read属性设为authentication(即需要配对才能访问),如果client没有与server配对而直接去访问这个attribute,那么server会返回一个错误码:告诉client你的权限不够,此时client会对server发起配对请求,以满足这个attribute的读属性要求。目前主要有如下四种权限属性:
Open,直接可以读或者写
No Access,禁止读或者写
Authentication,需要配对才能读或者写,由于配对有多种类型,因此authentication又衍生多种子类型,比如带不带MITM,有没有LESC
Authorization,跟open一样,不过server返回attribute的值之前需要应用先授权,也就是说应用可以在回调函数里面去修改读或者写的原始值。
Signed,签名后才能读或者写,这个用得比较少。
5、每个attribute都有一个handle和UUID,handle用来访问该attribute,UUID用来指明该attribute的类型。可以说,server提供数据,而数据是由attribute来表达,所有attribute组成一个attribute table,设备支持的服务不同,attribute table就不同。这里说明一下,当你在Nordic已有例程基础上再去添加新的服务或者删除已有的服务,记得一定要去修改ATTR_TAB_SIZE那个宏,否则协议栈初始化会有问题。