SafetyPlugin -> kt
This commit is contained in:
parent
c099bad8af
commit
1ef8629f57
2 changed files with 195 additions and 289 deletions
|
@ -1,289 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.constraints.safety;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import dagger.android.HasAndroidInjector;
|
|
||||||
import info.nightscout.androidaps.Config;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.data.Profile;
|
|
||||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
|
||||||
import info.nightscout.androidaps.interfaces.BgSourceInterface;
|
|
||||||
import info.nightscout.androidaps.interfaces.Constraint;
|
|
||||||
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
|
||||||
import info.nightscout.androidaps.interfaces.PluginDescription;
|
|
||||||
import info.nightscout.androidaps.interfaces.PluginType;
|
|
||||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
|
||||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin;
|
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin;
|
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
|
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker;
|
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
|
|
||||||
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
|
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin;
|
|
||||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
|
||||||
import info.nightscout.androidaps.utils.DecimalFormatter;
|
|
||||||
import info.nightscout.androidaps.utils.HardLimits;
|
|
||||||
import info.nightscout.androidaps.utils.Round;
|
|
||||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper;
|
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
|
|
||||||
|
|
||||||
private final SP sp;
|
|
||||||
private final RxBusWrapper rxBus;
|
|
||||||
private final ConstraintChecker constraintChecker;
|
|
||||||
private final OpenAPSAMAPlugin openAPSAMAPlugin;
|
|
||||||
private final OpenAPSSMBPlugin openAPSSMBPlugin;
|
|
||||||
private final SensitivityOref1Plugin sensitivityOref1Plugin;
|
|
||||||
private final ActivePluginProvider activePlugin;
|
|
||||||
private final HardLimits hardLimits;
|
|
||||||
private final BuildHelper buildHelper;
|
|
||||||
private final TreatmentsPlugin treatmentsPlugin;
|
|
||||||
private final Config config;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public SafetyPlugin(
|
|
||||||
HasAndroidInjector injector,
|
|
||||||
AAPSLogger aapsLogger,
|
|
||||||
ResourceHelper resourceHelper,
|
|
||||||
SP sp,
|
|
||||||
RxBusWrapper rxBus,
|
|
||||||
ConstraintChecker constraintChecker,
|
|
||||||
OpenAPSAMAPlugin openAPSAMAPlugin,
|
|
||||||
OpenAPSSMBPlugin openAPSSMBPlugin,
|
|
||||||
SensitivityOref1Plugin sensitivityOref1Plugin,
|
|
||||||
ActivePluginProvider activePlugin,
|
|
||||||
HardLimits hardLimits,
|
|
||||||
BuildHelper buildHelper,
|
|
||||||
TreatmentsPlugin treatmentsPlugin,
|
|
||||||
Config config
|
|
||||||
) {
|
|
||||||
super(new PluginDescription()
|
|
||||||
.mainType(PluginType.CONSTRAINTS)
|
|
||||||
.neverVisible(true)
|
|
||||||
.alwaysEnabled(true)
|
|
||||||
.showInList(false)
|
|
||||||
.pluginName(R.string.safety)
|
|
||||||
.preferencesId(R.xml.pref_safety),
|
|
||||||
aapsLogger, resourceHelper, injector
|
|
||||||
);
|
|
||||||
this.sp = sp;
|
|
||||||
this.rxBus = rxBus;
|
|
||||||
this.constraintChecker = constraintChecker;
|
|
||||||
this.openAPSAMAPlugin = openAPSAMAPlugin;
|
|
||||||
this.openAPSSMBPlugin = openAPSSMBPlugin;
|
|
||||||
this.sensitivityOref1Plugin = sensitivityOref1Plugin;
|
|
||||||
this.activePlugin = activePlugin;
|
|
||||||
this.hardLimits = hardLimits;
|
|
||||||
this.buildHelper = buildHelper;
|
|
||||||
this.treatmentsPlugin = treatmentsPlugin;
|
|
||||||
this.config = config;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constraints interface
|
|
||||||
**/
|
|
||||||
@NonNull @Override
|
|
||||||
public Constraint<Boolean> isLoopInvocationAllowed(@NonNull Constraint<Boolean> value) {
|
|
||||||
if (!activePlugin.getActivePump().getPumpDescription().isTempBasalCapable)
|
|
||||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.pumpisnottempbasalcapable), this);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public Constraint<Boolean> isClosedLoopAllowed(@NonNull Constraint<Boolean> value) {
|
|
||||||
String mode = sp.getString(R.string.key_aps_mode, "open");
|
|
||||||
if ((mode.equals("open")))
|
|
||||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.closedmodedisabledinpreferences), this);
|
|
||||||
|
|
||||||
if (!buildHelper.isEngineeringModeOrRelease()) {
|
|
||||||
if (value.value()) {
|
|
||||||
Notification n = new Notification(Notification.TOAST_ALARM, getResourceHelper().gs(R.string.closed_loop_disabled_on_dev_branch), Notification.NORMAL);
|
|
||||||
rxBus.send(new EventNewNotification(n));
|
|
||||||
}
|
|
||||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.closed_loop_disabled_on_dev_branch), this);
|
|
||||||
}
|
|
||||||
PumpInterface pump = activePlugin.getActivePump();
|
|
||||||
if (!pump.isFakingTempsByExtendedBoluses() && treatmentsPlugin.isInHistoryExtendedBoluslInProgress()) {
|
|
||||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.closed_loop_disabled_with_eb), this);
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public Constraint<Boolean> isAutosensModeEnabled(@NonNull Constraint<Boolean> value) {
|
|
||||||
boolean enabled = sp.getBoolean(R.string.key_openapsama_useautosens, false);
|
|
||||||
if (!enabled)
|
|
||||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.autosensdisabledinpreferences), this);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public Constraint<Boolean> isSMBModeEnabled(@NonNull Constraint<Boolean> value) {
|
|
||||||
boolean enabled = sp.getBoolean(R.string.key_use_smb, false);
|
|
||||||
if (!enabled)
|
|
||||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.smbdisabledinpreferences), this);
|
|
||||||
Constraint<Boolean> closedLoop = constraintChecker.isClosedLoopAllowed();
|
|
||||||
if (!closedLoop.value())
|
|
||||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.smbnotallowedinopenloopmode), this);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public Constraint<Boolean> isUAMEnabled(@NonNull Constraint<Boolean> value) {
|
|
||||||
boolean enabled = sp.getBoolean(R.string.key_use_uam, false);
|
|
||||||
if (!enabled)
|
|
||||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.uamdisabledinpreferences), this);
|
|
||||||
boolean oref1Enabled = sensitivityOref1Plugin.isEnabled(PluginType.SENSITIVITY);
|
|
||||||
if (!oref1Enabled)
|
|
||||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.uamdisabledoref1notselected), this);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public Constraint<Boolean> isAdvancedFilteringEnabled(@NonNull Constraint<Boolean> value) {
|
|
||||||
BgSourceInterface bgSource = activePlugin.getActiveBgSource();
|
|
||||||
|
|
||||||
if (!bgSource.advancedFilteringSupported())
|
|
||||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.smbalwaysdisabled), this);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, @NonNull Profile profile) {
|
|
||||||
|
|
||||||
absoluteRate.setIfGreater(getAapsLogger(), 0d, String.format(getResourceHelper().gs(R.string.limitingbasalratio), 0d, getResourceHelper().gs(R.string.itmustbepositivevalue)), this);
|
|
||||||
|
|
||||||
if (config.getAPS()) {
|
|
||||||
double maxBasal = sp.getDouble(R.string.key_openapsma_max_basal, 1d);
|
|
||||||
if (maxBasal < profile.getMaxDailyBasal()) {
|
|
||||||
maxBasal = profile.getMaxDailyBasal();
|
|
||||||
absoluteRate.addReason(getResourceHelper().gs(R.string.increasingmaxbasal), this);
|
|
||||||
}
|
|
||||||
absoluteRate.setIfSmaller(getAapsLogger(), maxBasal, String.format(getResourceHelper().gs(R.string.limitingbasalratio), maxBasal, getResourceHelper().gs(R.string.maxvalueinpreferences)), this);
|
|
||||||
|
|
||||||
// Check percentRate but absolute rate too, because we know real current basal in pump
|
|
||||||
double maxBasalMult = sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d);
|
|
||||||
double maxFromBasalMult = Math.floor(maxBasalMult * profile.getBasal() * 100) / 100;
|
|
||||||
absoluteRate.setIfSmaller(getAapsLogger(), maxFromBasalMult, String.format(getResourceHelper().gs(R.string.limitingbasalratio), maxFromBasalMult, getResourceHelper().gs(R.string.maxbasalmultiplier)), this);
|
|
||||||
|
|
||||||
double maxBasalFromDaily = sp.getDouble(R.string.key_openapsama_max_daily_safety_multiplier, 3d);
|
|
||||||
double maxFromDaily = Math.floor(profile.getMaxDailyBasal() * maxBasalFromDaily * 100) / 100;
|
|
||||||
absoluteRate.setIfSmaller(getAapsLogger(), maxFromDaily, String.format(getResourceHelper().gs(R.string.limitingbasalratio), maxFromDaily, getResourceHelper().gs(R.string.maxdailybasalmultiplier)), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
absoluteRate.setIfSmaller(getAapsLogger(), hardLimits.maxBasal(), String.format(getResourceHelper().gs(R.string.limitingbasalratio), hardLimits.maxBasal(), getResourceHelper().gs(R.string.hardlimit)), this);
|
|
||||||
|
|
||||||
PumpInterface pump = activePlugin.getActivePump();
|
|
||||||
// check for pump max
|
|
||||||
if (pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) {
|
|
||||||
double pumpLimit = pump.getPumpDescription().pumpType.getTbrSettings().getMaxDose();
|
|
||||||
absoluteRate.setIfSmaller(getAapsLogger(), pumpLimit, String.format(getResourceHelper().gs(R.string.limitingbasalratio), pumpLimit, getResourceHelper().gs(R.string.pumplimit)), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// do rounding
|
|
||||||
if (pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) {
|
|
||||||
absoluteRate.set(getAapsLogger(), Round.roundTo(absoluteRate.value(), pump.getPumpDescription().tempAbsoluteStep));
|
|
||||||
}
|
|
||||||
return absoluteRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
|
|
||||||
|
|
||||||
Double currentBasal = profile.getBasal();
|
|
||||||
double absoluteRate = currentBasal * ((double) percentRate.originalValue() / 100);
|
|
||||||
|
|
||||||
percentRate.addReason("Percent rate " + percentRate.originalValue() + "% recalculated to " + DecimalFormatter.to2Decimal(absoluteRate) + " U/h with current basal " + DecimalFormatter.to2Decimal(currentBasal) + " U/h", this);
|
|
||||||
|
|
||||||
Constraint<Double> absoluteConstraint = new Constraint<>(absoluteRate);
|
|
||||||
applyBasalConstraints(absoluteConstraint, profile);
|
|
||||||
percentRate.copyReasons(absoluteConstraint);
|
|
||||||
|
|
||||||
PumpInterface pump = activePlugin.getActivePump();
|
|
||||||
|
|
||||||
int percentRateAfterConst = Double.valueOf(absoluteConstraint.value() / currentBasal * 100).intValue();
|
|
||||||
if (percentRateAfterConst < 100)
|
|
||||||
percentRateAfterConst = Round.ceilTo((double) percentRateAfterConst, (double) pump.getPumpDescription().tempPercentStep).intValue();
|
|
||||||
else
|
|
||||||
percentRateAfterConst = Round.floorTo((double) percentRateAfterConst, (double) pump.getPumpDescription().tempPercentStep).intValue();
|
|
||||||
|
|
||||||
percentRate.set(getAapsLogger(), percentRateAfterConst, String.format(getResourceHelper().gs(R.string.limitingpercentrate), percentRateAfterConst, getResourceHelper().gs(R.string.pumplimit)), this);
|
|
||||||
|
|
||||||
if (pump.getPumpDescription().tempBasalStyle == PumpDescription.PERCENT) {
|
|
||||||
double pumpLimit = pump.getPumpDescription().pumpType.getTbrSettings().getMaxDose();
|
|
||||||
percentRate.setIfSmaller(getAapsLogger(), (int) pumpLimit, String.format(getResourceHelper().gs(R.string.limitingbasalratio), pumpLimit, getResourceHelper().gs(R.string.pumplimit)), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return percentRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) {
|
|
||||||
insulin.setIfGreater(getAapsLogger(), 0d, String.format(getResourceHelper().gs(R.string.limitingbolus), 0d, getResourceHelper().gs(R.string.itmustbepositivevalue)), this);
|
|
||||||
|
|
||||||
Double maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3d);
|
|
||||||
insulin.setIfSmaller(getAapsLogger(), maxBolus, String.format(getResourceHelper().gs(R.string.limitingbolus), maxBolus, getResourceHelper().gs(R.string.maxvalueinpreferences)), this);
|
|
||||||
|
|
||||||
insulin.setIfSmaller(getAapsLogger(), hardLimits.maxBolus(), String.format(getResourceHelper().gs(R.string.limitingbolus), hardLimits.maxBolus(), getResourceHelper().gs(R.string.hardlimit)), this);
|
|
||||||
|
|
||||||
PumpInterface pump = activePlugin.getActivePump();
|
|
||||||
double rounded = pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulin.value());
|
|
||||||
insulin.setIfDifferent(getAapsLogger(), rounded, getResourceHelper().gs(R.string.pumplimit), this);
|
|
||||||
return insulin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public Constraint<Double> applyExtendedBolusConstraints(Constraint<Double> insulin) {
|
|
||||||
insulin.setIfGreater(getAapsLogger(), 0d, String.format(getResourceHelper().gs(R.string.limitingextendedbolus), 0d, getResourceHelper().gs(R.string.itmustbepositivevalue)), this);
|
|
||||||
|
|
||||||
Double maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3d);
|
|
||||||
insulin.setIfSmaller(getAapsLogger(), maxBolus, String.format(getResourceHelper().gs(R.string.limitingextendedbolus), maxBolus, getResourceHelper().gs(R.string.maxvalueinpreferences)), this);
|
|
||||||
|
|
||||||
insulin.setIfSmaller(getAapsLogger(), hardLimits.maxBolus(), String.format(getResourceHelper().gs(R.string.limitingextendedbolus), hardLimits.maxBolus(), getResourceHelper().gs(R.string.hardlimit)), this);
|
|
||||||
|
|
||||||
PumpInterface pump = activePlugin.getActivePump();
|
|
||||||
double rounded = pump.getPumpDescription().pumpType.determineCorrectExtendedBolusSize(insulin.value());
|
|
||||||
insulin.setIfDifferent(getAapsLogger(), rounded, getResourceHelper().gs(R.string.pumplimit), this);
|
|
||||||
return insulin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public Constraint<Integer> applyCarbsConstraints(Constraint<Integer> carbs) {
|
|
||||||
carbs.setIfGreater(getAapsLogger(), 0, String.format(getResourceHelper().gs(R.string.limitingcarbs), 0, getResourceHelper().gs(R.string.itmustbepositivevalue)), this);
|
|
||||||
|
|
||||||
Integer maxCarbs = sp.getInt(R.string.key_treatmentssafety_maxcarbs, 48);
|
|
||||||
carbs.setIfSmaller(getAapsLogger(), maxCarbs, String.format(getResourceHelper().gs(R.string.limitingcarbs), maxCarbs, getResourceHelper().gs(R.string.maxvalueinpreferences)), this);
|
|
||||||
|
|
||||||
return carbs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public Constraint<Double> applyMaxIOBConstraints(@NonNull Constraint<Double> maxIob) {
|
|
||||||
double maxIobPref;
|
|
||||||
String apsmode = sp.getString(R.string.key_aps_mode, "open");
|
|
||||||
if (openAPSSMBPlugin.isEnabled(PluginType.APS))
|
|
||||||
maxIobPref = sp.getDouble(R.string.key_openapssmb_max_iob, 3d);
|
|
||||||
else
|
|
||||||
maxIobPref = sp.getDouble(R.string.key_openapsma_max_iob, 1.5d);
|
|
||||||
maxIob.setIfSmaller(getAapsLogger(), maxIobPref, String.format(getResourceHelper().gs(R.string.limitingiob), maxIobPref, getResourceHelper().gs(R.string.maxvalueinpreferences)), this);
|
|
||||||
|
|
||||||
if (openAPSAMAPlugin.isEnabled(PluginType.APS))
|
|
||||||
maxIob.setIfSmaller(getAapsLogger(), hardLimits.maxIobAMA(), String.format(getResourceHelper().gs(R.string.limitingiob), hardLimits.maxIobAMA(), getResourceHelper().gs(R.string.hardlimit)), this);
|
|
||||||
if (openAPSSMBPlugin.isEnabled(PluginType.APS))
|
|
||||||
maxIob.setIfSmaller(getAapsLogger(), hardLimits.maxIobSMB(), String.format(getResourceHelper().gs(R.string.limitingiob), hardLimits.maxIobSMB(), getResourceHelper().gs(R.string.hardlimit)), this);
|
|
||||||
if ((apsmode.equals("lgs")))
|
|
||||||
maxIob.setIfSmaller(getAapsLogger(), hardLimits.getMAXIOB_LGS(), String.format(getResourceHelper().gs(R.string.limitingiob), hardLimits.getMAXIOB_LGS(), getResourceHelper().gs(R.string.lowglucosesuspend)), this);
|
|
||||||
|
|
||||||
return maxIob;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,195 @@
|
||||||
|
package info.nightscout.androidaps.plugins.constraints.safety
|
||||||
|
|
||||||
|
import dagger.android.HasAndroidInjector
|
||||||
|
import info.nightscout.androidaps.Config
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.data.Profile
|
||||||
|
import info.nightscout.androidaps.interfaces.*
|
||||||
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
|
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin
|
||||||
|
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||||
|
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
|
||||||
|
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
|
||||||
|
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
|
||||||
|
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||||
|
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||||
|
import info.nightscout.androidaps.utils.HardLimits
|
||||||
|
import info.nightscout.androidaps.utils.Round
|
||||||
|
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
import kotlin.math.floor
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class SafetyPlugin @Inject constructor(
|
||||||
|
injector: HasAndroidInjector,
|
||||||
|
aapsLogger: AAPSLogger,
|
||||||
|
resourceHelper: ResourceHelper,
|
||||||
|
private val sp: SP,
|
||||||
|
private val rxBus: RxBusWrapper,
|
||||||
|
private val constraintChecker: ConstraintChecker,
|
||||||
|
private val openAPSAMAPlugin: OpenAPSAMAPlugin,
|
||||||
|
private val openAPSSMBPlugin: OpenAPSSMBPlugin,
|
||||||
|
private val sensitivityOref1Plugin: SensitivityOref1Plugin,
|
||||||
|
private val activePlugin: ActivePluginProvider,
|
||||||
|
private val hardLimits: HardLimits,
|
||||||
|
private val buildHelper: BuildHelper,
|
||||||
|
private val treatmentsPlugin: TreatmentsPlugin,
|
||||||
|
private val config: Config
|
||||||
|
) : PluginBase(PluginDescription()
|
||||||
|
.mainType(PluginType.CONSTRAINTS)
|
||||||
|
.neverVisible(true)
|
||||||
|
.alwaysEnabled(true)
|
||||||
|
.showInList(false)
|
||||||
|
.pluginName(R.string.safety)
|
||||||
|
.preferencesId(R.xml.pref_safety),
|
||||||
|
aapsLogger, resourceHelper, injector
|
||||||
|
), ConstraintsInterface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constraints interface
|
||||||
|
*/
|
||||||
|
override fun isLoopInvocationAllowed(value: Constraint<Boolean>): Constraint<Boolean> {
|
||||||
|
if (!activePlugin.activePump.pumpDescription.isTempBasalCapable) value[aapsLogger, false, resourceHelper.gs(R.string.pumpisnottempbasalcapable)] = this
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isClosedLoopAllowed(value: Constraint<Boolean>): Constraint<Boolean> {
|
||||||
|
val mode = sp.getString(R.string.key_aps_mode, "open")
|
||||||
|
if (mode == "open") value[aapsLogger, false, resourceHelper.gs(R.string.closedmodedisabledinpreferences)] = this
|
||||||
|
if (!buildHelper.isEngineeringModeOrRelease()) {
|
||||||
|
if (value.value()) {
|
||||||
|
val n = Notification(Notification.TOAST_ALARM, resourceHelper.gs(R.string.closed_loop_disabled_on_dev_branch), Notification.NORMAL)
|
||||||
|
rxBus.send(EventNewNotification(n))
|
||||||
|
}
|
||||||
|
value[aapsLogger, false, resourceHelper.gs(R.string.closed_loop_disabled_on_dev_branch)] = this
|
||||||
|
}
|
||||||
|
val pump = activePlugin.activePump
|
||||||
|
if (!pump.isFakingTempsByExtendedBoluses && treatmentsPlugin.isInHistoryExtendedBoluslInProgress) {
|
||||||
|
value[aapsLogger, false, resourceHelper.gs(R.string.closed_loop_disabled_with_eb)] = this
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isAutosensModeEnabled(value: Constraint<Boolean>): Constraint<Boolean> {
|
||||||
|
val enabled = sp.getBoolean(R.string.key_openapsama_useautosens, false)
|
||||||
|
if (!enabled) value[aapsLogger, false, resourceHelper.gs(R.string.autosensdisabledinpreferences)] = this
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isSMBModeEnabled(value: Constraint<Boolean>): Constraint<Boolean> {
|
||||||
|
val enabled = sp.getBoolean(R.string.key_use_smb, false)
|
||||||
|
if (!enabled) value[aapsLogger, false, resourceHelper.gs(R.string.smbdisabledinpreferences)] = this
|
||||||
|
val closedLoop = constraintChecker.isClosedLoopAllowed()
|
||||||
|
if (!closedLoop.value()) value[aapsLogger, false, resourceHelper.gs(R.string.smbnotallowedinopenloopmode)] = this
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isUAMEnabled(value: Constraint<Boolean>): Constraint<Boolean> {
|
||||||
|
val enabled = sp.getBoolean(R.string.key_use_uam, false)
|
||||||
|
if (!enabled) value[aapsLogger, false, resourceHelper.gs(R.string.uamdisabledinpreferences)] = this
|
||||||
|
val oref1Enabled = sensitivityOref1Plugin.isEnabled(PluginType.SENSITIVITY)
|
||||||
|
if (!oref1Enabled) value[aapsLogger, false, resourceHelper.gs(R.string.uamdisabledoref1notselected)] = this
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isAdvancedFilteringEnabled(value: Constraint<Boolean>): Constraint<Boolean> {
|
||||||
|
val bgSource = activePlugin.activeBgSource
|
||||||
|
if (!bgSource.advancedFilteringSupported()) value[aapsLogger, false, resourceHelper.gs(R.string.smbalwaysdisabled)] = this
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun applyBasalConstraints(absoluteRate: Constraint<Double>, profile: Profile): Constraint<Double> {
|
||||||
|
absoluteRate.setIfGreater(aapsLogger, 0.0, String.format(resourceHelper.gs(R.string.limitingbasalratio), 0.0, resourceHelper.gs(R.string.itmustbepositivevalue)), this)
|
||||||
|
if (config.APS) {
|
||||||
|
var maxBasal = sp.getDouble(R.string.key_openapsma_max_basal, 1.0)
|
||||||
|
if (maxBasal < profile.maxDailyBasal) {
|
||||||
|
maxBasal = profile.maxDailyBasal
|
||||||
|
absoluteRate.addReason(resourceHelper.gs(R.string.increasingmaxbasal), this)
|
||||||
|
}
|
||||||
|
absoluteRate.setIfSmaller(aapsLogger, maxBasal, String.format(resourceHelper.gs(R.string.limitingbasalratio), maxBasal, resourceHelper.gs(R.string.maxvalueinpreferences)), this)
|
||||||
|
|
||||||
|
// Check percentRate but absolute rate too, because we know real current basal in pump
|
||||||
|
val maxBasalMultiplier = sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0)
|
||||||
|
val maxFromBasalMultiplier = floor(maxBasalMultiplier * profile.basal * 100) / 100
|
||||||
|
absoluteRate.setIfSmaller(aapsLogger, maxFromBasalMultiplier, String.format(resourceHelper.gs(R.string.limitingbasalratio), maxFromBasalMultiplier, resourceHelper.gs(R.string.maxbasalmultiplier)), this)
|
||||||
|
val maxBasalFromDaily = sp.getDouble(R.string.key_openapsama_max_daily_safety_multiplier, 3.0)
|
||||||
|
val maxFromDaily = floor(profile.maxDailyBasal * maxBasalFromDaily * 100) / 100
|
||||||
|
absoluteRate.setIfSmaller(aapsLogger, maxFromDaily, String.format(resourceHelper.gs(R.string.limitingbasalratio), maxFromDaily, resourceHelper.gs(R.string.maxdailybasalmultiplier)), this)
|
||||||
|
}
|
||||||
|
absoluteRate.setIfSmaller(aapsLogger, hardLimits.maxBasal(), String.format(resourceHelper.gs(R.string.limitingbasalratio), hardLimits.maxBasal(), resourceHelper.gs(R.string.hardlimit)), this)
|
||||||
|
val pump = activePlugin.activePump
|
||||||
|
// check for pump max
|
||||||
|
if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) {
|
||||||
|
val pumpLimit = pump.pumpDescription.pumpType.tbrSettings.maxDose
|
||||||
|
absoluteRate.setIfSmaller(aapsLogger, pumpLimit, String.format(resourceHelper.gs(R.string.limitingbasalratio), pumpLimit, resourceHelper.gs(R.string.pumplimit)), this)
|
||||||
|
}
|
||||||
|
|
||||||
|
// do rounding
|
||||||
|
if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) {
|
||||||
|
absoluteRate[aapsLogger] = Round.roundTo(absoluteRate.value(), pump.pumpDescription.tempAbsoluteStep)
|
||||||
|
}
|
||||||
|
return absoluteRate
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun applyBasalPercentConstraints(percentRate: Constraint<Int>, profile: Profile): Constraint<Int> {
|
||||||
|
val currentBasal = profile.basal
|
||||||
|
val absoluteRate = currentBasal * (percentRate.originalValue().toDouble() / 100)
|
||||||
|
percentRate.addReason("Percent rate " + percentRate.originalValue() + "% recalculated to " + DecimalFormatter.to2Decimal(absoluteRate) + " U/h with current basal " + DecimalFormatter.to2Decimal(currentBasal) + " U/h", this)
|
||||||
|
val absoluteConstraint = Constraint(absoluteRate)
|
||||||
|
applyBasalConstraints(absoluteConstraint, profile)
|
||||||
|
percentRate.copyReasons(absoluteConstraint)
|
||||||
|
val pump = activePlugin.activePump
|
||||||
|
var percentRateAfterConst = java.lang.Double.valueOf(absoluteConstraint.value() / currentBasal * 100).toInt()
|
||||||
|
percentRateAfterConst = if (percentRateAfterConst < 100) Round.ceilTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt() else Round.floorTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt()
|
||||||
|
percentRate[aapsLogger, percentRateAfterConst, String.format(resourceHelper.gs(R.string.limitingpercentrate), percentRateAfterConst, resourceHelper.gs(R.string.pumplimit))] = this
|
||||||
|
if (pump.pumpDescription.tempBasalStyle == PumpDescription.PERCENT) {
|
||||||
|
val pumpLimit = pump.pumpDescription.pumpType.tbrSettings.maxDose
|
||||||
|
percentRate.setIfSmaller(aapsLogger, pumpLimit.toInt(), String.format(resourceHelper.gs(R.string.limitingbasalratio), pumpLimit, resourceHelper.gs(R.string.pumplimit)), this)
|
||||||
|
}
|
||||||
|
return percentRate
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun applyBolusConstraints(insulin: Constraint<Double>): Constraint<Double> {
|
||||||
|
insulin.setIfGreater(aapsLogger, 0.0, String.format(resourceHelper.gs(R.string.limitingbolus), 0.0, resourceHelper.gs(R.string.itmustbepositivevalue)), this)
|
||||||
|
val maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3.0)
|
||||||
|
insulin.setIfSmaller(aapsLogger, maxBolus, String.format(resourceHelper.gs(R.string.limitingbolus), maxBolus, resourceHelper.gs(R.string.maxvalueinpreferences)), this)
|
||||||
|
insulin.setIfSmaller(aapsLogger, hardLimits.maxBolus(), String.format(resourceHelper.gs(R.string.limitingbolus), hardLimits.maxBolus(), resourceHelper.gs(R.string.hardlimit)), this)
|
||||||
|
val pump = activePlugin.activePump
|
||||||
|
val rounded = pump.pumpDescription.pumpType.determineCorrectBolusSize(insulin.value())
|
||||||
|
insulin.setIfDifferent(aapsLogger, rounded, resourceHelper.gs(R.string.pumplimit), this)
|
||||||
|
return insulin
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun applyExtendedBolusConstraints(insulin: Constraint<Double>): Constraint<Double> {
|
||||||
|
insulin.setIfGreater(aapsLogger, 0.0, String.format(resourceHelper.gs(R.string.limitingextendedbolus), 0.0, resourceHelper.gs(R.string.itmustbepositivevalue)), this)
|
||||||
|
val maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3.0)
|
||||||
|
insulin.setIfSmaller(aapsLogger, maxBolus, String.format(resourceHelper.gs(R.string.limitingextendedbolus), maxBolus, resourceHelper.gs(R.string.maxvalueinpreferences)), this)
|
||||||
|
insulin.setIfSmaller(aapsLogger, hardLimits.maxBolus(), String.format(resourceHelper.gs(R.string.limitingextendedbolus), hardLimits.maxBolus(), resourceHelper.gs(R.string.hardlimit)), this)
|
||||||
|
val pump = activePlugin.activePump
|
||||||
|
val rounded = pump.pumpDescription.pumpType.determineCorrectExtendedBolusSize(insulin.value())
|
||||||
|
insulin.setIfDifferent(aapsLogger, rounded, resourceHelper.gs(R.string.pumplimit), this)
|
||||||
|
return insulin
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun applyCarbsConstraints(carbs: Constraint<Int>): Constraint<Int> {
|
||||||
|
carbs.setIfGreater(aapsLogger, 0, String.format(resourceHelper.gs(R.string.limitingcarbs), 0, resourceHelper.gs(R.string.itmustbepositivevalue)), this)
|
||||||
|
val maxCarbs = sp.getInt(R.string.key_treatmentssafety_maxcarbs, 48)
|
||||||
|
carbs.setIfSmaller(aapsLogger, maxCarbs, String.format(resourceHelper.gs(R.string.limitingcarbs), maxCarbs, resourceHelper.gs(R.string.maxvalueinpreferences)), this)
|
||||||
|
return carbs
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun applyMaxIOBConstraints(maxIob: Constraint<Double>): Constraint<Double> {
|
||||||
|
val apsMode = sp.getString(R.string.key_aps_mode, "open")
|
||||||
|
val maxIobPref: Double = if (openAPSSMBPlugin.isEnabled(PluginType.APS)) sp.getDouble(R.string.key_openapssmb_max_iob, 3.0) else sp.getDouble(R.string.key_openapsma_max_iob, 1.5)
|
||||||
|
maxIob.setIfSmaller(aapsLogger, maxIobPref, String.format(resourceHelper.gs(R.string.limitingiob), maxIobPref, resourceHelper.gs(R.string.maxvalueinpreferences)), this)
|
||||||
|
if (openAPSAMAPlugin.isEnabled(PluginType.APS)) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobAMA(), String.format(resourceHelper.gs(R.string.limitingiob), hardLimits.maxIobAMA(), resourceHelper.gs(R.string.hardlimit)), this)
|
||||||
|
if (openAPSSMBPlugin.isEnabled(PluginType.APS)) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobSMB(), String.format(resourceHelper.gs(R.string.limitingiob), hardLimits.maxIobSMB(), resourceHelper.gs(R.string.hardlimit)), this)
|
||||||
|
if (apsMode == "lgs") maxIob.setIfSmaller(aapsLogger, hardLimits.MAXIOB_LGS, String.format(resourceHelper.gs(R.string.limitingiob), hardLimits.MAXIOB_LGS, resourceHelper.gs(R.string.lowglucosesuspend)), this)
|
||||||
|
return maxIob
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue