|
@@ -12,10 +12,10 @@ protocol NightscoutManager: GlucoseSource {
|
|
|
func deleteCarbs(at date: Date, isFPU: Bool?, fpuID: String?, syncID: String)
|
|
func deleteCarbs(at date: Date, isFPU: Bool?, fpuID: String?, syncID: String)
|
|
|
func deleteInsulin(at date: Date)
|
|
func deleteInsulin(at date: Date)
|
|
|
func uploadStatus()
|
|
func uploadStatus()
|
|
|
- func uploadStatistics(dailystat: Statistics)
|
|
|
|
|
- func uploadPreferences()
|
|
|
|
|
func uploadGlucose()
|
|
func uploadGlucose()
|
|
|
- func uploadProfile()
|
|
|
|
|
|
|
+ func uploadStatistics(dailystat: Statistics)
|
|
|
|
|
+ func uploadPreferences(_ preferences: Preferences)
|
|
|
|
|
+ func uploadProfileAndSettings(_: Bool)
|
|
|
var cgmURL: URL? { get }
|
|
var cgmURL: URL? { get }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -274,7 +274,7 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- func uploadPreferences() {
|
|
|
|
|
|
|
+ func uploadPreferences(_ preferences: Preferences) {
|
|
|
let prefs = NightscoutPreferences(
|
|
let prefs = NightscoutPreferences(
|
|
|
preferences: settingsManager.preferences
|
|
preferences: settingsManager.preferences
|
|
|
)
|
|
)
|
|
@@ -289,6 +289,31 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
|
|
|
switch completion {
|
|
switch completion {
|
|
|
case .finished:
|
|
case .finished:
|
|
|
debug(.nightscout, "Preferences uploaded")
|
|
debug(.nightscout, "Preferences uploaded")
|
|
|
|
|
+ self.storage.save(preferences, as: OpenAPS.Nightscout.uploadedPreferences)
|
|
|
|
|
+ case let .failure(error):
|
|
|
|
|
+ debug(.nightscout, error.localizedDescription)
|
|
|
|
|
+ }
|
|
|
|
|
+ } receiveValue: {}
|
|
|
|
|
+ .store(in: &self.lifetime)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ func uploadSettings(_ settings: FreeAPSSettings) {
|
|
|
|
|
+ let sets = NightscoutSettings(
|
|
|
|
|
+ settings: settingsManager.settings
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ guard let nightscout = nightscoutAPI, isUploadEnabled else {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ processQueue.async {
|
|
|
|
|
+ nightscout.uploadSettings(sets)
|
|
|
|
|
+ .sink { completion in
|
|
|
|
|
+ switch completion {
|
|
|
|
|
+ case .finished:
|
|
|
|
|
+ debug(.nightscout, "Settings uploaded")
|
|
|
|
|
+ self.storage.save(settings, as: OpenAPS.Nightscout.uploadedSettings)
|
|
|
case let .failure(error):
|
|
case let .failure(error):
|
|
|
debug(.nightscout, error.localizedDescription)
|
|
debug(.nightscout, error.localizedDescription)
|
|
|
}
|
|
}
|
|
@@ -401,14 +426,29 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- func uploadProfile() {
|
|
|
|
|
- // These should be modified anyways and not the defaults
|
|
|
|
|
- guard let sensitivities = storage.retrieve(OpenAPS.Settings.insulinSensitivities, as: InsulinSensitivities.self),
|
|
|
|
|
- let basalProfile = storage.retrieve(OpenAPS.Settings.basalProfile, as: [BasalProfileEntry].self),
|
|
|
|
|
- let carbRatios = storage.retrieve(OpenAPS.Settings.carbRatios, as: CarbRatios.self),
|
|
|
|
|
- let targets = storage.retrieve(OpenAPS.Settings.bgTargets, as: BGTargets.self)
|
|
|
|
|
- else {
|
|
|
|
|
- NSLog("NightscoutManager uploadProfile Not all settings found to build profile!")
|
|
|
|
|
|
|
+ func uploadProfileAndSettings(_ force: Bool) {
|
|
|
|
|
+ guard let sensitivities = storage.retrieve(OpenAPS.Settings.insulinSensitivities, as: InsulinSensitivities.self) else {
|
|
|
|
|
+ debug(.nightscout, "NightscoutManager uploadProfile: error loading insulinSensitivities")
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ guard let settings = storage.retrieve(OpenAPS.FreeAPS.settings, as: FreeAPSSettings.self) else {
|
|
|
|
|
+ debug(.nightscout, "NightscoutManager uploadProfile: error loading settings")
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ guard let preferences = storage.retrieve(OpenAPS.Settings.preferences, as: Preferences.self) else {
|
|
|
|
|
+ debug(.nightscout, "NightscoutManager uploadProfile: error loading preferences")
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ guard let targets = storage.retrieve(OpenAPS.Settings.bgTargets, as: BGTargets.self) else {
|
|
|
|
|
+ debug(.nightscout, "NightscoutManager uploadProfile: error loading bgTargets")
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ guard let carbRatios = storage.retrieve(OpenAPS.Settings.carbRatios, as: CarbRatios.self) else {
|
|
|
|
|
+ debug(.nightscout, "NightscoutManager uploadProfile: error loading carbRatios")
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ guard let basalProfile = storage.retrieve(OpenAPS.Settings.basalProfile, as: [BasalProfileEntry].self) else {
|
|
|
|
|
+ debug(.nightscout, "NightscoutManager uploadProfile: error loading basalProfile")
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -416,32 +456,30 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
|
|
|
NightscoutTimevalue(
|
|
NightscoutTimevalue(
|
|
|
time: String(item.start.prefix(5)),
|
|
time: String(item.start.prefix(5)),
|
|
|
value: item.sensitivity,
|
|
value: item.sensitivity,
|
|
|
- timeAsSeconds: item.offset
|
|
|
|
|
|
|
+ timeAsSeconds: item.offset * 60
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
let target_low = targets.targets.map { item -> NightscoutTimevalue in
|
|
let target_low = targets.targets.map { item -> NightscoutTimevalue in
|
|
|
NightscoutTimevalue(
|
|
NightscoutTimevalue(
|
|
|
time: String(item.start.prefix(5)),
|
|
time: String(item.start.prefix(5)),
|
|
|
value: item.low,
|
|
value: item.low,
|
|
|
- timeAsSeconds: item.offset
|
|
|
|
|
|
|
+ timeAsSeconds: item.offset * 60
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
let target_high = targets.targets.map { item -> NightscoutTimevalue in
|
|
let target_high = targets.targets.map { item -> NightscoutTimevalue in
|
|
|
NightscoutTimevalue(
|
|
NightscoutTimevalue(
|
|
|
time: String(item.start.prefix(5)),
|
|
time: String(item.start.prefix(5)),
|
|
|
value: item.high,
|
|
value: item.high,
|
|
|
- timeAsSeconds: item.offset
|
|
|
|
|
|
|
+ timeAsSeconds: item.offset * 60
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
let cr = carbRatios.schedule.map { item -> NightscoutTimevalue in
|
|
let cr = carbRatios.schedule.map { item -> NightscoutTimevalue in
|
|
|
NightscoutTimevalue(
|
|
NightscoutTimevalue(
|
|
|
time: String(item.start.prefix(5)),
|
|
time: String(item.start.prefix(5)),
|
|
|
value: item.ratio,
|
|
value: item.ratio,
|
|
|
- timeAsSeconds: item.offset
|
|
|
|
|
|
|
+ timeAsSeconds: item.offset * 60
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
let basal = basalProfile.map { item -> NightscoutTimevalue in
|
|
let basal = basalProfile.map { item -> NightscoutTimevalue in
|
|
|
NightscoutTimevalue(
|
|
NightscoutTimevalue(
|
|
|
time: String(item.start.prefix(5)),
|
|
time: String(item.start.prefix(5)),
|
|
@@ -471,6 +509,7 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
|
|
|
// No, Decimal has no rounding function.
|
|
// No, Decimal has no rounding function.
|
|
|
carbs_hr = Decimal(round(Double(carbs_hr) * 10.0)) / 10
|
|
carbs_hr = Decimal(round(Double(carbs_hr) * 10.0)) / 10
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
let ps = ScheduledNightscoutProfile(
|
|
let ps = ScheduledNightscoutProfile(
|
|
|
dia: settingsManager.pumpSettings.insulinActionCurve,
|
|
dia: settingsManager.pumpSettings.insulinActionCurve,
|
|
|
carbs_hr: Int(carbs_hr),
|
|
carbs_hr: Int(carbs_hr),
|
|
@@ -484,6 +523,7 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
|
|
|
units: nsUnits
|
|
units: nsUnits
|
|
|
)
|
|
)
|
|
|
let defaultProfile = "default"
|
|
let defaultProfile = "default"
|
|
|
|
|
+
|
|
|
let now = Date()
|
|
let now = Date()
|
|
|
let p = NightscoutProfileStore(
|
|
let p = NightscoutProfileStore(
|
|
|
defaultProfile: defaultProfile,
|
|
defaultProfile: defaultProfile,
|
|
@@ -494,33 +534,48 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
|
|
|
store: [defaultProfile: ps]
|
|
store: [defaultProfile: ps]
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
- if let uploadedProfile = storage.retrieve(OpenAPS.Nightscout.uploadedProfile, as: NightscoutProfileStore.self),
|
|
|
|
|
- (uploadedProfile.store[defaultProfile]?.rawJSON ?? "") == ps.rawJSON
|
|
|
|
|
- {
|
|
|
|
|
- NSLog("NightscoutManager uploadProfile, no profile change")
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
guard let nightscout = nightscoutAPI, isNetworkReachable, isUploadEnabled else {
|
|
guard let nightscout = nightscoutAPI, isNetworkReachable, isUploadEnabled else {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
- processQueue.async {
|
|
|
|
|
- nightscout.uploadProfile(p)
|
|
|
|
|
- .sink { completion in
|
|
|
|
|
- switch completion {
|
|
|
|
|
- case .finished:
|
|
|
|
|
- self.storage.save(p, as: OpenAPS.Nightscout.uploadedProfile)
|
|
|
|
|
- debug(.nightscout, "Profile uploaded")
|
|
|
|
|
- case let .failure(error):
|
|
|
|
|
- debug(.nightscout, error.localizedDescription)
|
|
|
|
|
- }
|
|
|
|
|
- } receiveValue: {}
|
|
|
|
|
- .store(in: &self.lifetime)
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // UPLOAD PREFERNCES WHEN CHANGED
|
|
|
|
|
+ if let uploadedPreferences = storage.retrieve(OpenAPS.Nightscout.uploadedPreferences, as: Preferences.self),
|
|
|
|
|
+ uploadedPreferences.rawJSON.sorted() == preferences.rawJSON.sorted(), !force
|
|
|
|
|
+ {
|
|
|
|
|
+ NSLog("NightscoutManager Preferences, preferences unchanged")
|
|
|
|
|
+ } else { uploadPreferences(preferences) }
|
|
|
|
|
+
|
|
|
|
|
+ // UPLOAD FreeAPS Settings WHEN CHANGED
|
|
|
|
|
+ if let uploadedSettings = storage.retrieve(OpenAPS.Nightscout.uploadedSettings, as: FreeAPSSettings.self),
|
|
|
|
|
+ uploadedSettings.rawJSON.sorted() == settings.rawJSON.sorted(), !force
|
|
|
|
|
+ {
|
|
|
|
|
+ NSLog("NightscoutManager Settings, settings unchanged")
|
|
|
|
|
+ } else { uploadSettings(settings) }
|
|
|
|
|
+
|
|
|
|
|
+ // UPLOAD Profiles WHEN CHANGED
|
|
|
|
|
+ if let uploadedProfile = storage.retrieve(OpenAPS.Nightscout.uploadedProfile, as: NightscoutProfileStore.self),
|
|
|
|
|
+ (uploadedProfile.store["default"]?.rawJSON ?? "").sorted() == ps.rawJSON.sorted(), !force
|
|
|
|
|
+ {
|
|
|
|
|
+ NSLog("NightscoutManager uploadProfile, no profile change")
|
|
|
|
|
+ } else {
|
|
|
|
|
+ processQueue.async {
|
|
|
|
|
+ nightscout.uploadProfile(p)
|
|
|
|
|
+ .sink { completion in
|
|
|
|
|
+ switch completion {
|
|
|
|
|
+ case .finished:
|
|
|
|
|
+ self.storage.save(p, as: OpenAPS.Nightscout.uploadedProfile)
|
|
|
|
|
+ debug(.nightscout, "Profile uploaded")
|
|
|
|
|
+ case let .failure(error):
|
|
|
|
|
+ debug(.nightscout, error.localizedDescription)
|
|
|
|
|
+ }
|
|
|
|
|
+ } receiveValue: {}
|
|
|
|
|
+ .store(in: &self.lifetime)
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func uploadGlucose() {
|
|
func uploadGlucose() {
|
|
|
uploadGlucose(glucoseStorage.nightscoutGlucoseNotUploaded(), fileToSave: OpenAPS.Nightscout.uploadedGlucose)
|
|
uploadGlucose(glucoseStorage.nightscoutGlucoseNotUploaded(), fileToSave: OpenAPS.Nightscout.uploadedGlucose)
|
|
|
-
|
|
|
|
|
uploadTreatments(glucoseStorage.nightscoutCGMStateNotUploaded(), fileToSave: OpenAPS.Nightscout.uploadedCGMState)
|
|
uploadTreatments(glucoseStorage.nightscoutCGMStateNotUploaded(), fileToSave: OpenAPS.Nightscout.uploadedCGMState)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -560,8 +615,9 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
|
|
|
switch completion {
|
|
switch completion {
|
|
|
case .finished:
|
|
case .finished:
|
|
|
self.storage.save(glucose, as: fileToSave)
|
|
self.storage.save(glucose, as: fileToSave)
|
|
|
|
|
+ debug(.nightscout, "Glucose uploaded")
|
|
|
case let .failure(error):
|
|
case let .failure(error):
|
|
|
- debug(.nightscout, error.localizedDescription)
|
|
|
|
|
|
|
+ debug(.nightscout, "Upload of glucose failed: " + error.localizedDescription)
|
|
|
}
|
|
}
|
|
|
} receiveValue: {}
|
|
} receiveValue: {}
|
|
|
.store(in: &self.lifetime)
|
|
.store(in: &self.lifetime)
|
|
@@ -589,6 +645,7 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
|
|
|
switch completion {
|
|
switch completion {
|
|
|
case .finished:
|
|
case .finished:
|
|
|
self.storage.save(treatments, as: fileToSave)
|
|
self.storage.save(treatments, as: fileToSave)
|
|
|
|
|
+ debug(.nightscout, "Treatments uploaded")
|
|
|
case let .failure(error):
|
|
case let .failure(error):
|
|
|
debug(.nightscout, error.localizedDescription)
|
|
debug(.nightscout, error.localizedDescription)
|
|
|
}
|
|
}
|