import Foundation struct FreeAPSSettings: JSON, Equatable { 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 var useAppleHealth: Bool = false var glucoseBadge: Bool = false var glucoseNotificationsAlways: Bool = false var useAlarmSound: Bool = false var addSourceInfoToGlucoseNotifications: Bool = false var lowGlucose: Decimal = 72 var highGlucose: Decimal = 270 var carbsRequiredThreshold: Decimal = 10 } 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 } if let useAppleHealth = try? container.decode(Bool.self, forKey: .useAppleHealth) { settings.useAppleHealth = useAppleHealth } if let glucoseBadge = try? container.decode(Bool.self, forKey: .glucoseBadge) { settings.glucoseBadge = glucoseBadge } if let glucoseNotificationsAlways = try? container.decode(Bool.self, forKey: .glucoseNotificationsAlways) { settings.glucoseNotificationsAlways = glucoseNotificationsAlways } if let useAlarmSound = try? container.decode(Bool.self, forKey: .useAlarmSound) { settings.useAlarmSound = useAlarmSound } if let addSourceInfoToGlucoseNotifications = try? container.decode( Bool.self, forKey: .addSourceInfoToGlucoseNotifications ) { settings.addSourceInfoToGlucoseNotifications = addSourceInfoToGlucoseNotifications } if let lowGlucose = try? container.decode(Decimal.self, forKey: .lowGlucose) { settings.lowGlucose = lowGlucose } if let highGlucose = try? container.decode(Decimal.self, forKey: .highGlucose) { settings.highGlucose = highGlucose } if let carbsRequiredThreshold = try? container.decode(Decimal.self, forKey: .carbsRequiredThreshold) { settings.carbsRequiredThreshold = carbsRequiredThreshold } self = settings } }