藍牙4.0開發

一、關于藍牙開發的一些重要的理論概念:

1.當前ios中開發藍牙所運使用的系統庫是。

2.藍牙外設必需為4.0及以上(2.0需要MFI認證),否則無法開發,藍牙4.0設施由于低耗電,所以也叫做BLE。

3.CoreBluetooth框架的核心其實是兩個東西,peripheral和central, 能了解成外設和中心,就是你的蘋果手機就是中心,外部藍牙稱為外設。

4.服務和特征(service characteristic):簡而言之,外部藍牙中它有若干個服務service(服務你能了解為藍牙所擁有的可以力),而每個服務service下擁有若干個特征characteristic(特征你能了解為解釋這個服務的屬性)。

5.Descriptor(形容)使用來形容characteristic變量的屬性。例如,一個descriptor能規定一個可讀的形容,或者者一個characteristic變量可接受的范圍,或者者一個characteristic變量特定的單位。

6.我們用的藍牙板塊是在淘寶買的, 大概十多元一個, ios大概每次能接受90個字節, 安卓大概每次能接收20個字節, 具體數字可可以會浮動, 應該是與藍牙板塊有關。

二、藍牙連接的主要步驟

1、創建一個CBCentralManager實例來進行藍牙管理;

2、搜索掃描外圍設備;

3、連接外圍設備;

4、獲得外圍設備的服務;

5、獲得服務的特征;

6、從外圍設備讀取數據;

7、給外圍設備發送(寫入)數據。

三、代碼

// 加入權限訪問, 否則上傳AppStore會因為權限不足失敗

WechatIMG4.jpeg

WechatIMG4.jpeg

初始化

#import

self.centralManager = [[CBCentralManager alloc] initWithDelegate:selfqueue:nil];

搜索掃描外圍設備

/**

?*? --? 初始化成功自動調用

?*? --? 必須實現的代理,用來返回創建的centralManager的狀態。

?*? --? 注意:必須確認當前是CBCentralManagerStatePoweredOn狀態才可以調用掃描外設的方法:

?scanForPeripheralsWithServices

?*/

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

? ? switch(central.state) {

? ? ? ? caseCBCentralManagerStateUnknown:

? ? ? ? ? ? NSLog(@">>>CBCentralManagerStateUnknown");

? ? ? ? ? ? break;

? ? ? ? caseCBCentralManagerStateResetting:

? ? ? ? ? ? NSLog(@">>>CBCentralManagerStateResetting");

? ? ? ? ? ? break;

? ? ? ? caseCBCentralManagerStateUnsupported:

? ? ? ? ? ? NSLog(@">>>CBCentralManagerStateUnsupported");

? ? ? ? ? ? break;

? ? ? ? caseCBCentralManagerStateUnauthorized:

? ? ? ? ? ? NSLog(@">>>CBCentralManagerStateUnauthorized");

? ? ? ? ? ? break;

? ? ? ? caseCBCentralManagerStatePoweredOff:

? ? ? ? ? ? NSLog(@">>>CBCentralManagerStatePoweredOff");

? ? ? ? ? ? break;

? ? ? ? caseCBCentralManagerStatePoweredOn:

? ? ? ? {

? ? ? ? ? ? NSLog(@">>>CBCentralManagerStatePoweredOn");

? ? ? ? ? ? // 開始掃描周圍的外設。

? ? ? ? ? ? /*

?? ? ? ? ? ? -- 兩個參數為Nil表示默認掃描所有可見藍牙設備。

?? ? ? ? ? ? -- 注意:第一個參數是用來掃描有指定服務的外設。然后有些外設的服務是相同的,比如都有FFF5服務,那么都會發現;而有些外設的服務是不可見的,就會掃描不到設備。

?? ? ? ? ? ? -- 成功掃描到外設后調用didDiscoverPeripheral

?? ? ? ? ? ? */

? ? ? ? ? ? [self.centralManager scanForPeripheralsWithServices:niloptions:nil];

? ? ? ? }

? ? ? ? ? ? break;

? ? ? ? default:

? ? ? ? ? ? break;

? ? }

}

#pragma mark 發現外設

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

? ? NSLog(@"Find device:%@", [peripheral name]);

? ? if(![_deviceDic objectForKey:[peripheral name]]) {

? ? ? ? NSLog(@"Find device:%@", [peripheral name]);

? ? ? ? if(peripheral!=nil) {

? ? ? ? ? ? if([peripheral name]!=nil) {

? ? ? ? ? ? ? ? if([[peripheral name] hasPrefix:@"根據設備名過濾"]) {

? ? ? ? ? ? ? ? ? ? [_deviceDic setObject:peripheral forKey:[peripheral name]];

? ? ? ? ? ? ? ? ? ? // 停止掃描, 看需求決定要不要加

? ? ? ? ? ? ? ? ? ? //? ? ? ? ? ? ? ? ? ? [_centralManager stopScan];

? ? ? ? ? ? ? ? ? ? // 將設備信息傳到外面的頁面(VC), 構成掃描到的設備列表

? ? ? ? ? ? ? ? ? ? if([self.delegate respondsToSelector:@selector(dataWithBluetoothDic:)]) {

? ? ? ? ? ? ? ? ? ? ? ? [self.delegate dataWithBluetoothDic:_deviceDic];

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

3.連接外圍設備

// 連接設備(.h中聲明出去的接口, 一般在點擊設備列表連接時調用)

- (void)connectDeviceWithPeripheral:(CBPeripheral *)peripheral

{

? ? [self.centralManager connectPeripheral:peripheral options:nil];

}

#pragma mark 連接外設--成功

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

? ? //連接成功后停止掃描,節省內存

? ? [central stopScan];

? ? peripheral.delegate =self;

? ? self.peripheral = peripheral;

? ? //4.掃描外設的服務

? ? /**

?? ? --? ? 外設的服務、特征、描述等方法是CBPeripheralDelegate的內容,所以要先設置代理peripheral.delegate = self

?? ? --? ? 參數表示你關心的服務的UUID,比如我關心的是"FFE0",參數就可以為@[[CBUUID UUIDWithString:@"FFE0"]].那么didDiscoverServices方法回調內容就只有這兩個UUID的服務,不會有其他多余的內容,提高效率。nil表示掃描所有服務

?? ? --? ? 成功發現服務,回調didDiscoverServices

?? ? */

? ? [peripheral discoverServices:@[[CBUUID UUIDWithString:@"你要用的服務UUID"]]];

? ? if([self.delegate respondsToSelector:@selector(didConnectBle)]) {

? ? ? ? // 已經連接

? ? ? ? [self.delegate didConnectBle];

? ? }

}

#pragma mark 連接外設——失敗

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

? ? NSLog(@"%@", error);

}

#pragma mark 取消與外設的連接回調

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

? ? NSLog(@"%@", peripheral);

}

獲得外圍設備的服務

#pragma mark 發現服務回調

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


? ? //NSLog(@"didDiscoverServices,Error:%@",error);

? ? CBService *__nullablefindService =nil;

? ? // 遍歷服務

? ? for(CBService *serviceinperipheral.services)

? ? {

? ? ? ? //NSLog(@"UUID:%@",service.UUID);

? ? ? ? if([[service UUID] isEqual:[CBUUID UUIDWithString:@"你要用的服務UUID"]])

? ? ? ? {

? ? ? ? ? ? findService = service;

? ? ? ? }

? ? }

? ? NSLog(@"Find Service:%@",findService);

? ? if(findService)

? ? ? ? [peripheral discoverCharacteristics:NULLforService:findService];

}

#pragma mark 發現特征回調

/**

?--? 發現特征后,可以根據特征的properties進行:讀readValueForCharacteristic、寫writeValue、訂閱通知setNotifyValue、掃描特征的描述discoverDescriptorsForCharacteristic。

?**/

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

? ? for(CBCharacteristic *characteristicinservice.characteristics) {

? ? ? ? if([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"你要用的特征UUID"]]) {


? ? ? ? ? ? /**

?? ? ? ? ? ? -- 讀取成功回調didUpdateValueForCharacteristic

?? ? ? ? ? ? */

? ? ? ? ? ? self.characteristic = characteristic;

? ? ? ? ? ? // 接收一次(是讀一次信息還是數據經常變實時接收視情況而定, 再決定使用哪個)

? ? ? ? ? ? //? ? ? ? ? ? [peripheral readValueForCharacteristic:characteristic];

? ? ? ? ? ? // 訂閱, 實時接收

? ? ? ? ? ? [peripheral setNotifyValue:YESforCharacteristic:characteristic];


? ? ? ? ? ? // 發送下行指令(發送一條)

? ? ? ? ? ? NSData *data = [@"硬件工程師給我的指令, 發送給藍牙該指令, 藍牙會給我返回一條數據"dataUsingEncoding:NSUTF8StringEncoding];

? ? ? ? ? ? // 將指令寫入藍牙

? ? ? ? ? ? [self.peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];

? ? ? ? }

? ? ? ? /**

?? ? ? ? -- 當發現characteristic有descriptor,回調didDiscoverDescriptorsForCharacteristic

?? ? ? ? */

? ? ? ? [peripheral discoverDescriptorsForCharacteristic:characteristic];

? ? }

}

6.從外圍設備讀取數據

#pragma mark - 獲取值

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

? ? // characteristic.value就是藍牙給我們的值(我這里是json格式字符串)

? ? NSData *jsonData = [characteristic.value dataUsingEncoding:NSUTF8StringEncoding];

? ? NSDictionary *dataDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];

? ? // 將字典傳出去就可以使用了

}

#pragma mark - 中心讀取外設實時數據

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

? ? if(characteristic.isNotifying) {

? ? ? ? [peripheral readValueForCharacteristic:characteristic];

? ? }else{

? ? ? ? NSLog(@"Notification stopped on %@.? Disconnecting", characteristic);

? ? ? ? NSLog(@"%@", characteristic);

? ? ? ? [self.centralManager cancelPeripheralConnection:peripheral];

? ? }

}

給外圍設備發送(寫入)數據

// 上文中發現特征之后, 發送下行指令的時候其實就是向藍牙中寫入數據

// 例:

// 發送檢查藍牙命令

- (void)writeCheckBleWithBle

{

? ? _style =1;

? ? // 發送下行指令(發送一條)

? ? NSData *data = [@"硬件工程師提供給你的指令, 類似于5E16010203...這種很長一串"dataUsingEncoding:NSUTF8StringEncoding];

? ? [self.peripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];

}

#pragma mark 數據寫入成功回調

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

? ? NSLog(@"寫入成功");

? ? if([self.delegate respondsToSelector:@selector(didWriteSucessWithStyle:)]) {

? ? ? ? [self.delegate didWriteSucessWithStyle:_style];

? ? }

}

另外

- (void)scanDevice

{

? ? if(_centralManager ==nil) {

? ? ? ? self.centralManager = [[CBCentralManager alloc] initWithDelegate:selfqueue:nil];

? ? ? ? [_deviceDic removeAllObjects];

? ? }

}

#pragma mark 斷開連接

- (void)disConnectPeripheral{

? ? /**

?? ? -- 斷開連接后回調didDisconnectPeripheral

?? ? -- 注意斷開后如果要重新掃描這個外設,需要重新調用[self.centralManager scanForPeripheralsWithServices:nil options:nil];

?? ? */

? ? [self.centralManager cancelPeripheralConnection:self.peripheral];

}

#pragma mark 停止掃描外設

- (void)stopScanPeripheral{

? ? [self.centralManager stopScan];

}

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容