Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cartfile.resolved
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
github "LoopKit/Amplitude-iOS" "2137d5fd44bf630ed33e1e72d7af6d8f8612f270"
github "LoopKit/CGMBLEKit" "fe92d93c24d18ff9755ff027e9b036d3769a8a0a"
github "LoopKit/G4ShareSpy" "f6ae0cf1753131135f26046ddf07e096da884b84"
github "LoopKit/LoopKit" "dfc5268c1f1b92c76e949d48d9a1fd9c51f87a6c"
github "LoopKit/LoopKit" "eaed65166138c5ea1b8d8dddc7b14f1032f3da06"
github "LoopKit/dexcom-share-client-swift" "cdbb1cd19cf54b37add6d6c25300445a6abe24da"
github "i-schuetz/SwiftCharts" "0.6.5"
github "maxkonovalov/MKRingProgressView" "2.2.2"
github "ps2/rileylink_ios" "7297016d4fc063c75c40f9e8402e303df78816aa"
github "ps2/rileylink_ios" "3a5a92c9a69565dc32c916294826b4e7ae02297e"
14 changes: 7 additions & 7 deletions Common/Models/StatusExtensionContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct NetBasalContext {
let rate: Double
let percentage: Double
let start: Date
let end: Date
let end: Date?
}

struct SensorDisplayableContext: SensorDisplayable {
Expand Down Expand Up @@ -56,28 +56,28 @@ extension NetBasalContext: RawRepresentable {
typealias RawValue = [String: Any]

var rawValue: RawValue {
return [
var value: RawValue = [
"rate": rate,
"percentage": percentage,
"start": start,
"end": end
"start": start
]
value["end"] = end
return value
}

init?(rawValue: RawValue) {
guard
let rate = rawValue["rate"] as? Double,
let percentage = rawValue["percentage"] as? Double,
let start = rawValue["start"] as? Date,
let end = rawValue["end"] as? Date
let start = rawValue["start"] as? Date
else {
return nil
}

self.rate = rate
self.percentage = percentage
self.start = start
self.end = end
self.end = rawValue["end"] as? Date
}
}

Expand Down
20 changes: 12 additions & 8 deletions Loop.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@
C1C73F0D1DE3D0270022FC89 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = C1C73F0F1DE3D0270022FC89 /* InfoPlist.strings */; };
C1C7F1C1220D675800689850 /* OmniKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1C7F1BF220D675700689850 /* OmniKit.framework */; };
C1C7F1C2220D675800689850 /* OmniKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1C7F1C0220D675700689850 /* OmniKitUI.framework */; };
C1D289B522F90A52003FFBD9 /* BasalDeliveryState.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D289B422F90A52003FFBD9 /* BasalDeliveryState.swift */; };
C1E2773E224177C000354103 /* ClockKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1E2773D224177C000354103 /* ClockKit.framework */; };
C1E2774822433D7A00354103 /* MKRingProgressView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1E2774722433D7A00354103 /* MKRingProgressView.framework */; };
C1F8B243223E73FD00DD66CF /* BolusProgressTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1F8B1D122375E4200DD66CF /* BolusProgressTableViewCell.swift */; };
Expand Down Expand Up @@ -1030,6 +1031,7 @@
C1C6591B1E1B1FDA0025CC58 /* recommend_temp_basal_dropping_then_rising.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = recommend_temp_basal_dropping_then_rising.json; sourceTree = "<group>"; };
C1C7F1BF220D675700689850 /* OmniKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OmniKit.framework; path = Carthage/Build/iOS/OmniKit.framework; sourceTree = "<group>"; };
C1C7F1C0220D675700689850 /* OmniKitUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OmniKitUI.framework; path = Carthage/Build/iOS/OmniKitUI.framework; sourceTree = "<group>"; };
C1D289B422F90A52003FFBD9 /* BasalDeliveryState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasalDeliveryState.swift; sourceTree = "<group>"; };
C1E2773D224177C000354103 /* ClockKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ClockKit.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS.sdk/System/Library/Frameworks/ClockKit.framework; sourceTree = DEVELOPER_DIR; };
C1E2774722433D7A00354103 /* MKRingProgressView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MKRingProgressView.framework; sourceTree = BUILT_PRODUCTS_DIR; };
C1F8B1D122375E4200DD66CF /* BolusProgressTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BolusProgressTableViewCell.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1526,6 +1528,7 @@
437CEEE31CDE5C0A003C8C80 /* UIImage.swift */,
434FF1ED1CF27EEF000DB779 /* UITableViewCell.swift */,
430B29922041F5B200BA9F93 /* UserDefaults+Loop.swift */,
C1D289B422F90A52003FFBD9 /* BasalDeliveryState.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -2454,6 +2457,7 @@
43C05CC521EC29E3006FB252 /* TextFieldTableViewCell.swift in Sources */,
4FF4D1001E18374700846527 /* WatchContext.swift in Sources */,
4315D28A1CA5F45E00589052 /* DiagnosticLogger+LoopKit.swift in Sources */,
C1D289B522F90A52003FFBD9 /* BasalDeliveryState.swift in Sources */,
4F2C15821E074FC600E160D4 /* NSTimeInterval.swift in Sources */,
4311FB9B1F37FE1B00D4C0A7 /* TitleSubtitleTextFieldTableViewCell.swift in Sources */,
C1FB428F217921D600FAB378 /* PumpManagerUI.swift in Sources */,
Expand Down Expand Up @@ -3319,7 +3323,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = "$(APPICON_NAME)";
CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
DEVELOPMENT_TEAM = UY678SP37Q;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = Loop/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
"OTHER_SWIFT_FLAGS[arch=*]" = "-DDEBUG";
Expand All @@ -3337,7 +3341,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = "$(APPICON_NAME)";
CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
DEVELOPMENT_TEAM = UY678SP37Q;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = Loop/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER)";
Expand All @@ -3354,7 +3358,7 @@
CODE_SIGN_ENTITLEMENTS = "WatchApp Extension/WatchApp Extension.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer";
DEVELOPMENT_TEAM = UY678SP37Q;
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS";
INFOPLIST_FILE = "WatchApp Extension/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
Expand All @@ -3377,7 +3381,7 @@
CODE_SIGN_ENTITLEMENTS = "WatchApp Extension/WatchApp Extension.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer";
DEVELOPMENT_TEAM = UY678SP37Q;
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS";
INFOPLIST_FILE = "WatchApp Extension/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
Expand All @@ -3398,7 +3402,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = "$(APPICON_NAME)";
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer";
DEVELOPMENT_TEAM = UY678SP37Q;
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS";
IBSC_MODULE = WatchApp_Extension;
INFOPLIST_FILE = WatchApp/Info.plist;
Expand All @@ -3419,7 +3423,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = "$(APPICON_NAME)";
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer";
DEVELOPMENT_TEAM = UY678SP37Q;
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS";
IBSC_MODULE = WatchApp_Extension;
INFOPLIST_FILE = WatchApp/Info.plist;
Expand Down Expand Up @@ -3698,7 +3702,7 @@
CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
DEVELOPMENT_TEAM = UY678SP37Q;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "Loop Status Extension/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget";
Expand All @@ -3717,7 +3721,7 @@
CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
DEVELOPMENT_TEAM = UY678SP37Q;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "Loop Status Extension/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget";
Expand Down
50 changes: 50 additions & 0 deletions Loop/Extensions/BasalDeliveryState.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// BasalDeliveryState.swift
// Loop
//
// Created by Pete Schwamb on 8/5/19.
// Copyright © 2019 LoopKit Authors. All rights reserved.
//

import LoopKit
import LoopCore

extension PumpManagerStatus.BasalDeliveryState {
func getNetBasal(basalSchedule: BasalRateSchedule, settings: LoopSettings) -> NetBasal? {
func scheduledBasal(for date: Date) -> AbsoluteScheduleValue<Double>? {
return basalSchedule.between(start: date, end: date).first
}

switch self {
case .tempBasal(let dose):
if let scheduledBasal = scheduledBasal(for: dose.startDate) {
return NetBasal(
lastTempBasal: dose,
maxBasal: settings.maximumBasalRatePerHour,
scheduledBasal: scheduledBasal
)
} else {
return nil
}
case .suspended(let date):
if let scheduledBasal = scheduledBasal(for: date) {
return NetBasal(
suspendedAt: date,
maxBasal: settings.maximumBasalRatePerHour,
scheduledBasal: scheduledBasal
)
} else {
return nil
}
case .active(let date):
if let scheduledBasal = scheduledBasal(for: date) {
return NetBasal(scheduledRateStartedAt: date, scheduledBasal: scheduledBasal)
} else {
return nil
}
default:
return nil
}
}
}

4 changes: 2 additions & 2 deletions Loop/Extensions/PersistedPumpEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ extension PersistedPumpEvent {
timestamp: dose.startDate,
enteredBy: source,
bolusType: duration > 0 ? .Square : .Normal,
amount: dose.units,
programmed: dose.units, // Persisted pump events are always completed
amount: dose.deliveredUnits ?? dose.programmedUnits,
programmed: dose.programmedUnits, // Persisted pump events are always completed
unabsorbed: 0, // The pump's reported IOB isn't relevant, nor stored
duration: duration,
carbs: 0,
Expand Down
34 changes: 24 additions & 10 deletions Loop/Managers/DeviceDataManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,11 @@ final class DeviceDataManager {

remoteDataManager.delegate = self
statusExtensionManager = StatusExtensionDataManager(deviceDataManager: self)

loopManager = LoopDataManager(
lastLoopCompleted: statusExtensionManager.context?.lastLoopCompleted,
lastTempBasal: statusExtensionManager.context?.netBasal?.tempBasal
basalDeliveryState: pumpManager?.status.basalDeliveryState,
lastPumpEventsReconciliation: pumpManager?.lastReconciliation
)
watchManager = WatchDataManager(deviceManager: self)
nightscoutDataManager = NightscoutDataManager(deviceDataManager: self)
Expand Down Expand Up @@ -145,24 +147,25 @@ private extension DeviceDataManager {

// MARK: - Client API
extension DeviceDataManager {
func enactBolus(units: Double, at startDate: Date = Date(), willRequest: ((DoseEntry) -> Void)? = nil, completion: @escaping (_ error: Error?) -> Void) {
func enactBolus(units: Double, at startDate: Date = Date(), completion: @escaping (_ error: Error?) -> Void) {
guard let pumpManager = pumpManager else {
completion(LoopError.configurationError(.pumpManager))
return
}

self.loopManager.addRequestedBolus(DoseEntry(type: .bolus, startDate: Date(), value: units, unit: .units), completion: nil)
pumpManager.enactBolus(units: units, at: startDate, willRequest: { (dose) in
self.loopManager.addRequestedBolus(dose, completion: {
willRequest?(dose)
})
// No longer used...
}) { (result) in
switch result {
case .failure(let error):
self.log.error(error)
NotificationManager.sendBolusFailureNotification(for: error, units: units, at: startDate)
completion(error)
self.loopManager.bolusRequestFailed(error) {
completion(error)
}
case .success(let dose):
self.loopManager.addConfirmedBolus(dose) {
self.loopManager.bolusConfirmed(dose) {
completion(nil)
}
}
Expand Down Expand Up @@ -234,6 +237,7 @@ extension DeviceDataManager: CGMManagerDelegate {
}
}

self.log.default("Asserting current pump data")
self.pumpManager?.assertCurrentPumpData()
}
case .noData:
Expand All @@ -244,6 +248,7 @@ extension DeviceDataManager: CGMManagerDelegate {
log.default("CGMManager:\(type(of: manager)) did update with error: \(error)")

self.setLastError(error: error)
log.default("Asserting current pump data")
pumpManager?.assertCurrentPumpData()
}

Expand Down Expand Up @@ -295,7 +300,7 @@ extension DeviceDataManager: PumpManagerDelegate {
bleHeartbeatUpdateInterval = .minutes(1)
case let interval?:
// If we looped successfully less than 5 minutes ago, ignore the heartbeat.
log.default("PumpManager:\(type(of: pumpManager)) ignoring heartbeat. Last loop completed \(interval.minutes) ago")
log.default("PumpManager:\(type(of: pumpManager)) ignoring heartbeat. Last loop completed \(interval.minutes) minutes ago")
return
}

Expand Down Expand Up @@ -349,6 +354,10 @@ extension DeviceDataManager: PumpManagerDelegate {
}
}

if status.basalDeliveryState != oldStatus.basalDeliveryState {
loopManager.basalDeliveryState = status.basalDeliveryState
}

// Update the pump-schedule based settings
loopManager.setScheduleTimeZone(status.timeZone)
}
Expand Down Expand Up @@ -379,16 +388,20 @@ extension DeviceDataManager: PumpManagerDelegate {
nightscoutDataManager.uploadLoopStatus(loopError: error)
}

func pumpManager(_ pumpManager: PumpManager, didReadPumpEvents events: [NewPumpEvent], completion: @escaping (_ error: Error?) -> Void) {
func pumpManager(_ pumpManager: PumpManager, hasNewPumpEvents events: [NewPumpEvent], lastReconciliation: Date?, completion: @escaping (_ error: Error?) -> Void) {
dispatchPrecondition(condition: .onQueue(queue))
log.default("PumpManager:\(type(of: pumpManager)) did read pump events")

loopManager.addPumpEvents(events) { (error) in
loopManager.addPumpEvents(events, lastReconciliation: lastReconciliation) { (error) in
if let error = error {
self.log.error("Failed to addPumpEvents to DoseStore: \(error)")
}

completion(error)

if error == nil {
NotificationCenter.default.post(name: .PumpEventsAdded, object: self, userInfo: nil)
}
}
}

Expand Down Expand Up @@ -580,5 +593,6 @@ extension DeviceDataManager: CustomDebugStringConvertible {

extension Notification.Name {
static let PumpManagerChanged = Notification.Name(rawValue: "com.loopKit.notification.PumpManagerChanged")
static let PumpEventsAdded = Notification.Name(rawValue: "com.loopKit.notification.PumpEventsAdded")
}

Loading