From d65c22a2047edd801f63c7786082079626cb9eaf Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Thu, 31 Aug 2017 00:07:47 -0500 Subject: [PATCH] Treat period after rewind as suspend --- Loop.xcodeproj/project.pbxproj | 20 ++++++++++-- Loop/Extensions/DoseStore.swift | 46 ++++++++++++++++++++++++--- Loop/Managers/DeviceDataManager.swift | 4 +-- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index 31803b9090..d77f24d889 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -1115,7 +1115,8 @@ 43776F8A1B8022E90074EA36 /* Resources */, 43A9439C1B926B7B0051FA24 /* Embed Watch Content */, 43A943AE1B928D400051FA24 /* Embed Frameworks */, - 43EDDBEF1C361BCE007D89B5 /* ShellScript */, + 438207721F2C4DD400886C13 /* Homebrew & Carthage Setup */, + 43EDDBEF1C361BCE007D89B5 /* Copy Frameworks with Carthage */, 4F70C1EC1DE8DCA8006380B7 /* Embed App Extensions */, ); buildRules = ( @@ -1426,7 +1427,21 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 43EDDBEF1C361BCE007D89B5 /* ShellScript */ = { + 438207721F2C4DD400886C13 /* Homebrew & Carthage Setup */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Homebrew & Carthage Setup"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if ! [ -x \"$(command -v brew)\" ]; then\n # Install Homebrew\n ruby -e \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)\"\nfi\n\nif brew ls carthage > /dev/null; then\n brew upgrade carthage || echo \"Continuing…\"\nelse\n brew install carthage\nfi\n"; + }; + 43EDDBEF1C361BCE007D89B5 /* Copy Frameworks with Carthage */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1447,6 +1462,7 @@ "$(SRCROOT)/Carthage/Build/iOS/Crypto.framework", "$(SRCROOT)/Carthage/Build/iOS/G4ShareSpy.framework", ); + name = "Copy Frameworks with Carthage"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Loop/Extensions/DoseStore.swift b/Loop/Extensions/DoseStore.swift index 97828d2b42..9ca483e1c2 100644 --- a/Loop/Extensions/DoseStore.swift +++ b/Loop/Extensions/DoseStore.swift @@ -15,9 +15,10 @@ extension LoopDataManager { /** Adds and persists new pump events. */ - func addPumpEvents(_ pumpEvents: [TimestampedHistoryEvent], completion: @escaping (_ error: DoseStore.DoseStoreError?) -> Void) { + func addPumpEvents(_ pumpEvents: [TimestampedHistoryEvent], from model: MinimedKit.PumpModel, completion: @escaping (_ error: DoseStore.DoseStoreError?) -> Void) { var events: [NewPumpEvent] = [] var lastTempBasalAmount: DoseEntry? + var isRewound = false var title: String for event in pumpEvents { @@ -45,12 +46,49 @@ extension LoopDataManager { unit: .unitsPerHour ) } - case is BasalProfileStartPumpEvent: - break + case let basal as BasalProfileStartPumpEvent: + dose = DoseEntry( + type: .basal, + startDate: event.date, + // Use the maximum-possible duration for a basal entry; its true duration will be reconciled against other entries. + endDate: event.date.addingTimeInterval(.hours(24)), + value: basal.scheduleEntry.rate, + unit: .unitsPerHour + ) + + if isRewound { + isRewound = false + } case is RewindPumpEvent: - break + eventType = .rewind + + /* + No insulin is delivered between the beginning of a rewind until the suggested fixed prime is delivered or cancelled. + + If the fixed prime is cancelled, it is never recorded in history. It is possible to cancel a fixed prime and perform one manually some time later, but basal delivery will have resumed during that period. + + On an x23 model pump, the point at which basal delivery resumes is unambiguous thanks to the BasalProfileStart event. + On older model pumps, we take the conservative approach and assume delivery is paused only between the Rewind and the first Prime event. + */ + dose = DoseEntry(suspendDate: event.date) + isRewound = true case is PrimePumpEvent: eventType = .prime + + if !model.recordsBasalProfileStartEvents && isRewound { + isRewound = false + dose = DoseEntry(resumeDate: event.date) + } + case let alarm as PumpAlarmPumpEvent: + eventType = .alarm + if case .noDelivery = alarm.alarmType { + // TODO: Interpret a no delivery alarm as a suspend + } + break + case is ClearAlarmPumpEvent: + eventType = .alarmClear + // TODO: Interpret a clear no delivery as a Resume + break default: break } diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 3af4b0c9cb..10af3d58e3 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -267,8 +267,8 @@ final class DeviceDataManager { device.ops?.getHistoryEvents(since: startDate) { (result) in switch result { - case let .success(events, _): - self.loopManager.addPumpEvents(events) { (error) in + case let .success(events, model): + self.loopManager.addPumpEvents(events, from: model) { (error) in if let error = error { self.logger.addError("Failed to store history: \(error)", fromSource: "DoseStore") }