歡迎訪問我的博客 muhlenXi,該文章出自我的博客,歡迎轉載,轉載請注明來源: http://muhlenxi.com/2017/05/05/iOS-Bluetooth-Low-Energy-Develop-Chapter5。
導語:
在這一節,主要是與 Remote Peripheral 交互的最佳實踐,以及實際開發過程中應該注意的事項。
CoreBluetooth 框架使 Central 端的工作變得容易透明、容易理解。也就是說,你的 APP 可以控制和負責 Central 的大部分方面,比如搜索設備、建立連接、與 Remote Peripheral 進行數據交互。本章將以負責的方式來提供一些規范和最佳實踐,尤其是當你為 iOS 設備開發 APP 的時候。
要留意 Radio 的使用和電量的消耗
當開發一個 APP 與 BLE 設備交互時,需要銘記:BLE 通信會通過你的設備向空中發射 Radio 信號。其他形式的無線通信也可能需要使用設備的 Radio,比如,Wi-Fi,傳統藍牙以及使用 BLE 的其他 APP。因此要減少 Radio 的使用。
當開發 iOS 設備的 APP 時,最少次數使用 Radio 很重要,因為 Radio 的使用會對 iOS 設備電池的續航時間有不利影響。以下的這些規范將會幫助你更好的使用 Radio。作為回報,你的 APP 會良好運行和你設備電池的續航時間將會延長。
只在需要的時候搜索周邊設備
當你調用 CBCentralManager
類的 scanForPeripheralsWithServices:options:
方法來搜索正在廣播數據的 Remote Peripheral 時,你設備的 Radio 會一直監聽正在廣播的設備,直到你停止搜索為止。
除非你需要搜索更多的設備,否則當你找到你想要連接的設備后就應該停止搜索,前幾篇提到過,用 CBCentralManager
類的 stopScan
方法來停止搜索設備。
必要的時候再指定 CBCentralManagerScanOptionAllowDuplicatesKey 選項
Remote Peripheral 設備可能會每秒發送多個廣播數據包給監聽的 Central,當你調用 scanForPeripheralsWithServices:options:
方法搜索設備時,該方法默認的行為是將一個 Peripheral 的多個發現事件合并成一個發現事件,也就是說,Central Manager 每找到一個新的 Peripheral 時才會調用 centralManager:didDiscoverPeripheral:advertisementData:RSSI:
代理方法,不管收到多少廣播數據包都不會調用該方法。當已發現的 Peripheral 的廣播數據發生變化時也會調用這一代理方法。
如果你想改變默認行為,調用 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。
舉個例子,假如你連接的 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:
代理方法,此時設備重連成功。
參考文獻
1、Best Practices for Interacting with a Remote Peripheral Device
結束語
歡迎在本文下面留言一起交流心得...