@IT·互联网工具癖程序员

CoreBluetooth.framework(二)

2017-04-28  本文已影响49人  羊妞麻麻

1、通过扫描寻找服务

//允许iOS设备作为客户端从一个蓝牙设备读取数据
self.manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:@{CBCentralManagerOptionShowPowerAlertKey:@(NO)}];

首先扫描外围设备

 //从一个蓝牙设备读取数据 开始扫描蓝牙  是否允许中央设备多次收到曾经监听到的设备的消息,这样来监听外围设备联接的信号强度,以决定是否增大广播强度,为YES时会多耗电
    [self.manager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:_serviceUUID]] options:@{CBCentralManagerScanOptionAllowDuplicatesKey : [NSNumber numberWithBool:YES]}];

scanForPeripheralsWithServices:方法使用了一个服务数组作为参数,扫描周边地区广播这些服务的外围设备,如果使用Nil作为参数,会扫描所有可用的外围设备,不过这样会很慢。

CBCentralManager这个类有一个委托CBCentralManagerDelegate这个委托可以通知你已发现的外围设备、服务、服务的特性和数值变化。如果你的蓝牙么有打开,会在CBCentralManagerDelegate的centralManagerDidUpdateState方法中收到回调,这个方法也要开始扫描外围设备。

#pragma mark - CBCentralManagerDelegate
/**
 *当蓝牙状态改变的时候就会调用这个方法
 */
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
    switch (central.state) {
        case CBManagerStatePoweredOn:
            //正在重置状态 可以使用GCD
        case CBManagerStateResetting:
        {
            dispatch_async(dispatch_get_main_queue(), ^{
                
                if (self.connectState == DoorOpenStateScanning)
                    [self starScanPeripheral];
            });
            
        }
            break;
            //
        case CBManagerStateUnknown:
        {
        }
            break;
        default:
        {
            [self stopConnect];
        }
            break;
    }
}

找到外围设备后,通过CBCentralManagerDelegate的didDiscoverPeripheral:方法可以获取外围设备的详细信息。

2.连接设备
找到外围设备后,下一步就是连接外围设备并发现他提供的服务。

/**
 *发现服务
 */
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
//处理业务逻辑
//连接外围设备
    [central connectPeripheral:peripheral options:nil];
}

在连接外围设备之前应该先保留之,因为ARC编译器会释放外围设备对象而导致其无法连接。可以加入到一个数组里面来保留。

3.直接获取外围设备
如果你知道外围设备的标识符,可以使用这个方法扫描。这个方法是iOS7加入的。
先把外围设备列表加到数组,保存这个数组,每次扫描设备之前先尝试连接已知外围设备是个好习惯。扫描比较费电,应该避免。拿到外围设备的指针后,就可以直接连接了。

- (NSArray<CBPeripheral *> *)retrievePeripheralsWithIdentifiers:(NSArray<NSUUID *> *)identifiers NS_AVAILABLE(NA, 7_0);

4.发现服务
建立连接的尝试可能成功也可能失败,如果成功就会调用这个委托方法。下一步是发现外围设备提供的服务。

/**
 *连接成功之后调用的方法,然后开始扫描
 *peripheral 成功 扫描外设中的服务和特征,连接上外围设备的时候回调用这个方法
 * NSLog(@">>>连接到名称为(%@)的设备-成功",peripheral.name);
 */
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    self.peripheral = peripheral;
    _isConnect = YES;
    self.connectState = DoorOpenStateConnected;
    //设置的peripheral委托CBPeripheralDelegate
    [peripheral setDelegate:self];  //查找服务
    //扫描外设Services,成功后会进入方法
    [peripheral discoverServices:nil];
}

外围设备提供的服务列表是通过CBPeripheralDelegate一个委托方法通知的,从外围设备的services属性中可以获取服务列表。

#pragma mark - CBPeripheralDelegate

/**
 *  扫描外设Services,成功后会进入方法
 *  发现外围设备的服务会来到该方法(扫描到服务之后直接添加peripheral的services)
 */
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
    if (error)
    {
        if ([self.delegate respondsToSelector:@selector(openDoorFailed:error:)]) {
            [self.delegate openDoorFailed:self.curDoor error:error];
        }
        [self stopConnect];
        return;
    }
    
    BOOL bFind = NO;
    for (CBService *service in peripheral.services)
    {
        //发现服务
        if ([service.UUID.UUIDString isEqualToString:@"FFF0"])
        {
             NSLog(@"====%@------%@+++++++",service.UUID.UUIDString,self.peripheral.identifier);
             // characteristicUUIDs : 可以指定想要扫描的特征(传nil,扫描所有的特征)
            _service = service;
            [peripheral discoverCharacteristics:nil forService:service];
            bFind = YES;
            break;
        }
    }
    if (!bFind) {
        [self stopConnect];
        if ([self.delegate respondsToSelector:@selector(openDoorFailed:error:)]) {
            NSError *error1 = [NSError errorWithDomain:@"openDoorFailed" code:LeEGNotDiscoverServices userInfo:@{NSLocalizedDescriptionKey:@"没有找到指定蓝牙服务"}];
            [self.delegate openDoorFailed:self.curDoor error:error1];
        }
    }
}

5.发现特征
特性:打开/关闭服务或者是读取服务的当前值。(如上)返回已经发现的特性的委托方法。

/**
 * 找到了设备的服务然后扫描特征
 */
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error {

     NSLog(@"发现外围设备的特征");
    
    for (CBCharacteristic *characteristic in service.characteristics)
    {
         NSLog(@"====%@------+",characteristic.UUID.UUIDString);
        //发现特征
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FFF1"]]) {
            //          NSLog(@"监听:%@",characteristic);//监听特征
            // 拿到特征,和外围设备进行交互
            [self.peripheral setNotifyValue:YES forCharacteristic:characteristic];
            
            self.charWrite = characteristic;
        } else if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FFF4"]]) {
            [self.peripheral setNotifyValue:YES forCharacteristic:characteristic];
            self.charRead = characteristic;
            
        }
    }
    if (self.charRead && self.charWrite) {
        if (![self need3DES:self.curDoor]) {
            [self sendOpenDoorCommand];
        } else {
            // 拿到特征,和外围设备进行交互 保存写的特征
            [self WriteValue:@"BB"];
            self.connectState = DoorOpenStateWaitKey;
        }
    } else {
        if ([self.delegate respondsToSelector:@selector(openDoorFailed:error:)]) {
            NSError *error1 = [NSError errorWithDomain:@"openDoorFailed" code:LeEGNotDiscoverCharacteristics userInfo:@{NSLocalizedDescriptionKey:@"特征值缺失"}];
            [self.delegate openDoorFailed:self.curDoor error:error1];
        }
        [self stopConnect];
        return;
    }

}

在下面的方法里面,我们会接收到数据更新或者改变的消息

/**
 * 设置通知,数据通知会进入:didUpdateValueForCharacteristic方法
 */
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error {}

数值变化已NSData形式发送过来的。需要根据情况进行转换实际的数据。

6.创建自己的外围设备
CoreBluetooth.framework在iOS7中增加了 CBPeripheralManager 和 CBCentral两个类。

上一篇下一篇

猜你喜欢

热点阅读