目录
一、全面掌握广播
1、广播的基本概念和流程
1.1、广播的基本概念
1.2、广播的四种类型:
1.3、广播的配置、启动和停止(下面以Nordic蓝牙芯片为例进行说明)
2、广播数据包报文结构:
2.1、前导
2.2、接入地址
2.3、报头
2.4、长度
2.5、数据(AdvData)
2.6、校验
3、广播里可以含有的数据
4、设备地址
4.1、公共地址
4.2、随机地址
5、本地设备名称
5.1、设备名称示例:
5.2、应用场景
6、外观
6.1、加入外观的步骤
6.2、如何确保外观的值以及如何在广播中设置是否含外观
7、Flags
7.1、有限可发现模式和一般可发现模式的区别
7.2不支持BR/EDR
8、发射功率等级
9、服务的UUID
9.1、既然UUID是128位的数字,那么为什么还有16位的UUID?
9.2、UUID分为标准的UUID和厂商自定义的UUID
9.3、加入服务UUID的步骤和需要注意的地方
10、服务数据
10.1、服务数据的定义
10.2、加入服务数据的步骤
11、从设备连接间隔范围
11.1、从设备连接间隔范围定义
11.2、加入从设备连接间隔范围的步骤
12、厂商自定义数据
12.1、厂商自定义数据的定义
12.2、加入厂商自定义数据的步骤
二、实现一个标准的Profile
1、配置文件、服务和特征
1.1、Profile(配置文件)
1.2、服务
1.3、Characteristic(特征)和描述符
2、需求描述
2.1、角色
2.2、需求表和依据
广播就是设备将自身愿意展示的信息按照一定的间隔依“扫描者”可以理解的方式向周边发射。
广播报文的报头中有4个位专门用来指示广播报文的类型。
BLE报文结构如下,它有下图所示的各个域组成。因为有的域的长度超过了一个字节,所以在传输的过程中就涉及到多字节域中哪个字节先传输的问题,BLE报文传输时的字节域和比特序如下:
前导是一个8比特的交替序列,它不是01010101就是10101010,取决于接入地址的第一个比特。
接收机可以根据前导的无线信号强度来配置自动增益控值。
接入地址有两种类型,广播接入地址和数据接入地址。
1)数据接入地址不能超过6个连续的“0”或“1”。
2)数据接入地址的值不能与广播接入地址的值相同。
3)数据接入地址的4个字节的值必须互补相同。
4)数据接入地址不能有超过24次的比特翻转(比特0到1或者1到0,称为一次比特翻转)。
5)数据接入地址的最后6个比特需要至少2次的比特翻转。
6)符合上面的有效随机数据接入地址大概有231个。
报文的内容取决于该报文是广播报文还是数据报文。广播报文的包头如下图所示: 广播报文的报头包含4bit广播报文类型、2bit保留位、1bit发送地址类型和1bit接受地址类型。
每种广播报文类型都具有不同的数据格式及行为。Core_v4.2的2584页的2.3.1节详细的描述了各个广播报文类型。
广播报文和数据报文的长度域之所以不同,主要原因是因为:广播报文除了最多31个字节的数据之外,还必须要包含6个字节的广播 设备地址。6+31=37,所以需要6个比特的长度域。
广播和扫描相应的数据格式如下图所示,由有效数据部分和无效数据部分组成。
BLE采用的是24位CRC校验。CRC对报头、长度和数据进行计算,24位的CRC的生成多项式如下: CRC = x^24 + x^10 + x^9 + x^6 + x^4 + x^3 + x^1 + x^0 。
一般情况下,各大芯片厂商都会在其提供的资源代码中,有关于广播结构体的定义,这种结构体基本上囊括了广播中可以包含的数据。
比如说Nordic提供的SDK中,就定义了相关结构体ble_advdata_t,其结构体声明如下:
但是,这样一个结构体看下来,虽说可以知道大概含义,但是阅读起来比较麻烦,所以整理成一个表格,如下图所示,更方便阅读。下表中的数据都是可以加进广播报文中的,但是一般来说,建议在广播报文中至少含有Device Name、Flags、外观和首要服务的UUID列表。
到这里,基本上已经算是对广播及其报文有了总体了解,接下来,我们可以结合Nordic提供的SDK以及相应的案例,详细地看一下各个数据类型的意义以及在程序里面如何将它们加入至广播报文中。
BLE设备地址可以使用公共地址(Public Device Address)或随机地址(Random Device Address)两种地址类型,一个BEL设备至 少要使用一种地址类型,或者也可以两种地址类型同时使用。公共地址和随机地址的长度一样,都是48位(6个字节)的。BLE设备 地址的关系如下图所示。
从上图中的设备关系描述图,我们不难看出,蓝牙的设备地址类型一共有4种。
公共地址:从IEEE申请(购买),IEEE保证地址分发的唯一性。
随机静态地址(Static Device Address):自己定义的,上电初始化后就无法更改了。
随机不可解析私有地址(Non-resolvable private address):定时更新地址,蓝牙内核协议建议15分钟更新一次。
随机可解析私有地址(RPA:Resolvable Private Address):通信双方使用共享的身份解析密钥(IPK:Identity Resolving Key),生成和解析RPA。只有这台设备拥有它想要连接或监听的那台广播设备的IPK时,才能跟踪该广播设备的活动。
公共地址由两部分组成,如下图所示。公共地址由制造商从IEEE申请(购买),由IEEE注册机构为该制造商分配的机构唯一标识符OUI(Organizationally Unique Identifier)。这个地址是具有唯一性的,且不能修改的。
公共地址能明确的指示出设备,同时具有唯一性,但是安全度不够,试想如果我们携带者使用公共地址的BLE设备时,不法分子可以通过技术手段跟踪该涉笔对应的唯一公共地址,即可跟踪到该设备的使用者。
为了加强隐私保护,蓝牙内核协议中提供了另外一种地址:随即地址,随即地址是随机产生的,不是固定分配的,随即地址又分为多种类型,以适应不同的应用场景对隐私的保护需求。
随机静态地址是随机生成的48位地址,随机静态地址必须符合以下要求:
静态地址的最高2位有效位必须是1;
静态地址最高2位有效位之外的其余部分不能全为0;
静态地址最高2位有效位之外的其余部分不能全为1;
一个上电周期内不变。
静态地址的格式如下图所示,共48位,最高2位是固定的,必须是1。
随机不可解析私有地址
设备生成随机不可解析私有地址必须包含以下要求:
随机不可解析私有地址的最高2位有效位必须是0;
随机不可解析私有地址最高2位有效位之外的其余部分不能全为0;
随机不可解析私有地址最高2位有效位之外的其余部分不能全为1;
随机不可解析私有地址不能和公共地址一样。
随机不可解析私有地址的格式如下图所示,共48位,最高2位是固定的,必须是0。
随机不可解析私有地址相当于周期性改变的随机静态地址,随机不可解析私有地址一直在变化,并且该地址是个随机数,没有提供任何可解析的信息,因此很难通过跟踪设备地址来跟踪设备,所以具有很高的安全性。但是因为地址一直在变化,有没有可解析的信息,这就导致受信任的设备也无法该地址的真实身份。
由此可见,随机不可解析私有地址在隐私保护上“敌我”不分,不管是谁,统统让你无法分辨出该设备的真实身份,因此随机不可解析私有地址在实际应用中很少使用。
随机可解析私有地址
设备生成随机可解析私有地址必须包含以下要求:
随机可解析私有地址的最高2位有效位必须是0和1;
随机可解析私有地址最高2位有效位之外的其余部分不能全为0;
随机可解析私有地址最高2位有效位之外的其余部分不能全为1;
随机可解析私有地址不能和公共地址一样。
随机可解析私有地址的格式如下图所示,共48位,最高2位是固定的,必须是0和1。
本地设备名称(Local Name)有如下两种类型。
完整的本地名称(Complete local name):不能被截断
裁剪的本地名称(Shortened local name):可以被截断,截取的内容必须是从名称的起始位置开始连续的字符。
比如说一个完整的设备名称是:Nordic_BLE_Device,裁剪的本地名称可以是Nordic_BLE,也可以是Nordic_B等,但不能是BLE_Device(因为BLE_Device不是从名称的起始位置开始的)。
虽然说裁剪的设备名称使用比较少,但是却很有用。比如说一个非常长的设备名称:Nordic_BLE_Device_Name_19980110_V1.0,这时就可以使用裁剪的设备名称,长度设置为10,那么广播的设备名称是:Nordic_BLE,当需要全部名称时,可以在建立连接后查询设备名称特征值,获取全部设备名称。
外观是GAP服务的一个特征,外观的值是在GAP初始化函数里面设置的,广播初始化只能选择广播包中是否包含外观,而不能设置外观的值。所以,如果想要配置外观,首先需要在GAP初始化函数中根据实际应用场景来设置外观的值,然后再在广播初始化函数中设置是不是要包含外观。
确定外观的值的话,就要根据实际应用场景去查询外观编码,这样的话就可以确保外观的值了。一般来说,外观编码可以在SIG官网上查询,也可以在厂商提供的库函数中查询。比如说应用实现的是个心率带的话,查询外观编码知道心率带的外观编码是833,那在Nordic提供的SDK中的“ble_types.h”文件中可以查到对应的宏是:BLE_APPEARANCE_HEART_RATE_SENSOR_HEART_RATE_BELT。
广播中是否含有外观的话,其实很简单,只要去设置对应的广播结构体关于外观的标志位,再去进行广播初始化即可实现。
Flags是位字段的序列,当其中任意一个位不为0且广播可连接时广播包中包含flags,否则Flags可以被忽略。Flags只能包含在广播包中,扫描响应包中不能包含Flags。Flags的作用是在广播包中加入如下标志:
有了这些标志,当设备被扫描到后,对端设备即可根据这些标志执行相应动作,如Flags指示了设备不支持BR/EDR,对端设备扫描到该设备后,即可知道该设备仅支持LE,不支持传统蓝牙。Flags的格式如下表所示:
有限可发现模式有时间的限制,一般维持的时间是30s,而一般可发现模式没有时间的限制,有限可发现模式广播的间隔要比一般可发现模式的广播间隔小。
从时间的限制上,不难看出有限可发现模式对连接的迫切性和目的性比一般可发现模式高,一个处于有限可发现模式的设备正在广播,那么它一定是刚被用户操作过并且及其希望被连接的。
不支持BR/EDR表示该设备是单模设备,仅支持蓝牙低功耗,不支持传统蓝牙。
发射功率等级(TX Power Level),指的是传输该广播包时使用的发射功率值。长度一个字节,单位为dBm。发射功率等级定义如下表所示。
发射功率等级可以用来计算路径损耗,计算公式为:pathloss = TX Rower Level - RSSI。
发射功率等级的一个应用场景如下图所示,设备A的发射功率等级为0dBm,接受时读取的RSSI是-40dBm,链路损耗是-40dBm。设备B的发射功率等级为+4dBm,接收时读取的RSSI是-60dBm,链路损耗是-64dBm。应用程序中,通过链路损耗即可判断出哪个设备离自己更近一些。
广播数据中,一般会包含一个服务ID列表,用以展示自己支持的服务,但是GAP和GATT服务的UUID不能加入到广播包中。广播包中可以根据自身的情况包含一部分服务的UUID或者包含所有服务的UUID。部分服务的UUID列表和完整的UUID列表同一时间只能使用一种,不能在广播数据包中同时包含这两种。广播包中包含完整的服务UUID很容易理解,但是为什么还要有部分服务的UUID列表呢,说明它还是有应用场景的,那么什么时候才需要包含部分服务的UUID?下列这两种情况一般就会选择使用部分服务UUID。
蓝牙内核协议中定义的服务UUID的格式如下表所示。
UUID的含义:UUID(通用唯一识别码:Universally Unique Identifier)是一个128位的数字,用来标志属性的类型。服务也是一种属性,自然也就需要使用UUID来标志了。
因为128位的UUID相当长(16Bytes),设备间为了识别数据的类型需要发送长达16个字节的数据。为了提高传输效率,蓝牙技术联盟(SIG)定义了一个“UUID基数”,结合一个较短的16位数使用。二者仍然遵循通用唯一识别码的分配规则,只不过在设备间传输常用的UUID是,只发送较短的16位版本,接收方收到后补上蓝牙UUID基数即可。
下图是标准UUID传输的示意图。0x180D是心率服务的UUID,因为是标准的UUID,所以收发双方都知道UUID基数是多少,因此传输的时候只传输16位的UUID,接收方会自己补上UUID的基数。
再次强调说明:完整的UUID是128位的,我们常说的16位UUID本质上还是128位的,只不过在传输的时候为了提高传输效率,所以说采用了16位UUID的形式。
一般来说,为了方便管理且增加UUID的可读性,低功耗蓝牙使用的那部分UUID会被分为以下几组:
0x1800~0x26FF:用作服务类通用唯一识别码。
0x2700~0x27FF:用于标识计量单位。
0x2800~0x28FF:用于区分属性类型。
0x2900~0x29FF:用作特征描述。
0x2A00~0x7FFF:用于区分特征类型。
一般来说,在广播中加入服务UUID只需要这三步即可:1、定义一个UUID数组并初始化;2配置广播结构体中应该如何包含服务UUID数组(是包含全部的服务UUID还是部分的服务UUID); 3调用厂商提供的广播初始化函数进行广播初始化,初始化成功后,服务的UUID列表自然而然的就加入到广播数据包中了。
UUID列表可以放在广播数据中,也可以放在扫描相应的数据包中,但是需要特别注意的地方是:因为广播数据包的长度有限,我们还要考虑广播数据包的剩余长度是否能容纳我们定义的UUID列表。
服务数据是用来在广播中发送某个服务的数据,服务数据可以不需要连接就能解析出来数据,如果发送的是电池电量的服务数据,手机端APP扫描到广播数据后,就可以显示出来电池电量了。
服务数据由UUID和数据两部分组成,广播数据中可以加入多个服务数据,如可以同时加入电池电量服务数据和温湿度服务数据。
同上面所说的在广播中加入服务UUID大致相同,同样也需要三步即可:1、定义服务数据结构体变量并进行初始化; 2、配置广播c初始化结构体中可以包含服务数据,即设置服务数据的UUID以及指针指向服务数据; 3、调用厂商提供的广播初始化函数完成广播初始化。
广播初始化成功后,服务数据就已经加入到广播数据包中了。
从设备连接间隔范围代表外围设备倾向的连接间隔,需要注意的是:连接参数是完全由主设备控值的,从设备只能表达自己的倾向和申请协商连接参数更新。广播中加入从设备连接间隔范围,目的是向主机告知自己倾向的连接间隔,给主机一个参考值。从机连接间隔范围格式如下图所示,包含4个字节数据:1个16位的最小连接间隔范围和1个16位的最大连接间隔范围。
一般来说在广播中加入从设备连接间隔范围只需要两步即可:1、定义从设备连接间隔范围结构体变量并进行初始化; 2、调用厂商提供的广播初始化函数完成广播初始化。
广播初始化成功后,从设备连接间隔范围就已经加入到广播数据包中了。
厂商自定义数据(Manufacturer Specific data),是用来在广播数据中加入厂商自己定义的数据。这就增加了开发的一个灵活性,厂商就可以根据自己的实际需求组织数据结构,并将数据加入到广播数据中,入iBeacon使用的就是厂商自定义数据。
厂商自定义数据的格式如下表所示,广播数据中加入厂商自定义数据需要注意其数据长度不能超过当前广播包的剩余可用长度,也就是说要确保广播包的剩余空间足够容纳你想要加入的厂商自定义数据,这时你才可以将其加入进去。
在广播数据包中加入厂商自定义数据和以上几种例如服务UUID、服务数据等类似,都是只需要几步就可以实现:1、首先定义厂商自定义数据结构体变量并初始化; 2、配置厂商提供的广播初始化结构体中要可以包含厂商自定义数据; 3、调用厂商提供的广播初始化函数完成广播初始化,初始化成功后,自然就加入进广播数据中了。
配置文件是一种规范,配置文件定义为可能的应用,并规定了蓝牙设备与其它蓝牙设备通信的一般行为。配置文件构建于蓝牙标准基础上,以更明确确定蓝牙模块传输的数据类型。设备的应用决定了它需要支持的配置文件种类。
如心率配置文件中,定义了两种角色、规定了心率传感器必须包含的服务、建议的广播参数以及绑定和非绑定下建立连接的过程等。
为了方便用户使用,体现BLE的互操作性,SIG采纳了很多常用Profile并在官网上发布,这些Profile被称为标注Profile,如心率Profile、防丢器Profile、体温计Profile等。但是实际上,应用场景千奇百怪千变万化的,厂商对功能的设定也各不相同,仅仅靠SIG提供的这些标注Profile是无法满足这些需求的。鉴于如此,蓝牙内核协议允许厂商自定义适用于自己产品需求的Profile,这些Profile就被人们称为自定义Profile,如串口透传Profile、蓝牙灯控Profile等。
因此,配置文件分为两种类型:标准配置文件和自定义配置文件,如下图表示。
标准Profile的规格书在SIG的官网上可以查询和下载(SIG已采纳的配置文件:https://www.bluetooth.com/specifications/gatt)。下表列出一部分的配置文件。
服务是一组特征和通过它们所公开的行为的集合,一个服务可以包含多个特征。如心率服务就包含Heart Rate measurement、Body Sensor Location和Heart Rate Control Point这些特征。服务也和Profile一样,分为标准服务和自定义服务,标准服务是由SIG采纳并发布的,而自定义服务是厂商自己定义的,同样这些标准服务的规格书也是可以在SIG的官网上查询和下载的,下载的网址和Profile一样。下表就列出了一些SIG发布的标准服务。
服务存在于从机中,每个服务代表从机的一个能力,Profile规格书中规定了需要包含哪些服务,哪些服务是必选的,哪些服务是可选的。下图是一个心率的配置文件定义的心率传感器需要包含的服务,由图中不难看出,心率传感器必须包含心率服务和设备信息服务。
特征包含3个部分:声明、数值和描述符,其中声明和数值是必不可少的,而描述符可以是一个也可以是多个。
特征的数值是我们最终要操作的数据,如心率传感器的心率测量特征,它的特征值就是心率值和RR-Interval值,心率传感器通过将此特征值发送给主机,从而使能主机可以获取心率传感器的心率值和RR-Interval值。当然,主机也可以主动去读取心率测量特征来获取心率传感器的心率值和RR-Interval值。
通过无线传输数据本身来说是一个比较简单的事情,但是BLE为了达到低功耗、互操作性以及适应各种应用场景的目的,给这些数值设定了一些规范,从而让事情变得复杂很多。换句话说就是要让数据传输变得简单、可靠、通用,那么事先定的规则就多,规则多了,理解起来机会困难得多。
服务的规格书会定义服务需要包含哪些特征,下图是心率服务规格书定义的心率服务包含的特征,其中心率测量特征是强制包含的,身体测点位置特征是可选择包含的,心率Control Point是条件包含的(如果支持能量消耗统计就必须包含,否则不能包含此特征)。
对于特征来说,要建立一个特征,首先要进行声明,声明如下图所示:
特征性质:特征性质是一个8位字段,确定了特征数值属性对一系列操作的支持情况,各个位的描述如下图所示:
特征数值:特征数值是一个属性,特征性质字段给出了特征数值属性的访问权限,如读/写等等,通过特征性质字段的描述,确定了特征数值属性可以执行的操作类型。
特征的描述符大多数描述符是可选的,一个特征可以包含0到多个描述符,需要注意的是如果使用了通知(notify)和指示(indicate),必须要有客户端特征配置描述符(Client Characteristic Configuration Descriptor, CCCD),CCCD的UUID是0x2902。
心率Profile给出了明确的规定:如果一个设备声称符合心率Profile,应以服务指定的方式支持此服务中所有指示的强制功能(过程强制),这也同样适用于指示的可选的或有条件具备的功能。因此,我们需要阅读SIG发布的相关文档,根据文档的描述列出需求,之后才能根据需求编写相应的代码区实现它。对于实现心率Profile,至少阅读下表中的三个文档才能列出需求。
这些文档可以从SIG的网站上可以下载到,详细下载地址见《二.1节:(1)Profile(配置文件)》。打开网页后,可以看到SIG发布的profile和服务文档,如下图所示,红框中是心率相关的配置文件和服务。
心率Profile定义了如下图所示的两类角色:心率传感器和集中器(Collector),心率传感器是测量心率和其它信息的设备,集中器是接收心率传感器心率测量值和其它信息的设备。
本章的案例是实现心率传感器的角色,心率传感器实例化一个并且只能实例化一个心率服务和实例化一个设备信息服务。
心率Profile具有传输依赖性,心率Profile应该在LE上传输。
如何实现一个服务应用,其实也就等同于开发一个产品,要先列出大致框架。开发实现一个服务也是如此,我们要先列出需求表,然后按照表中的序号逐条解释表中列出的各个项目的依据,这样的话更容易理解,也更有利于开发。
2.2.1、广播数据
一般情况下,建议在广播数据中至少包含设备名称、Flags、外观和首要服务的UUID列表。心率Profile规格书的3.1节也对此提出了如下需求(注意关键字“宜”表明以下两条需求不是强制性的需求)。
1、心率传感器中的广播数据中 宜 包含心率服务的UUID,这样,Collector在发起连接前就可以识别到该设备是心率传感器,这会增强用户使用的体验。
2、为了增强用户使用的体验,广播数据或扫描响应数据中 宜 包含设备名称。
因此,在广播包中包含心率服务的UUID、设备信息服务的UUID(虽然心率Profile规格书中没有提到建议包含,但是按照一般的做法,设备信息服务是首要服务,本例中也含有此UUID),同时,在广播包中应该包含设备名称。
外观可以让主机在扫描到心率传感器后在列表上显示一个相关的小图标,更加直观。所以说,本例中广播包就含有外观,并设置外观为心率腕带,在SIG官网查询外观编码可以知道心率腕带的外观编码是833。
心率profile规格书的《2.5节:传输依赖性》规定:心率Profile应在LE上传输。所以说不管使用的蓝牙芯片是单模还是双模的,还是说LE、BR/EDR都支持还是说只支持LE,我们都只能在Flags中表明心率传感器不支持BR/EDR。
心率Profile规格书的《5节:连接建立规程》规定:心率传感器 宜 使用GAP一般可发现模式,所以本例中使用的就是一般可发现模式。
由此可知,Flags设置为:一般可发现模式,不支持BR/EDR。
2.2.2、广播参数
心率Profile规格书中的《第5节:连接建立规程》给出了广播参数的推荐值,如下图所示。该推荐值将广播分为俩个阶段,前30s广播间隔小,主机容易扫描到心率传感器,并能快速建立连接,但是消耗的能量较大。30s之后广播间隔加大,以节省能量消耗,此时主机扫描心率传感器的速度以及建立连接的速度会相应变慢。
广播之所以要分为两个阶段的原因是:一般认为,当一个设备启动时,是最有可能被连接的,所以在前30s内快速广播,以达到快速连接的目的。30s后被连接的可能性变小,这时可以降低广播速度来节省能量。
2.2.3、首选连接参数和连接参数协商
首选连接参数是从机倾向的连接参数,用户可以根据自己的需求设置首选连接参数,在本例中根据需求设置如下:
从机和主机刚建立连接时,会使用“快速”的连接参数(主机在连接请求中提供的连接参数)以达到迅速交换信息的目的。但是,从机和主机之间并不是一直需要快速的交换信息,因为这样会加快从机电池电量的损耗。因此,从机希望能采用自己倾向的连接参数。这时,从机就需要和主机协商连接参数了。
连接参数协商一般会在连接建立成功后延时一段时间进行,因为在建立连接的过程中需要交互的数据太多,延时一段时间可以避开“数据高峰”,在相对“空闲”的时间完成协商,以便影响连接建立的速度。除了延时,应用程序还需要配置连接参数协商的时间间隔和最大尝试次数,本例中使用的协商参数如下:
首次协商延时:5s。
每次协商之间的间隔:30s。
协商失败最大次数:3次。
2.2.4、GAP服务
心率Profile规格书的《第3节:心率传感器角色需求》给出了对GAP服务设备名称的额外需求:心率传感器可以支持设备名称特征的写入属性,以便允许Collector将设备名称写入心率传感器,即主机可以修改GAP的设备名称。
2.2.5、包含的服务
心率Profile规格书的《第3节:心率传感器角色需求》描述了心率传感器需要包含的服务,如下表所示,心率传感器强制包含心率服务和设备信息服务。
1)心率服务
心率服务规格书《第3节:服务的特征》中定义了心率服务包含的特征,如下图所示。
注意:
从上表中可以看到,对于心率服务,心率测量特征是必须要包含的,因为心率测量特征的性质是Notify,所以心率测量特征必须要有CCCD,用来使能/关闭Notify。身体测点位置特征是可选择包含的,心率Control Point特征是有条件包含的,如果心率传感器支持能量统计,就必须包含此特征,主机可以通过写该特征值复位能量消耗统计。
2)设备信息服务
设备信息服务规格书《第3节:服务的特征》中定义了设备信息服务包含的特征,如下表所示:
注意:
2.2.6、数据传输
BLE的数据传输是双向的,蓝牙内核协议中定义了两类数据传输的规程:服务器发起规程和客户端发起规程,通俗的说就是从机主动向主机发起数据传输和主机向从机发起数据传输。
1)从机主动发起
从机如果向主动发起数据传输,只能通过两种方式:通知(Notify)和指示(Indicate),从机可以通过这两种方式主动将数据发送给主机,它们的区别如下:
2)主机主动发起
主机通过从机发送的通知或指示可以获取从机的数据,但是数据发送的主动权在从机,主机是“被动接收”,主机无法决定从机何时发送数据,同时主机也无法将数据发送给从机。
主机如果想主动发起数据传输,也有两种方式:读和写,通过读和写,主机可以读/写特征值和特征描述符。
读(Read):主机通过“读”可以读取从机的特征值和特征描述符,从而获取从机的数据。
写(Write):主机通过“写”可以写入从机的特征值和特征描述符,从而将数据发送给主机。
综上所述,从机通过通知和指示可以将数据发送给主机,实现从机到主机的数据传输,主机通过读和写既可以读取从机的数据,也可以将数据发送给从机。
到这里我们可以简单的描述一下心率传感器的具体数据传输,如下图所示: