diff --git a/G7SensorKit/G7CGMManager/G7BluetoothManager.swift b/G7SensorKit/G7CGMManager/G7BluetoothManager.swift index 62ab5fc..8976104 100644 --- a/G7SensorKit/G7CGMManager/G7BluetoothManager.swift +++ b/G7SensorKit/G7CGMManager/G7BluetoothManager.swift @@ -101,6 +101,9 @@ class G7BluetoothManager: NSObject { return activePeripheralManager?.peripheral } } + + /// Isolated to `managerQueue` + private var eventRegistrationActive : Bool = false /// Isolated to `managerQueue` private var managedPeripherals: [UUID:G7PeripheralManager] = [:] @@ -131,7 +134,7 @@ class G7BluetoothManager: NSObject { self.centralManager = CBCentralManager(delegate: self, queue: managerQueue, options: [CBCentralManagerOptionRestoreIdentifierKey: "com.loudnate.CGMBLEKit"]) } } - + // MARK: - Actions func scanForPeripheral() { @@ -177,8 +180,24 @@ class G7BluetoothManager: NSObject { } } } - - private func managerQueue_scanForPeripheral() { + + func centralManager(_ central: CBCentralManager, connectionEventDidOccur event: CBConnectionEvent, for peripheral: CBPeripheral) { + + managerQueue.async { + guard self.eventRegistrationActive else { + self.centralManager.registerForConnectionEvents(options: nil) + return + } + + self.managerQueue_establishActivePeripheral() + + if !self.eventRegistrationActive { + self.centralManager.registerForConnectionEvents(options: nil) + } + } + } + + private func managerQueue_establishActivePeripheral() { dispatchPrecondition(condition: .onQueue(managerQueue)) guard centralManager.state == .poweredOn else { @@ -187,6 +206,7 @@ class G7BluetoothManager: NSObject { let currentState = activePeripheral?.state ?? .disconnected guard currentState != .connected else { + eventRegistrationActive = false return } @@ -201,6 +221,16 @@ class G7BluetoothManager: NSObject { handleDiscoveredPeripheral(peripheral) } } + + if activePeripheral != nil { + eventRegistrationActive = false + } + } + + private func managerQueue_scanForPeripheral() { + dispatchPrecondition(condition: .onQueue(managerQueue)) + + managerQueue_establishActivePeripheral() if activePeripheral == nil { log.debug("Scanning for peripherals") @@ -210,6 +240,14 @@ class G7BluetoothManager: NSObject { options: nil ) delegate?.bluetoothManagerScanningStatusDidChange(self) + + if !eventRegistrationActive { + eventRegistrationActive = true + centralManager.registerForConnectionEvents(options: [CBConnectionEventMatchingOption.serviceUUIDs: [ + SensorServiceUUID.advertisement.cbUUID, + SensorServiceUUID.cgmService.cbUUID + ]]) + } } } @@ -221,9 +259,9 @@ class G7BluetoothManager: NSObject { The sleep gives the transmitter time to shut down, but keeps the app running. */ - fileprivate func scanAfterDelay() { + func scanAfterDelay() { DispatchQueue.global(qos: .utility).async { - Thread.sleep(forTimeInterval: 2) + Thread.sleep(forTimeInterval: 5) self.scanForPeripheral() } diff --git a/G7SensorKit/G7CGMManager/G7CGMManager.swift b/G7SensorKit/G7CGMManager/G7CGMManager.swift index 198d5b3..e2861e6 100644 --- a/G7SensorKit/G7CGMManager/G7CGMManager.swift +++ b/G7SensorKit/G7CGMManager/G7CGMManager.swift @@ -237,14 +237,14 @@ public class G7CGMManager: CGMManager { return nil } - public func scanForNewSensor() { + public func scanForNewSensor(scanAfterDelay: Bool = false) { logDeviceCommunication("Forgetting existing sensor and starting scan for new sensor.", type: .connection) mutateState { state in state.sensorID = nil state.activatedAt = nil } - sensor.scanForNewSensor() + sensor.scanForNewSensor(scanAfterDelay: scanAfterDelay) } private var device: HKDevice? { @@ -319,7 +319,7 @@ extension G7CGMManager: G7SensorDelegate { public func sensorDisconnected(_ sensor: G7Sensor, suspectedEndOfSession: Bool) { logDeviceCommunication("Sensor disconnected: suspectedEndOfSession=\(suspectedEndOfSession)", type: .connection) if suspectedEndOfSession { - scanForNewSensor() + scanForNewSensor(scanAfterDelay: true) } } diff --git a/G7SensorKit/G7CGMManager/G7Sensor.swift b/G7SensorKit/G7CGMManager/G7Sensor.swift index b1745a1..5c51092 100644 --- a/G7SensorKit/G7CGMManager/G7Sensor.swift +++ b/G7SensorKit/G7CGMManager/G7Sensor.swift @@ -99,11 +99,15 @@ public final class G7Sensor: G7BluetoothManagerDelegate { bluetoothManager.delegate = self } - public func scanForNewSensor() { + public func scanForNewSensor(scanAfterDelay: Bool = false) { self.sensorID = nil bluetoothManager.disconnect() bluetoothManager.forgetPeripheral() - bluetoothManager.scanForPeripheral() + if scanAfterDelay { + bluetoothManager.scanAfterDelay() + } else { + bluetoothManager.scanForPeripheral() + } } public func resumeScanning() {