Как решить [CoreBluetooth] ПРЕДУПРЕЖДЕНИЕ: недопустимая характеристика для периферийного устройства с подключением нескольких устройств - PullRequest
1 голос
/ 12 мая 2019

Я устанавливаю соединение между моим iOS-приложением и парой устройств BLE, созданных мной.У меня нет проблем, когда подключено только одно устройство, но когда оба подключены, я получаю эту ошибку с одним из них:

[CoreBluetooth] ПРЕДУПРЕЖДЕНИЕ: уведомление = НЕТ> не является допустимой характеристикой для периферийного устройства.

Оба устройства имеют одинаковые имя и характеристики службы, но имеют разные имя и идентификатор, и я использую имя для идентификации того или другого устройства.

Один и тот же код работает нормально, если толькоподключено одно устройство.

Я показываю вам свой код:

//BLE starts here
extension BTManager: CBCentralManagerDelegate {
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .unknown:
            print("central.state is .unknown")
            connectionStatus = -5
        case .resetting:
            print("central.state is .resetting")
            connectionStatus = -4
        case .unsupported:
            print("central.state is .unsupported")
            connectionStatus = -3
        case .unauthorized:
            print("central.state is .unauthorized")
            connectionStatus = -2
        case .poweredOff:
            print("central.state is .poweredOff")
            connectionStatus = -1
        case .poweredOn:
            print("central.state is .poweredOn and searching mode")
            connectionStatus = 0
            //Scan
            if (!centralManager.isScanning){
                centralManager.scanForPeripherals(withServices: [insoleServiceCBUUID])
            }
        }
    }

//Some peripheral found
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral,
                        advertisementData: [String : Any], rssi RSSI: NSNumber) {

        if(isInsolePresentInUserDefaults()){

            let insolesDictionary = UserDefaults.standard.dictionary(forKey: "AriaSmartInsole") as! [String : String]

            if (peripheral.name! == insolesDictionary["leftInsole"]){

                leftDevicePeripheral = peripheral
                leftDevicePeripheral.delegate = self
                centralManager.connect(leftDevicePeripheral)

            }

            if (peripheral.name! == insolesDictionary["rightInsole"]){

                rightDevicePeripheral = peripheral
                rightDevicePeripheral.delegate = self
                centralManager.connect(rightDevicePeripheral)

            }

        //ELSE record couple devices
        }else{

                if (peripheral.name!.contains("Aria") && peripheral.name!.count > 8){

                    if (dispositiviTrovati.count > 1){

                        var dispositiviTrovatiArray: [CBPeripheral] = Array(Set(dispositiviTrovati))


                        for (index, element) in dispositiviTrovatiArray.enumerated(){

                            let nextElement = index + 1

                            if (nextElement < dispositiviTrovatiArray.count){

                                let nomePrimoDevice: String = dispositiviTrovatiArray[index].name!
                                let primoDevice: CBPeripheral = dispositiviTrovatiArray[index]
                                let nomeSuccessivoDevice: String = dispositiviTrovatiArray[nextElement].name!
                                let successivoDevice: CBPeripheral = dispositiviTrovatiArray[nextElement]
                                let latoPrimoDevice: Character = nomePrimoDevice[nomePrimoDevice.index(nomePrimoDevice.startIndex, offsetBy: 5)]
                                let latoSuccessivoDevice: Character = nomeSuccessivoDevice[nomeSuccessivoDevice.index(nomeSuccessivoDevice.startIndex, offsetBy: 5)]

                                //HERE I SEARCH FOR LEFT DEVICE AND RIGHT DEVICE OF A COUPLE 
                                if (nomePrimoDevice.suffix(8) == nomeSuccessivoDevice.suffix(8) && latoPrimoDevice != latoSuccessivoDevice){

                                    var deviceDictionary: [String:String] = [:]
                                    var deviceSinistro: CBPeripheral?
                                    var deviceDestro: CBPeripheral?

                                    if(latoPrimoDevice == "S"){
                                        deviceDictionary["leftInsole"] = nomePrimoDevice
                                        deviceSinistro = primoDevice
                                    }else if(latoPrimoDevice == "D"){
                                        deviceDictionary["rightInsole"] = nomePrimoDevice
                                        deviceDestro = primoDevice
                                    }

                                    if(latoSuccessivoDevice == "S"){
                                        deviceDictionary["leftInsole"] = nomeSuccessivoDevice
                                        deviceSinistro = successivoDevice
                                    }else if(latoSuccessivoDevice == "D"){
                                        deviceDictionary["rightInsole"] = nomeSuccessivoDevice
                                        deviceDestro = successivoDevice
                                    }

                                    //BINGO
                                    if(deviceDictionary.count == 2){

                                        print(deviceDictionary.description)

                                        UserDefaults.standard.set(deviceDictionary, forKey: "AriaSmartInsole")

                                        //ASK FOR CONNECTION COUPLE OF DEVICE
                                        for device in dispositiviTrovati{

                                            if (device.name! == UserDefaults.standard.dictionary(forKey: "AriaSmartInsole")!["leftInsole"] as! String){

                                                leftDevicePeripheral = deviceSinistro
                                                print(leftDevicePeripheral.name ?? "")
                                                leftDevicePeripheral.delegate = self
                                                centralManager.connect(leftDevicePeripheral)

                                            }else if(device.name! == UserDefaults.standard.dictionary(forKey: "AriaSmartInsole")!["rightInsole"] as! String){

                                                rightDevicePeripheral = deviceDestro
                                                print(rightDevicePeripheral.name ?? "")
                                                rightDevicePeripheral.delegate = self
                                                centralManager.connect(rightDevicePeripheral)

                                            }

                                        }

                                    }

                            }

                        }

                    }

                }

            }

        }

    }

//CONNECTED TO DEVICES
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {

        if (peripheral.name! == leftDevicePeripheral.name!){

            leftDevicePeripheral.isConnected = true
            leftDevicePeripheral.discoverServices([insoleServiceCBUUID])
            self.connectionStatus = 1

        }else if(peripheral.name! == rightDevicePeripheral.name!){

            rightDevicePeripheral.isConnected = true
            rightDevicePeripheral.discoverServices([insoleServiceCBUUID])
            self.connectionStatus = 1

        }

        if (leftDevicePeripheral.isConnected == true && rightDevicePeripheral.isConnected == true){

            self.connectionStatus = 2
            centralManager.stopScan()//Safe power

        }

    }

}
extension BTManager: CBPeripheralDelegate {

    //SERVICES FOUND
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {

        if (error != nil){

            print("didDiscoverServices ERROR: ", error.debugDescription);

            return;

        }

        var insoleServiceIsFound: Bool = false;

        for service in peripheral.services! {

            //FOUND MY SERVICE
            if (service.uuid == insoleServiceCBUUID){

                if (peripheral.name! == leftDevicePeripheral.name){

                    leftDevicePeripheral.insoleService = service
                    leftDevicePeripheral.discoverCharacteristics(nil, for: leftDevicePeripheral.insoleService)
                    insoleServiceIsFound = true;

                }else if (peripheral.name! == rightDevicePeripheral.name){

                    rightDevicePeripheral.insoleService = service
                    rightDevicePeripheral.discoverCharacteristics(nil, for: rightDevicePeripheral.insoleService)
                    insoleServiceIsFound = true;

                }

            }

        }

        if (!insoleServiceIsFound){

            print("didDiscoverServices: ARIA SERVICE NOT FOUND");

        }

    }

//CHARACTERISTIC OF MY SERVICE FOUND
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {

        if (error != nil){

            print("didDiscoverCharacteristicsFor ERROR: ", error.debugDescription)
            return
        }

        guard let characteristics = service.characteristics else {

            print("NO CHARACTERESTICS FOUND")
            return

        }

        if (peripheral.name! == leftDevicePeripheral.name){

            for characteristic in characteristics {

                switch characteristic.uuid {

                case userEnableCBUUID:

                    leftDevicePeripheral.temperatureEnableCharacteristic = characteristic

                    if characteristic.properties.contains(.read) {
                        print("\(characteristic.uuid): properties contains .read")
                        leftDevicePeripheral.readValue(for: leftDevicePeripheral.temperatureEnableCharacteristic)
                    }

                case batteryLevelCBUUID:

                    leftDevicePeripheral.batteryLevelCharacteristic = characteristic

                    if characteristic.properties.contains(.read) {
                        print("\(characteristic.uuid): properties contains .read")
                        leftDevicePeripheral.readValue(for: leftDevicePeripheral.batteryLevelCharacteristic)

                    }
                default:
                    print("Unhandled Characteristic UUID: \(characteristic.uuid)")
                }

            }

        }else if (peripheral.name! == rightDevicePeripheral.name){

            for characteristic in characteristics {

                switch characteristic.uuid {

                case userEnableCBUUID:

                    rightDevicePeripheral.temperatureEnableCharacteristic = characteristic

                    if characteristic.properties.contains(.read) {
                        print("\(characteristic.uuid): properties contains .read")
                        rightDevicePeripheral.readValue(for: rightDevicePeripheral.temperatureEnableCharacteristic)
                    }

                case batteryLevelCBUUID:

                    rightDevicePeripheral.batteryLevelCharacteristic = characteristic

                    if characteristic.properties.contains(.read) {
                        print("\(characteristic.uuid): properties contains .read")
                        rightDevicePeripheral.readValue(for: rightDevicePeripheral.batteryLevelCharacteristic)
                    }

                default:
                    print("Unhandled Characteristic UUID: \(characteristic.uuid)")
                }

            }

        }

    }

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

        print("Nome: \(peripheral.name ?? "")")

        if (error != nil){

            print("didUpdateValueFor ERROR: ", error.debugDescription)
            return

        }


        if (peripheral.name! == leftDevicePeripheral.name){

            //Assegno valori prelevati alle caratteristiche
            switch characteristic.uuid {

            case userEnableCBUUID:

                print("userEnableValue: ", characteristic.value?[0] ?? "no value")
                //print("userTemp: ", characteristic.value?[0] ?? "no value")
                var data = characteristic.value
                var values = [UInt8](repeating:0, count:(data?.count)!)
                data?.copyBytes(to: &values, count:(data?.count)!)

                if(Int(values[0]) == 1){
                    leftDevicePeripheral.isThermalEnabled = true
                }else if(Int(values[0]) == 0){
                    leftDevicePeripheral.isThermalEnabled = false
                }
                print("LEFT userEnableValue for \(peripheral.description) in delegate:", leftDevicePeripheral.isThermalEnabled)
                print("\n")


            case batteryLevelCBUUID:

                //print("Battery level: ", characteristic.value?[0] ?? "no value")
                let data = characteristic.value
                var byte:UInt8 = 0
                data?.copyBytes(to: &byte, count: 1)
                leftDevicePeripheral.batteryLevel = Int(byte)
                print("BATTERY level: ", leftDevicePeripheral.batteryLevel)


            default:

                print("Unhandled Characteristic UUID: \(characteristic.uuid)")

            }

        }else if (peripheral.name! == rightDevicePeripheral.name){

            //Assegno valori prelevati alle caratteristiche
            switch characteristic.uuid {

            case userEnableCBUUID:

                print("RIght userEnableValue: ", characteristic.value?[0] ?? "no value")
                //print("userTemp: ", characteristic.value?[0] ?? "no value")
                var data = characteristic.value
                var values = [UInt8](repeating:0, count:(data?.count)!)
                data?.copyBytes(to: &values, count:(data?.count)!)

                if(Int(values[0]) == 1){
                    rightDevicePeripheral.isThermalEnabled = true
                }else if(Int(values[0]) == 0){
                    rightDevicePeripheral.isThermalEnabled = false
                }
                print("RIGHT userEnableValue for \(peripheral.description) in delegate:", leftDevicePeripheral.isThermalEnabled)
                print("\n")

            case batteryLevelCBUUID:

                //print("Battery level: ", characteristic.value?[0] ?? "no value")
                let data = characteristic.value
                var byte:UInt8 = 0
                data?.copyBytes(to: &byte, count: 1)
                let battLevel = Int(byte)
                print("BATTERY level: ", battLevel)


            default:

                print("Unhandled Characteristic UUID: \(characteristic.uuid)")

            }

        }

    }

//FUNC THAT I CALL
func enableThermal(forDevice: String){

        //Se c'è connessione
        if(self.checkConnessione() > 0){

            var val = UInt8(1)
            let data = NSData(bytes: &val, length: MemoryLayout<UInt8>.size)

            print("Val: \(val)")
            print("Data: \(data.description)")

                if((forDevice == "left" || forDevice == "both") && leftDevicePeripheral.temperatureEnableCharacteristic != nil){

                    leftDevicePeripheral.writeValue(data as Data, for: leftDevicePeripheral.temperatureEnableCharacteristic, type: CBCharacteristicWriteType.withResponse)


                }

                if((forDevice == "right" || forDevice == "both") && rightDevicePeripheral.temperatureEnableCharacteristic != nil){

                    rightDevicePeripheral.writeValue(data as Data, for: rightDevicePeripheral.temperatureEnableCharacteristic, type: CBCharacteristicWriteType.withResponse)



                }

        //Error msg + Ritenta connessione
        }else{

            print("NO CONNECTION")

        }

    }

//Here I save my custom peripheral (left and right)

import Foundation
import CoreBluetooth

extension CBPeripheral{

    struct Holder {

        static var insoleService: CBService!

        static var temperatureEnableCharacteristic: CBCharacteristic? 
        static var batteryLevelCharacteristic: CBCharacteristic?

        static var isConnected: Bool = false
        static var isThermalEnabled: Bool = false
        static var batteryLevel: Int = 0
        static var userTemperature: Double = 0
        static var topTemperature: Double = 0
        static var midTemperature: Double = 0
        static var bottomTemperature: Double = 0
        static var steps: Int = 0

    }

    var insoleService: CBService {
        get {
            return Holder.insoleService
        }
        set(newValue) {
            Holder.insoleService = newValue
        }
    }

    var temperatureEnableCharacteristic: CBCharacteristic {
        get {
            return Holder.temperatureEnableCharacteristic!
        }
        set(newValue) {
            Holder.temperatureEnableCharacteristic = newValue
        }
    }

}

Я ожидаю записи на оба устройства, сначала одно, а затем другое, еслиоба связаны.

Спасибо.Эрос.

...