iOS基於CoreBlutooth的藍芽開發
首先如同網路一般,藍芽也類似的可以分服務端和客戶端,CoreBlutooth中有兩個角色,一個是Peripheral,相當於伺服器端,也就是我們開啟手機藍芽搜尋時找到的各個裝置;一個是Central,相當於客戶端,也就是我們使用的手機,這兩個角色和一般的手機使用主權引起的角色意識有點衝突。
藍芽通訊過程中有幾個部分,一個是Service,即伺服器提供的服務,一個服務端可能有一個或者多個Service,還有一個是Characteristic,即特徵值,相當於溝通過程中的欄位,服務端和客戶端可以針對指定特徵值進行資料交流。
因為沒有藍芽模組和藍芽裝置,所以我是在MAC端編寫了Peripheral端,手機上執行Central端(藍芽程式必須真機除錯
Peripheral端
#import <CoreBluetooth/CoreBluetooth.h> #define TRANSFER_SERVICE_UUID @"0bd51666-e7cb-469b-8e4d-2742f1ba77cc" //服務的UUID #define TRANSFER_CHARACTERISTIC_UUID @"1bd51666-e7cb-469b-8e4d-2742f1ba77dd" //讀取埠的特徵值UUID #define TRANSFER_CHARACTERISTIC1_UUID @"2bd51666-e7cb-469b-8e4d-2742f1ba77dd" //寫入埠的特徵值UUID @interface ViewController ()<CBPeripheralManagerDelegate> @property (nonatomic,strong) CBPeripheralManager *peripheral; //peripheral管理者 @property (nonatomic,strong) CBMutableCharacteristic *transferCharacteristic; //讀取埠特徵值 @property (nonatomic,strong) CBMutableCharacteristic *transferCharacteristic1; //寫入埠特徵值 @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //按鈕 用於更新欄位值 NSButton *button = [NSButton buttonWithTitle:@"dianji" target:self action:@selector(btnClick)]; button.frame = NSRectFromCGRect(CGRectMake(10, 10, 100, 50)); [self.view addSubview:button]; self.peripheral = [[CBPeripheralManager alloc]initWithDelegate:self queue:nil]; //初始化,並設定代理 CBMutableService *transferService = [[CBMutableService alloc]initWithType:[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID] primary:YES]; //構建服務 // 構建兩個特徵值 引數Type:特徵值UUID,properties:埠屬性,通知、讀、寫、不帶回應寫入等等,value:特徵值,如果要設定,特徵值須為readonly,permissions:讀寫許可權 self.transferCharacteristic = [[CBMutableCharacteristic alloc]initWithType:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID] properties: CBCharacteristicPropertyRead value:nil permissions:CBAttributePermissionsReadable]; // properties很重要,如果沒有設定讀屬性,central呼叫read方法時會被禁止 self.transferCharacteristic1 = [[CBMutableCharacteristic alloc]initWithType:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC1_UUID] properties: CBCharacteristicPropertyNotify | CBCharacteristicPropertyWrite | CBCharacteristicPropertyWriteWithoutResponse value:nil permissions: CBAttributePermissionsReadEncryptionRequired | CBAttributePermissionsWriteEncryptionRequired]; // 為服務新增特徵值 transferService.characteristics = @[self.transferCharacteristic,self.transferCharacteristic1]; [self.peripheral addService:transferService]; //為peripheral新增服務 [self.peripheral startAdvertising:@{CBAdvertisementDataServiceUUIDsKey:[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]}]; //開啟廣播 } // 必須的代理,狀態更新 - (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral{ NSLog(@"%ld",(long)peripheral.state); } // 接收到寫入請求後的代理 - (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests{ CBATTRequest *request = requests[0]; NSLog(@"-----%d",[self.peripheral updateValue:request.value forCharacteristic:self.transferCharacteristic1 onSubscribedCentrals:nil]); } // 接收到讀取請求後的代理 - (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request{ NSLog(@"read"); } - (void)btnClick{ // [self.peripheral updateValue:[NSData dataWithBytes:"Hello world" length:11] forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil]; // self.transferCharacteristic.value = [NSData dataWithBytes:"Hello World" length:11]; [self.peripheral updateValue:[NSData dataWithBytes:"hello World" length:11] forCharacteristic:self.transferCharacteristic1 onSubscribedCentrals:nil]; //更新指定特徵值埠的值,並不會改變characteristic.value [self.peripheral updateValue:[NSData dataWithBytes:"hello" length:11] forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil]; NSLog(@"%@",[[NSString alloc]initWithData:self.transferCharacteristic1.value encoding:NSUTF8StringEncoding]); } - (void)setRepresentedObject:(id)representedObject { [super setRepresentedObject:representedObject]; // Update the view, if already loaded. } @end
上面是服務端的程式碼,需要注意的是如果是自己開發藍芽模組的話,相關service的UUID以及characteristic的UUID可以和模組開發人員商定,如果是手環或者其他商用成品的話,商家應該會提供相關UUID。
Central端
// // ViewController.m // testDD // // Created by 周小偉 on 2017/7/7. // Copyright © 2017年 周小偉. All rights reserved. // #import "ViewController.h" #import <CoreBluetooth/CoreBluetooth.h> // 三個特徵值必須和服務端一樣,不然找不到指定特徵值 #define TRANSFER_SERVICE_UUID @"0bd51666-e7cb-469b-8e4d-2742f1ba77cc" #define TRANSFER_CHARACTERISTIC_UUID @"1bd51666-e7cb-469b-8e4d-2742f1ba77dd" #define TRANSFER_CHARACTERISTIC1_UUID @"2bd51666-e7cb-469b-8e4d-2742f1ba77dd" @interface ViewController ()<CBCentralManagerDelegate,CBPeripheralDelegate> @property (nonatomic,strong) NSMutableArray *peripherArr; //用於儲存已經發現的裝置 @property (nonatomic,strong) CBCentralManager *manager; //central管理者 @property (nonatomic,strong) CBPeripheral *peripheral; //當前連線的peripheral @property (nonatomic,strong) CBCharacteristic *char1; //讀取的特徵值埠 @property (nonatomic,strong) CBCharacteristic *char2; //寫入的特徵值埠 @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.manager = [[CBCentralManager alloc]initWithDelegate:self queue:nil]; //初始化管理者 //CBCentralManager非當前迴圈建立,如果不用強指標引用,出了應用域就會被釋放,執行會報錯 } // central管理者代理,必須呼叫 判斷藍芽狀態,如果狀態為藍芽開啟的話,開始掃描 - (void)centralManagerDidUpdateState:(CBCentralManager *)central{ if (central.state == CBManagerStatePoweredOn) { [self.manager scanForPeripheralsWithServices:nil options:nil]; } } // 掃描的代理方法 在停止掃描之前會不斷呼叫 - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI{ if (!peripheral.name) { return; //過濾沒有名字的裝置 } [self.manager stopScan]; //停止掃描,也可以在連線裝置後停止掃描 //因為附近只有一個裝置,所以沒有對裝置進行判斷,實際上可以新增到陣列中儲存,順便新增強引用 [central connectPeripheral:peripheral options:nil];//連線裝置,如果有必要可以針對裝置屬性進行判斷,然後連線,比如裝置名字,UUID等 self.peripheral = peripheral;//只為了新增強引用,一般不這麼寫 self.peripheral.delegate = self;//設定代理 } //管理者代理,連線到裝置後呼叫 - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{ [peripheral discoverServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]]];//查詢服務,引數如果設定為nil為查詢所有服務 } //peripheral代理,發現沒用的服務時呼叫 - (void)peripheral:(CBPeripheral *)peripheral didModifyServices:(NSArray<CBService *> *)invalidatedServices{ NSLog(@"---- %@",invalidatedServices); } //發現服務後呼叫 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{ NSArray *services = peripheral.services; //獲取裝置的所有服務,下面的處理只因為服務端我只有一個service,所以沒有進行處理,實際上一個裝置會有多個service,需要遍歷分別處置 if (services.count) { CBService *service = services[0]; CBUUID *writeUUID = [CBUUID UUIDWithString: TRANSFER_CHARACTERISTIC1_UUID]; CBUUID *readUUID = [CBUUID UUIDWithString: TRANSFER_CHARACTERISTIC_UUID]; [peripheral discoverCharacteristics:@[writeUUID, readUUID] forService:service];//查詢指定特徵值 } } //peripheral代理,發現特徵值時呼叫 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{ if (!error) { NSArray *characteristicArray = service.characteristics;//獲取service的特徵值,實際上一個service可能有多個特徵值,需要自己處理,比如針對特徵值的properties進行處理 if(characteristicArray.count > 1){ //因為讀寫操作是針對特徵值進行的,所以要取得兩個特徵值 CBCharacteristic *readCharacteristic = characteristicArray[0]; CBCharacteristic *writeCharacteristic = characteristicArray[1]; self.char1 = readCharacteristic; self.char2 = writeCharacteristic; // 通知使能, `YES` enable notification only, `NO` disable notifications and indications //[peripheral setNotifyValue:YES forCharacteristic:readCharacteristic]; // [peripheral setNotifyValue:YES forCharacteristic:writeCharacteristic]; //為指定特徵值新增通知,需要特徵值的properties設定了notify屬性才能設定,一般前面會加入判斷 if(writeCharacteristic.properties & CBCharacteristicPropertyNotify) // [peripheral readValueForCharacteristic:readCharacteristic];//讀取資料,需要特徵值的properties設定了read屬性,判斷方法類似上一句// [peripheral readValueForCharacteristic:writeCharacteristic]; } NSLog(@"Hello "); } else { NSLog(@"Discover Charactertics Error : %@", error); } } // peripheral代理,設定過notify屬性的特徵值的值發生變化後會呼叫這個方法,比如我的demo裡面的寫入特徵值我設定了notify和write,然後寫入後因為值改變了就會呼叫這個代理方法,在peripheral為特徵值設定setNotifyValue:forCharacteristic:時就會呼叫這個方法 - (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{ if (error) { NSLog(@"%@",characteristic); NSLog(@"%@",error.userInfo); return; } CBCharacteristicProperties properties = characteristic.properties; if (properties) { NSLog(@"%@",characteristic.value); } } // peripheral代理方法,寫入操作後呼叫需要寫入時設定type為withResponse才會呼叫 - (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{ if (!error) { NSLog(@"Write Success"); }else{ NSLog(@"WriteValue Error = %@",error.userInfo); } } // peripheral代理方法,指定特徵值的value值變化了後呼叫 - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{ if (error) { NSLog(@"update value error:%@",error.userInfo); }else{ NSData *responseData = characteristic.value; NSLog(@"||||||||||%@",[[NSString alloc]initWithData:responseData encoding:NSUTF8StringEncoding]); NSLog(@"%@",[[NSString alloc]initWithData:characteristic.value encoding:NSUTF8StringEncoding]); } } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ static int i = 0; NSString *str = [NSString stringWithFormat:@"Hello %d",i]; [self.peripheral writeValue:[NSData dataWithBytes:str.UTF8String length:strlen(str.UTF8String)]forCharacteristic:self.char2 type:CBCharacteristicWriteWithResponse];//寫入操作,引數type,必須要withResponse才會有代理回撥,如果要設定withoutResponse需要相關特徵值設定了一樣的屬性 NSLog(@"%ld",[self.peripheral maximumWriteValueLengthForType:CBCharacteristicWriteWithoutResponse]); i++; // [self.peripheral readValueForCharacteristic:self.char1];//讀取操作 } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
主要的藍芽互動過程就類似於上面所示,但實際上溝通過程並沒有達到理想效果,比如寫入操作只能進行一次,我並不知道是否因為裝置的原因,如果有機會可以找到其他裝置再來嘗試。
相關推薦
iOS基於CoreBlutooth的藍芽開發
首先如同網路一般,藍芽也類似的可以分服務端和客戶端,CoreBlutooth中有兩個角色,一個是Peripheral,相當於伺服器端,也就是我們開啟手機藍芽搜尋時找到的各個裝置;一個是Central,相當於客戶端,也就是我們使用的手機,這兩個角色和一般的手機使用主權引起的角
iOS之藍芽開發—CoreBluetooth詳解
CoreBluetooth的API是基於BLE4.0的標準的。這個框架涵蓋了BLE標準的所有細節。僅僅只有新的iOS裝置和Mac是和BLE標準相容.在CoreBluetooth框架中,有兩個主要的角色:周邊和中央(Peripheral and Central) ,整個框架
iOS藍芽開發(二)在裝置端實現Central角色
若想在裝置上實現Central角色的功能,主要有以下步驟: 2.搜尋周圍廣播的裝置 3.與一個外設進行連線,並探索外設提供的服務 4.向外設傳送讀寫characteristic的請求,如果有需要訂閱characteristic值得更新,來跟蹤資料的變化。 myCe
IOS Ble藍芽開發實現
1.本篇博文闡述如何開發Ble藍芽。在藍芽中的一些常見服務,掃描,以及連結; 主藍芽類檔案.h 主藍芽類檔案.m UUID檔案 藍芽列表展示的檔案 一:引入Ble藍芽的框架<CoreBluetooth/CoreBluetooth.h>
iOS藍芽開發 —— 連線列印機發送16進位制資料的問題
最近在做公司的一個藍芽連線印表機的專案,正常的藍芽連線印表機進行列印沒問題,但是要傳送一個16進位制的指令來獲取藍芽裝置資訊時頗費了一番功夫,現做如下記錄: Byte byteArray[] = {0x1d ,0x67 ,0x61}; NSData *sendData = [NSData data
iOS藍芽開發
原作者:===>https://blog.csdn.net/swibyn/article/details/20531593 demo下載 http://download.csdn.net/detail/swibyn/9717588 直接看程式碼 http://blog.
iOS近場通訊(藍芽開發,WiFi開發)
標籤: ios it 近場通訊 藍芽 wifi 分類: iOS 1 AirDrop (UIActivityViewController類) 功能:實現iOS裝置間的檔案和資料分享。AirDrop使用藍芽來掃描周圍的裝置,當兩臺裝置通過藍芽建立起了連線,考慮到
iOS藍芽開發:藍芽連線和資料讀寫
當下藍芽開發可謂是越來越火,不論是智慧穿戴的興起還是藍芽傢俱,車聯網藍芽等等,很多同學也會接觸到藍芽的專案,我從事藍芽開發也有一段時間了,經手了兩個專案。廢話不多說了,先向大家簡單的介紹有關藍芽開發的知識。藍芽低能耗(BLE),以下介紹的都是圍繞iOS的框架展開
iOS藍芽開發(二):iOS 藍芽4.0中心模式 程式碼實現
上一篇簡單介紹了藍芽的部分基礎知識,詳細的東西大家可以去github上搜babyBluetooth,裡面有一些學習資料 iOS連線外設的流程 建立中心管理者 掃描外設 discoverPeripheral 連線外設 connectPeripheral
iOS之藍芽開發
因工作的需要, 前段時間整理了一下IOS藍芽通訊相關的東西,把整理的一個成果給大家分享一下。如果有不足的地方歡迎指正。 一、專案背景 簡單介紹一下我所做的東西,裝置目前有四個,分別是體脂秤、血壓計、血糖儀、監護儀等。從名稱大家應該知道這些是什麼東西了。對,沒錯,這些裝置主要
ios藍芽開發(三)app作為外設被連線的實現
再上一節說了app作為central連線peripheral的情況,這一節介紹如何使用app釋出一個peripheral,給其他的central連線 還是這張圖,central模式用的都是左邊的類,而peripheral模式用的是右邊的類 peripheral模式的流
iOS藍芽開發:藍芽的連線和資料的讀寫
藍芽開發說簡單也簡單,說不簡單也有點難,開發人員在首次開發藍芽前首先需要搞清楚藍芽開發的概念,還要了解掌握藍芽開發的一整套流程,這樣才能快速上手開發藍芽。 藍芽開發分為兩種模式:管理者模式和中心者模式。管理者模式基本很少用到,相當於iPhone手機
iOS藍芽開發把16進位制字串轉換成NSData的方法
把16進位制字串轉換成NSData: -(NSData *)hexString:(NSString *)hexString { int j=0; Byte bytes[20];
藍芽開發BLE協議流程(iOS為例)
憑藉大腦殘留的記憶寫的BLE的一些概念與接入流程。IOT領域與智慧裝置通訊的方式除了zigbee wifi 就算藍芽了,BLE(bluetooth low energy)看名字就是低功耗的一個東西,通俗來說ble很簡單啊,因為無論是iOS還是android 提供的api 都遮
iOS 開發——CoreBluetooth藍芽開發(一)
最近要做關於iOS上的藍芽開發專案,為此閱讀了蘋果的官方文件,這裡做一些翻譯和摘錄和大家共享交流。(如需轉載請註明出處) 關於Core BlueTooth Core BlueTooth是一個iOS的開發框架,其中包含了若干類,能夠和低功耗藍芽(符合藍芽4
iOS藍芽開發CoreBluetooth快速入門
在iOS開發中,實現藍芽通訊有兩種方式,一種是使用傳統的GameKit.framework,另一種就是使用在iOS 5中加入的CoreBluetooth.framework。 利用CoreBluetooth框架,我們可以輕鬆實現兩個iOS裝置、iOS裝置與非
iOS藍芽開發(一)藍芽相關基礎知識
藍芽常見名稱和縮寫 MFI ======= make for ipad ,iphone, itouch 專們為蘋果裝置製作的裝置 BLE ==== buletouch low energy,藍芽4.0裝置因為低耗電,所以也叫做BLE peripher
Android藍芽開發與藍芽模組進行通訊(基於eclipse)
public class ComminuteActivity extends Activity { private BluetoothReceiver receiver; private BluetoothAdapter bluetoothAdapter; private Lis
Android 藍芽開發常用UUID表
// Sample Services. attributes.put("0000180d-0
IOS--swift BLE藍芽通訊管理(多裝置)
之前一直做的是Android,公司IOS端突然要同時進行多個專案,IOS同學表示壓力山大,所以臨危受命由我來完成專案中關於BLE通訊的功能模組,由於之前做過Android版本的,並且執行狀況良好,一直都比較穩定,因此分享出來,也希望大家能提出好的建議。 總共有4個swift檔案。 如圖