0

我有一个mac设置为使用CoreBluetooth作为CBPeripheralManager的蓝牙配件。 Mac在设置特征CBUUID上进行广告宣传,一旦它拥有订阅者,我点击一个按钮以每半秒流传输一个UTF-8编码的时间戳。iOS BluetoothLE:CBCentralManager取消订阅更新

我有一个iPhone设置为CBCentralManager订阅适当的特征。每次接收数据和应用程序处于活动状态时,我都会使用解码的时间戳更新iPhone的UI。 bluetooth-central背景模式在.plist文件中设置。

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

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

这里涉及很多代码,显示最相关的代码。

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 
    } 
} 

让我知道你还需要什么。

回答

0

好吧,看在上帝的份上。问题是行peripheralController.readValue(for: service.characteristics!.first!)我在应用程序的基础上的一些示例代码的行,以及它是没有必要的。

很明显,致电readValue(for:)会导致某种超时。我编辑了该应用程序的线路,并愉快地进行更新。

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