iOS 蓝牙开发(一)

作者: Alexander | 来源:发表于2021-10-11 14:38 被阅读0次

    前期回顾

    iOS 蓝牙开发(二)
    iOS 蓝牙开发(三)
    iOS 蓝牙开发(四)

    一、基本概念

    • 1.1,中心设备(central):是发起连接的主设备,如:App。
    • 1.2,外设(peripheral):被连接的设备称为外部设备,即外设, 如:体脂称,健康手环等;
    • 1.3,服务(CBService): 外设可以包含一个或多个服务,它是用于实现装置的功能或特征数据相关联的行为集合。
    • 1.4,特征(CBCharacteristic):每个服务可以对应多个特征,它是提供外设服务进一步的细节。
    开始前先记录运行后的扫描结果
    扫描结果和lightBule的对比

    二,蓝牙相关实现

    在iOS中蓝牙相关实现都是在CoreBluetooth这个framework中的,所以我们创建一个单例类中需要先导入#import <CoreBluetooth/CoreBluetooth.h>,再后即可使用这个单例类进行管理我们蓝牙的扫描、连接、状态等实现。

    • 2.1, 初始化蓝牙CBCentralManager
            dispatch_queue_t centralQueue = dispatch_queue_create("com.acadsoc.wgazjbuletoothsdk",DISPATCH_QUEUE_SERIAL);
            NSDictionary *options = @{CBCentralManagerOptionShowPowerAlertKey : [NSNumber numberWithBool:YES], CBCentralManagerOptionRestoreIdentifierKey : @"com.hykj.wgazjbuletoothsdk"};
            self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:centralQueue options:options];
                                        
    //        self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
            self.resultStr = @"";
            self.services = [[NSMutableArray alloc]init];
    
    • 2.2,扫描周边可连接蓝牙设备
      当我们在扫描周边外设之前需要判断蓝牙是否可用,在- (void)centralManagerDidUpdateState:(CBCentralManager *)central函数中进行获取设备蓝牙的更新。

    判断手机蓝牙状态
    CBManagerStateUnknown = 0, 未知
    CBManagerStateResetting, 重置中
    CBManagerStateUnsupported, 不支持
    CBManagerStateUnauthorized, 未验证
    CBManagerStatePoweredOff, 未启动
    CBManagerStatePoweredOn, 可用

    central.state为CBManagerStatePoweredOn即可开始扫描, 具体方法[self.centralManager scanForPeripheralsWithServices:nil options:nil]当调用scanForPeripheralsWithServices:options:函数时就会实时调用其代理方法- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI

    - (void)centralManagerDidUpdateState:(CBCentralManager *)central {
        
        if (self.stateUpdateBlock) {
            self.stateUpdateBlock(central.state);
        }
        switch (central.state)
        {
            case CBManagerStatePoweredOn:
    
                NSLog(@"蓝牙已开启");
                // 根据SERVICE_UUID来扫描外设,如果不设置SERVICE_UUID,则扫描所有蓝牙设备
                // 第一个参数为CBUUID的数组,需要搜索特点服务的蓝牙设备,只要每搜索到一个符合条件的蓝牙设备都会调用didDiscoverPeripheral代理方法
                [self startScan];
                break;
            case CBManagerStatePoweredOff:
                
                NSLog(@"蓝牙已关闭, 请打开蓝牙");
                break;
            case CBManagerStateUnsupported:
                NSLog(@"设备不支持蓝牙");
                break;
            case CBManagerStateUnauthorized:
                NSLog(@"应用尚未被授权使用蓝牙");
                break;
            case CBManagerStateUnknown:
                NSLog(@"未知错误,请重新开启蓝牙");
                break;
            case CBManagerStateResetting:
                NSLog(@"蓝牙重置中");
                [self stopScan];
                break;
            default:
                NSLog(@"Central Manager did change state");
                break;
        }
    }
    
    // 开始扫描周围可用蓝牙
    - (void)startScan {
        
        //不重复扫描已发现设备
        //CBCentralManagerScanOptionAllowDuplicatesKey设置为NO表示不重复扫瞄已发现设备,为YES就是允许。
        //CBCentralManagerOptionShowPowerAlertKey设置为YES就是在蓝牙未打开的时候显示弹框
        NSDictionary *option = @{CBCentralManagerScanOptionAllowDuplicatesKey : [NSNumber numberWithBool:NO],CBCentralManagerOptionShowPowerAlertKey:[NSNumber numberWithBool:YES]};
        // 第一个参数填nil代表扫描所有蓝牙设备,第二个参数options也可以写nil
        [self.centralManager scanForPeripheralsWithServices:nil options:option];
    }
    
    // 扫描外设的代理方法,在该函数中揭开筛选出周边的蓝牙外设
    // 在蓝牙于后台被杀掉时,重连之后会首先调用此方法,可以获取蓝牙恢复时的各种状态
    - (void)centralManager:(CBCentralManager *)central
     didDiscoverPeripheral:(CBPeripheral *)peripheral
         advertisementData:(NSDictionary *)advertisementData
                      RSSI:(NSNumber *)RSSI
    {
        NSString *perName = [[NSUserDefaults standardUserDefaults] objectForKey:@"conPeripheral"];
        NSString *setOrDelNum = [[NSUserDefaults standardUserDefaults] objectForKey:@"setOrDel"];
    
        // 检索到设备
        if (self.discoverPeripheralBlcok) {
            if (self.prefixString.length > 0) {
                if ([peripheral.name hasPrefix:self.prefixString]) {
                    self.discoverPeripheralBlcok(central,peripheral,advertisementData,RSSI);
                }
            } else {
                self.discoverPeripheralBlcok(central,peripheral,advertisementData,RSSI);
            }
            [self startScan];
        }
        if ([setOrDelNum isEqualToString:@"0"]) {
            //有自动重连的设备
            [[NSNotificationCenter defaultCenter]postNotificationName:PostAutoConnectionNotificaiton object:nil];
            if ([peripheral.name isEqualToString:perName]) {
                self.peripheral = peripheral;
                [self.centralManager connectPeripheral:peripheral options:nil];
            }
        }
    }
    

    peripheral是外设类advertisementData是广播的值,一般携带设备名,serviceUUID等信息。RSSI绝对值越大,表示信号越差,设备离的越远。如果想装换成百分比强度,(RSSI+100)/1001(这是一个约数,蓝牙信号值并不一定是-100 - 0的值)

    3,连接

    蓝牙的连接是当中心设备扫描到可用外设后, 利用函数[self.centralManager connectPeripheral:peripheral options:nil];进行链接, 当函数被调用后, 就会回调其对应的代理函数。

    • 3.1,链接成功后的回调
    // 蓝牙设备连接成功
    - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
    {
        [self.centralManager stopScan];
        [self.peripheral setDelegate:self];
        [self.peripheral discoverServices:nil];
        
        //延时操作
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            if (self.connectSuccessBlock) {
                self.connectSuccessBlock(peripheral,nil,self.writeCharacteristic);
            } else {
                //返回连接成功
                if ([self.delegate respondsToSelector:@selector(automaticConnectionWithPerpheral:)]) {
                    [self.delegate automaticConnectionWithPerpheral:peripheral];
                }
            }
        });
    }
    
    • 3.2, 链接失败后的回调
    // 连接失败
    - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
    {
        if (self.connectFailureBlock) {
            self.connectFailureBlock(peripheral,error);
        }
    }
    

    4, 其他函数和代理方法

    • 4.1,断开链接
    // 断开蓝牙连接
    - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
    {
        [self disconectPeripheral];
        if (error)
            {
            NSLog(@">>> didDisconnectPeripheral for %@ with error: %@", peripheral.name, [error localizedDescription]);
            }
    }
    
    // 断开链接
    - (void)disconectPeripheral {
        
        if (self.peripheral) {
            [self.centralManager cancelPeripheralConnection:self.peripheral];
        }
    }
    
    • 4.2,停止扫描
    // 停止扫描
    - (void)stopScan
    {
        [self.centralManager stopScan];
    }
    

    5,中心管理供给外界使用方法

    // 单例
    + (ZJAWGBluetoothManager *)defaultManager;
    
    /**
     当前蓝牙的状态
     
     @param state  状态
     */
    - (void)returnBluetoothStateWithBlock:(BTStateUpdateBlock)state;
    
    /**
     搜索蓝牙外设, 每次回调表示返回一个蓝牙外设信息
     
     @param name  模糊搜索设备名称, 即目标设备名称包含的字段
     @param discoverBlock  搜索到蓝牙外设后的回调
     */
    - (void)scanPeripheralsWithName:(NSString *)name
                   discoverPeripheral:(BTDiscoverPeripheralBlock)discoverBlock;
    
    /**
     搜索蓝牙外设
     
     @param discoverBlock  搜索蓝牙外设
     */
    - (void)scanPeripheralsWithDiscoverPeripheral:(BTDiscoverPeripheralBlock)discoverBlock;
    
    /**
     连接某个蓝牙外设,并查询服务,特性,服务等描述
     
     @param peripheral  要连接的蓝牙外设
     @param complete  连接成功后的回调
     @param failure  连接失败后的回调
     */
    - (void)connectPeripheral:(CBPeripheral *)peripheral
                     complete:(BTConnectSuccessBlock)complete
                      failure:(BTConnectFailureBlock)failure;
    

    总结

    本篇笔记主要是记录如何初始化蓝牙的CBCentralManager的中心管理类,并记录如何实现扫描周边外设、如何链接、获取蓝牙当前状态。

    相关文章

      网友评论

        本文标题:iOS 蓝牙开发(一)

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