I am re implementing a BLE manager class from a different code base that didn’t have state preservation and restore. It works good, but doesn’t reconnect after the phone being locked for an uncertain amount of hours, not even sure how to test that.
Anything I can improve?
class BLEController: NSObject, CBPeripheralDelegate, ObservableObject {
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
self.connectedPeripheral = nil
self.isConnecting = false
self.isConnected = false
self.isSubscribed = false
if let e = error {
let errorCode = (e as NSError).code
if errorCode == 6 {
// save/print error code
} else if errorCode == 7 {
// save/print error code
} else if errorCode == 14 {
// save/print error code
} else {
// save/print error code
}
connectTo(peripheral: peripheral)
} else {
// Disconnected without error which indicates user intent to disconnect
// Happens when swiping to disconnect
print("ℹ️ BLE Disconnected: (peripheral.name ?? "Unknown"): User Initiated Disconnect")
}
}
// Connect to a specific peripheral
func connectTo(peripheral: CBPeripheral) {
stopScanning()
DispatchQueue.main.async {
self.isConnecting = true
self.lastConnectionError = ""
self.automaticallyReconnect = true
}
if connectedPeripheral != nil {
print("ℹ️ BLE Disconnecting from: (connectedPeripheral.name) to connect to (peripheral.name ?? "Unknown")")
disconnectPeripheral()
}
centralManager?.connect(peripheral)
// Invalidate any existing timer
if timeoutTimer != nil {
timeoutTimer!.invalidate()
}
// Use a timer to keep track of connecting peripherals, context to pass the radio name with the timer and the RunLoop to prevent
// the timer from running on the main UI thread
let context = ["name": "(peripheral.name ?? "Unknown")"]
timeoutTimer = Timer.scheduledTimer(timeInterval: 1.5, target: self, selector: #selector(timeoutTimerFired), userInfo: context, repeats: true)
RunLoop.current.add(timeoutTimer!, forMode: .common)
print("ℹ️ BLE Connecting: (peripheral.name ?? "Unknown")")
}
func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any]) {
//I dont even think anything has to go here?? Followed an example.
let peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey] as? [CBPeripheral]
let navigationServiceUUIDObject = RavedioServiceCBUUID
let recoverPeripherals = peripherals?.filter({ (peripheral: CBPeripheral) -> Bool in
var found = false
if let services = peripheral.services {
for service in services {
if service.uuid == navigationServiceUUIDObject {
found = true
break
}
}
}
return found
})
foundPeripherals = recoverPeripherals
}
Or could it be with my peripheral not pinging the app enough?
New contributor
ron is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.