转载自:http://www.cydaxiang.com/2016/11/ble-stack-gap/
GAP(Generic Access Profile)通用访问规范层算是BLE协议栈中最顶部的一层,它定义了设备如何广播、扫描、发现和建立连接,以及配置工作角色(Role)、可发现性、广播数据内容和安全相关的参数。从编程视角来看,GAP中的内容就像是一个config文件,BLE协议栈其他层的工作,都要从GAP中获取初始化参数和配置信息。
GAP中定义了一系列模式(Mode)和规程(Procedure),二者相互配合,完成广播和连接的工作。
有以下几种种GAP角色:
第五种Central&Peripheral,在内部是两种角色进行按需转换,并非一种独立的角色。
中央设备是向外围发起连接的设备,连接起来后就称为主设备(Master)。Peripheral是向外部广播的设备,连接起来后称为从设备(Slave)。因为建立连接需要进行数据收发,所以无论是Central还是Peripheral,他们都必须具有数据接收和发送的能力。
广播者是一个纯广播设备,观察者是一个纯扫描设备。假如功能需求极其简单,这两种角色可以是只接收或只发送的设备。
iBeacon设备就可以设置为一个广播者角色。
与GAP角色相似的还有一个GATT角色概念。GATT角色包括以下三种:
GATT Server是指数据服务器,有发送数据的需求,GATT Client指数据客户端,有接收数据的需求。GATT Server的特征值有Read/Write/Indicate等属性,配置后可以收发处理数据;而GATT Client的特征值是没有这些属性的,仅能够扫描读取GATT Server的特征值,针对Server的特征值进行读写。
所以大多数情况下,Central扮演着GATT Client的角色,而Peripheral扮演着GATT Server的角色。不过这并不绝对,理论上无论Central还是Peripheral设备,它都可以是GATT Server,或者GATT Client。
比如Alert Notification Profile,它是一个主机,提供扫描功能,但是连接后它是数据源,向外部提供数据,承担Server责任,因而它是GAP Central + GATT Server。
总而言之,GAP角色决定了谁广播谁扫描,GATT角色决定了数据从哪里出发。
BLE设备地址为6字节,分两部分,前半部分为公司部分,后半部分为设备部分。一个典型的BLE设备地址为:00A050-123456,00A050表示Cypress,123456表示设备序号。
BLE广播时候会携带设备地址,扫描时候也会记录设备地址,如果两个设备使用相同的地址,则会产生冲突,所以BLE的设备地址应该保证唯一。后半部分3个字节总共6个字符空间,总的可用地址数:16 ^ 6 = 16777216。这个数字对于一个普通的应用,应该绰绰有余。
为了保证地址唯一性,有以下2个办法:
1)根据芯片的随机信息生成随机地址
2)在量产时候用上位机累加或随机算法避免重复
第一个方法在PSoC BLE中很常用,它利用芯片的Silicon ID等信息,生成一个3字节的随机数。Silicon ID是一个芯片唯一信息,加上一些算法处理,获得的3字节数在10年内遇到重复的几率极小,所以可以在普通的应用中使用。
第二个方法,是在量产时候,将地址信息写入SFlash中,每次地址信息都不相同,BLE程序启动时候,先从sFlash中读出地址信息并设置自身设备地址。
注意这里的随机地址,只是两个设备相互之间不同,对于某个设备,一旦写入,就是确定了的。这些地址都属于下面提到的public address。
在协议栈内部,地址分为两类public address和random address。random address又分为static address和private address。private address又分为resolvable private address和non-resolvable private address。如下图:
通常使用的地址都是public address,即明文地址。有些场合为了提高设备的隐私性(Privacy),可以使用resolvable private address,如果将设备地址标记为这一类型,从外部看来,每次重连,设备的地址都会发生变化,与之绑定的另一端设备需要利用IRK(身份解析密钥)对加密地址进行解码,进而获得原始地址。
在GAP中设置的GAP名字,会反映到GATT Generic Access Service下的Device Name特征值的数据。它通常跟广播包中的设备名相同,也可以人为设置不同。
设备名字最长不应超过128字节,支持UTF-8字符,所以我们可以使用中文名字。
关于设备名字,在以前的文章中有详述。
设置不同的图标,可以在手机APP上显示出来。
这两个词(Mode,Procedure)都可以描述设备在一段时间内以一种状态或方式运行,但是在GAP层的描述中被重点区分。模式强调设备在一段时间内被设置为某种状态,规程强调设备在某种模式下去执行某种动作。
举个例子,Discovery Mode表示发现模式,有“可被发现”和“不可被发现”等模式,这个参数适用于从机(Peripheral),描述从机的运行状态;而Discovery Procedure表示发现规程,有“普通发现”和“受限发现”等规程,这个参数适用于主机(Central),描述主机怎么去发现从机。类似的,从机有绑定模式,主机执行绑定规程等。
模式和规程大致相互对应,从机有某种模式,主机就有相应的规程。
这几个概念其实属于链路层(Link Layer),前面文章链路层的的“广播”一节有详细介绍。这里简单回顾一下:
可连接+无定向广播是最常用广播,它的广播数据可以被周边主机发现,可以携带扫描响应数据,同时可以被连接。
可扫描+无定向广播是指可以携带扫描响应数据,但不能被连接。
不可连接+无定向广播指不能携带扫描响应数据,也不能被连接。
可连接+定向广播指只能被指定的主机发现和连接。
主动扫描是指Central设备发出SCAN_REQ,从机收到后返回SCAN_RSP。于是从机可以在扫描响应(scan response)数据中加入一些数据,等待主机主动扫描。
被动扫描是指Central设备不发出SCAN_REQ,仅仅接收从机的广播数据,无法获取扫描响应数据。
BLE SPEC中建议在广播数据中存放变化的数据,静态的数据放在扫描响应数据中。
绝大多数Central设备都是用主动扫描,我至今没有见到被动扫描的设备。
发现模式与广播模式相互关联,“不可发现模式”下,只能选择Scannable undirected advertising和Non-connectable undirected advertising两种广播模式,即这种发现模式下,BLE设备不可以被连接。“广播器模式”下也只能选择不可被连接的广播模式。“受限发现模式”和“普通发现模式”下,可以任意选择广播模式。
第一种不可发现模式,使广播设备不被发现,参考 。注意,这里不被发现是指不被执行“普通发现规程”的Central设备发现。如果Central设备执行观察规程(obverving procedure),仍然能够看到广播信号。而手机APP等软件默认为观察规程,所以假如使用手机BLE扫描APP来测试,依旧可以看到设为“不可发现模式”的广播设备。正确的测试方法是使用CySmart(PC),将主机的扫描规程设置为“普通”或“受限”,而不是“观察者”,就能够观察到正确现象。
第三种为普通发现模式,可以选择任意的广播模式,然后自由处理各项参数。
第二种受限发现模式,这里“受限”是指受时间限制。与普通发现模式相比,这个模式好像只是强制要求广播超时参数,其他相同。但是二者的“含义”是不同的,一个受限发现的设备,即有超时限制的设备,给Central传达一个消息,我很快就不行了,要连接应赶紧。所以Central设备如果发现了多个广播设备,在显示设备列表的时候,应该有意识的将受限发现模式的设备放在前面,而普通发现模式的设备放在后面。
广播数据中有两个标志位:LE General Discovery Mode和LE Limited Discovery Mode,分别设置这两个标志位即可设置发现模式。
前两个发现规程,基本上是为了匹配上面前三种发现模式而设计的。
如果Central使用普通发现规程,则能够发现“受限发现模式”和“普通发现模式”的设备,不能发现“不可发现模式”设备。如果Central使用受限发现规程,则仅能够发现“受限发现模式”的设备。对于观察期规程,则能发现各种发现模式下的广播设备。
这几个连接模式与上面的几种定向、无定性的广播模式基本对应,确定了广播模式,就会在内部建立相应的连接模式。
自动连接规程,需要白名单(White List)的配合,即只能自动连接白名单中的设备,不是毫无限制的自动连接。
普通连接规程,就是最常用的连接方式。
选择连接规程,这个“选择”是选择合适的连接参数。Central周边有多个广播设备,从机的连接参数各不相同,主机设备可以选择期望的连接参数设备进行连接。选择连接规程与自动连接规程都用于一拖多的场景,一对一的场景,他们俩几乎功能一样。
定向连接规程,与定向广播模式相对应。
与连接相关的规程,还有:
就是将配对过程中的密钥保存起来,详细过程参考前面关于安全管理(SM)层的介绍。
模式1是进行加密形式的配对,模式2是进行签名形式的配对。这两种模式含义很明了,不明白BLE协议为什么没有取个有意义的名字。
模式1下有三种安全等级:
第一种是无安全,不认证也不加密,俗称裸奔。第二、三种均进行加密,第三种做认证,第二种不认证。
第二种安全等级将使用Just Works配对方式,而第三种安全等级则根据IO Capability选择合适的配对方式。
第四种安全等级是BLE v4.2新增的选项。BLE配对时候传输Passkey有被窃听风险,而这种等级使用特殊算法避免传输Passkey被窃听。
模式2有两种安全等级:
跟模式1相比,不做数据加密,而是进行数据签名。这种模式,链路不进行加密。
数据签名和数据加密,可以通过这个帖子有个感性的认识。简单的讲,加密是将数据明文转成密文,而签名则不改动数据本身,但是伴随数据额外提供一份事先约定好的信息,接收方一看到这个额外信息就知道是指定的发送方发来的消息,于是确认这个消息的真实性。这个额外信息,就是“签名”。如果没有这个签名,假如第三方攻击者混入通信链路,发出伪造消息,接收方就无法判断消息真伪。在配对过程的第三个阶段,分发一系列的密钥,其中CSRK就是用于数据签名的密钥。
广播包最大长度为31字节,广播包中可以包含多种元素,各个元素的格式是确定的:
AD Element = Length + AD Type + AD Data
其中Length = length(AD Type) + lenght(AD Data)。
一些常用过的元素如下:
全部元素列表参考官方页面。
对于Flags,它的数据内容为单字节数,在CySmart(PC)上可以清楚看到各个bit表示的含义:
其中BR/EDR指Basic Rate/Enhanced Data Rate,是经典蓝牙的特性,对BLE设备,这几项标志位应该清空,对于双模和经典蓝牙设备,则按需置位。
其他元素在使用时候稍加理解便知其义,这里不做赘言。
关于广播包的讲解,网上帖子一大把,比如:1, 2, 3。
Generic Access Service是每个BLE设备都有的服务,可以理解为强制服务。该服务项中包括:
Generic Access Service |- Device Name |- Appearance |- Peripheral Preferred Connection Parameters (PPCP)
由于每个设备都有这个Device Name,所以主机端可以通过UUID读取特征值数据,快速获取设备名。在Android系统中,APP是通过广播包中的Device Name来识别设备名的,在iOS系统中,则不管广播包,只认这个GAP服务下的Device Name。
Appearance就是个图标。
外设期望连接参数PPCP,BLE主机可以通过UUID快速读取PPCP的特征值数据,获取从机期望的连接参数信息。市面上大多数APP并不去读这个参数,从而只能在从机中发起更新连接参数的请求,显式的告诉主机更新连接参数。
(完)