iOS 藍牙初窺

iOS藍牙連接

因為項目需要,這幾天接觸了一下藍牙相關API,自己寫了一個Demo 傳送門來調試,當然AppStore的LightBlue也是不錯的。
好了,閑話不多說,來談談我這幾天遇到的問題和最后是怎么解決的。


首先說一下CoreBlueTooth藍牙框架的一些常用的API。

相關類和協議

  • CBCentralManager
  • CBPeripheral
  • CBCharacteristic
  • CBCentralManagerDelegate
  • CBPeripheralDelegate

API介紹

  • 中心設備狀態改變

這個是CBCentralManager必須實現的方法

- (void)centralManagerDidUpdateState:(CBCentralManager *)central;

以下API只有在設備藍牙開啟時才可以,所以你可以像這樣...

-(void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    if(central.state != CBCentralManagerStatePoweredOn)
    {
        // ****
    }
}
  • 掃描設備
- (void)scanForPeripheralsWithServices:(nullable NSArray<CBUUID *> *)serviceUUIDs options:(nullable NSDictionary<NSString *, id> *)options;

第一個參數傳nil表示返回所有發現的設備。

第二個參數是一個字典,可以傳nil

對應的回調方法是

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI;

RSSI表示設備連接的信號強度

注意:

這里發現的外圍設備,如果后面需要使用它,必須要對它進行保留,官方是這樣說的:

A discovered peripheral must

  •                          be retained in order to use it; otherwise, it is assumed to not be of interest and will be cleaned up by the central manager
    

取消掃描

- (void)stopScan;
  • 連接設備
- (void)connectPeripheral:(CBPeripheral *)peripheral options:(nullable NSDictionary<NSString *, id> *)options;

對應的回調方法:

連接成功:

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;

連接失敗:

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error;

取消連接

- (void)cancelPeripheralConnection:(CBPeripheral *)peripheral;
- (void)connectPeripheral:(CBPeripheral *)peripheral options:(nullable NSDictionary<NSString *, id> *)options;
  • 發現設備服務、特征、描述
查找服務
- (void)discoverServices:(nullable NSArray<CBUUID *> *)serviceUUIDs;

同樣的,serviceUUIDsnil表示所有服務

查找某一服務下的特征
- (void)discoverCharacteristics:(nullable NSArray<CBUUID *> *)characteristicUUIDs forService:(CBService *)service;
查找某一特征下的描述
- (void)discoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic;

對應的回調函數:

發現服務
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error;
發現特征
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error;
發現描述
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error;
  • 特征值變化通知
- (void)setNotifyValue:(BOOL)enabled forCharacteristic:(CBCharacteristic *)characteristic;

回調

- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error

如果開啟通知,當連接設備的當前特征的值發生變化時,就會調用函數:

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error

調用下面的方法也是可以的,但是如果該特性不可讀,也就是characteristic.properties & CBCharacteristicPropertyRead,那么在回調函數里面會產生一個錯誤

- (void)readValueForCharacteristic:(CBCharacteristic *)characteristic;
  • 讀值和寫值

讀值:

讀取特征的值
- (void)readValueForCharacteristic:(CBCharacteristic *)characteristic;
回調
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error;
讀取特征描述的值
- (void)readValueForDescriptor:(CBDescriptor *)descriptor;
回調
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(nullable NSError *)error

寫值:

寫特征的值
- (void)writeValue:(NSData *)data forCharacteristic:(CBCharacteristic *)characteristic type:(CBCharacteristicWriteType)type
回調
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error
寫特征描述的值
- (void)writeValue:(NSData *)data forDescriptor:(CBDescriptor *)descriptor
回調
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForDescriptor:(CBDescriptor *)descriptor error:(nullable NSError *)error

寫值之前確保特征是可寫的,如果寫值的類型是CBCharacteristicWriteWithResponse的話,才會調用回調函數。

  • 設備信號強度

外圍設備有一個RSSI屬性,但是現在被棄用了,改用回調函數代替了。

- (void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(nullable NSError *)error NS_AVAILABLE(NA, 8_0);

好了API大致的介紹了一下,還有一些沒有介紹到的,大家可以自己去了解一下。

遇到的問題

  1. 讀取特征的值的時候,在沒有可讀類型的特征的時候,會報錯。
  2. 在還未連接到外圍設備的情況下,更新設備信號強度。

解決方法:

  • 1.原來是自己開啟了廣播,同時又調用了讀值的方法,雖然這兩種方式都會調用回調函數,但是特征并不可讀。0..0

This method is invoked after a @link readValueForCharacteristic: @/link call, or upon receipt of a notification/indication.

忽略了一個or

  • 2.本意是想模仿LightBlue App信號強度的更新,在Log中看到設備的信號強度在沒有連接的情況下就在更新了。但是readRSSI方法明確表明是要在已連接狀態下才能讀取,回調方法也才會響應。在委托方法:
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI;

中能拿到RSSI,但是卻沒有實時更新。經過幾番摸索,在掃描外設的方法中看到了希望

- (void)scanForPeripheralsWithServices:(nullable NSArray<CBUUID *> *)serviceUUIDs options:(nullable NSDictionary<NSString *, id> *)options;

第二個參數options之前傳的是nil,在CBCentralManagerScanOptionAllowDuplicatesKey這個Key中看到了這樣一段話

This can be useful in specific situations, such as making a connection based on a peripheral's RSSI, but may have an adverse affect on battery-life and application performance

問題得到解決,修改后的掃描方法

[_centralManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @(YES)}];

這樣就可以在回調方法中拿到實時的信號強度了。

好了,就說這么多了,后續再有遇到問題,會繼續更新的...

Demo地址

代碼寫的不好,還望見諒 0.0

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

推薦閱讀更多精彩內容