core bluetooth详细介绍

遵守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];

或者是:

manager = [[CBCentralManager alloc]initWithDelegate:self queue:dispatch_get_main_queue()];

 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];
     [manager connectPeripheral:peripheral options:nil];
NSLog(@"dicoveredPeripherals:%@", _dicoveredPeripherals);

 if ([peripheral.name hasPrefix:@"P"]){
            //找到的设备必须持有它,否则CBCentralManager中也不会保存peripheral,那么CBPeripheralDelegate中的方法也不会被调用!!
            [peripherals addObject:peripheral];
            // 发现设备后就连接,根据外设的名臣连接设备
            [manager connectPeripheral:peripheral options:nil];
        } 
    }
}

// 当我们查找到Peripheral端时,我们可以停止查找其它设备,以节省电量


    //    [_definecentermanager stopScan];

 

上面的代码可以优化成,连接指定的外设名称

一个主设备最多能连7个外设,每个外设最多只能给一个主设备连接,连接成功,失败,断开会进入各自的委托

4.扫描外设的服务和特征

下面的方法是确定已经连接到外设,然后才去扫描外设的服务和特征;设备下面有服务,服务下面有特征;服务有UUID,特征也有UUID;

中心回调方法:连接外设成功

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;//连接外设成功的委托

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
  // 设置外设的代理是自己    
  [peripheral setDelegate:self];
  // 连接外设成功后,开始扫描服务   [peripheral discoverServices:nil]; }

 中心回调方法:连接外设失败

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;//外设连接失败的委托

中心回调方法:断开外设连接

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;//断开外设的委托

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

上面一般回调的是CBCentralManagerDelegate代理方法,一般是CentralManager开头;

下面开始扫描服务和特征时,回调的是CBPeripheralDelegate代理方法,一般是Peripheral开头;

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

分界线:

设备连接成功后,就可以扫描设备的服务了,同样是通过委托形式,扫描到结果后会进入委托方法。但是这个委托已经不再是主设备的委托(CBCentralManagerDelegate),而是外设的委托(CBPeripheralDelegate,这个委托包含了主设备与外设交互的许多 回调方法,包括获取services,获取characteristics,获取characteristics的值,获取characteristicsDescriptor,和Descriptor的值,写数据,读rssi,用通知的方式订阅数据等等。

5.确定发现了服务,调用下面的方法;设备下面有服务,服务下面有特征;服务有UUID,特征也有UUID;

外设回调方法:

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
  
for (CBService *service in peripheral.services){

    if ([service.UUID isEqual:[CBUUID UUIDWithString:@"?"]]){

            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];
}
原文地址:https://www.cnblogs.com/williamliuwen/p/5397607.html