Просмотр исходного кода

Refactor NS settings, preferences, profile uplad to async/await; introduce strict mg/dl and parse when necessary

Deniz Cengiz 1 год назад
Родитель
Сommit
87748cc204

+ 1 - 6
FreeAPS/Sources/Models/RawFetchedProfile.swift

@@ -4,15 +4,10 @@ struct FetchedNightscoutProfileStore: JSON {
     let _id: String
     let defaultProfile: String
     let startDate: String
-    // TODO: what is this shit used for?
-    // <<<<<<< HEAD
     let mills: Decimal
     let enteredBy: String
-//    let store: [String: ScheduledNightscoutProfile]
+    let store: [String: ScheduledNightscoutProfile]
     let created_at: String
-    //=======
-    let store: [String: FetchedNightscoutProfile]
-    // >>>>>>> 9672da256c317a314acc76d6e4f6e82cc174d133
 }
 
 struct FetchedNightscoutProfile: JSON {

+ 15 - 30
FreeAPS/Sources/Modules/NightscoutConfig/NightscoutConfigStateModel.swift

@@ -161,26 +161,14 @@ extension NightscoutConfig {
                 {
                     do {
                         let fetchedProfileStore = try jsonDecoder.decode([FetchedNightscoutProfileStore].self, from: data)
-                        let loop = fetchedProfileStore.first?.enteredBy.contains("Loop")
-                        guard let fetchedProfile: FetchedNightscoutProfile =
-                            (fetchedProfileStore.first?.store["default"] != nil) ?
-                            fetchedProfileStore.first?.store["default"] :
-                            fetchedProfileStore.first?.store["Default"]
+                        guard let fetchedProfile: ScheduledNightscoutProfile = fetchedProfileStore.first?.store["default"]
                         else {
                             error = "\nCan't find the default Nightscout Profile."
                             group.leave()
                             return
                         }
 
-                        guard fetchedProfile.units.contains(self.units.rawValue.prefix(4)) else {
-                            debug(
-                                .nightscout,
-                                "Mismatching glucose units in Nightscout and Pump Settings. Import settings aborted."
-                            )
-                            error = "\nMismatching glucose units in Nightscout and Pump Settings. Import settings aborted."
-                            group.leave()
-                            return
-                        }
+                        let shouldConvertToMgdL = fetchedProfile.units.contains("mmol")
 
                         var areCRsOK = true
                         let carbratios = fetchedProfile.carbratio
@@ -230,41 +218,35 @@ extension NightscoutConfig {
 
                         let sensitivities = fetchedProfile.sens.map { sensitivity -> InsulinSensitivityEntry in
                             InsulinSensitivityEntry(
-                                sensitivity: sensitivity.value,
+                                sensitivity: shouldConvertToMgdL ? sensitivity.value.asMgdL : sensitivity.value,
                                 offset: self.offset(sensitivity.time) / 60,
                                 start: sensitivity.time
                             )
                         }
                         if sensitivities.filter({ $0.sensitivity <= 0 }).isNotEmpty {
                             error =
-                                "\nInvalid Nightscout Sensitivities Settings. \n\nImport aborted. Please check your Nightscout Profile Sensitivities Settings!"
+                                "\nInvalid Nightcsout Sensitivities Settings. \n\nImport aborted. Please check your Nightscout Profile Sensitivities Settings!"
                             group.leave()
                             return
                         }
 
                         let sensitivitiesProfile = InsulinSensitivities(
-                            units: self.units,
-                            userPreferredUnits: self.units,
+                            units: .mgdL,
+                            userPreferredUnits: .mgdL,
                             sensitivities: sensitivities
                         )
 
                         let targets = fetchedProfile.target_low
                             .map { target -> BGTargetEntry in
-                                let median = loop! ? self.getMedianTarget(
-                                    lowTargetValue: target.value,
-                                    lowTargetTime: target.time,
-                                    highTarget: fetchedProfile.target_high,
-                                    units: self.units
-                                ) : target.value
-                                return BGTargetEntry(
-                                    low: median,
-                                    high: median,
+                                BGTargetEntry(
+                                    low: shouldConvertToMgdL ? target.value.asMgdL : target.value,
+                                    high: shouldConvertToMgdL ? target.value.asMgdL : target.value,
                                     start: target.time,
                                     offset: self.offset(target.time) / 60
                                 ) }
                         let targetsProfile = BGTargets(
-                            units: self.units,
-                            userPreferredUnits: self.units,
+                            units: .mgdL,
+                            userPreferredUnits: .mgdL,
                             targets: targets
                         )
                         // IS THERE A PUMP?
@@ -305,7 +287,10 @@ extension NightscoutConfig {
                                         maxBasal: self.maxBasal
                                     )
                                     self.storage.save(file, as: OpenAPS.Settings.settings)
-                                    debug(.nightscout, "DIA setting updated to " + dia.description + " after a NS import.")
+                                    debug(
+                                        .nightscout,
+                                        "DIA setting updated to " + dia.description + " after a NS import."
+                                    )
                                 }
                                 group.leave()
                             case .failure:

+ 2 - 2
FreeAPS/Sources/Modules/Settings/SettingsStateModel.swift

@@ -54,9 +54,9 @@ extension Settings {
             return items
         }
 
-        func uploadProfileAndSettings(_ force: Bool) {
+        func uploadProfileAndSettings(_ force: Bool) async {
             NSLog("SettingsState Upload Profile and Settings")
-            nightscoutManager.uploadProfileAndSettings(force)
+            await nightscoutManager.uploadProfileAndSettings(force)
         }
 
         func hideSettingsModal() {

+ 5 - 1
FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift

@@ -326,7 +326,11 @@ extension Settings {
                     }
                 }
                 .searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
-                .onDisappear(perform: { state.uploadProfileAndSettings(false) })
+                .onDisappear(perform: {
+                    Task.detached(priority: .low) {
+                        await state.uploadProfileAndSettings(false)
+                    }
+                })
                 .screenNavigation(self)
         }
     }

+ 36 - 24
FreeAPS/Sources/Services/Network/NightscoutAPI.swift

@@ -352,7 +352,7 @@ extension NightscoutAPI {
         }
         request.httpMethod = "POST"
 
-        let (data, response) = try await URLSession.shared.data(for: request)
+        let (_, response) = try await URLSession.shared.data(for: request)
 
         // Check the response status code
         guard let httpResponse = response as? HTTPURLResponse, 200 ..< 300 ~= httpResponse.statusCode else {
@@ -388,7 +388,7 @@ extension NightscoutAPI {
         }
         request.httpMethod = "POST"
 
-        let (data, response) = try await URLSession.shared.data(for: request)
+        let (_, response) = try await URLSession.shared.data(for: request)
 
         // Check the response status code
         guard let httpResponse = response as? HTTPURLResponse, 200 ..< 300 ~= httpResponse.statusCode else {
@@ -416,7 +416,7 @@ extension NightscoutAPI {
         request.httpBody = try JSONCoding.encoder.encode(stats)
         request.httpMethod = "POST"
 
-        let (data, response) = try await URLSession.shared.data(for: request)
+        let (_, response) = try await URLSession.shared.data(for: request)
 
         guard let httpResponse = response as? HTTPURLResponse, (200 ... 299).contains(httpResponse.statusCode) else {
             throw URLError(.badServerResponse)
@@ -482,14 +482,18 @@ extension NightscoutAPI {
             .eraseToAnyPublisher()
     }
 
-    func uploadSettings(_ settings: NightscoutSettings) -> AnyPublisher<Void, Swift.Error> {
+    func uploadSettings(_ settings: NightscoutSettings) async throws {
         var components = URLComponents()
         components.scheme = url.scheme
         components.host = url.host
         components.port = url.port
         components.path = Config.statusPath
 
-        var request = URLRequest(url: components.url!)
+        guard let url = components.url else {
+            throw URLError(.badURL)
+        }
+
+        var request = URLRequest(url: url)
         request.allowsConstrainedNetworkAccess = false
         request.timeoutInterval = Config.timeout
         request.addValue("application/json", forHTTPHeaderField: "Content-Type")
@@ -497,23 +501,27 @@ extension NightscoutAPI {
         if let secret = secret {
             request.addValue(secret.sha1(), forHTTPHeaderField: "api-secret")
         }
-        request.httpBody = try! JSONCoding.encoder.encode(settings)
+        request.httpBody = try JSONCoding.encoder.encode(settings)
         request.httpMethod = "POST"
 
-        return service.run(request)
-            .retry(Config.retryCount)
-            .map { _ in () }
-            .eraseToAnyPublisher()
+        let (_, response) = try await URLSession.shared.data(for: request)
+        if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 200 {
+            throw URLError(.badServerResponse)
+        }
     }
 
-    func uploadProfile(_ profile: NightscoutProfileStore) -> AnyPublisher<Void, Swift.Error> {
+    func uploadProfile(_ profile: NightscoutProfileStore) async throws {
         var components = URLComponents()
         components.scheme = url.scheme
         components.host = url.host
         components.port = url.port
         components.path = Config.profilePath
 
-        var request = URLRequest(url: components.url!)
+        guard let url = components.url else {
+            throw URLError(.badURL)
+        }
+
+        var request = URLRequest(url: url)
         request.allowsConstrainedNetworkAccess = false
         request.timeoutInterval = Config.timeout
         request.addValue("application/json", forHTTPHeaderField: "Content-Type")
@@ -521,23 +529,27 @@ extension NightscoutAPI {
         if let secret = secret {
             request.addValue(secret.sha1(), forHTTPHeaderField: "api-secret")
         }
-        request.httpBody = try! JSONCoding.encoder.encode(profile)
+        request.httpBody = try JSONCoding.encoder.encode(profile)
         request.httpMethod = "POST"
 
-        return service.run(request)
-            .retry(Config.retryCount)
-            .map { _ in () }
-            .eraseToAnyPublisher()
+        let (_, response) = try await URLSession.shared.data(for: request)
+        if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 200 {
+            throw URLError(.badServerResponse)
+        }
     }
 
-    func uploadPreferences(_ preferences: Preferences) -> AnyPublisher<Void, Swift.Error> {
+    func uploadPreferences(_ preferences: Preferences) async throws {
         var components = URLComponents()
         components.scheme = url.scheme
         components.host = url.host
         components.port = url.port
         components.path = Config.profilePath
 
-        var request = URLRequest(url: components.url!)
+        guard let url = components.url else {
+            throw URLError(.badURL)
+        }
+
+        var request = URLRequest(url: url)
         request.allowsConstrainedNetworkAccess = false
         request.timeoutInterval = Config.timeout
         request.addValue("application/json", forHTTPHeaderField: "Content-Type")
@@ -545,13 +557,13 @@ extension NightscoutAPI {
         if let secret = secret {
             request.addValue(secret.sha1(), forHTTPHeaderField: "api-secret")
         }
-        request.httpBody = try! JSONCoding.encoder.encode(preferences)
+        request.httpBody = try JSONCoding.encoder.encode(preferences)
         request.httpMethod = "POST"
 
-        return service.run(request)
-            .retry(Config.retryCount)
-            .map { _ in () }
-            .eraseToAnyPublisher()
+        let (_, response) = try await URLSession.shared.data(for: request)
+        if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 200 {
+            throw URLError(.badServerResponse)
+        }
     }
 
     func uploadOverrides(_ overrides: [NightscoutExercise]) async throws {

+ 164 - 171
FreeAPS/Sources/Services/Network/NightscoutManager.swift

@@ -17,8 +17,8 @@ protocol NightscoutManager: GlucoseSource {
     func uploadGlucose() async
     func uploadManualGlucose() async
     func uploadStatistics(dailystat: Statistics) async
-    func uploadPreferences(_ preferences: Preferences)
-    func uploadProfileAndSettings(_: Bool)
+    func uploadPreferences(_ preferences: Preferences) async
+    func uploadProfileAndSettings(_: Bool) async
     var cgmURL: URL? { get }
 }
 
@@ -299,51 +299,35 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
         }
     }
 
-    func uploadPreferences(_ preferences: Preferences) {
-        let prefs = NightscoutPreferences(
-            preferences: settingsManager.preferences
-        )
+    func uploadPreferences(_ preferences: Preferences) async {
+        let prefs = NightscoutPreferences(preferences: settingsManager.preferences)
 
         guard let nightscout = nightscoutAPI, isUploadEnabled else {
             return
         }
 
-        processQueue.async {
-            nightscout.uploadPrefs(prefs)
-                .sink { completion in
-                    switch completion {
-                    case .finished:
-                        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)
+        do {
+            try await nightscout.uploadPrefs(prefs)
+            debug(.nightscout, "Preferences uploaded")
+            storage.save(preferences, as: OpenAPS.Nightscout.uploadedPreferences)
+        } catch {
+            debug(.nightscout, error.localizedDescription)
         }
     }
 
-    func uploadSettings(_ settings: FreeAPSSettings) {
-        let sets = NightscoutSettings(
-            settings: settingsManager.settings
-        )
+    func uploadSettings(_ settings: FreeAPSSettings) async {
+        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):
-                        debug(.nightscout, error.localizedDescription)
-                    }
-                } receiveValue: {}
-                .store(in: &self.lifetime)
+        do {
+            try await nightscout.uploadSettings(sets)
+            debug(.nightscout, "Settings uploaded")
+            storage.save(settings, as: OpenAPS.Nightscout.uploadedSettings)
+        } catch {
+            debug(.nightscout, error.localizedDescription)
         }
     }
 
@@ -528,150 +512,159 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
         }
     }
 
-    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
-        }
+    func uploadProfileAndSettings(_ force: Bool) async {
+        do {
+            guard let sensitivities = await storage.retrieveAsync(
+                OpenAPS.Settings.insulinSensitivities,
+                as: InsulinSensitivities.self
+            ) else {
+                debug(.nightscout, "NightscoutManager uploadProfile: error loading insulinSensitivities")
+                return
+            }
+            guard let settings = await storage.retrieveAsync(OpenAPS.FreeAPS.settings, as: FreeAPSSettings.self) else {
+                debug(.nightscout, "NightscoutManager uploadProfile: error loading settings")
+                return
+            }
+            guard let preferences = await storage.retrieveAsync(OpenAPS.Settings.preferences, as: Preferences.self) else {
+                debug(.nightscout, "NightscoutManager uploadProfile: error loading preferences")
+                return
+            }
+            guard let targets = await storage.retrieveAsync(OpenAPS.Settings.bgTargets, as: BGTargets.self) else {
+                debug(.nightscout, "NightscoutManager uploadProfile: error loading bgTargets")
+                return
+            }
+            guard let carbRatios = await storage.retrieveAsync(OpenAPS.Settings.carbRatios, as: CarbRatios.self) else {
+                debug(.nightscout, "NightscoutManager uploadProfile: error loading carbRatios")
+                return
+            }
+            guard let basalProfile = await storage.retrieveAsync(OpenAPS.Settings.basalProfile, as: [BasalProfileEntry].self)
+            else {
+                debug(.nightscout, "NightscoutManager uploadProfile: error loading basalProfile")
+                return
+            }
 
-        let sens = sensitivities.sensitivities.map { item -> NightscoutTimevalue in
-            NightscoutTimevalue(
-                time: String(item.start.prefix(5)),
-                value: item.sensitivity,
-                timeAsSeconds: item.offset * 60
-            )
-        }
-        let target_low = targets.targets.map { item -> NightscoutTimevalue in
-            NightscoutTimevalue(
-                time: String(item.start.prefix(5)),
-                value: item.low,
-                timeAsSeconds: item.offset * 60
-            )
-        }
-        let target_high = targets.targets.map { item -> NightscoutTimevalue in
-            NightscoutTimevalue(
-                time: String(item.start.prefix(5)),
-                value: item.high,
-                timeAsSeconds: item.offset * 60
-            )
-        }
-        let cr = carbRatios.schedule.map { item -> NightscoutTimevalue in
-            NightscoutTimevalue(
-                time: String(item.start.prefix(5)),
-                value: item.ratio,
-                timeAsSeconds: item.offset * 60
-            )
-        }
-        let basal = basalProfile.map { item -> NightscoutTimevalue in
-            NightscoutTimevalue(
-                time: String(item.start.prefix(5)),
-                value: item.rate,
-                timeAsSeconds: item.minutes * 60
-            )
-        }
+            let sens = sensitivities.sensitivities.map { item in
+                NightscoutTimevalue(
+                    time: String(item.start.prefix(5)),
+                    value: item.sensitivity,
+                    timeAsSeconds: item.offset * 60
+                )
+            }
+            let targetLow = targets.targets.map { item in
+                NightscoutTimevalue(
+                    time: String(item.start.prefix(5)),
+                    value: item.low,
+                    timeAsSeconds: item.offset * 60
+                )
+            }
+            let targetHigh = targets.targets.map { item in
+                NightscoutTimevalue(
+                    time: String(item.start.prefix(5)),
+                    value: item.high,
+                    timeAsSeconds: item.offset * 60
+                )
+            }
+            let cr = carbRatios.schedule.map { item in
+                NightscoutTimevalue(
+                    time: String(item.start.prefix(5)),
+                    value: item.ratio,
+                    timeAsSeconds: item.offset * 60
+                )
+            }
+            let basal = basalProfile.map { item in
+                NightscoutTimevalue(
+                    time: String(item.start.prefix(5)),
+                    value: item.rate,
+                    timeAsSeconds: item.minutes * 60
+                )
+            }
 
-        var nsUnits = ""
-        switch settingsManager.settings.units {
-        case .mgdL:
-            nsUnits = "mg/dl"
-        case .mmolL:
-            nsUnits = "mmol"
-        }
+            let nsUnits: String = {
+                switch settingsManager.settings.units {
+                case .mgdL:
+                    return "mg/dl"
+                case .mmolL:
+                    return "mmol"
+                }
+            }()
+
+            var carbsHr: Decimal = 0
+            if let isf = sensitivities.sensitivities.map(\.sensitivity).first,
+               let cr = carbRatios.schedule.map(\.ratio).first,
+               isf > 0, cr > 0
+            {
+                carbsHr = settingsManager.preferences.min5mCarbimpact * 12 / isf * cr
+                if settingsManager.settings.units == .mmolL {
+                    carbsHr *= GlucoseUnits.exchangeRate
+                }
+                carbsHr = Decimal(round(Double(carbsHr) * 10.0)) / 10
+            }
 
-        var carbs_hr: Decimal = 0
-        if let isf = sensitivities.sensitivities.map(\.sensitivity).first,
-           let cr = carbRatios.schedule.map(\.ratio).first,
-           isf > 0, cr > 0
-        {
-            // CarbImpact -> Carbs/hr = CI [mg/dl/5min] * 12 / ISF [mg/dl/U] * CR [g/U]
-            carbs_hr = settingsManager.preferences.min5mCarbimpact * 12 / isf * cr
-            if settingsManager.settings.units == .mmolL {
-                carbs_hr = carbs_hr * GlucoseUnits.exchangeRate
-            }
-            // No, Decimal has no rounding function.
-            carbs_hr = Decimal(round(Double(carbs_hr) * 10.0)) / 10
-        }
-
-        let ps = ScheduledNightscoutProfile(
-            dia: settingsManager.pumpSettings.insulinActionCurve,
-            carbs_hr: Int(carbs_hr),
-            delay: 0,
-            timezone: TimeZone.current.identifier,
-            target_low: target_low,
-            target_high: target_high,
-            sens: sens,
-            basal: basal,
-            carbratio: cr,
-            units: nsUnits
-        )
-        let defaultProfile = "default"
-
-        let now = Date()
-        let p = NightscoutProfileStore(
-            defaultProfile: defaultProfile,
-            startDate: now,
-            mills: Int(now.timeIntervalSince1970) * 1000,
-            units: nsUnits,
-            enteredBy: NightscoutTreatment.local,
-            store: [defaultProfile: ps]
-        )
+            let scheduledProfile = ScheduledNightscoutProfile(
+                dia: settingsManager.pumpSettings.insulinActionCurve,
+                carbs_hr: Int(carbsHr),
+                delay: 0,
+                timezone: TimeZone.current.identifier,
+                target_low: targetLow,
+                target_high: targetHigh,
+                sens: sens,
+                basal: basal,
+                carbratio: cr,
+                units: nsUnits
+            )
+            let defaultProfile = "default"
+
+            let now = Date()
+            let profileStore = NightscoutProfileStore(
+                defaultProfile: defaultProfile,
+                startDate: now,
+                mills: Int(now.timeIntervalSince1970) * 1000,
+                units: nsUnits,
+                enteredBy: NightscoutTreatment.local,
+                store: [defaultProfile: scheduledProfile]
+            )
 
-        guard let nightscout = nightscoutAPI, isNetworkReachable, isUploadEnabled else {
-            return
-        }
+            guard let nightscout = nightscoutAPI, isNetworkReachable, isUploadEnabled else {
+                return
+            }
 
-        // 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 Preferences when changed
+            if let uploadedPreferences = await storage.retrieveAsync(
+                OpenAPS.Nightscout.uploadedPreferences,
+                as: Preferences.self
+            ),
+                uploadedPreferences.rawJSON.sorted() == preferences.rawJSON.sorted(), !force
+            {
+                NSLog("NightscoutManager Preferences, preferences unchanged")
+            } else {
+                await 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 FreeAPS Settings when changed
+            if let uploadedSettings = await storage.retrieveAsync(OpenAPS.Nightscout.uploadedSettings, as: FreeAPSSettings.self),
+               uploadedSettings.rawJSON.sorted() == settings.rawJSON.sorted(), !force
+            {
+                NSLog("NightscoutManager Settings, settings unchanged")
+            } else {
+                await 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)
+            // Upload Profiles when changed
+            if let uploadedProfile = await storage.retrieveAsync(
+                OpenAPS.Nightscout.uploadedProfile,
+                as: NightscoutProfileStore.self
+            ),
+                (uploadedProfile.store["default"]?.rawJSON ?? "").sorted() == scheduledProfile.rawJSON.sorted(), !force
+            {
+                NSLog("NightscoutManager uploadProfile, no profile change")
+            } else {
+                do {
+                    try await nightscout.uploadProfile(profileStore)
+                    storage.save(profileStore, as: OpenAPS.Nightscout.uploadedProfile)
+                    debug(.nightscout, "Profile uploaded")
+                } catch {
+                    debug(.nightscout, "NightscoutManager uploadProfile: \(error.localizedDescription)")
+                }
             }
         }
     }