iOS BLE 開發(fā)小記[5] - 與 Remote Peripheral 交互的最佳實(shí)踐

歡迎訪問我的博客 muhlenXi,該文章出自我的博客,歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明來源: http://muhlenxi.com/2017/05/05/iOS-Bluetooth-Low-Energy-Develop-Chapter5。

導(dǎo)語:

在這一節(jié),主要是與 Remote Peripheral 交互的最佳實(shí)踐,以及實(shí)際開發(fā)過程中應(yīng)該注意的事項(xiàng)。

CoreBluetooth 框架使 Central 端的工作變得容易透明、容易理解。也就是說,你的 APP 可以控制和負(fù)責(zé) Central 的大部分方面,比如搜索設(shè)備、建立連接、與 Remote Peripheral 進(jìn)行數(shù)據(jù)交互。本章將以負(fù)責(zé)的方式來提供一些規(guī)范和最佳實(shí)踐,尤其是當(dāng)你為 iOS 設(shè)備開發(fā) APP 的時(shí)候。

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

當(dāng)開發(fā)一個 APP 與 BLE 設(shè)備交互時(shí),需要銘記:BLE 通信會通過你的設(shè)備向空中發(fā)射 Radio 信號。其他形式的無線通信也可能需要使用設(shè)備的 Radio,比如,Wi-Fi,傳統(tǒng)藍(lán)牙以及使用 BLE 的其他 APP。因此要減少 Radio 的使用。

當(dāng)開發(fā) iOS 設(shè)備的 APP 時(shí),最少次數(shù)使用 Radio 很重要,因?yàn)?Radio 的使用會對 iOS 設(shè)備電池的續(xù)航時(shí)間有不利影響。以下的這些規(guī)范將會幫助你更好的使用 Radio。作為回報(bào),你的 APP 會良好運(yùn)行和你設(shè)備電池的續(xù)航時(shí)間將會延長。

只在需要的時(shí)候搜索周邊設(shè)備

當(dāng)你調(diào)用 CBCentralManager 類的 scanForPeripheralsWithServices:options: 方法來搜索正在廣播數(shù)據(jù)的 Remote Peripheral 時(shí),你設(shè)備的 Radio 會一直監(jiān)聽正在廣播的設(shè)備,直到你停止搜索為止。

除非你需要搜索更多的設(shè)備,否則當(dāng)你找到你想要連接的設(shè)備后就應(yīng)該停止搜索,前幾篇提到過,用 CBCentralManager 類的 stopScan 方法來停止搜索設(shè)備。

必要的時(shí)候再指定 CBCentralManagerScanOptionAllowDuplicatesKey 選項(xiàng)

Remote Peripheral 設(shè)備可能會每秒發(fā)送多個廣播數(shù)據(jù)包給監(jiān)聽的 Central,當(dāng)你調(diào)用 scanForPeripheralsWithServices:options: 方法搜索設(shè)備時(shí),該方法默認(rèn)的行為是將一個 Peripheral 的多個發(fā)現(xiàn)事件合并成一個發(fā)現(xiàn)事件,也就是說,Central Manager 每找到一個新的 Peripheral 時(shí)才會調(diào)用 centralManager:didDiscoverPeripheral:advertisementData:RSSI: 代理方法,不管收到多少廣播數(shù)據(jù)包都不會調(diào)用該方法。當(dāng)已發(fā)現(xiàn)的 Peripheral 的廣播數(shù)據(jù)發(fā)生變化時(shí)也會調(diào)用這一代理方法。

如果你想改變默認(rèn)行為,調(diào)用 scanForPeripheralsWithServices:options: 方法時(shí)你可以指定 scan option 為 CBCentralManagerScanOptionAllowDuplicatesKey,這樣每當(dāng) Central 收到來自 Peripheral 的數(shù)據(jù)包就會創(chuàng)建一個發(fā)現(xiàn)事件。對于某些情況關(guān)閉默認(rèn)行為會很有用,比如基于 Peripheral 的 Proximity (靠近程度)來進(jìn)行連接交互。Proximity 可以通過 Peripheral 的 接收信號強(qiáng)度指示(RSSI)的值來判斷,也就是說,指定這個掃描選項(xiàng)會對電源的續(xù)航和 APP 的運(yùn)行造成不利影響。因此,只在必要的情況下再指定該方法的 scan option。

明智地獲取 Peripheral 的數(shù)據(jù)

當(dāng)你開發(fā) APP 的時(shí)候,對于特定的使用情景,一個 Peripheral 設(shè)備可能擁的大量的 Service 和 Characteristic 已經(jīng)超過了你需要的數(shù)量 ,搜索 Peripheral 全部的 Service 和 Characteristic 對電源的續(xù)航和 APP 的性能帶來不利影響。因此。你應(yīng)該只搜索你的 APP 需要的 Service 和 Characteristic。

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

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

當(dāng)你搜索到這兩個需要的 Service 后,你可以用相似的方式來搜索你需要的 Characteristic,同樣地,在調(diào)用 CBPeripheral 類的 discoverCharacteristics:forService: 方法時(shí)傳入你想要的 Characteristic UUID(用 CBUUID 對象表示) 數(shù)組就可以了。

訂閱值頻繁變化的 Characteristic

通過前面的文章,我們了解到,獲取一個 Characteristic 值的方式有兩種:

  • 你可以在每次需要值的時(shí)候明確的調(diào)用 readValueForCharacteristic: 方法來讀取 Characteristic 的值。
  • 你可以調(diào)用 setNotifyValue:forCharacteristic: 方法來訂閱 Characteristic 的值,這樣當(dāng)值發(fā)生改變后就會收到來自 Peripheral 的通知。

對于值可能變化的 Characteristic 來說,訂閱是最佳實(shí)踐方式,尤其是對于值頻繁改變的 Characteristic,關(guān)于如何訂閱一個 Characteristic 的值,可以查閱 Subscribing to a Characteristic’s Value.

當(dāng)你得到你需要的數(shù)據(jù)后斷開與設(shè)備的連接

當(dāng)不再需要連接的時(shí)候與設(shè)備斷開連接可以幫助你減少 Radio 的使用,你應(yīng)該在以下的情景中斷開與 Peripheral 設(shè)備的連接:

  • 你所有訂閱的 Characteristic 的值已經(jīng)不再通知,你可以通過 Characteristic 的 isNotifying 屬性來判斷 Characteristic 的值是否通知。
  • 你從 Peripheral 設(shè)備中得到了所有的數(shù)據(jù)。

在上述的場景中,取消一些訂閱并與 Peripheral 斷開連接,你可以通過調(diào)用 setNotifyValue:forCharacteristic: 方法來取消訂閱一個 Characteristic 的值,設(shè)置第一個參數(shù)為 NO 。你可以通過調(diào)用 CBCentralManager 類的 cancelPeripheralConnection: 方法來斷開與 Peripheral 設(shè)備的連接。像這樣:

[myCentralManager cancelPeripheralConnection:peripheral];

提示:cancelPeripheralConnection:方法是 nonblocking(非阻塞)的,一些 CBPeripheral 類的命令仍然等待 Peripheral,當(dāng)你嘗試斷開連接可能沒有完成執(zhí)行.因?yàn)榭赡芷渌?APP 還在連接 Peripheral,取消一個本地連接不能保證設(shè)備物理連接立刻斷開。從 APP 的角度來看,認(rèn)為 Peripheral 是斷開的,Central Manager 會調(diào)用 centralManager:didDisconnectPeripheral:error: 代理方法進(jìn)行回調(diào)。

重新連接 Peripheral

使用 CoreBluetooth 框架,你有三種方式可以重新連接 Peripheral:

  • 通過調(diào)用 retrievePeripheralsWithIdentifiers: 方法來恢復(fù)一個已知的 Peripheral 列表 --- Peripheral 是你發(fā)現(xiàn)的或者過去連接的。如果你要找的 Peripheral 在列表中,嘗試去連接它。這種重連方式在 恢復(fù)已知的 Peripheral 列表 小節(jié)中有描述。

  • 通過調(diào)用 retrieveConnectedPeripheralsWithServices: 方法來恢復(fù)系統(tǒng)當(dāng)前已經(jīng)連接的 Peripheral 列表,如果你要找的在列表中,則與它創(chuàng)建一個本地連接,這種重連方式在 恢復(fù)當(dāng)前已連接的 Peripheral 列表 小節(jié)中有描述。

  • 通過調(diào)用 scanForPeripheralsWithServices:options: 方法掃描和搜索 Peripheral,如果找到它,則連接。這種方式在 iOS BLE 開發(fā)小記[2]中有描述。

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

重連工作流程

提示:你決定嘗試的重連方式的個數(shù)取決于 APP 的使用情況,舉個例子,你可能決定不使用第一種方式,或者你可能并行使用第一種和第二種方式。

恢復(fù)已知的 Peripheral 列表

當(dāng)你第一次發(fā)現(xiàn)一個 Peripheral 時(shí)候,系統(tǒng)會創(chuàng)建一個標(biāo)識符(用 NSUUID 對象表示的一個 UUID)來標(biāo)識這個 Peripheral,你可以使用 NSUserDefaults 來保存這個標(biāo)識符。過后你可以嘗試調(diào)用CBCentralManager 類的 retrievePeripheralsWithIdentifiers: 方法來恢復(fù)并重新連接這個 Peripheral,下面描述的一種方式就是使用這個方法來重新連接以前的 Peripheral。

當(dāng) APP 啟動時(shí),調(diào)用 retrievePeripheralsWithIdentifiers: 方法,傳入一個包含 Peripheral 標(biāo)識符的數(shù)組來發(fā)現(xiàn)和重連先前的 Peripheral,像這樣:

knownPeripherals =
        [myCentralManager retrievePeripheralsWithIdentifiers:savedIdentifiers];

Central Manager 嘗試在先前發(fā)現(xiàn)的 Peripheral中去匹配你提供的標(biāo)識符,然后返回一個包含 CBPeripheral 對象的數(shù)組,如果沒有匹配的對象,數(shù)組將會是空的。你應(yīng)該去嘗試其余的兩種方式中的一種。如果數(shù)組不是空的,在界面中讓用戶去選擇要重連哪一個。

當(dāng)用戶選擇 Peripheral 后,調(diào)用 CBCentralManager 類的 connectPeripheral:options: 方法去連接 Peripheral。如果 Peripheral 設(shè)備被連接后, Central Manager 會調(diào)用 centralManager:didConnectPeripheral: 代理方法,此時(shí) Peripheral 重連成功。

提示:Peripheral 可能因?yàn)橐恍┰虿荒苓B接,舉個例子,設(shè)備不在 Central 附近,此外,一些 BLE 設(shè)備使用周期變化的隨機(jī)設(shè)備地址。因此,即使設(shè)備在附近,從上次系統(tǒng)發(fā)現(xiàn) Peripheral,設(shè)備的地址也可能發(fā)生改變,在這種情況下,你嘗試連接的 CBPeripheral 對象與實(shí)際的 Peripheral 不相符。如果你不能重新連接 Peripheral,因?yàn)樗脑O(shè)備地址已經(jīng)變了,你必須重新調(diào)用 scanForPeripheralsWithServices:options: 方法來搜索連接。

關(guān)于設(shè)備隨機(jī)地址的詳細(xì)信息,請查閱 Bluetooth 4.0 規(guī)范,第3卷,C部分,10.8 章節(jié)和 Bluetooth Accessory Design Guidelines for Apple Products.

恢復(fù)當(dāng)前已連接的 Peripheral 列表

另一種重連 Peripheral 的方式就是檢查你要連接的 Peripheral 是否一直被系統(tǒng)連接(舉例,被另一個 APP 連接),你可以調(diào)用 CBCentralManager 類的 retrieveConnectedPeripheralsWithServices: 方法,它返回一個 CBPeripheral 對象的數(shù)組,數(shù)組中包含當(dāng)前系統(tǒng)已經(jīng)連接的 Peripheral。

因?yàn)橄到y(tǒng)當(dāng)前可能連接超過一個以上的 Peripheral,你可以傳入一個 CBUUID 對象的數(shù)組來恢復(fù)你指定 Service的 Peripheral,如果當(dāng)前連接的 Peripheral 中沒有你指定的 Peripheral,數(shù)組將是空的,你應(yīng)該嘗試其余兩種方式中的一種。如果數(shù)組不為空,在界面中讓用戶去選擇要重連哪一個。

假設(shè)用戶選擇了渴望的 Peripheral,通過調(diào)用 CBCentralManager 類的 connectPeripheral:options: 方法來本地化連接。即使系統(tǒng)一直連接著設(shè)備,你必須本地化連接后再進(jìn)行交互。當(dāng)建立了本地連接后,Central Manager 會調(diào)用 centralManager:didConnectPeripheral: 代理方法,此時(shí)設(shè)備重連成功。

參考文獻(xiàn)

1、Best Practices for Interacting with a Remote Peripheral Device

結(jié)束語

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容