99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网

歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋果6袋
6
麥子學(xué)院

iOS藍(lán)牙開發(fā)CoreBluetooth快速入門

發(fā)布時(shí)間:2016-11-29 16:28  回復(fù):0  查看:4008   最后回復(fù):2016-11-29 16:28  

iOS開發(fā)中,實(shí)現(xiàn)藍(lán)牙通信有兩種方式,一種是使用傳統(tǒng)的GameKit.framework,另一種就是使用在iOS 5中加入的CoreBluetooth.framework。

  利用CoreBluetooth框架,我們可以輕松實(shí)現(xiàn)兩個(gè)iOS設(shè)備、iOS設(shè)備與非iOS藍(lán)牙設(shè)備的交互。要注意的一點(diǎn)是目前這個(gè)框架只能支持藍(lán)牙4.0BLE標(biāo)準(zhǔn),所以對(duì)硬件上是有一定要求的,iPhone 4S及以后的設(shè)備,第三代iPad及以后的設(shè)備是支持這一標(biāo)準(zhǔn)的。

  術(shù)語(yǔ)解釋

  我們首先看一下CoreBluetooth框架的結(jié)構(gòu)。這是CoreBluetooth/CoreBluetooth.h文件中的聲明。

  #ifndef _CORE_BLUETOOTH_H_#define _CORE_BLUETOOTH_H_#endif#import #import #import #import #import #import #import #import #import #import #import

  其中,CBCentral開頭的都是中心設(shè)備類,CBPeripheral開頭的都是外設(shè)類。這就要講到藍(lán)牙設(shè)備的兩個(gè)角色了。

  ·中心設(shè)備:中心設(shè)備可以理解為是處理數(shù)據(jù)的iOS設(shè)備,比如你的 iPhone、iPad 等。

  ·外設(shè):外設(shè)顧名思義,就是產(chǎn)生數(shù)據(jù)的外部設(shè)備。這個(gè)外部設(shè)備可以是單片機(jī)、嵌入式設(shè)備甚至是另一個(gè)iOS設(shè)備等等。外設(shè)可以通過(guò)其傳感器等產(chǎn)生有用數(shù)據(jù),數(shù)據(jù)后通過(guò)藍(lán)牙傳給中心設(shè)備使用。

  在建立連接的之前,外設(shè)向外發(fā)出廣播數(shù)據(jù)(advertisementData,官方描述“A dictionary containing any advertisement and scan response data.”),廣播數(shù)據(jù)是一個(gè)字典類數(shù)據(jù),中心設(shè)備可以獲取一定范圍內(nèi)的外設(shè)發(fā)出的廣播數(shù)據(jù)。

  現(xiàn)在開始

  初始化

  為了使用CoreBluetooth框架中的回調(diào)方法,我們要使用CBCentralManagerDelegateCBPeripheralDelegate這兩個(gè)協(xié)議。

  我們先要初始化一個(gè)CBCentralManager類的對(duì)象。代碼如下:

  @interface SKBluetoothManager : NSObject{

  CBCentralManager *manager;

  id delegate;

  }

  manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];

  manager.delegate = self;

  掃描外設(shè)

  初始化完成,我們就可以讓管理器開始掃描外設(shè)了:

  [manager scanForPeripheralsWithServices:nil options:nil];

  在設(shè)備發(fā)現(xiàn)周圍外設(shè)的advertisementData后,會(huì)回調(diào)這個(gè)方法:

  - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI;

  其中參數(shù)central指回調(diào)這個(gè)方法的中心設(shè)備,peripheral指發(fā)現(xiàn)的外設(shè)對(duì)象CBPeripheraladvertisementData就是前面說(shuō)的字典類型廣播數(shù)據(jù),RSSI是當(dāng)前外設(shè)的信號(hào)強(qiáng)度,單位是dbm。

  剛開始對(duì)陌生的藍(lán)牙設(shè)備調(diào)試時(shí),建議我們先用一個(gè)數(shù)組NSArray將所掃描到的外設(shè)進(jìn)行保存:

  [_peripherals addObject:peripheral];

  連接外設(shè)

  保存后,可根據(jù)設(shè)備的UUID來(lái)確定該設(shè)備是否為我們需要進(jìn)行操作的藍(lán)牙設(shè)備,在確認(rèn)外設(shè)身份后,即可發(fā)起對(duì)外設(shè)的連接操作:

  if ([peripheral.identifier.UUIDString isEqualToString:kPeripheralUUID]) {

  [manager stopScan];

  [manager connectPeripheral:peripheral options:nil];

  NSLog(@"連接外設(shè):%@",peripheral.description);

  self.peripheral = peripheral;

  }

  在此步操作后,我們完成了對(duì)藍(lán)牙設(shè)備的掃描工作,接下來(lái)的回調(diào)方法分為兩種情況:

  連接到外設(shè)后

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

  NSLog(@"已經(jīng)連接到:%@", peripheral.description);

  peripheral.delegate = self;

  [central stopScan];

  [peripheral discoverServices:nil];

  }

  一旦連接好外設(shè),我們就可以馬上停止掃描。然后發(fā)起對(duì)服務(wù)的搜索:

  - (void)discoverServices:(NSArray *)serviceUUIDs;

  此處參數(shù)位需要掃描的服務(wù)的UUID的數(shù)組。文檔中特別提到,若該參數(shù)為nil,將會(huì)掃描所有的服務(wù)。

  連接失敗后

  在連接外設(shè)失敗的回調(diào)方法中,提供了error參數(shù),可根據(jù)實(shí)際需要來(lái)做異常處理,在此不做過(guò)多說(shuō)明

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

  NSLog(@"連接%@失敗",peripheral);

  }

  在搜索到藍(lán)牙設(shè)備的服務(wù)后,將會(huì)回調(diào)

  - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error

  若有錯(cuò)誤發(fā)生,通過(guò)NSError異常處理。

  掃描服務(wù)

  由于服務(wù)在peripheral里是以NSArray的形式存在的,所以我們要對(duì)peripheral中的所有服務(wù)進(jìn)行遍歷:

  for (CBService *service in peripheral.services) {

  //發(fā)現(xiàn)服務(wù)

  if ([service.UUID isEqual:[CBUUID UUIDWithString:kServiceUUID]]) {

  NSLog(@"發(fā)現(xiàn)服務(wù):%@", service.UUID);

  [peripheral discoverCharacteristics:nil forService:service];

  break;

  }

  }

  掃描特征值

  在遍歷中,趁熱打鐵,直接對(duì)其特征值進(jìn)行掃描,

  [peripheral discoverCharacteristics:nil forService:service];

  這里與掃描service是相同的,若掃描所有的特征值,直接傳入nil作為參數(shù)即可。

  這里的kServiceUUID是我們根據(jù)藍(lán)牙設(shè)備的具體情況,提前設(shè)置好的UUID常量。本文所有kXxxxxUUID均為預(yù)設(shè)的UUID常量。

  同樣的,characteristics也是一個(gè)數(shù)組,我們利用像遍歷services一樣的方式來(lái)遍歷所有的特征值。

  - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {

  if (error) {

  NSLog(@"搜索特征%@時(shí)發(fā)生錯(cuò)誤:%@", service.UUID, [error localizedDescription]);

  return;

  }

  NSLog(@"服務(wù):%@",service.UUID);

  for (CBCharacteristic *characteristic in service.characteristics) {// NSLog(@"特征:%@",characteristic);

  //發(fā)現(xiàn)特征

  if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristicWriteUUID]]) {

  _writeCharacteristic = characteristic;

  }

  if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristicNotifyUUID]]) {

  NSLog(@"監(jiān)聽特征:%@",characteristic);//監(jiān)聽特征

  [self.peripheral setNotifyValue:YES forCharacteristic:characteristic];

  _isConnected = YES;

  }

  }

  }

  特別要提到的是,我們不同的藍(lán)牙設(shè)備有不同的服務(wù)和特征值。我的藍(lán)牙模塊的說(shuō)明文檔中已經(jīng)說(shuō)清楚了,write特征、read特征、notify特征,所以在此根據(jù)自身需要,來(lái)對(duì)不同的特征值進(jìn)行操作。

  設(shè)置監(jiān)聽

  我在此要解釋一下,當(dāng)我們?cè)噲D去讀取藍(lán)牙外設(shè)發(fā)過(guò)來(lái)的數(shù)據(jù)時(shí),一定要找準(zhǔn)特征值,用這個(gè)方法進(jìn)行訂閱。每次特征值變化的時(shí)候,就會(huì)有回調(diào)方法執(zhí)行,從而達(dá)到讀取數(shù)據(jù)的目的。容易出錯(cuò)誤,一定分清楚到底哪個(gè)特征值該被訂閱。

  在訂閱了特征值后,我們嘗試用藍(lán)牙外設(shè)發(fā)送一些數(shù)據(jù)出來(lái),即可回調(diào)下一階段的方法:

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

  if (error) {

  NSLog(@"更新特征值%@時(shí)發(fā)生錯(cuò)誤:%@", characteristic.UUID, [error localizedDescription]);

  return;

  }// 收到數(shù)據(jù)

  [delegate didGetDataForString:[self hexadecimalString:characteristic.value]];// NSLog(@"%@",[self hexadecimalString:characteristic.value]);

  }

  數(shù)據(jù)的轉(zhuǎn)換

  我們接收到的數(shù)據(jù),正是characteristic.value,這是一個(gè)NSData類數(shù)據(jù),我們可以通過(guò)UTF8StringEncoding來(lái)轉(zhuǎn)化為NSString,為了代碼結(jié)構(gòu)清晰,我專門把NSDataNSString互轉(zhuǎn)寫成了兩個(gè)方法:

  //將傳入的NSData類型轉(zhuǎn)換成NSString并返回

  - (NSString*)hexadecimalString:(NSData *)data{

  NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

  return result;

  }//將傳入的NSString類型轉(zhuǎn)換成NSData并返回

  - (NSData*)dataWithHexstring:(NSString *)hexstring{

  NSData *aData;

  return aData = [hexstring dataUsingEncoding: NSASCIIStringEncoding];

  }

  在拿到字符串后,通過(guò)各種回調(diào)方法,處理UI變動(dòng)。

  結(jié)語(yǔ)

  整個(gè)藍(lán)牙開發(fā)實(shí)現(xiàn)方便,但回調(diào)方法非常多,新手容易暈頭轉(zhuǎn)向。按部就班把每個(gè)回調(diào)方法實(shí)現(xiàn),即可保證藍(lán)牙開發(fā)的順利進(jìn)行。

 

來(lái)源:CocoaChina

您還未登錄,請(qǐng)先登錄

熱門帖子

最新帖子

?