Explorar o código

Allow incomplete settings parsing

Ivan Valkou %!s(int64=4) %!d(string=hai) anos
pai
achega
e7f523cd28

+ 2 - 3
FreeAPS/Resources/json/defaults/freeaps/freeaps_settings.json

@@ -2,7 +2,7 @@
     "units": "mmol/L",
     "closedLoop": false,
     "allowAnnouncements": false,
-    "useAutotune": false
+    "useAutotune": false,
     "isUploadEnabled": false,
     "useLocalGlucoseSource": false,
     "localGlucosePort": 8080,
@@ -10,6 +10,5 @@
     "insulinReqFraction": 0.7,
     "skipBolusScreenAfterCarbs": false,
     "cgm": "nightscout",
-    "uploadGlucose": false,
-    "useCalendar": false
+    "uploadGlucose": false
 }

+ 1 - 2
FreeAPS/Sources/APS/FetchGlucoseManager.swift

@@ -34,8 +34,7 @@ final class BaseFetchGlucoseManager: FetchGlucoseManager, Injectable {
         case .dexcomG5,
              .dexcomG6:
             glucoseSource = dexcomSource
-        case .nightscout,
-             .none:
+        case .nightscout:
             glucoseSource = nightscoutManager
         case .libreTransmitter:
             glucoseSource = libreTransmitter

+ 9 - 4
FreeAPS/Sources/Helpers/JSON.swift

@@ -11,12 +11,17 @@ extension JSON {
     }
 
     init?(from: String) {
-        guard let data = from.data(using: .utf8),
-              let object = try? JSONCoding.decoder.decode(Self.self, from: data)
-        else {
+        guard let data = from.data(using: .utf8) else {
+            return nil
+        }
+
+        do {
+            let object = try JSONCoding.decoder.decode(Self.self, from: data)
+            self = object
+        } catch {
+            warning(.service, "Cannot decode JSON", error: error)
             return nil
         }
-        self = object
     }
 
     var dictionaryRepresentation: [String: Any]? {

+ 75 - 13
FreeAPS/Sources/Models/FreeAPSSettings.swift

@@ -1,17 +1,79 @@
 import Foundation
 
 struct FreeAPSSettings: JSON, Equatable {
-    var units: GlucoseUnits
-    var closedLoop: Bool
-    var allowAnnouncements: Bool
-    var useAutotune: Bool
-    var isUploadEnabled: Bool?
-    var useLocalGlucoseSource: Bool?
-    var localGlucosePort: Int?
-    var debugOptions: Bool?
-    var insulinReqFraction: Decimal?
-    var skipBolusScreenAfterCarbs: Bool?
-    var cgm: CGMType?
-    var uploadGlucose: Bool?
-    var useCalendar: Bool?
+    var units: GlucoseUnits = .mmolL
+    var closedLoop: Bool = false
+    var allowAnnouncements: Bool = false
+    var useAutotune: Bool = false
+    var isUploadEnabled: Bool = false
+    var useLocalGlucoseSource: Bool = false
+    var localGlucosePort: Int = 8080
+    var debugOptions: Bool = false
+    var insulinReqFraction: Decimal = 0.7
+    var skipBolusScreenAfterCarbs: Bool = false
+    var cgm: CGMType = .nightscout
+    var uploadGlucose: Bool = false
+    var useCalendar: Bool = false
+}
+
+extension FreeAPSSettings: Decodable {
+    // Needed to decode incomplete JSON
+    init(from decoder: Decoder) throws {
+        let container = try decoder.container(keyedBy: CodingKeys.self)
+        var settings = FreeAPSSettings()
+
+        if let units = try? container.decode(GlucoseUnits.self, forKey: .units) {
+            settings.units = units
+        }
+
+        if let closedLoop = try? container.decode(Bool.self, forKey: .closedLoop) {
+            settings.closedLoop = closedLoop
+        }
+
+        if let allowAnnouncements = try? container.decode(Bool.self, forKey: .allowAnnouncements) {
+            settings.allowAnnouncements = allowAnnouncements
+        }
+
+        if let useAutotune = try? container.decode(Bool.self, forKey: .useAutotune) {
+            settings.useAutotune = useAutotune
+        }
+
+        if let isUploadEnabled = try? container.decode(Bool.self, forKey: .isUploadEnabled) {
+            settings.isUploadEnabled = isUploadEnabled
+        }
+
+        if let useLocalGlucoseSource = try? container.decode(Bool.self, forKey: .useLocalGlucoseSource) {
+            settings.useLocalGlucoseSource = useLocalGlucoseSource
+        }
+
+        if let localGlucosePort = try? container.decode(Int.self, forKey: .localGlucosePort) {
+            settings.localGlucosePort = localGlucosePort
+        }
+
+        if let debugOptions = try? container.decode(Bool.self, forKey: .debugOptions) {
+            settings.debugOptions = debugOptions
+        }
+
+        if let insulinReqFraction = try? container.decode(Decimal.self, forKey: .insulinReqFraction) {
+            settings.insulinReqFraction = insulinReqFraction
+        }
+
+        if let skipBolusScreenAfterCarbs = try? container.decode(Bool.self, forKey: .skipBolusScreenAfterCarbs) {
+            settings.skipBolusScreenAfterCarbs = skipBolusScreenAfterCarbs
+        }
+
+        if let cgm = try? container.decode(CGMType.self, forKey: .cgm) {
+            settings.cgm = cgm
+        }
+
+        if let uploadGlucose = try? container.decode(Bool.self, forKey: .uploadGlucose) {
+            settings.uploadGlucose = uploadGlucose
+        }
+
+        if let useCalendar = try? container.decode(Bool.self, forKey: .useCalendar) {
+            settings.useCalendar = useCalendar
+        }
+
+        self = settings
+    }
 }

+ 1 - 1
FreeAPS/Sources/Modules/AddCarbs/AddCarbsStateModel.swift

@@ -23,7 +23,7 @@ extension AddCarbs {
                 CarbsEntry(createdAt: date, carbs: carbs, enteredBy: CarbsEntry.manual)
             ])
 
-            if settingsManager.settings.skipBolusScreenAfterCarbs ?? false {
+            if settingsManager.settings.skipBolusScreenAfterCarbs {
                 apsManager.determineBasalSync()
                 showModal(for: nil)
             } else {

+ 1 - 1
FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift

@@ -77,7 +77,7 @@ extension Bolus {
             DispatchQueue.main.async {
                 self.inslinRequired = self.provider.suggestion?.insulinReq ?? 0
                 self.inslinRecommended = self.apsManager
-                    .roundBolus(amount: max(self.inslinRequired * (self.settingsManager.settings.insulinReqFraction ?? 0.7), 0))
+                    .roundBolus(amount: max(self.inslinRequired * self.settingsManager.settings.insulinReqFraction, 0))
             }
         }
     }

+ 3 - 3
FreeAPS/Sources/Modules/CGM/CGMStateModel.swift

@@ -16,12 +16,12 @@ extension CGM {
         @Persisted(key: "CalendarManager.currentCalendarID") var storedCalendarID: String? = nil
 
         override func subscribe() {
-            cgm = settingsManager.settings.cgm ?? .nightscout
-            uploadGlucose = settingsManager.settings.uploadGlucose ?? false
+            cgm = settingsManager.settings.cgm
+            uploadGlucose = settingsManager.settings.uploadGlucose
             transmitterID = UserDefaults.standard.dexcomTransmitterID ?? ""
             currentCalendarID = storedCalendarID ?? ""
             calendarIDs = calendarManager.calendarIDs()
-            createCalendarEvents = settingsManager.settings.useCalendar ?? false
+            createCalendarEvents = settingsManager.settings.useCalendar
 
             $cgm
                 .removeDuplicates()

+ 3 - 3
FreeAPS/Sources/Modules/NightscoutConfig/NightscoutConfigStateModel.swift

@@ -18,9 +18,9 @@ extension NightscoutConfig {
         override func subscribe() {
             url = keychain.getValue(String.self, forKey: Config.urlKey) ?? ""
             secret = keychain.getValue(String.self, forKey: Config.secretKey) ?? ""
-            isUploadEnabled = settingsManager.settings.isUploadEnabled ?? false
-            useLocalSource = settingsManager.settings.useLocalGlucoseSource ?? false
-            localPort = Decimal(settingsManager.settings.localGlucosePort ?? 8080)
+            isUploadEnabled = settingsManager.settings.isUploadEnabled
+            useLocalSource = settingsManager.settings.useLocalGlucoseSource
+            localPort = Decimal(settingsManager.settings.localGlucosePort)
 
             $isUploadEnabled
                 .removeDuplicates()

+ 2 - 2
FreeAPS/Sources/Modules/PreferencesEditor/PreferencesEditorStateModel.swift

@@ -17,8 +17,8 @@ extension PreferencesEditor {
             unitsIndex = settingsManager.settings.units == .mgdL ? 0 : 1
             allowAnnouncements = settingsManager.settings.allowAnnouncements
 
-            insulinReqFraction = settingsManager.settings.insulinReqFraction ?? 0.7
-            skipBolusScreenAfterCarbs = settingsManager.settings.skipBolusScreenAfterCarbs ?? false
+            insulinReqFraction = settingsManager.settings.insulinReqFraction
+            skipBolusScreenAfterCarbs = settingsManager.settings.skipBolusScreenAfterCarbs
 
             $unitsIndex
                 .removeDuplicates()

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

@@ -13,7 +13,7 @@ extension Settings {
 
         override func subscribe() {
             closedLoop = settingsManager.settings.closedLoop
-            debugOptions = settingsManager.settings.debugOptions ?? false
+            debugOptions = settingsManager.settings.debugOptions
 
             $closedLoop
                 .removeDuplicates()
@@ -45,6 +45,6 @@ extension Settings {
 extension Settings.StateModel: SettingsObserver {
     func settingsDidChange(_ settings: FreeAPSSettings) {
         closedLoop = settings.closedLoop
-        debugOptions = settings.debugOptions ?? false
+        debugOptions = settings.debugOptions
     }
 }

+ 1 - 1
FreeAPS/Sources/Services/Calendar/CalendarManager.swift

@@ -47,7 +47,7 @@ final class BaseCalendarManager: CalendarManager, Injectable {
     }
 
     func createEvent(for glucose: BloodGlucose?, delta: Int?) {
-        guard settingsManager.settings.useCalendar ?? false else { return }
+        guard settingsManager.settings.useCalendar else { return }
 
         guard let calendar = currentCalendar else { return }
 

+ 7 - 9
FreeAPS/Sources/Services/Network/NightscoutManager.swift

@@ -35,11 +35,11 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
     }
 
     private var isUploadEnabled: Bool {
-        settingsManager.settings.isUploadEnabled ?? false
+        settingsManager.settings.isUploadEnabled
     }
 
     private var isUploadGlucoseEnabled: Bool {
-        settingsManager.settings.uploadGlucose ?? false
+        settingsManager.settings.uploadGlucose
     }
 
     private var nightscoutAPI: NightscoutAPI? {
@@ -67,23 +67,21 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
     }
 
     var cgmURL: URL? {
-        if let url = settingsManager.settings.cgm?.appURL {
+        if let url = settingsManager.settings.cgm.appURL {
             return url
         }
 
-        let useLocal = (settingsManager.settings.useLocalGlucoseSource ?? false) && settingsManager.settings
-            .localGlucosePort != nil
+        let useLocal = settingsManager.settings.useLocalGlucoseSource
 
         let maybeNightscout = useLocal
-            ? NightscoutAPI(url: URL(string: "http://127.0.0.1:\(settingsManager.settings.localGlucosePort!)")!)
+            ? NightscoutAPI(url: URL(string: "http://127.0.0.1:\(settingsManager.settings.localGlucosePort)")!)
             : nightscoutAPI
 
         return maybeNightscout?.url
     }
 
     func fetchGlucose() -> AnyPublisher<[BloodGlucose], Never> {
-        let useLocal = (settingsManager.settings.useLocalGlucoseSource ?? false) && settingsManager.settings
-            .localGlucosePort != nil
+        let useLocal = settingsManager.settings.useLocalGlucoseSource
 
         if !useLocal {
             guard isNetworkReachable else {
@@ -92,7 +90,7 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
         }
 
         let maybeNightscout = useLocal
-            ? NightscoutAPI(url: URL(string: "http://127.0.0.1:\(settingsManager.settings.localGlucosePort!)")!)
+            ? NightscoutAPI(url: URL(string: "http://127.0.0.1:\(settingsManager.settings.localGlucosePort)")!)
             : nightscoutAPI
 
         guard let nightscout = maybeNightscout else {

+ 1 - 10
FreeAPS/Sources/Services/SettingsManager/SettingsManager.swift

@@ -31,16 +31,7 @@ final class BaseSettingsManager: SettingsManager, Injectable {
         let storage = resolver.resolve(FileStorage.self)!
         settings = storage.retrieve(OpenAPS.FreeAPS.settings, as: FreeAPSSettings.self)
             ?? FreeAPSSettings(from: OpenAPS.defaults(for: OpenAPS.FreeAPS.settings))
-            ?? FreeAPSSettings(
-                units: .mmolL,
-                closedLoop: false,
-                allowAnnouncements: false,
-                useAutotune: false,
-                isUploadEnabled: false,
-                useLocalGlucoseSource: false,
-                localGlucosePort: nil,
-                debugOptions: false
-            )
+            ?? FreeAPSSettings()
 
         injectServices(resolver)
     }