StupidBeauty
Read times:748Posted at:Wed Sep 25 16:56:59 2013
- no title specified

iOS开发文档翻译:完成常见的中央设备角色任务,Performing Common Central Role Tasks

在蓝牙低功耗通信过程中充当中央设备角色的设备,会完成一系列的常见任务—例如,发现并连接到可用的外设,探索并与该外设提供的数据进行交互。反过来,充当外设角色的设备也会完成一系列常见却不同的任务—例如,发布并且广播服务,对已连接的中央设备的读、写和订阅请求作出响应。

在本章节中,妳将会学习,怎么样使用Core Bluetooth 框架来完成中央设备一侧的大部分蓝牙低功耗任务。下面带代码的示例会帮助妳在本地设备上实现中央设备角色。妳将会学到:

  • •.启动一个中央设备管理对象

  • •.发现并连接到正在广播的外设

  • •.在连接到一个外设之后,探索它的数据

  • •.向一个外设的一个服务中的一个特性值发送读取及写入请求

  • •.订阅某个特性的值,以便当它被更新时得到通知

在下一章节中,妳将会学到如何在本地设备上实现外设角色。

妳在本章节中看到的代码示例是简单而又抽象的;当妳将它们用于实际的软件中时,可能需要做一些适当的修改。关于实现中央设备角色的更高级的话题—包括建议、技巧和最佳实践—将会在之后的章节中呈现, iOS 软件的 Core Bluetooth 后台处理”“与远端外设交互时的最佳实践”

启动一个中央设备管理器

CBCentralManager 对象是Core Bluetooth 中对本地中央设备的面向对象表示方式,所以,在妳进行任何与蓝牙低功耗相关的操作之前,都要创建并初始化一个中央设备管理器实例。妳可以通过调用 CBCentralManager 类的 initWithDelegate:queue:options: 方法来启动一个中央设备管理器,比如这样:

myCentralManager =

[[CBCentralManager alloc] initWithDelegate:self queue:nil options:nil];

在这个例子中,self 被设置为代表(delegate),用来接收任何中央设备角色的事件。由于将事件分发队列设置为了nil,所以中央设备管理器会使用主事件队列来分发中央设备相关的事件。

当妳创建一个中央设备管理器时,该中央设备管理器会调用它的代表对象的 centralManagerDidUpdateState: 方法。妳必须实现这个代表方法,以检查确认在当前中央设备上蓝牙低功耗是被支持并且是可用的。关于如何实现这个代表方法的更多信息,参考 CBCentralManagerDelegate协议参考

发现那些正在广播的外设

妳最有可能做的第一件中央设备侧任务就是,发现那些可被妳的软件连接到的外设。之前在“中央设备发现并且连接到正在广播的外设”里面已经说过,发送广播是外设使得其它设备得知它的存在的主要手段。妳可以通过调用 CBCentralManager 类的 scanForPeripheralsWithServices:options: 方法来发现任何正在发送广播的外设,就像这样:

[myCentralManager scanForPeripheralsWithServices:nil options:nil];

注意:如果妳将第一个参数设置为nil,则中央设备管理器会返回所有被发现的外设,而不管它们分别都支持什么服务。在一个实际使用的软件中,妳通常会指定一个 CBUUID 对象数组,其中每个对象都表示了某个外设正在广播的一个服务所对应的宇宙唯一标识符(UUID)。当妳指定了一个由服务的宇宙唯一标识符组成的数组时,中央设备管理器只会返回那些广播了这些服务的外设,这就使得妳可以只扫描那些妳感兴趣的外设。

宇宙唯一标识符,以及用来表示它们的 CBUUID 对象,将会在“服务和特性是由宇宙唯一标识符来标识的”里详细说明。

当妳调用了 scanForPeripheralsWithServices:options: 方法来发现可用的外设之后,中央设备管理器会在每次发现了一个外设之后调用它的代表对象的 centralManager:didDiscoverPeripheral:advertisementData:RSSI: 方法。每个被发现的外设都会以一个 CBPeripheral 对象的形式返回。就像以下代码展示的这样,妳可以实现这个代表方法,来列出所有被发现的外设:

- (void)centralManager:(CBCentralManager *)central

didDiscoverPeripheral:(CBPeripheral *)peripheral

advertisementData:(NSDictionary *)advertisementData

RSSI:(NSNumber *)RSSI {

NSLog(@"Discovered %@", peripheral.name);

...

当妳找到了要连接的外设之后,停止扫描其它设备,以节约用电。

[myCentralManager stopScan];

NSLog(@"Scanning stopped");

在发现一个外设之后,连接到它

在发现了一个正在广播妳感兴趣的服务的外设之后,妳就可以通过调用 CBCentralManager 类的 connectPeripheral:options: 方法来要求连接到该外设。只需要调用此方法并且指定妳想要连接的外设,就像这样:

[myCentralManager connectPeripheral:peripheral options:nil];

假设连接请求成功完成,则,中央设备管理器会调用它的代表对象的 centralManager:didConnectPeripheral: 方法,妳可以实现该方法,以便记录下来该连接已经建立,就像这样:

- (void)centralManager:(CBCentralManager *)central

didConnectPeripheral:(CBPeripheral *)peripheral {

NSLog(@"Peripheral connected");

...

在妳开始与该外设交互之前,应当设置该外设的代表对象,以确保能够收到适当的回调,就像这样:

peripheral.delegate = self;

探索已连接的外设的服务

在连接到一个外设之后,就可以开始探索它的数据了。探索某个外设所能提供的数据的第一步,就是去发现它所提供的服务。由于外设广播的数据包的尺寸有限,所以,妳会发现,一个外设所能提供的服务往往比它广播的(在广播数据包中广播的)要多。妳可以调用 CBPeripheral 类的 discoverServices: 方法来发现该外设提供的所有服务,就像这样:

[peripheral discoverServices:nil];

注意:在一个实际使用的软件中,妳一般不会使用nil 作为参数,因为,这将会返回该外设提供的所有服务。由于外设可能会包含了比妳感兴趣的服务多得多的服务,所以,去发现所有的服务的话,会折损电池寿命,同时也是花费不必要的时间。通常情况下,妳会在发现服务的步骤中指定那些已知感兴趣的服务的宇宙唯一标识符,在“理性地探索一个外设的数据”里有演示。

当指定的服务被发现之后,该外设(妳所连接到的 CBPeripheral 对象)会调用它的代表对象的 peripheral:didDiscoverServices: 方法。Core Bluetooth会创建一个由 CBService 对象组成的数组—其中每个都对应着在该外设上发现的一个服务。就像以下代码演示的那样,妳可以实现这个方法,来访问被发现的服务的数组:

- (void)peripheral:(CBPeripheral *)peripheral

didDiscoverServices:(NSError *)error {

for (CBService *service in peripheral.services) {

NSLog(@"Discovered service %@", service);

...

}

...

发现一个服务的特性

假设妳找到了一个妳感兴趣的服务,那么,探索该外设可提供的数据的下一步,就是,发现该服务的所有特性。发现一个服务的所有特性是非常简单的事,只需调用 CBPeripheral 类的 discoverCharacteristics:forService: 方法,并且指定适当的服务对象,就像这样:

NSLog(@"Discovering characteristics for service %@", interestingService);

[peripheral discoverCharacteristics:nil forService:interestingService];

注意:在一个实际的软件中,妳一般不会将nil 作为第一个参数,因为这将会导致返回该外设的服务的所有特性。由于一个外设的某个服务可能会包含比妳所感兴趣的特性多得多的特性,所以,去发现所有的特性会导致折损电池寿命,同时也会花费不必要的时间。一般情况下,妳会在发现特性的过程中,指定那些妳已知感兴趣的特性的宇宙唯一标识符。

在发现了指定服务的特性之后,外设对象会调用它的代表对象的 peripheral:didDiscoverCharacteristicsForService:error: 方法。Core Bluetooth 会创建一个由 CBCharacteristic 对象组成的数组—每个都对应着一个被发现的特性。以下示例,演示了,妳可以实现这个方法来记录下被发现的特性:

- (void)peripheral:(CBPeripheral *)peripheral

didDiscoverCharacteristicsForService:(CBService *)service

error:(NSError *)error {

for (CBCharacteristic *characteristic in service.characteristics) {

NSLog(@"Discovered characteristic %@", characteristic);

...

}

...

获取某个特性的值

一个特性,包含着一个单独的值,它代表着关于某个外设的服务的更多信息。例如,某个体温计服务的温度测量特性,可能拥有一个值,以摄氏度来指示当前体温。妳可以通过两种方式来获取某个特性的值:直接读取它;订阅它。

读取某个特性的值

当妳找到了妳感兴趣的服务的某个特性之后,妳可以通过调用 CBPeripheral 类的 readValueForCharacteristic: 方法来读取该特性的值,要指定适当的特性作为参数,就像这样:

NSLog(@"Reading value for characteristic %@", interestingCharacteristic);

[peripheral readValueForCharacteristic:interestingCharacteristic];

当妳尝试着读取某个特性的值时,外设会调用它的代表对象的 peripheral:didUpdateValueForCharacteristic:error: 方法来获取该值。如果该值被成功获取到了,则妳可以通过该属性的值属性来访问到它,就像这样:

- (void)peripheral:(CBPeripheral *)peripheral

didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic

error:(NSError *)error {

NSData *data = characteristic.value;

// 按照实际需要来解析数据

...

注意:并不是所有的特性都确保拥有可读的值。妳可以通过访问一个特性的 CBCharacteristicPropertyRead 常量来确定它的值是否可读,具体细节见 CBCharacteristic类参考 。如果妳试图读取一个不可读的值,则 peripheral:didUpdateValueForCharacteristic:error: 代表方法会返回一个对应的错误。

订阅某个特性的值

尽管使用 readValueForCharacteristic: 方法来读取一个特性的值在某些情况下是足够有效率的,但是,它并不是用来获取会变化的值的最有效率的手段。对于大部分会变化的特性值—例如,妳在任何时刻的心率—妳应当通过订阅它们来获取它们的值。当妳订阅了一个特性的值的时候,每当该值发生改变,妳都会从该外设对象收到一个通知。

妳可以通过调用 CBPeripheral 类的 setNotifyValue:forCharacteristic: 方法来订阅到妳感兴趣的特性的值,指定YES 作为第一个参数,就像这样:

[peripheral setNotifyValue:YES forCharacteristic:interestingCharacteristic];

当妳尝试订阅(或取消订阅)到一个特性的值的时候,外设对象会调用它的代表对象的 peripheral:didUpdateNotificationStateForCharacteristic:error: 方法。如果此次订阅请求因为任何原因而失败的话,妳可以实现这个代表方法,以得知发生错误的原因,就像以下示例中的这样:

- (void)peripheral:(CBPeripheral *)peripheral

didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic

error:(NSError *)error {

if (error) {

NSLog(@"Error changing notification state: %@",

[error localizedDescription]);

}

...

注意:并非所有的特性都允许妳订阅它们的值。妳可通过访问 特性属性 枚举中相关的常量来确定某个特性是否允许订阅,详情见 CBCharacteristic类参考

当妳成功地订阅到一个特性的值之后,外设就会在该值发生改变时通知妳。每当该值发生改变时,外设对象就会调用它的代表对象的 peripheral:didUpdateValueForCharacteristic:error: 方法。要想获取新的值,妳就按照之前在“读取某个特性的值”里说的方法那样来实现这个方法就可以。

写入某个特性的值

在某些情况下,有必要向某个特性写入新的值。例如,如果妳的软件在与一个蓝牙低功耗的数字式恒温器交互,则妳可能需要向恒温器提供一个值,让它将室温控制在这个值的水平。如果某个特性的值是可写的,则妳可以带着数据( NSData 的一个实例)调用 CBPeripheral 类的 writeValue:forCharacteristic:type: 方法来写入它的值,就像这样:

NSLog(@"Writing value for characteristic %@", interestingCharacteristic);

[peripheral writeValue:dataToWrite forCharacteristic:interestingCharacteristic

type:CBCharacteristicWriteWithResponse];

当妳尝试写入某个特性的值的时候, 妳需要指定所要进行的写入类型。在上面的例子中,写入类型被指定为 CBCharacteristicWriteWithResponse ,意思就是,外设对象会让妳的软件知道写入操作是否成功。参考 CBPeripheral类参考 中的 CBCharacteristicWriteType 枚举值,以了解更多关于Core Bluetooth 框架中被支持的写入类型的信息。

外设对象通过调用它的代表对象的 peripheral:didWriteValueForCharacteristic:error: 方法来对指定为 CBCharacteristicWriteWithResponse 类型的写入请求作出响应。如果写入请求因为任何原因而失败了,妳可以通过实现这个代表方法来得知发生错误的原因,就像以下示例中这样:

- (void)peripheral:(CBPeripheral *)peripheral

didWriteValueForCharacteristic:(CBCharacteristic *)characteristic

error:(NSError *)error {

if (error) {

NSLog(@"Error writing characteristic value: %@",

[error localizedDescription]);

}

...

注意:有些特性可能只允许对它们的值进行一部分类型的写入操作。要想确定某个特性的值允许进行哪些类型的写操作,就访问 特性属性 枚举量的相关属性,详情见 CBCharacteristic类参考

办公室女郎

未知美人

未知美人

未知美人

Your opinions
Your name:Email:Website url:Opinion content:
- no title specified

HxLauncher: Launch Android applications by voice commands

 
Recent comments
2017年4月~2019年4月垃圾短信排行榜Posted at:Thu Sep 26 04:51:48 2024
Qt5.7文档翻译:QWebEngineCookieStore类,QWebEngineCookieStore ClassPosted at:Fri Aug 11 06:50:35 2023盲盒kill -9 18289 Grebe.20230517.211749.552.mp4