二、中心设备实现CBCentralManager

2023-05-07  本文已影响0人  LucXion

Central 的规范:查找、连接外设,订阅Characteristic,通过连接的Peripheral向Characteristic发送读写请求

一、保存中心设备管理对象 CBCentralManager
    // 中心设备 CBCentralManager
    lazy var centeralManager:CBCentralManager! = nil
    // 连接的外设必须用属性强引用,否则会被系统忽略,收不到回调
    lazy var peripheral:CBPeripheral! = nil
二、初始化中心设备
/*
初始化中心设备  options有两个key
 1. CBCentralManagerOptionRestoreIdentifierKey (用于持久连接的): 中心设备UID,不能变,通过UID来恢复状态,可以通过命令行生成128位标准uid $uuidgen
 2. [CBCentralManagerOptionShowPowerAlertKey:NSNumber(booleanLiteral: true)]

默认nil为主线程,设置了线程,所有的代理回调都会在同一个线程里回调,通过主线程连接不会造成阻塞
*/
  centeralManager = CBCentralManager.init(delegate: self, queue: nil ,options: nil)
三、CBCentralManagerDelegate:

连接外设,保存外设,并通过外设扫描服务

// 1.中心设备初始化完成
    func centralManagerDidUpdateState(_ central: CBCentralManager){
        // 在central.state == .poweredOn的状态下,根据服务UUID来搜索外设
        central.scanForPeripherals(withServices: [CBUUID.init(string: s1UUID),CBUUID.init(string: s2UUID)])
    }
// 2.搜索到拥有 s2UUID服务 的外设广播
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber){
        // 根据 peripheral.name 来进一步筛选外设,连接
        // 关键的一步,根据名称+服务找到对应的外设后,将外设保存到本地再进行连接,否则会没有任何响应,在这里还可以加入信号强度的判断 RSSI
        self.peripheral = peripheral
        // 关闭扫描
        central.stopScan()
        // 尝试连接外设
        central.connect(peripheral)
    }
// 3. 接下来就是连接外设结果的相关代理方法
   func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        //连接外设成功 
        peripheral.delegate = self
        //通过外设来扫描外设服务,接下来就会走外设代理 CBPeripheralDelegate,来与特征进行一系列交互
        peripheral.discoverServices([CBUUID.init(string: s1UUID)])
    }
    
    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
        // 连接外设失败
    }
    
    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
        // 连接已经被断开
    }
    
    func centralManager(_ central: CBCentralManager, connectionEventDidOccur event: CBConnectionEvent, for peripheral: CBPeripheral){
        // 状态发生改变
    }
四、CBPeripheralDelegate
// 1.中心设备成功连接外设后,通过外设扫描服务的回调
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
         // 在这个回调里,可以拿到外设的服务对象集合
         for element in peripheral.services! {
                // 通常你可以做两件事,1.发现子服务
                peripheral.discoverIncludedServices([CBUUID.init(string: s2UUID)], for: element)
                // 2.直接扫描服务中的特征
                peripheral.discoverCharacteristics([CBUUID.init(string: s1c1UUID),CBUUID.init(string: s1c2UUID)],for:element)
         }
    }

// 1.2 扫描到子服务,接着扫描子服务特征
    func peripheral(_ peripheral: CBPeripheral, didDiscoverIncludedServicesFor service: CBService, error: Error?) {
        appendCenteralInfo(content: "didDiscoverIncludedServicesFor成功读取到服务\(service.includedServices)")
        for element in service.includedServices! {
            appendCenteralInfo(content: "我发现了子服务\(element.uuid)")
            // 去查询子服务的特征
            peripheral.discoverCharacteristics([CBUUID.init(string: s2c1UUID)], for: element)
        }
    }

// 2.扫描到特征,可以读、写、订阅特征
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        for characteristicItem in service.characteristics! {
            if(characteristicItem.uuid.isEqual(CBUUID.init(string: s1c1UUID))){
                // 只要是扫描服务特征,特征同一个回调,不区分主服务、子服务
                // 这些请求,会生成CBATTRequest对象,并由外设捕获
                peripheral.readValue(for: characteristicItem)
            }else if(characteristicItem.uuid.isEqual(CBUUID.init(string: s1c2UUID))){
                peripheral.setNotifyValue(true, for: characteristicItem)
            }else if(characteristicItem.uuid.isEqual(CBUUID.init(string: s2c1UUID))){
                peripheral.writeValue("我写信给你".data(using: .utf8)!, for: characteristicItem, type: .withResponse)
            }
        }
    }
// 3.1 读取到特征值的回调
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        let data = characteristic.value
        if let data = characteristic.value {
            let str :String = String.init(data: data, encoding: .utf8) ?? ""
        }
    }
// 3.2 订阅到特征值的回调
    func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
        let data = characteristic.value
        if let data = characteristic.value {
            let str :String = String.init(data: data, encoding: .utf8) ?? ""
        }
    }
// 3.3 写入特征值成功的回调
    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
    }
上一篇下一篇

猜你喜欢

热点阅读