diff --git a/.travis.yml b/.travis.yml index 7834eff41..88cc82c9b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: objective-c -osx_image: xcode8 -xcode_sdk: iphonesimulator10 +osx_image: xcode8.3 +xcode_sdk: iphonesimulator10.3 xcode_project: RileyLink.xcodeproj xcode_scheme: RileyLink script: - - xcodebuild -project RileyLink.xcodeproj -scheme RileyLink -sdk iphonesimulator10.0 build -destination 'name=iPhone SE' test + - xcodebuild -project RileyLink.xcodeproj -scheme RileyLink -sdk iphonesimulator10.3 build -destination 'name=iPhone SE' test diff --git a/Crypto/Info.plist b/Crypto/Info.plist index fbe1e6b31..f9a819406 100644 --- a/Crypto/Info.plist +++ b/Crypto/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0 + 1.0.1 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass diff --git a/MinimedKit/Info.plist b/MinimedKit/Info.plist index d3de8eefb..7a8455339 100644 --- a/MinimedKit/Info.plist +++ b/MinimedKit/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0 + 1.0.1 CFBundleSignature ???? CFBundleVersion diff --git a/MinimedKitTests/Info.plist b/MinimedKitTests/Info.plist index bec4c60a2..c41602f9c 100644 --- a/MinimedKitTests/Info.plist +++ b/MinimedKitTests/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.0 + 1.0.1 CFBundleSignature ???? CFBundleVersion diff --git a/NightscoutUploadKit/DeviceStatus/PumpStatus.swift b/NightscoutUploadKit/DeviceStatus/PumpStatus.swift index 335b97994..a69092f2c 100644 --- a/NightscoutUploadKit/DeviceStatus/PumpStatus.swift +++ b/NightscoutUploadKit/DeviceStatus/PumpStatus.swift @@ -16,8 +16,9 @@ public struct PumpStatus { let suspended: Bool? let bolusing: Bool? let reservoir: Double? - - public init(clock: Date, pumpID: String, iob: IOBStatus? = nil, battery: BatteryStatus? = nil, suspended: Bool? = nil, bolusing: Bool? = nil, reservoir: Double? = nil) { + let secondsFromGMT: Int? + + public init(clock: Date, pumpID: String, iob: IOBStatus? = nil, battery: BatteryStatus? = nil, suspended: Bool? = nil, bolusing: Bool? = nil, reservoir: Double? = nil, secondsFromGMT: Int? = nil) { self.clock = clock self.pumpID = pumpID self.iob = iob @@ -25,6 +26,7 @@ public struct PumpStatus { self.suspended = suspended self.bolusing = bolusing self.reservoir = reservoir + self.secondsFromGMT = secondsFromGMT } public var dictionaryRepresentation: [String: Any] { @@ -32,17 +34,29 @@ public struct PumpStatus { rval["clock"] = TimeFormat.timestampStrFromDate(clock) rval["pumpID"] = pumpID - + + if let iob = iob { + rval["iob"] = iob.dictionaryRepresentation + } + if let battery = battery { rval["battery"] = battery.dictionaryRepresentation } + if let suspended = suspended { + rval["suspended"] = suspended + } + + if let bolusing = bolusing { + rval["bolusing"] = bolusing + } + if let reservoir = reservoir { rval["reservoir"] = reservoir } - - if let iob = iob { - rval["iob"] = iob.dictionaryRepresentation + + if let secondsFromGMT = secondsFromGMT { + rval["secondsFromGMT"] = secondsFromGMT } return rval diff --git a/NightscoutUploadKit/Info.plist b/NightscoutUploadKit/Info.plist index d3de8eefb..7a8455339 100644 --- a/NightscoutUploadKit/Info.plist +++ b/NightscoutUploadKit/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0 + 1.0.1 CFBundleSignature ???? CFBundleVersion diff --git a/NightscoutUploadKit/NightscoutPumpEvents.swift b/NightscoutUploadKit/NightscoutPumpEvents.swift index 0582d39ca..4408bde4e 100644 --- a/NightscoutUploadKit/NightscoutPumpEvents.swift +++ b/NightscoutUploadKit/NightscoutPumpEvents.swift @@ -64,10 +64,10 @@ public class NightscoutPumpEvents: NSObject { lastBasalDuration = tempBasalDuration lastBasalDurationDate = event.date case is SuspendPumpEvent: - let entry = SuspendPumpTreatment(timestamp: event.date, enteredBy: eventSource, suspended: true) + let entry = PumpSuspendTreatment(timestamp: event.date, enteredBy: eventSource) results.append(entry) case is ResumePumpEvent: - let entry = SuspendPumpTreatment(timestamp: event.date, enteredBy: eventSource, suspended: false) + let entry = PumpResumeTreatment(timestamp: event.date, enteredBy: eventSource) results.append(entry) default: break diff --git a/NightscoutUploadKit/NightscoutUploader.swift b/NightscoutUploadKit/NightscoutUploader.swift index 0deb0c501..7736ccb50 100644 --- a/NightscoutUploadKit/NightscoutUploader.swift +++ b/NightscoutUploadKit/NightscoutUploader.swift @@ -36,7 +36,7 @@ public class NightscoutUploader { private(set) var entries = [NightscoutEntry]() private(set) var deviceStatuses = [[String: Any]]() private(set) var treatmentsQueue = [NightscoutTreatment]() - + private(set) var lastMeterMessageRxTime: Date? public private(set) var observingPumpEventsSince: Date! @@ -282,7 +282,7 @@ public class NightscoutUploader { lastMeterMessageRxTime = date } } - + // MARK: - Uploading func flushAll() { diff --git a/NightscoutUploadKit/Treatments/BGCheckNightscoutTreatment.swift b/NightscoutUploadKit/Treatments/BGCheckNightscoutTreatment.swift index 1a3cd2d8b..72c1db933 100644 --- a/NightscoutUploadKit/Treatments/BGCheckNightscoutTreatment.swift +++ b/NightscoutUploadKit/Treatments/BGCheckNightscoutTreatment.swift @@ -14,16 +14,15 @@ public class BGCheckNightscoutTreatment: NightscoutTreatment { let glucoseType: GlucoseType let units: Units - init(timestamp: Date, enteredBy: String, glucose: Int, glucoseType: GlucoseType, units: Units) { + public init(timestamp: Date, enteredBy: String, glucose: Int, glucoseType: GlucoseType, units: Units, notes: String? = nil) { self.glucose = glucose self.glucoseType = glucoseType self.units = units - super.init(timestamp: timestamp, enteredBy: enteredBy) + super.init(timestamp: timestamp, enteredBy: enteredBy, notes: notes, eventType: "BG Check") } override public var dictionaryRepresentation: [String: Any] { var rval = super.dictionaryRepresentation - rval["eventType"] = "BG Check" rval["glucose"] = glucose rval["glucoseType"] = glucoseType.rawValue rval["units"] = units.rawValue diff --git a/NightscoutUploadKit/Treatments/BolusNightscoutTreatment.swift b/NightscoutUploadKit/Treatments/BolusNightscoutTreatment.swift index 704054ca2..0fa2f7fa7 100644 --- a/NightscoutUploadKit/Treatments/BolusNightscoutTreatment.swift +++ b/NightscoutUploadKit/Treatments/BolusNightscoutTreatment.swift @@ -10,12 +10,12 @@ import Foundation public class BolusNightscoutTreatment: NightscoutTreatment { - enum BolusType: String { + public enum BolusType: String { case Normal = "normal" case Square = "square" case DualWave = "dual" } - + let bolusType: BolusType let amount: Double let programmed: Double @@ -23,8 +23,8 @@ public class BolusNightscoutTreatment: NightscoutTreatment { let duration: TimeInterval let carbs: Int let ratio: Double - - init(timestamp: Date, enteredBy: String, bolusType: BolusType, amount: Double, programmed: Double, unabsorbed: Double, duration: TimeInterval, carbs: Int, ratio: Double) { + + public init(timestamp: Date, enteredBy: String, bolusType: BolusType, amount: Double, programmed: Double, unabsorbed: Double, duration: TimeInterval, carbs: Int, ratio: Double, notes: String? = nil) { self.bolusType = bolusType self.amount = amount self.programmed = programmed @@ -32,17 +32,16 @@ public class BolusNightscoutTreatment: NightscoutTreatment { self.duration = duration self.carbs = carbs self.ratio = ratio - super.init(timestamp: timestamp, enteredBy: enteredBy) + super.init(timestamp: timestamp, enteredBy: enteredBy, notes: notes, + eventType: (carbs > 0) ? "Meal Bolus" : "Correction Bolus") + } - + override public var dictionaryRepresentation: [String: Any] { var rval = super.dictionaryRepresentation if carbs > 0 { - rval["eventType"] = "Meal Bolus" rval["carbs"] = carbs rval["ratio"] = ratio - } else { - rval["eventType"] = "Correction Bolus" } rval["type"] = bolusType.rawValue rval["insulin"] = amount diff --git a/NightscoutUploadKit/Treatments/MealBolusNightscoutTreatment.swift b/NightscoutUploadKit/Treatments/MealBolusNightscoutTreatment.swift index 3112adce4..25ffeb83d 100644 --- a/NightscoutUploadKit/Treatments/MealBolusNightscoutTreatment.swift +++ b/NightscoutUploadKit/Treatments/MealBolusNightscoutTreatment.swift @@ -17,19 +17,18 @@ public class MealBolusNightscoutTreatment: NightscoutTreatment { let units: Units? // of glucose entry let glucoseType: GlucoseType? - public init(timestamp: Date, enteredBy: String, id: String?, carbs: Int, absorptionTime: TimeInterval? = nil, insulin: Double? = nil, glucose: Int? = nil, glucoseType: GlucoseType? = nil, units: Units? = nil) { + public init(timestamp: Date, enteredBy: String, id: String?, carbs: Int, absorptionTime: TimeInterval? = nil, insulin: Double? = nil, glucose: Int? = nil, glucoseType: GlucoseType? = nil, units: Units? = nil, notes: String? = nil) { self.carbs = carbs self.absorptionTime = absorptionTime self.glucose = glucose self.glucoseType = glucoseType self.units = units self.insulin = insulin - super.init(timestamp: timestamp, enteredBy: enteredBy, id: id) + super.init(timestamp: timestamp, enteredBy: enteredBy, notes: notes, id: id, eventType: "Meal Bolus") } override public var dictionaryRepresentation: [String: Any] { var rval = super.dictionaryRepresentation - rval["eventType"] = "Meal Bolus" rval["carbs"] = carbs if let absorptionTime = absorptionTime { rval["absorptionTime"] = absorptionTime.minutes diff --git a/NightscoutUploadKit/Treatments/NightscoutTreatment.swift b/NightscoutUploadKit/Treatments/NightscoutTreatment.swift index 28d470ccf..9711d8c37 100644 --- a/NightscoutUploadKit/Treatments/NightscoutTreatment.swift +++ b/NightscoutUploadKit/Treatments/NightscoutTreatment.swift @@ -22,12 +22,17 @@ public class NightscoutTreatment: DictionaryRepresentable { let timestamp: Date let enteredBy: String + let notes: String? let id: String? + let eventType: String? - init(timestamp: Date, enteredBy: String, id: String? = nil) { + + public init(timestamp: Date, enteredBy: String, notes: String? = nil, id: String? = nil, eventType: String? = nil) { self.timestamp = timestamp self.enteredBy = enteredBy self.id = id + self.notes = notes + self.eventType = eventType } public var dictionaryRepresentation: [String: Any] { @@ -39,6 +44,12 @@ public class NightscoutTreatment: DictionaryRepresentable { if let id = id { rval["_id"] = id } + if let notes = notes { + rval["notes"] = notes + } + if let eventType = eventType { + rval["eventType"] = eventType + } return rval } } diff --git a/NightscoutUploadKit/Treatments/NoteNightscoutTreatment.swift b/NightscoutUploadKit/Treatments/NoteNightscoutTreatment.swift new file mode 100644 index 000000000..76c1c978c --- /dev/null +++ b/NightscoutUploadKit/Treatments/NoteNightscoutTreatment.swift @@ -0,0 +1,17 @@ +// +// NoteNightscoutTreatment.swift +// RileyLink +// +// Copyright © 2017 Pete Schwamb. All rights reserved. +// + +import Foundation + + +public class NoteNightscoutTreatment: NightscoutTreatment { + + public init(timestamp: Date, enteredBy: String, notes: String? = nil, id: String? = nil) { + super.init(timestamp: timestamp, enteredBy: enteredBy, notes: notes, id: id, eventType: "Note") + } + +} diff --git a/NightscoutUploadKit/Treatments/PumpResumeTreatment.swift b/NightscoutUploadKit/Treatments/PumpResumeTreatment.swift new file mode 100644 index 000000000..15420f419 --- /dev/null +++ b/NightscoutUploadKit/Treatments/PumpResumeTreatment.swift @@ -0,0 +1,17 @@ +// +// PumpResumeTreatment.swift +// RileyLink +// +// Created by Pete Schwamb on 3/27/17. +// Copyright © 2017 Pete Schwamb. All rights reserved. +// + +import Foundation + +public class PumpResumeTreatment: NightscoutTreatment { + + public init(timestamp: Date, enteredBy: String) { + super.init(timestamp: timestamp, enteredBy: enteredBy, eventType: "Resume Pump") + } + +} diff --git a/NightscoutUploadKit/Treatments/PumpSuspendTreatment.swift b/NightscoutUploadKit/Treatments/PumpSuspendTreatment.swift new file mode 100644 index 000000000..c51a5331b --- /dev/null +++ b/NightscoutUploadKit/Treatments/PumpSuspendTreatment.swift @@ -0,0 +1,17 @@ +// +// PumpSuspendTreatment.swift +// RileyLink +// +// Created by Pete Schwamb on 3/27/17. +// Copyright © 2017 Pete Schwamb. All rights reserved. +// + +import Foundation + +public class PumpSuspendTreatment: NightscoutTreatment { + + public init(timestamp: Date, enteredBy: String) { + super.init(timestamp: timestamp, enteredBy: enteredBy, eventType: "Suspend Pump") + } + +} diff --git a/NightscoutUploadKit/Treatments/SuspendPumpTreatment.swift b/NightscoutUploadKit/Treatments/SuspendPumpTreatment.swift deleted file mode 100644 index 1a31fae5b..000000000 --- a/NightscoutUploadKit/Treatments/SuspendPumpTreatment.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// SuspendPumpTreatment.swift -// RileyLink -// -// Created by Pete Schwamb on 2/25/17. -// Copyright © 2017 Pete Schwamb. All rights reserved. -// - -import Foundation - -public class SuspendPumpTreatment: NightscoutTreatment { - - let suspended: Bool - - init(timestamp: Date, enteredBy: String, suspended: Bool) { - self.suspended = suspended - - super.init(timestamp: timestamp, enteredBy: enteredBy) - } - - override public var dictionaryRepresentation: [String: Any] { - var rval = super.dictionaryRepresentation - rval["eventType"] = "Pump Suspend" - rval["suspended"] = suspended - return rval - } -} diff --git a/NightscoutUploadKit/Treatments/TempBasalNightscoutTreatment.swift b/NightscoutUploadKit/Treatments/TempBasalNightscoutTreatment.swift index c00edc283..225d998f3 100644 --- a/NightscoutUploadKit/Treatments/TempBasalNightscoutTreatment.swift +++ b/NightscoutUploadKit/Treatments/TempBasalNightscoutTreatment.swift @@ -27,12 +27,11 @@ public class TempBasalNightscoutTreatment: NightscoutTreatment { self.temp = temp self.duration = duration - super.init(timestamp: timestamp, enteredBy: enteredBy) + super.init(timestamp: timestamp, enteredBy: enteredBy, eventType: "Temp Basal") } override public var dictionaryRepresentation: [String: Any] { var rval = super.dictionaryRepresentation - rval["eventType"] = "Temp Basal" rval["temp"] = temp.rawValue rval["rate"] = rate if let absolute = absolute { diff --git a/NightscoutUploadKitTests/Info.plist b/NightscoutUploadKitTests/Info.plist index ba72822e8..07841bd8b 100644 --- a/NightscoutUploadKitTests/Info.plist +++ b/NightscoutUploadKitTests/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.0 + 1.0.1 CFBundleSignature ???? CFBundleVersion diff --git a/RileyLink.xcodeproj/project.pbxproj b/RileyLink.xcodeproj/project.pbxproj index 7c339e66c..9aa657e3a 100644 --- a/RileyLink.xcodeproj/project.pbxproj +++ b/RileyLink.xcodeproj/project.pbxproj @@ -88,6 +88,7 @@ 43EC9DCB1B786C6200DB0D18 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 43EC9DCA1B786C6200DB0D18 /* LaunchScreen.xib */; }; 43F348061D596270009933DC /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F348051D596270009933DC /* HKUnit.swift */; }; 43FF221C1CB9B9DE00024F30 /* NSDateComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43FF221B1CB9B9DE00024F30 /* NSDateComponents.swift */; }; + 492526711E4521FB00ACBA5F /* NoteNightscoutTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 492526701E4521FB00ACBA5F /* NoteNightscoutTreatment.swift */; }; 541688DB1DB820BF005B1891 /* ReadCurrentGlucosePageMessageBodyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 541688DA1DB820BF005B1891 /* ReadCurrentGlucosePageMessageBodyTests.swift */; }; 541688DD1DB82213005B1891 /* ReadCurrentGlucosePageMessageBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = 541688DC1DB82213005B1891 /* ReadCurrentGlucosePageMessageBody.swift */; }; 541688DF1DB82E72005B1891 /* TimestampedGlucoseEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 541688DE1DB82E72005B1891 /* TimestampedGlucoseEvent.swift */; }; @@ -175,7 +176,6 @@ C12EA25E198B436900309FA4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = C12EA25C198B436900309FA4 /* InfoPlist.strings */; }; C12EA260198B436900309FA4 /* RileyLinkTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C12EA25F198B436900309FA4 /* RileyLinkTests.m */; }; C12EA26A198B442100309FA4 /* Storyboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C12EA269198B442100309FA4 /* Storyboard.storyboard */; }; - C130BF7A1E6290CA002EDB99 /* SuspendPumpTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C130BF791E6290CA002EDB99 /* SuspendPumpTreatment.swift */; }; C1330F431DBDA46400569064 /* ChangeSensorAlarmSilenceConfigPumpEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1330F421DBDA46400569064 /* ChangeSensorAlarmSilenceConfigPumpEvent.swift */; }; C133CF931D5943780034B82D /* PredictedBG.swift in Sources */ = {isa = PBXBuildFile; fileRef = C133CF921D5943780034B82D /* PredictedBG.swift */; }; C139AC241BFD84B500B0518F /* RuntimeUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = C139AC231BFD84B500B0518F /* RuntimeUtils.m */; }; @@ -303,6 +303,8 @@ C1C357911C92733A009BDD4F /* MeterMessageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1C357901C92733A009BDD4F /* MeterMessageTests.swift */; }; C1C659191E16BA9D0025CC58 /* CaseCountable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1C659181E16BA9D0025CC58 /* CaseCountable.swift */; }; C1C73F1D1DE6306A0022FC89 /* BatteryChemistryType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1C73F1C1DE6306A0022FC89 /* BatteryChemistryType.swift */; }; + C1D00E9D1E8986A400B733B7 /* PumpSuspendTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D00E9C1E8986A400B733B7 /* PumpSuspendTreatment.swift */; }; + C1D00EA11E8986F900B733B7 /* PumpResumeTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D00EA01E8986F900B733B7 /* PumpResumeTreatment.swift */; }; C1E535EA1991E36700C2AC49 /* NSData+Conversion.m in Sources */ = {isa = PBXBuildFile; fileRef = C1E535E91991E36700C2AC49 /* NSData+Conversion.m */; }; C1E5BEAD1D5E26F200BD4390 /* RileyLinkStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1E5BEAC1D5E26F200BD4390 /* RileyLinkStatus.swift */; }; C1EAD6B31C826B6D006DBA60 /* AlertType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1EAD6AE1C826B6D006DBA60 /* AlertType.swift */; }; @@ -522,6 +524,7 @@ 43EC9DCA1B786C6200DB0D18 /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LaunchScreen.xib; sourceTree = ""; }; 43F348051D596270009933DC /* HKUnit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = ""; }; 43FF221B1CB9B9DE00024F30 /* NSDateComponents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSDateComponents.swift; sourceTree = ""; }; + 492526701E4521FB00ACBA5F /* NoteNightscoutTreatment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NoteNightscoutTreatment.swift; sourceTree = ""; }; 541688DA1DB820BF005B1891 /* ReadCurrentGlucosePageMessageBodyTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReadCurrentGlucosePageMessageBodyTests.swift; sourceTree = ""; }; 541688DC1DB82213005B1891 /* ReadCurrentGlucosePageMessageBody.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReadCurrentGlucosePageMessageBody.swift; sourceTree = ""; }; 541688DE1DB82E72005B1891 /* TimestampedGlucoseEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimestampedGlucoseEvent.swift; sourceTree = ""; }; @@ -619,7 +622,6 @@ C12EA25D198B436900309FA4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; C12EA25F198B436900309FA4 /* RileyLinkTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RileyLinkTests.m; sourceTree = ""; }; C12EA269198B442100309FA4 /* Storyboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Storyboard.storyboard; sourceTree = ""; }; - C130BF791E6290CA002EDB99 /* SuspendPumpTreatment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SuspendPumpTreatment.swift; sourceTree = ""; }; C1330F421DBDA46400569064 /* ChangeSensorAlarmSilenceConfigPumpEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChangeSensorAlarmSilenceConfigPumpEvent.swift; sourceTree = ""; }; C133CF921D5943780034B82D /* PredictedBG.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PredictedBG.swift; sourceTree = ""; }; C139AC221BFD84B500B0518F /* RuntimeUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RuntimeUtils.h; sourceTree = ""; }; @@ -749,6 +751,8 @@ C1C357901C92733A009BDD4F /* MeterMessageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MeterMessageTests.swift; path = Messages/MeterMessageTests.swift; sourceTree = ""; }; C1C659181E16BA9D0025CC58 /* CaseCountable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaseCountable.swift; sourceTree = ""; }; C1C73F1C1DE6306A0022FC89 /* BatteryChemistryType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BatteryChemistryType.swift; sourceTree = ""; }; + C1D00E9C1E8986A400B733B7 /* PumpSuspendTreatment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PumpSuspendTreatment.swift; sourceTree = ""; }; + C1D00EA01E8986F900B733B7 /* PumpResumeTreatment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PumpResumeTreatment.swift; sourceTree = ""; }; C1E535E81991E36700C2AC49 /* NSData+Conversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+Conversion.h"; sourceTree = ""; }; C1E535E91991E36700C2AC49 /* NSData+Conversion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+Conversion.m"; sourceTree = ""; }; C1E5BEAC1D5E26F200BD4390 /* RileyLinkStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RileyLinkStatus.swift; sourceTree = ""; }; @@ -1380,8 +1384,10 @@ C1AF21EB1D4901220088C41D /* BolusNightscoutTreatment.swift */, C1AF21EE1D4901220088C41D /* MealBolusNightscoutTreatment.swift */, C1AF21EC1D4901220088C41D /* NightscoutTreatment.swift */, - C130BF791E6290CA002EDB99 /* SuspendPumpTreatment.swift */, + C1D00E9C1E8986A400B733B7 /* PumpSuspendTreatment.swift */, C1AF21EF1D4901220088C41D /* TempBasalNightscoutTreatment.swift */, + 492526701E4521FB00ACBA5F /* NoteNightscoutTreatment.swift */, + C1D00EA01E8986F900B733B7 /* PumpResumeTreatment.swift */, ); path = Treatments; sourceTree = ""; @@ -1782,8 +1788,10 @@ }; C12EA236198B436800309FA4 = { LastSwiftMigration = 0800; + ProvisioningStyle = Automatic; }; C12EA251198B436800309FA4 = { + ProvisioningStyle = Automatic; TestTargetID = C12EA236198B436800309FA4; }; C1B3830A1CD0665D00CE7782 = { @@ -2231,6 +2239,7 @@ C1B4A94E1D1C423D003B8985 /* NSUserDefaults.swift in Sources */, C1AF21F01D4901220088C41D /* BolusNightscoutTreatment.swift in Sources */, C1AF21F21D4901220088C41D /* BGCheckNightscoutTreatment.swift in Sources */, + C1D00EA11E8986F900B733B7 /* PumpResumeTreatment.swift in Sources */, C1AF21E61D48667F0088C41D /* UploaderStatus.swift in Sources */, C1BAD1181E63984C009BA1C6 /* RadioAdapter.swift in Sources */, C1E5BEAD1D5E26F200BD4390 /* RileyLinkStatus.swift in Sources */, @@ -2239,12 +2248,13 @@ C1A492651D4A5DEB008964FF /* BatteryStatus.swift in Sources */, C1A492631D4A5A19008964FF /* IOBStatus.swift in Sources */, 43F348061D596270009933DC /* HKUnit.swift in Sources */, - C130BF7A1E6290CA002EDB99 /* SuspendPumpTreatment.swift in Sources */, 43D657461D0CF38F00216E20 /* NSTimeInterval.swift in Sources */, C133CF931D5943780034B82D /* PredictedBG.swift in Sources */, + C1D00E9D1E8986A400B733B7 /* PumpSuspendTreatment.swift in Sources */, C1AF21E41D4865320088C41D /* LoopStatus.swift in Sources */, C13D155A1DAACE8400ADC044 /* Either.swift in Sources */, C1AF21F11D4901220088C41D /* NightscoutTreatment.swift in Sources */, + 492526711E4521FB00ACBA5F /* NoteNightscoutTreatment.swift in Sources */, C1A492671D4A65D9008964FF /* RecommendedTempBasal.swift in Sources */, C178845F1D5166BE00405663 /* COBStatus.swift in Sources */, 43B0ADC91D1268B300AAD278 /* TimeFormat.swift in Sources */, @@ -2356,11 +2366,11 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - CURRENT_PROJECT_VERSION = 29; + CURRENT_PROJECT_VERSION = 30; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 29; + DYLIB_CURRENT_VERSION = 30; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -2384,11 +2394,11 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 29; + CURRENT_PROJECT_VERSION = 30; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 29; + DYLIB_CURRENT_VERSION = 30; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -2447,11 +2457,11 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - CURRENT_PROJECT_VERSION = 29; + CURRENT_PROJECT_VERSION = 30; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 29; + DYLIB_CURRENT_VERSION = 30; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -2478,11 +2488,11 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 29; + CURRENT_PROJECT_VERSION = 30; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 29; + DYLIB_CURRENT_VERSION = 30; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -2545,12 +2555,12 @@ CLANG_WARN_SUSPICIOUS_MOVES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - CURRENT_PROJECT_VERSION = 29; + CURRENT_PROJECT_VERSION = 30; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 29; + DYLIB_CURRENT_VERSION = 30; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Crypto/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -2573,12 +2583,12 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 29; + CURRENT_PROJECT_VERSION = 30; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 29; + DYLIB_CURRENT_VERSION = 30; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Crypto/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -2599,11 +2609,11 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - CURRENT_PROJECT_VERSION = 29; + CURRENT_PROJECT_VERSION = 30; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 29; + DYLIB_CURRENT_VERSION = 30; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -2629,11 +2639,11 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 29; + CURRENT_PROJECT_VERSION = 30; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 29; + DYLIB_CURRENT_VERSION = 30; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -2708,7 +2718,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 29; + CURRENT_PROJECT_VERSION = 30; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -2755,7 +2765,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 29; + CURRENT_PROJECT_VERSION = 30; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -2790,6 +2800,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.rileylink.rlapp; PRODUCT_NAME = RileyLink; PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "RileyLink/RileyLink-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 3.0; @@ -2811,6 +2822,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.rileylink.rlapp; PRODUCT_NAME = RileyLink; PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "RileyLink/RileyLink-Bridging-Header.h"; SWIFT_VERSION = 3.0; WRAPPER_EXTENSION = app; @@ -2823,12 +2835,14 @@ BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/RileyLink.app/RileyLink"; CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEVELOPMENT_TEAM = ""; GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; INFOPLIST_FILE = "RileyLinkTests/RileyLinkTests-Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.rileylink.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = RileyLinkTests; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; TEST_HOST = "$(BUNDLE_LOADER)"; WRAPPER_EXTENSION = xctest; @@ -2841,11 +2855,13 @@ BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/RileyLink.app/RileyLink"; CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "RileyLinkTests/RileyLinkTests-Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.rileylink.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = RileyLinkTests; + PROVISIONING_PROFILE_SPECIFIER = ""; TEST_HOST = "$(BUNDLE_LOADER)"; WRAPPER_EXTENSION = xctest; }; @@ -2859,11 +2875,11 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - CURRENT_PROJECT_VERSION = 29; + CURRENT_PROJECT_VERSION = 30; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 29; + DYLIB_CURRENT_VERSION = 30; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -2889,11 +2905,11 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 29; + CURRENT_PROJECT_VERSION = 30; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 29; + DYLIB_CURRENT_VERSION = 30; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; diff --git a/RileyLink/KeychainManager.swift b/RileyLink/KeychainManager.swift index 75e4205dd..ff0e0db0d 100644 --- a/RileyLink/KeychainManager.swift +++ b/RileyLink/KeychainManager.swift @@ -256,8 +256,8 @@ private extension URLComponents { host = keychainAttributes[kSecAttrServer as String] as? String - if let port = keychainAttributes[kSecAttrPort as String] as? NSNumber, port.intValue > 0 { - self.port = port as Int? + if let port = keychainAttributes[kSecAttrPort as String] as? Int, port > 0 { + self.port = port } if let path = keychainAttributes[kSecAttrPath as String] as? String { diff --git a/RileyLink/RileyLink-Info.plist b/RileyLink/RileyLink-Info.plist index 80bbbfbc3..7fbe43e9f 100644 --- a/RileyLink/RileyLink-Info.plist +++ b/RileyLink/RileyLink-Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0 + 1.0.1 CFBundleSignature ???? CFBundleVersion diff --git a/RileyLinkBLEKit/Info.plist b/RileyLinkBLEKit/Info.plist index d3de8eefb..7a8455339 100644 --- a/RileyLinkBLEKit/Info.plist +++ b/RileyLinkBLEKit/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0 + 1.0.1 CFBundleSignature ???? CFBundleVersion diff --git a/RileyLinkBLEKitTests/Info.plist b/RileyLinkBLEKitTests/Info.plist index bec4c60a2..c41602f9c 100644 --- a/RileyLinkBLEKitTests/Info.plist +++ b/RileyLinkBLEKitTests/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.0 + 1.0.1 CFBundleSignature ???? CFBundleVersion diff --git a/RileyLinkKit/Info.plist b/RileyLinkKit/Info.plist index d3de8eefb..7a8455339 100644 --- a/RileyLinkKit/Info.plist +++ b/RileyLinkKit/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0 + 1.0.1 CFBundleSignature ???? CFBundleVersion diff --git a/RileyLinkKit/PumpOps.swift b/RileyLinkKit/PumpOps.swift index 2b9555682..146dade5b 100644 --- a/RileyLinkKit/PumpOps.swift +++ b/RileyLinkKit/PumpOps.swift @@ -94,19 +94,21 @@ public class PumpOps { This operation is performed asynchronously and the completion will be executed on an arbitrary background queue. - parameter completion: A closure called after the command is complete. This closure takes a single Result argument: - - success(units): The reservoir volume, in units of insulin + - success(units, date): The reservoir volume, in units of insulin, and DateCompoments representing the pump's clock - failure(error): An error describing why the command failed */ - public func readRemainingInsulin(_ completion: @escaping (Either) -> Void) { + public func readRemainingInsulin(_ completion: @escaping (Either<(units: Double, date: DateComponents), Error>) -> Void) { device.runSession(withName: "Read remaining insulin") { (session) in let ops = PumpOpsSynchronous(pumpState: self.pumpState, session: session) do { let pumpModel = try ops.getPumpModel() + let clockResp: ReadTimeCarelinkMessageBody = try ops.messageBody(to: .readTime) + let response: ReadRemainingInsulinMessageBody = try ops.messageBody(to: .readRemainingInsulin) - completion(.success(response.getUnitsRemainingForStrokes(pumpModel.strokesPerUnit))) + completion(.success(response.getUnitsRemainingForStrokes(pumpModel.strokesPerUnit), clockResp.dateComponents)) } catch let error { completion(.failure(error)) } @@ -245,25 +247,15 @@ public class PumpOps { This operation is performed asynchronously and the completion will be executed on an arbitrary background queue. - - parameter units: The number of units to deliver - - parameter completion: A closure called after the command is complete. This closure takes a single argument: + - parameter units: The number of units to deliver + - parameter cancelExistingTemp: If true, additional pump commands will be issued to clear any running temp basal. Defaults to false. + - parameter completion: A closure called after the command is complete. This closure takes a single argument: - error: An error describing why the command failed */ - public func setNormalBolus(units: Double, completion: @escaping (_ error: Error?) -> Void) { + public func setNormalBolus(units: Double, cancelExistingTemp: Bool = false, completion: @escaping (_ error: SetBolusError?) -> Void) { device.runSession(withName: "Set normal bolus") { (session) in let ops = PumpOpsSynchronous(pumpState: self.pumpState, session: session) - - do { - let pumpModel = try ops.getPumpModel() - - let message = PumpMessage(packetType: .carelink, address: self.pumpState.pumpID, messageType: .bolus, messageBody: BolusCarelinkMessageBody(units: units, strokesPerUnit: pumpModel.strokesPerUnit)) - - _ = try ops.runCommandWithArguments(message) - - completion(nil) - } catch let error { - completion(error) - } + completion(ops.setNormalBolus(units: units, cancelExistingTemp: cancelExistingTemp)) } } diff --git a/RileyLinkKit/PumpOpsSynchronous.swift b/RileyLinkKit/PumpOpsSynchronous.swift index 165b9c892..652e3a65b 100644 --- a/RileyLinkKit/PumpOpsSynchronous.swift +++ b/RileyLinkKit/PumpOpsSynchronous.swift @@ -11,6 +11,15 @@ import MinimedKit import RileyLinkBLEKit +/// An error that occurs during a command run +/// +/// - command: The error took place during the command sequence +/// - arguments: The error took place during the argument sequence +public enum PumpCommandError: Error { + case command(PumpCommsError) + case arguments(PumpCommsError) +} + public enum PumpCommsError: Error { case rfCommsFailure(String) case unknownPumpModel @@ -19,6 +28,13 @@ public enum PumpCommsError: Error { case noResponse(during: String) case unexpectedResponse(PumpMessage, from: PumpMessage) case crosstalk(PumpMessage, during: String) + case bolusInProgress + case pumpSuspended +} + +public enum SetBolusError: Error { + case certain(PumpCommsError) + case uncertain(PumpCommsError) } public enum RXFilterMode: UInt8 { @@ -47,7 +63,7 @@ class PumpOpsSynchronous { private func makePumpMessage(to messageType: MessageType, using body: MessageBody = CarelinkShortMessageBody()) -> PumpMessage { return PumpMessage(packetType: .carelink, address: pump.pumpID, messageType: messageType, messageBody: body) } - + private func sendAndListen(_ msg: PumpMessage, timeoutMS: UInt16 = standardPumpResponseWindow, repeatCount: UInt8 = 0, msBetweenPackets: UInt8 = 0, retryCount: UInt8 = 3) throws -> PumpMessage { let cmd = SendAndListenCmd() cmd.packet = RFPacket(data: msg.txData) @@ -56,22 +72,22 @@ class PumpOpsSynchronous { cmd.msBetweenPackets = msBetweenPackets cmd.retryCount = retryCount cmd.listenChannel = 0 - + let minTimeBetweenPackets = 12 // At least 12 ms between packets for radio to stop/start - + let timeBetweenPackets = max(minTimeBetweenPackets, Int(msBetweenPackets)) - + // 16384 = bitrate, 8 = bits per byte, 6/4 = 4b6 encoding, 1000 = ms in 1s let singlePacketSendTime = (Double(msg.txData.count * 8) * 6 / 4 / 16384.0) * 1000 - + let totalSendTime = Double(repeatCount) * (singlePacketSendTime + Double(timeBetweenPackets)) - + let totalTimeout = Int(retryCount+1) * (Int(totalSendTime) + Int(timeoutMS)) + expectedMaxBLELatencyMS - + guard session.doCmd(cmd, withTimeoutMs: totalTimeout) else { throw PumpCommsError.rileyLinkTimeout } - + guard let data = cmd.receivedPacket.data else { if cmd.didReceiveResponse { throw PumpCommsError.unknownResponse(rx: cmd.rawReceivedData.hexadecimalString, during: "Sent \(msg)") @@ -79,26 +95,30 @@ class PumpOpsSynchronous { throw PumpCommsError.noResponse(during: "Sent \(msg)") } } - + guard let message = PumpMessage(rxData: data) else { throw PumpCommsError.unknownResponse(rx: data.hexadecimalString, during: "Sent \(msg)") } - + guard message.address == msg.address else { throw PumpCommsError.crosstalk(message, during: "Sent \(msg)") } NotificationCenter.default.post(name: .PumpOpsSynchronousDidReceivePacket, object: self, userInfo: [type(of: self).PacketKey: cmd.receivedPacket]) - + return message } - /** - Attempts to send initial short wakeup message that kicks off the wakeup process. - - If successful, still does not fully wake up the pump - only alerts it such that the - longer wakeup message can be sent next. - */ + /// Attempts to send initial short wakeup message that kicks off the wakeup process. + /// + /// If successful, still does not fully wake up the pump - only alerts it such that the longer wakeup message can be sent next. + /// + /// - Throws: + /// - PumpCommsError.rileyLinkTimeout + /// - PumpCommsError.unknownResponse + /// - PumpCommsError.noResponse + /// - PumpCommsError.crosstalk + /// - PumpCommsError.unexpectedResponse private func sendWakeUpBurst() throws { var lastError: Error? @@ -149,9 +169,13 @@ class PumpOpsSynchronous { } return false } - - + /// - Throws: + /// - PumpCommsError.rileyLinkTimeout + /// - PumpCommsError.unknownResponse + /// - PumpCommsError.noResponse + /// - PumpCommsError.crosstalk + /// - PumpCommsError.unexpectedResponse private func wakeup(_ duration: TimeInterval = TimeInterval(minutes: 1)) throws { guard !pump.isAwake else { return @@ -177,31 +201,50 @@ class PumpOpsSynchronous { NSLog("Power on for %.0f minutes", duration.minutes) pump.awakeUntil = Date(timeIntervalSinceNow: duration) } - + + /// - Throws: `PumpCommandError` specifying the failure sequence internal func runCommandWithArguments(_ msg: PumpMessage, responseMessageType: MessageType = .pumpAck) throws -> PumpMessage { - try wakeup() + do { + try wakeup() - let shortMsg = makePumpMessage(to: msg.messageType) - let shortResponse = try sendAndListen(shortMsg) + let shortMsg = makePumpMessage(to: msg.messageType) + let shortResponse = try sendAndListen(shortMsg) - guard shortResponse.messageType == .pumpAck else { - throw PumpCommsError.unexpectedResponse(shortResponse, from: shortMsg) + guard shortResponse.messageType == .pumpAck else { + throw PumpCommsError.unexpectedResponse(shortResponse, from: shortMsg) + } + } catch let error { + throw PumpCommandError.command(error as! PumpCommsError) } + + do { + let response = try sendAndListen(msg) - let response = try sendAndListen(msg) - - guard response.messageType == responseMessageType else { - throw PumpCommsError.unexpectedResponse(response, from: msg) + guard response.messageType == responseMessageType else { + throw PumpCommsError.unexpectedResponse(response, from: msg) + } + + return response + } catch let error { + throw PumpCommandError.arguments(error as! PumpCommsError) } - - return response } - + + /// - Throws: + /// - PumpCommsError.rileyLinkTimeout + /// - PumpCommsError.unknownResponse + /// - PumpCommsError.noResponse + /// - PumpCommsError.crosstalk + /// - PumpCommsError.unexpectedResponse internal func getPumpModelNumber() throws -> String { let body: GetPumpModelCarelinkMessageBody = try messageBody(to: .getPumpModel) return body.model } - + + /// Retrieves the pump model from either the state or from the + /// + /// - Returns: The pump model + /// - Throws: `PumpCommsError` internal func getPumpModel() throws -> PumpModel { if let pumpModel = pump.pumpModel { return pumpModel @@ -215,7 +258,13 @@ class PumpOpsSynchronous { return pumpModel } - + + /// - Throws: + /// - PumpCommsError.rileyLinkTimeout + /// - PumpCommsError.unknownResponse + /// - PumpCommsError.noResponse + /// - PumpCommsError.crosstalk + /// - PumpCommsError.unexpectedResponse internal func messageBody(to messageType: MessageType) throws -> T { try wakeup() @@ -250,7 +299,7 @@ class PumpOpsSynchronous { if response.timeRemaining == duration && response.rateType == .absolute { return response } else { - lastError = PumpCommsError.rfCommsFailure("Could not verify TempBasal on attempt \(attempt)") + lastError = PumpCommsError.rfCommsFailure("Could not verify TempBasal on attempt \(attempt). ") } } catch let error { lastError = error @@ -692,6 +741,52 @@ class PumpOpsSynchronous { return PumpStatus(clock: clockResp.dateComponents, batteryVolts: battResp.volts, batteryStatus: battResp.status, suspended: statusResp.suspended, bolusing: statusResp.bolusing, reservoir: reservoir, model: pumpModel, pumpID: pump.pumpID) } + + internal func setNormalBolus(units: Double, cancelExistingTemp: Bool) -> SetBolusError? { + do { + let pumpModel = try getPumpModel() + + let statusResp: ReadPumpStatusMessageBody = try messageBody(to: .readPumpStatus) + + if statusResp.bolusing { + throw PumpCommsError.bolusInProgress + } + + if statusResp.suspended { + throw PumpCommsError.pumpSuspended + } + + if cancelExistingTemp { + do { + _ = try setTempBasal(0, duration: TimeInterval(0)) + } catch let error as PumpCommandError { + switch error { + case .command(let error): + return .certain(error) + case .arguments(let error): + return .certain(error) + } + } + } + + let message = PumpMessage(packetType: .carelink, address: pump.pumpID, messageType: .bolus, messageBody: BolusCarelinkMessageBody(units: units, strokesPerUnit: pumpModel.strokesPerUnit)) + + _ = try runCommandWithArguments(message) + + } catch let error as PumpCommsError { + return .certain(error) + } catch let error as PumpCommandError { + switch error { + case .command(let error): + return .certain(error) + case .arguments(let error): + return .uncertain(error) + } + } catch { + assertionFailure() + } + return nil + } } public struct PumpStatus { diff --git a/RileyLinkKit/PumpState.swift b/RileyLinkKit/PumpState.swift index 2061575cc..bcf27470d 100644 --- a/RileyLinkKit/PumpState.swift +++ b/RileyLinkKit/PumpState.swift @@ -87,6 +87,7 @@ public class PumpState { extension PumpState: CustomDebugStringConvertible { public var debugDescription: String { + return [ "## PumpState", "timeZone: \(timeZone)", @@ -94,7 +95,7 @@ extension PumpState: CustomDebugStringConvertible { "pumpModel: \(pumpModel?.rawValue ?? "")", "lastHistoryDump: \(lastHistoryDump ?? .distantPast)", "awakeUntil: \(awakeUntil ?? .distantPast)", - "lastWakeAttempt: \(lastWakeAttempt)", + "lastWakeAttempt: \(String(describing: lastWakeAttempt))", ].joined(separator: "\n") } } diff --git a/RileyLinkKitTests/Info.plist b/RileyLinkKitTests/Info.plist index bec4c60a2..c41602f9c 100644 --- a/RileyLinkKitTests/Info.plist +++ b/RileyLinkKitTests/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.0 + 1.0.1 CFBundleSignature ???? CFBundleVersion diff --git a/RileyLinkTests/RileyLinkTests-Info.plist b/RileyLinkTests/RileyLinkTests-Info.plist index d6f1c99b7..d2db0dba1 100644 --- a/RileyLinkTests/RileyLinkTests-Info.plist +++ b/RileyLinkTests/RileyLinkTests-Info.plist @@ -13,7 +13,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.0 + 1.0.1 CFBundleSignature ???? CFBundleVersion