标签:
遵守CBCentralManagerDelegate代理和CBPeripheralDelegate代理
在使用你的应用去扫描设备之前,先要确定你的蓝牙是否已经打开,所以我们要做一个判断:
其中f3d9是我连接到iPad mini2的LightBlue app模拟的BLE外围设备,你要换成你设备的UUID。
centralManagerDidUpdateState是CBCentralManagerDelegate必须实现的方法
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{ if (central.state == CBCentralManagerStatePoweredOn) { [self.centralManger scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:@"f3d9"]] options:nil]; } }
switch (central.state) { case CBCentralManagerStateUnknown: NSLog(@">>>CBCentralManagerStateUnknown"); break; case CBCentralManagerStateResetting: NSLog(@">>>CBCentralManagerStateResetting"); break; case CBCentralManagerStateUnsupported: NSLog(@">>>CBCentralManagerStateUnsupported"); break; case CBCentralManagerStateUnauthorized: NSLog(@">>>CBCentralManagerStateUnauthorized"); break; case CBCentralManagerStatePoweredOff: NSLog(@">>>CBCentralManagerStatePoweredOff"); break; case CBCentralManagerStatePoweredOn: NSLog(@">>>CBCentralManagerStatePoweredOn"); // 把最上面的代码放到这里
break; default: break; } }
中心:
1.建立中心角色
顺便设置中心的代理是自己
CBCentralManager *manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
2.扫描外设
[manager scanForPeripheralsWithServices:nil options:options];
3.连接外设
扫描到4.0的外设后进行连接,下面的方法是确定发现外设,把发现的外设对象存放到数组中
中心回调方法:
前提:定义好了NSMutableArray *dicoveredPeripherals;这个用来保存发现的外设对象
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{ // 把外设保存起来 if(![_dicoveredPeripherals containsObject:peripheral]) [_dicoveredPeripherals addObject:peripheral]; NSLog(@"dicoveredPeripherals:%@", _dicoveredPeripherals); }
上面的代码可以优化成,连接指定的外设名称
一个主设备最多能连7个外设,每个外设最多只能给一个主设备连接,连接成功,失败,断开会进入各自的委托
中心回调方法:
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;//连接外设成功的委托
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;//外设连接失败的委托
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;//断开外设的委托
if ([peripheral.name hasPrefix:@"P"]){ //找到的设备必须持有它,否则CBCentralManager中也不会保存peripheral,那么CBPeripheralDelegate中的方法也不会被调用!! [peripherals addObject:peripheral]; //连接设备 [manager connectPeripheral:peripheral options:nil]; } }
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
上面一般回调的是CBCentralManagerDelegate代理方法,一般是CentralManager开头;
下面开始扫描服务和特征时,回调的是CBPeripheralDelegate代理方法,一般是Peripheral开头;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
分界线:
设备连接成功后,就可以扫描设备的服务了,同样是通过委托形式,扫描到结果后会进入委托方法。但是这个委托已经不再是主设备的委托(CBCentralManagerDelegate),而是外设的委托(CBPeripheralDelegate),这个委托包含了主设备与外设交互的许多 回调方法,包括获取services,获取characteristics,获取characteristics的值,获取characteristics的Descriptor,和Descriptor的值,写数据,读rssi,用通知的方式订阅数据等等。
4.扫描外设的服务和特征
下面的方法是确定已经连接到外设,然后才去扫描外设的服务和特征;设备下面有服务,服务下面有特征;服务有UUID,特征也有UUID;
中心回调方法:
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { // 设置外设的代理是自己
[peripheral setDelegate:self];
// 连接外设成功后,开始扫描服务 [peripheral discoverServices:nil]; }
5.确定发现了服务,调用下面的方法;设备下面有服务,服务下面有特征;服务有UUID,特征也有UUID;
外设回调方法:
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{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; } } }
6.根据服务找到了特征
针对某个服务确定发现了特征;设备下面有服务,服务下面有特征;服务有UUID,特征也有UUID;
外设回调方法:
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
// 根据服务发现了特征,可以对服务的特征进行遍历,也可以针对某个特征的UUID来进行单独处理,下面提供两种,一种是遍历全部,一种是针对某个
// 遍历全部
//获取Characteristic的值,读到数据会进入方法:
// -(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error for (CBCharacteristic *characteristic in service.characteristics){ [peripheral readValueForCharacteristic:characteristic]; } //搜索Characteristic的Descriptors,读到数据会进入方法:
// -(void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error for (CBCharacteristic *characteristic in service.characteristics){ [peripheral discoverDescriptorsForCharacteristic:characteristic]; }
// 针对某个特征,通过UUID判断这个特征
for (CBCharacteristic *characteristic in service.characteristics){ if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:UUIDSTR_ISSC_TRANS_TX]]){ NSLog(@"Discovered read characteristics:%@ for service: %@", characteristic.UUID, service.UUID); _readCharacteristic = characteristic;//保存读的特征
// 自己设置代理,让代理去执行读特征的方法 if ([self.delegate respondsToSelector:@selector(DidFoundReadChar:)]){ [self.delegate DidFoundReadChar:characteristic]; break; } } for (CBCharacteristic * characteristic in service.characteristics){ if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:UUIDSTR_ISSC_TRANS_RX]]){ NSLog(@"Discovered write characteristics:%@ for service: %@", characteristic.UUID, service.UUID); _writeCharacteristic = characteristic;//保存写的特征
// 自己设置代理,让代理去执行读特征的方法
if ([self.delegate respondsToSelector:@selector(DidFoundWriteChar:)])
[self.delegate DidFoundWriteChar:characteristic]; break; } } // 调用根据外设发现特征的代理方法; if ([self.delegate respondsToSelector:@selector(DidFoundCharacteristic:withPeripheral:error:)]) [self.delegate DidFoundCharacteristic:nil withPeripheral:nil error:nil]; }
找到服务和特征还有以下回调方法在下面:
外设回调方法:
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
[_recvData appendData:characteristic.value];
if ([_recvData length] >= 5)//已收到长度{
unsigned char *buffer = (unsigned char *)[_recvData bytes];
int nLen = buffer[3]*256 + buffer[4];
if ([_recvData length] == (nLen+3+2+2)){
//接收完毕,通知代理做事
if ([_mainMenuDelegate respondsToSelector:@selector(DidNotifyReadData)])
[_mainMenuDelegate DidNotifyReadData];
}
}
}
//搜索到Characteristic的Descriptors
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
//打印出Characteristic和他的Descriptors
NSLog(@"characteristic uuid:%@",characteristic.UUID);
for (CBDescriptor *d in characteristic.descriptors) {
NSLog(@"Descriptor uuid:%@",d.UUID);
}
}
//获取到Descriptors的值
-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error{
//打印出DescriptorsUUID 和value
//这个descriptor都是对于characteristic的描述,一般都是字符串,所以这里我们转换成字符串去解析
NSLog(@"characteristic uuid:%@ value:%@",[NSString stringWithFormat:@"%@",descriptor.UUID],descriptor.value);
}
现在先做数据交互
7.和外设做数据交互
1)写数据:
-(void)writeChar:(NSData *)data{ [_testPeripheral writeValue:data forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithResponse]; }
//写数据 -(void)writeCharacteristic:(CBPeripheral *)peripheral characteristic:(CBCharacteristic *)characteristic value:(NSData *)value{ // 打印出 characteristic 的权限,可以看到有很多种,这是一个NS_OPTIONS,就是可以同时用于好几个值,常见的有read,write,notify,indicate,
// 知知道这几个基本就够用了,前连个是读写权限,后两个都是通知,两种不同的通知方式。 // CBCharcteristicProperties是一个枚举值,有很多// 只有 characteristic.properties 有write的权限才可以写 if(characteristic.properties & CBCharacteristicPropertyWrite){ // 最好一个type参数可以为CBCharacteristicWriteWithResponse或type:CBCharacteristicWriteWithResponse,区别是是否会有反馈 [peripheral writeValue:value forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse]; }else{ NSLog(@"该字段不可写!"); } }
2)读数据:注意:数据的读分两种,一种是直接读,一种是订阅;方式的选择通过特征的characteristic.properties来规定;
订阅的方式是:
订阅方法1:
-(void)startSubscribe{ [_testPeripheral setNotifyValue:YES forCharacteristic:_readCharacteristic]; }
订阅方法2:
//设置通知 -(void)notifyCharacteristic:(CBPeripheral *)peripheral characteristic:(CBCharacteristic *)characteristic{ //设置通知,数据通知会进入:didUpdateValueForCharacteristic方法 [peripheral setNotifyValue:YES forCharacteristic:characteristic]; }
//取消通知 -(void)cancelNotifyCharacteristic:(CBPeripheral *)peripheral characteristic:(CBCharacteristic *)characteristic{ [peripheral setNotifyValue:NO forCharacteristic:characteristic]; }
8.主动断开设备
方法1:
-(void)disConnect{ if (_testPeripheral != nil){ NSLog(@"disConnect start"); [manager cancelPeripheralConnection:_testPeripheral]; } }
方法2:
//停止扫描并断开连接 -(void)disconnectPeripheral:(CBCentralManager *)centralManager peripheral:(CBPeripheral *)peripheral{ //停止扫描 [centralManager stopScan]; //断开连接 [centralManager cancelPeripheralConnection:peripheral]; }
标签:
原文地址:http://www.cnblogs.com/williamliuwen/p/5397607.html