Skip to content

Commit 1a7989a

Browse files
authored
Merge pull request #10 from loopandlearn/update_for_pr34
Update for pr34
2 parents 425a6b0 + b858f79 commit 1a7989a

File tree

7 files changed

+82
-70
lines changed

7 files changed

+82
-70
lines changed

G7SensorKit/AlgorithmError.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@ extension AlgorithmState {
3737
return LocalizedString("Sensor is OK", comment: "The description of sensor algorithm state when sensor is ok.")
3838
case .stopped:
3939
return LocalizedString("Sensor is stopped", comment: "The description of sensor algorithm state when sensor is stopped.")
40-
case .warmup, .questionMarks:
40+
case .warmup, .temporarySensorIssue:
4141
return LocalizedString("Sensor is warming up", comment: "The description of sensor algorithm state when sensor is warming up.")
4242
case .expired:
4343
return LocalizedString("Sensor expired", comment: "The description of sensor algorithm state when sensor is expired.")
4444
case .sensorFailed:
4545
return LocalizedString("Sensor failed", comment: "The description of sensor algorithm state when sensor failed.")
46+
default:
47+
return "Sensor state: \(String(describing: state))"
4648
}
4749
case .unknown(let rawValue):
4850
return String(format: LocalizedString("Sensor is in unknown state %1$d", comment: "The description of sensor algorithm state when raw value is unknown. (1: missing data details)"), rawValue)

G7SensorKit/AlgorithmState.swift

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,29 @@ public enum AlgorithmState: RawRepresentable {
1515
public enum State: RawValue {
1616
case stopped = 1
1717
case warmup = 2
18+
case excessNoise = 3
19+
case firstOfTwoBGsNeeded = 4
20+
case secondOfTwoBGsNeeded = 5
1821
case ok = 6
19-
case questionMarks = 18
22+
case needsCalibration = 7
23+
case calibrationError1 = 8
24+
case calibrationError2 = 9
25+
case calibrationLinearityFitFailure = 10
26+
case sensorFailedDuetoCountsAberration = 11
27+
case sensorFailedDuetoResidualAberration = 12
28+
case outOfCalibrationDueToOutlier = 13
29+
case outlierCalibrationRequest = 14
30+
case sessionExpired = 15
31+
case sessionFailedDueToUnrecoverableError = 16
32+
case sessionFailedDueToTransmitterError = 17
33+
case temporarySensorIssue = 18
34+
case sensorFailedDueToProgressiveSensorDecline = 19
35+
case sensorFailedDueToHighCountsAberration = 20
36+
case sensorFailedDueToLowCountsAberration = 21
37+
case sensorFailedDueToRestart = 22
2038
case expired = 24
2139
case sensorFailed = 25
40+
case sessionEnded = 26
2241
}
2342

2443
case known(State)
@@ -48,7 +67,7 @@ public enum AlgorithmState: RawRepresentable {
4867
}
4968

5069
switch state {
51-
case .sensorFailed:
70+
case .sensorFailed, .sensorFailedDuetoCountsAberration, .sensorFailedDuetoResidualAberration, .sessionFailedDueToTransmitterError, .sessionFailedDueToUnrecoverableError, .sensorFailedDueToProgressiveSensorDecline, .sensorFailedDueToHighCountsAberration, .sensorFailedDueToLowCountsAberration, .sensorFailedDueToRestart:
5271
return true
5372
default:
5473
return false
@@ -68,13 +87,13 @@ public enum AlgorithmState: RawRepresentable {
6887
}
6988
}
7089

71-
public var isInSensorError: Bool {
90+
public var hasTemporaryError: Bool {
7291
guard case .known(let state) = self else {
7392
return false
7493
}
7594

7695
switch state {
77-
case .questionMarks:
96+
case .temporarySensorIssue:
7897
return true
7998
default:
8099
return false
@@ -88,14 +107,10 @@ public enum AlgorithmState: RawRepresentable {
88107
}
89108

90109
switch state {
91-
case .stopped,
92-
.warmup,
93-
.questionMarks,
94-
.expired,
95-
.sensorFailed:
96-
return false
97110
case .ok:
98111
return true
112+
default:
113+
return false
99114
}
100115
}
101116
}

G7SensorKit/G7CGMManager/G7BluetoothManager.swift

Lines changed: 24 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,6 @@ class G7BluetoothManager: NSObject {
101101
return activePeripheralManager?.peripheral
102102
}
103103
}
104-
105-
/// Isolated to `managerQueue`
106-
private var eventRegistrationActive : Bool = false
107104

108105
/// Isolated to `managerQueue`
109106
private var managedPeripherals: [UUID:G7PeripheralManager] = [:]
@@ -134,7 +131,7 @@ class G7BluetoothManager: NSObject {
134131
self.centralManager = CBCentralManager(delegate: self, queue: managerQueue, options: [CBCentralManagerOptionRestoreIdentifierKey: "com.loudnate.CGMBLEKit"])
135132
}
136133
}
137-
134+
138135
// MARK: - Actions
139136

140137
func scanForPeripheral() {
@@ -159,7 +156,7 @@ class G7BluetoothManager: NSObject {
159156

160157
private func managerQueue_stopScanning() {
161158
if centralManager.isScanning {
162-
log.debug("Stopping scan")
159+
log.default("Stopping scan")
163160
centralManager.stopScan()
164161
delegate?.bluetoothManagerScanningStatusDidChange(self)
165162
}
@@ -170,7 +167,7 @@ class G7BluetoothManager: NSObject {
170167

171168
managerQueue.sync {
172169
if centralManager.isScanning {
173-
log.debug("Stopping scan on disconnect")
170+
log.default("Stopping scan on disconnect")
174171
centralManager.stopScan()
175172
delegate?.bluetoothManagerScanningStatusDidChange(self)
176173
}
@@ -180,24 +177,17 @@ class G7BluetoothManager: NSObject {
180177
}
181178
}
182179
}
183-
180+
184181
func centralManager(_ central: CBCentralManager, connectionEventDidOccur event: CBConnectionEvent, for peripheral: CBPeripheral) {
185-
186182
managerQueue.async {
187-
guard self.eventRegistrationActive else {
188-
self.centralManager.registerForConnectionEvents(options: nil)
189-
return
190-
}
191-
192-
self.managerQueue_establishActivePeripheral()
193-
194-
if !self.eventRegistrationActive {
195-
self.centralManager.registerForConnectionEvents(options: nil)
183+
if self.activePeripheralIdentifier == nil {
184+
self.log.default("Discovered peripheral from connectionEventDidOccur %{public}@", peripheral.identifier.uuidString)
185+
self.handleDiscoveredPeripheral(peripheral)
196186
}
197187
}
198188
}
199-
200-
private func managerQueue_establishActivePeripheral() {
189+
190+
private func managerQueue_scanForPeripheral() {
201191
dispatchPrecondition(condition: .onQueue(managerQueue))
202192

203193
guard centralManager.state == .poweredOn else {
@@ -206,48 +196,36 @@ class G7BluetoothManager: NSObject {
206196

207197
let currentState = activePeripheral?.state ?? .disconnected
208198
guard currentState != .connected else {
209-
eventRegistrationActive = false
210199
return
211200
}
212201

213202
if let peripheralID = activePeripheralIdentifier, let peripheral = centralManager.retrievePeripherals(withIdentifiers: [peripheralID]).first {
214-
log.debug("Retrieved peripheral %{public}@", peripheral.identifier.uuidString)
203+
log.default("Retrieved peripheral %{public}@", peripheral.identifier.uuidString)
215204
handleDiscoveredPeripheral(peripheral)
216205
} else {
217206
for peripheral in centralManager.retrieveConnectedPeripherals(withServices: [
218207
SensorServiceUUID.advertisement.cbUUID,
219208
SensorServiceUUID.cgmService.cbUUID
220209
]) {
210+
log.default("Found system-connected peripheral: %{public}@", peripheral.identifier.uuidString)
221211
handleDiscoveredPeripheral(peripheral)
222212
}
223213
}
224-
225-
if activePeripheral != nil {
226-
eventRegistrationActive = false
227-
}
228-
}
229-
230-
private func managerQueue_scanForPeripheral() {
231-
dispatchPrecondition(condition: .onQueue(managerQueue))
232-
233-
managerQueue_establishActivePeripheral()
234214

235215
if activePeripheral == nil {
236-
log.debug("Scanning for peripherals")
216+
log.default("Scanning for peripherals and listening for connection events")
217+
218+
centralManager.registerForConnectionEvents(options: [CBConnectionEventMatchingOption.serviceUUIDs: [
219+
SensorServiceUUID.advertisement.cbUUID,
220+
SensorServiceUUID.cgmService.cbUUID
221+
]])
222+
237223
centralManager.scanForPeripherals(withServices: [
238224
SensorServiceUUID.advertisement.cbUUID
239225
],
240226
options: nil
241227
)
242228
delegate?.bluetoothManagerScanningStatusDidChange(self)
243-
244-
if !eventRegistrationActive {
245-
eventRegistrationActive = true
246-
centralManager.registerForConnectionEvents(options: [CBConnectionEventMatchingOption.serviceUUIDs: [
247-
SensorServiceUUID.advertisement.cbUUID,
248-
SensorServiceUUID.cgmService.cbUUID
249-
]])
250-
}
251229
}
252230
}
253231

@@ -259,9 +237,9 @@ class G7BluetoothManager: NSObject {
259237
The sleep gives the transmitter time to shut down, but keeps the app running.
260238

261239
*/
262-
func scanAfterDelay() {
240+
fileprivate func scanAfterDelay() {
263241
DispatchQueue.global(qos: .utility).async {
264-
Thread.sleep(forTimeInterval: 5)
242+
Thread.sleep(forTimeInterval: 2)
265243

266244
self.scanForPeripheral()
267245
}
@@ -295,7 +273,7 @@ class G7BluetoothManager: NSObject {
295273
if let delegate = delegate {
296274
switch delegate.bluetoothManager(self, shouldConnectPeripheral: peripheral) {
297275
case .makeActive:
298-
log.debug("Making peripheral active: %{public}@", peripheral.identifier.uuidString)
276+
log.default("Making peripheral active: %{public}@", peripheral.identifier.uuidString)
299277

300278
if let peripheralManager = activePeripheralManager {
301279
peripheralManager.peripheral = peripheral
@@ -311,7 +289,7 @@ class G7BluetoothManager: NSObject {
311289
self.centralManager.connect(peripheral)
312290

313291
case .connect:
314-
log.debug("Connecting to peripheral: %{public}@", peripheral.identifier.uuidString)
292+
log.default("Connecting to peripheral: %{public}@", peripheral.identifier.uuidString)
315293
self.centralManager.connect(peripheral)
316294
let peripheralManager = G7PeripheralManager(
317295
peripheral: peripheral,
@@ -349,7 +327,7 @@ extension G7BluetoothManager: CBCentralManagerDelegate {
349327
fallthrough
350328
@unknown default:
351329
if central.isScanning {
352-
log.debug("Stopping scan on central not powered on")
330+
log.default("Stopping scan on central not powered on")
353331
central.stopScan()
354332
delegate?.bluetoothManagerScanningStatusDidChange(self)
355333
}
@@ -370,7 +348,7 @@ extension G7BluetoothManager: CBCentralManagerDelegate {
370348
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
371349
dispatchPrecondition(condition: .onQueue(managerQueue))
372350

373-
log.info("%{public}@: %{public}@, data = %{public}@", #function, peripheral, String(describing: advertisementData))
351+
log.default("%{public}@: %{public}@, data = %{public}@", #function, peripheral, String(describing: advertisementData))
374352

375353
managerQueue.async {
376354
self.handleDiscoveredPeripheral(peripheral)

G7SensorKit/G7CGMManager/G7CGMManager.swift

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,14 +237,14 @@ public class G7CGMManager: CGMManager {
237237
return nil
238238
}
239239

240-
public func scanForNewSensor(scanAfterDelay: Bool = false) {
240+
public func scanForNewSensor() {
241241
logDeviceCommunication("Forgetting existing sensor and starting scan for new sensor.", type: .connection)
242242

243243
mutateState { state in
244244
state.sensorID = nil
245245
state.activatedAt = nil
246246
}
247-
sensor.scanForNewSensor(scanAfterDelay: scanAfterDelay)
247+
sensor.scanForNewSensor()
248248
}
249249

250250
private var device: HKDevice? {
@@ -319,10 +319,15 @@ extension G7CGMManager: G7SensorDelegate {
319319
public func sensorDisconnected(_ sensor: G7Sensor, suspectedEndOfSession: Bool) {
320320
logDeviceCommunication("Sensor disconnected: suspectedEndOfSession=\(suspectedEndOfSession)", type: .connection)
321321
if suspectedEndOfSession {
322-
scanForNewSensor(scanAfterDelay: true)
322+
scanForNewSensor()
323323
}
324324
}
325325

326+
public func sensor(_ sensor: G7Sensor, logComms comms: String) {
327+
logDeviceCommunication("Sensor comms \(comms)", type: .receive)
328+
}
329+
330+
326331
public func sensor(_ sensor: G7Sensor, didError error: Error) {
327332
logDeviceCommunication("Sensor error \(error)", type: .error)
328333
}
@@ -335,6 +340,17 @@ extension G7CGMManager: G7SensorDelegate {
335340
return
336341
}
337342

343+
if message.algorithmState.sensorFailed {
344+
logDeviceCommunication("Detected failed sensor... scanning for new sensor.", type: .receive)
345+
scanForNewSensor()
346+
}
347+
348+
if message.algorithmState == .known(.sessionEnded) {
349+
logDeviceCommunication("Detected session ended... scanning for new sensor.", type: .receive)
350+
scanForNewSensor()
351+
}
352+
353+
338354
guard let activationDate = sensor.activationDate else {
339355
logDeviceCommunication("Unable to process sensor reading without activation date.", type: .error)
340356
return

G7SensorKit/G7CGMManager/G7Sensor.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ public protocol G7SensorDelegate: AnyObject {
1919

2020
func sensor(_ sensor: G7Sensor, didError error: Error)
2121

22+
func sensor(_ sensor: G7Sensor, logComms comms: String)
23+
2224
func sensor(_ sensor: G7Sensor, didRead glucose: G7GlucoseMessage)
2325

2426
func sensor(_ sensor: G7Sensor, didReadBackfill backfill: [G7BackfillMessage])
@@ -99,15 +101,11 @@ public final class G7Sensor: G7BluetoothManagerDelegate {
99101
bluetoothManager.delegate = self
100102
}
101103

102-
public func scanForNewSensor(scanAfterDelay: Bool = false) {
104+
public func scanForNewSensor() {
103105
self.sensorID = nil
104106
bluetoothManager.disconnect()
105107
bluetoothManager.forgetPeripheral()
106-
if scanAfterDelay {
107-
bluetoothManager.scanAfterDelay()
108-
} else {
109-
bluetoothManager.scanForPeripheral()
110-
}
108+
bluetoothManager.scanForPeripheral()
111109
}
112110

113111
public func resumeScanning() {
@@ -198,7 +196,9 @@ public final class G7Sensor: G7BluetoothManagerDelegate {
198196
if let sensorID = sensorID, sensorID == peripheralManager.peripheral.name {
199197

200198
let suspectedEndOfSession: Bool
201-
if pendingAuth && wasRemoteDisconnect {
199+
200+
self.log.info("Sensor disconnected: wasRemoteDisconnect:%{public}@", String(describing: wasRemoteDisconnect))
201+
if pendingAuth, wasRemoteDisconnect {
202202
suspectedEndOfSession = true // Normal disconnect without auth is likely that G7 app stopped this session
203203
} else {
204204
suspectedEndOfSession = false
@@ -237,7 +237,7 @@ public final class G7Sensor: G7BluetoothManagerDelegate {
237237

238238
guard response.count > 0 else { return }
239239

240-
log.debug("Received control response: %{public}@", response.hexadecimalString)
240+
log.default("Received control response: %{public}@", response.hexadecimalString)
241241

242242
switch G7Opcode(rawValue: response[0]) {
243243
case .glucoseTx?:
@@ -256,7 +256,7 @@ public final class G7Sensor: G7BluetoothManagerDelegate {
256256
}
257257
}
258258
default:
259-
// We ignore all other known opcodes
259+
self.delegate?.sensor(self, logComms: response.hexadecimalString)
260260
break
261261
}
262262
}

G7SensorKit/Messages/G7Opcode.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Foundation
1010

1111
enum G7Opcode: UInt8 {
1212
case authChallengeRx = 0x05
13+
case sessionStopTx = 0x28
1314
case glucoseTx = 0x4e
1415
case backfillFinished = 0x59
1516
}

G7SensorKitUI/G7CGMManager/G7CGMManager+UI.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ extension G7CGMManager: CGMManagerUI {
7474
state: .warning)
7575
}
7676

77-
if let latestReading = latestReading, latestReading.algorithmState.isInSensorError {
77+
if let latestReading = latestReading, latestReading.algorithmState.hasTemporaryError {
7878
return G7DeviceStatusHighlight(
7979
localizedMessage: LocalizedString("Sensor\nIssue", comment: "G7 Status highlight text for sensor error"),
8080
imageName: "exclamationmark.circle.fill",

0 commit comments

Comments
 (0)