CoreBluetooth的API是基于BLE4.0的标准的,从iphone4s往后的设备支持,还有iPhone iOS6的模拟器也支持。

一,外设(Peripheral)和中央(Central)

CoreBluetooth框架的核心就是peripheral(外设)和central(中心)。

比如,通过手机和智能手表通信,那么手机就是Central,手表就是Peripheral。可以认为外设是一个广播数据的设备,他广播到外部世界说他这儿有数据,并且也说明了能提供的服务。另一边,中央开始扫描附近有没有服务,如果中央发现了想要的服务,就会请求连接该外设,一旦连接建立成功,两个设备之间就开始交换传输数据了。

在具体的使用场景下,每一个外设都通过唯一的设备UUID来彼此区分,也可以保存下来作为重连的凭据,在第四部分具体说明。 

二,服务(Service)和特征值(Characteristic)

每个BLE4.0设备必然包含一个或多个服务,每个服务下面又包含若干个特征。特征是与外界交互的最小单位。比如说一只智能手表,用特征值A来描述自己的出厂信息,用特征值B来收发数据等。

服务和特征值都是用UUID来唯一标识的,UUID是一个16bit或者128bit的值。国际蓝牙组织为一些很典型的设备(比如测量心跳和血压的设备)规定了标准的service UUID,当然还有很多设备并不在这个标准列表里,比如我在开发中用到的智能手表,“6e400001-b5a3-f393-e0a9-e50e24dcca9e”用来读写手表信息,“00001530-1212-efde-1523-785feabcd123”用来进行ota升级。

三,BLE通信实现流程

1,建立中心角色

1
2
3
4
5
#import   
 
CBCentralManager *manager;  
 
manager = [[CBCentralManager alloc] initWithDelegate: self  queue: nil ]; 

 

2,扫描外设(discover)

[manager scanForPeripheralsWithServices:nil options:options];

 

3,连接外设(connect)

1
2
3
4
5
6
7
8
9
10
11
12
13
- ( void )centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:( NSDictionary  *)advertisementData RSSI:( NSNumber  *)RSSI  
{
         if ([peripheral.name  isEqualToString:BLE_SERVICE_NAME]){
                 [ self  connect:peripheral];
         }
}        
 
-( BOOL )connect:(CBPeripheral *)peripheral
{
   self .manager.delegate =  self ;
       [ self .manager connectPeripheral:peripheral
                                 options:[ NSDictionary  dictionaryWithObject:[ NSNumber  numberWithBool: YES ] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];


4,扫描外设中的服务和特征值(discover)

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
- ( void )centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral  
{  
     NSLog (@ "Did connect to peripheral: %@" , peripheral);  
     _testPeripheral = peripheral;  
 
  
     [peripheral setDelegate: self ];   //查×××
     [peripheral discoverServices: nil ];      
}  
 
- ( void )peripheral:(CBPeripheral *)peripheral didDiscoverServices:( NSError  *)error  
{  
     NSLog (@ "didDiscoverServices" );  
     if  (error)  
     {  
         NSLog (@ "Discovered services for %@ with error: %@" , peripheral.name, [error localizedDescription]);  
 
         if  ([ self .delegate respondsToSelector: @selector (DidNotifyFailConnectService:withPeripheral:error:)])  
             [ self .delegate DidNotifyFailConnectService: nil  withPeripheral: nil  error: nil ];            
 
             return ;  
     }  
 
     for  (CBService *service in peripheral.services)  
     {  
          //发现服务
         if  ([service.UUID isEqual:[CBUUID UUIDWithString:UUIDSTR_ISSC_PROPRIETARY_SERVICE]])  
         {  
             NSLog (@ "Service found with UUID: %@" , service.UUID);  //查找特征值
             [peripheral discoverCharacteristics: nil  forService:service];  
             break ;  
         }            
     }  
 
- ( void )peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:( NSError  *)error
{
     if  (error)
     {
         NSLog (@ "Discovered characteristics for %@ with error: %@" , service.UUID, [error localizedDescription]);        
 
         [ self  error];
         return ;
     }    
 
     NSLog (@ "服务:%@" ,service.UUID);
     for  (CBCharacteristic *characteristic in service.characteristics)
     {
            //发现特征
             if  ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@ "xxxxxxx" ]]) {
                 NSLog (@ "监听:%@" ,characteristic);  //监听特征值
                 [ self .peripheral setNotifyValue: YES  forCharacteristic:characteristic];
             }         
     }

 

5,与外设做数据交互(读 与 写)  

1
2
3
4
5
6
7
8
9
10
11
12
- ( void )peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:( NSError  *)error
{
     if  (error)
     {
         NSLog (@ "Error updating value for characteristic %@ error: %@" , characteristic.UUID, [error localizedDescription]);
         self .error_b = BluetoothError_System;
         [ self  error];
 
         return ;
     }
     [ self  decodeData:characteristic.value];

1
2
3
4
5
NSInteger  time = [[ NSDate  date] timeIntervalSince1970]; //时间戳
NSMutableData  * data = [ NSMutableData  data];
[data appendBytes:&time length:4];

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

读写数据需要考虑具体的使用场景,比如Data,Byte,bit的转换,数据字节序的大小端,数据是否分包。以及对于外设的某些信息的判断:比如说,你要交互的特征,它的properties的值是0x10,表示你只能用订阅的方式来接收数据:

[_testPeripheral setNotifyValue:YES forCharacteristic:_readCharacteristic]; 

四,重连外设(Retrieve)

当外设已处于连接状态,或者与手机配对的状态下,是无法直接通过扫描发现外设的,CoreBluetooth提供了重连恢复的API,它有两种方式,返回值都是外设Peripheral数组:

1.retrievePeripheralsWithIdentifiers,参数是设备的UUID

2.retrieveConnectedPeripheralsWithServices,参数是特定服务的UUID

1
2
3
4
5
6
7
NSUUID  * uuid  = [[ NSUUID  alloc] initWithUUIDString:uuidString1];
[uuidArray addObject:( id ) uuid ];  
if (uuidArray.count != 0)
{
     NSArray  * arr = [_bleCentralManager retrievePeripheralsWithIdentifiers:uuidArray];
}

原文出处:http://www.cnblogs.com/clumsy1006/p/5251992.html