美文网首页@IT·互联网工具癖程序员
CoreBluetooth.framework(二)

CoreBluetooth.framework(二)

作者: 羊妞麻麻 | 来源:发表于2017-04-28 10:49 被阅读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两个类。

    相关文章

      网友评论

        本文标题:CoreBluetooth.framework(二)

        本文链接:https://www.haomeiwen.com/subject/dnxnzttx.html