Skip to content
Open
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
42 changes: 33 additions & 9 deletions TidepoolServiceKit/Extensions/StoredSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,18 @@ import TidepoolKit
- date Date .time
- controllerTimeZone TimeInterval .timeZone, .timeZoneOffset
- dosingEnabled Bool TPumpSettingsDatum.automatedDelivery
- glucoseTargetRangeSchedule GlucoseRangeSchedule? TPumpSettingsDatum.bloodGlucoseTargetSchedules["Default"]
- glucoseTargetRangeSchedule GlucoseRangeSchedule? TPumpSettingsDatum.bloodGlucoseTargetSchedules[activeScheduleName]
- preMealTargetRange ClosedRange<HKQuantity>? TPumpSettingsDatum.bloodGlucoseTargetPreprandial
- overridePresets [TemporaryScheduleOverridePreset]? TPumpSettingsDatum.overridePresets
- maximumBasalRatePerHour Double? TPumpSettingsDatum.basal.rateMaximum.value
- maximumBolus Double? TPumpSettingsDatum.bolus.amountMaximum.value
- suspendThreshold GlucoseThreshold? TPumpSettingsDatum.bloodGlucoseSafetyLimit
- defaultRapidActingModel StoredInsulinModel? TPumpSettingsDatum.insulinModel
- basalRateSchedule BasalRateSchedule? TPumpSettingsDatum.basalRateSchedules["Default"]
- insulinSensitivitySchedule InsulinSensitivitySchedule? TPumpSettingsDatum.insulinSensitivitySchedules["Default"]
- carbRatioSchedule CarbRatioSchedule? TPumpSettingsDatum.carbohydrateRatioSchedules["Default"]
- basalRateSchedule BasalRateSchedule? TPumpSettingsDatum.basalRateSchedules[activeScheduleName]
- insulinSensitivitySchedule InsulinSensitivitySchedule? TPumpSettingsDatum.insulinSensitivitySchedules[activeScheduleName]
- carbRatioSchedule CarbRatioSchedule? TPumpSettingsDatum.carbohydrateRatioSchedules[activeScheduleName]
- therapyProfiles [TherapyProfile] the four schedule dictionaries, keyed by profile name
- activeProfileName String? TPumpSettingsDatum.activeScheduleName ("Default" when nil)
- notificationSettings NotificationSettings? TControllerSettingsDatum.notifications
- controllerDevice ControllerDevice? TControllerSettingsDatum.device
- pumpDevice HKDevice? TPumpSettingsDatum[.firmwareVersion, .hardwareVersion, .manufacturers, .model, .serialNumber, .softwareVersion]
Expand Down Expand Up @@ -144,7 +146,21 @@ extension StoredSettings: IdentifiableDatum {
private var datumCGMUnits: TCGMSettingsDatum.Units { .milligramsPerDeciliter }

private var datumPumpActiveScheduleName: String? {
return Self.activeScheduleNameDefault
return TherapyProfiles.activeName(activeProfileName)
}

/// The profiles other than the active one, whose schedules are the live ones.
private var datumInactiveProfiles: [TherapyProfile] {
let activeName = TherapyProfiles.activeName(activeProfileName)
return resolvedTherapyProfiles.filter { $0.name != activeName }
}

private func datumSchedules<Value>(live: [Value], _ transform: (TherapyProfile) -> [Value]) -> [String: [Value]] {
var schedules = [TherapyProfiles.activeName(activeProfileName): live]
for profile in datumInactiveProfiles {
schedules[profile.name] = transform(profile)
}
return schedules
}

private var datumPumpBasal: TPumpSettingsDatum.Basal? {
Expand All @@ -158,7 +174,9 @@ extension StoredSettings: IdentifiableDatum {
guard let basalRateSchedule = basalRateSchedule else {
return nil
}
return [Self.activeScheduleNameDefault: basalRateSchedule.items.map { TPumpSettingsDatum.BasalRateStart(start: $0.startTime, rate: $0.value) }]
return datumSchedules(live: basalRateSchedule.items.map { TPumpSettingsDatum.BasalRateStart(start: $0.startTime, rate: $0.value) }) { profile in
profile.basalRateSchedule.items.map { TPumpSettingsDatum.BasalRateStart(start: $0.startTime, rate: $0.value) }
}
}

private var datumPumpBloodGlucoseSafetyLimit: Double? {
Expand All @@ -180,7 +198,9 @@ extension StoredSettings: IdentifiableDatum {
guard let glucoseTargetRangeSchedule = glucoseTargetRangeSchedule else {
return nil
}
return [Self.activeScheduleNameDefault: glucoseTargetRangeSchedule.items(for: .milligramsPerDeciliter).map { TPumpSettingsDatum.BloodGlucoseStartTarget(start: $0.startTime, low: $0.value.minValue, high: $0.value.maxValue) }]
return datumSchedules(live: glucoseTargetRangeSchedule.items(for: .milligramsPerDeciliter).map { TPumpSettingsDatum.BloodGlucoseStartTarget(start: $0.startTime, low: $0.value.minValue, high: $0.value.maxValue) }) { profile in
profile.glucoseTargetRangeSchedule.items(for: .milligramsPerDeciliter).map { TPumpSettingsDatum.BloodGlucoseStartTarget(start: $0.startTime, low: $0.value.minValue, high: $0.value.maxValue) }
}
}

private var datumPumpBolus: TPumpSettingsDatum.Bolus? {
Expand All @@ -194,7 +214,9 @@ extension StoredSettings: IdentifiableDatum {
guard let carbRatioSchedule = carbRatioSchedule else {
return nil
}
return [Self.activeScheduleNameDefault: carbRatioSchedule.items(for: .gram).map { TPumpSettingsDatum.CarbohydrateRatioStart(start: $0.startTime, amount: $0.value) }]
return datumSchedules(live: carbRatioSchedule.items(for: .gram).map { TPumpSettingsDatum.CarbohydrateRatioStart(start: $0.startTime, amount: $0.value) }) { profile in
profile.carbRatioSchedule.items(for: .gram).map { TPumpSettingsDatum.CarbohydrateRatioStart(start: $0.startTime, amount: $0.value) }
}
}

private var datumPumpDisplay: TPumpSettingsDatum.Display? {
Expand Down Expand Up @@ -250,7 +272,9 @@ extension StoredSettings: IdentifiableDatum {
guard let insulinSensitivitySchedule = insulinSensitivitySchedule else {
return nil
}
return [Self.activeScheduleNameDefault: insulinSensitivitySchedule.items(for: .milligramsPerDeciliter).map { return TPumpSettingsDatum.InsulinSensitivityStart(start: $0.startTime, amount: $0.value) }]
return datumSchedules(live: insulinSensitivitySchedule.items(for: .milligramsPerDeciliter).map { TPumpSettingsDatum.InsulinSensitivityStart(start: $0.startTime, amount: $0.value) }) { profile in
profile.insulinSensitivitySchedule.items(for: .milligramsPerDeciliter).map { TPumpSettingsDatum.InsulinSensitivityStart(start: $0.startTime, amount: $0.value) }
}
}

private var datumPumpManufacturers: [String]? { pumpDevice?.manufacturer.map { [$0] } }
Expand Down
20 changes: 20 additions & 0 deletions TidepoolServiceKitTests/Extensions/StoredSettingsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,26 @@ class StoredSettingsTests: XCTestCase {
)
}

func testDatumPumpSettingsNamesSchedulesAfterProfiles() {
var settings = StoredSettings.test
let live = settings.liveTherapyProfile!
var sport = live
sport.name = "Sport"
settings.basalRateSchedule = BasalRateSchedule(dailyItems: [RepeatingScheduleValue(startTime: 0, value: 0.5)], timeZone: live.basalRateSchedule.timeZone)
sport.basalRateSchedule = settings.basalRateSchedule!
settings.therapyProfiles = [live, sport]
settings.activeProfileName = "Sport"

let datum = settings.datumPumpSettings(for: "1234567890", hostIdentifier: "Loop", hostVersion: "1.2.3")

XCTAssertEqual(datum.activeScheduleName, "Sport")
XCTAssertEqual(datum.basalRateSchedules?["Sport"]?.map(\.rate), [0.5])
XCTAssertEqual(datum.basalRateSchedules?["Default"]?.count, live.basalRateSchedule.items.count)
XCTAssertEqual(Set(datum.carbohydrateRatioSchedules?.keys ?? [:].keys), ["Default", "Sport"])
XCTAssertEqual(Set(datum.insulinSensitivitySchedules?.keys ?? [:].keys), ["Default", "Sport"])
XCTAssertEqual(Set(datum.bloodGlucoseTargetSchedules?.keys ?? [:].keys), ["Default", "Sport"])
}

private static let encoder: JSONEncoder = {
let encoder = JSONEncoder.tidepool
encoder.outputFormatting.insert(.prettyPrinted)
Expand Down
4 changes: 4 additions & 0 deletions TidepoolServiceKitTests/TidepoolServiceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,10 @@ private class MockServiceDelegate: ServiceDelegate {
func cancelRemoteOverride() async throws {}
func deliverRemoteCarbs(amountInGrams: Double, absorptionTime: TimeInterval?, foodType: String?, startDate: Date?) async throws {}
func deliverRemoteBolus(amountInUnits: Double, decisionId: UUID?) async throws {}
func switchRemoteTherapyProfile(name: String, expectedFingerprint: String) async throws {}
func saveRemoteTherapyProfile(_ profile: TherapyProfile, originalName: String?, expectedFingerprint: String?) async throws {}
func deleteRemoteTherapyProfile(name: String, expectedFingerprint: String) async throws {}
func saveRemoteScheduledProfileSwitches(_ entries: [ScheduledProfileSwitch], expectedFingerprint: String) async throws {}
}

fileprivate extension StoredSettings.ControllerDevice {
Expand Down