AutoISF -> separate plugin

This commit is contained in:
Milos Kozak 2022-02-16 00:03:21 +01:00
parent e32515a369
commit 8a19267a39
17 changed files with 1809 additions and 218 deletions

View file

@ -277,56 +277,16 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
var profile_sens = round(profile.sens,1)
var sens = profile.sens;
var now = new Date().getHours();
if (now < 1){
now = 1;}
else {
console.error("Time now is "+now+"; ");
}
if (meal_data.TDDAIMI7){
var tdd7 = meal_data.TDDAIMI7;
}
else{
var tdd7 = ((basal * 12)*100)/21;
}
var tdd_pump_now = meal_data.TDDPUMP;
var tdd_pump = ( tdd_pump_now / (now / 24));
var TDD = (tdd7 * 0.4) + (tdd_pump * 0.6);
console.error("Pump extrapolated TDD = "+tdd_pump+"; ");
//if (tdd7 > 0){
if ( tdd_pump > tdd7 && now < 5 || now < 7 && TDD < ( 0.8 * tdd7 ) ){
TDD = ( 0.8 * tdd7 );
console.log("Excess or too low insulin from pump so TDD set to "+TDD+" based on 75% of TDD7; ");
rT.reason += "TDD: " +TDD+ " due to low or high tdd from pump; ";
}
else if (tdd_pump < (0.33 * tdd7)){
TDD = (tdd7 * 0.25) + (tdd_pump * 0.75);
console.error("TDD weighted to pump due to low insulin usage. TDD = "+TDD+"; ");
rT.reason += "TDD weighted to pump due to low insulin usage. TDD = "+TDD+"; ";
}
else {
console.log("TDD 7 ="+tdd7+", TDD Pump ="+tdd_pump+" and TDD = "+TDD+";");
rT.reason += "TDD: " +TDD+ " based on standard pump 60/tdd7 40 split; ";
}
var variable_sens = (277700 / (TDD * bg));
variable_sens = round(variable_sens,1);
console.log("Current sensitivity for predictions is " +variable_sens+" based on current bg");
sens = variable_sens;
if ( high_temptarget_raises_sensitivity && profile.temptargetSet && target_bg > normalTarget || profile.low_temptarget_lowers_sensitivity && profile.temptargetSet && target_bg < normalTarget ) {
sens = sens / sensitivityRatio ;
sens = round(sens, 1);
console.log("ISF from "+variable_sens+" to "+sens+ "due to temp target; ");
} else {
sens = sens;
if (typeof autosens_data !== 'undefined' && autosens_data) {
sens = profile.sens / sensitivityRatio;
sens = round(sens, 1);
if (sens !== profile_sens) {
console.log("ISF from "+profile_sens+" to "+sens);
} else {
console.log("ISF unchanged: "+sens);
}
//console.log(" (autosens ratio "+sensitivityRatio+")");
}
console.error("; CR:",profile.carb_ratio);
// compare currenttemp to iob_data.lastTemp and cancel temp if they don't match
@ -740,20 +700,6 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
console.error("UAM Impact:",uci,"mg/dL per 5m; UAM Duration:",UAMduration,"hours");
console.log("EventualBG is" +eventualBG+" ;");
if( glucose_status.delta >= 0 || bg > 60 && glucose_status.delta < 2 && glucose_status.delta > -2 && glucose_status.short_avgdelta > -2 && glucose_status.short_avgdelta < 2 || eventualBG > target_bg && glucose_status.delta < 0 ) {
var future_sens = ( 277700 / (TDD * bg) );
console.log("Future state sensitivity is " +future_sens+" using current bg due to no COB & small delta or variation");
rT.reason += "Dosing sensitivity: " +future_sens+" using current BG;";
}
else {
var future_sens = ( 277700 / (TDD * eventualBG));
console.log("Future state sensitivity is " +future_sens+" based on eventual bg due to -ve delta");
rT.reason += "Dosing sensitivity: " +future_sens+" using eventual BG;";
}
var future_sens = round(future_sens,1);
minIOBPredBG = Math.max(39,minIOBPredBG);
minCOBPredBG = Math.max(39,minCOBPredBG);
@ -974,33 +920,30 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
rT.reason += ", but Min. Delta " + minDelta.toFixed(2) + " > Exp. Delta " + convert_bg(expectedDelta, profile);
}
if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
rT.reason += ", temp " + currenttemp.rate + " ~ req " + round(basal, 2) + "U/hr. ";
rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr. ";
return rT;
} else {
rT.reason += "; setting current basal of " + round(basal, 2) + " as temp. ";
rT.reason += "; setting current basal of " + basal + " as temp. ";
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
}
}
// calculate 30m low-temp required to get projected BG up to target
// multiply by 2 to low-temp faster for increased hypo safety
var insulinReq = 2 * Math.min(0, (eventualBG - target_bg) / future_sens);
insulinReq = round( insulinReq , 2);
// calculate naiveInsulinReq based on naive_eventualBG
var naiveInsulinReq = Math.min(0, (naive_eventualBG - target_bg) / sens);
naiveInsulinReq = round( naiveInsulinReq , 2);
if (minDelta < 0 && minDelta > expectedDelta) {
// if we're barely falling, newinsulinReq should be barely negative
var newinsulinReq = round(( insulinReq * (minDelta / expectedDelta) ), 2);
//console.error("Increasing insulinReq from " + insulinReq + " to " + newinsulinReq);
insulinReq = newinsulinReq;
}
// rate required to deliver insulinReq less insulin over 30m:
var rate = basal + (2 * insulinReq);
rate = round_basal(rate, profile);
// calculate 30m low-temp required to get projected BG up to target
// multiply by 2 to low-temp faster for increased hypo safety
var insulinReq = 2 * Math.min(0, (eventualBG - target_bg) / sens);
insulinReq = round( insulinReq , 2);
// calculate naiveInsulinReq based on naive_eventualBG
var naiveInsulinReq = Math.min(0, (naive_eventualBG - target_bg) / sens);
naiveInsulinReq = round( naiveInsulinReq , 2);
if (minDelta < 0 && minDelta > expectedDelta) {
// if we're barely falling, newinsulinReq should be barely negative
var newinsulinReq = round(( insulinReq * (minDelta / expectedDelta) ), 2);
//console.error("Increasing insulinReq from " + insulinReq + " to " + newinsulinReq);
insulinReq = newinsulinReq;
}
// rate required to deliver insulinReq less insulin over 30m:
var rate = basal + (2 * insulinReq);
rate = round_basal(rate, profile);
// if required temp < existing temp basal
var insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60;
@ -1049,10 +992,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " > " + convert_bg(min_bg, profile) + " but Min. Delta " + minDelta.toFixed(2) + " < Exp. Delta " + convert_bg(expectedDelta, profile);
}
if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
rT.reason += ", temp " + currenttemp.rate + " ~ req " + round(basal, 2) + "U/hr. ";
rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr. ";
return rT;
} else {
rT.reason += "; setting current basal of " + round(basal, 2) + " as temp. ";
rT.reason += "; setting current basal of " + basal + " as temp. ";
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
}
}
@ -1063,10 +1006,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
if (! (microBolusAllowed && enableSMB )) {
rT.reason += convert_bg(eventualBG, profile)+"-"+convert_bg(minPredBG, profile)+" in range: no temp required";
if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
rT.reason += ", temp " + currenttemp.rate + " ~ req " + round(basal, 2) + "U/hr. ";
rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr. ";
return rT;
} else {
rT.reason += "; setting current basal of " + round(basal, 2) + " as temp. ";
rT.reason += "; setting current basal of " + basal + " as temp. ";
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
}
}
@ -1080,22 +1023,22 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
if (iob_data.iob > max_iob) {
rT.reason += "IOB " + round(iob_data.iob,2) + " > max_iob " + max_iob;
if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
rT.reason += ", temp " + currenttemp.rate + " ~ req " + round(basal, 2) + "U/hr. ";
rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr. ";
return rT;
} else {
rT.reason += "; setting current basal of " + round(basal, 2) + " as temp. ";
rT.reason += "; setting current basal of " + basal + " as temp. ";
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
}
} else { // otherwise, calculate 30m high-temp required to get projected BG down to target
// insulinReq is the additional insulin required to get minPredBG down to target_bg
//console.error(minPredBG,eventualBG);
insulinReq = round( (Math.min(minPredBG,eventualBG) - target_bg) / future_sens, 2);
// if that would put us over max_iob, then reduce accordingly
if (insulinReq > max_iob-iob_data.iob) {
rT.reason += "max_iob " + max_iob + ", ";
insulinReq = max_iob-iob_data.iob;
}
// insulinReq is the additional insulin required to get minPredBG down to target_bg
//console.error(minPredBG,eventualBG);
insulinReq = round( (Math.min(minPredBG,eventualBG) - target_bg) / sens, 2);
// if that would put us over max_iob, then reduce accordingly
if (insulinReq > max_iob-iob_data.iob) {
rT.reason += "max_iob " + max_iob + ", ";
insulinReq = max_iob-iob_data.iob;
}
// rate required to deliver insulinReq more insulin over 30m:
rate = basal + (2 * insulinReq);

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,7 @@ import info.nightscout.androidaps.plugins.aps.openAPSAMA.DetermineBasalAdapterAM
import info.nightscout.androidaps.plugins.aps.openAPSAMA.DetermineBasalResultAMA
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalAdapterSMBJS
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
import info.nightscout.androidaps.plugins.aps.openAPSSMBAutoISF.DetermineBasalAdapterSMBAutoISFJS
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOref1Thread
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobThread
@ -19,6 +20,7 @@ abstract class APSModule {
@ContributesAndroidInjector abstract fun determineBasalResultAMAInjector(): DetermineBasalResultAMA
@ContributesAndroidInjector abstract fun determineBasalAdapterAMAJSInjector(): DetermineBasalAdapterAMAJS
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBJSInjector(): DetermineBasalAdapterSMBJS
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBAutoISFJSInjector(): DetermineBasalAdapterSMBAutoISFJS
@ContributesAndroidInjector abstract fun iobCobThreadInjector(): IobCobThread
@ContributesAndroidInjector abstract fun iobCobOref1ThreadInjector(): IobCobOref1Thread
}

View file

@ -14,6 +14,7 @@ import info.nightscout.androidaps.plugin.general.openhumans.OpenHumansUploader
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
import info.nightscout.androidaps.plugins.aps.openAPSSMBAutoISF.OpenAPSSMBAutoISFPlugin
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.constraints.bgQualityCheck.BgQualityCheckPlugin
import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin
@ -212,6 +213,12 @@ abstract class PluginsModule {
@IntKey(220)
abstract fun bindOpenAPSSMBPlugin(plugin: OpenAPSSMBPlugin): PluginBase
@Binds
@APS
@IntoMap
@IntKey(222)
abstract fun bindOpenAPSSMBAutoISFPlugin(plugin: OpenAPSSMBAutoISFPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap

View file

@ -7,6 +7,7 @@ import info.nightscout.androidaps.data.MealData
import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
import info.nightscout.androidaps.interfaces.DetermineBasalAdapterInterface
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.Profile
@ -14,6 +15,7 @@ import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback
import info.nightscout.androidaps.plugins.aps.loop.APSResult
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
@ -30,7 +32,7 @@ import java.nio.charset.StandardCharsets
import javax.inject.Inject
import kotlin.math.min
class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader, injector: HasAndroidInjector) {
class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader, injector: HasAndroidInjector) : DetermineBasalAdapterInterface {
private val injector: HasAndroidInjector
@ -48,21 +50,15 @@ class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader
private var currentTemp = JSONObject()
private var autosensData = JSONObject()
var currentTempParam: String? = null
private set
var iobDataParam: String? = null
private set
var glucoseStatusParam: String? = null
private set
var profileParam: String? = null
private set
var mealDataParam: String? = null
private set
var scriptDebug = ""
private set
override var currentTempParam: String? = null
override var iobDataParam: String? = null
override var glucoseStatusParam: String? = null
override var profileParam: String? = null
override var mealDataParam: String? = null
override var scriptDebug = ""
@Suppress("SpellCheckingInspection")
operator fun invoke(): DetermineBasalResultAMA? {
override operator fun invoke(): APSResult? {
aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<")
aapsLogger.debug(LTag.APS, "Glucose status: " + glucoseStatus.toString().also { glucoseStatusParam = it })
aapsLogger.debug(LTag.APS, "IOB data: " + iobData.toString().also { iobDataParam = it })
@ -143,18 +139,25 @@ class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader
}
@Suppress("SpellCheckingInspection")
@Throws(JSONException::class) fun setData(profile: Profile,
maxIob: Double,
maxBasal: Double,
minBg: Double,
maxBg: Double,
targetBg: Double,
basalRate: Double,
iobArray: Array<IobTotal>,
glucoseStatus: GlucoseStatus,
mealData: MealData,
autosensDataRatio: Double,
tempTargetSet: Boolean) {
@Throws(JSONException::class)
override fun setData(
profile: Profile,
maxIob: Double,
maxBasal: Double,
minBg: Double,
maxBg: Double,
targetBg: Double,
basalRate: Double,
iobArray: Array<IobTotal>,
glucoseStatus: GlucoseStatus,
mealData: MealData,
autosensDataRatio: Double,
tempTargetSet: Boolean,
microBolusAllowed: Boolean,
uamAllowed: Boolean,
advancedFiltering: Boolean,
isSaveCgmSource: Boolean
) {
this.profile = JSONObject()
this.profile.put("max_iob", maxIob)
this.profile.put("dia", min(profile.dia, 3.0))

View file

@ -96,7 +96,7 @@ class OpenAPSAMAFragment : DaggerFragment() {
binding.result.text = jsonFormatter.format(lastAPSResult.json)
binding.request.text = lastAPSResult.toSpanned()
}
openAPSAMAPlugin.lastDetermineBasalAdapterAMAJS?.let { determineBasalAdapterAMAJS ->
openAPSAMAPlugin.lastDetermineBasalAdapter?.let { determineBasalAdapterAMAJS ->
binding.glucosestatus.text = jsonFormatter.format(determineBasalAdapterAMAJS.glucoseStatusParam)
binding.currenttemp.text = jsonFormatter.format(determineBasalAdapterAMAJS.currentTempParam)
try {

View file

@ -60,8 +60,8 @@ class OpenAPSAMAPlugin @Inject constructor(
// last values
override var lastAPSRun: Long = 0
override var lastAPSResult: DetermineBasalResultAMA? = null
var lastDetermineBasalAdapterAMAJS: DetermineBasalAdapterAMAJS? = null
var lastAutosensResult: AutosensResult = AutosensResult()
override var lastDetermineBasalAdapter: DetermineBasalAdapterInterface? = null
override var lastAutosensResult: AutosensResult = AutosensResult()
override fun specialEnableCondition(): Boolean {
return try {
@ -158,7 +158,7 @@ class OpenAPSAMAPlugin @Inject constructor(
// Fix bug determine basal
if (determineBasalResultAMA == null) {
aapsLogger.error(LTag.APS, "SMB calculation returned null")
lastDetermineBasalAdapterAMAJS = null
lastDetermineBasalAdapter = null
lastAPSResult = null
lastAPSRun = 0
} else {
@ -167,8 +167,8 @@ class OpenAPSAMAPlugin @Inject constructor(
val now = System.currentTimeMillis()
determineBasalResultAMA.json?.put("timestamp", dateUtil.toISOString(now))
determineBasalResultAMA.inputConstraints = inputConstraints
lastDetermineBasalAdapterAMAJS = determineBasalAdapterAMAJS
lastAPSResult = determineBasalResultAMA
lastDetermineBasalAdapter = determineBasalAdapterAMAJS
lastAPSResult = determineBasalResultAMA as DetermineBasalResultAMA
lastAPSRun = now
}
rxBus.send(EventOpenAPSUpdateGui())

View file

@ -4,27 +4,19 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.MealData
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.*
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback
import info.nightscout.androidaps.plugins.aps.loop.APSResult
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.shared.SafeParse
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.stats.TddCalculator
import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONArray
import org.json.JSONException
@ -36,7 +28,7 @@ import java.lang.reflect.InvocationTargetException
import java.nio.charset.StandardCharsets
import javax.inject.Inject
class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader: ScriptReader, private val injector: HasAndroidInjector) {
class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader: ScriptReader, private val injector: HasAndroidInjector) : DetermineBasalAdapterInterface {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var constraintChecker: ConstraintChecker
@ -45,10 +37,6 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var iobCobCalculator: IobCobCalculator
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var repository: AppRepository
@Inject lateinit var dateUtil: DateUtil
//@Inject lateinit var danaPump: DanaPump
private var profile = JSONObject()
private var mGlucoseStatus = JSONObject()
@ -60,26 +48,16 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
private var smbAlwaysAllowed = false
private var currentTime: Long = 0
private var saveCgmSource = false
private var lastBolusNormalTime: Long = 0
private val millsToThePast = T.hours(4).msecs()
private var tddAIMI: TddCalculator? = null
var currentTempParam: String? = null
private set
var iobDataParam: String? = null
private set
var glucoseStatusParam: String? = null
private set
var profileParam: String? = null
private set
var mealDataParam: String? = null
private set
var scriptDebug = ""
private set
override var currentTempParam: String? = null
override var iobDataParam: String? = null
override var glucoseStatusParam: String? = null
override var profileParam: String? = null
override var mealDataParam: String? = null
override var scriptDebug = ""
@Suppress("SpellCheckingInspection")
operator fun invoke(): DetermineBasalResultSMB? {
override operator fun invoke(): APSResult? {
aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<")
aapsLogger.debug(LTag.APS, "Glucose status: " + mGlucoseStatus.toString().also { glucoseStatusParam = it })
aapsLogger.debug(LTag.APS, "IOB data: " + iobData.toString().also { iobDataParam = it })
@ -169,22 +147,24 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
return determineBasalResultSMB
}
@Suppress("SpellCheckingInspection") fun setData(profile: Profile,
maxIob: Double,
maxBasal: Double,
minBg: Double,
maxBg: Double,
targetBg: Double,
basalRate: Double,
iobArray: Array<IobTotal>,
glucoseStatus: GlucoseStatus,
mealData: MealData,
autosensDataRatio: Double,
tempTargetSet: Boolean,
microBolusAllowed: Boolean,
uamAllowed: Boolean,
advancedFiltering: Boolean,
isSaveCgmSource: Boolean
@Suppress("SpellCheckingInspection")
override fun setData(
profile: Profile,
maxIob: Double,
maxBasal: Double,
minBg: Double,
maxBg: Double,
targetBg: Double,
basalRate: Double,
iobArray: Array<IobTotal>,
glucoseStatus: GlucoseStatus,
mealData: MealData,
autosensDataRatio: Double,
tempTargetSet: Boolean,
microBolusAllowed: Boolean,
uamAllowed: Boolean,
advancedFiltering: Boolean,
isSaveCgmSource: Boolean
) {
val pump = activePlugin.activePump
val pumpBolusStep = pump.pumpDescription.bolusStep
@ -255,7 +235,6 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
} else {
mGlucoseStatus.put("delta", glucoseStatus.delta)
}
mGlucoseStatus.put("short_avgdelta", glucoseStatus.shortAvgDelta)
mGlucoseStatus.put("long_avgdelta", glucoseStatus.longAvgDelta)
mGlucoseStatus.put("date", glucoseStatus.date)
@ -264,13 +243,7 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
this.mealData.put("slopeFromMaxDeviation", mealData.slopeFromMaxDeviation)
this.mealData.put("slopeFromMinDeviation", mealData.slopeFromMinDeviation)
this.mealData.put("lastBolusTime", mealData.lastBolusTime)
this.mealData.put("lastBolusNormalTime", lastBolusNormalTime)
this.mealData.put("lastCarbTime", mealData.lastCarbTime)
tddAIMI = TddCalculator(aapsLogger,rh,activePlugin,profileFunction,dateUtil,iobCobCalculator, repository)
this.mealData.put("TDDAIMI7", tddAIMI!!.averageTDD(tddAIMI!!.calculate(7)).totalAmount)
this.mealData.put("TDDPUMP", tddAIMI!!.calculateDaily().totalAmount)
if (constraintChecker.isAutosensModeEnabled().value()) {
autosensData.put("ratio", autosensDataRatio)
} else {

View file

@ -9,8 +9,7 @@ import android.view.ViewGroup
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.databinding.OpenapsamaFragmentBinding
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateResultGui
import info.nightscout.androidaps.plugins.bus.RxBus
@ -19,6 +18,8 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.JSONFormatter
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import org.json.JSONArray
@ -34,7 +35,7 @@ class OpenAPSSMBFragment : DaggerFragment() {
@Inject lateinit var rxBus: RxBus
@Inject lateinit var rh: ResourceHelper
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var openAPSSMBPlugin: OpenAPSSMBPlugin
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var jsonFormatter: JSONFormatter
@ -44,8 +45,7 @@ class OpenAPSSMBFragment : DaggerFragment() {
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = OpenapsamaFragmentBinding.inflate(inflater, container, false)
return binding.root
}
@ -54,7 +54,7 @@ class OpenAPSSMBFragment : DaggerFragment() {
super.onViewCreated(view, savedInstanceState)
binding.run.setOnClickListener {
openAPSSMBPlugin.invoke("OpenAPSSMB button", false)
activePlugin.activeAPS.invoke("OpenAPSSMB button", false)
}
}
@ -92,11 +92,12 @@ class OpenAPSSMBFragment : DaggerFragment() {
@Synchronized
fun updateGUI() {
if (_binding == null) return
val openAPSSMBPlugin = activePlugin.activeAPS
openAPSSMBPlugin.lastAPSResult?.let { lastAPSResult ->
binding.result.text = jsonFormatter.format(lastAPSResult.json)
binding.request.text = lastAPSResult.toSpanned()
}
openAPSSMBPlugin.lastDetermineBasalAdapterSMBJS?.let { determineBasalAdapterSMBJS ->
openAPSSMBPlugin.lastDetermineBasalAdapter?.let { determineBasalAdapterSMBJS ->
binding.glucosestatus.text = jsonFormatter.format(determineBasalAdapterSMBJS.glucoseStatusParam)
binding.currenttemp.text = jsonFormatter.format(determineBasalAdapterSMBJS.currentTempParam)
try {

View file

@ -10,8 +10,6 @@ import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.extensions.target
import info.nightscout.androidaps.interfaces.*
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateResultGui
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
@ -24,6 +22,8 @@ import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.Profiler
import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import javax.inject.Inject
import javax.inject.Singleton
@ -37,7 +37,7 @@ class OpenAPSSMBPlugin @Inject constructor(
private val constraintChecker: ConstraintChecker,
rh: ResourceHelper,
private val profileFunction: ProfileFunction,
private val context: Context,
val context: Context,
private val activePlugin: ActivePlugin,
private val iobCobCalculator: IobCobCalculator,
private val hardLimits: HardLimits,
@ -46,23 +46,24 @@ class OpenAPSSMBPlugin @Inject constructor(
private val dateUtil: DateUtil,
private val repository: AppRepository,
private val glucoseStatusProvider: GlucoseStatusProvider
) : PluginBase(PluginDescription()
.mainType(PluginType.APS)
.fragmentClass(OpenAPSSMBFragment::class.java.name)
.pluginIcon(R.drawable.ic_generic_icon)
.pluginName(R.string.openapssmb)
.shortName(R.string.smb_shortname)
.preferencesId(R.xml.pref_openapssmb)
.description(R.string.description_smb)
.setDefault(),
) : PluginBase(
PluginDescription()
.mainType(PluginType.APS)
.fragmentClass(OpenAPSSMBFragment::class.java.name)
.pluginIcon(R.drawable.ic_generic_icon)
.pluginName(R.string.openapssmb)
.shortName(R.string.smb_shortname)
.preferencesId(R.xml.pref_openapssmb)
.description(R.string.description_smb)
.setDefault(),
aapsLogger, rh, injector
), APS, Constraints {
// last values
override var lastAPSRun: Long = 0
override var lastAPSResult: DetermineBasalResultSMB? = null
var lastDetermineBasalAdapterSMBJS: DetermineBasalAdapterSMBJS? = null
var lastAutosensResult = AutosensResult()
override var lastDetermineBasalAdapter: DetermineBasalAdapterInterface? = null
override var lastAutosensResult = AutosensResult()
override fun specialEnableCondition(): Boolean {
return try {
@ -120,15 +121,34 @@ class OpenAPSSMBPlugin @Inject constructor(
}.value()
var minBg = hardLimits.verifyHardLimits(Round.roundTo(profile.getTargetLowMgdl(), 0.1), R.string.profile_low_target, HardLimits.VERY_HARD_LIMIT_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_MIN_BG[1])
var maxBg = hardLimits.verifyHardLimits(Round.roundTo(profile.getTargetHighMgdl(), 0.1), R.string.profile_high_target, HardLimits.VERY_HARD_LIMIT_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_MAX_BG[1])
var maxBg =
hardLimits.verifyHardLimits(Round.roundTo(profile.getTargetHighMgdl(), 0.1), R.string.profile_high_target, HardLimits.VERY_HARD_LIMIT_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_MAX_BG[1])
var targetBg = hardLimits.verifyHardLimits(profile.getTargetMgdl(), R.string.temp_target_value, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TARGET_BG[1])
var isTempTarget = false
val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
if (tempTarget is ValueWrapper.Existing) {
isTempTarget = true
minBg = hardLimits.verifyHardLimits(tempTarget.value.lowTarget, R.string.temp_target_low_target, HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1].toDouble())
maxBg = hardLimits.verifyHardLimits(tempTarget.value.highTarget, R.string.temp_target_high_target, HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1].toDouble())
targetBg = hardLimits.verifyHardLimits(tempTarget.value.target(), R.string.temp_target_value, HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1].toDouble())
minBg =
hardLimits.verifyHardLimits(
tempTarget.value.lowTarget,
R.string.temp_target_low_target,
HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0].toDouble(),
HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1].toDouble()
)
maxBg =
hardLimits.verifyHardLimits(
tempTarget.value.highTarget,
R.string.temp_target_high_target,
HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0].toDouble(),
HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1].toDouble()
)
targetBg =
hardLimits.verifyHardLimits(
tempTarget.value.target(),
R.string.temp_target_value,
HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0].toDouble(),
HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1].toDouble()
)
}
if (!hardLimits.checkHardLimits(profile.dia, R.string.profile_dia, hardLimits.minDia(), hardLimits.maxDia())) return
if (!hardLimits.checkHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), R.string.profile_carbs_ratio_value, hardLimits.minIC(), hardLimits.maxIC())) return
@ -165,8 +185,9 @@ class OpenAPSSMBPlugin @Inject constructor(
profiler.log(LTag.APS, "SMB data gathering", start)
start = System.currentTimeMillis()
DetermineBasalAdapterSMBJS(ScriptReader(context), injector).also { determineBasalAdapterSMBJS ->
determineBasalAdapterSMBJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg,
provideDetermineBasalAdapter().also { determineBasalAdapterSMBJS ->
determineBasalAdapterSMBJS.setData(
profile, maxIob, maxBasal, minBg, maxBg, targetBg,
activePlugin.activePump.baseBasalRate,
iobArray,
glucoseStatus,
@ -176,24 +197,26 @@ class OpenAPSSMBPlugin @Inject constructor(
smbAllowed.value(),
uam.value(),
advancedFiltering.value(),
activePlugin.activeBgSource.javaClass.simpleName == "DexcomPlugin")
activePlugin.activeBgSource.javaClass.simpleName == "DexcomPlugin"
)
val now = System.currentTimeMillis()
val determineBasalResultSMB = determineBasalAdapterSMBJS.invoke()
profiler.log(LTag.APS, "SMB calculation", start)
if (determineBasalResultSMB == null) {
aapsLogger.error(LTag.APS, "SMB calculation returned null")
lastDetermineBasalAdapterSMBJS = null
lastDetermineBasalAdapter = null
lastAPSResult = null
lastAPSRun = 0
} else {
// TODO still needed with oref1?
// Fix bug determine basal
if (determineBasalResultSMB.rate == 0.0 && determineBasalResultSMB.duration == 0 && iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now()) == null) determineBasalResultSMB.tempBasalRequested = false
if (determineBasalResultSMB.rate == 0.0 && determineBasalResultSMB.duration == 0 && iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now()) == null) determineBasalResultSMB.tempBasalRequested =
false
determineBasalResultSMB.iob = iobArray[0]
determineBasalResultSMB.json?.put("timestamp", dateUtil.toISOString(now))
determineBasalResultSMB.inputConstraints = inputConstraints
lastDetermineBasalAdapterSMBJS = determineBasalAdapterSMBJS
lastAPSResult = determineBasalResultSMB
lastDetermineBasalAdapter = determineBasalAdapterSMBJS
lastAPSResult = determineBasalResultSMB as DetermineBasalResultSMB
lastAPSRun = now
}
}
@ -204,4 +227,6 @@ class OpenAPSSMBPlugin @Inject constructor(
value.set(aapsLogger, false)
return value
}
fun provideDetermineBasalAdapter(): DetermineBasalAdapterInterface = DetermineBasalAdapterSMBJS(ScriptReader(context), injector)
}

View file

@ -0,0 +1,298 @@
package info.nightscout.androidaps.plugins.aps.openAPSSMBAutoISF
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.MealData
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
import info.nightscout.androidaps.interfaces.DetermineBasalAdapterInterface
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.stats.TddCalculator
import info.nightscout.shared.SafeParse
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import org.mozilla.javascript.*
import org.mozilla.javascript.Function
import java.io.IOException
import java.lang.reflect.InvocationTargetException
import java.nio.charset.StandardCharsets
import javax.inject.Inject
class DetermineBasalAdapterSMBAutoISFJS internal constructor(private val scriptReader: ScriptReader, private val injector: HasAndroidInjector) : DetermineBasalAdapterInterface {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var sp: SP
@Inject lateinit var rh: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var iobCobCalculator: IobCobCalculator
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var repository: AppRepository
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var tddCalculator: TddCalculator
private var profile = JSONObject()
private var mGlucoseStatus = JSONObject()
private var iobData: JSONArray? = null
private var mealData = JSONObject()
private var currentTemp = JSONObject()
private var autosensData = JSONObject()
private var microBolusAllowed = false
private var smbAlwaysAllowed = false
private var currentTime: Long = 0
private var saveCgmSource = false
private var lastBolusNormalTime: Long = 0
override var currentTempParam: String? = null
override var iobDataParam: String? = null
override var glucoseStatusParam: String? = null
override var profileParam: String? = null
override var mealDataParam: String? = null
override var scriptDebug = ""
@Suppress("SpellCheckingInspection")
override operator fun invoke(): DetermineBasalResultSMB? {
aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<")
aapsLogger.debug(LTag.APS, "Glucose status: " + mGlucoseStatus.toString().also { glucoseStatusParam = it })
aapsLogger.debug(LTag.APS, "IOB data: " + iobData.toString().also { iobDataParam = it })
aapsLogger.debug(LTag.APS, "Current temp: " + currentTemp.toString().also { currentTempParam = it })
aapsLogger.debug(LTag.APS, "Profile: " + profile.toString().also { profileParam = it })
aapsLogger.debug(LTag.APS, "Meal data: " + mealData.toString().also { mealDataParam = it })
aapsLogger.debug(LTag.APS, "Autosens data: $autosensData")
aapsLogger.debug(LTag.APS, "Reservoir data: " + "undefined")
aapsLogger.debug(LTag.APS, "MicroBolusAllowed: $microBolusAllowed")
aapsLogger.debug(LTag.APS, "SMBAlwaysAllowed: $smbAlwaysAllowed")
aapsLogger.debug(LTag.APS, "CurrentTime: $currentTime")
aapsLogger.debug(LTag.APS, "isSaveCgmSource: $saveCgmSource")
var determineBasalResultSMB: DetermineBasalResultSMB? = null
val rhino = Context.enter()
val scope: Scriptable = rhino.initStandardObjects()
// Turn off optimization to make Rhino Android compatible
rhino.optimizationLevel = -1
try {
//register logger callback for console.log and console.error
ScriptableObject.defineClass(scope, LoggerCallback::class.java)
val myLogger = rhino.newObject(scope, "LoggerCallback", null)
scope.put("console2", scope, myLogger)
rhino.evaluateString(scope, readFile("OpenAPSAMA/loggerhelper.js"), "JavaScript", 0, null)
//set module parent
rhino.evaluateString(scope, "var module = {\"parent\":Boolean(1)};", "JavaScript", 0, null)
rhino.evaluateString(scope, "var round_basal = function round_basal(basal, profile) { return basal; };", "JavaScript", 0, null)
rhino.evaluateString(scope, "require = function() {return round_basal;};", "JavaScript", 0, null)
//generate functions "determine_basal" and "setTempBasal"
rhino.evaluateString(scope, readFile("OpenAPSSMBAutoISF/determine-basal.js"), "JavaScript", 0, null)
rhino.evaluateString(scope, readFile("OpenAPSSMB/basal-set-temp.js"), "setTempBasal.js", 0, null)
val determineBasalObj = scope["determine_basal", scope]
val setTempBasalFunctionsObj = scope["tempBasalFunctions", scope]
//call determine-basal
if (determineBasalObj is Function && setTempBasalFunctionsObj is NativeObject) {
//prepare parameters
val params = arrayOf(
makeParam(mGlucoseStatus, rhino, scope),
makeParam(currentTemp, rhino, scope),
makeParamArray(iobData, rhino, scope),
makeParam(profile, rhino, scope),
makeParam(autosensData, rhino, scope),
makeParam(mealData, rhino, scope),
setTempBasalFunctionsObj,
java.lang.Boolean.valueOf(microBolusAllowed),
makeParam(null, rhino, scope), // reservoir data as undefined
java.lang.Long.valueOf(currentTime),
java.lang.Boolean.valueOf(saveCgmSource)
)
val jsResult = determineBasalObj.call(rhino, scope, scope, params) as NativeObject
scriptDebug = LoggerCallback.scriptDebug
// Parse the jsResult object to a JSON-String
val result = NativeJSON.stringify(rhino, scope, jsResult, null, null).toString()
aapsLogger.debug(LTag.APS, "Result: $result")
try {
val resultJson = JSONObject(result)
determineBasalResultSMB = DetermineBasalResultSMB(injector, resultJson)
} catch (e: JSONException) {
aapsLogger.error(LTag.APS, "Unhandled exception", e)
}
} else {
aapsLogger.error(LTag.APS, "Problem loading JS Functions")
}
} catch (e: IOException) {
aapsLogger.error(LTag.APS, "IOException")
} catch (e: RhinoException) {
aapsLogger.error(LTag.APS, "RhinoException: (" + e.lineNumber() + "," + e.columnNumber() + ") " + e.toString())
} catch (e: IllegalAccessException) {
aapsLogger.error(LTag.APS, e.toString())
} catch (e: InstantiationException) {
aapsLogger.error(LTag.APS, e.toString())
} catch (e: InvocationTargetException) {
aapsLogger.error(LTag.APS, e.toString())
} finally {
Context.exit()
}
glucoseStatusParam = mGlucoseStatus.toString()
iobDataParam = iobData.toString()
currentTempParam = currentTemp.toString()
profileParam = profile.toString()
mealDataParam = mealData.toString()
return determineBasalResultSMB
}
@Suppress("SpellCheckingInspection")
override fun setData(
profile: Profile,
maxIob: Double,
maxBasal: Double,
minBg: Double,
maxBg: Double,
targetBg: Double,
basalRate: Double,
iobArray: Array<IobTotal>,
glucoseStatus: GlucoseStatus,
mealData: MealData,
autosensDataRatio: Double,
tempTargetSet: Boolean,
microBolusAllowed: Boolean,
uamAllowed: Boolean,
advancedFiltering: Boolean,
isSaveCgmSource: Boolean
) {
val pump = activePlugin.activePump
val pumpBolusStep = pump.pumpDescription.bolusStep
this.profile.put("max_iob", maxIob)
//mProfile.put("dia", profile.getDia());
this.profile.put("type", "current")
this.profile.put("max_daily_basal", profile.getMaxDailyBasal())
this.profile.put("max_basal", maxBasal)
this.profile.put("min_bg", minBg)
this.profile.put("max_bg", maxBg)
this.profile.put("target_bg", targetBg)
this.profile.put("carb_ratio", profile.getIc())
this.profile.put("sens", profile.getIsfMgdl())
this.profile.put("max_daily_safety_multiplier", sp.getInt(R.string.key_openapsama_max_daily_safety_multiplier, 3))
this.profile.put("current_basal_safety_multiplier", sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0))
//mProfile.put("high_temptarget_raises_sensitivity", SP.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity));
this.profile.put("high_temptarget_raises_sensitivity", false)
//mProfile.put("low_temptarget_lowers_sensitivity", SP.getBoolean(R.string.key_low_temptarget_lowers_sensitivity, SMBDefaults.low_temptarget_lowers_sensitivity));
this.profile.put("low_temptarget_lowers_sensitivity", false)
this.profile.put("sensitivity_raises_target", sp.getBoolean(R.string.key_sensitivity_raises_target, SMBDefaults.sensitivity_raises_target))
this.profile.put("resistance_lowers_target", sp.getBoolean(R.string.key_resistance_lowers_target, SMBDefaults.resistance_lowers_target))
this.profile.put("adv_target_adjustments", SMBDefaults.adv_target_adjustments)
this.profile.put("exercise_mode", SMBDefaults.exercise_mode)
this.profile.put("half_basal_exercise_target", SMBDefaults.half_basal_exercise_target)
this.profile.put("maxCOB", SMBDefaults.maxCOB)
this.profile.put("skip_neutral_temps", pump.setNeutralTempAtFullHour())
// min_5m_carbimpact is not used within SMB determinebasal
//if (mealData.usedMinCarbsImpact > 0) {
// mProfile.put("min_5m_carbimpact", mealData.usedMinCarbsImpact);
//} else {
// mProfile.put("min_5m_carbimpact", SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact));
//}
this.profile.put("remainingCarbsCap", SMBDefaults.remainingCarbsCap)
this.profile.put("enableUAM", uamAllowed)
this.profile.put("A52_risk_enable", SMBDefaults.A52_risk_enable)
val smbEnabled = sp.getBoolean(R.string.key_use_smb, false)
this.profile.put("SMBInterval", sp.getInt(R.string.key_smbinterval, SMBDefaults.SMBInterval))
this.profile.put("enableSMB_with_COB", smbEnabled && sp.getBoolean(R.string.key_enableSMB_with_COB, false))
this.profile.put("enableSMB_with_temptarget", smbEnabled && sp.getBoolean(R.string.key_enableSMB_with_temptarget, false))
this.profile.put("allowSMB_with_high_temptarget", smbEnabled && sp.getBoolean(R.string.key_allowSMB_with_high_temptarget, false))
this.profile.put("enableSMB_always", smbEnabled && sp.getBoolean(R.string.key_enableSMB_always, false) && advancedFiltering)
this.profile.put("enableSMB_after_carbs", smbEnabled && sp.getBoolean(R.string.key_enableSMB_after_carbs, false) && advancedFiltering)
this.profile.put("maxSMBBasalMinutes", sp.getInt(R.string.key_smbmaxminutes, SMBDefaults.maxSMBBasalMinutes))
this.profile.put("maxUAMSMBBasalMinutes", sp.getInt(R.string.key_uamsmbmaxminutes, SMBDefaults.maxUAMSMBBasalMinutes))
//set the min SMB amount to be the amount set by the pump.
this.profile.put("bolus_increment", pumpBolusStep)
this.profile.put("carbsReqThreshold", sp.getInt(R.string.key_carbsReqThreshold, SMBDefaults.carbsReqThreshold))
this.profile.put("current_basal", basalRate)
this.profile.put("temptargetSet", tempTargetSet)
this.profile.put("autosens_max", SafeParse.stringToDouble(sp.getString(R.string.key_openapsama_autosens_max, "1.2")))
if (profileFunction.getUnits() == GlucoseUnit.MMOL) {
this.profile.put("out_units", "mmol/L")
}
val now = System.currentTimeMillis()
val tb = iobCobCalculator.getTempBasalIncludingConvertedExtended(now)
currentTemp.put("temp", "absolute")
currentTemp.put("duration", tb?.plannedRemainingMinutes ?: 0)
currentTemp.put("rate", tb?.convertedToAbsolute(now, profile) ?: 0.0)
// as we have non default temps longer than 30 mintues
if (tb != null) currentTemp.put("minutesrunning", tb.getPassedDurationToTimeInMinutes(now))
iobData = iobCobCalculator.convertToJSONArray(iobArray)
mGlucoseStatus.put("glucose", glucoseStatus.glucose)
mGlucoseStatus.put("noise", glucoseStatus.noise)
if (sp.getBoolean(R.string.key_always_use_shortavg, false)) {
mGlucoseStatus.put("delta", glucoseStatus.shortAvgDelta)
} else {
mGlucoseStatus.put("delta", glucoseStatus.delta)
}
mGlucoseStatus.put("short_avgdelta", glucoseStatus.shortAvgDelta)
mGlucoseStatus.put("long_avgdelta", glucoseStatus.longAvgDelta)
mGlucoseStatus.put("date", glucoseStatus.date)
this.mealData.put("carbs", mealData.carbs)
this.mealData.put("mealCOB", mealData.mealCOB)
this.mealData.put("slopeFromMaxDeviation", mealData.slopeFromMaxDeviation)
this.mealData.put("slopeFromMinDeviation", mealData.slopeFromMinDeviation)
this.mealData.put("lastBolusTime", mealData.lastBolusTime)
this.mealData.put("lastBolusNormalTime", lastBolusNormalTime)
this.mealData.put("lastCarbTime", mealData.lastCarbTime)
this.mealData.put("TDDAIMI7", tddCalculator.averageTDD(tddCalculator.calculate(7)).totalAmount)
this.mealData.put("TDDPUMP", tddCalculator.calculateDaily().totalAmount)
if (constraintChecker.isAutosensModeEnabled().value()) {
autosensData.put("ratio", autosensDataRatio)
} else {
autosensData.put("ratio", 1.0)
}
this.microBolusAllowed = microBolusAllowed
smbAlwaysAllowed = advancedFiltering
currentTime = now
saveCgmSource = isSaveCgmSource
}
private fun makeParam(jsonObject: JSONObject?, rhino: Context, scope: Scriptable): Any {
return if (jsonObject == null) Undefined.instance
else NativeJSON.parse(rhino, scope, jsonObject.toString()) { _: Context?, _: Scriptable?, _: Scriptable?, objects: Array<Any?> -> objects[1] }
}
private fun makeParamArray(jsonArray: JSONArray?, rhino: Context, scope: Scriptable): Any {
return NativeJSON.parse(rhino, scope, jsonArray.toString()) { _: Context?, _: Scriptable?, _: Scriptable?, objects: Array<Any?> -> objects[1] }
}
@Throws(IOException::class) private fun readFile(filename: String): String {
val bytes = scriptReader.readFile(filename)
var string = String(bytes, StandardCharsets.UTF_8)
if (string.startsWith("#!/usr/bin/env node")) {
string = string.substring(20)
}
return string
}
init {
injector.androidInjector().inject(this)
}
}

View file

@ -0,0 +1,74 @@
package info.nightscout.androidaps.plugins.aps.openAPSSMBAutoISF
import android.content.Context
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.annotations.OpenForTesting
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
import info.nightscout.androidaps.interfaces.DetermineBasalAdapterInterface
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.Profiler
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.sharedPreferences.SP
import javax.inject.Inject
import javax.inject.Singleton
@OpenForTesting
@Singleton
class OpenAPSSMBAutoISFPlugin @Inject constructor(
injector: HasAndroidInjector,
aapsLogger: AAPSLogger,
rxBus: RxBus,
constraintChecker: ConstraintChecker,
rh: ResourceHelper,
profileFunction: ProfileFunction,
context: Context,
activePlugin: ActivePlugin,
iobCobCalculator: IobCobCalculator,
hardLimits: HardLimits,
profiler: Profiler,
sp: SP,
dateUtil: DateUtil,
repository: AppRepository,
glucoseStatusProvider: GlucoseStatusProvider,
private val buildHelper: BuildHelper
) : OpenAPSSMBPlugin(
injector,
aapsLogger,
rxBus,
constraintChecker,
rh,
profileFunction,
context,
activePlugin,
iobCobCalculator,
hardLimits,
profiler,
sp,
dateUtil,
repository,
glucoseStatusProvider
) {
init {
pluginDescription
.pluginName(R.string.openapssmbautoisf)
.description(R.string.description_smb_auto_isf)
.setDefault(false)
}
override fun specialEnableCondition(): Boolean = buildHelper.isEngineeringMode() && buildHelper.isDev()
override fun provideDetermineBasalAdapter(): DetermineBasalAdapterInterface = DetermineBasalAdapterSMBAutoISFJS(ScriptReader(context), injector)
}

View file

@ -96,7 +96,6 @@ class TddCalculator @Inject constructor(
//result.put(midnight, tdd)
}
val calculationStep = T.mins(5).msecs()
val tempBasals = iobCobCalculator.getTempBasalIncludingConvertedExtendedForRange(startTime, endTime, calculationStep)
for (t in startTime until endTime step calculationStep) {
//val midnight = MidnightTime.calc(t)

View file

@ -80,6 +80,7 @@
<string name="description_ns_client">Synchronizes your data with Nightscout</string>
<string name="description_ama">State of the algorithm in 2017</string>
<string name="description_smb">Most recent algorithm for advanced users</string>
<string name="description_smb_auto_isf">Most recent algorithm for advanced users with automatic ISF</string>
<string name="description_overview">Displays the current state of your loop and buttons for most common actions</string>
<string name="description_persistent_notification">Shows an ongoing notification with a short overview of what your loop is doing</string>
<string name="description_profile_local">Define a profile which is available offline.</string>
@ -535,6 +536,7 @@
<string name="ns_localbroadcasts">Enable broadcasts to other apps (like xDrip+). Do not enable if you have more than one instance of AAPS or NSClient installed!</string>
<string name="ns_localbroadcasts_title">Enable local Broadcasts.</string>
<string name="openapssmb">OpenAPS SMB</string>
<string name="openapssmbautoisf">OpenAPS SMB Auto ISF</string>
<string name="key_use_smb" translatable="false">use_smb</string>
<string name="key_use_uam" translatable="false">use_uam</string>
<string name="key_smb_enable_carbs_suggestions_threshold" translatable="false">smb_enable_carbs_suggestions_threshold</string>

View file

@ -1,10 +1,14 @@
package info.nightscout.androidaps.interfaces
import info.nightscout.androidaps.plugins.aps.loop.APSResult
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
interface APS {
val lastAPSResult: APSResult?
val lastAPSRun: Long
var lastDetermineBasalAdapter: DetermineBasalAdapterInterface?
var lastAutosensResult: AutosensResult
operator fun invoke(initiator: String, tempBasalFallback: Boolean)
}

View file

@ -0,0 +1,36 @@
package info.nightscout.androidaps.interfaces
import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.MealData
import info.nightscout.androidaps.plugins.aps.loop.APSResult
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
interface DetermineBasalAdapterInterface {
var currentTempParam: String?
var iobDataParam: String?
var glucoseStatusParam: String?
var profileParam: String?
var mealDataParam: String?
var scriptDebug: String
fun setData(profile: Profile,
maxIob: Double,
maxBasal: Double,
minBg: Double,
maxBg: Double,
targetBg: Double,
basalRate: Double,
iobArray: Array<IobTotal>,
glucoseStatus: GlucoseStatus,
mealData: MealData,
autosensDataRatio: Double,
tempTargetSet: Boolean,
microBolusAllowed: Boolean = false,
uamAllowed: Boolean = false,
advancedFiltering: Boolean = false,
isSaveCgmSource: Boolean = false
) {}
operator fun invoke(): APSResult?
}

View file

@ -35,5 +35,5 @@ class PluginDescription {
fun enableByDefault(enableByDefault: Boolean): PluginDescription = this.also { it.enableByDefault = enableByDefault }
fun visibleByDefault(visibleByDefault: Boolean): PluginDescription = this.also { it.visibleByDefault = visibleByDefault }
fun description(description: Int): PluginDescription = this.also { it.description = description }
fun setDefault(): PluginDescription = this.also { it.defaultPlugin = true }
fun setDefault(value: Boolean = true): PluginDescription = this.also { it.defaultPlugin = value }
}