iOS BLE 開發小記[5] 與 Remote Peripheral 交互的最佳實踐

歡迎訪問個人博客 muhlenXi,該文章出自個人博客,歡迎轉載,轉載請註明來源: muhlenxi.com/2017/05/05/…html

導語:

在這一節,主要是與 Remote Peripheral 交互的最佳實踐,以及實際開發過程當中應該注意的事項。數組

CoreBluetooth 框架使 Central 端的工做變得容易透明、容易理解。也就是說,你的 APP 能夠控制和負責 Central 的大部分方面,好比搜索設備、創建鏈接、與 Remote Peripheral 進行數據交互。本章將以負責的方式來提供一些規範和最佳實踐,尤爲是當你爲 iOS 設備開發 APP 的時候。app

要留意 Radio 的使用和電量的消耗

當開發一個 APP 與 BLE 設備交互時,須要銘記:BLE 通訊會經過你的設備向空中發射 Radio 信號。其餘形式的無線通訊也可能須要使用設備的 Radio,好比,Wi-Fi,傳統藍牙以及使用 BLE 的其餘 APP。所以要減小 Radio 的使用。框架

當開發 iOS 設備的 APP 時,最少次數使用 Radio 很重要,由於 Radio 的使用會對 iOS 設備電池的續航時間有不利影響。如下的這些規範將會幫助你更好的使用 Radio。做爲回報,你的 APP 會良好運行和你設備電池的續航時間將會延長。ide

只在須要的時候搜索周邊設備

當你調用 CBCentralManager 類的 scanForPeripheralsWithServices:options: 方法來搜索正在廣播數據的 Remote Peripheral 時,你設備的 Radio 會一直監聽正在廣播的設備,直到你中止搜索爲止。性能

除非你須要搜索更多的設備,不然當你找到你想要鏈接的設備後就應該中止搜索,前幾篇提到過,用 CBCentralManager 類的 stopScan 方法來中止搜索設備。ui

必要的時候再指定 CBCentralManagerScanOptionAllowDuplicatesKey 選項

Remote Peripheral 設備可能會每秒發送多個廣播數據包給監聽的 Central,當你調用 scanForPeripheralsWithServices:options: 方法搜索設備時,該方法默認的行爲是將一個 Peripheral 的多個發現事件合併成一個發現事件,也就是說,Central Manager 每找到一個新的 Peripheral 時纔會調用 centralManager:didDiscoverPeripheral:advertisementData:RSSI: 代理方法,無論收到多少廣播數據包都不會調用該方法。當已發現的 Peripheral 的廣播數據發生變化時也會調用這一代理方法。spa

若是你想改變默認行爲,調用 scanForPeripheralsWithServices:options: 方法時你能夠指定 scan option 爲 CBCentralManagerScanOptionAllowDuplicatesKey,這樣每當 Central 收到來自 Peripheral 的數據包就會建立一個發現事件。對於某些狀況關閉默認行爲會頗有用,好比基於 Peripheral 的 Proximity (靠近程度)來進行鏈接交互。Proximity 能夠經過 Peripheral 的 接收信號強度指示(RSSI)的值來判斷,也就是說,指定這個掃描選項會對電源的續航和 APP 的運行形成不利影響。所以,只在必要的狀況下再指定該方法的 scan option。代理

明智地獲取 Peripheral 的數據

當你開發 APP 的時候,對於特定的使用情景,一個 Peripheral 設備可能擁的大量的 Service 和 Characteristic 已經超過了你須要的數量 ,搜索 Peripheral 所有的 Service 和 Characteristic 對電源的續航和 APP 的性能帶來不利影響。所以。你應該只搜索你的 APP 須要的 Service 和 Characteristic。code

舉個例子,假如你鏈接的 Peripheral 有許多可用的 Service,可是你的 APP 只須要用到其中的兩個。你只須要搜索這兩個 Service 就能夠了,只須要調用 CBPeripheral 類的 discoverServices: 方法時傳入 Service UUID(用 CBUUID 對象表示) 數組就能夠了。以下所示:

[peripheral discoverServices:@[firstServiceUUID, secondServiceUUID]];
複製代碼

當你搜索到這兩個須要的 Service 後,你能夠用類似的方式來搜索你須要的 Characteristic,一樣地,在調用 CBPeripheral 類的 discoverCharacteristics:forService: 方法時傳入你想要的 Characteristic UUID(用 CBUUID 對象表示) 數組就能夠了。

訂閱值頻繁變化的 Characteristic

經過前面的文章,咱們瞭解到,獲取一個 Characteristic 值的方式有兩種:

  • 你能夠在每次須要值的時候明確的調用 readValueForCharacteristic: 方法來讀取 Characteristic 的值。
  • 你能夠調用 setNotifyValue:forCharacteristic: 方法來訂閱 Characteristic 的值,這樣當值發生改變後就會收到來自 Peripheral 的通知。

對於值可能變化的 Characteristic 來講,訂閱是最佳實踐方式,尤爲是對於值頻繁改變的 Characteristic,關於如何訂閱一個 Characteristic 的值,能夠查閱 Subscribing to a Characteristic’s Value.

當你獲得你須要的數據後斷開與設備的鏈接

當再也不須要鏈接的時候與設備斷開鏈接能夠幫助你減小 Radio 的使用,你應該在如下的情景中斷開與 Peripheral 設備的鏈接:

  • 你全部訂閱的 Characteristic 的值已經再也不通知,你能夠經過 Characteristic 的 isNotifying 屬性來判斷 Characteristic 的值是否通知。
  • 你從 Peripheral 設備中獲得了全部的數據。

在上述的場景中,取消一些訂閱並與 Peripheral 斷開鏈接,你能夠經過調用 setNotifyValue:forCharacteristic: 方法來取消訂閱一個 Characteristic 的值,設置第一個參數爲 NO 。你能夠經過調用 CBCentralManager 類的 cancelPeripheralConnection: 方法來斷開與 Peripheral 設備的鏈接。像這樣:

[myCentralManager cancelPeripheralConnection:peripheral];
複製代碼

提示:cancelPeripheralConnection:方法是 nonblocking(非阻塞)的,一些 CBPeripheral 類的命令仍然等待 Peripheral,當你嘗試斷開鏈接可能沒有完成執行.由於可能其餘 APP 還在鏈接 Peripheral,取消一個本地鏈接不能保證設備物理鏈接馬上斷開。從 APP 的角度來看,認爲 Peripheral 是斷開的,Central Manager 會調用 centralManager:didDisconnectPeripheral:error: 代理方法進行回調。

從新鏈接 Peripheral

使用 CoreBluetooth 框架,你有三種方式能夠從新鏈接 Peripheral:

  • 經過調用 retrievePeripheralsWithIdentifiers: 方法來恢復一個已知的 Peripheral 列表 --- Peripheral 是你發現的或者過去鏈接的。若是你要找的 Peripheral 在列表中,嘗試去鏈接它。這種重連方式在 恢復已知的 Peripheral 列表 小節中有描述。

  • 經過調用 retrieveConnectedPeripheralsWithServices: 方法來恢復系統當前已經鏈接的 Peripheral 列表,若是你要找的在列表中,則與它建立一個本地鏈接,這種重連方式在 恢復當前已鏈接的 Peripheral 列表 小節中有描述。

  • 經過調用 scanForPeripheralsWithServices:options: 方法掃描和搜索 Peripheral,若是找到它,則鏈接。這種方式在 iOS BLE 開發小記[2]中有描述。

根據使用狀況,每次重連 Peripheral ,你可能不想掃描和搜索一樣的 Peripheral,你可能首先想用其餘方式來重連。如圖所示,一個可能的重連工做流程多是按照上面的提到的順序依次嘗試這些方式。

重連工做流程

提示:你決定嘗試的重連方式的個數取決於 APP 的使用狀況,舉個例子,你可能決定不使用第一種方式,或者你可能並行使用第一種和第二種方式。

恢復已知的 Peripheral 列表

當你第一次發現一個 Peripheral 時候,系統會建立一個標識符(用 NSUUID 對象表示的一個 UUID)來標識這個 Peripheral,你可使用 NSUserDefaults 來保存這個標識符。事後你能夠嘗試調用CBCentralManager 類的 retrievePeripheralsWithIdentifiers: 方法來恢復並從新鏈接這個 Peripheral,下面描述的一種方式就是使用這個方法來從新鏈接之前的 Peripheral。

當 APP 啓動時,調用 retrievePeripheralsWithIdentifiers: 方法,傳入一個包含 Peripheral 標識符的數組來發現和重連先前的 Peripheral,像這樣:

knownPeripherals =
        [myCentralManager retrievePeripheralsWithIdentifiers:savedIdentifiers];
複製代碼

Central Manager 嘗試在先前發現的 Peripheral中去匹配你提供的標識符,而後返回一個包含 CBPeripheral 對象的數組,若是沒有匹配的對象,數組將會是空的。你應該去嘗試其他的兩種方式中的一種。若是數組不是空的,在界面中讓用戶去選擇要重連哪個。

當用戶選擇 Peripheral 後,調用 CBCentralManager 類的 connectPeripheral:options: 方法去鏈接 Peripheral。若是 Peripheral 設備被鏈接後, Central Manager 會調用 centralManager:didConnectPeripheral: 代理方法,此時 Peripheral 重連成功。

提示:Peripheral 可能由於一些緣由不能鏈接,舉個例子,設備不在 Central 附近,此外,一些 BLE 設備使用週期變化的隨機設備地址。所以,即便設備在附近,從上次系統發現 Peripheral,設備的地址也可能發生改變,在這種狀況下,你嘗試鏈接的 CBPeripheral 對象與實際的 Peripheral 不相符。若是你不能從新鏈接 Peripheral,由於它的設備地址已經變了,你必須從新調用 scanForPeripheralsWithServices:options: 方法來搜索鏈接。

關於設備隨機地址的詳細信息,請查閱 Bluetooth 4.0 規範,第3卷,C部分,10.8 章節和 Bluetooth Accessory Design Guidelines for Apple Products.

恢復當前已鏈接的 Peripheral 列表

另外一種重連 Peripheral 的方式就是檢查你要鏈接的 Peripheral 是否一直被系統鏈接(舉例,被另外一個 APP 鏈接),你能夠調用 CBCentralManager 類的 retrieveConnectedPeripheralsWithServices: 方法,它返回一個 CBPeripheral 對象的數組,數組中包含當前系統已經鏈接的 Peripheral。

由於系統當前可能鏈接超過一個以上的 Peripheral,你能夠傳入一個 CBUUID 對象的數組來恢復你指定 Service的 Peripheral,若是當前鏈接的 Peripheral 中沒有你指定的 Peripheral,數組將是空的,你應該嘗試其他兩種方式中的一種。若是數組不爲空,在界面中讓用戶去選擇要重連哪個。

假設用戶選擇了渴望的 Peripheral,經過調用 CBCentralManager 類的 connectPeripheral:options: 方法來本地化鏈接。即便系統一直鏈接着設備,你必須本地化鏈接後再進行交互。當創建了本地鏈接後,Central Manager 會調用 centralManager:didConnectPeripheral: 代理方法,此時設備重連成功。

參考文獻

一、Best Practices for Interacting with a Remote Peripheral Device

結束語

歡迎在本文下面留言一塊兒交流心得...

相關文章
相關標籤/搜索