ios蓝牙开发学习笔记(五)与peripheral通信的最佳实践

本文转自:http://blog.csdn.net/swibyn/article/details/52096673

Best Practices for Interacting with a Remote Peripheral Device

与peripheral通信的最佳实践。

蓝牙库使得central端的一些事情的处理变得透明。也就是你的应用可以实现central端的大部分事情,如搜索和连接设备,检索和交互peripheral的数据。这一章将提供开发指引及如何最佳实现。

Be Mindful of Radio Usage and Power Consumption

永远记住需要使用无线电并且会消耗电量

当开发应用需要用到蓝牙低功耗设备,请记住蓝牙低功耗通讯需要使用你设备的无线电来传输信号。同时其他形式的无线通讯也可能使用设备的无线电—比如,wi-fi,经典蓝牙,甚至其他使用蓝牙低功耗的应用—所以,尽量让你的应用尽少使用无线电。

在开发iOS应用中,尽少使用无线电是非常重要的,因为无线电的使用会减少电池的寿命。下面的指引将帮助你如何以更好的方式使用无线电,从而使你的应用表现更加,更省电。
Scan for Devices Only When You Need To

只有在需要的时候才搜索设备

当你调用CBCentralManager的scanForPeripheralsWithServices:options: 方法来搜索(发现)当前正在发送广播的peripheral,这时你正在使用你设备的无线电来监听广播设备,直到你显示的停止它。
除非你需要搜索更多的设备,否则在你搜索到所需要的设备后,及时的停止搜索。使用CBCentralManager的stopScan方法停止搜索设备,参见Connecting to a Peripheral Device After You’ve Discovered It.

Specify the CBCentralManagerScanOptionAllowDuplicatesKey Option Only When Necessary

只有在需要的时候才添加CBCentralManagerScanOptionAllowDuplicatesKey搜索参数

peripheral设备一秒钟可能发送多个广播包。在搜索peripheral时,默认情况下,多次搜到的广播包只会触发一次事件代理。结果就是不管收到多少个广播包,central manager对一个peripheral只会触发centralManager:didDiscoverPeripheral:advertisementData:RSSI: 方法一次。但是如果peripheral的广播数据变了,也会重新触发代理事件。

如果你不喜欢这种默认的方式,你可以在搜索时给搜索方法scanForPeripheralsWithServices:options: 添加CBCentralManagerScanOptionAllowDuplicatesKey 参数。 这样的话,就可以每次收到广播包信息都触发消息。在某些情况下,我们需要这么做。比如说需要检查设备是在靠近还是在远离(通过RSSI值判断)。所以,请记住添加这个参数会消耗电量,并影响性能,只有在确定需要的时候才使用这个参数。

Explore a Peripheral’s Data Wisely

明智的检索peripheral的数据

peripheral设备可能会有多个services和characteristics。如果搜索全部的services和characteristics会浪费电量,对应用性能也不好。所以我们应该只搜索那些我们需要的services和characteristics。

比如,peripheral设备上有多个services,而我们只需要其中两个,那么在使用CBPeripheral 的discoverServices: 方法进行搜索时,通过CBUUID的对象封装我们需要的services,作为参数传过去。如下

[peripheral discoverServices:@[firstServiceUUID, secondServiceUUID]];

在搜索到需要的services之后,接着就搜索需要的characteristics。同样的,使用CBUUID封装好需要的characteristics,使用CBPeripheral 的discoverCharacteristics:forService: 方法开始搜索。

Subscribe to Characteristic Values That Change Often

订阅经常改变的characteristic值

在Retrieving the Value of a Characteristic谈过,有两种方式可以获得characteristic的值。

1,在需要的时候使用readValueForCharacteristic: 轮询characteristic的值
2,使用setNotifyValue:forCharacteristic: 订阅这个characteristic。

可能的话,最好采用订阅的方式,特别是在characteristic的值经常变的情况下。至于如何订阅参见Subscribing to a Characteristic’s Value.

Disconnect from a Device When You Have All the Data You Need

当获得全部所需数据后断开设备连接

当连接已不再需要的时候,断开连接,这样有助于降低无线电的使用。下面两种情况,你应用断开与peripheral的连接。

1,你所订阅的特征值已不再发通知。(可以通过characteristic的isNotifying属性得知)
2,你已获得了全部所需要的数据。

这两种情况下,取消订阅并断开连接。通过setNotifyValue:forCharacteristic: 设置第一个参数 为NO来取消订阅,通过CBCentralManager 的cancelPeripheralConnection:方法取消连接。如下:

[myCentralManager cancelPeripheralConnection:peripheral];

注意:cancelPeripheralConnection: 这个方法是非阻塞的,所以其他正在进行的通讯可能完成也可能因此没完成。因为其他应用可能仍保持跟这个设备的连接,所以当前的取消连接并不能保证底层就立即断开物理上的连接。但从应用本身看来,这个设备已经被认为是断开连接了,central manager对象也对触发代理的centralManager:didDisconnectPeripheral:error: 方法。

Reconnecting to Peripherals

重新连接peripherals

有三种方式可以重连

1,重新获取已发现的设备列表(搜索到的或是连接过的设备),使用 retrievePeripheralsWithIdentifiers: 。如果列表中有想要寻找的设备,那么发起连接。参见Retrieving a List of Known Peripherals
2,重新获取当前连接着的设备列表,使用retrieveConnectedPeripheralsWithServices:。 如果列表中有想要寻找的设备,发起本地连接,使得应用与之连接上。参见Retrieving a List of Connected Peripherals 。
3,使用scanForPeripheralsWithServices:options: 重新搜索设备,如果找到了就去连接。参见Discovering Peripheral Devices That Are Advertising and Connecting to a Peripheral Device After You’ve Discovered It.

实际情况下,你可能不想每次连接都先去搜索设备,你可能更希望使用另外两种方式。如图5-1所示,一种先尝试使用另两种方式连接的方法

Figure 5-1 A sample reconnection workflow

1.png

注意:采用什么方式,什么顺序依情况而定,比如你可以不采用第一种方式,也可以同时使用前两种并行的方式。

Retrieving a List of Known Peripherals

获取已知设备列表

当你第一次发现某个peripheral,系统会为他生成一个identifier(一个NSUUID对象),你可以保存这个identifier(比如用NSUserDefaults保存),然后在后面需要用的时候使用retrievePeripheralsWithIdentifiers: 重新连接。

当应用启动时,调用retrievePeripheralsWithIdentifiers: 方法,传入包含peripheral的identifiers的array:如下:

knownPeripherals = [myCentralManager retrievePeripheralsWithIdentifiers:savedIdentifiers];

central manager尝试匹配你传入的identifiers,并返回CBPeripheral对象。如果没有匹配的设备,array将为空,这时你需要使用另外两种方式。如果不为空,那么让用户选择要连接到哪个设备。

当用户选择了要连接的设备,则调用connectPeripheral:options: 方法来尝试连接。如果设备被连接上,则会触发代理消息centralManager:didConnectPeripheral: 。

注意:可能有多种原因导致设备不能被连接上。比如,设备不在附近。还有一种可能,一些低功耗蓝牙使用随机设备地址,在重新连接时,它的地址可能已经变了。因此,即使设备就在附近,设备的地址也已经变了,这种情况下,你想要连接的设备与实际设备已经不匹配了。这种情况,你只有重新搜索了。更多详情请参考Bluetooth 4.0 specification, Volume 3, Part C, Section 10.8 and Bluetooth Accessory Design Guidelines for Apple Products.

Retrieving a List of Connected Peripherals

获取已连接蓝牙

另一种重新连接的方法是检查你想要连接的设备是否已经连接到系统了(可能其他应用正连着呢)。你可以使用retrieveConnectedPeripheralsWithServices: 方法获取CBPeripheral对象Array。

因为当前可能有多个peripheral连接着系统,你可以传递CBUUID对象(注意是service的 UUID)的Array。这样他将只返回当前连接着的,并且包含array中所有serives的peripheral。如果没有符合条件的,则返回的array为空,这时你需要使用别的方法。如果array不为空,那么让用户来选择。

如果用户找到并选择了所要的peripheral,使用connectPeripheral:options: 把它连接到你的应用。当连接建立,会触发代理centralManager:didConnectPeripheral: 这时说明连接成功了。

推荐阅读更多精彩内容