学计算机的那个

不是我觉到、悟到,你给不了我,给了也拿不住;只有我觉到、悟到,才有可能做到,能做到的才是我的.

0%

【译】iOS蓝牙

关于Core Bluetooth

蓝牙低耗能无线技术(Bluetooth low energy wireless technology)基于蓝牙4.0规范,该规范定义了一组用于低耗能设备之间通信的协议。核心蓝牙框架(The Core Bluetooth framework)是蓝牙低能耗协议栈的抽象。也就是说,它对开发人员隐藏了规范的许多底层细节,使您更容易开发与蓝牙低能耗设备交互的应用程序。

中心 和 外围设备

在所有的蓝牙低能耗通信中有两个主要的参与者:中心和外围设备。基于某种传统的客户机-服务器体系结构(client-server architecture),外围设备通常拥有其他设备需要的数据。中心通常使用外设提供的信息来完成某些特定的任务。如图1-1所示,例如,心率监测器可能具有Mac或iOS应用程序可能需要的有用信息,以便以用户友好的方式显示用户的心率。

每个玩家在扮演自己的角色时都要执行不同的任务。外围设备通过广播宣传它们所拥有的数据来表明它们的存在。中央设备扫描附近可能有他们感兴趣的数据的外围设备。当中心发现这样的外设时,中心请求连接到外设,并开始探索外设的数据并与之交互。外围设备负责以适当的方式响应中央设备。

如图1-2所示。中心设备可以请求连接到任何发现广告的外围设备。

外围数据结构

外设可能包含一个或多个服务,或提供有关其连接的信号强度的有用信息。服务是用于完成设备(或该设备的部分)的功能或特性的数据和相关行为的集合。
例如,心率监控器的一项服务可能是公开来自监控器的心率传感器的心率数据。

服务本身由特征或包含的服务(即对其他服务的引用)组成。特性提供了关于外设服务的更多细节。例如,刚才描述的心率服务可以包含描述设备的心率传感器的预期身体位置的一个特征和传输心率测量数据的另一个特征

中心端对象

中心设备探索外设上的数据并与之交互

在中心成功地建立到外围设备的连接后,它可以发现外围设备必须提供的全部服务和特征(广告数据可能只包含可用服务的一小部分)。

中心还可以通过读取或写入外围服务的特征值来与该服务交互。例如,你的应用程序可以从数字恒温器请求当前的室温,或者它可以为恒温器提供一个值来设置房间的温度

本地中心和远程外围设备

在中心端,本地中心设备由CBCentralManager对象表示。这些对象用于管理已发现或已连接的远程外围设备(由CBPeripheral对象表示),包括扫描、发现和连接到广告外围设备。图1-4显示了本地中心和远程外围设备如何在核心蓝牙框架中表示。

远程外设的数据由CBServiceCBCharacteristic对象表示

当您与远程外设(由CBPeripheral对象表示)上的数据交互时,您正在处理它的服务和特征。在核心蓝牙框架中,远程外设的服务由CBService表示,类似地,远程外围设备服务的特征由CBCharacteristic对象表示。远程外设的基本结构和特点如图1-5所示。

外围端对象

从macOS 10.9和iOS 6开始,Mac和iOS设备可以作为蓝牙低耗能外设,为其他设备(包括其他Mac、iPhone和iPad设备)提供数据。当设置您的设备以实现外设角色时,您正在蓝牙低耗能通信的外设端执行操作

本地外设和远程中心

在外围端,本地外围设备由一个CBPeripheralManager对象表示。这些对象用于在本地外围设备的服务和特征数据库中管理已发布的服务,并将这些服务发布到远程中心设备(由CBCentral对象表示)。外围管理器对象还用于响应来自这些远程中心的读写请求。图1-6显示了本地外围设备和远程中心如何在核心蓝牙框架中表示。

本地外设的数据由CBMutableServicecbmutablecharistic对象表示

当您在本地外设(由CBPeripheralManager对象表示)上设置数据并与之交互时,您正在处理其服务和特征的可变版本。在核心蓝牙框架中,本地外围设备的服务由CBMutableService对象表示。类似地,本地外围设备的服务的特征由cbmutablechartraits对象表示。本地外设的基本结构和特点如图1-7所示。

读写

检索特征值

一个特征包含一个表示外设服务信息的值。例如,健康温度计服务的温度测量特性可能具有一个值,该值指示以摄氏度为单位的温度。您**可以通过直接读取或订阅来检索特征的值 **

  • 直接读取
    1
    2
    NSLog(@"Reading value for characteristic %@", interestingCharacteristic);
    [peripheral readValueForCharacteristic:interestingCharacteristic];
1
2
3
4
5
6
7
- (void)peripheral:(CBPeripheral *)peripheral
didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error {

NSData *data = characteristic.value;
// parse the data as needed
...
  • 订阅特征值
    使用readValueForCharacteristic:方法读取特征值对于静态值是有效的,但它不是检索动态值的最有效方法。检索随时间变化的特征值——例如,您的心率——通过订阅它们。当你订阅一个特征值时,当值发生变化时,你会收到来自外围设备的通知。

[peripheral setNotifyValue:YES forCharacteristic:interestingCharacteristic];

当你订阅(或取消订阅)一个特征值时,外围设备调用它的委托对象的peripheral:didUpdateNotificationStateForCharacteristic:error:方法。如果订阅请求由于任何原因失败,您可以实现这个委托方法来访问错误的原因,如下例所示:

1
2
3
4
5
6
7
8
9
- (void)peripheral:(CBPeripheral *)peripheral
didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error {

if (error) {
NSLog(@"Error changing notification state: %@",
[error localizedDescription]);
}
...

注:并非所有特征都提供订阅。您可以通过检查其properties属性是否包含CBCharacteristicPropertyNotify或CBCharacteristicPropertyIndicate常量来确定一个特征是否提供订阅。

当你成功订阅了一个特征值后,当值发生变化时,外围设备会通知你的应用程序。每次这个值改变时,外围设备都会调用它的委托对象的peripheral:didUpdateValueForCharacteristic:error:方法。要检索更新的值,可以按照上面读取特征值中描述的方法实现此方法。

写特征值

如果一个特征的值是可写的,你可以通过调用外围的writeValue:forCharacteristic:type:方法来写它的值(NSData的一个实例),就像这样:

1
2
3
NSLog(@"Writing value for characteristic %@", interestingCharacteristic);
[peripheral writeValue:dataToWrite forCharacteristic:interestingCharacteristic
type:CBCharacteristicWriteWithResponse];

当您写入一个特征的值时,您可以指定要执行哪种类型的写入。在上面的例子中,写类型是CBCharacteristicWriteWithResponse,它指示外围设备通过调用它的委托对象的peripheral:didWriteValueForCharacteristic:error:方法让你的应用程序知道写是否成功。你可以实现这个委托方法来处理错误情况,如下面的例子所示:

1
2
3
4
5
6
7
8
9
- (void)peripheral:(CBPeripheral *)peripheral
didWriteValueForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error {

if (error) {
NSLog(@"Error writing characteristic value: %@",
[error localizedDescription]);
}
...

如果您指定写类型为CBCharacteristicWriteWithoutResponse,那么写操作将尽最大努力执行,并且既不保证也不报告交付。外围设备不调用任何委托方法。

注意:特征可能只支持某些类型的写操作,也可能根本不支持。您可以通过检查CBCharacteristicPropertyWriteWithoutResponse或CBCharacteristicPropertyWrite常量之一的properties属性来确定一个特性支持哪种类型的写操作

服务和特征由uuid标识

外设的服务和特征由128位特定于蓝牙的uuid标识,这些uuid在核心蓝牙框架中由CBUUID对象表示。并非所有标识服务或特征的uuid都是由蓝牙特殊兴趣小组(Bluetooth Special Interest Group, SIG)预定义的,但蓝牙SIG已经定义并发布了许多常用的uuid,为了方便起见,这些uuid已被缩短为16位。例如,Bluetooth SIG预定义了用于标识心率服务的16位UUID为180D。该UUID是其等效的128位UUID 0000180D-0000-1000-8000-00805F9B34FB的缩写,它基于蓝牙4.0规范,卷3,F部分,章节3.2.1中定义的蓝牙基本UUID。

CBUUID *heartRateServiceUUID = [CBUUID UUIDWithString: @"180D"];