Skip to content

Commit

Permalink
Move dynamic ISF settings out from "OpenAPS" to "Extra Features" section
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon-b-m committed Nov 5, 2023
1 parent 1cde3dd commit 5ae04a9
Show file tree
Hide file tree
Showing 11 changed files with 209 additions and 78 deletions.
34 changes: 33 additions & 1 deletion FreeAPS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
1927C8E62744606D00347C69 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1927C8E82744606D00347C69 /* InfoPlist.strings */; };
1935364028496F7D001E0B16 /* Oref2_variables.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1935363F28496F7D001E0B16 /* Oref2_variables.swift */; };
193F6CDD2A512C8F001240FD /* Loops.swift in Sources */ = {isa = PBXBuildFile; fileRef = 193F6CDC2A512C8F001240FD /* Loops.swift */; };
195D80B42AF6973A00D25097 /* DynamicRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80B32AF6973A00D25097 /* DynamicRootView.swift */; };
195D80B72AF697B800D25097 /* DynamicDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80B62AF697B800D25097 /* DynamicDataFlow.swift */; };
195D80B92AF697F700D25097 /* DynamicProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80B82AF697F700D25097 /* DynamicProvider.swift */; };
195D80BB2AF6980B00D25097 /* DynamicStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80BA2AF6980B00D25097 /* DynamicStateModel.swift */; };
1967DFBE29D052C200759F30 /* Icons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1967DFBD29D052C200759F30 /* Icons.swift */; };
1967DFC029D053AC00759F30 /* IconSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1967DFBF29D053AC00759F30 /* IconSelection.swift */; };
1967DFC229D053D300759F30 /* IconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1967DFC129D053D300759F30 /* IconImage.swift */; };
Expand Down Expand Up @@ -526,6 +530,10 @@
1927C8FE274489BA00347C69 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/InfoPlist.strings; sourceTree = "<group>"; };
1935363F28496F7D001E0B16 /* Oref2_variables.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Oref2_variables.swift; sourceTree = "<group>"; };
193F6CDC2A512C8F001240FD /* Loops.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Loops.swift; sourceTree = "<group>"; };
195D80B32AF6973A00D25097 /* DynamicRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRootView.swift; sourceTree = "<group>"; };
195D80B62AF697B800D25097 /* DynamicDataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicDataFlow.swift; sourceTree = "<group>"; };
195D80B82AF697F700D25097 /* DynamicProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicProvider.swift; sourceTree = "<group>"; };
195D80BA2AF6980B00D25097 /* DynamicStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicStateModel.swift; sourceTree = "<group>"; };
1967DFBD29D052C200759F30 /* Icons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icons.swift; sourceTree = "<group>"; };
1967DFBF29D053AC00759F30 /* IconSelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconSelection.swift; sourceTree = "<group>"; };
1967DFC129D053D300759F30 /* IconImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconImage.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1050,6 +1058,25 @@
name = "Recovered References";
sourceTree = "<group>";
};
195D80B22AF696EE00D25097 /* Dynamic */ = {
isa = PBXGroup;
children = (
195D80B62AF697B800D25097 /* DynamicDataFlow.swift */,
195D80B82AF697F700D25097 /* DynamicProvider.swift */,
195D80BA2AF6980B00D25097 /* DynamicStateModel.swift */,
195D80B52AF6974200D25097 /* View */,
);
path = Dynamic;
sourceTree = "<group>";
};
195D80B52AF6974200D25097 /* View */ = {
isa = PBXGroup;
children = (
195D80B32AF6973A00D25097 /* DynamicRootView.swift */,
);
path = View;
sourceTree = "<group>";
};
198377CF266BFEDE004DE65E /* Localizations */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -1168,10 +1195,11 @@
3811DE0325C9D31700A708ED /* Modules */ = {
isa = PBXGroup;
children = (
195D80B22AF696EE00D25097 /* Dynamic */,
BD7DA9A32AE06DBA00601B20 /* BolusCalculatorConfig */,
190EBCC229FF134900BA767D /* StatConfig */,
CE94597C29E9E1CD0047C9C6 /* WatchConfig */,
19F95FF129F10F9C00314DDC /* Stat */,
CE94597C29E9E1CD0047C9C6 /* WatchConfig */,
19E1F7E629D0828B005C8D20 /* IconConfig */,
19D466A129AA2B0A004D5F33 /* FPUConfig */,
F90692CD274B99850037068D /* HealthKit */,
Expand Down Expand Up @@ -2576,6 +2604,7 @@
38C4D33725E9A1A300D30B77 /* DispatchQueue+Extensions.swift in Sources */,
F90692CF274B999A0037068D /* HealthKitDataFlow.swift in Sources */,
CE7CA3552A064973004BE681 /* ListStateIntent.swift in Sources */,
195D80B72AF697B800D25097 /* DynamicDataFlow.swift in Sources */,
3862CC2E2743F9F700BF832C /* CalendarManager.swift in Sources */,
CEA4F62329BE10F70011ADF7 /* SavitzkyGolayFilter.swift in Sources */,
38B4F3C325E2A20B00E76A18 /* PumpSetupView.swift in Sources */,
Expand Down Expand Up @@ -2758,6 +2787,7 @@
19F95FF729F10FEE00314DDC /* StatStateModel.swift in Sources */,
385CEAC125F2EA52002D6D5B /* Announcement.swift in Sources */,
8B759CFCF47B392BB365C251 /* BasalProfileEditorDataFlow.swift in Sources */,
195D80B42AF6973A00D25097 /* DynamicRootView.swift in Sources */,
389442CB25F65F7100FA1F27 /* NightscoutTreatment.swift in Sources */,
CE7CA3512A064973004BE681 /* ApplyTempPresetIntent.swift in Sources */,
FA630397F76B582C8D8681A7 /* BasalProfileEditorProvider.swift in Sources */,
Expand All @@ -2770,6 +2800,7 @@
38887CCE25F5725200944304 /* IOBEntry.swift in Sources */,
38E98A2425F52C9300C0CED0 /* Logger.swift in Sources */,
CA370FC152BC98B3D1832968 /* BasalProfileEditorRootView.swift in Sources */,
195D80BB2AF6980B00D25097 /* DynamicStateModel.swift in Sources */,
E00EEC0327368630002FF094 /* ServiceAssembly.swift in Sources */,
38192E07261BA9960094D973 /* FetchTreatmentsManager.swift in Sources */,
19012CDC291D2CB900FB8210 /* LoopStats.swift in Sources */,
Expand Down Expand Up @@ -2853,6 +2884,7 @@
1D845DF2E3324130E1D95E67 /* DataTableProvider.swift in Sources */,
19F95FFA29F1102A00314DDC /* StatRootView.swift in Sources */,
0D9A5E34A899219C5C4CDFAF /* DataTableStateModel.swift in Sources */,
195D80B92AF697F700D25097 /* DynamicProvider.swift in Sources */,
D6D02515BBFBE64FEBE89856 /* DataTableRootView.swift in Sources */,
38569349270B5DFB0002C50D /* AppGroupSource.swift in Sources */,
F5CA3DB1F9DC8B05792BBFAA /* CGMDataFlow.swift in Sources */,
Expand Down
5 changes: 5 additions & 0 deletions FreeAPS/Sources/Modules/Dynamic/DynamicDataFlow.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
enum Dynamic {
enum Config {}
}

protocol DynamicProvider: Provider {}
3 changes: 3 additions & 0 deletions FreeAPS/Sources/Modules/Dynamic/DynamicProvider.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
extension Dynamic {
final class Provider: BaseProvider, DynamicProvider {}
}
69 changes: 69 additions & 0 deletions FreeAPS/Sources/Modules/Dynamic/DynamicStateModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import SwiftUI

extension Dynamic {
final class StateModel: BaseStateModel<Provider> {
@Injected() var settings: SettingsManager!
@Injected() var storage: FileStorage!

@Published var useNewFormula: Bool = false
@Published var enableDynamicCR: Bool = false
@Published var sigmoid: Bool = false
@Published var adjustmentFactor: Decimal = 0.5
@Published var weightPercentage: Decimal = 0.65
@Published var tddAdjBasal: Bool = false
@Published var threshold_setting: Decimal = 65
@Published var unit: GlucoseUnits = .mmolL

var preferences: Preferences {
settingsManager.preferences
}

override func subscribe() {
unit = settingsManager.settings.units
useNewFormula = settings.preferences.useNewFormula
enableDynamicCR = settings.preferences.enableDynamicCR
sigmoid = settings.preferences.sigmoid
adjustmentFactor = settings.preferences.adjustmentFactor
weightPercentage = settings.preferences.weightPercentage
tddAdjBasal = settings.preferences.tddAdjBasal

if unit == .mmolL {
threshold_setting = settings.preferences.threshold_setting.asMmolL
} else {
threshold_setting = settings.preferences.threshold_setting
}
}

var unChanged: Bool {
preferences.enableDynamicCR == enableDynamicCR &&
preferences.adjustmentFactor == adjustmentFactor &&
preferences.sigmoid == sigmoid &&
preferences.tddAdjBasal == tddAdjBasal &&
preferences.threshold_setting == convertBack(threshold_setting) &&
preferences.useNewFormula == useNewFormula &&
preferences.weightPercentage == weightPercentage
}

func convertBack(_ glucose: Decimal) -> Decimal {
if unit == .mmolL {
return glucose.asMgdL
}
return glucose
}

func saveIfChanged() {
if !unChanged {
var newSettings = storage.retrieve(OpenAPS.Settings.preferences, as: Preferences.self) ?? Preferences()
newSettings.enableDynamicCR = enableDynamicCR
newSettings.adjustmentFactor = adjustmentFactor
newSettings.sigmoid = sigmoid
newSettings.tddAdjBasal = tddAdjBasal
newSettings.threshold_setting = convertBack(threshold_setting)
newSettings.useNewFormula = useNewFormula
newSettings.weightPercentage = weightPercentage
newSettings.timestamp = Date()
storage.save(newSettings, as: OpenAPS.Settings.preferences)
}
}
}
}
89 changes: 89 additions & 0 deletions FreeAPS/Sources/Modules/Dynamic/View/DynamicRootView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import SwiftUI
import Swinject

extension Dynamic {
struct RootView: BaseView {
let resolver: Resolver
@StateObject var state = StateModel()

private var conversionFormatter: NumberFormatter {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 1

return formatter
}

private var formatter: NumberFormatter {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter
}

private var glucoseFormatter: NumberFormatter {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
if state.unit == .mmolL {
formatter.maximumFractionDigits = 1
} else { formatter.maximumFractionDigits = 0 }
formatter.roundingMode = .halfUp
return formatter
}

var body: some View {
Form {
Section {
HStack {
Toggle("Activate Dynamic Sensitivity (ISF)", isOn: $state.useNewFormula)
}
if state.useNewFormula {
HStack {
Toggle("Activate Dynamic Carb Ratio (CR)", isOn: $state.enableDynamicCR)
}
}
} header: { Text("Enable") }

if state.useNewFormula {
Section {
HStack {
Toggle("Use Sigmoid Formula", isOn: $state.sigmoid)
}
} header: { Text("Formula") }

Section {
HStack {
Text("Adjustment Factor")
Spacer()
DecimalTextField("0", value: $state.adjustmentFactor, formatter: formatter)
}

HStack {
Text("Weighted Average of TDD. Weight of past 24 hours:")
Spacer()
DecimalTextField("0", value: $state.weightPercentage, formatter: formatter)
}

HStack {
Toggle("Adjust basal", isOn: $state.tddAdjBasal)
}
} header: { Text("Settings") }

Section {
HStack {
Text("Threshold Setting")
Spacer()
DecimalTextField("0", value: $state.threshold_setting, formatter: glucoseFormatter)
Text(state.unit.rawValue)
}
} header: { Text("Safety") }
}
}
.onAppear(perform: configureView)
.navigationBarTitle("Dynamic ISF")
.navigationBarTitleDisplayMode(.automatic)
.onDisappear {
state.saveIfChanged()
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ extension NightscoutConfig {
@Published var dia: Decimal = 6
@Published var maxBasal: Decimal = 2
@Published var maxBolus: Decimal = 10
@Published var allowAnnouncements: Bool = false

override func subscribe() {
url = keychain.getValue(String.self, forKey: Config.urlKey) ?? ""
Expand All @@ -41,6 +42,7 @@ extension NightscoutConfig {
maxBasal = settingsManager.pumpSettings.maxBasal
maxBolus = settingsManager.pumpSettings.maxBolus

subscribeSetting(\.allowAnnouncements, on: $allowAnnouncements) { allowAnnouncements = $0 }
subscribeSetting(\.isUploadEnabled, on: $isUploadEnabled) { isUploadEnabled = $0 }
subscribeSetting(\.useLocalGlucoseSource, on: $useLocalSource) { useLocalSource = $0 }
subscribeSetting(\.localGlucosePort, on: $localPort.map(Int.init)) { localPort = Decimal($0) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ extension NightscoutConfig {
Button("Backfill glucose") { state.backfillGlucose() }
.disabled(state.url.isEmpty || state.connecting || state.backfilling)
}

Section {
Toggle("Remote control", isOn: $state.allowAnnouncements)
} header: { Text("Allow Remote control of iAPS") }
}
.onAppear(perform: configureView)
.navigationBarTitle("Nightscout Config")
Expand Down
Loading

0 comments on commit 5ae04a9

Please sign in to comment.