Search code examples
iosswiftbluetooth-lowenergycore-bluetoothcbcentralmanager

Can't connect to BLE Peripheral in some iOS devices


BLE works fine on 7 Plus (iOS 14.4.2) and 6 (iOS 12). But on XR (14.4.2) and 11 connection stuck after centralManager.connect(peripheral, options: nil) (infinite connection)

The peripheral is in connection mode because other smartphones cannot detect it. At first I thought that the problem was with the radio module of the peripheral device itself (NRF52), but the problem also occurred with the debug board. Rebooting the smartphone did not help. It's funny that the app works fine on a MacBook with an M1 chip

Part of code:

// Peripheral model

init(withPeripheral peripheral: CBPeripheral, advertisementData advertisementDictionary: [String : Any], andRSSI currentRSSI: NSNumber, using manager: CBCentralManager) {
    centralManager = manager
    basePeripheral = peripheral
    RSSI = currentRSSI
    super.init()
    advertisedName = parseAdvertisementData(advertisementDictionary)
    basePeripheral.delegate = self
}

public func connect() {
    centralManager.delegate = self
    centralManager.connect(basePeripheral, options: nil)
    print("Connecting to \(advertisedName ?? "device")...") 
// logs stops here
}

public func disconnect() {
    centralManager.cancelPeripheralConnection(basePeripheral)
    print("Cancelling connection with \(advertisedName ?? "device")...")
// triggers on VC dismiss
}

func centralManagerDidUpdateState(_ central: CBCentralManager) {
    if central.state != .poweredOn {
        print("Central Manager stated changed to \(central.state)")
    }
}

func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
    if peripheral == basePeripheral {
        print("Connected to \(advertisedName ?? "device")")
        delegate?.peripheralDidConnect()
        discoverPrimaryServices()
    }
}

func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
    if peripheral == basePeripheral {
        print("Disconnected from \(advertisedName ?? "device")")
        delegate?.peripheralDidDisconnect()
    }
}

Solution

  • "The peripheral is in connection mode because other smartphones cannot detect it." Did you mean that other smartphones can detect it?

    Given the phones you've listed as working and not working, I would expect that your board is having trouble with Bluetooth 5 (which was first supported on the iPhone 8). The NRF52 supports BT5 (it supports 5.2), but if you've written your own firmware you may have broken the support. I'd start by making sure you're running the most vanilla code you can from Nordic.