你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> iOS藍牙開發CoreBluetooth快速入門

iOS藍牙開發CoreBluetooth快速入門

編輯:IOS開發基礎

在iOS開發中,實現藍牙通信有兩種方式,一種是使用傳統的GameKit.framework,另一種就是使用在iOS 5中加入的CoreBluetooth.framework。

利用CoreBluetooth框架,我們可以輕松實現兩個iOS設備、iOS設備與非iOS藍牙設備的交互。要注意的一點是目前這個框架只能支持藍牙4.0BLE標准,所以對硬件上是有一定要求的,iPhone 4S及以後的設備,第三代iPad及以後的設備是支持這一標准的。

術語解釋

我們首先看一下CoreBluetooth框架的結構。這是CoreBluetooth/CoreBluetooth.h文件中的聲明。

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

其中,CBCentral開頭的都是中心設備類,CBPeripheral開頭的都是外設類。這就要講到藍牙設備的兩個角色了。

  • 中心設備:中心設備可以理解為是處理數據的iOS設備,比如你的 iPhone、iPad 等。

  • 外設:外設顧名思義,就是產生數據的外部設備。這個外部設備可以是單片機、嵌入式設備甚至是另一個iOS設備等等。外設可以通過其傳感器等產生有用數據,數據後通過藍牙傳給中心設備使用。

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

現在開始

初始化

為了使用CoreBluetooth框架中的回調方法,我們要使用CBCentralManagerDelegate、CBPeripheralDelegate這兩個協議。

我們先要初始化一個CBCentralManager類的對象。代碼如下:

@interface SKBluetoothManager : NSObject{
    CBCentralManager *manager;
    id delegate;
}

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

掃描外設

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

[manager scanForPeripheralsWithServices:nil options:nil];

在設備發現周圍外設的advertisementData後,會回調這個方法:

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

其中參數central指回調這個方法的中心設備,peripheral指發現的外設對象CBPeripheral,advertisementData就是前面說的字典類型廣播數據,RSSI是當前外設的信號強度,單位是dbm。

剛開始對陌生的藍牙設備調試時,建議我們先用一個數組NSArray將所掃描到的外設進行保存:

[_peripherals addObject:peripheral];

連接外設

保存後,可根據設備的UUID來確定該設備是否為我們需要進行操作的藍牙設備,在確認外設身份後,即可發起對外設的連接操作:

if ([peripheral.identifier.UUIDString isEqualToString:kPeripheralUUID]) {
    [manager stopScan];
    [manager connectPeripheral:peripheral options:nil];
    NSLog(@"連接外設:%@",peripheral.description);
    self.peripheral = peripheral;
}

在此步操作後,我們完成了對藍牙設備的掃描工作,接下來的回調方法分為兩種情況:

連接到外設後

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    NSLog(@"已經連接到:%@", peripheral.description);
    peripheral.delegate = self;
    [central stopScan];
    [peripheral discoverServices:nil];
}

一旦連接好外設,我們就可以馬上停止掃描。然後發起對服務的搜索:

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

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

連接失敗後

在連接外設失敗的回調方法中,提供了error參數,可根據實際需要來做異常處理,在此不做過多說明

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    NSLog(@"連接%@失敗",peripheral);
}

在搜索到藍牙設備的服務後,將會回調

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

若有錯誤發生,通過NSError異常處理。

掃描服務

由於服務在peripheral裡是以NSArray的形式存在的,所以我們要對peripheral中的所有服務進行遍歷:

for (CBService *service in peripheral.services) {
    //發現服務
    if ([service.UUID isEqual:[CBUUID UUIDWithString:kServiceUUID]]) {
        NSLog(@"發現服務:%@", service.UUID);
        [peripheral discoverCharacteristics:nil forService:service];
        break;
    }
}

掃描特征值

在遍歷中,趁熱打鐵,直接對其特征值進行掃描,

[peripheral discoverCharacteristics:nil forService:service];

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

這裡的kServiceUUID是我們根據藍牙設備的具體情況,提前設置好的UUID常量。本文所有kXxxxxUUID均為預設的UUID常量。

同樣的,characteristics也是一個數組,我們利用像遍歷services一樣的方式來遍歷所有的特征值。

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
    if (error) {
        NSLog(@"搜索特征%@時發生錯誤:%@", service.UUID, [error localizedDescription]);
        return;
    }
    NSLog(@"服務:%@",service.UUID);
    for (CBCharacteristic *characteristic in service.characteristics) {
//        NSLog(@"特征:%@",characteristic);
        //發現特征
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristicWriteUUID]]) {
            _writeCharacteristic = characteristic;
        }
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristicNotifyUUID]]) {
            NSLog(@"監聽特征:%@",characteristic);//監聽特征
            [self.peripheral setNotifyValue:YES forCharacteristic:characteristic];
            _isConnected = YES;
        }
    }
}

特別要提到的是,我們不同的藍牙設備有不同的服務和特征值。我的藍牙模塊的說明文檔中已經說清楚了,write特征、read特征、notify特征,所以在此根據自身需要,來對不同的特征值進行操作。

設置監聽

我在此要解釋一下,當我們試圖去讀取藍牙外設發過來的數據時,一定要找准特征值,用這個方法進行訂閱。每次特征值變化的時候,就會有回調方法執行,從而達到讀取數據的目的。容易出錯誤,一定分清楚到底哪個特征值該被訂閱。

在訂閱了特征值後,我們嘗試用藍牙外設發送一些數據出來,即可回調下一階段的方法:

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
        NSLog(@"更新特征值%@時發生錯誤:%@", characteristic.UUID, [error localizedDescription]);
        return;
    }
// 收到數據
    [delegate didGetDataForString:[self hexadecimalString:characteristic.value]];
//    NSLog(@"%@",[self hexadecimalString:characteristic.value]);
}

數據的轉換

我們接收到的數據,正是characteristic.value,這是一個NSData類數據,我們可以通過UTF8StringEncoding來轉化為NSString,為了代碼結構清晰,我專門把NSData和NSString互轉寫成了兩個方法:

//將傳入的NSData類型轉換成NSString並返回
- (NSString*)hexadecimalString:(NSData *)data{
    NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    return result;
}
//將傳入的NSString類型轉換成NSData並返回
- (NSData*)dataWithHexstring:(NSString *)hexstring{
    NSData *aData;
    return aData = [hexstring dataUsingEncoding: NSASCIIStringEncoding];
}

在拿到字符串後,通過各種回調方法,處理UI變動。

結語

整個藍牙開發實現方便,但回調方法非常多,新手容易暈頭轉向。按部就班把每個回調方法實現,即可保證藍牙開發的順利進行。

最後貼上我封裝的 SKBluetooth 的地址:SKBluetooth


  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved