applyBasalPercentConstraints reactor & tests part1

This commit is contained in:
Milos Kozak 2018-03-21 20:24:02 +01:00
parent ca70cbdaec
commit e2ea44a8a8
26 changed files with 144 additions and 108 deletions

View file

@ -13,7 +13,7 @@ public class Constants {
public static final double defaultDIA = 3d;
public static final Double REALLYHIGHBASALRATE = 1111111d;
public static final Integer basalPercentOnlyForCheckLimit = 10101010;
public static final Integer REALLYHIGHPERCENTBASALRATE = 1111111;
public static final double bolusOnlyForCheckLimit = 10101010d;
public static final Integer carbsOnlyForCheckLimit = 10101010;

View file

@ -112,15 +112,14 @@ public class ConstraintChecker implements ConstraintsInterface {
}
@Override
public Integer applyBasalPercentConstraints(Integer percentRate) {
Integer rateAfterConstrain = percentRate;
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
ArrayList<PluginBase> constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constrain = (ConstraintsInterface) p;
if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue;
rateAfterConstrain = Math.min(constrain.applyBasalPercentConstraints(percentRate), rateAfterConstrain);
constrain.applyBasalPercentConstraints(percentRate, profile);
}
return rateAfterConstrain;
return percentRate;
}
@Override

View file

@ -19,7 +19,7 @@ public interface ConstraintsInterface {
Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile);
Integer applyBasalPercentConstraints(Integer percentRate);
Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile);
Double applyBolusConstraints(Double insulin);

View file

@ -36,7 +36,7 @@ public interface PumpInterface {
PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo);
void stopBolusDelivering();
PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew);
PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew);
PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew);
PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes);
//some pumps might set a very short temp close to 100% as cancelling a temp can be noisy
//when the cancel request is requested by the user (forced), the pump should always do a real cancel

View file

@ -125,7 +125,7 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
String confirmMessage = getString(R.string.setbasalquestion);
if (setAsPercent) {
int basalPercentInput = SafeParse.stringToInt(basalPercent.getText());
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(basalPercentInput);
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(basalPercentInput), profile).value();
confirmMessage += "\n" + percent + "% ";
confirmMessage += "\n" + getString(R.string.duration) + " " + durationInMinutes + "min ?";
if (percent != basalPercentInput)
@ -162,7 +162,7 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
}
};
if (setAsPercent) {
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(finalBasalPercent, finalDurationInMinutes, true, callback);
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(finalBasalPercent, finalDurationInMinutes, true, profile, callback);
} else {
ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(finalBasal, finalDurationInMinutes, true, profile, callback);
}

View file

@ -303,7 +303,9 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
}
};
Integer maxPercent = MainApp.getConstraintChecker().applyBasalPercentConstraints(Constants.basalPercentOnlyForCheckLimit);
Integer maxPercent = 200;
if (profile != null)
maxPercent = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(Constants.REALLYHIGHPERCENTBASALRATE), profile).value();
editPercent = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_percentinput);
editPercent.setParams(0d, 0d, (double) maxPercent, 5d, new DecimalFormat("0"), true, percentTextWatcher);

View file

@ -696,9 +696,9 @@ public class ConfigBuilderPlugin implements PluginBase, TreatmentsInterface {
return null;
}
public void disconnectPump(int durationInMinutes) {
public void disconnectPump(int durationInMinutes, Profile profile) {
getActiveLoop().disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L);
getCommandQueue().tempBasalPercent(0, durationInMinutes, true, new Callback() {
getCommandQueue().tempBasalPercent(0, durationInMinutes, true, profile, new Callback() {
@Override
public void run() {
if (!result.success) {

View file

@ -351,7 +351,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
}
@Override
public Integer applyBasalPercentConstraints(Integer percentRate) {
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
return percentRate;
}

View file

@ -14,6 +14,7 @@ import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.HardLimits;
import info.nightscout.utils.Round;
import info.nightscout.utils.SP;
@ -154,49 +155,25 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
}
@Override
public Integer applyBasalPercentConstraints(Integer percentRate) {
Integer origPercentRate = percentRate;
Double maxBasal = SP.getDouble(R.string.key_openapsma_max_basal, 1d);
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null) return percentRate;
Double currentBasal = profile.getBasal();
Double absoluteRate = currentBasal * ((double) percentRate.originalValue() / 100);
Double absoluteRate = currentBasal * ((double) percentRate / 100);
percentRate.reason("Percent rate " + percentRate.originalValue() + "% recalculated to " + DecimalFormatter.to2Decimal(absoluteRate) + " U/h with current basal " + DecimalFormatter.to2Decimal(currentBasal) + " U/h");
if (Config.logConstraintsChanges)
log.debug("Percent rate " + percentRate + "% recalculated to " + absoluteRate + "U/h with current basal " + currentBasal + "U/h");
Constraint<Double> absoluteConstraint = new Constraint<>(absoluteRate);
applyBasalConstraints(absoluteConstraint, profile);
if (absoluteRate < 0) absoluteRate = 0d;
Double maxBasalMult = SP.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d);
Integer maxBasalFromDaily = SP.getInt(R.string.key_openapsama_max_daily_safety_multiplier, 3);
// Check percentRate but absolute rate too, because we know real current basal in pump
Double origRate = absoluteRate;
if (absoluteRate > maxBasal) {
absoluteRate = maxBasal;
if (Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
log.debug("Limiting rate " + origRate + " by maxBasal preference to " + absoluteRate + "U/h");
}
if (absoluteRate > maxBasalMult * profile.getBasal()) {
absoluteRate = Math.floor(maxBasalMult * profile.getBasal() * 100) / 100;
if (Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
log.debug("Limiting rate " + origRate + " by maxBasalMult to " + absoluteRate + "U/h");
}
if (absoluteRate > profile.getMaxDailyBasal() * maxBasalFromDaily) {
absoluteRate = profile.getMaxDailyBasal() * maxBasalFromDaily;
if (Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
log.debug("Limiting rate " + origRate + " by 3 * maxDailyBasal to " + absoluteRate + "U/h");
}
Integer percentRateAfterConst = new Double(absoluteRate / currentBasal * 100).intValue();
Integer percentRateAfterConst = Double.valueOf(absoluteConstraint.value() / currentBasal * 100).intValue();
if (percentRateAfterConst < 100)
percentRateAfterConst = Round.ceilTo((double) percentRateAfterConst, 10d).intValue();
else percentRateAfterConst = Round.floorTo((double) percentRateAfterConst, 10d).intValue();
if (Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
log.debug("Recalculated percent rate " + percentRate + "% to " + percentRateAfterConst + "%");
return percentRateAfterConst;
percentRate.set(percentRateAfterConst, String.format(MainApp.gs(R.string.limitingpercentrate), percentRateAfterConst, MainApp.gs(R.string.pumplimit)));
return percentRate;
}
@Override

View file

@ -296,7 +296,9 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
return;
}
okClicked = true;
if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) {
final Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile != null && (calculatedTotalInsulin > 0d || calculatedCarbs > 0d)) {
DecimalFormat formatNumber2decimalplaces = new DecimalFormat("0.00");
String confirmMessage = getString(R.string.entertreatmentquestion);
@ -341,7 +343,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
activeloop.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000);
MainApp.bus().post(new EventRefreshOverview("WizardDialog"));
}
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 120, true, new Callback() {
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 120, true, profile, new Callback() {
@Override
public void run() {
if (!result.success) {

View file

@ -440,7 +440,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
if (v == apsModeView) {
final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop();
final PumpDescription pumpDescription = ConfigBuilderPlugin.getActivePump().getPumpDescription();
if (activeloop == null)
if (activeloop == null || !MainApp.getConfigBuilder().isProfileValid("ContexMenuCreation"))
return;
menu.setHeaderTitle(MainApp.sResources.getString(R.string.loop));
if (activeloop.isEnabled(PluginBase.LOOP)) {
@ -474,6 +474,9 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
@Override
public boolean onContextItemSelected(MenuItem item) {
final Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null)
return true;
final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop();
if (item.getTitle().equals(MainApp.sResources.getString(R.string.disableloop))) {
activeloop.setFragmentEnabled(PluginBase.LOOP, false);
@ -527,23 +530,23 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
updateGUI("suspendmenu");
return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor15m))) {
MainApp.getConfigBuilder().disconnectPump(15);
MainApp.getConfigBuilder().disconnectPump(15, profile);
updateGUI("suspendmenu");
return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor30m))) {
MainApp.getConfigBuilder().disconnectPump(30);
MainApp.getConfigBuilder().disconnectPump(30, profile);
updateGUI("suspendmenu");
return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor1h))) {
MainApp.getConfigBuilder().disconnectPump(60);
MainApp.getConfigBuilder().disconnectPump(60, profile);
updateGUI("suspendmenu");
return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor2h))) {
MainApp.getConfigBuilder().disconnectPump(120);
MainApp.getConfigBuilder().disconnectPump(120, profile);
updateGUI("suspendmenu");
return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor3h))) {
MainApp.getConfigBuilder().disconnectPump(180);
MainApp.getConfigBuilder().disconnectPump(180, profile);
updateGUI("suspendmenu");
return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.careportal_profileswitch))) {
@ -761,7 +764,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
activeloop.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000);
MainApp.bus().post(new EventRefreshOverview("WizardDialog"));
}
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 120, true, new Callback() {
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 120, true, profile, new Callback() {
@Override
public void run() {
if (!result.success) {

View file

@ -764,7 +764,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
* is or isn't running at the moment
*/
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, final Integer durationInMinutes, boolean forceNew) {
public PumpEnactResult setTempBasalPercent(Integer percent, final Integer durationInMinutes, Profile profile, boolean forceNew) {
return setTempBasalPercent(percent, durationInMinutes);
}
@ -1458,7 +1458,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
}
@Override
public Integer applyBasalPercentConstraints(Integer percentRate) {
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
return percentRate;
}

View file

@ -214,9 +214,9 @@ public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface,
}
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) {
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) {
PumpEnactResult result = new PumpEnactResult();
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(percent);
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(percent), profile).value();
if (percent < 0) {
result.isTempCancel = false;
result.enacted = false;
@ -291,7 +291,8 @@ public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface,
result.isTempCancel = false;
result.duration = pump.extendedBolusRemainingMinutes;
result.absolute = pump.extendedBolusAbsoluteRate;
if (! SP.getBoolean("danar_useextended", false)) result.bolusDelivered = pump.extendedBolusAmount;
if (!SP.getBoolean("danar_useextended", false))
result.bolusDelivered = pump.extendedBolusAmount;
result.isPercent = false;
if (Config.logPumpActions)
log.debug("setExtendedBolus: OK");
@ -465,19 +466,14 @@ public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface,
return absoluteRate;
}
@SuppressWarnings("PointlessBooleanExpression")
@Override
public Integer applyBasalPercentConstraints(Integer percentRate) {
Integer origPercentRate = percentRate;
if (percentRate < 0) percentRate = 0;
if (percentRate > getPumpDescription().maxTempPercent)
percentRate = getPumpDescription().maxTempPercent;
if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%");
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
percentRate.setIfGreater(0, String.format(MainApp.gs(R.string.limitingpercentrate), 0, MainApp.gs(R.string.basalmustbepositivevalue)));
percentRate.setIfSmaller(getPumpDescription().maxTempPercent, String.format(MainApp.gs(R.string.limitingpercentrate), getPumpDescription().maxTempPercent, MainApp.gs(R.string.pumplimit)));
return percentRate;
}
@SuppressWarnings("PointlessBooleanExpression")
@Override
public Double applyBolusConstraints(Double insulin) {
double origInsulin = insulin;

View file

@ -249,7 +249,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
// Convert duration from minutes to hours
if (Config.logPumpActions)
log.debug("setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)");
return setTempBasalPercent(percentRate, durationInMinutes, false);
return setTempBasalPercent(percentRate, durationInMinutes, profile, false);
}
if (doExtendedTemp) {
// Check if some temp is already in progress

View file

@ -250,7 +250,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
// Convert duration from minutes to hours
if (Config.logPumpActions)
log.debug("setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)");
return setTempBasalPercent(percentRate, durationInMinutes, false);
return setTempBasalPercent(percentRate, durationInMinutes, profile,false);
}
if (doExtendedTemp) {
// Check if some temp is already in progress

View file

@ -306,16 +306,14 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface,
}
@Override
public Integer applyBasalPercentConstraints(Integer percentRate) {
Integer origPercentRate = percentRate;
if (percentRate < 0) percentRate = 0;
if (percentRate > getPumpDescription().maxTempPercent)
percentRate = getPumpDescription().maxTempPercent;
if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%");
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
percentRate.setIfGreater(0, String.format(MainApp.gs(R.string.limitingpercentrate), 0, MainApp.gs(R.string.basalmustbepositivevalue)));
percentRate.setIfSmaller(getPumpDescription().maxTempPercent, String.format(MainApp.gs(R.string.limitingpercentrate), getPumpDescription().maxTempPercent, MainApp.gs(R.string.pumplimit)));
return percentRate;
}
@Override
public Double applyBolusConstraints(Double insulin) {
double origInsulin = insulin;
@ -586,9 +584,9 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface,
}
@Override
public synchronized PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) {
public synchronized PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) {
PumpEnactResult result = new PumpEnactResult();
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(percent);
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(percent), profile).value();
if (percent < 0) {
result.isTempCancel = false;
result.enacted = false;

View file

@ -262,9 +262,9 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
}
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) {
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) {
PumpEnactResult result = new PumpEnactResult();
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(percent);
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(percent), profile).value();
if (percent < 0) {
result.isTempCancel = false;
result.enacted = false;

View file

@ -22,11 +22,11 @@ import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
@ -65,13 +65,12 @@ import static info.nightscout.androidaps.plugins.PumpInsight.history.PumpIdCache
/**
* Created by jamorham on 23/01/2018.
*
* <p>
* Connects to SightRemote app service using SightParser library
*
* <p>
* SightRemote and SightParser created by Tebbe Ubben
*
* <p>
* Original proof of concept SightProxy by jamorham
*
*/
@SuppressWarnings("AccessStaticViaInstance")
@ -394,7 +393,8 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints
for (int i = 0; i < profile.getBasalValues().length; i++) {
Profile.BasalValue basalValue = profile.getBasalValues()[i];
Profile.BasalValue nextValue = null;
if (profile.getBasalValues().length > i + 1) nextValue = profile.getBasalValues()[i + 1];
if (profile.getBasalValues().length > i + 1)
nextValue = profile.getBasalValues()[i + 1];
profileBlocks.add(new BRProfileBlock.ProfileBlock((((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60), Helpers.roundDouble(basalValue.value, 2)));
log("setNewBasalProfile: " + basalValue.value + " for " + Integer.toString(((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60));
}
@ -424,12 +424,15 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints
BRProfileBlock.ProfileBlock profileBlock = profileBlocks.get(i);
Profile.BasalValue basalValue = profile.getBasalValues()[i];
Profile.BasalValue nextValue = null;
if (profile.getBasalValues().length > i + 1) nextValue = profile.getBasalValues()[i + 1];
if (profile.getBasalValues().length > i + 1)
nextValue = profile.getBasalValues()[i + 1];
log("isThisProfileSet - Comparing block: Pump: " + profileBlock.getAmount() + " for " + profileBlock.getDuration()
+ " Profile: " + basalValue.value + " for " + Integer.toString(((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60));
if (profileBlock.getDuration() * 60 != (nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) return false;
if (profileBlock.getDuration() * 60 != (nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds)
return false;
//Allow a little imprecision due to rounding errors
if (Math.abs(profileBlock.getAmount() - Helpers.roundDouble(basalValue.value, 2)) >= 0.01D) return false;
if (Math.abs(profileBlock.getAmount() - Helpers.roundDouble(basalValue.value, 2)) >= 0.01D)
return false;
}
return true;
}
@ -516,9 +519,12 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints
final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
ActiveBolusesMessage activeBolusesMessage = (ActiveBolusesMessage) mstatus.getResponseObject();
ActiveBolus activeBolus = null;
if (activeBolusesMessage.getBolus1() != null && activeBolusesMessage.getBolus1().getBolusID() == bolusingEvent.bolusId) activeBolus = activeBolusesMessage.getBolus1();
else if (activeBolusesMessage.getBolus2() != null && activeBolusesMessage.getBolus2().getBolusID() == bolusingEvent.bolusId) activeBolus = activeBolusesMessage.getBolus2();
else if (activeBolusesMessage.getBolus3() != null && activeBolusesMessage.getBolus3().getBolusID() == bolusingEvent.bolusId) activeBolus = activeBolusesMessage.getBolus3();
if (activeBolusesMessage.getBolus1() != null && activeBolusesMessage.getBolus1().getBolusID() == bolusingEvent.bolusId)
activeBolus = activeBolusesMessage.getBolus1();
else if (activeBolusesMessage.getBolus2() != null && activeBolusesMessage.getBolus2().getBolusID() == bolusingEvent.bolusId)
activeBolus = activeBolusesMessage.getBolus2();
else if (activeBolusesMessage.getBolus3() != null && activeBolusesMessage.getBolus3().getBolusID() == bolusingEvent.bolusId)
activeBolus = activeBolusesMessage.getBolus3();
if (activeBolus == null) break;
else {
bolusingEvent.percent = (int) (100D / activeBolus.getInitialAmount() * (activeBolus.getInitialAmount() - activeBolus.getLeftoverAmount()));
@ -567,7 +573,6 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints
if (percent_amount > 250) percent_amount = 250;
final SetTBRTaskRunner task = new SetTBRTaskRunner(connector.getServiceConnector(), percent_amount, durationInMinutes);
final UUID cmd = aSyncTaskRunner(task, "Set TBR abs: " + absoluteRate + " " + durationInMinutes + "m");
@ -611,7 +616,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) {
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) {
log("Set TBR %");
percent = (int) Math.round(((double) percent) / 10d) * 10;
@ -1117,8 +1122,11 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints
}
@Override
public Integer applyBasalPercentConstraints(Integer percentRate) {
return Math.min(percentRate, pumpDescription.maxTempPercent);
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
percentRate.setIfGreater(0, String.format(MainApp.gs(R.string.limitingpercentrate), 0, MainApp.gs(R.string.basalmustbepositivevalue)));
percentRate.setIfSmaller(getPumpDescription().maxTempPercent, String.format(MainApp.gs(R.string.limitingpercentrate), getPumpDescription().maxTempPercent, MainApp.gs(R.string.pumplimit)));
return percentRate;
}
@Override

View file

@ -204,7 +204,7 @@ public class MDIPlugin implements PluginBase, PumpInterface {
}
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) {
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) {
PumpEnactResult result = new PumpEnactResult();
result.success = false;
result.comment = MainApp.instance().getString(R.string.pumperror);

View file

@ -313,7 +313,7 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface {
}
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) {
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) {
TreatmentsInterface treatmentsInterface = MainApp.getConfigBuilder();
PumpEnactResult result = new PumpEnactResult();
if (MainApp.getConfigBuilder().isTempBasalInProgress()) {

View file

@ -208,7 +208,7 @@ public class CommandQueue {
}
// returns true if command is queued
public boolean tempBasalPercent(int percent, int durationInMinutes, boolean enforceNew, Callback callback) {
public boolean tempBasalPercent(Integer percent, int durationInMinutes, boolean enforceNew, Profile profile, Callback callback) {
if (isRunning(Command.CommandType.TEMPBASAL)) {
if (callback != null)
callback.result(executingNowError()).run();
@ -218,10 +218,10 @@ public class CommandQueue {
// remove all unfinished
removeAll(Command.CommandType.TEMPBASAL);
Integer percentAfterConstraints = MainApp.getConstraintChecker().applyBasalPercentConstraints(percent);
Integer percentAfterConstraints = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(percent), profile).value();
// add new command to queue
add(new CommandTempBasalPercent(percentAfterConstraints, durationInMinutes, enforceNew, callback));
add(new CommandTempBasalPercent(percentAfterConstraints, durationInMinutes, enforceNew, profile, callback));
notifyAboutNewCommand();

View file

@ -4,6 +4,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.queue.Callback;
@ -18,18 +19,20 @@ public class CommandTempBasalPercent extends Command {
int durationInMinutes;
int percent;
boolean enforceNew;
Profile profile;
public CommandTempBasalPercent(int percent, int durationInMinutes, boolean enforceNew, Callback callback) {
public CommandTempBasalPercent(int percent, int durationInMinutes, boolean enforceNew, Profile profile, Callback callback) {
commandType = CommandType.TEMPBASAL;
this.percent = percent;
this.durationInMinutes = durationInMinutes;
this.enforceNew = enforceNew;
this.profile = profile;
this.callback = callback;
}
@Override
public void execute() {
PumpEnactResult r = ConfigBuilderPlugin.getActivePump().setTempBasalPercent(percent, durationInMinutes, enforceNew);
PumpEnactResult r = ConfigBuilderPlugin.getActivePump().setTempBasalPercent(percent, durationInMinutes, profile, enforceNew);
if (Config.logCongigBuilderActions)
log.debug("setTempBasalPercent percent: " + percent + " durationInMinutes: " + durationInMinutes + " success: " + r.success + " enacted: " + r.enacted);
if (callback != null)

View file

@ -978,5 +978,6 @@
<string name="key_openapsma_max_iob" translatable="false">openapsma_max_iob</string>
<string name="smb_frequency_exceeded">A bolus was delivered within the last 3 minutes, skipping SMB</string>
<string name="basal_set_correctly">Basal set correctly</string>
<string name="limitingpercentrate" formatted="false">Limiting percent rate to %d%% because of %s</string>
</resources>

View file

@ -38,5 +38,6 @@ public class ConstraintTest {
d.setIfSmaller(4d, "Set 4d");
Assert.assertEquals(4d, d.value());
Assert.assertEquals("Set 5d\nSet 6d\nSet 4d", d.getReasons());
Assert.assertEquals(10d, d.originalValue());
}
}

View file

@ -215,6 +215,48 @@ public class ConstraintsCheckerTest {
}
// applyBasalConstraints tests
@Test
public void percentBasalRateShouldBeLimited() throws Exception {
// DanaR, RS
danaRPlugin.setFragmentEnabled(PluginBase.PUMP, true);
danaRSPlugin.setFragmentEnabled(PluginBase.PUMP, true);
DanaRPump.getInstance().maxBasal = 0.8d;
// Insight
insightPlugin.setFragmentEnabled(PluginBase.PUMP, true);
StatusTaskRunner.Result result = new StatusTaskRunner.Result();
result.maximumBasalAmount = 1.1d;
insightPlugin.setStatusResult(result);
// No limit by default
when(SP.getDouble(R.string.key_openapsma_max_basal, 1d)).thenReturn(1d);
when(SP.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d)).thenReturn(4d);
when(SP.getDouble(R.string.key_openapsama_max_daily_safety_multiplier, 3d)).thenReturn(3d);
// Negative basal not allowed
Constraint<Integer> i = new Constraint<>(-22);
constraintChecker.applyBasalPercentConstraints(i, profile);
Assert.assertEquals((Integer)0, i.value());
Assert.assertEquals("Percent rate -22% recalculated to -0.22 U/h with current basal 1.00 U/h\n" + // SafetyPlugin
"Limiting percent rate to 0% because of pump limit\n" + // SafetyPlugin
"Limiting percent rate to 0% because of basal must be positive value\n" + // DanaRPlugin
"Limiting percent rate to 0% because of basal must be positive value\n" + // DanaRSPlugin
"Limiting percent rate to 0% because of basal must be positive value", i.getReasons()); // InsightPlugin
// Apply all limits
i = new Constraint<>(Constants.REALLYHIGHPERCENTBASALRATE);
constraintChecker.applyBasalPercentConstraints(i, profile);
Assert.assertEquals((Integer)100, i.value());
Assert.assertEquals("Percent rate 1111111% recalculated to 11111.11 U/h with current basal 1.00 U/h\n" + // SafetyPlugin
"Limiting percent rate to 100% because of pump limit\n" +
"Limiting percent rate to 200% because of pump limit\n" +
"Limiting percent rate to 200% because of pump limit\n" +
"Limiting percent rate to 250% because of pump limit", i.getReasons());
}
@Before
public void prepareMock() throws Exception {
Locale.setDefault(new Locale("en", "US"));
@ -247,6 +289,8 @@ public class ConstraintsCheckerTest {
when(MainApp.gs(R.string.maxbasalinpreferences)).thenReturn("max basal settings in preferences");
when(MainApp.gs(R.string.maxbasalmultiplier)).thenReturn("max basal multiplier");
when(MainApp.gs(R.string.maxdailybasalmultiplier)).thenReturn("max daily basal multiplier");
when(MainApp.gs(R.string.limitingpercentrate)).thenReturn("Limiting percent rate to %d%% because of %s");
when(MainApp.gs(R.string.pumplimit)).thenReturn("pump limit");
PowerMockito.mockStatic(SP.class);
// RS constructor

View file

@ -73,7 +73,7 @@ public class CommandQueueTest extends CommandQueue {
Assert.assertEquals(1, size());
// add tempbasal percent. it should replace previous TEMPBASAL
tempBasalPercent(0, 30, true, null);
tempBasalPercent(0, 30, true, profile, null);
Assert.assertEquals(1, size());
// add extended bolus
@ -129,6 +129,8 @@ public class CommandQueueTest extends CommandQueue {
when(MainApp.getConstraintChecker().applyCarbsConstraints(carbs)).thenReturn(carbs);
Constraint<Double> rateConstraint = new Constraint<>(0d);
when(MainApp.getConstraintChecker().applyBasalConstraints(any(), any())).thenReturn(rateConstraint);
Constraint<Integer> percentageConstraint = new Constraint<>(0);
when(MainApp.getConstraintChecker().applyBasalPercentConstraints(any(), any())).thenReturn(percentageConstraint);
PowerMockito.mockStatic(ToastUtils.class);
Context context = mock(Context.class);