diff --git a/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.kt b/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.kt index 24b8449fcc..0b8852a64a 100644 --- a/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.kt @@ -11,8 +11,8 @@ import info.nightscout.androidaps.insight.database.InsightDatabaseDao import info.nightscout.androidaps.insight.database.InsightDbHelper import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin import info.nightscout.database.impl.AppRepository -import info.nightscout.interfaces.ApsMode import info.nightscout.implementation.iob.GlucoseStatusProviderImpl +import info.nightscout.interfaces.ApsMode import info.nightscout.interfaces.bgQualityCheck.BgQualityCheck import info.nightscout.interfaces.constraints.Constraint import info.nightscout.interfaces.constraints.Constraints @@ -29,6 +29,7 @@ import info.nightscout.interfaces.pump.PumpSync import info.nightscout.interfaces.pump.TemporaryBasalStorage import info.nightscout.interfaces.pump.defs.PumpDescription import info.nightscout.interfaces.queue.CommandQueue +import info.nightscout.interfaces.stats.TddCalculator import info.nightscout.interfaces.ui.UiInteraction import info.nightscout.interfaces.utils.HardLimits import info.nightscout.plugins.aps.openAPSAMA.OpenAPSAMAPlugin @@ -75,6 +76,7 @@ class ConstraintsCheckerTest : TestBaseWithProfile() { @Mock lateinit var danaHistoryDatabase: DanaHistoryDatabase @Mock lateinit var insightDatabase: InsightDatabase @Mock lateinit var bgQualityCheck: BgQualityCheck + @Mock lateinit var tddCalculator: TddCalculator private lateinit var hardLimits: HardLimits private lateinit var danaPump: DanaPump @@ -190,7 +192,8 @@ class ConstraintsCheckerTest : TestBaseWithProfile() { dateUtil, repository, glucoseStatusProvider, - bgQualityCheck + bgQualityCheck, + tddCalculator ) openAPSSMBDynamicISFPlugin = OpenAPSSMBDynamicISFPlugin( @@ -209,8 +212,8 @@ class ConstraintsCheckerTest : TestBaseWithProfile() { dateUtil, repository, glucoseStatusProvider, - config, - bgQualityCheck + bgQualityCheck, + tddCalculator ) openAPSAMAPlugin = OpenAPSAMAPlugin( diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/safety/SafetyPluginTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/safety/SafetyPluginTest.kt index d15f8835d0..6ce0cd1929 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/safety/SafetyPluginTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/safety/SafetyPluginTest.kt @@ -15,6 +15,7 @@ import info.nightscout.interfaces.plugin.ActivePlugin import info.nightscout.interfaces.plugin.PluginType import info.nightscout.interfaces.profiling.Profiler import info.nightscout.interfaces.pump.defs.PumpDescription +import info.nightscout.interfaces.stats.TddCalculator import info.nightscout.interfaces.ui.UiInteraction import info.nightscout.interfaces.utils.HardLimits import info.nightscout.plugins.aps.openAPSAMA.OpenAPSAMAPlugin @@ -41,6 +42,7 @@ class SafetyPluginTest : TestBaseWithProfile() { @Mock lateinit var glucoseStatusProvider: GlucoseStatusProvider @Mock lateinit var bgQualityCheck: BgQualityCheck @Mock lateinit var uiInteraction: UiInteraction + @Mock lateinit var tddCalculator: TddCalculator private lateinit var hardLimits: HardLimits private lateinit var safetyPlugin: SafetyPlugin @@ -84,7 +86,7 @@ class SafetyPluginTest : TestBaseWithProfile() { ) openAPSSMBPlugin = OpenAPSSMBPlugin( injector, aapsLogger, rxBus, constraintChecker, rh, profileFunction, context, activePlugin, iobCobCalculator, hardLimits, profiler, sp, - dateUtil, repository, glucoseStatusProvider, bgQualityCheck + dateUtil, repository, glucoseStatusProvider, bgQualityCheck, tddCalculator ) } diff --git a/core/interfaces/src/main/java/info/nightscout/interfaces/aps/DetermineBasalAdapter.kt b/core/interfaces/src/main/java/info/nightscout/interfaces/aps/DetermineBasalAdapter.kt index cc03ca3a3c..a4ee6afd34 100644 --- a/core/interfaces/src/main/java/info/nightscout/interfaces/aps/DetermineBasalAdapter.kt +++ b/core/interfaces/src/main/java/info/nightscout/interfaces/aps/DetermineBasalAdapter.kt @@ -30,7 +30,12 @@ interface DetermineBasalAdapter { microBolusAllowed: Boolean = false, uamAllowed: Boolean = false, advancedFiltering: Boolean = false, - flatBGsDetected: Boolean = false + flatBGsDetected: Boolean = false, + tdd1D: Double?, + tdd7D: Double?, + tddLast24H: Double?, + tddLast4H: Double?, + tddLast8to4H: Double? ) operator fun invoke(): APSResult? diff --git a/core/interfaces/src/main/java/info/nightscout/interfaces/constraints/Constraints.kt b/core/interfaces/src/main/java/info/nightscout/interfaces/constraints/Constraints.kt index 7d44743b92..97bf1c4f35 100644 --- a/core/interfaces/src/main/java/info/nightscout/interfaces/constraints/Constraints.kt +++ b/core/interfaces/src/main/java/info/nightscout/interfaces/constraints/Constraints.kt @@ -21,6 +21,7 @@ interface Constraints { fun isLgsAllowed(value: Constraint = Constraint(true)): Constraint = value fun isAutosensModeEnabled(value: Constraint = Constraint(true)): Constraint = value fun isSMBModeEnabled(value: Constraint = Constraint(true)): Constraint = value + fun isDynIsfModeEnabled(value: Constraint = Constraint(true)): Constraint = value fun isUAMEnabled(value: Constraint = Constraint(true)): Constraint = value fun isAdvancedFilteringEnabled(value: Constraint = Constraint(true)): Constraint = value fun isSuperBolusEnabled(value: Constraint = Constraint(true)): Constraint = value diff --git a/core/interfaces/src/main/java/info/nightscout/interfaces/constraints/Objectives.kt b/core/interfaces/src/main/java/info/nightscout/interfaces/constraints/Objectives.kt index 69a0aa9165..88c7d8f6f8 100644 --- a/core/interfaces/src/main/java/info/nightscout/interfaces/constraints/Objectives.kt +++ b/core/interfaces/src/main/java/info/nightscout/interfaces/constraints/Objectives.kt @@ -13,6 +13,7 @@ interface Objectives { const val AUTOSENS_OBJECTIVE = 7 const val SMB_OBJECTIVE = 8 const val AUTO_OBJECTIVE = 9 + const val DYN_ISF_OBJECTIVE = 10 } fun isAccomplished(index: Int): Boolean diff --git a/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.kt b/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.kt index e65441e276..99f56f187d 100644 --- a/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.kt +++ b/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.kt @@ -1,7 +1,6 @@ package info.nightscout.plugins.aps.openAPSAMA import dagger.android.HasAndroidInjector -import info.nightscout.plugins.aps.APSResultObject import info.nightscout.core.extensions.convertedToAbsolute import info.nightscout.core.extensions.getPassedDurationToTimeInMinutes import info.nightscout.core.extensions.plannedRemainingMinutes @@ -15,6 +14,7 @@ import info.nightscout.interfaces.iob.IobTotal import info.nightscout.interfaces.iob.MealData import info.nightscout.interfaces.profile.Profile import info.nightscout.interfaces.profile.ProfileFunction +import info.nightscout.plugins.aps.APSResultObject import info.nightscout.plugins.aps.R import info.nightscout.plugins.aps.logger.LoggerCallback import info.nightscout.plugins.aps.utils.ScriptReader @@ -162,7 +162,12 @@ class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader microBolusAllowed: Boolean, uamAllowed: Boolean, advancedFiltering: Boolean, - flatBGsDetected: Boolean + flatBGsDetected: Boolean, + tdd1D: Double?, + tdd7D: Double?, + tddLast24H: Double?, + tddLast4H: Double?, + tddLast8to4H: Double? ) { this.profile = JSONObject() this.profile.put("max_iob", maxIob) diff --git a/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.kt b/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.kt index 9e8ba9502c..34da305bb7 100644 --- a/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.kt +++ b/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.kt @@ -181,7 +181,12 @@ class OpenAPSAMAPlugin @Inject constructor( determineBasalAdapterAMAJS.setData( profile, maxIob, maxBasal, minBg, maxBg, targetBg, activePlugin.activePump.baseBasalRate, iobArray, glucoseStatus, mealData, lastAutosensResult.ratio, - isTempTarget + isTempTarget, + tdd1D = null, + tdd7D = null, + tddLast4H = null, + tddLast8to4H = null, + tddLast24H = null, ) } catch (e: JSONException) { fabricPrivacy.logException(e) diff --git a/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.kt b/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.kt index c882fc9e8f..89c7e6f9ba 100644 --- a/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.kt +++ b/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.kt @@ -1,7 +1,6 @@ package info.nightscout.plugins.aps.openAPSSMB import dagger.android.HasAndroidInjector -import info.nightscout.plugins.aps.APSResultObject import info.nightscout.core.extensions.convertedToAbsolute import info.nightscout.core.extensions.getPassedDurationToTimeInMinutes import info.nightscout.core.extensions.plannedRemainingMinutes @@ -16,6 +15,7 @@ import info.nightscout.interfaces.iob.MealData import info.nightscout.interfaces.plugin.ActivePlugin import info.nightscout.interfaces.profile.Profile import info.nightscout.interfaces.profile.ProfileFunction +import info.nightscout.plugins.aps.APSResultObject import info.nightscout.plugins.aps.R import info.nightscout.plugins.aps.logger.LoggerCallback import info.nightscout.plugins.aps.utils.ScriptReader @@ -174,7 +174,12 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader: microBolusAllowed: Boolean, uamAllowed: Boolean, advancedFiltering: Boolean, - flatBGsDetected: Boolean + flatBGsDetected: Boolean, + tdd1D: Double?, + tdd7D: Double?, + tddLast24H: Double?, + tddLast4H: Double?, + tddLast8to4H: Double? ) { val pump = activePlugin.activePump val pumpBolusStep = pump.pumpDescription.bolusStep diff --git a/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.kt b/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.kt index 5364a88101..7019ef8e7a 100644 --- a/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.kt +++ b/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.kt @@ -25,6 +25,7 @@ import info.nightscout.interfaces.plugin.PluginType import info.nightscout.interfaces.profile.Profile import info.nightscout.interfaces.profile.ProfileFunction import info.nightscout.interfaces.profiling.Profiler +import info.nightscout.interfaces.stats.TddCalculator import info.nightscout.interfaces.utils.HardLimits import info.nightscout.interfaces.utils.Round import info.nightscout.plugins.aps.R @@ -57,7 +58,8 @@ class OpenAPSSMBPlugin @Inject constructor( private val dateUtil: DateUtil, private val repository: AppRepository, private val glucoseStatusProvider: GlucoseStatusProvider, - private val bgQualityCheck: BgQualityCheck + private val bgQualityCheck: BgQualityCheck, + private val tddCalculator: TddCalculator ) : PluginBase( PluginDescription() .mainType(PluginType.APS) @@ -71,6 +73,14 @@ class OpenAPSSMBPlugin @Inject constructor( aapsLogger, rh, injector ), APS, Constraints { + // DynamicISF specific + var tdd1D : Double? = null + var tdd7D : Double? = null + var tddLast24H : Double? = null + var tddLast4H : Double? = null + var tddLast8to4H : Double? = null + var dynIsfEnabled : Constraint = Constraint(false) + // last values override var lastAPSRun: Long = 0 override var lastAPSResult: DetermineBasalResultSMB? = null @@ -193,11 +203,24 @@ class OpenAPSSMBPlugin @Inject constructor( constraintChecker.isUAMEnabled(it) inputConstraints.copyReasons(it) } + dynIsfEnabled = Constraint(true).also { + constraintChecker.isDynIsfModeEnabled(it) + inputConstraints.copyReasons(it) + } val flatBGsDetected = bgQualityCheck.state == BgQualityCheck.State.FLAT profiler.log(LTag.APS, "detectSensitivityAndCarbAbsorption()", startPart) profiler.log(LTag.APS, "SMB data gathering", start) start = System.currentTimeMillis() + // DynamicISF specific + // without these values DynISF doesn't work properly + // Current implementation is fallback to SMB if TDD history is not available. Thus calculated here + tdd1D = tddCalculator.averageTDD(tddCalculator.calculate(1, allowMissingDays = false))?.totalAmount + tdd7D = tddCalculator.averageTDD(tddCalculator.calculate(7, allowMissingDays = false))?.totalAmount + tddLast24H = tddCalculator.calculateDaily(-24, 0)?.totalAmount + tddLast4H = tddCalculator.calculateDaily(-4, 0)?.totalAmount + tddLast8to4H = tddCalculator.calculateDaily(-8, -4)?.totalAmount + provideDetermineBasalAdapter().also { determineBasalAdapterSMBJS -> determineBasalAdapterSMBJS.setData( profile, maxIob, maxBasal, minBg, maxBg, targetBg, @@ -210,7 +233,12 @@ class OpenAPSSMBPlugin @Inject constructor( smbAllowed.value(), uam.value(), advancedFiltering.value(), - flatBGsDetected + flatBGsDetected, + tdd1D = tdd1D, + tdd7D = tdd7D, + tddLast24H = tddLast24H, + tddLast4H = tddLast4H, + tddLast8to4H = tddLast8to4H ) val now = System.currentTimeMillis() val determineBasalResultSMB = determineBasalAdapterSMBJS.invoke() @@ -243,7 +271,7 @@ class OpenAPSSMBPlugin @Inject constructor( override fun applyMaxIOBConstraints(maxIob: Constraint): Constraint { if (isEnabled()) { - val maxIobPref: Double = sp.getDouble(info.nightscout.plugins.aps.R.string.key_openapssmb_max_iob, 3.0) + val maxIobPref: Double = sp.getDouble(R.string.key_openapssmb_max_iob, 3.0) maxIob.setIfSmaller(aapsLogger, maxIobPref, rh.gs(R.string.limiting_iob, maxIobPref, rh.gs(R.string.maxvalueinpreferences)), this) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobSMB(), rh.gs(R.string.limiting_iob, hardLimits.maxIobSMB(), rh.gs(R.string.hardlimit)), this) } diff --git a/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSSMBDynamicISF/DetermineBasalAdapterSMBDynamicISFJS.kt b/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSSMBDynamicISF/DetermineBasalAdapterSMBDynamicISFJS.kt index c5e19f0061..cd0c861339 100644 --- a/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSSMBDynamicISF/DetermineBasalAdapterSMBDynamicISFJS.kt +++ b/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSSMBDynamicISF/DetermineBasalAdapterSMBDynamicISFJS.kt @@ -14,7 +14,6 @@ import info.nightscout.interfaces.iob.MealData import info.nightscout.interfaces.plugin.ActivePlugin import info.nightscout.interfaces.profile.Profile import info.nightscout.interfaces.profile.ProfileFunction -import info.nightscout.interfaces.stats.TddCalculator import info.nightscout.interfaces.utils.Round import info.nightscout.plugins.aps.R import info.nightscout.plugins.aps.logger.LoggerCallback @@ -38,6 +37,7 @@ import org.mozilla.javascript.Undefined import java.io.IOException import java.lang.reflect.InvocationTargetException import java.nio.charset.StandardCharsets +import java.security.InvalidParameterException import javax.inject.Inject import kotlin.math.ln @@ -48,7 +48,6 @@ class DetermineBasalAdapterSMBDynamicISFJS internal constructor(private val scri @Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var iobCobCalculator: IobCobCalculator @Inject lateinit var activePlugin: ActivePlugin - @Inject lateinit var tddCalculator: TddCalculator private var profile = JSONObject() private var mGlucoseStatus = JSONObject() @@ -176,8 +175,19 @@ class DetermineBasalAdapterSMBDynamicISFJS internal constructor(private val scri microBolusAllowed: Boolean, uamAllowed: Boolean, advancedFiltering: Boolean, - flatBGsDetected: Boolean + flatBGsDetected: Boolean, + tdd1D: Double?, + tdd7D: Double?, + tddLast24H: Double?, + tddLast4H: Double?, + tddLast8to4H: Double? ) { + tdd1D ?: throw InvalidParameterException() + tdd7D ?: throw InvalidParameterException() + tddLast24H ?: throw InvalidParameterException() + tddLast4H ?: throw InvalidParameterException() + tddLast8to4H ?: throw InvalidParameterException() + val pump = activePlugin.activePump val pumpBolusStep = pump.pumpDescription.bolusStep this.profile.put("max_iob", maxIob) @@ -262,12 +272,6 @@ class DetermineBasalAdapterSMBDynamicISFJS internal constructor(private val scri this.mealData.put("lastBolusTime", mealData.lastBolusTime) this.mealData.put("lastCarbTime", mealData.lastCarbTime) - val tdd1D = tddCalculator.averageTDD(tddCalculator.calculate(1, allowMissingDays = false))?.totalAmount - val tdd7D = tddCalculator.averageTDD(tddCalculator.calculate(7, allowMissingDays = false))?.totalAmount - val tddLast24H = tddCalculator.calculateDaily(-24, 0)?.totalAmount - val tddLast4H = tddCalculator.calculateDaily(-4, 0)?.totalAmount - val tddLast8to4H = tddCalculator.calculateDaily(-8, -4)?.totalAmount - val insulin = activePlugin.activeInsulin val insulinDivisor = when { insulin.peak > 65 -> 55 // lyumjev peak: 45 @@ -275,34 +279,19 @@ class DetermineBasalAdapterSMBDynamicISFJS internal constructor(private val scri else -> 75 // rapid peak: 75 } - var tdd: Double? = null - var variableSensitivity: Double - if (tddLast24H != null && tddLast4H != null && tddLast8to4H != null) { - val tddWeightedFromLast8H = ((1.4 * tddLast4H) + (0.6 * tddLast8to4H)) * 3 -// console.error("Rolling 8 hours weight average: " + tdd_last8_wt + "; "); -// console.error("1-day average TDD is: " + tdd1 + "; "); -// console.error("7-day average TDD is: " + tdd7 + "; "); + val tddWeightedFromLast8H = ((1.4 * tddLast4H) + (0.6 * tddLast8to4H)) * 3 + var tdd = (tddWeightedFromLast8H * 0.33) + (tdd7D * 0.34) + (tdd1D * 0.33) + val dynISFadjust = SafeParse.stringToDouble(sp.getString(R.string.key_DynISFAdjust, "100")) / 100.0 + tdd *= dynISFadjust - tdd = - if (tdd1D != null && tdd7D != null) (tddWeightedFromLast8H * 0.33) + (tdd7D * 0.34) + (tdd1D * 0.33) - else tddWeightedFromLast8H -// console.log("TDD = " + TDD + " using average of 7-day, 1-day and weighted 8hr average"); - - val dynISFadjust = SafeParse.stringToDouble(sp.getString(R.string.key_DynISFAdjust, "100")) / 100.0 - tdd *= dynISFadjust - - variableSensitivity = 1800 / (tdd * (ln((glucoseStatus.glucose / insulinDivisor) + 1))) - variableSensitivity = Round.roundTo(variableSensitivity, 0.1) - } else { - variableSensitivity = profile.getIsfMgdl() - } + val variableSensitivity = Round.roundTo(1800 / (tdd * (ln((glucoseStatus.glucose / insulinDivisor) + 1))), 0.1) this.profile.put("variable_sens", variableSensitivity) this.profile.put("insulinDivisor", insulinDivisor) - tdd?.let { this.profile.put("TDD", tdd) } + this.profile.put("TDD", tdd) - if (sp.getBoolean(R.string.key_adjust_sensitivity, false) && tdd7D != null && tddLast24H != null) + if (sp.getBoolean(R.string.key_adjust_sensitivity, false)) autosensData.put("ratio", tddLast24H / tdd7D) else autosensData.put("ratio", 1.0) diff --git a/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSSMBDynamicISF/OpenAPSSMBDynamicISFPlugin.kt b/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSSMBDynamicISF/OpenAPSSMBDynamicISFPlugin.kt index bc004da0ff..750d9a46d7 100644 --- a/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSSMBDynamicISF/OpenAPSSMBDynamicISFPlugin.kt +++ b/plugins/aps/src/main/java/info/nightscout/plugins/aps/openAPSSMBDynamicISF/OpenAPSSMBDynamicISFPlugin.kt @@ -4,7 +4,6 @@ import android.content.Context import dagger.android.HasAndroidInjector import info.nightscout.androidaps.annotations.OpenForTesting import info.nightscout.database.impl.AppRepository -import info.nightscout.interfaces.Config import info.nightscout.interfaces.aps.DetermineBasalAdapter import info.nightscout.interfaces.bgQualityCheck.BgQualityCheck import info.nightscout.interfaces.constraints.Constraints @@ -13,8 +12,10 @@ import info.nightscout.interfaces.iob.IobCobCalculator import info.nightscout.interfaces.plugin.ActivePlugin import info.nightscout.interfaces.profile.ProfileFunction import info.nightscout.interfaces.profiling.Profiler +import info.nightscout.interfaces.stats.TddCalculator import info.nightscout.interfaces.utils.HardLimits import info.nightscout.plugins.aps.R +import info.nightscout.plugins.aps.openAPSSMB.DetermineBasalAdapterSMBJS import info.nightscout.plugins.aps.openAPSSMB.OpenAPSSMBPlugin import info.nightscout.plugins.aps.utils.ScriptReader import info.nightscout.rx.bus.RxBus @@ -43,8 +44,8 @@ class OpenAPSSMBDynamicISFPlugin @Inject constructor( dateUtil: DateUtil, repository: AppRepository, glucoseStatusProvider: GlucoseStatusProvider, - private val config: Config, - private val bgQualityCheck: BgQualityCheck + bgQualityCheck: BgQualityCheck, + tddCalculator: TddCalculator ) : OpenAPSSMBPlugin( injector, aapsLogger, @@ -61,7 +62,8 @@ class OpenAPSSMBDynamicISFPlugin @Inject constructor( dateUtil, repository, glucoseStatusProvider, - bgQualityCheck + bgQualityCheck, + tddCalculator ) { init { @@ -71,10 +73,11 @@ class OpenAPSSMBDynamicISFPlugin @Inject constructor( .shortName(R.string.dynisf_shortname) .preferencesId(R.xml.pref_openapssmbdynamicisf) .setDefault(false) - .showInList(config.isEngineeringMode() && config.isDev()) } - override fun specialEnableCondition(): Boolean = config.isEngineeringMode() && config.isDev() - - override fun provideDetermineBasalAdapter(): DetermineBasalAdapter = DetermineBasalAdapterSMBDynamicISFJS(ScriptReader(context), injector) + // If there is no TDD data fallback to SMB as ISF calculation may be really off + override fun provideDetermineBasalAdapter(): DetermineBasalAdapter = + if (tdd1D == null || tdd7D == null || tddLast4H == null || tddLast8to4H == null || tddLast24H == null || !dynIsfEnabled.value()) + DetermineBasalAdapterSMBJS(ScriptReader(context), injector) + else DetermineBasalAdapterSMBDynamicISFJS(ScriptReader(context), injector) } \ No newline at end of file diff --git a/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/ConstraintsImpl.kt b/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/ConstraintsImpl.kt index 923619063e..990e860a28 100644 --- a/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/ConstraintsImpl.kt +++ b/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/ConstraintsImpl.kt @@ -60,6 +60,16 @@ class ConstraintsImpl @Inject constructor(private val activePlugin: ActivePlugin return value } + override fun isDynIsfModeEnabled(value: Constraint): Constraint { + val constraintsPlugins = activePlugin.getSpecificPluginsListByInterface(Constraints::class.java) + for (p in constraintsPlugins) { + val constraint = p as Constraints + if (!p.isEnabled()) continue + constraint.isDynIsfModeEnabled(value) + } + return value + } + override fun isUAMEnabled(value: Constraint): Constraint { val constraintsPlugins = activePlugin.getSpecificPluginsListByInterface(Constraints::class.java) for (p in constraintsPlugins) { diff --git a/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/di/ObjectivesModule.kt b/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/di/ObjectivesModule.kt index 086ea46a7c..898f8a5151 100644 --- a/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/di/ObjectivesModule.kt +++ b/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/di/ObjectivesModule.kt @@ -9,6 +9,7 @@ import info.nightscout.plugins.constraints.objectives.objectives.Objective import info.nightscout.plugins.constraints.objectives.objectives.Objective0 import info.nightscout.plugins.constraints.objectives.objectives.Objective1 import info.nightscout.plugins.constraints.objectives.objectives.Objective10 +import info.nightscout.plugins.constraints.objectives.objectives.Objective11 import info.nightscout.plugins.constraints.objectives.objectives.Objective2 import info.nightscout.plugins.constraints.objectives.objectives.Objective3 import info.nightscout.plugins.constraints.objectives.objectives.Objective4 @@ -36,4 +37,5 @@ abstract class ObjectivesModule { @ContributesAndroidInjector abstract fun objective7Injector(): Objective7 @ContributesAndroidInjector abstract fun objective9Injector(): Objective9 @ContributesAndroidInjector abstract fun objective10Injector(): Objective10 + @ContributesAndroidInjector abstract fun objective11Injector(): Objective11 } \ No newline at end of file diff --git a/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/objectives/ObjectivesPlugin.kt b/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/objectives/ObjectivesPlugin.kt index 5495d609a6..d1aa0a557c 100644 --- a/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/objectives/ObjectivesPlugin.kt +++ b/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/objectives/ObjectivesPlugin.kt @@ -7,6 +7,7 @@ import info.nightscout.interfaces.constraints.Constraints import info.nightscout.interfaces.constraints.Objectives import info.nightscout.interfaces.constraints.Objectives.Companion.AUTOSENS_OBJECTIVE import info.nightscout.interfaces.constraints.Objectives.Companion.AUTO_OBJECTIVE +import info.nightscout.interfaces.constraints.Objectives.Companion.DYN_ISF_OBJECTIVE import info.nightscout.interfaces.constraints.Objectives.Companion.FIRST_OBJECTIVE import info.nightscout.interfaces.constraints.Objectives.Companion.MAXBASAL_OBJECTIVE import info.nightscout.interfaces.constraints.Objectives.Companion.MAXIOB_ZERO_CL_OBJECTIVE @@ -20,6 +21,7 @@ import info.nightscout.plugins.constraints.objectives.objectives.Objective import info.nightscout.plugins.constraints.objectives.objectives.Objective0 import info.nightscout.plugins.constraints.objectives.objectives.Objective1 import info.nightscout.plugins.constraints.objectives.objectives.Objective10 +import info.nightscout.plugins.constraints.objectives.objectives.Objective11 import info.nightscout.plugins.constraints.objectives.objectives.Objective2 import info.nightscout.plugins.constraints.objectives.objectives.Objective3 import info.nightscout.plugins.constraints.objectives.objectives.Objective4 @@ -76,6 +78,7 @@ class ObjectivesPlugin @Inject constructor( objectives.add(Objective7(injector)) objectives.add(Objective9(injector)) objectives.add(Objective10(injector)) + objectives.add(Objective11(injector)) // edit companion object if you remove/add Objective } @@ -137,6 +140,12 @@ class ObjectivesPlugin @Inject constructor( return value } + override fun isDynIsfModeEnabled(value: Constraint): Constraint { + if (!objectives[DYN_ISF_OBJECTIVE].isStarted) + value.set(aapsLogger, false, rh.gs(R.string.objectivenotstarted, DYN_ISF_OBJECTIVE + 1), this) + return value + } + override fun applyMaxIOBConstraints(maxIob: Constraint): Constraint { if (objectives[MAXIOB_ZERO_CL_OBJECTIVE].isStarted && !objectives[MAXIOB_ZERO_CL_OBJECTIVE].isAccomplished) maxIob.set(aapsLogger, 0.0, rh.gs(R.string.objectivenotfinished, MAXIOB_ZERO_CL_OBJECTIVE + 1), this) diff --git a/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/objectives/objectives/Objective.kt b/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/objectives/objectives/Objective.kt index 7389d92e77..f87d5e86ec 100644 --- a/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/objectives/objectives/Objective.kt +++ b/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/objectives/objectives/Objective.kt @@ -46,6 +46,7 @@ abstract class Objective(injector: HasAndroidInjector, spName: String, @StringRe } init { + @Suppress("LeakingThis") injector.androidInjector().inject(this) this.spName = spName this.objective = objective @@ -70,10 +71,10 @@ abstract class Objective(injector: HasAndroidInjector, spName: String, @StringRe val isStarted: Boolean get() = startedOn != 0L - open fun specialActionEnabled(): Boolean { - return true - } + @Suppress("unused") + open fun specialActionEnabled(): Boolean = true + @Suppress("unused") open fun specialAction(activity: FragmentActivity, input: String) {} abstract inner class Task(var objective: Objective, @StringRes val task: Int) { @@ -157,7 +158,7 @@ abstract class Objective(injector: HasAndroidInjector, spName: String, @StringRe inner class Option internal constructor(@StringRes var option: Int, var isCorrect: Boolean) { - var cb: CheckBox? = null // TODO: change it, this will block releasing memory + private var cb: CheckBox? = null // TODO: change it, this will block releasing memory fun generate(context: Context): CheckBox { cb = CheckBox(context) @@ -184,13 +185,5 @@ abstract class Objective(injector: HasAndroidInjector, spName: String, @StringRe } } - inner class Learned internal constructor(@StringRes var learned: Int) { - - fun generate(context: Context): TextView { - val textView = TextView(context) - textView.setText(learned) - textView.setLinkTextColor(rh.gac(context, com.google.android.material.R.attr.colorSecondary)) - return textView - } - } + inner class Learned internal constructor(@StringRes var learned: Int) } \ No newline at end of file diff --git a/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/objectives/objectives/Objective11.kt b/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/objectives/objectives/Objective11.kt new file mode 100644 index 0000000000..febdc830f2 --- /dev/null +++ b/plugins/constraints/src/main/java/info/nightscout/plugins/constraints/objectives/objectives/Objective11.kt @@ -0,0 +1,15 @@ +package info.nightscout.plugins.constraints.objectives.objectives + +import dagger.android.HasAndroidInjector +import info.nightscout.plugins.constraints.R +import info.nightscout.shared.utils.T + +class Objective11(injector: HasAndroidInjector) : Objective(injector, "dyn_isf", R.string.objectives_dyn_isf_objective, R.string.objectives_dyn_isf_gate) { + + init { + tasks.add( + MinimumDurationTask(this, T.days(28).msecs()) + .learned(Learned(R.string.objectives_dyn_isf_learned)) + ) + } +} \ No newline at end of file diff --git a/plugins/constraints/src/main/res/values/objectives.xml b/plugins/constraints/src/main/res/values/objectives.xml index c2913b368e..62b3030568 100644 --- a/plugins/constraints/src/main/res/values/objectives.xml +++ b/plugins/constraints/src/main/res/values/objectives.xml @@ -28,6 +28,9 @@ Enabling additional features for daytime use, such as SMB You must read the wiki and raise maxIOB to get SMBs working fine! A good start is maxIOB=average mealbolus + 3 x max daily basal Using SMB is your goal. Oref1 algorithm was designed to help you with your boluses as well. You should not give full bolus for your food but only part of it and let AAPS give you the rest if needed. This way you have more space for miscalculated carbs. Did you know that you can set a percentage of bolus calculator result to reduce the size of bolus? + Enabling additional features for daytime use, such as Dynamic sensitivity plugin + Make sure SMB is working well. Enable DynamicISF plugin and determine correct strangeness specific to your body. It\'s safer to start with lower value than 100%. + Dynamic sensitivity plugin is based on idea that total insulin income and current glycemia affects actual sensitivity. DynamicISF plugin can adjust ISF passed to the algorithm for you. Enabling automation Read the docs on how automation works. Set up your first simple rules. Instead of action let AAPS display only notification. When you are sure automation is triggered at the right time replace notification by real action. (https://wiki.aaps.app/en/latest/Usage/Automation.html) Automation can be a good servant but a bad master. Don\'t overuse it. Do not try to replace underlying algorithm. Test the rule with message only before use. It depends on order.