Восстановить периферийные службы BLE, входящие в фоновый режим - PullRequest
1 голос
/ 09 июля 2020

Я создал приложение, которое является периферийным устройством, работающим на моем iPhone. Это периферийное устройство является рекламным и объединяет услуги и характеристики. С помощью nrfConnect или других приложений сканирования я могу подключиться и увидеть все созданные службы / характеристики, пока мое приложение находится на переднем плане. Чтобы включить фоновый режим, я следовал официальной документации: https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/CoreBluetoothBackgroundProcessingForIOSApps/PerformingTasksWhileYourAppIsInTheBackground.html

Сегодня, когда я убиваю приложение вручную, фоновый режим работает, и я вижу свое периферийное устройство (без его локального name, потому что iOS удалите его, но я могу распознать адрес ma c, предоставленный nrfConnect). Моя проблема заключается в том, что я пытаюсь подключиться к периферийному устройству, когда приложение убито и находится в фоновом режиме. Все сервисы отсутствуют !! В документации Apple объясняется, что мы можем восстанавливать службы в фоновом режиме с помощью метода делегата willRestoreState и устанавливать CBPeripheralManagerRestoredStateServicesKey при инициализации CBPeripheralManager. Я выполнил все эти шаги, но службы не восстанавливаются ... Если у кого-то есть идея?

Вот мой полный код моего AppDelegate файла:

import UIKit
import CoreBluetooth

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CBPeripheralManagerDelegate {

    var window: UIWindow?
    var peripheralManager: CBPeripheralManager!
    var deviceName = "DIGITALBLEND"
    var dataToBeAdvertised: [String: [CBUUID]]!

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        
        self.window = UIWindow(frame: UIScreen.main.bounds)
        self.window?.backgroundColor = UIColor.white
        
        UIView.transition(with: self.window!, duration: 0.5, options: UIView.AnimationOptions.transitionCrossDissolve, animations: {
            self.window?.rootViewController = ViewController()
            self.window?.makeKeyAndVisible()
        }, completion: nil)
        
        let optionsPeripheral = [
            CBPeripheralManagerOptionRestoreIdentifierKey: self.deviceName,
            CBPeripheralManagerRestoredStateServicesKey: [
                CBUUID(string: "1ABB0000-542A-3BA1-C243-6F5AAF168DB7"),
                CBUUID(string: "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"),
                CBUUID(string: "0xFE59"),
            ],
            ] as [String : Any]
        
        self.peripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: optionsPeripheral)
        
        
        return true
    }
    
    // MARK: Peripheral Manager Functions
    
    func startAdvertising() {
        
        //Start advertising
        let advertisementData = [
            CBAdvertisementDataLocalNameKey: self.deviceName,
        ]
        
        if self.peripheralManager.isAdvertising == false {
            self.peripheralManager.startAdvertising(advertisementData)
        }
        
    }
    
    func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {
        
        if peripheral.isAdvertising{
            print("My Device Started Advertising")
        }
        
    }
    
    
    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        
        if peripheral.state == .poweredOn {
            
            //Add services
            self.createServices()
            
        } else {
            print("Bluetooth is not active")
        }
    }
    
    func createServices() {
        
        //Primary Service
        let primaryServiceUUID = CBUUID(string: "1ABB0000-542A-3BA1-C243-6F5AAF168DB7")
        let primaryService = CBMutableService(type: primaryServiceUUID, primary: true)
        
        //Nordic UARD Service
        let nusUUID = CBUUID(string: "6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
        let nusService = CBMutableService(type: nusUUID, primary: true)
        
        //Secure DFU Service
        let dfuUUID = CBUUID(string: "0xFE59")
        let dfuService = CBMutableService(type: dfuUUID, primary: true)
        
        //Create characteristics
        self.createCharacteristic_PRIMARY(service: primaryService)
        self.createCharacteristic_NUS(service: nusService)
        self.createCharacteristic_DFU(service: dfuService)
        
    }
    
    func createCharacteristic_PRIMARY(service : CBMutableService) {
        
        let permissions: CBAttributePermissions = [.readable, .writeable]
        
        //Characteristic 1
        let characteristicUUID_1 = CBUUID(string: "1ABB0001-542A-3BA1-C243-6F5AAF168DB7")
        let properties_1: CBCharacteristicProperties = [.read, .write]
        let characteristic_1 = CBMutableCharacteristic(
            type: characteristicUUID_1,
            properties: properties_1,
            value: nil,
            permissions: permissions)
        
        //Characteristic 2
        let characteristicUUID_2 = CBUUID(string: "1ABB0002-542A-3BA1-C243-6F5AAF168DB7")
        let properties_2: CBCharacteristicProperties = [.notify, .read, .write]
        let characteristic_2 = CBMutableCharacteristic(
            type: characteristicUUID_2,
            properties: properties_2,
            value: nil,
            permissions: permissions)

        //Add characteristic to service
        service.characteristics = [characteristic_1, characteristic_2]
        
        self.peripheralManager.add(service)
    }
    
    func createCharacteristic_NUS(service : CBMutableService) {
        
        let permissions: CBAttributePermissions = [.readable, .writeable]
        
        //Characteristic 1 - RX
        let characteristicUUID_1 = CBUUID(string: "6E400002-B5A3-F393-E0A9-E50E24DCCA9E")
        let properties_1: CBCharacteristicProperties = [.write]
        let characteristic_1 = CBMutableCharacteristic(
            type: characteristicUUID_1,
            properties: properties_1,
            value: nil,
            permissions: permissions)
        
        //Characteristic 2 - TX
        let characteristicUUID_2 = CBUUID(string: "6E400003-B5A3-F393-E0A9-E50E24DCCA9E")
        let properties_2: CBCharacteristicProperties = [.notify]
        let characteristic_2 = CBMutableCharacteristic(
            type: characteristicUUID_2,
            properties: properties_2,
            value: nil,
            permissions: permissions)
        
        //Add characteristic to service
        service.characteristics = [characteristic_1, characteristic_2]
        
        self.peripheralManager.add(service)
    }
    
    func createCharacteristic_DFU(service : CBMutableService) {
        
        let permissions: CBAttributePermissions = [.readable, .writeable]
        
        //Characteristic 1 - Buttonless DFU
        let characteristicUUID_1 = CBUUID(string: "8EC90003-F315-4F60-9FB8-838830DAEA50")
        let properties_1: CBCharacteristicProperties = [.indicate, .write]
        let characteristic_1 = CBMutableCharacteristic(
            type: characteristicUUID_1,
            properties: properties_1,
            value: nil,
            permissions: permissions)
        
        //Add characteristic to service
        service.characteristics = [characteristic_1]
        
        self.peripheralManager.add(service)
    }
    
    func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) {
        
        if error == nil{
            print("success publishing the service")
            self.startAdvertising()
        } else {
            print(error?.localizedDescription ?? "error publishing service")
        }
    }
    
    // CENTRAL read from TX
    func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveRead request: CBATTRequest) {
        print("salut")
    }
    
    // CENTRAL read from RX
    func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) {
        
    }
    
    func peripheralManager(_ peripheral: CBPeripheralManager, willRestoreState dict: [String : Any]) {
        
        self.peripheralManager = peripheral
        
        //  Note: restoring CBPeripheralManager services only works on iOS 11.2+
        guard let services = dict[CBPeripheralManagerRestoredStateServicesKey] as? [CBMutableService] else {
            return
        }

        for service in services {
            self.peripheralManager.add(service)
        }
        
    }
}
...