iOS CoreBluetoothios 底层iOS

iOS 蓝牙开发(一)

2021-10-11  本文已影响0人  Alexander

前期回顾

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

一、基本概念

开始前先记录运行后的扫描结果
扫描结果和lightBule的对比

二,蓝牙相关实现

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

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

判断手机蓝牙状态
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];进行链接, 当函数被调用后, 就会回调其对应的代理函数。

// 蓝牙设备连接成功
- (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];
            }
        }
    });
}
// 连接失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    if (self.connectFailureBlock) {
        self.connectFailureBlock(peripheral,error);
    }
}

4, 其他函数和代理方法

// 断开蓝牙连接
- (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];
    }
}
// 停止扫描
- (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的中心管理类,并记录如何实现扫描周边外设、如何链接、获取蓝牙当前状态。

上一篇下一篇

猜你喜欢

热点阅读