简体   繁体   中英

How to connect to a BLE device the second time in iOS Swift

I am working on an app where I connect to a BLE device. I can successfully connect, pass data back and forth, etc. The problem I am having is when I run the app the second time. If I try to connect to the device a second time, after pairing to it the first time, nothing seems to happen. I press my 'connect' button and I get nothing. To get it to connect again, I have to go into Settings, select the device, and forget the device. Once I have done this, everything works fine.

I am sure there is a simple way to connect to "reconnect" to the device, but I can't seem to find any information on how to do this. If fact, it looks like I am still connected to the device at the system level, but I need to know what to do to load it back into my local CBPeripheral variable.

Does anyone have any suggestions for me?

This is my current connection code:

private var centralManager : CBCentralManager!
private var peripheral: CBPeripheral!


centralManager = CBCentralManager(delegate: self, queue: nil, options: nil) //init central manager

func centralManagerDidUpdateState(_ central: CBCentralManager) {
        Print("Central state update")
        switch central.state {
        case .poweredOn:
            Print("Bluetooth is On, Starting scan.")
            peripheral_list.removeAll()
            centralManager.scanForPeripherals(withServices: nil,
                                              options: nil)
            case .unknown:
                Print("central.state is 'unknown'")
            case .resetting:
                Print("central.state is 'resetting'")
            case .unsupported:
                Print("central.state is 'unsupported'")
            case .unauthorized:
                Print("central.state is 'unauthorized'")
            case .poweredOff:
                Print("central.state is 'poweredOff'")
            @unknown default:
                Print("central.state **** Default *****")
        }
    }
    
    public func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        
        if let name = advertisementData["kCBAdvDataLocalName"] {
            if true /*name as! String == "RyanBT"*/ {
                Print("\nName   : \(name)")
                Print("UUID   : \(peripheral.identifier)")
                Print("RSSI   : \(RSSI)")
                for ad in advertisementData {
                    Print("AD Data: \(ad)")
                }
                
                peripheral_list.append(peripheral)
                picker.reloadAllComponents()
            }
        }
    }

    
    // The handler if we do connect succesfully
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        if peripheral == self.peripheral {
            Print("Connected!!!")
            peripheral.discoverServices(nil)
        }
    }
    
    func connectToDevice() {
        
        // Stop scan before connecting
        self.centralManager.stopScan()
        
        
        self.peripheral = self.peripheral_list[rowSelected]   //use selected peripheral
        self.peripheral.delegate = self
        
        // Connect!
        self.centralManager.connect(self.peripheral, options: nil)
    }

Edit: I added this code:

func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
        if error != nil {
            Print("\(error!)")
        }
    }

And this is the message it is printing when I try to connect the second time:

Error Domain=CBATTErrorDomain Code=14 "Peer removed pairing information" UserInfo={NSLocalizedDescription=Peer removed pairing information}

An iPhone can be connected to a BLE device even when your app is not connected. The actual device connection is handled by the OS, and shared among apps. While connected, most devices will not advertise, so you won't find them in didDiscover . This is all completely normal, particularly if you never disconnect by calling cancelPeripheralConnection . But even then it can happen.

Assuming that you're connecting to specific devices that advertise specific services, you should change your scanForPeripherals call to pass those services rather than nil. As a rule you shouldn't pass nil to scanForPeripherals unless you're building a general-purpose scanner. It's slower, and can return devices you don't want.

If you do that, you can then check for already connected devices by calling retrieveConnectedPeripherals(withServices:) . Given your current code, you would likely do that inside centralManagerDidUpdateState .

Alternately, you could keep track of individual devices that you've seen before by their peripheral UUIDs (by storing them in UserDefaults for example). You can check if those specific peripherals are currently connected using retrievePeripherals(withIdentifiers:) . Again, you'd probably do this in centralManagerDidUpdateState .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM