美文网首页
iOS封装蓝牙中心管理者类

iOS封装蓝牙中心管理者类

作者: oldSix_Zhu | 来源:发表于2017-09-17 13:24 被阅读738次

    承接上文iOS蓝牙中心端开发

    目前github上有很多封装的iOS蓝牙库,稍微改改就可以拿来直接使用,不必在控制器中实现那一套的<CBCentralManagerDelegate><CBPeripheralDelegate>协议中的方法。
    本篇文章记一下我是如何一步步进行封装蓝牙中心管理者类的,也让看客能够很快上手,自己封装一个,毕竟自己写的代码改起来顺手。

    1、了解其他封装
    2、我的封装

    1、了解其他封装

    我根据封装的库中对数据的处理方式,把库简单地分为三级:

    第一级:CJBlueTooth这种,就是简单的封装了个中心管理类,把两个协议的方法实现了,还加上了SVProgressHUD。
    数据处理方面,在didUpdateValueForCharacteristic方法中用的属性。把外设发送的数据存为属性,然后在使用蓝牙的控制器中用一个dispatch_after访问属性拿到数据。

    第二级: ALBLEFramework这种,在第一级的基础上,加了协议,设置了代理。
    数据处理方面,在didUpdateValueForCharacteristic方法中用的代理。让使用蓝牙的控制器成为代理,实现协议中的方法来拿到外设发送的数据。

    第三级:BabyBluetooth这种,在第一级的基础上,把代理方法中各值用block传了出去,还可以使用链式语法,很直观。
    数据处理方面,在didUpdateValueForCharacteristic方法中是用的通知以及block。

    BabyBluetooth这个库在github上是star最多的库,但我并没有用,除非你真的很赶时间,可以直接拿来用。
    因为在我从零开始做蓝牙的时候,原生的代理方法虽然繁琐,但一系列方法反而比较易懂,建议刚开始做蓝牙的小伙伴先把原生的各个方法搞明白,在实现功能的基础上,有时间了再去研究这个库,模仿封装一个。
    而我自己是封装第二级的这种,我认为已经够用了,对于一个APP来说,没必要像第三级那样。


    2、我的封装
    第一步:新建一个NSObject类,实现<CBCentralManagerDelegate><CBPeripheralDelegate>协议中的方法

    1、新建一个NSObject类,我起的名字是OSZBLECenterManager
    2、引入框架#import <CoreBluetooth/CoreBluetooth.h>
    3、遵循协议@interface OSZBLECenterManager : NSObject<CBCentralManagerDelegate, CBPeripheralDelegate>
    4、设置属性。主要是保存外设和特征。
    5、暴露方法。比如初始化,开始连接,写入数据等需要在控制器中使用的方法。

    第二步:创建协议,设置代理

    创建一个协议,主要包括在实现<CBCentralManagerDelegate><CBPeripheralDelegate>协议中的方法时外面控制器要实现的方法。

    肯定要有更新控制器UI的方法,例如等待指示器的显示与消失。
    肯定还要包括一个把数据传给外面控制器的方法。
    因为在监听外设发送数据的时候,需要把数据实时传给外面的控制器,而不是让外面的控制器主动访问外设传了哪些数据,这点很重要。

    也可以使用通知和block,通知还需要移除,block稍微有些麻烦,我这里就是简单的用下代理,不想用代理也可以。

    OSZBLECenterManager.h

    #import <Foundation/Foundation.h>
    #import <CoreBluetooth/CoreBluetooth.h>
    
    @protocol OSZBLECenterManagerDelegate <NSObject>
    
    @optional
    //点击连接按钮
    - (void)didClickStart;
    //连接成功
    - (void)BLEConnectSucceed;
    //收到的数据
    - (void)receivedValue:(NSData *)data;
    
    @end
    
    @interface OSZBLECenterManager : NSObject<CBCentralManagerDelegate, CBPeripheralDelegate>
    //代理
    @property (nonatomic, weak) id<OSZBLECenterManagerDelegate> delegate;
    //中心
    @property (nonatomic,strong) CBCentralManager *centralManager;
    //外设
    @property (nonatomic,strong) CBPeripheral *peripheral;
    //特征
    @property (nonatomic, strong) CBCharacteristic *characteristic;
    
    //初始化
    + (instancetype)sharedInstance;
    //开始连接
    - (void)startConnect;
    //断开连接
    - (void)endConnect;
    //读数据
    - (void)readFromPeripheral;
    //写数据
    - (void)writeToPeripheralWith:(NSString *)name;
    //监听数据
    - (void)notifyPeripheral;
    
    @end
    

    OSZBLECenterManager.m

    #import "OSZBLECenterManager.h"
    @implementation OSZBLECenterManager
    
    + (instancetype)sharedInstance
    {
        static OSZBLECenterManager *manager = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            manager = [[OSZBLECenterManager alloc]init];
        });
        return manager;
    }
    
    
    - (void)startConnect
    {
        if (self.delegate && [self.delegate respondsToSelector:@selector(didClickStart)])
        {
            //控制器更新UI
            [self.delegate didClickStart];
        }
        
        //初始化中心端,开始蓝牙模块
        self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
        self.centralManager.delegate = self;
    }
    
    //断开连接
    - (void)endConnect
    {
        [self.centralManager cancelPeripheralConnection:self.peripheral];
    }
    
    
    #pragma mark - CBCentralManagerDelegate
    // 状态更新后触发
    -(void)centralManagerDidUpdateState:(CBCentralManager *)central
    {
        switch (central.state) {
            case CBCentralManagerStatePoweredOff:
                break;
            case CBCentralManagerStatePoweredOn:
                break;
            case CBCentralManagerStateResetting:
                break;
            case CBCentralManagerStateUnauthorized:
                break;
            case CBCentralManagerStateUnknown:
                break;
            case CBCentralManagerStateUnsupported:
                break;
            default:
                break;
        }
        [central scanForPeripheralsWithServices:nil options:nil];
    }
    
    
    // 扫描到外部设备后触发的代理方法//多次调用的
    - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(nonnull CBPeripheral *)peripheral advertisementData:(nonnull NSDictionary<NSString *,id> *)advertisementData RSSI:(nonnull NSNumber *)RSSI
    {
        //    扫描到的外部设备
        NSString *msg = [NSString stringWithFormat:@"信号强度: %@, 外设: %@", RSSI, peripheral];
        NSLog(@"%@",msg);
        if ([peripheral.name isEqualToString:@"CSR Serial Server"])
        {
            //连接外部设备
            self.peripheral = peripheral;
            [central connectPeripheral:peripheral options:nil];
            //停止搜索
            [central stopScan];
        }
    }
    
    
    //连接失败
    - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
    {
        NSLog(@"%@",error.localizedDescription);
        [self.centralManager connectPeripheral:self.peripheral options:nil];
    }
    
    
    // 当中心端连接上外设时触发
    - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
    {
        NSLog(@"连接上外设");
        self.peripheral.delegate = self;
        [peripheral discoverServices:nil];
    }
    
    
    //如果连接上的两个设备突然断开了,程序里面会自动回调下面的方法
    -   (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
    {
        NSLog(@"设备断开重连");
        [self.centralManager connectPeripheral:self.peripheral options:nil];
        //当断开时做缺省数据处理
    }
    
    
    #pragma mark - CBPeripheralDelegate
    // 外设端发现了服务时触发
    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
    {
        NSLog(@"%@",peripheral.services);
        if (error)
        {
            NSLog(@"%@",error.localizedDescription);
            return;
        }
        for (CBService *service in peripheral.services)
        {
            //只找有用的服务
            if ([service.UUID.description isEqualToString:@"服务UUID名称"])
            {
                [peripheral discoverCharacteristics:nil forService:service];
            }
        }
    }
    
    
    //从服务获取特征
    -(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
    {
        NSLog(@"%@",service.characteristics);
        for (CBCharacteristic *characteristic in service.characteristics)
        {
            // -------- 读特征的处理 --------
            if ([characteristic.UUID.description isEqualToString: @"读特征名称"])
            {
                NSLog(@"处理读特征");
                [self.peripheral readValueForCharacteristic:characteristic];
            }
            
            // -------- 写特征的处理 --------
            if ([characteristic.UUID.description isEqualToString: @"写特征名称"])
            {
                NSLog(@"处理写特征");
                //向外设发送0001命令
                NSData *data = [@"0001" dataUsingEncoding:NSUTF8StringEncoding];
                [self.peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
                self.characteristic = characteristic;
            }
            
            // -------- 订阅特征的处理 --------
            if ([characteristic.UUID.description isEqualToString: @"订阅特征名称"])
            {
                NSLog(@"处理了订阅特征");
                [peripheral setNotifyValue:YES forCharacteristic:characteristic];
            }
        }
    }
    
    
    //收到数据
    - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
    {
    //    NSLog(@"%@",characteristic.value);
        //控制器去处理
        if (self.delegate && [self.delegate respondsToSelector:@selector(receivedValue:)])
        {
            [self.delegate receivedValue:characteristic.value.copy];
        }
        
    }
    
    
    // 写特征CBCharacteristicWriteWithResponse的数据写入的结果回调
    - (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
    {
        if (error) {
            NSLog(@"数据写入失败: %@", error);
        } else {
            NSLog(@"数据写入成功");
            [peripheral readValueForCharacteristic:characteristic];
        }
    }
    
    #pragma mark - VCMethod 
    //读数据
    - (void)readFromPeripheral
    {
        NSLog(@"读数据");
        [self.peripheral readValueForCharacteristic:self.characteristic];
    }
    
    //写数据
    - (void)writeToPeripheralWith:(NSString *)instruct
    {
        NSLog(@"写数据");
        NSData *data = [[OSZDataTool sharedTool] hexToBytes:instruct];
        [self.peripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithoutResponse];
    }
    
    //监听数据
    - (void)notifyPeripheral
    {
        NSLog(@"监听数据");
        [self.peripheral setNotifyValue:YES forCharacteristic:self.characteristic];
    }
    
    
    第三步:在控制器中实现

    然后在要使用蓝牙的控制器中,设置属性强引用@property (nonatomic, strong) OSZBLECenterManager *manager;
    遵循协议<OSZBLECenterManagerDelegate>
    在你想要启动蓝牙的方法里加入以下代码(比如“连接外设”按钮),启动蓝牙中心管理类,并设置代理,然后实现代理方法就可以了。

    OSZBLECenterManager *manager = [OSZBLECenterManager sharedInstance];
    manager.delegate = self;
    self.manager = manager;
    [manager startConnect];
    

    可以看到我封装的很简单,但主要的功能都有。主要是为了方便理解,可以自行扩展功能。
    如果有帮助到你,给个喜欢吧:-D


    2018.6.25
    这个是我用的数据转化工具类,可能并不是最好的,如果使用中有什么问题请留言给我改进,thanks
    OSZDataTool下载地址:https://github.com/oldSixZhu/OSZDataTool

    相关文章

      网友评论

          本文标题:iOS封装蓝牙中心管理者类

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