1 前言
目前有越來越多的可穿戴裝置使用了藍牙4.0 BLE(Bluetooth Low Energy)。對于iOS開發而言,Apple之前專門推出CoreBluetooth的Framework來支援BLE的開發。對于硬體開發有了解的朋友應該知道,在之前使用低版本的藍牙的裝置,要連接配接到iOS裝置上,需要注冊MFI,擁有MFI協定才能進行相應的開發。如果大家關注我之前對LEGO EV3的研究,就可以發現,EV3是使用了藍牙2.1,是以需要MFI協定來進行開發。
本文将一步一步講解如何使用CoreBluetooth架構來與各種可穿戴裝置進行通信,使用 小米手環 來進行基本的測試。
2 開發環境
1 Macbook Pro Mac OS X 10.10
2 Xcode 6.3.2
3 iPhone 5s v8.1
4 小米手環
3 基本流程
要開發藍牙,需要對整個通訊過程有個基本了解。這裡我摘錄一些Apple官方的文檔Core Bluetooth Programming Guide的圖檔來加以說明。這個文檔其實對于開發的流程寫的是非常的清楚,大家最好可以看一下。
3.1 可穿戴裝置與iOS互聯方式
從上面這幅圖可以看到,我們的iOS裝置是Central,用來接收資料和發送指令,而外設比如小米手環是Peripheral,向外傳輸資料和接收指令。我們要做的就是通過Central來連接配接Peripheral,然後實作資料的接收和控制指令的發送。在做到這一步之後,再根據具體的硬體,對接收到的資料進行parse解析。
3.2 可穿戴裝置藍牙的資料結構
這裡用的是心率裝置來做說明,每個外設Peripheral都有對應的服務Service,比如這裡是心率Service。一個外設可以有不止一個s、Service。每個service裡面可以有多個屬性Characteristic,比如這裡有兩個Characteristic,一個是用來測量心率,一個是用來定位位置。
那麼很關鍵的一點是每個Service,每個Characteristic都是用UUID來确定的。UUID就是每個Service或Characteristic的identifier。
大家可以在iPhone上下載下傳LightBlue這個應用。可以在這裡檢視一些裝置的UUID。
在實際使用中,我們都是要通過UUID來擷取資料。這點非常重要。
在CoreBluetooth中,其具體的資料結構圖如下:
4 Step-By-Step 上手BLE開發
4.1 Step 1 建立CBCentralManager
從名字上大家可以很清楚的知道,這個類是用來管理BLE的。我們也就是通過這個類來實作連接配接。
先建立一個:
@property (nonatomic,strong) CBCentralManager *centralManager;
dispatch_queue_t centralQueue = dispatch_queue_create("com.manmanlai", DISPATCH_QUEUE_SERIAL); self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:centralQueue];
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
然後關鍵在于CBCentralManagerDelegate的使用。這個之後再講。
4.2 Step 2 尋找CBPeripheral外設
有了CBCentralManager,接下來就是尋找CBPeripheral外設,方法很簡單:
- 1
- 1
這裡的Service就是對應的UUID,如果為空,這scan所有service。
4.3 Step 3 連接配接CBPeripheral
在上一步中,如果找到了裝置,則CBCentralManager的delegate會調用下面的方法:
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
NSLog(@"name:%@",peripheral); if (!peripheral || !peripheral.name || ([peripheral.name isEqualToString:@""])) { return; } if (!self.peripheral || (self.peripheral.state == CBPeripheralStateDisconnected)) { self.peripheral = peripheral; self.peripheral.delegate = self; NSLog(@"connect peripheral"); [self.centralManager connectPeripheral:peripheral options:nil]; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
我們在這裡建立了一個CBPeripheral的對象,然後直接連接配接
CBPeripheral的對象也需要設定delegate.
4.4 Step 4 尋找Service
如果Peripheral連接配接成功的話,就會調用delegate的方法:
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
if (!peripheral) {
return;
}
[self.centralManager stopScan]; NSLog(@"peripheral did connect"); [self.peripheral discoverServices:nil]; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
我們這裡先停止Scan,然後讓Peripheral外設尋找其Service。
4.5 Step 5 尋找Characteristic
找到Service後會調用下面的方法:
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
NSArray *services = nil;
if (peripheral != self.peripheral) { NSLog(@"Wrong Peripheral.\n"); return ; } if (error != nil) { NSLog(@"Error %@\n", error); return ; } services = [peripheral services]; if (!services || ![services count]) { NSLog(@"No Services"); return ; } for (CBService *service in services) { NSLog(@"service:%@",service.UUID); [peripheral discoverCharacteristics:nil forService:service]; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
我們根據找到的service尋找其對應的Characteristic。
4.6 Step 6 找到Characteristic後讀取資料
找到Characteristic後會調用下面的delegate方法:
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
NSLog(@"characteristics:%@",[service characteristics]);
NSArray *characteristics = [service characteristics]; if (peripheral != self.peripheral) { NSLog(@"Wrong Peripheral.\n"); return ; } if (error != nil) { NSLog(@"Error %@\n", error); return ; } self.characteristic = [characteristics firstObject]; //[self.peripheral readValueForCharacteristic:self.characteristic]; [self.peripheral setNotifyValue:YES forCharacteristic:self.characteristic];
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
這裡我們可以使用readValueForCharacteristic:來讀取資料。如果資料是不斷更新的,則可以使用setNotifyValue:forCharacteristic:來實作隻要有新資料,就擷取。
4.7 Step 7 處理資料
讀到資料後會調用delegate方法:
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
NSData *data = characteristic.value;
// Parse data ...
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
4.8 Step 8 向裝置寫資料
這個很簡單,隻要使用:
- 1
- 1
data是NSData類型。
5 實驗
使用小米手環實驗,得到如下結果:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
6 小結
通過上面的方法,我們就可以輕松的對BLE進行開發。實際上比想象的要簡單。
轉載于:https://www.cnblogs.com/liaolijun/p/6689858.html