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

歡迎訪問我的博客 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

結束語

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,034評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,337評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,883評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,114評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,625評論 1 332
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,555評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,737評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,973評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,343評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,699評論 2 370

推薦閱讀更多精彩內容