Skip to content

Commit 34d670f

Browse files
authored
Bolus tracking (#567)
* Improve tracking of recent boluses * Improve tracking of recent boluses
1 parent 7e07af6 commit 34d670f

File tree

7 files changed

+117
-56
lines changed

7 files changed

+117
-56
lines changed

Loop.xcodeproj/project.pbxproj

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
437CCAE01D285C7B0075D2C3 /* ServiceAuthentication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437CCADF1D285C7B0075D2C3 /* ServiceAuthentication.swift */; };
7575
437CEEE41CDE5C0A003C8C80 /* UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437CEEE31CDE5C0A003C8C80 /* UIImage.swift */; };
7676
437D9BA31D7BC977007245E8 /* PredictionTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437D9BA21D7BC977007245E8 /* PredictionTableViewController.swift */; };
77+
438172D91F4E9E37003C3328 /* NewPumpEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 438172D81F4E9E37003C3328 /* NewPumpEvent.swift */; };
7778
4381D2261F3C0FDD004ACCF9 /* RileyLinkDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4381D2251F3C0FDD004ACCF9 /* RileyLinkDevice.swift */; };
7879
43846AD51D8FA67800799272 /* Base.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 43846AD41D8FA67800799272 /* Base.lproj */; };
7980
43846ADB1D91057000799272 /* ContextUpdatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43846ADA1D91057000799272 /* ContextUpdatable.swift */; };
@@ -447,6 +448,7 @@
447448
437CEEE31CDE5C0A003C8C80 /* UIImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImage.swift; sourceTree = "<group>"; };
448449
437D9BA11D7B5203007245E8 /* Loop.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Loop.xcconfig; sourceTree = "<group>"; };
449450
437D9BA21D7BC977007245E8 /* PredictionTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PredictionTableViewController.swift; sourceTree = "<group>"; };
451+
438172D81F4E9E37003C3328 /* NewPumpEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewPumpEvent.swift; sourceTree = "<group>"; };
450452
4381D2251F3C0FDD004ACCF9 /* RileyLinkDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RileyLinkDevice.swift; sourceTree = "<group>"; };
451453
43846AD41D8FA67800799272 /* Base.lproj */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Base.lproj; sourceTree = "<group>"; };
452454
43846ADA1D91057000799272 /* ContextUpdatable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContextUpdatable.swift; sourceTree = "<group>"; };
@@ -888,6 +890,7 @@
888890
4302F4E41D4EA75100F0FCAF /* DoseStore.swift */,
889891
43C513181E864C4E001547C7 /* GlucoseRangeSchedule.swift */,
890892
C15713811DAC6983005BC4D2 /* MealBolusNightscoutTreatment.swift */,
893+
438172D81F4E9E37003C3328 /* NewPumpEvent.swift */,
891894
43CEE6E51E56AFD400CB9116 /* NightscoutUploader.swift */,
892895
4398973A1CD2FC2000223065 /* NSDateFormatter.swift */,
893896
43E344A31B9E1B1C00C85C07 /* NSUserDefaults.swift */,
@@ -1278,7 +1281,7 @@
12781281
isa = PBXProject;
12791282
attributes = {
12801283
LastSwiftUpdateCheck = 0730;
1281-
LastUpgradeCheck = 0820;
1284+
LastUpgradeCheck = 0820;
12821285
ORGANIZATIONNAME = "LoopKit Authors";
12831286
TargetAttributes = {
12841287
43776F8B1B8022E90074EA36 = {
@@ -1499,7 +1502,7 @@
14991502
);
15001503
runOnlyForDeploymentPostprocessing = 0;
15011504
shellPath = /bin/sh;
1502-
shellScript = "# /usr/local/bin/carthage build --platform \"$PLATFORM_NAME\" \"$SRCROOT\"\n# Only run this script if we're not using a workspace or installing\nif [ ! -d $PROJECT_DIR/Loop.xcworkspace ] || [ \"$ACTION\" = \"install\" ]; then\n /usr/local/bin/carthage copy-frameworks\nfi";
1505+
shellScript = "# /usr/local/bin/carthage build --platform \"$PLATFORM_NAME\" \"$SRCROOT\"\n# Only run this script if we're not using a workspace or installing\nif [ ! -d $PROJECT_DIR/Loop.xcworkspace ] || [ \"$ACTION\" = \"install\" ]; then\n /usr/local/bin/carthage copy-frameworks\nfi";
15031506
};
15041507
/* End PBXShellScriptBuildPhase section */
15051508

@@ -1560,6 +1563,7 @@
15601563
439BED2A1E76093C00B0AED5 /* CGMManager.swift in Sources */,
15611564
C18C8C511D5A351900E043FB /* NightscoutDataManager.swift in Sources */,
15621565
438849EA1D297CB6003B3F23 /* NightscoutService.swift in Sources */,
1566+
438172D91F4E9E37003C3328 /* NewPumpEvent.swift in Sources */,
15631567
437CCADC1D284B830075D2C3 /* ButtonTableViewCell.swift in Sources */,
15641568
4389916B1E91B689000EEF90 /* ChartSettings+Loop.swift in Sources */,
15651569
4315D2871CA5CC3B00589052 /* CarbEntryEditTableViewController.swift in Sources */,
@@ -1838,7 +1842,7 @@
18381842
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
18391843
CODE_SIGN_IDENTITY = "iPhone Developer: [email protected] (XZN842LDLT)";
18401844
COPY_PHASE_STRIP = NO;
1841-
CURRENT_PROJECT_VERSION = 39;
1845+
CURRENT_PROJECT_VERSION = 39;
18421846
DEBUG_INFORMATION_FORMAT = dwarf;
18431847
ENABLE_STRICT_OBJC_MSGSEND = YES;
18441848
ENABLE_TESTABILITY = YES;
@@ -1866,7 +1870,7 @@
18661870
ONLY_ACTIVE_ARCH = YES;
18671871
SDKROOT = iphoneos;
18681872
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
1869-
SWIFT_VERSION = 3.0.1;
1873+
SWIFT_VERSION = 3.0.1;
18701874
TARGETED_DEVICE_FAMILY = "1,2";
18711875
WARNING_CFLAGS = "-Wall";
18721876
};
@@ -1896,7 +1900,7 @@
18961900
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
18971901
CODE_SIGN_IDENTITY = "iPhone Developer: [email protected] (XZN842LDLT)";
18981902
COPY_PHASE_STRIP = NO;
1899-
CURRENT_PROJECT_VERSION = 39;
1903+
CURRENT_PROJECT_VERSION = 39;
19001904
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
19011905
ENABLE_NS_ASSERTIONS = NO;
19021906
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -1917,7 +1921,7 @@
19171921
MTL_ENABLE_DEBUG_INFO = NO;
19181922
SDKROOT = iphoneos;
19191923
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
1920-
SWIFT_VERSION = 3.0.1;
1924+
SWIFT_VERSION = 3.0.1;
19211925
TARGETED_DEVICE_FAMILY = "1,2";
19221926
VALIDATE_PRODUCT = YES;
19231927
WARNING_CFLAGS = "-Wall";
@@ -1931,7 +1935,7 @@
19311935
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
19321936
CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements;
19331937
CODE_SIGN_IDENTITY = "iPhone Developer";
1934-
DEVELOPMENT_TEAM = "";
1938+
DEVELOPMENT_TEAM = "";
19351939
INFOPLIST_FILE = Loop/Info.plist;
19361940
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
19371941
"OTHER_SWIFT_FLAGS[sdk=iphonesimulator*]" = "-D IOS_SIMULATOR";
@@ -1948,7 +1952,7 @@
19481952
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
19491953
CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements;
19501954
CODE_SIGN_IDENTITY = "iPhone Developer";
1951-
DEVELOPMENT_TEAM = "";
1955+
DEVELOPMENT_TEAM = "";
19521956
INFOPLIST_FILE = Loop/Info.plist;
19531957
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
19541958
PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER)";
@@ -1963,7 +1967,7 @@
19631967
ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication;
19641968
CODE_SIGN_IDENTITY = "iPhone Developer";
19651969
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer";
1966-
DEVELOPMENT_TEAM = "";
1970+
DEVELOPMENT_TEAM = "";
19671971
INFOPLIST_FILE = "WatchApp Extension/Info.plist";
19681972
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
19691973
PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).watchkitapp.watchkitextension";
@@ -1981,7 +1985,7 @@
19811985
ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication;
19821986
CODE_SIGN_IDENTITY = "iPhone Developer";
19831987
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer";
1984-
DEVELOPMENT_TEAM = "";
1988+
DEVELOPMENT_TEAM = "";
19851989
INFOPLIST_FILE = "WatchApp Extension/Info.plist";
19861990
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
19871991
PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).watchkitapp.watchkitextension";
@@ -2000,7 +2004,7 @@
20002004
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
20012005
CODE_SIGN_IDENTITY = "iPhone Developer";
20022006
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer";
2003-
DEVELOPMENT_TEAM = "";
2007+
DEVELOPMENT_TEAM = "";
20042008
IBSC_MODULE = WatchApp_Extension;
20052009
INFOPLIST_FILE = WatchApp/Info.plist;
20062010
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@@ -2020,7 +2024,7 @@
20202024
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
20212025
CODE_SIGN_IDENTITY = "iPhone Developer";
20222026
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer";
2023-
DEVELOPMENT_TEAM = "";
2027+
DEVELOPMENT_TEAM = "";
20242028
IBSC_MODULE = WatchApp_Extension;
20252029
INFOPLIST_FILE = WatchApp/Info.plist;
20262030
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@@ -2038,7 +2042,7 @@
20382042
buildSettings = {
20392043
CLANG_ANALYZER_NONNULL = YES;
20402044
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
2041-
DEVELOPMENT_TEAM = "";
2045+
DEVELOPMENT_TEAM = "";
20422046
INFOPLIST_FILE = DoseMathTests/Info.plist;
20432047
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/Frameworks";
20442048
PRODUCT_BUNDLE_IDENTIFIER = com.loudnate.DoseMathTests;
@@ -2051,7 +2055,7 @@
20512055
buildSettings = {
20522056
CLANG_ANALYZER_NONNULL = YES;
20532057
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
2054-
DEVELOPMENT_TEAM = "";
2058+
DEVELOPMENT_TEAM = "";
20552059
INFOPLIST_FILE = DoseMathTests/Info.plist;
20562060
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/Frameworks";
20572061
PRODUCT_BUNDLE_IDENTIFIER = com.loudnate.DoseMathTests;
@@ -2065,7 +2069,7 @@
20652069
BUNDLE_LOADER = "$(TEST_HOST)";
20662070
CLANG_ANALYZER_NONNULL = YES;
20672071
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
2068-
DEVELOPMENT_TEAM = "";
2072+
DEVELOPMENT_TEAM = "";
20692073
INFOPLIST_FILE = LoopTests/Info.plist;
20702074
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
20712075
PRODUCT_BUNDLE_IDENTIFIER = com.loudnate.LoopTests;
@@ -2080,7 +2084,7 @@
20802084
BUNDLE_LOADER = "$(TEST_HOST)";
20812085
CLANG_ANALYZER_NONNULL = YES;
20822086
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
2083-
DEVELOPMENT_TEAM = "";
2087+
DEVELOPMENT_TEAM = "";
20842088
INFOPLIST_FILE = LoopTests/Info.plist;
20852089
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
20862090
PRODUCT_BUNDLE_IDENTIFIER = com.loudnate.LoopTests;
@@ -2098,7 +2102,7 @@
20982102
CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements";
20992103
CODE_SIGN_IDENTITY = "iPhone Developer";
21002104
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
2101-
DEVELOPMENT_TEAM = "";
2105+
DEVELOPMENT_TEAM = "";
21022106
INFOPLIST_FILE = "Loop Status Extension/Info.plist";
21032107
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
21042108
PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget";
@@ -2117,7 +2121,7 @@
21172121
CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements";
21182122
CODE_SIGN_IDENTITY = "iPhone Developer";
21192123
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
2120-
DEVELOPMENT_TEAM = "";
2124+
DEVELOPMENT_TEAM = "";
21212125
INFOPLIST_FILE = "Loop Status Extension/Info.plist";
21222126
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
21232127
PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget";
@@ -2135,11 +2139,11 @@
21352139
CLANG_WARN_SUSPICIOUS_MOVES = YES;
21362140
CODE_SIGN_IDENTITY = "";
21372141
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
2138-
CURRENT_PROJECT_VERSION = 39;
2142+
CURRENT_PROJECT_VERSION = 39;
21392143
DEFINES_MODULE = YES;
21402144
DEVELOPMENT_TEAM = "";
21412145
DYLIB_COMPATIBILITY_VERSION = 1;
2142-
DYLIB_CURRENT_VERSION = 39;
2146+
DYLIB_CURRENT_VERSION = 39;
21432147
DYLIB_INSTALL_NAME_BASE = "@rpath";
21442148
INFOPLIST_FILE = LoopUI/Info.plist;
21452149
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
@@ -2162,11 +2166,11 @@
21622166
CLANG_WARN_SUSPICIOUS_MOVES = YES;
21632167
CODE_SIGN_IDENTITY = "";
21642168
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
2165-
CURRENT_PROJECT_VERSION = 39;
2169+
CURRENT_PROJECT_VERSION = 39;
21662170
DEFINES_MODULE = YES;
21672171
DEVELOPMENT_TEAM = "";
21682172
DYLIB_COMPATIBILITY_VERSION = 1;
2169-
DYLIB_CURRENT_VERSION = 39;
2173+
DYLIB_CURRENT_VERSION = 39;
21702174
DYLIB_INSTALL_NAME_BASE = "@rpath";
21712175
INFOPLIST_FILE = LoopUI/Info.plist;
21722176
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";

Loop/Extensions/DoseStore.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ extension LoopDataManager {
2727

2828
switch event.pumpEvent {
2929
case let bolus as BolusNormalPumpEvent:
30-
dose = DoseEntry(type: .bolus, startDate: event.date, endDate: event.date.addingTimeInterval(bolus.duration), value: bolus.amount, unit: .units)
30+
// For entries in-progress, use the programmed amount
31+
let units = event.isMutable() ? bolus.programmed : bolus.amount
32+
33+
dose = DoseEntry(type: .bolus, startDate: event.date, endDate: event.date.addingTimeInterval(bolus.duration), value: units, unit: .units)
3134
case is SuspendPumpEvent:
3235
dose = DoseEntry(suspendDate: event.date)
3336
case is ResumePumpEvent:

Loop/Extensions/NewPumpEvent.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//
2+
// NewPumpEvent.swift
3+
// Loop
4+
//
5+
// Copyright © 2017 LoopKit Authors. All rights reserved.
6+
//
7+
8+
import InsulinKit
9+
10+
11+
extension NewPumpEvent {
12+
13+
/// Constructs a pump event placeholder representing a bolus just enacted.
14+
///
15+
/// - Parameters:
16+
/// - units: The units of insulin requested
17+
/// - date: The date the bolus was enacted
18+
static func enactedBolus(units: Double, at date: Date) -> NewPumpEvent {
19+
let dose = DoseEntry(type: .bolus, startDate: date, endDate: date, value: units, unit: .units)
20+
21+
return self.init(
22+
date: date,
23+
dose: dose,
24+
isMutable: true,
25+
raw: Data(), // This can be empty, as mutable events aren't persisted
26+
title: ""
27+
)
28+
}
29+
}

Loop/Managers/DeviceDataManager.swift

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -427,13 +427,16 @@ final class DeviceDataManager {
427427
}
428428

429429
let setBolus = {
430-
ops.setNormalBolus(units: units) { (error) in
431-
if let error = error {
432-
self.logger.addError(error, fromSource: "Bolus")
433-
notify(error)
434-
} else {
435-
self.loopManager.addExpectedBolus(units, at: Date())
436-
notify(nil)
430+
self.loopManager.addRequestedBolus(units: units, at: Date()) {
431+
ops.setNormalBolus(units: units) { (error) in
432+
if let error = error {
433+
self.logger.addError(error, fromSource: "Bolus")
434+
notify(error)
435+
} else {
436+
self.loopManager.addConfirmedBolus(units: units, at: Date()) {
437+
notify(nil)
438+
}
439+
}
437440
}
438441
}
439442
}
@@ -735,28 +738,33 @@ extension DeviceDataManager: LoopDataManagerDelegate {
735738
return
736739
}
737740

741+
let notify = { (result: Result<DoseEntry>) -> Void in
742+
// If we haven't fetched history in a while (preferredInsulinDataSource == .reservoir),
743+
// let's try to do so while the pump radio is on.
744+
if self.loopManager.doseStore.lastAddedPumpEvents.timeIntervalSinceNow < .minutes(-4) {
745+
self.fetchPumpHistory { (_) in
746+
completion(result)
747+
}
748+
} else {
749+
completion(result)
750+
}
751+
}
752+
738753
ops.setTempBasal(rate: basal.rate, duration: basal.duration) { (result) -> Void in
739754
switch result {
740755
case .success(let body):
741756
let now = Date()
742757
let endDate = now.addingTimeInterval(body.timeRemaining)
743758
let startDate = endDate.addingTimeInterval(-basal.duration)
744-
745-
completion(.success(DoseEntry(
759+
notify(.success(DoseEntry(
746760
type: .tempBasal,
747761
startDate: startDate,
748762
endDate: endDate,
749763
value: body.rate,
750764
unit: .unitsPerHour
751765
)))
752-
753-
// If we haven't fetched history in a while (preferredInsulinDataSource == .reservoir),
754-
// let's try to do so while the pump radio is on.
755-
if self.loopManager.doseStore.lastAddedPumpEvents.timeIntervalSinceNow < .minutes(-4) {
756-
self.fetchPumpHistory { (_) in }
757-
}
758766
case .failure(let error):
759-
completion(.failure(error))
767+
notify(.failure(error))
760768
}
761769
}
762770
}

0 commit comments

Comments
 (0)