一. 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 *)RSSI{}
1.3.4 扫描外设中的服务和特征(discover)
当连接成功后,系统会通过回调函数告诉我们,然后我们就在这个回调里去扫描设备下所有的服务和特征,代码如下:
//连接成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {}
// 寻找到服务
- (void)peripheral:(CBPeripheral *)aPeripheral didDiscoverServices:(NSError *)error {}
//寻找到特征
- (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值,得转换]