iOS藍芽開發 藍芽連線和資料讀寫
在做藍芽開發之前,最好先了解一些概念:
服務(services):藍芽外設對外廣播的必定會有一個服務,可能也有多個,服務下面包含著一些特徵,服務可以理解成一個模組的視窗;
特徵(characteristic):存在於服務下面的,一個服務下面也可以存在多個特徵,特徵可以理解成具體實現功能的視窗,一般特徵都會有value,也就是特徵值,特徵是與外界互動的最小單位;
UUID:可以理解成藍芽上的唯一識別符號(硬體上肯定不是這個意思,但是這樣理解便於我們開發),為了區分不同的服務和特徵,或者給服務和特徵取名字,我們就用UUID來代表服務和特徵。
藍芽連線可以大致分為以下幾個步驟
1.建立一個Central Manager例項進行藍芽管理
3.連線外圍裝置
4.獲得外圍裝置的服務
5.獲得服務的特徵
6.從外圍裝置讀資料
7.給外圍裝置傳送資料
其他:提醒
首先我們先匯入系統的BLE的框架
#import <CoreBluetooth/CoreBluetooth.h>
必須遵守2個協議
<CBCentralManagerDelegate,CBPeripheralDelegate>
/** 中心管理者 */
@property (nonatomic,strong) CBCentralManager *cMgr;
/** 連線到的外設 */
@property (nonatomic,strong) CBPeripheral *peripheral;
1.建立一個Central Manager例項進行藍芽管理
-(CBCentralManager *)cmgr { if (!_cmgr) { _cMgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; } return _cMgr; } //只要中心管理者初始化 就會觸發此代理方法 判斷手機藍芽狀態 - (void)centralManagerDidUpdateState:(CBCentralManager *)central { switch (central.state) { case 0: NSLog(@"CBCentralManagerStateUnknown"); break; case 1: NSLog(@"CBCentralManagerStateResetting"); break; case 2: NSLog(@"CBCentralManagerStateUnsupported");//不支援藍芽 break; case 3: NSLog(@"CBCentralManagerStateUnauthorized"); break; case 4: { NSLog(@"CBCentralManagerStatePoweredOff");//藍芽未開啟 } break; case 5: { NSLog(@"CBCentralManagerStatePoweredOn");//藍芽已開啟 // 在中心管理者成功開啟後再進行一些操作 // 搜尋外設 [self.cMgr scanForPeripheralsWithServices:nil // 通過某些服務篩選外設 options:nil]; // dict,條件 // 搜尋成功之後,會呼叫我們找到外設的代理方法 // - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI; //找到外設 } break; default: break; } }
2.搜尋外圍裝置 (我這裡為了舉例,採用了自己身邊的一個手環)
// 發現外設後呼叫的方法 - (void)centralManager:(CBCentralManager *)central // 中心管理者 didDiscoverPeripheral:(CBPeripheral *)peripheral // 外設 advertisementData:(NSDictionary *)advertisementData // 外設攜帶的資料 RSSI:(NSNumber *)RSSI // 外設發出的藍芽訊號強度 { //NSLog(@"%s,line = %d,cetral = %@,peripheral = %@,advertisementData = %@,RSSI = %@",__FUNCTION__,__LINE__,central,peripheral,advertisementData,RSSI); /* peripheral = <CBPeripheral: 0x166668f0 identifier = C69010E7-EB75-E078-FFB4-421B4B951341,Name = "OBand-75",state = disconnected>,advertisementData = { kCBAdvDataChannel = 38; kCBAdvDataIsConnectable = 1; kCBAdvDataLocalName = OBand; kCBAdvDataManufacturerData = <4c69616e 0e060678 a5043853 75>; kCBAdvDataServiceUUIDs = ( FEE7 ); kCBAdvDataTxPowerLevel = 0; },RSSI = -55 根據列印結果,我們可以得到運動手環它的名字叫 OBand-75 */ // 需要對連線到的外設進行過濾 // 1.訊號強度(40以上才連線,80以上連線) // 2.通過裝置名(裝置字串字首是 OBand) // 在此時我們的過濾規則是:有OBand字首並且訊號強度大於35 // 通過列印,我們知道RSSI一般是帶-的 if ([peripheral.name hasPrefix:@"OBand"]) { // 在此處對我們的 advertisementData(外設攜帶的廣播資料) 進行一些處理 // 通常通過過濾,我們會得到一些外設,然後將外設儲存到我們的可變陣列中,// 這裡由於附近只有1個運動手環,所以我們先按1個外設進行處理 // 標記我們的外設,讓他的生命週期 = vc self.peripheral = peripheral; // 發現完之後就是進行連線 [self.cMgr connectPeripheral:self.peripheral options:nil]; NSLog(@"%s,line = %d",__LINE__); } }
3.連線外圍裝置
// 中心管理者連線外設成功 - (void)centralManager:(CBCentralManager *)central // 中心管理者 didConnectPeripheral:(CBPeripheral *)peripheral // 外設 { NSLog(@"%s,%@=連線成功",peripheral.name); // 連線成功之後,可以進行服務和特徵的發現 // 設定外設的代理 self.peripheral.delegate = self; // 外設發現服務,傳nil代表不過濾 // 這裡會觸發外設的代理方法 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error [self.peripheral discoverServices:nil]; } // 外設連線失敗 - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { NSLog(@"%s,%@=連線失敗",peripheral.name); } // 丟失連線 - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { NSLog(@"%s,%@=斷開連線",peripheral.name); }
4.獲得外圍裝置的服務 & 5.獲得服務的特徵
// 發現外設服務裡的特徵的時候呼叫的代理方法(這個是比較重要的方法,你在這裡可以通過事先知道UUID找到你需要的特徵,訂閱特徵,或者這裡寫入資料給特徵也可以) - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { NSLog(@"%s,__LINE__); for (CBCharacteristic *cha in service.characteristics) { //NSLog(@"%s,char = %@",cha); } }
5.從外圍裝置讀資料
// 更新特徵的value的時候會呼叫 (凡是從藍芽傳過來的資料都要經過這個回撥,簡單的說這個方法就是你拿資料的唯一方法) 你可以判斷是否 - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { NSLog(@"%s,__LINE__); if (characteristic == @"你要的特徵的UUID或者是你已經找到的特徵") { //characteristic.value就是你要的資料 } }
6.給外圍裝置傳送資料(也就是寫入資料到藍芽)
這個方法你可以放在button的響應裡面,也可以在找到特徵的時候就寫入,具體看你業務需求怎麼用啦
[self.peripherale writeValue:_batteryData forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse]; //第一個引數是已連線的藍芽裝置 ;第二個引數是要寫入到哪個特徵; 第三個引數是通過此響應記錄是否成功寫入
// 需要注意的是特徵的屬性是否支援寫資料 - (void)yf_peripheral:(CBPeripheral *)peripheral didWriteData:(NSData *)data forCharacteristic:(nonnull CBCharacteristic *)characteristic { /* typedef NS_OPTIONS(NSUInteger,CBCharacteristicProperties) { CBCharacteristicPropertyBroadcast = 0x01,CBCharacteristicPropertyRead = 0x02,CBCharacteristicPropertyWriteWithoutResponse = 0x04,CBCharacteristicPropertyWrite = 0x08,CBCharacteristicPropertyNotify = 0x10,CBCharacteristicPropertyIndicate = 0x20,CBCharacteristicPropertyAuthenticatedSignedWrites = 0x40,CBCharacteristicPropertyExtendedProperties = 0x80,CBCharacteristicPropertyNotifyEncryptionRequired NS_ENUM_AVAILABLE(NA,6_0) = 0x100,CBCharacteristicPropertyIndicateEncryptionRequired NS_ENUM_AVAILABLE(NA,6_0) = 0x200 }; 打印出特徵的許可權(characteristic.properties),可以看到有很多種,這是一個NS_OPTIONS的列舉,可以是多個值 常見的又read,write,noitfy,indicate.知道這幾個基本夠用了,前倆是讀寫許可權,後倆都是通知,倆不同的通知方式 */ // NSLog(@"%s,char.pro = %d",characteristic.properties); // 此時由於列舉屬性是NS_OPTIONS,所以一個列舉可能對應多個型別,所以判斷不能用 =,而應該用包含& }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。