zoukankan      html  css  js  c++  java
  • CoreBluetooth

     BLE中心模式流程-coding

     

     BLE中心模式流程

    - 1.建立中心角色

    - 2.扫描外设(Discover Peripheral)

    - 3.连接外设(Connect Peripheral)

    - 4.扫描外设中的服务和特征(Discover Services And Characteristics)

        * 4.1 获取外设的services

        * 4.2 获取外设的Characteristics,获取characteristics的值,,获取CharacteristicsDescriptorDescriptor的值

    - 5.利用特征与外设做数据交互(Explore And Interact)

    - 6.订阅Characteristic的通知

    - 7.断开连接(Disconnect)

     

    ## 准备环境

     

    - 1.Xcode7.0

    - 2.手机

    - 3.外设(手机+LightBlue)

     

    #import "CentralViewController.h"
    // BLE 框架
    #import <CoreBluetooth/CoreBluetooth.h>
    
    @interface CentralViewController ()<CBCentralManagerDelegate, CBPeripheralDelegate>
    
    /** 中心管理者 */
    PROPERTYSTRONG(CBCentralManager, cMgr)
    /** 连接到的外设 */
    PROPERTYSTRONG(CBPeripheral, cPeriphery)
    
    
    @end
    
    @implementation CentralViewController
    /**
     *  懒加载
     *
     *  @ 需要调用完成对象初始化
     */
    - (CBCentralManager *)cMgr
    {
        if (!_cMgr) {
            _cMgr = [[CBCentralManager alloc] initWithDelegate:self
                                                         queue:dispatch_get_main_queue()
                                                    options:nil];
        }
        return _cMgr;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.title = @"CentralViewController";
        
        // 在ios5之前, 再通过以下方法设置背景时, 有闪屏bug
        //    self.view.backgroundColor = [UIColor colorWithPatternImage:<#(nonnull UIImage *)#>];
        //    // 解决方案
        //    self.view.layer.contents = (id)[UIColor colorWithPatternImage:[UIImage imageNamed:xxx]];
        // 0. 创建管理者对象
    #pragma mark -
    #pragma mark - - 1.建立中心角色
        [self cMgr];
        
    }
    
    // 通常在此需要 断开连接外设
    - (void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:animated];
        
        // 此处断开连接外设
        [self yf_dismissConnectedWithPeripheral:self.cPeriphery];
    }
    
    #pragma mark - CBCentralManagerDelegate
    /**
     *  @1 只要中心管理者初始化, 就会触发此方法
     */
    - (void)centralManagerDidUpdateState:(CBCentralManager *)central
    {
        switch (central.state) { // 开启
            case CBCentralManagerStateUnknown: { // 未知
                LogRed(@"CBCentralManagerState--- Unknown");
                break;
            }
            case CBCentralManagerStateResetting: { // 重置
                 LogRed(@"CBCentralManagerState--- Resetting");
                break;
            }
            case CBCentralManagerStateUnsupported: { // 不支持
                LogRed(@"CBCentralManagerState--- Unsupported");
                break;
            }
            case CBCentralManagerStateUnauthorized: { // 未授权
                LogRed(@"CBCentralManagerState--- Unauthorized");
                break;
            }
            case CBCentralManagerStatePoweredOff: { // 关闭
                LogRed(@"CBCentralManagerState---- PoweredOff");
                break;
            }
            case CBCentralManagerStatePoweredOn: { // 开启
                LogRed(@"CBCentralManagerState---  PoweredOn");
    #pragma mark -
    #pragma mark - - 2.扫描外设(Discover Peripheral)
                // 1. 搜索外设
                [self.cMgr scanForPeripheralsWithServices:nil // 通过某些服务, 筛选外设
                                                  options:nil];
                break;
            }
        }
    }
    
    
    /*!
     *  @method centralManager:willRestoreState:
     **/
    - (void)centralManager:(CBCentralManager *)central
          willRestoreState:(NSDictionary<NSString *, id> *)dict{
        
    }
    
    /*!  *****@2 常用方法 - 发现外设触发此方法
     *  @method centralManager:didDiscoverPeripheral:advertisementData:RSSI:
     *
     */
    - (void)centralManager:(CBCentralManager *)central // 中心管理者
     didDiscoverPeripheral:(CBPeripheral *)peripheral // 外设
         advertisementData:(NSDictionary<NSString *, id> *)advertisementData // 外设携带的数据
                      RSSI:(NSNumber *)RSSI // 外设信号强度
    {
        /**
        peripheral -  <CBPeripheral: 0x1666faa0, identifier = E57942BE-7941-DC11-1CD9-CEA1725456DF, name = (null), state = disconnected>
         advertisementData - {
         kCBAdvDataIsConnectable = 0;
         kCBAdvDataManufacturerData = <75004204 018020fc 8f90a492 9bfe8f90 a4929a01 00000000 0000>;
         }
         */
        LogYellow(@"%@
     -- %@
     --%@
     --%@
    ", central, peripheral, advertisementData, RSSI);
        // 需要对连接到的设备进行过滤
        // 1. 信号强度(大于35)
        // 2. 设备名(前缀 "0") [peripheral.name hasPrefix:@"0"] &&
        if((ABS(RSSI.integerValue) > 35)){
            // 在此处对我们的 advertisementData, 进行处理
            
            // 此处应该讲得到的外设存储到可变数组中
            // 以下对一个外设处理:
            // 让外设的生命周期 == VC
            self.cPeriphery = peripheral;
    #pragma mark -
    #pragma mark - - 3.连接外设(Connect Peripheral)
            // 发现外设之后进行连接
            [self.cMgr connectPeripheral:self.cPeriphery options:nil];
        }
    }
    
    /*! *****@3  中心管理者成功连接外设后, 会触发此方法
     *  @method centralManager:didConnectPeripheral:
     *
     */
    - (void)centralManager:(CBCentralManager *)central // 中心管理者
      didConnectPeripheral:(CBPeripheral *)peripheral // 外设
    {
        
        LogBlue(@"%@
     --- %@", central, peripheral);
        // 连接成功后可以进行数据交互
        // 3.1 获取外设的服务
        self.cPeriphery.delegate = self;
    #pragma mark -
    #pragma mark - - 4.扫描外设中的服务和特征(Discover Services And Characteristics)
        // 3.2 外设发现所有服务, nil代表不过滤
        // 触发: - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
        [self.cPeriphery discoverServices:nil];
    }
    
    /*! *** 外设连接失败
     *  @method centralManager:didFailToConnectPeripheral:error:
     
     */
    - (void)centralManager:(CBCentralManager *)central
    didFailToConnectPeripheral:(CBPeripheral *)peripheral
                     error:(nullable NSError *)error{
        LogGreen(@"error - %@ ", error);
    }
    
    /*! *** 断开连接
     *  @method centralManager:didDisconnectPeripheral:error:
     *
      */
    - (void)centralManager:(CBCentralManager *)central
    didDisconnectPeripheral:(CBPeripheral *)peripheral
                     error:(nullable NSError *)error{
         LogGreen(@"error - %@ ", error);
    }
    
    
    #pragma mark - CBPeripheryDelegate
    /**
     *  外设发现服务 触发此代理方法
     */
    #warning 以下方法中只要error, 都要容错处理
    - (void)peripheral:(CBPeripheral *)peripheral
    didDiscoverServices:(NSError *)error
    {
        // 容错处理
       [self dealError:error];
    #pragma mark - -   * 4.1 获取外设的services
        // 遍历外设的所有服务
        for (CBService *service in peripheral.services) {
            // 发现服务后, 让外设发现服务内部 特征
            // 触发: - (void)peripheral: didDiscoverCharacteristicsForService: error:
            [peripheral discoverCharacteristics:nil forService:service];
        }
        LogGreen(@"%@", peripheral);
    }
    
    /**
     *  发现外设服务里面特征后 触发此代理方法
     *
     *  @param peripheral 外设
     *  @param service    服务
     *  @param error      错误
     */
    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service
                 error:(NSError *)error
    {
        [self dealError:error];
    #pragma mark - -   * 4.2 获取外设的Characteristics和Descriptor
    
        for (CBCharacteristic *character in service.characteristics) {
            // 获取特征对应的描述
            // 触发: - didUpdateValueForDescriptor
            [peripheral discoverDescriptorsForCharacteristic:character];
            // 获取特征的值
            // 触发: - didUpdateValueForCharacteristic:
            [peripheral readValueForCharacteristic:character];
            
    #warning 在此处调用写入数据方法
    //        [self yf_peripheral:peripheral didWriteData:<#(NSData *)#> forCharacteristic:character];
        }
        
    }
    
    
    /**
     *  更新特征的时候就会 触发此方法
     *
     *  @param peripheral     外设
     *  @param characteristic 对应的服务的特征
     *  @param error          错误
     */
    - (void)peripheral:(CBPeripheral *)peripheral
    didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
                 error:(NSError *)error
    {
        LogRed(@"%s", __FUNCTION__);
        [self dealError:error];
    
        for (CBDescriptor *descriptor in characteristic.descriptors) {
            // 获取特征描述值
            // 触发: - didDiscoverDescriptorsForCharacteristic
            [peripheral readValueForDescriptor:descriptor];
        }
    }
    
    /**
     *  更新特征的描述的值时, 触发此方法
     *
     *  @param peripheral 外设
     *  @param descriptor 外设对应服务的特征的描述
     *  @param error      错误
     */
    - (void)peripheral:(CBPeripheral *)peripheral
    didUpdateValueForDescriptor:(CBDescriptor *)descriptor
                 error:(NSError *)error
    {
        
         LogRed(@"%s", __FUNCTION__);
        [self dealError:error];
    
        // 当前描述更新时, 直接调用此方法
        [peripheral readValueForDescriptor:descriptor];
    }
    
    
    /**
     *  发现外设服务特征中的描述, 触发此方法
     *
     *  @param peripheral     外设
     *  @param characteristic 服务对应的特征
     *  @param error          错误
     */
    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
    {
        LogRed(@"%s", __FUNCTION__);
        [self dealError:error];
        // 此处读取描述即可
        for (CBDescriptor *descriptor in characteristic.descriptors) {
            [peripheral readValueForDescriptor:descriptor];
        }
    }
    
    // 容错处理
    - (void)dealError:(NSError *)error
    {
        if (error) {
            LogRed(@"error - %@", error.localizedDescription);
            return;
        }
    }
    
    
    #pragma mark  自定义方法
    #pragma mark -
    #pragma mark - - 5.利用特征与外设做数据交互(Explore And Interact)
    /**
     *  外设 写数据到特征中
     * [注意]: 需要判断, 特征的属性是否支持写入
     */
    - (void)yf_peripheral:(CBPeripheral *)peripheral
             didWriteData:(NSData *)data
        forCharacteristic:(nonnull CBCharacteristic *)charcteristic
    {
        /**
         typedef NS_OPTIONS(NSUInteger, CBCharacteristicProperties) {
         CBCharacteristicPropertyBroadcast												= 0x01,
         CBCharacteristicPropertyRead													= 0x02,
         CBCharacteristicPropertyWriteWithoutResponse									= 0x04,
         CBCharacteristicPropertyWrite													= 0x08,
         CBCharacteristicPropertyNotify													= 0x10,
         CBCharacteristicPropertyIndicate												= 0x20,
         CBCharacteristicPropertyAuthenticatedSignedWrites								= 0x40,
         CBCharacteristicPropertyExtendedProperties										= 0x80,
         CBCharacteristicPropertyNotifyEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0)		= 0x100,
         CBCharacteristicPropertyIndicateEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0)	= 0x200
         };
         */
        LogYellow(@"char.pro = %d", charcteristic.properties);
        // 由于枚举属性是 NS_OPTIONS类型, 所有一个枚举可能对应多个类型, 判断不能用 = , 应该用&(包含)
        if (charcteristic.properties & CBCharacteristicPropertyWrite) {
            // 核心代码 ---
            [peripheral writeValue:data // 写入的数据
                 forCharacteristic:charcteristic // 特征
                              type:CBCharacteristicWriteWithResponse]; // 通过此响应记录是否成功写入
        }
    }
    
    #pragma mark -
    #pragma mark - - 6.订阅Characteristic的通知
    // 订阅通知和取消订阅
    // [注意]: 一般根据项目的具体需求确定, 以下方法在哪调用
    - (void)yf_peripheral:(CBPeripheral *)peripheral regNotifyWithCharacteristic:(nonnull CBCharacteristic *)charcteristic
    {
        // 外设为特征 订阅通知
        // 触发: - didUpdateValueForCharacteristic:方法
        [peripheral setNotifyValue:YES forCharacteristic:charcteristic];
    }
    
    - (void)yf_peripheral:(CBPeripheral *)peripheral cancelNotifyWithCharacteristic:(nonnull CBCharacteristic *)charcteristic
    {
        // 外设为特征 取消订阅通知
        // 触发: - didUpdateValueForCharacteristic:方法
        [peripheral setNotifyValue:NO forCharacteristic:charcteristic];
    }
    
    
    #pragma mark -
    #pragma mark - - 7.断开连接(Disconnect)
    - (void)yf_dismissConnectedWithPeripheral:(CBPeripheral *)peripheral
    {
        // 停止扫描
        [self.cMgr stopScan];
        
        // 断开连接
        [self.cMgr cancelPeripheralConnection:peripheral];
    }
    
    @end
    

      demo时刻 我的github  

  • 相关阅读:
    webSocket
    Spring中注解大全和应用
    原生js替换jQuery各种方法-中文版
    正则表达式-基础知识Review
    Swoole 4.1.0 正式版发布,支持原生 Redis/PDO/MySQLi 协程化
    Javascript 模块化指北
    精读《sqorn 源码》
    nodejs源码—初始化
    ubuntu显卡驱动安装
    iOS推断当前控制器是否在显示
  • 原文地址:https://www.cnblogs.com/guangleijia/p/5195293.html
Copyright © 2011-2022 走看看