一. iOS蓝牙CoreBluetooth介绍

1. 1   CoreBluetooth框架的核心其实是两个东西,peripheral和central, 可以理解成外设和中心。对应他们分别有一组相关的API和类,如下图所示:



1.2    服务和特征(service and characteristic)

一个蓝牙4.0的设备都是通过服务和特征来展示自己的,一个设备必然包含一个或多个服务,每个服务下面又包含若干个特征。特征是与外界交互的最小单位。比如说,一台蓝牙4.0设备,用特征A来描述自己的出厂信息,用特征B来与收发数据等。服务和特征都是用UUID来唯一标识的.


1.3 实现过程

作为一个中心要实现完整的通讯,一般要经过这样几个步骤:

建立中心角色—扫描外设(discover)—连接外设(connect)—扫描外设中的服务和特征(discover)—与外设做数据交互(explore and interact)—断开连接(disconnect)。

1.3.1 建立中心角色

centralManager = [[CBCentralManageralloc]initWithDelegate:selfqueue:nil];

1.3.2 扫描外设

[self.centralManagerscanForPeripheralsWithServices:niloptions:nil];

1.3.3  连接外设 

//发现蓝牙设备 回调函数

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber



1.3.4  扫描外设中的服务和特征(discover)

当连接成功后,系统会通过回调函数告诉我们,然后我们就在这个回调里去扫描设备下所有的服务和特征,代码如下:

//连接成功

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral

// 寻找到服务

- (void)peripheral:(CBPeripheral *)aPeripheral didDiscoverServices:(NSError

//寻找到特征

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError

1.3.5  与外设做数据交互(explore and interact)

//写数据

-(void)writeChar:(NSData *)data{}



数据的读分为两种,一种是直接读(reading directly),另外一种是订阅(subscribe)。

实际使用中具体用一种要看具体的应用场景以及特征本身的属性。前一个好理解,特征本身的属性是指什么呢?特征有个properties字段(characteristic.properties),它是一个整型值,有如下几个定义:

enum {

     CBCharacteristicPropertyBroadcast = 0x01,

     CBCharacteristicPropertyRead = 0x02,

     CBCharacteristicPropertyWriteWithoutResponse =0x04,

     CBCharacteristicPropertyWrite = 0x08,

     CBCharacteristicPropertyNotify = 0x10,

     CBCharacteristicPropertyIndicate = 0x20,

     CBCharacteristicPropertyAuthenticatedSignedWrites =0x40,

     CBCharacteristicPropertyExtendedProperties =0x80,

};

比如说,你要交互的特征,它的properties的值是0x10,表示你只能用订阅的方式来接收数据。我这里是用订阅的方式,启动订阅的代码如下:

//监听设备
-(void)startSubscribe
{
    [_testPeripheral setNotifyValue:YES forCharacteristic:_readCharacteristic];
}

当设备有数据返回时,同样是通过一个系统回调通知我,如下所示:


- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    if(error) 
{
        NSLog(@"Error updating value for characteristic %@ error: %@", characteristic.UUID, [error localizedDescription]);
         
        if([_mainMenuDelegate respondsToSelector:@selector(DidNotifyReadError:)])
            [_mainMenuDelegate DidNotifyReadError:error];
return;
}
    [_recvData appendData:characteristic.value];
     
    if([_recvData length] >=5)//已收到长度
{
        unsigned char*buffer = (unsignedchar*)[_recvData bytes];
        intnLen = buffer[3]*256+ buffer[4];
        if([_recvData length] == (nLen+3+2+2))
{
            //接收完毕,通知代理做事
            if([_mainMenuDelegate respondsToSelector:@selector(DidNotifyReadData)])
                [_mainMenuDelegate DidNotifyReadData];
}
}
}
 1.3.6   
断开连接(disconnect) 
//主动断开设备
-(void)disConnect





二.  

过程:

1.判断状态为powerOn,然后执行扫描 

2.停止扫描,连接外设 

3.连接成功,寻找服务 

4.在服务里寻找特征 

5.为特征添加通知 

5.通知添加成功,那么就可以实时的读取value[也就是说只要外设发送数据[一般外设的频率为10Hz],代理就会调用此方法]。 

6.处理接收到的value,[hex值,得转换] 


三.  呵护宝项目蓝牙分析

问题:

 1.  数据格式,一定是byte ?

 2.  一个设备有多个服务,一个服务下有多个特征, 传输的数据是封装在特征里,接收对应的特征,就可以接收到数据?

 3. 如何识别所有呵护宝的蓝牙设备,过滤其他的?


iOS 上的蓝牙框架 - Core Bluetooth for iOS [译]:  http://doruby.com/blog/2013/08/15/core-bluetooth-for-ios/