轉載自https://www.jianshu.com/p/f0e4b0e98336
2015年的時候自己寫過一個藍牙4.0項目,當忘了寫博客,最近看到這篇博客寫的挺詳細,所以轉載一下
一: 介紹
藍牙分為藍牙2.0和藍牙4.0。
藍牙2.0為傳統藍牙,傳統藍牙也稱為經典藍牙。
藍牙4.0因為低耗電,所以也叫做低功耗藍(BLE),它將三種規格集一體,包括傳統藍牙技術、高速技術和低耗能技術。
這篇文章用來介紹BLE 4.0的使用以及相關問題的解決。
二:BLE的兩種模式
BLE的兩種模式分為CBCentralMannager 中心模式 和CBPeripheralManager 外設模式,在這里主要和大家分享CBCentralMannager 中心模式的開發和使用。
CBCentralMannager 中心模式
以手機(app)作為中心,連接其他外設的場景。詳細流程如下:
- 建立中心角色
- 掃描外設
- 發現外設
- 連接外設
4.1 連接失敗
4.2 連接斷開
4.3 連接成功 - 掃描外設中的服務
5.1 發現並獲取外設中的服務 - 掃描外設對應服務的特征
6.1 發現並獲取外設對應服務的特征
6.2 給對應特征寫數據 - 訂閱特征的通知
7.1 根據特征讀取數據
CBPeripheralManager 外設模式
使用手機作為外設連接其他中心設備操作的場景。
PS:因為蘋果設備的安全性和封閉性,蘋果設備不能通過與其他設備藍牙鏈接進行文件傳輸等功能,所以在iOS與藍牙開發的編程中是CBCentralMannager 中心模式編程居多.
- 建立外設角色
- 設置本地外設的服務和特征
- 發布外設和特征
- 廣播服務
- 響應中心的讀寫請求
- 發送更新的特征值,訂閱中心
三:BLE開發步驟
在介紹CBCentralMannager 中心模式開發步驟之前,首先需要對項目進行如下配置:
#import "ESPFBYBLEHelper.h" #import <CoreBluetooth/CoreBluetooth.h> @interface ESPFBYBLEHelper ()<CBCentralManagerDelegate,CBPeripheralDelegate> // 中心管理者(管理設備的掃描和連接) @property (nonatomic, strong) CBCentralManager *centralManager; // 存儲的設備 @property (nonatomic, strong) NSMutableArray *peripherals; // 掃描到的設備 @property (nonatomic, strong) CBPeripheral *cbPeripheral; // 外設狀態 @property (nonatomic, assign) CBManagerState peripheralState; @end // 藍牙4.0設備名 static NSString * const kBlePeripheralName = @"lighte290"; // 通知服務 static NSString * const kNotifyServerUUID = @"FF03"; // 寫服務 static NSString * const kWriteServerUUID = @"FFFF"; // 通知特征值 static NSString * const kNotifyCharacteristicUUID = @"FF05"; // 寫特征值 static NSString * const kWriteCharacteristicUUID = @"FF08"; @implementation ESPFBYBLEHelper
這其中需要導入CoreBluetooth框架
#import <CoreBluetooth/CoreBluetooth.h>
遵守CBCentralManagerDelegate,CBPeripheralDelegate協議
@interface ESPFBYBLEHelper ()<CBCentralManagerDelegate,CBPeripheralDelegate>
然后需要檢測藍牙狀態,代碼如下:
// 狀態更新時調用 - (void)centralManagerDidUpdateState:(CBCentralManager *)central { switch (central.state) { case CBManagerStateUnknown:{ NSLog(@"為知狀態"); self.peripheralState = central.state; } break; case CBManagerStateResetting: { NSLog(@"重置狀態"); self.peripheralState = central.state; } break; case CBManagerStateUnsupported: { NSLog(@"不支持的狀態"); self.peripheralState = central.state; } break; case CBManagerStateUnauthorized: { NSLog(@"未授權的狀態"); self.peripheralState = central.state; } break; case CBManagerStatePoweredOff: { NSLog(@"關閉狀態"); self.peripheralState = central.state; } break; case CBManagerStatePoweredOn: { NSLog(@"開啟狀態-可用狀態"); self.peripheralState = central.state; NSLog(@"%ld",(long)self.peripheralState); } break; default: break; } }
添加屬性和常量,常量需要根據自己的項目來進行配置。
下面只需要根據實現流程一步步實現即可,核心代碼如下:
1. 建立中心角色
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
2. 掃描外設
if (self.peripheralState == CBManagerStatePoweredOn){ [self.centralManager scanForPeripheralsWithServices:nil options:nil]; }
3. 發現外設
/** 掃描到設備 @param central 中心管理者 @param peripheral 掃描到的設備 @param advertisementData 廣告信息 @param RSSI 信號強度 */ - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI { NSLog(@"%@",[NSString stringWithFormat:@"發現設備,設備名:%@",peripheral.name]); }
4. 連接外設
[self.centralManager connectPeripheral:peripheral options:nil];
- 4.1 連接失敗 didFailToConnectPeripheral
/** 連接失敗 @param central 中心管理者 @param peripheral 連接失敗的設備 @param error 錯誤信息 */ - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { NSLog(@"%@",@"連接失敗"); }
- 4.2 連接斷開
/** 連接斷開 @param central 中心管理者 @param peripheral 連接斷開的設備 @param error 錯誤信息 */ - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { NSLog(@"%@",@"斷開連接"); }
- 4.3 連接成功
/** 連接成功 @param central 中心管理者 @param peripheral 連接成功的設備 */ - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { NSLog(@"連接設備:%@成功",peripheral.name); [self.centralManager stopScan]; }
5. 掃描外設中的服務
// 設置設備的代理 peripheral.delegate = self; // services:傳入nil 代表掃描所有服務 [peripheral discoverServices:nil];
5.1 發現並獲取外設中的服務
/** 掃描到服務 @param peripheral 服務對應的設備 @param error 掃描錯誤信息 */ - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error { // 遍歷所有的服務 for (CBService *service in peripheral.services) { NSLog(@"服務:%@",service.UUID.UUIDString); } }
6. 掃描外設對應服務的特征
// 獲取對應的服務 if (![service.UUID.UUIDString isEqualToString:kWriteServerUUID]) { return; } // 根據服務去掃描特征 [peripheral discoverCharacteristics:nil forService:service];
6.1 發現並獲取外設對應服務的特征
/** 掃描到對應的特征 @param peripheral 設備 @param service 特征對應的服務 @param error 錯誤信息 */ - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { NSLog(@"%@",peripheral); }
6.2 給對應特征寫數據
[peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
7. 訂閱特征的通知
if ([characteristic.UUID.UUIDString isEqualToString:kNotifyCharacteristicUUID]){ [peripheral setNotifyValue:YES forCharacteristic:characteristic]; }
7.1 根據特征讀取數據 didUpdateValueForCharacteristic
/** 根據特征讀到數據 @param peripheral 讀取到數據對應的設備 @param characteristic 特征 @param error 錯誤信息 */ - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error { if ([characteristic.UUID.UUIDString isEqualToString:kNotifyCharacteristicUUID]) { NSData *data = characteristic.value; NSLog(@"%@",data); } }