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:)會導致某種超時。我編輯了該應用程序的線路,並愉快地進行更新。

留下問題並添加此答案,以防有人終有一天面臨同樣的事情。