蓝牙BLE协议栈基础知识

蓝牙BLE协议栈基础知识,第1张

这次介绍一下蓝牙协议栈(BLE)的基础知识,蓝牙协议栈组成如下图所示,首先我们说说GAP和GATT

GAP层是负责连接的,其中包含广播、扫描、连接、断开的过程和参数

11 角色

蓝牙设备的角色主要有中心(Central)和外围设备(Peripheral)两种,中心设备向外围设备发起连接。链路层的主机(Master)和从机(Slave)的概念跟中心和外围的概念是对应的。

除了中心和外围之外,还有Observer和Broadcaster角色,Observer一直进行监听,Broadcaster一直进行发送,这两种角色都只广播,不能发起连接或者被连接,这里就不详细说了

12 广播

建立连接之前,外围设备每隔一段时间发送一个广播包,让正在扫描的设备知道这是一个可以连接的设备,扫描设备才能对外围设备开始连接,这个广播包的时间间隔叫advertising interval,这个间隔可以在10ms到1024s之间,间隔的长短会影响建立连接所花时间。

中心要收到广播包之后才能发送连接请求,相应的,外围设备在发送广播包之后会等待连接请求。

蓝牙广播包最多可以包含31字节数据,包含设备名称和一些标志。中心收到广播包之后可以发送Scan Request以请求更多的广播信息,外围设备会回复一个同样是31个字节的Scan Response。

BLE有37个数据信道和3个广播信道,广播包,Scan Request,Scan Response使用广播信道

13 扫描

扫描是指中心监听广播包并且发送Scan request。扫描中有两个参数:Scan window(扫描窗口) 和Scan interval(扫描间隔)

14 发起连接

中心发起连接的过程类似于扫描的过程,中心收到广播包之后会发送一个连接请求给外围设备

15 连接

中心和外围设备连接上之后,中心会按照一定的连接间隔(Connection interval)向外围设备请求数据,这个间隔是由中心定的,在75ms到4s之间。

如果要提高吞吐量,可以在一个连接间隔中传输多个数据包,每个包最多可以包含20字节数据。如果要省电,并且外围设备并没有什么数据需要传输,可以跳过几个连接间隔,这称之为Slave latency。

如果外围设备没有在规定时间内响应中心的请求就会认为是连接中断,称之为Supervision Time-out(01s-32s),所以在使用Slave latency的时候要注意不要引起Supervision Time-out

这些参数是建立连接的时候中心确定的,如果建立连接之后外围设备想要更改,可以向中心发送Connection parameter update request。

整个数据交换的过程会在不同的频段中跳频(除了广播频段),跳频是自动完成的,不需要我们去管。

设备之间的数据传输是在GATT这层完成的

21 角色

除了GAP里面的角色,BLE在GATT里面也定义了两个角色,分别是GATT Server 和GATT Client,一般来说产生数据的设备是GATT Server,访问数据的设备是GATT Client,一个设备可以既是GATT Server也是GATT Client。这两个角色跟GAP中的角色并没有关系。

22 GATT结构

GATT Server通过属性表(Attribute table)来组织数据,

221 Attribute

上图中每一行就是一个属性Attribute。

每个属性具有一个handle,一个UUID,和一个Value。

Handle是Attribute的一个索引,每个Attribute的Handle都是唯一的。

UUID(universal unique identifier)表示的是Attribute中数据的类型信息。UUID在一个设备里面不是唯一的,可以有多个Attribute的UUID都一样

222 Characteristic

可以把Characteristic看作是上图中几行的集合(几个Attribute的集合)

每个Characteristic至少有两个Attribute,其中一个是声明,另一个包含数据。前面说过,蓝牙传输数据是通过GATT来传的,更具体的来说,是通过一个个Characteristic来传的。

223 Descriptors 描述符

Characteristic除了包含声明和数据之外,还可以有描述符(Descriptors,但不是必须有),Descriptors是用来进一步描述Characteristic(但不提供数据)的Attribute,比如说用自然语言描述该Characteristic是用来干什么的。

有一类特殊的描述符,叫CCCD(Client Characteristic Configuration Descriptor),支持Notify和Indicate的Characteristic 必须包含CCCD

224 Service

Service 是一个或者多个Characteristic的逻辑组合

一个GATT Service 通常包含了一些相关的功能,举例来说,一个人机界面Service包含了各种人机交互输入输出的数据,而其中的每个Characteristic 是一类信号或者设备

介绍几个常见的Service。

GAP GATT Service:作为Central或者Peripheral的BLE设备都需要有这个Service。这个Service包含了如何发现和连接设备的信息

Generic Attribute Service: GATT Server都要有这个Service,这个Service包含了GATT Server的信息

225 Profile

一个或者多个Service组合在一起称为Profile。Profile 是逻辑上的概念,自己并不具备单独的Attribute。

23 标准和自定义的Service和Characteristic

蓝牙联盟定义了一些标准的Profile, Service, Characteristic 和Attribute。由于Profile和Service是在具体应用中规定的,所以用户可以进行自定义

24 UUID

图2中每一个Attribute都有UUID,UUID是一个128位的数字,是用来描述Attribute的类型的

241 蓝牙联盟UUID

蓝牙联盟把UUID分为基础UUID(base UUID)和16位UUID。

蓝牙联盟规定的UUID都具有同样的base UUID:

0x0000xxxx-0000-1000-8000-00805F9B34FB

蓝牙联盟规定了一些16位UUID,替换掉base UUID中的xxxx就组成一个完整的128位UUID了。举例来说,0x2A37是一个16位Heart Rate Measurement Characteristic,那么对应的128位的UUID就是:

0x00002A37-0000-1000-8000-00805F9B34FB。

由于所有蓝牙联盟的UUID都具有同样的base UUID,所以用16位UUID就可以区分蓝牙联盟规定的Attribute了

但我们自定义的Attribute, Characteristic, Service,不能使用这个base UUID,因此也不能用16位UUID,只能使用制造商自定义的128位UUID。

25 空中接口操作和属性

由于每个Attribute具有唯一的Handle,所以几乎所有的操作都是通过Handle去完成,Characteristic常用的属性有:Write, Write without response, Read, Notify, Indicate。 Characteristic的属性决定了我们可以如何使用它

Write, Write without response

这两种属性允许GATT Client 对Server的characteristic的值进行写操作,两者的区别是Write without response对写操作不会有确认

Read

GATT Client可以读Server的Characteristic的值。

Notify 和Indicate

这两种属性表示的是当GATT Server 中该Characteristic 的值发生变化的时候会通知Client。两者的区别是Indicate 会进行确认但Notify不会

接下来举例说明一下前面介绍的概念

Thingy 的Services,作为Server需要有GAP Service和GATT Service,另外还有一个标准的Battery Service,后面是几个自定义的服务

详细的看看GAP Service,这个服务的Handle是1到9,那么把这些Characteristics和Attribute都打出来

可以看到这个Service的结构是这样的

这是一个标准的Service,使用标准Service/Characteristic的时候要符合蓝牙SIG对这个Service/Characteristic的规定,我们可以到 蓝牙SIG 看看是不是一致

以上就是BLE的一些基础知识和示例

Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。Android操作系统最初由Andy Rubin开发,主要支持手机。2005年8月由Google收购注资。2007年11月,Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。随后Google以Apache开源许可证的授权方式,发布了Android的源代码。第一部Android智能手机发布于2008年10月。Android逐渐扩展到平板电脑及其他领域上,如电视、数码相机、游戏机等。

BLE广告是蓝牙低功耗最重要的方面之一。 了解如何正确使用广告可以帮助你降低功耗,加快连接速度,提高可靠性。 我们将要了解他们的工作原理以及如何使用它们。

蓝牙智能(Bluetooth Smart)有两种通信方式。 第一种通信方式是使用广告,其中BLE外围设备向其周围的每个设备广播数据包。 然后,接收设备可以对该信息进行操作或连接以接收更多信息。 第二种通信方式是使用连接来接收数据包,外围和中心都发送数据包。 我们将重点放在广告上,原因有几个:

广告是有意设计为单向的。 中央 设备无法在没有连接的情况下将任何数据发送到外围设备。 但是单个外设可以向该区域的多个主设备发送广告。

在我们进入广告包发送之前,我们想谈谈一下BLE物理层。 物理层负责在空中实际发送信号。 这包括实际的射频收发器。

蓝牙低功耗与经典蓝牙具有一些相似之处。 两者都使用24GHz频谱。 基本速率(BR)和BLE均采用1Mbps的GFSK调制,但其调制指数不同。 增强数据速率(EDR)使用与GFSK完全不同的调制。 经典蓝牙与LE的40个频道相比有79个频道。 通道间隔也不同。 这两个差异使LE和经典蓝牙不同,不兼容,所以他们无法沟通。 双模式射频,像CC256x,通过切换其调制参数和运行频道来支持LE和经典蓝牙。

用于蓝牙的24GHz频谱从2402MHz延伸到2480MHz。 LE使用40个1MHz宽的信道,编号为0到39,每个信道分开2MHz。

频道37,38和39仅用于发送广告包。 其余的用于连接期间的数据交换。 我们对这3个频道的情况感兴趣,这就是我们在这里介绍的内容。

在BLE广告期间,BLE外围设备一个接一个地在3个广告信道上发送数据包。 扫描设备或信标的中央设备将收听这些频道的广告数据包,这有助于其发现附近的设备。

频道37,38和39有目的地分布在24GHz频谱上。 频道37和频道39是频带中的第一个和最后一个频道,而频道38在中间。 如果任何一个广告频道被阻止,其他频道可能是空闲的,因为它们分开了相当多的带宽。

这是特别真实的,因为干扰BLE的大多数其他设备是窄带。 频道38特别放在Wi-Fi频道1和6之间,所以它避开了Wi-Fi信号。 广告频道的宽间距有助于BLE更好地管理来自Wi-Fi,经典蓝牙,微波炉,婴儿监视器等的干扰,以确保广告成功。

当BLE外围设备处于广告模式时,在每个广告频道上周期性地发送广告包。 分组之间的时间间隔具有固定间隔和随机延迟。

你可以将固定间隔设置为从20ms到1024秒,步长为0625ms。 随机延迟是自动添加的从1ms到10ms的伪随机值。 这种随机性有助于减少不同设备的广告之间的碰撞的可能性。 我们提到过广告对于发现设备至关重要,所以不惜一切代价避免冲突是非常重要的。 这是蓝牙智能(Bluetooth Smart)使用的另一种方式来提高稳健性。

你可能会想,我只想在一个或两个频道上做广告,而不是全部三个来节省电量。 由于干扰的影响,大多数公司都对这种做法感到沮丧。 如果你选择的频道被阻止,你的设备将无法正常工作。 例如,苹果建议在所有3个频道上都进行广告,其他制造商也同样如此。

广告间隔与连接间隔是分开独立的。 因此,即便你的设备形成连接的速度较慢,连接建立后也不会阻止你快速发送数据。

蓝牙规范在蓝牙LE中定义了两个数据单元的顶级数据包。 分组本身具有包括前同步码和接入地址以及CRC的若干部分。

用于广告信道的分组数据单元(称为广告信道PDU)包括2字节报头和6到37字节的可变有效载荷。 有效载荷的实际长度由 广告信道PDU 的报头中的6位长度字段来定义。

请注意,广告有几种PDU类型,但我们将主要关注 ADV_IND ADV_NONCONN_IND 。 ADV_IND是一个通用的广告,通常是最常见的。 这是通用的,因为它没有被定向(not directed),并且它是可连接的(connectable),这意味着中央设备可以连接到正在发送此广告的外围设备,并且不指向特定的中央设备。

当外围设备发送ADV_IND广告时,它正在帮助诸如智能手机的中央设备找到它。 一旦找到,中央设备就可以开始连接过程。

ADV_NONCONN_IND是当外设不想接受连接时所使用的广告类型,这在信标(Beacons)中是典型的。

正确的广告方式取决于你的应用,无论你要形成快速连接还是完全避免连接。

广告信道PDU本身具有取决于广告PDU类型的有效载荷。 上图显示了ADV_IND有效载荷。 该有效载荷具有6字节的 广告地址 和可变数量的广告数据结构。

在考虑广告地址后(通常将其称为蓝牙MAC地址,尽管可能会随意更改),实际的广告数据结构仅有37 - 6 = 31字节。 这还必须包括长度,类型和数据本身。

我们浏览了几个层次,你可以看到BLE封装了大量数据。 这为你提供了很多灵活性来支持最适合你产品的不同行为。

在最低级别,广告有31个字节可以广告任何数量的不同的东西。 你可以在蓝牙Sig网站上查看广告数据类型的 完整列表 ,每种数据类型都指定了有效载荷中不同的数据标准。

一些最常用的 广告数据类型 是:

由于广告数据结构的数量是可变的,你可以根据需要进行组合。

建立广告最重要的部分是获取正确的信息到中央设备(智能手机或独立的中央设备),这通常取决于对你的产品什么最重要。 如果你的产品提供独特的服务,你可以广告这些服务,以便智能手机可以区分你的产品和附近的其他产品。 例如,Beacons具有诸如独特的UUID,功率级别和其他对于查找和使用Beacons很重要的特性的定制数据。

蓝牙SIG还具有制造商特定的0xFF数据类型,因此你可以灵活地定义自己的自定义有效负载。 苹果公司为iBeacons做了这一工作,它将标准的广告数据类型与制造商特定的一起组合。

定义自己的广告给你很大的力量,但是需要由你自己找到最好的方法来达到你想要的地方。

虽然每个应用程序都是不同的,但外设广告其提供的最重要或最独特的服务是连接到它的最简单方式,在许多产品中都是有意义的。当iPhone或Android正在寻找设备时,它可以使用定制服务UUID来查找要与其通话的确切设备并过滤掉其他设备。 搜索特定地址是不太可能的,但是找到具有唯一ID的设备更容易。

例如,假设你的产品是小型光传感器。 你可以使用唯一的128位UUID创建自定义服务。 然后,通过将UUID包括在广告包中,iPhone可以忽略除了你的产品之外的所有其他设备。 这样可以快速找到设备,因为你无需连接到每个设备来发现其功能。

这在节电方面也很好。 新一代的智能手机正在越来越多的在低水平上决策和过滤。 他们这样做是因为能够更高效地丢弃没有用的广告包,而不是通知操作系统和用户稍后再丢弃。 但手机需要有关哪些应用程序必须提供过滤哪些的信息,这取决于服务或设备地址的唯一UUID。

一旦你开始使用BLE设备,你将很快意识到UUID至关重要。 服务,特征和其他项目都使用UUID来唯一标识它们。

UUID只不过是唯一的128位(16字节)数字:

75BEB663-74FC-4871-9737-AD184157450E

通常以4-2-2-2-6格式排列UUID。 每对字符表示一个十六进制数字。 所以75以上是实际的0x75。

为避免不断传输可能浪费的16个字节(蓝牙数据量非常有限,16个字节很大),蓝牙SIG采用了标准的UUID基础。 该基础形成128位UUID的前96位(12字节)。 其余的位由蓝牙SIG定义:

XXXXXXXX-0000-1000-8000-00805F9B34FB

最高的32位由你决定。 对于16位UUID,底部16位保持为0。例如,心率服务的简单16位UUID是:

0x180D

实际上这代表一个128位的UUID:

0000 180D -0000-1000-8000-00805F9B34FB

如果你使用Bluetooth SIG指定的现有服务或配置文件,则可以避免使用完整的128位UUID。 但是,定制服务需要一个完全定义的128位UUID。

UUID唯一重要的是它们是独一无二的。

你可以以各种方式随机生成它们。 一个可以生成它们的网站是 在线UUID生成器 。 在Mac OS X中,你可以使用命令行中的uuidgen实用程序来执行相同的操作。

由于位数,你不太可能像其他任何人一样生成一样的UUID。 最重要的是你可以避免在自定义的UUID中使用蓝牙SIG的UUID基础。

最重要的事情之一是功耗和延迟之间的大的折中。 每个广告都消耗电力。 BLE射频必须通电并传输。 较少的广告,系统用一组电池能运行的时间越长。 那么将广告间隔设置为10秒是个好主意吗?

那么我们假设用户想连接到外设。 你能等10秒吗? 长时间间隔对于用户来说可能非常令人沮丧,尤其是在环境干扰和数据包丢失的情况下。 所以,使间隔太大对于用户体验是不利的。 在中间的某个地方,大约500ms到1秒是大多数产品的最佳选择。 在我们开发的一些应用程序中,我们已经增加了延时,但只有经过仔细考虑之后才做的决定。 某些系统在循环中没有用户,因此更容易做到。

当你构建广告数据包时,你还需要考虑更多字节意味着更高的功耗。 广告包中的每个字节都迫使射频收发器停留在更长的时间内传输,从而使用更多的能量。 在某些情况下,将广告中的字节数减少到最低限度可以帮助挤压硬币电池的所有内容。

蓝牙智能(Bluetooth Smart)设计允许外设功耗极低。 这部分是通过在智能手机上放置大量的负担,假设智能手机具有较大的电池并且容易充电。 但是,在实际产品中,你希望避免在智能手机上造成显着的电池消耗。 如果启用蓝牙会更快地耗尽电池,一些用户最终将无奈地停用蓝牙。 对于大多数要为用户提供快速体验的产品而言,这是一个问题。

智能手机使用的大部分功耗来自扫描广告。 因此,Android和iOS极大地限制了扫描,特别是后台扫描。

当你的应用程序处于前台时,你基本上可以完全控制BLE,并且你具有高优先级。 这是有道理的,因为苹果和谷歌知道你想要快速向用户显示数据,所以没有必要拖延它。

一旦你的应用程序处于后台,寻找附近的设备(如果你的应用程序支持它),则操作系统通常会降低优先级。 这是通过几种方式完成的:

Android和iOS各自单独处理这个问题,因此了解在后台运行的效果对你的设备和连接很重要。

我们已经提到广告包有31个可供你使用的数据字节。 这不是很多,特别是当你考虑到128位UUID需要16字节时。 如果要包含更多信息,你唯一的选择是响应扫描响应。

当智能手机扫描广告时,它也可以从广告设备请求更多的信息而不形成连接。 这是通过扫描请求完成的,扫描请求是发送到外设的特殊数据包。 BLE外设接收扫描请求并以扫描响应进行响应。

扫描响应分组具有与广告相同的分组格式,除了较高层上的类型,表示它是扫描响应而不是广告。 因此,你的扫描响应可以提供你在广告数据包中没有提及的设备名称或其他服务。

扫描响应有一个已知问题。 如果在外围设备中启用扫描响应,则在发送广告以能够接收扫描请求包之后,设备必须将射频保持在RX模式。 即使没有实际发送的设备,仍然必须这样做(因为外设不知道谁真正在那里)。 这意味着更多的能源消耗。 对于非常低功耗的应用,如果不是绝对需要,请考虑禁用扫描响应。

如果不讨论Beacons,特别是Apple的iBeacon标准,则关于BLE广告的讨论将是不完整的。

信标(Beacons)是BLE外设,专门使用广告,但不允许连接。 不允许连接的原因是,如果信标要建立连接,广告将不得不停止,所以没有其他设备可以找到信标。 发送的数据包格式有所不同。 而苹果的iBeacon使用了非常特定的格式的有效载荷。

你可以看到iBeacon数据包的格式。 这些数据包使用基本的BLE格式和一些特定的字段。 我们一个接一个地来看看它们。

广告包包含蓝牙MAC地址和有效载荷。 有效载荷由两个AD结构组成,第一个使用Flags数据类型给出通用信息,第二个是Apple特定的iBeacon信息。

该数据包的数据类型为0x01,表示各种标志。 长度为2,因为有两个字节,数据类型和实际标志值。 标志值有几位表示iBeacon的功能:

大多数iBeacons是单模设备,BR/EDR不被使用。 对于iBeacons,使用通用可发现模式。

最重要的广告数据类型是第二个。 第一个字节表示字节数,总共26字节为0x1A,有效载荷为25字节,类型为1字节。 AD类型是制造商特定的0xFF,所以苹果已经定义了自己的广告数据。

前两个字节表示公司标识符0x4C00。 你也可以看到 其他公司的标识符 。

第二个两字节是信标广告标志。 这些总是0x02和0x15。

关键字段是iBeacon Proximity UUID,它独特地标识了iBeacon,后面是主要和次要(major and minor)字段。

每个iBeacon都必须拥有唯一的UUID,以便iPhone应用程序可以准确了解相对于一个或多个iBeacons的位置。

最后,还有一个校准的TX功率(calibrated TX power)的2的补码,可用于提高信标的位置精度(已经知道功率电平)。

没有什么阻止你用不同的制造商格式创建自己的信标。 问题是苹果专门检测具有特定格式的iBeacons,所以不会有任何互操作性。

我们已经介绍了一些最受欢迎的BLE和蓝牙设备,其规格以及做出决定时要牢记的一些关键方面。

和往常一样,在创建BLE产品时,会有许多细节和问题发挥作用。 我们致力于帮助你完成正确的操作,请随时与我们联系讨论。

[1]蓝牙特别兴趣小组 蓝牙v42规格 。

[2] Apple Inc iBeacon for Developers 。

蓝牙广播中对服务 UUID 格式定义都有三种 16 bit UUID、32 bit UUID、128 bit UUID。

但是熟悉安卓开发的小伙伴都知道接口都 UUID 格式,fromString 时候 16bit 的 UUID 该咋办呢?

16bit 和 32bit 的 UUID 与 128bit 的值之间转换关系:

128_bit_UUID = 16_bit_UUID 2^96 + Bluetooth_Base_UUID

128_bit_UUID = 32_bit_UUID 2^96 + Bluetooth_Base_UUID

其中 Bluetooth_Base_UUID 定义为 00000000-0000-1000-8000-00805F9B34FB 

如果你想说这是啥呀,那我这样说你应该可以明白点:

若 16 bit UUID为xxxx,那么 128 bit UUID 为 0000xxxx-0000-1000-8000-00805F9B34FB

若 32 bit UUID为xxxxxxxx,那么 128 bit UUID 为 xxxxxxxx-0000-1000-8000-00805F9B34FB

最近遇到了一个BLE的项目,花时间恶补了下相关的知识,这里记录下来备忘。这篇笔记是纯协议的,先大概了解ble的协议和流程,能帮助我们更好的编码

Ble设备的发现实际上靠的是Advertising(广播)机制。广播也有人管它叫做Beacon,我没有在官方文档里面查找到这个词,但是从网络上的文章来看,它们差不多就是同一个东西。

基于广播发现Ble设备有两种方式:

由于这两种方式都基于广播,所以它们的数据格式是一样的。广播会自带一些信息,例如设备的名称、MAC地址等。除了自带的数据之外,我们还能携带一些额外的信息数据。根据 官方 的 文档 ,可以看到这个额外数据的具体格式如下:

可以看到广播数据里面包含多个AD Structure。每个AD Structure分为两个部分:数据段长度(1字节)+数据段(N字节)。数据段又分为头1个字节的AD Type标识类型和剩余的AD Data具体数据。

注意看最后的Non-significant part,有时候在安卓的回调里面会在byte数组的最后看到一堆的0x0,这个实际上也是定义在协议里面正常的无意义数据,我们直接忽略它们就好。

举个实际的例子,在手机上使用ble搜索应用搜索我司开发的蓝牙设备,查看其广播数据:

可以看到广播数据0x0319C703020104030312180C094D41584559455F353146300C16791300000002000000735C,实际有5个AD Structure。

AD Type如上图所说可以去蓝牙协议的 官方 查看[Generic Access Profile文档]( https://btprodspecificationrefsblobcorewindowsnet/assigned-numbers/Assigned Number Types/Generic Access Profilepdf),可以看到这五个字段类型分别是:

根据这里找到的DataType我们又可以去 官方 的 Core Specification Supplement 10文档 查看Value的具体格式。这里我就不展开了。

虽然基于广播的机制我们已经能够实现手机与Ble设备的通信了,但是这种通信能实现的功能比较基础。所以Ble的协议还支持连接之后一对一的通信方式。

Ble的连接都基于 GATT (Generic Attribute Profile) 协议之上,GATT 是一个在蓝牙连接之上的发送和接收很短的数据段的通用规范。

GATT的结构如下:

Ble设备里面会提供多个Service,这些Service会提供一些特定的功能。而每个Service里面有会有多个Characteristic,这些Characteristic里面的value实际就是功能具体的属性值。

例如电池服务Battery Service里面就有一个Characteristic叫做Battery Level,手机可以读取这个Characteristic的value值来获取Ble设备当前的电量。

我们来看看实际设备读取出来的数据:

可以看到这里有Generic Access、Generic Attribute、Device Information三个Service。而Device Information Service下面又有四个Characteristic

这些Service、Characteristic都会有一个UUID去做标识,例如Generic Access Service的UUID是0x1800。虽然我们这里看到的UUID都是16bit的,但是实际上它们的完整形式应该是0x0000xxxx-0000-1000-8000-00805F9B34FB。中间的xxxx就是截图中显示的16位uuid,即Generic Access Service的完整UUID是0x00001800-0000-1000-8000-00805F9B34FB。

Service的UUID映射表可以到 官方 的[16-bit UUIDs文档]( https://btprodspecificationrefsblobcorewindowsnet/assigned-values/16-bit UUID Numbers Documentpdf)查看。

截图里面的Characteristic的Properties都是READ,代表这个Characteristic是可读取的。它实际上是描述了这个Characteristic可以如何使用。Properties在安卓ble的sdk里面靠一个int类型的变量表示,每一个二进制位都标识了一直能力。我们可以通过按位与的方式判断是否支持:

上面的机制实际上我只验证了Read、Write、Notify。其他的我都是根据根据 官方 的 文档 的“Table 35: Characteristic Properties bit field”表格自己理解的,可能会有错误,大家可以参考官方文档去理解。

除了Properties之外,Characteristic还有一个十分重要的数据段叫做Descriptors。一个Characteristic可能有0个或者多个Descriptor去描述它。

例如当一个Characteristic是Notify或者Indicate的时候它会携带一个Client Characteristic Configuration Descriptor(uuid 0x2902)描述当前Characteristic是否打开通知功能。也就是说通知功能是可以通过修改Client Characteristic Configuration Descriptor主动打开或者关闭的,通过Descriptor携带数据的二进制位去标识功能的打开关闭:

Descriptor的UUID映射表同样可以到 官方 的[16-bit UUIDs文档]( https://btprodspecificationrefsblobcorewindowsnet/assigned-values/16-bit UUID Numbers Documentpdf)查看。

MTU指的是最大传输单元MAXIMUM TRANSMISSION UNIT,表示一次数据传输最多能传多大的数据,我们直接看它的官方说明:

可以看到我圈出来的地方,MTU最小需要支持23个字节,但是实际上这23三个字节也不是全部用来放数据,它的头三个字节需要携带操作类型和属性的16位uuid。所以只剩下23-3=20个字节用于传输数据:

这里实际上有个坑,安卓默认MTU就是23也就是每次最多只能写入20字节的数据,所以最开始我写入一些比较大的数据的时候直接就失败了。需要先使用requestMtu将mtu设大。

嗨大家好,我是iOS开发一枚大帅比,过去的几年项目涉及到蓝牙比较多,抽空之余,把使用的小知识点归纳起来,一是方便自己对知识做很好的总结和复习,二是希望能帮助到琅琊开发的朋友们。

现在的互联网时代,智能硬件设备越来越多样化,这些设备中,有多是通过手机来控制硬件设备,来达到控制的效果,这中间少不了要使用到蓝牙功能,通过蓝牙来通信来控制设备。也就是我们说的“设备中心和外设的故事”。

蓝牙版本介绍:

每个人对于蓝牙都不陌生,近距离数据传输,方便;可是当你的业务需求需要你第一次接触蓝牙开发的时候,却会发现你对它并不了解;首先,蓝牙发展至今经历了8个版本的更新。11、12、20、21、30、40、41、42。那么在1x~30之间的我们称之为传统蓝牙,4x开始的蓝牙我们称之为低功耗蓝牙也就是蓝牙ble,当然4x版本的蓝牙也是向下兼容的。android手机必须系统版本43及以上才支持BLE API。低功耗蓝牙较传统蓝牙,传输速度更快,覆盖范围更广,安全性更高,延迟更短,耗电极低等等优点。(现在的穿戴设备都是使用BLE蓝牙技术的)

传统蓝牙与低功耗蓝牙通信方式也有所不同,传统的一般通过socket方式,而低功耗蓝牙是通过Gatt协议来实现。

本文章目的便是介绍BLE 40的使用以及相关问题的解决,本文采用简要模式介绍BLE40的核心类的使用以及蓝牙开发的简介,如需了解蓝牙知识的详细知识点,百度可搜索其他大神的文章进行学习,下文通用BLE代为蓝牙40。

BLE的两种模式分为CBCentralMannager 中心模式 和CBPeripheralManager 外设模式,在这里主要和大家分享 CBCentralMannager 中心模式的开发和使用。

说明:Service,Characteristic是每个硬件设备出厂设定的设备服务和特征值,用UUID作为唯一标识符。UUID为这种格式:0000ffe1-0000-1000-8000-00805f9b34fb。比如有3个Service,那么就有三个不同的UUID与Service对应。这些UUID都写在硬件里,我们通过BLE提供的API可以读取到,一个BLE终端可以包含多个Service, 一个Service可以包含多个Characteristic,一个Characteristic包含一个value和多个Descriptor,一个Descriptor包含一个Value。Characteristic是比较重要的,是手机与BLE终端交换数据的关键,读取设置数据等操作都是操作Characteristic的相关属性。说白了,我们可以把每个服务特征值看成是我们网络请求的api接口,我们和蓝牙的交互,是要连接到对应的service和对应的Characteristic才可以正确读取到和硬件文档以及出厂定制好的服务和数据。

1、导入:#import <CoreBluetooth/CoreBluetoothh>

2、遵守CBCentralManagerDelegate,CBPeripheralDelegate协议

3、初始化中心Manager,创建中心角色

4、检查当前设备中心的蓝牙状态

5、开始扫描

6、发现外设

7、连接外设

      连接状态

8、扫描外设服务Service

9、扫描service特征值

10、给特征值写数据(就是发送指令)

11、订阅特征值通知(订阅后可收到回应的数据)

12、根据特征值读取数据(注:应把之前发送数据和订阅通知的peripheral和characteristic定义为全局属性)

该处即为接收到外设发送的数据的方法

到这里,整个蓝牙使用的核心流程就基本介绍完了,鉴于写博客文章太累,太耗时,我决定先睡觉去,回头把文章慢慢细化一下,查漏补缺,格式可能也不是很完美,请读者们见谅,多提宝贵意见,喜欢的老铁们,可以点下喜欢或者收藏!

本人github地址: shLuckySeven

欢迎去点star

洗面奶:玉兰油清爽洗面奶和雅芳中草药洗面奶都在用,感觉一般,雅芳的还可以

化妆水:可伶可利,都说这个含酒精多,可视用来用去还是觉得这个好,之前用过泊美和兰寇的都不适合我。而且刚刚开始用还可以,久了就没有效果了。

乳液:玉兰油滋润乳液,挺好用的,就是觉得还是太油了点。

日霜晚霜:雅芳美白日、晚霜。刚开始用,感觉应该还可以,就是有点干。

粉底:安尚秀,这个是我买的第一瓶粉底液,而且一直用到现在,感觉真的很好,要换了,因为是日货,不过这个牌子好多店都没有卖,偶是在07买的。

散粉:买了一盒,是色彩地带的,可是不太会用这个东西,不知道怎么用,所以一直放着,也不知道它好不好。

眼霜:嘉那宝,真是一点效果都没有啊,听人说保护眼睛除了睡眠好什么都没用的。

眼影:雅芳的,不错。

思红:基本上很少用,用的是爱丽的,etude,感觉很好用。

睫毛膏和眼线笔:安利雅资的,很好用,涂起来感觉还算比较自然。

嘴巴:就用普通的润唇膏,有时候再上点唇彩,用雅芳唇彩,才99,是新品做活动是买的,很好用,感觉东西很不错,价格也是超级便宜啊。

雅芳的东西基本上都含酒精,比较适合年纪小的MM使用,因为相对来说,价格比较合适,而且18、9岁的MM自身皮肤修复快,不怕破坏。年纪稍长的就不合适,毕竟酒精还是对皮肤不好。

玉兰油的东西中归中矩,不过普遍的反映都是比较油,适合熟龄肌肤或者偏干的皮肤。

安利雅资没用过,不过听说都还可以的。

润唇膏如果想30以下的,选择余地就不大了。

彩妆类,没用过,不好评价。

护理的用水芝澳和碧欧泉,这比较适合干性皮肤的人,这是我这去年开始用这两种牌子,以前都是用韩国的爱茉莉非常不错,连我妈都用这个,它的隔离霜和散粉是最好的,在韩国爱茉莉都是属于高档的现在我的彩妆基本上用爱丽的,基本上韩国的彩妆都是非常适合亚洲人的,兰蔻的洁毛膏非常好,它的眼霜也不错,面膜用倍佳斯的.

欢迎分享,转载请注明来源:品搜搜测评网

原文地址:https://pinsoso.cn/meirong/1076535.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-08-27
下一篇2023-08-27

随机推荐

  • 男士用什么防晒霜好

    1、LISSAGEMEN防晒霜。嘉娜宝旗下的男士护肤品牌,乳液质地,采用ADVAN深度紫外线损伤屏障技术,让防晒涂抹见均匀分布于皮肤上,同时让霜体质地更细腻,透明度更高,清爽,不泛白,不黏腻。物化型防晒,添加芦荟提取物、西梅提取物、绿茶提取

    2024-04-15
    1023300
  • skii清莹嫩肤露和神仙水可以一起用吗?

    skii清莹嫩肤露和神仙水是两款非常受欢迎的护肤产品,很多消费者都对它们的效果非常期待。问题来了,这两款产品可以一起使用吗?答案是可以的。让我们来了解一下这两款产品的功效和特点。skii清莹嫩肤露是一款能够深层滋润肌肤、提亮肤色的精华水。它

    2024-04-15
    44700
  • 发之萃这个品牌的防脱育发套盒怎么样?

    效果因人而异。产品特点:发之萃防脱育发套盒选取本草精华,何首乌、侧伯叶、川穹、当归等,采用高能活性萃取工艺精制而成,其活性成分能快速改善毛囊生态环境,改善头皮状况,激活毛囊,具有头发防脱、促进毛发生长、促进毛发的作用,长期用会使头发乌黑柔顺

    2024-04-15
    44400
  • 黄芪精华露和精华液的区别

    黄芪精华露和精华液是两种常见的护肤品,它们在成分和功效上有一定的区别。下面我将从多个角度对这两种产品进行比较,帮助你更好地了解它们。黄芪精华露和精华液在成分上存在差异。黄芪精华露主要以黄芪等本植物提取物为主要成分,这些植物提取物富含多种活性

    2024-04-15
    34100
  • 精华水和纯露哪个好 两种精华优劣势比拼

    化妆水作为仙女们的护肤必备品之一,才不是随便买来用用,把对精华的关心分给化妆水一点,肌肤才能更好哦。下面我带大家来看一下精华水和纯露哪个好?两种精华优劣势比拼。精华水和纯露哪个好一、精华水 精华水不同于一般所说的化妆水,它介于普通化

    2024-04-15
    40200
  • 佰花萃牡丹臻白光采花泥面膜如何使用

    佰花萃牡丹臻白光采花泥面膜的使用方法如下:1 首先,在使用之前需要彻底清洁面部,确保面部干净,避免污垢和灰尘进入毛孔。2 在使用面膜之前,可以进行适当的热敷,以帮助毛孔打开,更有利于面膜的吸收。3 取适量面膜产品,均匀涂抹于脸部,避开眼部和

    2024-04-15
    27900
  • 妮维雅活力清新爽身气雾

    是一款活力清新爽身的气雾,令肌肤持久保持干爽舒适,令人感受妮维雅始终如一的温柔呵护,鳄梨萃取物,香体同时为肌肤提供滋养。带来一整天的清新感受。有效止汗长达24小时。散发爽朗清新的柠檬草香气,令人精神为之一振。滋润呵护腋下肌肤。不含酒精,任何

    2024-04-15
    34300

发表评论

登录后才能评论
保存