與遠(yuǎn)程外設(shè)交互的最佳實踐
Core Bluetooth框架使中央端的很多事務(wù)對你的應(yīng)用程序透明,也就是,你的應(yīng)用程序已經(jīng)控制了见擦,并負(fù)責(zé)實現(xiàn)大多數(shù)中央角色方面,設(shè)備掃描移袍,連接,探索和與遠(yuǎn)程外設(shè)數(shù)據(jù)交互老充。這個章節(jié)提供指導(dǎo)和最佳實踐為以負(fù)責(zé)任的方式治理控制水平葡盗,特別是當(dāng)給一個iOS設(shè)備開發(fā)你的應(yīng)用程序時。
注意無線的使用和功耗
當(dāng)開發(fā)一個與藍(lán)牙低功耗設(shè)備交互的應(yīng)用程序時蚂维,記住藍(lán)牙低功耗在通信過程中會享用你的設(shè)備無線來在空中傳遞信號戳粒。因為其它形式的無線通信可能需要用你的設(shè)備無線--例如,Wi-Fi虫啥,經(jīng)典藍(lán)牙蔚约,和其它應(yīng)用程序使用藍(lán)牙低功耗--開發(fā)你的應(yīng)用程序最小化使用無線。
當(dāng)給一個iOS設(shè)備開發(fā)一個應(yīng)用程序時最小化無線的使用是特別重要的涂籽,因為無線的使用不利于電池的壽命苹祟。下面的指導(dǎo)方針將幫你成為一個你設(shè)備的無線的好公民。因此评雌,你的應(yīng)用程序?qū)?zhí)行得更好树枫,你的設(shè)備的電池將持續(xù)更長的時間。
只有當(dāng)你需要的時候才去掃描設(shè)備
當(dāng)你調(diào)用CBCentralManager
類的scanForPeripheralsWithServices:options:
方法來發(fā)現(xiàn)正在廣播服務(wù)的外設(shè)時景东,你的中央設(shè)備會使用無線來監(jiān)聽正在廣播的設(shè)備砂轻,直到你明確告訴它停止。
除非你需要發(fā)現(xiàn)更多的設(shè)備斤吐,在你已經(jīng)發(fā)現(xiàn)了你想要連接的設(shè)備的時候停止掃描其它設(shè)備搔涝。用CBCentralManager
類的stopScan
方法來停止掃描其它的設(shè)備厨喂,在Connecting to a Peripheral Device After You've Discovered It中可見。
只有在必要的時候才指定CBCentralManagerScanOptionAllowDuplicatesKey
選項
遠(yuǎn)程外設(shè)可能會每秒發(fā)送多個廣播包給在監(jiān)聽的中央來宣布它們的存在庄呈,當(dāng)你使用scanForPeripheralsWithService:options:
方法正在掃描設(shè)備時蜕煌,這個方法的默認(rèn)行為是合并多個發(fā)現(xiàn)的廣播外設(shè)成單個發(fā)現(xiàn)事件--也就是說,沒發(fā)現(xiàn)一個新的外設(shè)诬留,中央管理者會調(diào)用它的代理對象的centralManager:didDiscoverPeripheral:advertisementData:RSSI:
方法斜纪,不管它接受到了多少廣播包。當(dāng)一個已經(jīng)準(zhǔn)備發(fā)現(xiàn)的外設(shè)廣播數(shù)據(jù)改變時中央管理者也會調(diào)用這個代理方法文兑。
如果你想要改變這個默認(rèn)行為盒刚,你可以在調(diào)用scanForPeripheralsWithServices:options:
方法時指定CBCentralManagerScanOptionAllowDuplicatesKey
常量作為掃描選項。當(dāng)你這樣做彩届,每次中央接受到外設(shè)的廣播包時都會形成一個發(fā)現(xiàn)事件伪冰。關(guān)掉默認(rèn)的行為對某些情況是有用的誓酒,例如在外設(shè)上啟動與外設(shè)的連接(使用外設(shè)接受信號強(qiáng)度指示值(RSSI)).也就是說樟蠕,記住指定這個掃描選項不利于電池的壽命和應(yīng)用程序的性能。因此靠柑,只有在特殊使用情況下需要的時候才指定這個掃描選項寨辩。
明智地探索一個外設(shè)的數(shù)據(jù)
當(dāng)你在開發(fā)一個應(yīng)用程序來實現(xiàn)一種特定的使用情況時一個外設(shè)可能有比你可能感興趣的更多的服務(wù)和特征。發(fā)現(xiàn)所有的外設(shè)服務(wù)和相關(guān)的特征會給你的應(yīng)用程序性能和電池壽命帶來不好的影響歼冰。因此靡狞,你應(yīng)該查看和發(fā)現(xiàn)你的應(yīng)用程序需要的服務(wù)和特征。
例如隔嫡,想象你已經(jīng)連接了一個有很多有效服務(wù)的外設(shè)甸怕,但是你的應(yīng)用程序只需要訪問它們中的兩個。你可以只查看和發(fā)現(xiàn)這兩個服務(wù)腮恩,通過調(diào)用CBPeripheral
類的discoverServices:
方法傳遞的參數(shù)是它們的服務(wù)的UUIDs的數(shù)組(使用CBUUID
對象表示)梢杭,就像:
[peripheral discoverServices:@[firstServiceUUID, secondServiceUUID]];
在你發(fā)現(xiàn)了你感興趣的兩個服務(wù)之后,你可以類似地發(fā)現(xiàn)你只感興趣的服務(wù)的特征秸滴。再一次武契,通過調(diào)用CBPeripheral
類的discoverCharacteristics:forService:
方法傳遞參數(shù)是你想要發(fā)現(xiàn)的特征的UUIDs組成的數(shù)組(對于每個服務(wù))。
訂閱經(jīng)常改變的特征值
正如Retrieving Value of a Characteristic中描述荡含,有兩種方式獲得一個特征值:
- 你可以通過每次需要值的時候調(diào)用
readValueForCharacteristic:
方法來明確地獲取特征值 - 你可以通過調(diào)用
setNotifyValue:forCharacteristic:
方法來訂閱特征值咒唆,一旦值發(fā)生了變化會接受到一個從外設(shè)發(fā)來的通知。
當(dāng)指定的特征值經(jīng)常發(fā)生改變時訂閱這個特征值是一個好的實踐释液。有一個例子關(guān)于訂閱特征值全释,請看Subscribing to a Characteristic's Value 。
當(dāng)你已經(jīng)有了你想要的所有數(shù)據(jù)的時候斷開與設(shè)備的連接
當(dāng)你有一個不再需要的連接的時候通過斷開與外設(shè)的連接可以有助于減少你的應(yīng)用程序的無線使用误债。你應(yīng)該在下面的兩種情況下斷開與外設(shè)的連接:
- 你訂閱的所有特征值已經(jīng)停止發(fā)送了通知(你可以通過訪問特征的
isNotifying
屬性來決定特征值是否正在通知) - 你已經(jīng)從外設(shè)那里獲取到了你想要的所有數(shù)據(jù)
在這兩種情況下浸船,取消訂閱你可能有的并斷開與外設(shè)的連接符衔。你可以通過調(diào)用setNotifyValue:forCharacteristic:
方法來取消訂閱一個特征值,設(shè)置第一個參數(shù)為NO
糟袁。你可以通過調(diào)用CBCentralManager
類的cancelPeripheralConnection:
方法取消與一個外設(shè)的連接判族。就像:
[myCentralManager cancelPeripheralConnection:peripheral];
注意:
cancelPeripheralConnection:
方法是不閉塞的,你嘗試斷開連接的外設(shè)的還沒發(fā)出的命令可能沒執(zhí)行完项戴。因為其它的應(yīng)用程序可能仍然與該外設(shè)連接著形帮,取消一個本地的連接不能保證底層的物理鏈路立即斷開。從你的應(yīng)用程序角度來看周叮,外設(shè)是斷開的辩撑,和中央角色會調(diào)用它的代理對象的centralManager:didDisconnectPeripheral:error:
方法。
重新連接外設(shè)
使用Core Bluetooth框架仿耽,有三種方式可以用來重新連接外設(shè)合冀,你可以:
- 獲得外設(shè)的列表-在過去你發(fā)現(xiàn)或已經(jīng)連接的外設(shè)-使用
retrievePeripheralsWithIdentifiers:
方法。如果這個外設(shè)你能在該列表中查找到项贺,嘗試連接君躺。這個重連的選項在Retrieving a List of Known Peripherals中有描述。 - 使用
retrieveConnectedPeripheralsWithServices:
方法獲得當(dāng)前與系統(tǒng)連接的外設(shè)列表开缎。如果這個外設(shè)你能在該列表中查找到棕叫,連接它到你的本地應(yīng)用程序。這個重連的選項在Retrieving a List of Connected Peripherals中有描述奕删。 - 使用
scanForPeripheralsWithServices:options:
方法掃描和發(fā)現(xiàn)外設(shè)俺泣。如果你找到它了,連接它完残。這一步在Discover Peripheral Devices That Are Advertising和Connecting to a Peripheral Device After You're Discovered It中都有描述伏钠。
視使用情況而定,你想重連它但又不想每次都必須掃描和發(fā)現(xiàn)相同的外設(shè)谨设,你可能想要嘗試使用第一個選項來重連它來代替熟掂。如圖5-1所示,它們在上面列出的順序中有可能嘗試每一個選項的重連工作流程。
注意:你決定嘗試的重連選項的數(shù)目铝宵,和你這樣做的順序打掘,可能由你的應(yīng)用程序嘗試滿足的使用情況而有所不同。例如鹏秋,你可能決定根本就不使用第一個連接的選項尊蚁,或者你可能決定嘗試使用第一個和第二個選項。
獲取已知的外設(shè)列表
第一次你發(fā)現(xiàn)一個外設(shè)侣夷,系統(tǒng)會用一個標(biāo)識符(一個UUID,用NSUUID
對象表示)來標(biāo)識這個外設(shè)横朋。然后你可以存儲這個標(biāo)識符(使用NSUserDefaults
類的資源),然后用CBCentralManager
類的retrievePeripheralsWithIdentifiers:
方法嘗試重連這個外設(shè)。下面描述了一個方式來使用這個方法來重連一個你已經(jīng)之前連接過的外設(shè)百拓。
當(dāng)你的應(yīng)用程序啟動時琴锭,調(diào)用retrievePeripheralsWithIdentifiers:
方法晰甚,通過你之前發(fā)現(xiàn)和連接過的外設(shè)(你已經(jīng)保存了它的標(biāo)識符)的標(biāo)識符號來獲得一個數(shù)組,就像:
knownPeripherals = [myCentralManager retrievePeripheralsWithIdentifiers:savedIdentifiers];
中央管理者嘗試匹配你提供的之前發(fā)現(xiàn)外設(shè)的標(biāo)識符號然后返回一個包含CBPeripheral
對象的數(shù)組結(jié)果。如果發(fā)現(xiàn)的都沒有匹配上决帖,這個數(shù)組是空的厕九,你應(yīng)該嘗試使用另外兩種重連方式。如果這個數(shù)組不是空的地回,讓用戶在界面上選擇嘗試重新連接哪一個外設(shè)扁远。
當(dāng)用戶選擇了一個外設(shè),通過調(diào)用CBCentralManager
類的connectPeripheral:options:
方法嘗試連接它刻像。如果這個外設(shè)依然能有效地被連接上畅买,中央管理者會調(diào)用它的代理對象的centralManager:didConnectPeripheral:
方法,這個外設(shè)就被成功重新連接上了细睡。
注意:一個外設(shè)可能因為一些原因在被連接的時候無效谷羞。對于這種情況,外設(shè)可能不在中央附近溜徙。另外湃缎,一些藍(lán)牙低功耗設(shè)備使用一個隨機(jī)的設(shè)備地址周期性的改變。因此萌京,即使設(shè)備在附近雁歌,設(shè)備的地址可能已經(jīng)改變了自從它被系統(tǒng)發(fā)現(xiàn)的上一次宏浩。在這種情況下知残,你嘗試連接的
CBPeripheral
對象不符合真實的外設(shè)。如果你因為它的設(shè)備地址已經(jīng)改變了而不能重新連接上這個外設(shè)比庄,你必須使用scanForPeripheralsWithServices:options:
方法重新發(fā)現(xiàn)它求妹。關(guān)于隨機(jī)設(shè)備地址的更多信息,請看藍(lán)牙4.0規(guī)范佳窑,和Bluetooth Accessory Design Guidelines for Apple Produces制恍。
獲取已經(jīng)連接的外設(shè)列表
另外一種方式來重新連接外設(shè)是通過檢查看你發(fā)現(xiàn)已經(jīng)與系統(tǒng)(例如,被其它的應(yīng)用程序)連接的哪個外設(shè).你可以通過調(diào)用CBCentralManager
類的retrieveConnectedPeripheralsWithServices:
方法神凑,會返回一個裝有當(dāng)前與系統(tǒng)連接的外設(shè)用CBPeripheral
對象表示的數(shù)組净神。
因為可能當(dāng)前與系統(tǒng)連接的外設(shè)不止一個,你可以通過有CBUUID
對象(表示服務(wù)的UUIDs)的數(shù)組來獲取只與當(dāng)前系統(tǒng)連接的和包含一些被你指定的UUIDs的標(biāo)識的服務(wù)的外設(shè)溉委。如果沒有外設(shè)與當(dāng)前系統(tǒng)連接鹃唯,這個數(shù)組是空的,你應(yīng)該嘗試用其它的兩種重連方法瓣喊。如果這個數(shù)組不是空的坡慌,讓用戶在界面上嘗試連接哪個外設(shè)。
假定用戶發(fā)現(xiàn)和選擇了想要的外設(shè)藻三,通過調(diào)用CBCentralManager
類的connectPeripheral:options:
方法來讓它與你的應(yīng)用程序連接洪橘。(即使這個設(shè)備已經(jīng)與系統(tǒng)連接了跪者,你仍然必須連接它到你的應(yīng)用程序來開始探索和與它交互)。當(dāng)這個本地連接建立了熄求,中央管理者會調(diào)用它的代理對象的centralManager:didConnectPeripheral:
方法渣玲,這個外設(shè)就成功地被重新連接了。
-- 翻譯的文檔地址:Best Practices for Interacting With a Remote Peripheral Device