【问题标题】:iOS BluetoothLE: CBCentralManager Unsubscribes From UpdatesiOS BluetoothLE:CBCentralManager 取消订阅更新
【发布时间】:2017-11-04 13:06:09
【问题描述】:

我将 Mac 设置为蓝牙配件,使用 CoreBluetooth 作为CBPeripheralManager。 Mac 正在针对一组特征 CBUUID 做广告,一旦它有订阅者,我单击一个按钮以每半秒流式传输一个 UTF-8 编码的时间戳。

我将 iPhone 设置为CBCentralManager,订阅了相应的特性。每次收到数据并且应用程序处于活动状态时,我都会使用解码的时间戳更新 iPhone 的 UI。 bluetooth-central 后台模式在.plist 文件中设置。

iPhone 继续调试打印并更新 UI 的时间戳约 25 秒,然后停止。无论应用程序是在前台还是后台,都会发生这种情况。 编辑:此时CBPeripheralManager 收到didUnsubscribeFrom characteristic 回调。我看不出有任何理由会调用 didUnsubscribeFrom,不知道为什么总是在 25 秒后。

CBPeripheralManager 继续愉快地发送它的时间戳。 CBPeripheralManagerupdateData(_:for:onSubscribedCentrals:) 调用的返回值始终为 true,表示队列永远不会满。

这里涉及到很多代码,展示了最相关的。

来自CBCentralManager 应用程序:

 func centralManagerDidUpdateState(_ central: CBCentralManager) {
     print(central.state.rawValue)
     centralManager.scanForPeripherals(withServices: [timeUUID], options: nil)
     print("scanning")
 }

 func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
     peripheral.delegate = self
     peripheral.discoverServices(nil)

     print("connected")
 }

 func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
     print(peripheral.name as Any)
     print(advertisementData[CBAdvertisementDataServiceUUIDsKey] as! Array<CBUUID>)
     self.peripheralController = peripheral

     self.centralManager.connect(peripheral, options: nil)
 }

 func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {

    if service.uuid.uuidString == timeUUID.uuidString {
        peripheralController.setNotifyValue(true, for: service.characteristics!.first!)
        peripheralController.readValue(for: service.characteristics!.first!) // EDIT: This was the offending line
    }
 }

 func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {

    if characteristic.uuid.uuidString == timeUUID.uuidString {
        if let valueFrom = characteristic.value  {
            if let this = String(data: valueFrom, encoding: .utf8) {
                if UIApplication.shared.applicationState == .active {
                    label.text = this
                    print("ACTIVE \(this)")
                } else if UIApplication.shared.applicationState == .background {
                    print("BACKGROUND \(this)")
                } else if UIApplication.shared.applicationState == .inactive {
                    print("INACTIVE \(this)")
                }
            }
        }
    }
 }

来自CBPeripheralManager 应用程序:

func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
    myCharacteristic = CBMutableCharacteristic(type: myServiceUUID, properties: [CBCharacteristicProperties.read, CBCharacteristicProperties.notify], value: nil, permissions: CBAttributePermissions.readable)
    let myService = CBMutableService(type: myServiceUUID, primary: true)
    myService.characteristics = [myCharacteristic]
    bluetoothController.add(myService)
}

func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didSubscribeTo characteristic: CBCharacteristic) {
    print(characteristic.uuid)
    subscriber = central
}

func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didUnsubscribeFrom characteristic: CBCharacteristic) {
    print(characteristic)
    print("unsubscribe")
}

func repeatAdvertisement() {
    timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [unowned self] (timerRef) in
        guard let maybeTimer = self.timer, maybeTimer.isValid else { return }
        let datum = Date()
        let stringFromDate = self.dateFormatter.string(from: datum)
        let data = stringFromDate.data(using: .utf8)
        print(data!.count)
        //        myCharacteristic.value = data
        let myService = CBMutableService(type: self.myServiceUUID, primary: true)
        myService.characteristics = [self.myCharacteristic]
        let did = self.bluetoothController.updateValue(data!, for: self.myCharacteristic as! CBMutableCharacteristic, onSubscribedCentrals: [self.subscriber])
        print("timed \(stringFromDate) \(did)")
    }


}


func advertise() {
    if timer == nil {
        repeatAdvertisement()
    } else {
        timer?.invalidate()
        timer = nil
    }
}

如果您需要任何其他信息,请告诉我。

【问题讨论】:

    标签: ios swift bluetooth-lowenergy core-bluetooth cbcentralmanager


    【解决方案1】:

    好吧,看在上帝的份上。问题是 peripheralController.readValue(for: service.characteristics!.first!) 这行我根据一些示例代码在应用程序中有那行,嗯,这是不必要的。

    显然对readValue(for:) 的调用会导致某种超时。我从应用程序中编辑了该行,它愉快地不断更新。

    留下问题并添加此答案,以防有一天有人最终面临同样的事情。

    【讨论】:

      猜你喜欢
      • 2019-04-09
      • 2018-03-25
      • 1970-01-01
      • 2021-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-13
      相关资源
      最近更新 更多