本文轉(zhuǎn)自:http://blog.csdn.net/swibyn/article/details/52096673
Best Practices for Interacting with a Remote Peripheral Device
與peripheral通信的最佳實(shí)踐。
藍(lán)牙庫(kù)使得central端的一些事情的處理變得透明京革。也就是你的應(yīng)用可以實(shí)現(xiàn)central端的大部分事情拿诸,如搜索和連接設(shè)備票摇,檢索和交互peripheral的數(shù)據(jù)私痹。這一章將提供開(kāi)發(fā)指引及如何最佳實(shí)現(xiàn)。
Be Mindful of Radio Usage and Power Consumption
永遠(yuǎn)記住需要使用無(wú)線電并且會(huì)消耗電量
當(dāng)開(kāi)發(fā)應(yīng)用需要用到藍(lán)牙低功耗設(shè)備宣脉,請(qǐng)記住藍(lán)牙低功耗通訊需要使用你設(shè)備的無(wú)線電來(lái)傳輸信號(hào)宁昭。同時(shí)其他形式的無(wú)線通訊也可能使用設(shè)備的無(wú)線電—比如,wi-fi相种,經(jīng)典藍(lán)牙威恼,甚至其他使用藍(lán)牙低功耗的應(yīng)用—所以,盡量讓你的應(yīng)用盡少使用無(wú)線電寝并。
在開(kāi)發(fā)iOS應(yīng)用中箫措,盡少使用無(wú)線電是非常重要的,因?yàn)闊o(wú)線電的使用會(huì)減少電池的壽命衬潦。下面的指引將幫助你如何以更好的方式使用無(wú)線電斤蔓,從而使你的應(yīng)用表現(xiàn)更加,更省電镀岛。
Scan for Devices Only When You Need To
只有在需要的時(shí)候才搜索設(shè)備
當(dāng)你調(diào)用CBCentralManager的scanForPeripheralsWithServices:options: 方法來(lái)搜索(發(fā)現(xiàn))當(dāng)前正在發(fā)送廣播的peripheral弦牡,這時(shí)你正在使用你設(shè)備的無(wú)線電來(lái)監(jiān)聽(tīng)廣播設(shè)備,直到你顯示的停止它漂羊。
除非你需要搜索更多的設(shè)備驾锰,否則在你搜索到所需要的設(shè)備后,及時(shí)的停止搜索走越。使用CBCentralManager的stopScan方法停止搜索設(shè)備椭豫,參見(jiàn)Connecting to a Peripheral Device After You’ve Discovered It.
Specify the CBCentralManagerScanOptionAllowDuplicatesKey Option Only When Necessary
只有在需要的時(shí)候才添加CBCentralManagerScanOptionAllowDuplicatesKey搜索參數(shù)
peripheral設(shè)備一秒鐘可能發(fā)送多個(gè)廣播包。在搜索peripheral時(shí),默認(rèn)情況下捻悯,多次搜到的廣播包只會(huì)觸發(fā)一次事件代理匆赃。結(jié)果就是不管收到多少個(gè)廣播包,central manager對(duì)一個(gè)peripheral只會(huì)觸發(fā)centralManager:didDiscoverPeripheral:advertisementData:RSSI: 方法一次今缚。但是如果peripheral的廣播數(shù)據(jù)變了算柳,也會(huì)重新觸發(fā)代理事件。
如果你不喜歡這種默認(rèn)的方式姓言,你可以在搜索時(shí)給搜索方法scanForPeripheralsWithServices:options: 添加CBCentralManagerScanOptionAllowDuplicatesKey 參數(shù)瞬项。 這樣的話,就可以每次收到廣播包信息都觸發(fā)消息何荚。在某些情況下囱淋,我們需要這么做。比如說(shuō)需要檢查設(shè)備是在靠近還是在遠(yuǎn)離(通過(guò)RSSI值判斷)餐塘。所以妥衣,請(qǐng)記住添加這個(gè)參數(shù)會(huì)消耗電量,并影響性能戒傻,只有在確定需要的時(shí)候才使用這個(gè)參數(shù)税手。
Explore a Peripheral’s Data Wisely
明智的檢索peripheral的數(shù)據(jù)
peripheral設(shè)備可能會(huì)有多個(gè)services和characteristics。如果搜索全部的services和characteristics會(huì)浪費(fèi)電量芦倒,對(duì)應(yīng)用性能也不好。所以我們應(yīng)該只搜索那些我們需要的services和characteristics兵扬。
比如,peripheral設(shè)備上有多個(gè)services器钟,而我們只需要其中兩個(gè),那么在使用CBPeripheral 的discoverServices: 方法進(jìn)行搜索時(shí)亚皂,通過(guò)CBUUID的對(duì)象封裝我們需要的services俱箱,作為參數(shù)傳過(guò)去灭必。如下
[peripheral discoverServices:@[firstServiceUUID, secondServiceUUID]];
在搜索到需要的services之后,接著就搜索需要的characteristics禁漓。同樣的跟衅,使用CBUUID封裝好需要的characteristics,使用CBPeripheral 的discoverCharacteristics:forService: 方法開(kāi)始搜索播歼。
Subscribe to Characteristic Values That Change Often
訂閱經(jīng)常改變的characteristic值
在Retrieving the Value of a Characteristic談過(guò)伶跷,有兩種方式可以獲得characteristic的值。
1蹈集,在需要的時(shí)候使用readValueForCharacteristic: 輪詢characteristic的值
2,使用setNotifyValue:forCharacteristic: 訂閱這個(gè)characteristic拢肆。
可能的話靖诗,最好采用訂閱的方式,特別是在characteristic的值經(jīng)常變的情況下刊橘。至于如何訂閱參見(jiàn)Subscribing to a Characteristic’s Value.
Disconnect from a Device When You Have All the Data You Need
當(dāng)獲得全部所需數(shù)據(jù)后斷開(kāi)設(shè)備連接
當(dāng)連接已不再需要的時(shí)候,斷開(kāi)連接促绵,這樣有助于降低無(wú)線電的使用。下面兩種情況叙甸,你應(yīng)用斷開(kāi)與peripheral的連接。
1,你所訂閱的特征值已不再發(fā)通知熔萧。(可以通過(guò)characteristic的isNotifying屬性得知)
2,你已獲得了全部所需要的數(shù)據(jù)贮缕。
這兩種情況下俺榆,取消訂閱并斷開(kāi)連接。通過(guò)setNotifyValue:forCharacteristic: 設(shè)置第一個(gè)參數(shù) 為NO來(lái)取消訂閱罐脊,通過(guò)CBCentralManager 的cancelPeripheralConnection:方法取消連接。如下:
[myCentralManager cancelPeripheralConnection:peripheral];
注意:cancelPeripheralConnection: 這個(gè)方法是非阻塞的宵溅,所以其他正在進(jìn)行的通訊可能完成也可能因此沒(méi)完成。因?yàn)槠渌麘?yīng)用可能仍保持跟這個(gè)設(shè)備的連接恃逻,所以當(dāng)前的取消連接并不能保證底層就立即斷開(kāi)物理上的連接。但從應(yīng)用本身看來(lái)寇损,這個(gè)設(shè)備已經(jīng)被認(rèn)為是斷開(kāi)連接了,central manager對(duì)象也對(duì)觸發(fā)代理的centralManager:didDisconnectPeripheral:error: 方法线椰。
Reconnecting to Peripherals
重新連接peripherals
有三種方式可以重連
1尘盼,重新獲取已發(fā)現(xiàn)的設(shè)備列表(搜索到的或是連接過(guò)的設(shè)備)憨愉,使用 retrievePeripheralsWithIdentifiers: 卿捎。如果列表中有想要尋找的設(shè)備,那么發(fā)起連接躺孝。參見(jiàn)Retrieving a List of Known Peripherals
2底桂,重新獲取當(dāng)前連接著的設(shè)備列表植袍,使用retrieveConnectedPeripheralsWithServices:籽懦。 如果列表中有想要尋找的設(shè)備,發(fā)起本地連接暮顺,使得應(yīng)用與之連接上。參見(jiàn)Retrieving a List of Connected Peripherals 羽氮。
3惫恼,使用scanForPeripheralsWithServices:options: 重新搜索設(shè)備,如果找到了就去連接祈纯。參見(jiàn)Discovering Peripheral Devices That Are Advertising and Connecting to a Peripheral Device After You’ve Discovered It.
實(shí)際情況下,你可能不想每次連接都先去搜索設(shè)備盆繁,你可能更希望使用另外兩種方式。如圖5-1所示革娄,一種先嘗試使用另兩種方式連接的方法
Figure 5-1 A sample reconnection workflow
注意:采用什么方式,什么順序依情況而定拦惋,比如你可以不采用第一種方式,也可以同時(shí)使用前兩種并行的方式厕妖。
Retrieving a List of Known Peripherals
獲取已知設(shè)備列表
當(dāng)你第一次發(fā)現(xiàn)某個(gè)peripheral,系統(tǒng)會(huì)為他生成一個(gè)identifier(一個(gè)NSUUID對(duì)象)软能,你可以保存這個(gè)identifier(比如用NSUserDefaults保存)举畸,然后在后面需要用的時(shí)候使用retrievePeripheralsWithIdentifiers: 重新連接。
當(dāng)應(yīng)用啟動(dòng)時(shí)抄沮,調(diào)用retrievePeripheralsWithIdentifiers: 方法,傳入包含peripheral的identifiers的array:如下:
knownPeripherals = [myCentralManager retrievePeripheralsWithIdentifiers:savedIdentifiers];
central manager嘗試匹配你傳入的identifiers叛买,并返回CBPeripheral對(duì)象。如果沒(méi)有匹配的設(shè)備刻伊,array將為空难礼,這時(shí)你需要使用另外兩種方式。如果不為空蛾茉,那么讓用戶選擇要連接到哪個(gè)設(shè)備撩鹿。
當(dāng)用戶選擇了要連接的設(shè)備,則調(diào)用connectPeripheral:options: 方法來(lái)嘗試連接节沦。如果設(shè)備被連接上,則會(huì)觸發(fā)代理消息centralManager:didConnectPeripheral: 吼鳞。
注意:可能有多種原因?qū)е略O(shè)備不能被連接上叫搁。比如供炎,設(shè)備不在附近。還有一種可能音诫,一些低功耗藍(lán)牙使用隨機(jī)設(shè)備地址雪位,在重新連接時(shí),它的地址可能已經(jīng)變了雹洗。因此,即使設(shè)備就在附近庇茫,設(shè)備的地址也已經(jīng)變了,這種情況下港令,你想要連接的設(shè)備與實(shí)際設(shè)備已經(jīng)不匹配了锈颗。這種情況,你只有重新搜索了击吱。更多詳情請(qǐng)參考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
獲取已連接藍(lán)牙
另一種重新連接的方法是檢查你想要連接的設(shè)備是否已經(jīng)連接到系統(tǒng)了(可能其他應(yīng)用正連著呢)覆醇。你可以使用retrieveConnectedPeripheralsWithServices: 方法獲取CBPeripheral對(duì)象Array。
因?yàn)楫?dāng)前可能有多個(gè)peripheral連接著系統(tǒng)永脓,你可以傳遞CBUUID對(duì)象(注意是service的 UUID)的Array。這樣他將只返回當(dāng)前連接著的搅吁,并且包含array中所有serives的peripheral。如果沒(méi)有符合條件的谎懦,則返回的array為空溃斋,這時(shí)你需要使用別的方法。如果array不為空梗劫,那么讓用戶來(lái)選擇截碴。
如果用戶找到并選擇了所要的peripheral隐岛,使用connectPeripheral:options: 把它連接到你的應(yīng)用瓷翻。當(dāng)連接建立聚凹,會(huì)觸發(fā)代理centralManager:didConnectPeripheral: 這時(shí)說(shuō)明連接成功了齐帚。