在后台扫描BLE外设的RSSI

时间:2020-06-14 19:45:52

标签: ios swift iphone bluetooth core-bluetooth

更新15/6-1-替代方法

根据Paulw的建议,我改变了策略,而不是发现外围设备,而是与外围设备连接,并且当外围设备或中央设备处于前台时,它都工作正常。在以下情况下会发生此问题:

1)我在代表呼叫上设置通知。

2)外围和中央都在背景中。

3)当我靠近它们时,我看不到任何代表呼叫。

4)一旦将外围设备或中央设备置于前台,我就接到didDiscover的电话,即使我现在将应用程序都放在后台的两部手机中,一切也都可以正常工作。

简而言之,如果两个都处于后台状态,则中央不会发现外围设备。 这是这两部分的代码:

    func startAsPeripheral() {
        peripheralManager = CBPeripheralManager(delegate: self, queue: DispatchQueue.global(qos: .background))
    }

    func startAsCentral() {
        centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.global(qos: .background))
    }

}

extension BluetoothManager: CBCentralManagerDelegate {

    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        LogManager.shared.log(object: "Central state update")
        LogManager.shared.log(object: central.state)
        if central.state != .poweredOn {
            LogManager.shared.log(object: "Central is not powered on")
        } else {
            LogManager.shared.log(object: "Central scanning for: " + self.serviceUUID.uuidString);
            self.centralManager.scanForPeripherals(withServices: [self.serviceUUID], options: [CBCentralManagerScanOptionAllowDuplicatesKey : false])
        }
    }

    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        self.centralManager.stopScan()
        self.peripheral = peripheral
        self.peripheral.delegate = self
        self.centralManager.connect(self.peripheral, options: nil)
        let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String
        LogManager.shared.log(object: "Peripheral (" + (name ?? "unknown") + "): " + RSSI.stringValue)
    }

    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        if peripheral == self.peripheral {
            LogManager.shared.log(object: "Connected.")
            peripheral.discoverServices([serviceUUID])
        }
    }

    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
        if peripheral == self.peripheral {
            LogManager.shared.log(object: "Disconnected")
            self.peripheral = nil
            LogManager.shared.log(object: "Central scanning for: " + self.serviceUUID.uuidString);
            self.centralManager.scanForPeripherals(withServices: [self.serviceUUID], options: [CBCentralManagerScanOptionAllowDuplicatesKey: false])
        }
    }


}

extension BluetoothManager: CBPeripheralDelegate {
    func peripheral( _ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        LogManager.shared.log(object: "Services: \(peripheral.services!)")
        for service in peripheral.services! {
            peripheral.discoverCharacteristics(nil, for: service)
        }
    }

    func peripheral( _ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        LogManager.shared.log(object: "Characteristics: \(service.characteristics!)")
    }

}


extension BluetoothManager: CBPeripheralManagerDelegate {
    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        switch peripheral.state {
        case .unknown:
            LogManager.shared.log(object: "Bluetooth Device is UNKNOWN")
        case .unsupported:
            LogManager.shared.log(object: "Bluetooth Device is UNSUPPORTED")
        case .unauthorized:
            LogManager.shared.log(object: "Bluetooth Device is UNAUTHORIZED")
        case .resetting:
            LogManager.shared.log(object: "Bluetooth Device is RESETTING")
        case .poweredOff:
            LogManager.shared.log(object: "Bluetooth Device is POWERED OFF")
        case .poweredOn:
            LogManager.shared.log(object: "Bluetooth Device is POWERED ON")
            let service = serviceUUID
            let myService = CBMutableService(type: service, primary: true)
            let writeCharacteristics = CBMutableCharacteristic(type: characteristricUUID, properties: .write, value: nil, permissions: .writeable)
            myService.characteristics = [writeCharacteristics]
            peripheralManager.add(myService)
            peripheralManager.startAdvertising([CBAdvertisementDataLocalNameKey : "Spacedemic", CBAdvertisementDataServiceUUIDsKey : [service]])
            LogManager.shared.log(object: "Started Advertising")
        default:
            LogManager.shared.log(object: "Unknown State")
        }
    }
}

原始问题

我有一个用于跟踪联系人的应用程序。我将其配置为既可以在中央也可以在外围使用,都应该在后台和前台工作。这是用于联系人跟踪的,因此在大多数情况下,用户不会将应用程序置于前台状态。无论在背景还是前景方面,广告都可以像我观察到的那样很好地工作。这里的问题是,当Central处于后台时,它有时仅进入didDiscover一次,有时甚至从未进入。因此,如果外围设备在范围之内,我将无法从中央检测到RSSI,或者用户无法从中央移开。相反,在前台时,我会使用didDiscover方法中的RSSI进行频繁更新。 我该如何解决?还是有一种解决方法来获得所需的结果?

0 个答案:

没有答案