diff --git a/OmnipodKit/OmnipodCommon/PendingCommand.swift b/OmnipodKit/OmnipodCommon/PendingCommand.swift index bdfdd2e..2480357 100644 --- a/OmnipodKit/OmnipodCommon/PendingCommand.swift +++ b/OmnipodKit/OmnipodCommon/PendingCommand.swift @@ -13,7 +13,7 @@ import Foundation enum StartProgram: RawRepresentable { typealias RawValue = [String: Any] - case bolus(volume: Double, automatic: Bool) + case bolus(volume: Double, automatic: Bool, bolusReference: UUID? = nil) case basalProgram(schedule: BasalSchedule) case tempBasal(unitsPerHour: Double, duration: TimeInterval, isHighTemp: Bool, automatic: Bool) @@ -23,12 +23,14 @@ enum StartProgram: RawRepresentable { var rawValue: RawValue { switch self { - case .bolus(let volume, let automatic): - return [ + case .bolus(let volume, let automatic, let bolusReference): + var raw: RawValue = [ "programType": StartProgramType.bolus.rawValue, "volume": volume, "automatic": automatic ] + raw["bolusReference"] = bolusReference?.uuidString + return raw case .basalProgram(let schedule): return [ "programType": StartProgramType.basalProgram.rawValue, @@ -58,7 +60,7 @@ enum StartProgram: RawRepresentable { { return nil } - self = .bolus(volume: volume, automatic: automatic) + self = .bolus(volume: volume, automatic: automatic, bolusReference: (rawValue["bolusReference"] as? String).flatMap { UUID(uuidString: $0) }) case .basalProgram: guard let rawSchedule = rawValue["schedule"] as? BasalSchedule.RawValue, let schedule = BasalSchedule(rawValue: rawSchedule) else @@ -80,8 +82,8 @@ enum StartProgram: RawRepresentable { static func == (lhs: StartProgram, rhs: StartProgram) -> Bool { switch(lhs, rhs) { - case (.bolus(let lhsVolume, let lhsAutomatic), .bolus(let rhsVolume, let rhsAutomatic)): - return lhsVolume == rhsVolume && lhsAutomatic == rhsAutomatic + case (.bolus(let lhsVolume, let lhsAutomatic, let lhsBolusReference), .bolus(let rhsVolume, let rhsAutomatic, let rhsBolusReference)): + return lhsVolume == rhsVolume && lhsAutomatic == rhsAutomatic && lhsBolusReference == rhsBolusReference case (.basalProgram(let lhsSchedule), .basalProgram(let rhsSchedule)): return lhsSchedule == rhsSchedule case (.tempBasal(let lhsUnitsPerHour, let lhsDuration, let lhsIsHighTemp, let lhsAutomatic), .tempBasal(let rhsUnitsPerHour, let rhsDuration, let rhsIsHighTemp, let rhsAutomatic)): diff --git a/OmnipodKit/OmnipodCommon/UnfinalizedDose.swift b/OmnipodKit/OmnipodCommon/UnfinalizedDose.swift index dc31da6..8e179a5 100644 --- a/OmnipodKit/OmnipodCommon/UnfinalizedDose.swift +++ b/OmnipodKit/OmnipodCommon/UnfinalizedDose.swift @@ -67,6 +67,7 @@ public struct UnfinalizedDose: RawRepresentable, Equatable, CustomStringConverti var isHighTemp: Bool = false // Track this for situations where cancelling temp basal is unacknowledged, and recovery fails, and we have to assume the most possible delivery var insulinType: InsulinType? + var bolusReference: UUID? // Opaque, caller-supplied reference echoed back on the resulting DoseEntry; not interpreted by the pump var finishTime: Date? { get { @@ -110,7 +111,8 @@ public struct UnfinalizedDose: RawRepresentable, Equatable, CustomStringConverti startTime: Date, scheduledCertainty: ScheduledCertainty, insulinType: InsulinType, - automatic: Bool = false + automatic: Bool = false, + bolusReference: UUID? = nil ) { doseType = .bolus units = bolusAmount @@ -120,6 +122,7 @@ public struct UnfinalizedDose: RawRepresentable, Equatable, CustomStringConverti scheduledUnits = nil self.automatic = automatic self.insulinType = insulinType + self.bolusReference = bolusReference } init( @@ -324,6 +327,8 @@ public struct UnfinalizedDose: RawRepresentable, Equatable, CustomStringConverti if let rawInsulinType = rawValue["insulinType"] as? InsulinType.RawValue { insulinType = InsulinType(rawValue: rawInsulinType) } + + bolusReference = (rawValue["bolusReference"] as? String).flatMap { UUID(uuidString: $0) } } public var rawValue: RawValue { @@ -340,6 +345,7 @@ public struct UnfinalizedDose: RawRepresentable, Equatable, CustomStringConverti rawValue["scheduledTempRate"] = scheduledTempRate rawValue["duration"] = duration rawValue["insulinType"] = insulinType?.rawValue + rawValue["bolusReference"] = bolusReference?.uuidString return rawValue } @@ -377,7 +383,8 @@ extension DoseEntry { deliveredUnits: dose.finalizedUnits, insulinType: dose.insulinType, automatic: dose.automatic, - isMutable: dose.isMutable() + isMutable: dose.isMutable(), + bolusReference: dose.bolusReference ) case .tempBasal: self = DoseEntry( @@ -406,13 +413,14 @@ extension StartProgram { insulinType: InsulinType ) -> UnfinalizedDose? { switch self { - case let .bolus(volume: volume, automatic: automatic): + case let .bolus(volume: volume, automatic: automatic, bolusReference: bolusReference): return UnfinalizedDose( bolusAmount: volume, startTime: programDate, scheduledCertainty: certainty, insulinType: insulinType, - automatic: automatic + automatic: automatic, + bolusReference: bolusReference ) case let .tempBasal(unitsPerHour: rate, duration: duration, isHighTemp, automatic): return UnfinalizedDose( diff --git a/OmnipodKit/PumpManager/OmniPumpManager.swift b/OmnipodKit/PumpManager/OmniPumpManager.swift index 42d846f..f3a6ccf 100644 --- a/OmnipodKit/PumpManager/OmniPumpManager.swift +++ b/OmnipodKit/PumpManager/OmniPumpManager.swift @@ -2488,6 +2488,10 @@ extension OmniPumpManager: PumpManager { // MARK: - Programming Delivery public func enactBolus(units: Double, activationType: BolusActivationType, completion: @escaping (PumpManagerError?) -> Void) { + enactBolus(units: units, activationType: activationType, bolusReference: nil, completion: completion) + } + + public func enactBolus(units: Double, activationType: BolusActivationType, bolusReference: UUID?, completion: @escaping (PumpManagerError?) -> Void) { guard self.hasActivePod else { completion(.configuration(OmniPumpManagerError.noPodPaired)) return @@ -2552,7 +2556,7 @@ extension OmniPumpManager: PumpManager { // in 63 minutes if bolus had not completed by then. let bolusWasAutomaticIndicator: TimeInterval = activationType.isAutomatic ? TimeInterval(minutes: 0x3F) : 0 - let result = session.bolus(units: enactUnits, automatic: activationType.isAutomatic, acknowledgementBeep: acknowledgementBeep, completionBeep: completionBeep, programReminderInterval: bolusWasAutomaticIndicator) + let result = session.bolus(units: enactUnits, automatic: activationType.isAutomatic, acknowledgementBeep: acknowledgementBeep, completionBeep: completionBeep, programReminderInterval: bolusWasAutomaticIndicator, bolusReference: bolusReference) switch result { case .success: diff --git a/OmnipodKit/PumpManager/PodCommsSession.swift b/OmnipodKit/PumpManager/PodCommsSession.swift index 3b93281..971f0cd 100644 --- a/OmnipodKit/PumpManager/PodCommsSession.swift +++ b/OmnipodKit/PumpManager/PodCommsSession.swift @@ -666,7 +666,7 @@ class PodCommsSession: MessageTransportDelegate { case unacknowledged(error: PodCommsError) } - func bolus(units: Double, automatic: Bool = false, acknowledgementBeep: Bool = false, completionBeep: Bool = false, programReminderInterval: TimeInterval = 0, extendedUnits: Double = 0.0, extendedDuration: TimeInterval = 0) -> DeliveryCommandResult { + func bolus(units: Double, automatic: Bool = false, acknowledgementBeep: Bool = false, completionBeep: Bool = false, programReminderInterval: TimeInterval = 0, extendedUnits: Double = 0.0, extendedDuration: TimeInterval = 0, bolusReference: UUID? = nil) -> DeliveryCommandResult { if podState.unacknowledgedCommand != nil { do { @@ -710,10 +710,10 @@ class PodCommsSession: MessageTransportDelegate { let bolusExtraCommand = BolusExtraCommand(units: units, timeBetweenPulses: timeBetweenPulses, extendedUnits: extendedUnits, extendedDuration: extendedDuration, acknowledgementBeep: acknowledgementBeep, completionBeep: completionBeep, programReminderInterval: programReminderInterval, bolusInfo: bolusInfo) do { - podState.unacknowledgedCommand = PendingCommand.program(.bolus(volume: units, automatic: automatic), transport.messageNumber, currentDate) + podState.unacknowledgedCommand = PendingCommand.program(.bolus(volume: units, automatic: automatic, bolusReference: bolusReference), transport.messageNumber, currentDate) let statusResponse: StatusResponse = try send([bolusScheduleCommand, bolusExtraCommand]) podState.unacknowledgedCommand = nil - podState.unfinalizedBolus = UnfinalizedDose(bolusAmount: units, startTime: currentDate, scheduledCertainty: .certain, insulinType: podState.insulinType, automatic: automatic) + podState.unfinalizedBolus = UnfinalizedDose(bolusAmount: units, startTime: currentDate, scheduledCertainty: .certain, insulinType: podState.insulinType, automatic: automatic, bolusReference: bolusReference) podState.updateFromStatusResponse(statusResponse, at: currentDate) return DeliveryCommandResult.success(statusResponse: statusResponse) } catch PodCommsError.unacknowledgedMessage(let seq, let error) {