applyBasalConstraints reactor & tests

This commit is contained in:
Milos Kozak 2018-03-20 22:09:22 +01:00
parent c2cfe4e7ea
commit 15ebfc1193
40 changed files with 353 additions and 205 deletions

View file

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

View file

@ -29,7 +29,6 @@ import info.nightscout.androidaps.data.ConstraintChecker;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.plugins.Actions.ActionsFragment;
import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
@ -201,7 +200,7 @@ public class MainApp extends Application {
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-G5Uploader"));
else if (Config.PUMPCONTROL)
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-PumpControl"));
else if (MainApp.getConstraintChecker().isClosedLoopAllowed().get())
else if (MainApp.getConstraintChecker().isClosedLoopAllowed().value())
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-ClosedLoop"));
else
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-OpenLoop"));

View file

@ -6,7 +6,6 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.utils.SP;
/**
* Created by mike on 19.03.2018.
@ -102,25 +101,24 @@ public class ConstraintChecker implements ConstraintsInterface {
}
@Override
public Double applyBasalConstraints(Double absoluteRate) {
Double rateAfterConstrain = absoluteRate;
public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) {
ArrayList<PluginBase> constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constrain = (ConstraintsInterface) p;
ConstraintsInterface constraint = (ConstraintsInterface) p;
if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue;
rateAfterConstrain = Math.min(constrain.applyBasalConstraints(absoluteRate), rateAfterConstrain);
constraint.applyBasalConstraints(absoluteRate, profile);
}
return rateAfterConstrain;
return absoluteRate;
}
@Override
public Integer applyBasalConstraints(Integer percentRate) {
public Integer applyBasalPercentConstraints(Integer percentRate) {
Integer rateAfterConstrain = percentRate;
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.applyBasalConstraints(percentRate), rateAfterConstrain);
rateAfterConstrain = Math.min(constrain.applyBasalPercentConstraints(percentRate), rateAfterConstrain);
}
return rateAfterConstrain;
}

View file

@ -1,5 +1,8 @@
package info.nightscout.androidaps.interfaces;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@ -7,20 +10,30 @@ import java.util.List;
* Created by mike on 19.03.2018.
*/
public class Constraint<T> {
public class Constraint<T extends Comparable> {
private static Logger log = LoggerFactory.getLogger(Constraint.class);
T value;
T originalValue;
List<String> reasons = new ArrayList<>();
public Constraint(T value) {
this.value = value;
this.originalValue = value;
}
public T get() {
public T value() {
return value;
}
public T originalValue() {
return originalValue;
}
public Constraint<T> set(T value) {
this.value = value;
this.originalValue = value;
return this;
}
@ -30,6 +43,26 @@ public class Constraint<T> {
return this;
}
public Constraint<T> setIfSmaller(T value, String reason) {
if (value.compareTo(this.value) < 0) {
this.value = value;
}
if (value.compareTo(this.originalValue) < 0) {
reason(reason);
}
return this;
}
public Constraint<T> setIfGreater(T value, String reason) {
if (value.compareTo(this.value) > 0) {
this.value = value;
}
if (value.compareTo(this.originalValue) > 0) {
reason(reason);
}
return this;
}
public Constraint reason(String reason) {
reasons.add(reason);
return this;
@ -42,6 +75,8 @@ public class Constraint<T> {
if (count++ != 0) sb.append("\n");
sb.append(r);
}
log.debug("Limiting origial value: " + originalValue + " to " + value + ". Reason: " + sb.toString());
return sb.toString();
}
}

View file

@ -1,5 +1,7 @@
package info.nightscout.androidaps.interfaces;
import info.nightscout.androidaps.data.Profile;
/**
* Created by mike on 15.06.2016.
*/
@ -15,9 +17,9 @@ public interface ConstraintsInterface {
Constraint<Boolean> isSMBModeEnabled(Constraint<Boolean> value);
Double applyBasalConstraints(Double absoluteRate);
Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile);
Integer applyBasalConstraints(Integer percentRate);
Integer applyBasalPercentConstraints(Integer percentRate);
Double applyBolusConstraints(Double insulin);

View file

@ -35,7 +35,7 @@ public interface PumpInterface {
PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo);
void stopBolusDelivering();
PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew);
PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew);
PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, 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

View file

@ -22,6 +22,7 @@ import java.text.DecimalFormat;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
@ -117,17 +118,21 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
final boolean setAsPercent = percentRadio.isChecked();
int durationInMinutes = SafeParse.stringToInt(duration.getText());
Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null)
return;
String confirmMessage = getString(R.string.setbasalquestion);
if (setAsPercent) {
int basalPercentInput = SafeParse.stringToInt(basalPercent.getText());
percent = MainApp.getConstraintChecker().applyBasalConstraints(basalPercentInput);
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(basalPercentInput);
confirmMessage += "\n" + percent + "% ";
confirmMessage += "\n" + getString(R.string.duration) + " " + durationInMinutes + "min ?";
if (percent != basalPercentInput)
confirmMessage += "\n" + getString(R.string.constraintapllied);
} else {
Double basalAbsoluteInput = SafeParse.stringToDouble(basalAbsolute.getText());
absolute = MainApp.getConstraintChecker().applyBasalConstraints(basalAbsoluteInput);
absolute = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(basalAbsoluteInput), profile).value();
confirmMessage += "\n" + absolute + " U/h ";
confirmMessage += "\n" + getString(R.string.duration) + " " + durationInMinutes + "min ?";
if (absolute - basalAbsoluteInput != 0d)
@ -159,7 +164,7 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
if (setAsPercent) {
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(finalBasalPercent, finalDurationInMinutes, true, callback);
} else {
ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(finalBasal, finalDurationInMinutes, true, callback);
ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(finalBasal, finalDurationInMinutes, true, profile, callback);
}
FabricPrivacy.getInstance().logCustom(new CustomEvent("TempBasal"));
}

View file

@ -51,6 +51,7 @@ import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
@ -302,7 +303,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
}
};
Integer maxPercent = MainApp.getConstraintChecker().applyBasalConstraints(Constants.basalPercentOnlyForCheckLimit);
Integer maxPercent = MainApp.getConstraintChecker().applyBasalPercentConstraints(Constants.basalPercentOnlyForCheckLimit);
editPercent = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_percentinput);
editPercent.setParams(0d, 0d, (double) maxPercent, 5d, new DecimalFormat("0"), true, percentTextWatcher);
@ -324,7 +325,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
}
};
Double maxAbsolute = MainApp.getConstraintChecker().applyBasalConstraints(Constants.basalAbsoluteOnlyForCheckLimit);
Double maxAbsolute = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(Constants.REALLYHIGHBASALRATE), profile).value();
editAbsolute = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_absoluteinput);
editAbsolute.setParams(0d, 0d, maxAbsolute, 0.05d, new DecimalFormat("0.00"), true, absoluteTextWatcher);

View file

@ -31,6 +31,7 @@ import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventAppInitialized;
import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.BgSourceInterface;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.ProfileInterface;
@ -351,7 +352,9 @@ public class ConfigBuilderPlugin implements PluginBase, TreatmentsInterface {
*/
public void applyTBRRequest(APSResult request, Profile profile, Callback callback) {
PumpInterface pump = getActivePump();
request.rate = MainApp.getConstraintChecker().applyBasalConstraints(request.rate);
request.rateConstraint = new Constraint<>(request.rate);
request.rate = MainApp.getConstraintChecker().applyBasalConstraints(request.rateConstraint, profile).value();
long now = System.currentTimeMillis();
@ -399,7 +402,7 @@ public class ConfigBuilderPlugin implements PluginBase, TreatmentsInterface {
} else {
if (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: setTempBasalAbsolute()");
getCommandQueue().tempBasalAbsolute(request.rate, request.duration, false, callback);
getCommandQueue().tempBasalAbsolute(request.rate, request.duration, false, profile, callback);
}
}
}

View file

@ -13,6 +13,7 @@ import java.util.List;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.Constraint;
@ -189,7 +190,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
case 3:
Constraint<Boolean> closedLoopEnabled = new Constraint<>(true);
SafetyPlugin.getPlugin().isClosedLoopAllowed(closedLoopEnabled);
return new RequirementResult(closedLoopEnabled.get(), MainApp.gs(R.string.closedmodeenabled) + ": " + yesOrNo(closedLoopEnabled.get()));
return new RequirementResult(closedLoopEnabled.value(), MainApp.gs(R.string.closedmodeenabled) + ": " + yesOrNo(closedLoopEnabled.value()));
case 4:
double maxIOB = MainApp.getConstraintChecker().applyMaxIOBConstraints(1000d);
boolean maxIobSet = maxIOB > 0;
@ -345,12 +346,12 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
}
@Override
public Double applyBasalConstraints(Double absoluteRate) {
public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) {
return absoluteRate;
}
@Override
public Integer applyBasalConstraints(Integer percentRate) {
public Integer applyBasalPercentConstraints(Integer percentRate) {
return percentRate;
}

View file

@ -135,40 +135,28 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
}
@Override
public Double applyBasalConstraints(Double absoluteRate) {
Double origAbsoluteRate = absoluteRate;
Double maxBasal = SP.getDouble("openapsma_max_basal", 1d);
public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) {
Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null) return absoluteRate;
if (absoluteRate < 0) absoluteRate = 0d;
absoluteRate.setIfGreater(0d, String.format(MainApp.gs(R.string.limitingbasalratio), 0d, MainApp.gs(R.string.basalmustbepositivevalue)));
double maxBasal = SP.getDouble(R.string.key_openapsma_max_basal, 1d);
absoluteRate.setIfSmaller(maxBasal, String.format(MainApp.gs(R.string.limitingbasalratio), maxBasal, MainApp.gs(R.string.maxbasalinpreferences)));
Double maxBasalMult = SP.getDouble("openapsama_current_basal_safety_multiplier", 4d);
Integer maxBasalFromDaily = SP.getInt("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 && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
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 && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
log.debug("Limiting rate " + origRate + " by maxBasalMult to " + absoluteRate + "U/h");
}
if (absoluteRate > profile.getMaxDailyBasal() * maxBasalFromDaily) {
absoluteRate = profile.getMaxDailyBasal() * maxBasalFromDaily;
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
log.debug("Limiting rate " + origRate + " by 3 * maxDailyBasal to " + absoluteRate + "U/h");
}
Double maxBasalMult = SP.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d);
double maxFromBasalMult = Math.floor(maxBasalMult * profile.getBasal() * 100) / 100;
absoluteRate.setIfSmaller(maxFromBasalMult, String.format(MainApp.gs(R.string.limitingbasalratio), maxFromBasalMult, MainApp.gs(R.string.maxbasalmultiplier)));
Double maxBasalFromDaily = SP.getDouble(R.string.key_openapsama_max_daily_safety_multiplier, 3d);
double maxFromDaily = Math.floor(profile.getMaxDailyBasal() * maxBasalFromDaily * 100) / 100;
absoluteRate.setIfSmaller(maxFromDaily, String.format(MainApp.gs(R.string.limitingbasalratio), maxFromDaily, MainApp.gs(R.string.maxdailybasalmultiplier)));
return absoluteRate;
}
@Override
public Integer applyBasalConstraints(Integer percentRate) {
public Integer applyBasalPercentConstraints(Integer percentRate) {
Integer origPercentRate = percentRate;
Double maxBasal = SP.getDouble("openapsma_max_basal", 1d);
Double maxBasal = SP.getDouble(R.string.key_openapsma_max_basal, 1d);
Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null) return percentRate;
@ -181,8 +169,8 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
if (absoluteRate < 0) absoluteRate = 0d;
Double maxBasalMult = SP.getDouble("openapsama_current_basal_safety_multiplier", 4d);
Integer maxBasalFromDaily = SP.getInt("openapsama_max_daily_safety_multiplier", 3);
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) {

View file

@ -17,6 +17,7 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.DecimalFormatter;
@ -39,6 +40,9 @@ public class APSResult {
public double smb = 0d; // super micro bolus in units
public long deliverAt = 0;
public Constraint<Double> rateConstraint;
public Constraint<Double> smbConstraint;
@Override
public String toString() {
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
@ -101,6 +105,12 @@ public class APSResult {
newResult.tempBasalReqested = tempBasalReqested;
newResult.bolusRequested = bolusRequested;
newResult.iob = iob;
newResult.json = json;
newResult.hasPredictions = hasPredictions;
newResult.smb = smb;
newResult.deliverAt = deliverAt;
newResult.rateConstraint = rateConstraint;
newResult.smbConstraint = smbConstraint;
return newResult;
}

View file

@ -261,7 +261,7 @@ public class LoopPlugin implements PluginBase {
log.debug("invoke from " + initiator);
Constraint<Boolean> loopEnabled = MainApp.getConstraintChecker().isLoopInvokationAllowed();
if (!loopEnabled.get()) {
if (!loopEnabled.value()) {
String message = MainApp.sResources.getString(R.string.loopdisabled) + "\n" + loopEnabled.getReasons();
log.debug(message);
MainApp.bus().post(new EventLoopSetLastRunGui(message));
@ -298,7 +298,8 @@ public class LoopPlugin implements PluginBase {
// check rate for constrais
final APSResult resultAfterConstraints = result.clone();
resultAfterConstraints.rate = MainApp.getConstraintChecker().applyBasalConstraints(resultAfterConstraints.rate);
resultAfterConstraints.rateConstraint = new Constraint<>(resultAfterConstraints.rate);
resultAfterConstraints.rate = MainApp.getConstraintChecker().applyBasalConstraints(resultAfterConstraints.rateConstraint, profile).value();
resultAfterConstraints.smb = MainApp.getConstraintChecker().applyBolusConstraints(resultAfterConstraints.smb);
// safety check for multiple SMBs
@ -332,7 +333,7 @@ public class LoopPlugin implements PluginBase {
Constraint<Boolean> closedLoopEnabled = MainApp.getConstraintChecker().isClosedLoopAllowed();
if (closedLoopEnabled.get()) {
if (closedLoopEnabled.value()) {
if (result.isChangeRequested()) {
final PumpEnactResult waiting = new PumpEnactResult();
waiting.queued = true;

View file

@ -21,6 +21,7 @@ import java.lang.reflect.InvocationTargetException;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData;
@ -205,8 +206,8 @@ public class DetermineBasalAdapterAMAJS {
mProfile.put("target_bg", targetBg);
mProfile.put("carb_ratio", profile.getIc());
mProfile.put("sens", Profile.toMgdl(profile.getIsf(), units));
mProfile.put("max_daily_safety_multiplier", SP.getInt("openapsama_max_daily_safety_multiplier", 3));
mProfile.put("current_basal_safety_multiplier", SP.getDouble("openapsama_current_basal_safety_multiplier", 4d));
mProfile.put("max_daily_safety_multiplier", SP.getInt(R.string.key_openapsama_max_daily_safety_multiplier, 3));
mProfile.put("current_basal_safety_multiplier", SP.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d));
mProfile.put("skip_neutral_temps", true);
mProfile.put("current_basal", basalrate);
mProfile.put("temptargetSet", tempTargetSet);
@ -250,7 +251,7 @@ public class DetermineBasalAdapterAMAJS {
mMealData.put("boluses", mealData.boluses);
mMealData.put("mealCOB", mealData.mealCOB);
if (MainApp.getConstraintChecker().isAMAModeEnabled().get()) {
if (MainApp.getConstraintChecker().isAMAModeEnabled().value()) {
mAutosensData = new JSONObject();
mAutosensData.put("ratio", autosensDataRatio);
} else {

View file

@ -19,7 +19,6 @@ import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
@ -174,8 +173,8 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
String units = profile.getUnits();
double maxIob = SP.getDouble("openapsma_max_iob", 1.5d);
double maxBasal = SP.getDouble("openapsma_max_basal", 1d);
double maxIob = SP.getDouble(R.string.key_openapsma_max_iob, 1.5d);
double maxBasal = SP.getDouble(R.string.key_openapsma_max_basal, 1d);
double minBg = Profile.toMgdl(profile.getTargetLow(), units);
double maxBg = Profile.toMgdl(profile.getTargetHigh(), units);
double targetBg = Profile.toMgdl(profile.getTarget(), units);
@ -223,7 +222,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
return;
startPart = new Date();
if (MainApp.getConstraintChecker().isAMAModeEnabled().get()) {
if (MainApp.getConstraintChecker().isAMAModeEnabled().value()) {
lastAutosensResult = IobCobCalculatorPlugin.getPlugin().detectSensitivityWithLock(IobCobCalculatorPlugin.oldestDataAvailable(), System.currentTimeMillis());
} else {
lastAutosensResult = new AutosensResult();
@ -249,7 +248,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
determineBasalResultAMA.tempBasalReqested = false;
// limit requests on openloop mode
if (!MainApp.getConstraintChecker().isClosedLoopAllowed().get()) {
if (!MainApp.getConstraintChecker().isClosedLoopAllowed().value()) {
long now = System.currentTimeMillis();
TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(now);
if (activeTemp != null && determineBasalResultAMA.rate == 0 && determineBasalResultAMA.duration == 0) {

View file

@ -19,7 +19,6 @@ import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
@ -30,7 +29,6 @@ import info.nightscout.utils.HardLimits;
import info.nightscout.utils.Profiler;
import info.nightscout.utils.Round;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
import static info.nightscout.utils.HardLimits.checkOnlyHardLimits;
import static info.nightscout.utils.HardLimits.verifyHardLimits;
@ -175,8 +173,8 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
String units = profile.getUnits();
double maxIob = SP.getDouble("openapsma_max_iob", 1.5d);
double maxBasal = SafeParse.stringToDouble(SP.getString("openapsma_max_basal", "1"));
double maxIob = SP.getDouble(R.string.key_openapsma_max_iob, 1.5d);
double maxBasal = SP.getDouble(R.string.key_openapsma_max_basal, 1d);
double minBg = Profile.toMgdl(profile.getTargetLow(), units);
double maxBg = Profile.toMgdl(profile.getTargetHigh(), units);
double targetBg = Profile.toMgdl(profile.getTarget(), units);
@ -238,7 +236,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
if (determineBasalResultMA.rate == 0d && determineBasalResultMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
determineBasalResultMA.tempBasalReqested = false;
// limit requests on openloop mode
if (!MainApp.getConstraintChecker().isClosedLoopAllowed().get()) {
if (!MainApp.getConstraintChecker().isClosedLoopAllowed().value()) {
TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(now);
if (activeTemp != null && determineBasalResultMA.rate == 0 && determineBasalResultMA.duration == 0) {
// going to cancel

View file

@ -27,7 +27,6 @@ import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
@ -228,8 +227,8 @@ public class DetermineBasalAdapterSMBJS {
mProfile.put("target_bg", targetBg);
mProfile.put("carb_ratio", profile.getIc());
mProfile.put("sens", Profile.toMgdl(profile.getIsf(), units));
mProfile.put("max_daily_safety_multiplier", SP.getInt("openapsama_max_daily_safety_multiplier", 3));
mProfile.put("current_basal_safety_multiplier", SP.getDouble("openapsama_current_basal_safety_multiplier", 4d));
mProfile.put("max_daily_safety_multiplier", SP.getInt(R.string.key_openapsama_max_daily_safety_multiplier, 3));
mProfile.put("current_basal_safety_multiplier", SP.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d));
mProfile.put("high_temptarget_raises_sensitivity", SMBDefaults.high_temptarget_raises_sensitivity);
mProfile.put("low_temptarget_lowers_sensitivity", SMBDefaults.low_temptarget_lowers_sensitivity);
@ -245,7 +244,7 @@ public class DetermineBasalAdapterSMBJS {
mProfile.put("remainingCarbsCap", SMBDefaults.remainingCarbsCap);
mProfile.put("enableUAM", SP.getBoolean(R.string.key_use_uam, false));
mProfile.put("A52_risk_enable", SMBDefaults.A52_risk_enable);
boolean SMBEnabled = MainApp.getConstraintChecker().isSMBModeEnabled().get() && MainApp.getConstraintChecker().isClosedLoopAllowed().get();
boolean SMBEnabled = MainApp.getConstraintChecker().isSMBModeEnabled().value() && MainApp.getConstraintChecker().isClosedLoopAllowed().value();
mProfile.put("enableSMB_with_COB", SMBEnabled && SP.getBoolean(R.string.key_enableSMB_with_COB, false));
mProfile.put("enableSMB_with_temptarget", SMBEnabled && SP.getBoolean(R.string.key_enableSMB_with_temptarget, false));
mProfile.put("allowSMB_with_high_temptarget", SMBEnabled && SP.getBoolean(R.string.key_allowSMB_with_high_temptarget, false));
@ -301,7 +300,7 @@ public class DetermineBasalAdapterSMBJS {
mMealData.put("lastCarbTime", mealData.lastCarbTime);
if (MainApp.getConstraintChecker().isAMAModeEnabled().get()) {
if (MainApp.getConstraintChecker().isAMAModeEnabled().value()) {
mAutosensData = new JSONObject();
mAutosensData.put("ratio", autosensDataRatio);
} else {

View file

@ -19,7 +19,6 @@ import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
@ -179,8 +178,8 @@ public class OpenAPSSMBPlugin implements PluginBase, APSInterface {
String units = profile.getUnits();
double maxIob = SP.getDouble("openapsma_max_iob", 1.5d);
double maxBasal = SP.getDouble("openapsma_max_basal", 1d);
double maxIob = SP.getDouble(R.string.key_openapsma_max_iob, 1.5d);
double maxBasal = SP.getDouble(R.string.key_openapsma_max_basal, 1d);
double minBg = Profile.toMgdl(profile.getTargetLow(), units);
double maxBg = Profile.toMgdl(profile.getTargetHigh(), units);
double targetBg = Profile.toMgdl(profile.getTarget(), units);
@ -225,7 +224,7 @@ public class OpenAPSSMBPlugin implements PluginBase, APSInterface {
if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, HardLimits.maxBasal())) return;
startPart = new Date();
if (MainApp.getConstraintChecker().isAMAModeEnabled().get()) {
if (MainApp.getConstraintChecker().isAMAModeEnabled().value()) {
lastAutosensResult = IobCobCalculatorPlugin.getPlugin().detectSensitivityWithLock(IobCobCalculatorPlugin.oldestDataAvailable(), System.currentTimeMillis());
} else {
lastAutosensResult = new AutosensResult();
@ -254,7 +253,7 @@ public class OpenAPSSMBPlugin implements PluginBase, APSInterface {
if (determineBasalResultSMB.rate == 0d && determineBasalResultSMB.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
determineBasalResultSMB.tempBasalReqested = false;
// limit requests on openloop mode
if (!MainApp.getConstraintChecker().isClosedLoopAllowed().get()) {
if (!MainApp.getConstraintChecker().isClosedLoopAllowed().value()) {
TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(now);
if (activeTemp != null && determineBasalResultSMB.rate == 0 && determineBasalResultSMB.duration == 0) {
// going to cancel

View file

@ -1039,7 +1039,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
apsModeView.setText(MainApp.sResources.getString(R.string.pumpsuspended));
apsModeView.setTextColor(Color.WHITE);
} else if (activeloop != null && activeloop.isEnabled(activeloop.getType())) {
if (closedLoopEnabled.get()) {
if (closedLoopEnabled.value()) {
apsModeView.setText(MainApp.sResources.getString(R.string.closedloop));
} else {
apsModeView.setText(MainApp.sResources.getString(R.string.openloop));
@ -1069,7 +1069,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
// **** Temp button ****
if (acceptTempLayout != null) {
boolean showAcceptButton = !closedLoopEnabled.get(); // Open mode needed
boolean showAcceptButton = !closedLoopEnabled.value(); // Open mode needed
showAcceptButton = showAcceptButton && finalLastRun != null && finalLastRun.lastAPSRun != null; // aps result must exist
showAcceptButton = showAcceptButton && (finalLastRun.lastOpenModeAccept == null || finalLastRun.lastOpenModeAccept.getTime() < finalLastRun.lastAPSRun.getTime()); // never accepted or before last result
showAcceptButton = showAcceptButton && finalLastRun.constraintsProcessed.isChangeRequested(); // change is requested

View file

@ -746,7 +746,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
* the new value (and thus still has the old duration of e.g. 1 min) expires?)
*/
@Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force) {
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean force) {
log.debug("setTempBasalAbsolute called with a rate of " + absoluteRate + " for " + durationInMinutes + " min.");
int unroundedPercentage = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue();
int roundedPercentage = (int) (Math.round(absoluteRate / getBaseBasalRate() * 10) * 10);
@ -1453,12 +1453,12 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
}
@Override
public Double applyBasalConstraints(Double absoluteRate) {
public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) {
return absoluteRate;
}
@Override
public Integer applyBasalConstraints(Integer percentRate) {
public Integer applyBasalPercentConstraints(Integer percentRate) {
return percentRate;
}

View file

@ -216,7 +216,7 @@ public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface,
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) {
PumpEnactResult result = new PumpEnactResult();
percent = MainApp.getConstraintChecker().applyBasalConstraints(percent);
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(percent);
if (percent < 0) {
result.isTempCancel = false;
result.enacted = false;
@ -458,23 +458,16 @@ public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface,
return value;
}
@SuppressWarnings("PointlessBooleanExpression")
@Override
public Double applyBasalConstraints(Double absoluteRate) {
double origAbsoluteRate = absoluteRate;
if (pump != null) {
if (absoluteRate > pump.maxBasal) {
absoluteRate = pump.maxBasal;
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h");
}
}
public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) {
if (pump != null)
absoluteRate.setIfSmaller(pump.maxBasal, String.format(MainApp.gs(R.string.limitingbasalratio), pump.maxBasal, MainApp.gs(R.string.pumplimit)));
return absoluteRate;
}
@SuppressWarnings("PointlessBooleanExpression")
@Override
public Integer applyBasalConstraints(Integer percentRate) {
public Integer applyBasalPercentConstraints(Integer percentRate) {
Integer origPercentRate = percentRate;
if (percentRate < 0) percentRate = 0;
if (percentRate > getPumpDescription().maxTempPercent)

View file

@ -14,12 +14,14 @@ import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService;
import info.nightscout.utils.Round;
@ -160,7 +162,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
// This is called from APS
@Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) {
// Recheck pump status if older than 30 min
//This should not be needed while using queue because connection should be done before calling this
//if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) {
@ -169,7 +171,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
PumpEnactResult result = new PumpEnactResult();
absoluteRate = MainApp.getConstraintChecker().applyBasalConstraints(absoluteRate);
absoluteRate = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(absoluteRate), profile).value();
final boolean doTempOff = getBaseBasalRate() - absoluteRate == 0d;
final boolean doLowTemp = absoluteRate < getBaseBasalRate();
@ -266,7 +268,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
Integer durationInHalfHours = Math.max(durationInMinutes / 30, 1);
// We keep current basal running so need to sub current basal
Double extendedRateToSet = absoluteRate - getBaseBasalRate();
extendedRateToSet = MainApp.getConstraintChecker().applyBasalConstraints(extendedRateToSet);
extendedRateToSet = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(extendedRateToSet), profile).value();
// needs to be rounded to 0.1
extendedRateToSet = Round.roundTo(extendedRateToSet, pumpDescription.extendedBolusStep * 2); // *2 because of halfhours

View file

@ -14,12 +14,14 @@ import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.plugins.PumpDanaR.AbstractDanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.services.DanaRKoreanExecutionService;
@ -161,7 +163,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
// This is called from APS
@Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) {
// Recheck pump status if older than 30 min
//This should not be needed while using queue because connection should be done before calling this
//if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) {
@ -170,7 +172,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
PumpEnactResult result = new PumpEnactResult();
absoluteRate = MainApp.getConstraintChecker().applyBasalConstraints(absoluteRate);
absoluteRate = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(absoluteRate), profile).value();
final boolean doTempOff = getBaseBasalRate() - absoluteRate == 0d;
final boolean doLowTemp = absoluteRate < getBaseBasalRate();
@ -267,7 +269,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
Integer durationInHalfHours = Math.max(durationInMinutes / 30, 1);
// We keep current basal running so need to sub current basal
Double extendedRateToSet = absoluteRate - getBaseBasalRate();
extendedRateToSet = MainApp.getConstraintChecker().applyBasalConstraints(extendedRateToSet);
extendedRateToSet = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(extendedRateToSet), profile).value();
// needs to be rounded to 0.1
extendedRateToSet = Round.roundTo(extendedRateToSet, pumpDescription.extendedBolusStep * 2); // *2 because of halfhours

View file

@ -299,20 +299,14 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface,
}
@Override
public Double applyBasalConstraints(Double absoluteRate) {
double origAbsoluteRate = absoluteRate;
if (pump != null) {
if (absoluteRate > pump.maxBasal) {
absoluteRate = pump.maxBasal;
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h");
}
}
public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) {
if (pump != null)
absoluteRate.setIfSmaller(pump.maxBasal, String.format(MainApp.gs(R.string.limitingbasalratio), pump.maxBasal, MainApp.gs(R.string.pumplimit)));
return absoluteRate;
}
@Override
public Integer applyBasalConstraints(Integer percentRate) {
public Integer applyBasalPercentConstraints(Integer percentRate) {
Integer origPercentRate = percentRate;
if (percentRate < 0) percentRate = 0;
if (percentRate > getPumpDescription().maxTempPercent)
@ -512,7 +506,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface,
// This is called from APS
@Override
public synchronized PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
public synchronized PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) {
// Recheck pump status if older than 30 min
//This should not be needed while using queue because connection should be done before calling this
@ -522,7 +516,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface,
PumpEnactResult result = new PumpEnactResult();
absoluteRate = MainApp.getConstraintChecker().applyBasalConstraints(absoluteRate);
absoluteRate = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(absoluteRate), profile).value();
final boolean doTempOff = getBaseBasalRate() - absoluteRate == 0d;
final boolean doLowTemp = absoluteRate < getBaseBasalRate();
@ -594,7 +588,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface,
@Override
public synchronized PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) {
PumpEnactResult result = new PumpEnactResult();
percent = MainApp.getConstraintChecker().applyBasalConstraints(percent);
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(percent);
if (percent < 0) {
result.isTempCancel = false;
result.enacted = false;

View file

@ -14,10 +14,12 @@ import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage;
import info.nightscout.androidaps.plugins.PumpDanaR.AbstractDanaRPlugin;
@ -183,7 +185,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
// This is called from APS
@Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) {
// Recheck pump status if older than 30 min
//This should not be needed while using queue because connection should be done before calling this
//if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) {
@ -192,7 +194,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
PumpEnactResult result = new PumpEnactResult();
absoluteRate = MainApp.getConstraintChecker().applyBasalConstraints(absoluteRate);
absoluteRate = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(absoluteRate), profile).value();
final boolean doTempOff = getBaseBasalRate() - absoluteRate == 0d;
final boolean doLowTemp = absoluteRate < getBaseBasalRate();
@ -262,7 +264,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) {
PumpEnactResult result = new PumpEnactResult();
percent = MainApp.getConstraintChecker().applyBasalConstraints(percent);
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(percent);
if (percent < 0) {
result.isTempCancel = false;
result.enacted = false;

View file

@ -355,7 +355,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints
Mstatus mstatus = async.busyWaitForCommandResult(uuid, BUSY_WAIT_TIME);
if (mstatus.success()) {
log("GOT STATUS RESULT!!! PARTY WOOHOO!!!");
statusResult = (StatusTaskRunner.Result) mstatus.getResponseObject();
setStatusResult((StatusTaskRunner.Result) mstatus.getResponseObject());
statusResultTime = Helpers.tsl();
processStatusResult();
updateGui();
@ -375,6 +375,10 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints
}
}
public void setStatusResult(StatusTaskRunner.Result result) {
this.statusResult = result;
}
@Override
public PumpEnactResult setNewBasalProfile(Profile profile) {
PumpEnactResult result = new PumpEnactResult();
@ -543,7 +547,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints
// Temporary Basals
@Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) {
absoluteRate = Helpers.roundDouble(absoluteRate, 3);
log("Set TBR absolute: " + absoluteRate);
final double base_basal = getBaseBasalRate();
@ -1105,12 +1109,15 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints
}
@Override
public Double applyBasalConstraints(Double absoluteRate) {
return Math.min(absoluteRate, statusResult != null ? statusResult.maximumBasalAmount : 0);
public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) {
if (statusResult != null) {
absoluteRate.setIfSmaller(statusResult.maximumBasalAmount, String.format(MainApp.gs(R.string.limitingbasalratio), statusResult.maximumBasalAmount, MainApp.gs(R.string.pumplimit)));
}
return absoluteRate;
}
@Override
public Integer applyBasalConstraints(Integer percentRate) {
public Integer applyBasalPercentConstraints(Integer percentRate) {
return Math.min(percentRate, pumpDescription.maxTempPercent);
}

View file

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

View file

@ -289,7 +289,7 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface {
}
@Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) {
TreatmentsInterface treatmentsInterface = MainApp.getConfigBuilder();
TemporaryBasal tempBasal = new TemporaryBasal();
tempBasal.date = System.currentTimeMillis();

View file

@ -29,6 +29,7 @@ import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
@ -418,7 +419,12 @@ public class SmsCommunicatorPlugin implements PluginBase {
}
} else {
tempBasal = SafeParse.stringToDouble(splited[1]);
tempBasal = MainApp.getConstraintChecker().applyBasalConstraints(tempBasal);
Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null) {
reply = MainApp.sResources.getString(R.string.noprofile);
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
} else {
tempBasal = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(tempBasal), profile).value();
if (remoteCommandsAllowed) {
passCode = generatePasscode();
reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_basalreplywithcode), tempBasal, passCode);
@ -433,6 +439,7 @@ public class SmsCommunicatorPlugin implements PluginBase {
}
}
}
}
break;
case "BOLUS":
if (System.currentTimeMillis() - lastRemoteBolusTime.getTime() < Constants.remoteBolusMinDistance) {
@ -503,7 +510,9 @@ public class SmsCommunicatorPlugin implements PluginBase {
} else if (tempBasalWaitingForConfirmation != null && !tempBasalWaitingForConfirmation.processed &&
tempBasalWaitingForConfirmation.confirmCode.equals(splited[0]) && System.currentTimeMillis() - tempBasalWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) {
tempBasalWaitingForConfirmation.processed = true;
ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(tempBasalWaitingForConfirmation.tempBasal, 30, true, new Callback() {
Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile != null)
ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(tempBasalWaitingForConfirmation.tempBasal, 30, true, profile, new Callback() {
@Override
public void run() {
if (result.success) {

View file

@ -27,7 +27,6 @@ import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.plugins.Actions.dialogs.FillDialog;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
@ -435,7 +434,7 @@ public class ActionStringHandler {
// decide if enabled/disabled closed/open; what Plugin as APS?
final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop();
if (activeloop != null && activeloop.isEnabled(activeloop.getType())) {
if (MainApp.getConstraintChecker().isClosedLoopAllowed().get()) {
if (MainApp.getConstraintChecker().isClosedLoopAllowed().value()) {
ret += "CLOSED LOOP\n";
} else {
ret += "OPEN LOOP\n";

View file

@ -18,6 +18,7 @@ import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.events.EventBolusRequested;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog;
@ -186,7 +187,7 @@ public class CommandQueue {
}
// returns true if command is queued
public boolean tempBasalAbsolute(double absoluteRate, int durationInMinutes, boolean enforceNew, Callback callback) {
public boolean tempBasalAbsolute(double absoluteRate, int durationInMinutes, boolean enforceNew, Profile profile, Callback callback) {
if (isRunning(Command.CommandType.TEMPBASAL)) {
if (callback != null)
callback.result(executingNowError()).run();
@ -196,10 +197,10 @@ public class CommandQueue {
// remove all unfinished
removeAll(Command.CommandType.TEMPBASAL);
Double rateAfterConstraints = MainApp.getConstraintChecker().applyBasalConstraints(absoluteRate);
Double rateAfterConstraints = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(absoluteRate), profile).value();
// add new command to queue
add(new CommandTempBasalAbsolute(rateAfterConstraints, durationInMinutes, enforceNew, callback));
add(new CommandTempBasalAbsolute(rateAfterConstraints, durationInMinutes, enforceNew, profile, callback));
notifyAboutNewCommand();
@ -217,7 +218,7 @@ public class CommandQueue {
// remove all unfinished
removeAll(Command.CommandType.TEMPBASAL);
Integer percentAfterConstraints = MainApp.getConstraintChecker().applyBasalConstraints(percent);
Integer percentAfterConstraints = MainApp.getConstraintChecker().applyBasalPercentConstraints(percent);
// add new command to queue
add(new CommandTempBasalPercent(percentAfterConstraints, durationInMinutes, enforceNew, callback));

View file

@ -5,6 +5,7 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
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;
@ -19,18 +20,20 @@ public class CommandTempBasalAbsolute extends Command {
int durationInMinutes;
double absoluteRate;
boolean enforceNew;
Profile profile;
public CommandTempBasalAbsolute(double absoluteRate, int durationInMinutes, boolean enforceNew, Callback callback) {
public CommandTempBasalAbsolute(double absoluteRate, int durationInMinutes, boolean enforceNew, Profile profile, Callback callback) {
commandType = CommandType.TEMPBASAL;
this.absoluteRate = absoluteRate;
this.durationInMinutes = durationInMinutes;
this.enforceNew = enforceNew;
this.profile = profile;
this.callback = callback;
}
@Override
public void execute() {
PumpEnactResult r = ConfigBuilderPlugin.getActivePump().setTempBasalAbsolute(absoluteRate, durationInMinutes, enforceNew);
PumpEnactResult r = ConfigBuilderPlugin.getActivePump().setTempBasalAbsolute(absoluteRate, durationInMinutes, profile, enforceNew);
if (Config.logCongigBuilderActions)
log.debug("setTempBasalAbsolute rate: " + absoluteRate + " durationInMinutes: " + durationInMinutes + " success: " + r.success + " enacted: " + r.enacted);
if (callback != null)

View file

@ -430,9 +430,7 @@
<string name="advancedsettings_title">Advanced Settings</string>
<string name="danar_model" formatted="false">Model: %02X Protocol: %02X Code: %02X</string>
<string name="profile">Profile</string>
<string name="openapsama_max_daily_safety_multiplier" translatable="false">max_daily_safety_multiplier</string>
<string name="openapsama_max_daily_safety_multiplier_summary">Default value: 3 This is a key OpenAPS safety cap. What this does is limit your basals to be 3x (in this people) your biggest basal rate. You likely will not need to change this, but you should be aware thats what is discussed about “3x max daily; 4x current” for safety caps.</string>
<string name="openapsama_current_basal_safety_multiplier" translatable="false">current_basal_safety_multiplier</string>
<string name="openapsama_current_basal_safety_multiplier_summary">Default value: 4 This is the other half of the key OpenAPS safety caps, and the other half of “3x max daily; 4x current” of the safety caps. This means your basal, regardless of max basal set on your pump, cannot be any higher than this number times the current level of your basal. This is to prevent people from getting into dangerous territory by setting excessively high max basals before understanding how the algorithm works. Again, the default is 4x; most people will never need to adjust this and are instead more likely to need to adjust other settings if they feel like they are “running into” this safety cap.</string>
<string name="openapsama_autosens_max" translatable="false">autosens_max</string>
<string name="openapsama_autosens_max_summary">Default value: 1.2\nThis is a multiplier cap for autosens (and soon autotune) to set a 20% max limit on how high the autosens ratio can be, which in turn determines how high autosens can adjust basals, how low it can adjust ISF, and how low it can set the BG target.</string>
@ -968,5 +966,15 @@
<string name="closedmodedisabledinpreferences">Closed loop mode disabled in preferences</string>
<string name="amadisabledinpreferences">AMA disabled in preferences</string>
<string name="smbdisabledinpreferences">SMB disabled in preferences</string>
<string name="limitingbasalratio">Limiting basal rate to %.2f U/h because of %s</string>
<string name="pumplimit">pump limit</string>
<string name="key_openapsma_max_basal" translatable="false">openapsma_max_basal</string>
<string name="key_openapsama_current_basal_safety_multiplier" translatable="false">openapsama_current_basal_safety_multiplier</string>
<string name="key_openapsama_max_daily_safety_multiplier" translatable="false">openapsama_max_daily_safety_multiplier</string>
<string name="basalmustbepositivevalue">basal must be positive value</string>
<string name="maxbasalinpreferences">max basal settings in preferences</string>
<string name="maxbasalmultiplier">max basal multiplier</string>
<string name="maxdailybasalmultiplier">max daily basal multiplier</string>
<string name="key_openapsma_max_iob" translatable="false">openapsma_max_iob</string>
</resources>

View file

@ -46,10 +46,10 @@
android:dialogMessage="@string/openapsama_max_daily_safety_multiplier_summary"
android:digits="0123456789.,"
android:inputType="number"
android:key="openapsama_max_daily_safety_multiplier"
android:key="@string/key_openapsama_max_daily_safety_multiplier"
android:maxLines="20"
android:selectAllOnFocus="true"
android:title="@string/openapsama_max_daily_safety_multiplier"
android:title="@string/key_openapsama_max_daily_safety_multiplier"
validate:maxNumber="10"
validate:minNumber="1"
validate:testType="numericRange" />
@ -58,11 +58,11 @@
android:dialogMessage="@string/openapsama_current_basal_safety_multiplier_summary"
android:digits="0123456789.,"
android:inputType="number"
android:key="openapsama_current_basal_safety_multiplier"
android:key="@string/key_openapsama_current_basal_safety_multiplier"
android:maxLines="20"
android:selectAllOnFocus="true"
android:singleLine="true"
android:title="@string/openapsama_current_basal_safety_multiplier"
android:title="@string/key_openapsama_current_basal_safety_multiplier"
validate:floatmaxNumber="10"
validate:floatminNumber="1"
validate:testType="floatNumericRange" />

View file

@ -7,13 +7,13 @@
<EditTextPreference
android:defaultValue="1"
android:key="openapsma_max_basal"
android:key="@string/key_openapsma_max_basal"
android:numeric="decimal"
android:dialogMessage="@string/openapsma_maxbasal_summary"
android:title="@string/openapsma_maxbasal_title" />
<EditTextPreference
android:defaultValue="1.5"
android:key="openapsma_max_iob"
android:key="@string/key_openapsma_max_iob"
android:numeric="decimal"
android:dialogMessage="@string/openapsma_maxiob_summary"
android:title="@string/openapsma_maxiob_title" />

View file

@ -6,13 +6,13 @@
<EditTextPreference
android:defaultValue="1"
android:key="openapsma_max_basal"
android:key="@string/key_openapsma_max_basal"
android:numeric="decimal"
android:dialogMessage="@string/openapsma_maxbasal_summary"
android:title="@string/openapsma_maxbasal_title" />
<EditTextPreference
android:defaultValue="1.5"
android:key="openapsma_max_iob"
android:key="@string/key_openapsma_max_iob"
android:numeric="decimal"
android:dialogMessage="@string/openapsma_maxiob_summary"
android:title="@string/openapsma_maxiob_title" />

View file

@ -6,13 +6,13 @@
android:title="@string/openapssmb">
<EditTextPreference
android:defaultValue="1"
android:key="openapsma_max_basal"
android:key="@string/key_openapsma_max_basal"
android:numeric="decimal"
android:dialogMessage="@string/openapsma_maxbasal_summary"
android:title="@string/openapsma_maxbasal_title" />
<EditTextPreference
android:defaultValue="1.5"
android:key="openapsma_max_iob"
android:key="@string/key_openapsma_max_iob"
android:numeric="decimal"
android:dialogMessage="@string/openapsma_maxiob_summary"
android:title="@string/openapsma_maxiob_title" />

View file

@ -6,8 +6,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.modules.junit4.PowerMockRunner;
import info.nightscout.androidaps.interfaces.Constraint;
/**
* Created by mike on 19.03.2018.
*/
@ -17,19 +15,28 @@ public class ConstraintTest {
@Test
public void doTests() throws Exception {
Constraint<Boolean> c;
Constraint<Boolean> b = new Constraint<>(true);
Assert.assertEquals(Boolean.TRUE, b.value());
Assert.assertEquals("", b.getReasons());
b.set(false);
Assert.assertEquals(Boolean.FALSE, b.value());
Assert.assertEquals("", b.getReasons());
b.set(true, "Set true");
Assert.assertEquals(Boolean.TRUE, b.value());
Assert.assertEquals("Set true", b.getReasons());
b.set(false, "Set false");
Assert.assertEquals(Boolean.FALSE, b.value());
Assert.assertEquals("Set true\nSet false", b.getReasons());
c = new Constraint<Boolean>(true);
Assert.assertEquals(Boolean.TRUE, c.get());
Assert.assertEquals("", c.getReasons());
c.set(false);
Assert.assertEquals(Boolean.FALSE, c.get());
Assert.assertEquals("", c.getReasons());
c.set(true, "Set true");
Assert.assertEquals(Boolean.TRUE, c.get());
Assert.assertEquals("Set true", c.getReasons());
c.set(false, "Set false");
Assert.assertEquals(Boolean.FALSE, c.get());
Assert.assertEquals("Set true\nSet false", c.getReasons());
Constraint<Double> d = new Constraint<>(10d);
d.set(5d, "Set 5d");
Assert.assertEquals(5d, b.value());
Assert.assertEquals("Set 5d", b.getReasons());
d.setIfSmaller(6d, "Set 6d");
Assert.assertEquals(5d, b.value());
Assert.assertEquals("Set 5d", b.getReasons());
d.setIfSmaller(4d, "Set 4d");
Assert.assertEquals(4d, b.value());
Assert.assertEquals("Set 5d\nSet 4d", b.getReasons());
}
}

View file

@ -1,9 +1,13 @@
package info.nightscout.androidaps.interfaces;
import android.content.Context;
import com.squareup.otto.Bus;
import junit.framework.Assert;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -14,13 +18,20 @@ import org.powermock.modules.junit4.PowerMockRunner;
import java.util.ArrayList;
import java.util.Date;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ConstraintChecker;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
import info.nightscout.androidaps.plugins.PumpCombo.ComboPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.PumpInsight.InsightPumpPlugin;
import info.nightscout.androidaps.plugins.PumpInsight.connector.StatusTaskRunner;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.SP;
@ -32,7 +43,7 @@ import static org.mockito.Mockito.when;
* Created by mike on 18.03.2018.
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, FabricPrivacy.class, SP.class})
@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, FabricPrivacy.class, SP.class, Context.class})
public class ConstraintsCheckerTest {
PumpInterface pump = new VirtualPumpPlugin();
@ -42,12 +53,21 @@ public class ConstraintsCheckerTest {
MainApp mainApp = mock(MainApp.class);
MockedBus bus = new MockedBus();
String validProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}";
Profile profile = new Profile(new JSONObject(validProfile), Constants.MGDL);
SafetyPlugin safetyPlugin;
ObjectivesPlugin objectivesPlugin;
ComboPlugin comboPlugin;
DanaRPlugin danaRPlugin;
DanaRSPlugin danaRSPlugin;
InsightPumpPlugin insightPlugin;
boolean notificationSent = false;
public ConstraintsCheckerTest() throws JSONException {
}
// isLoopInvokationAllowed tests
@Test
public void pumpDescriptionShouldLimitLoopInvokation() throws Exception {
@ -55,7 +75,7 @@ public class ConstraintsCheckerTest {
Constraint<Boolean> c = constraintChecker.isLoopInvokationAllowed();
Assert.assertEquals(true, c.getReasons().contains("Pump is not temp basal capable"));
Assert.assertEquals(Boolean.FALSE, c.get());
Assert.assertEquals(Boolean.FALSE, c.value());
}
@Test
@ -64,7 +84,7 @@ public class ConstraintsCheckerTest {
Constraint<Boolean> c = constraintChecker.isLoopInvokationAllowed();
Assert.assertEquals(true, c.getReasons().contains("Objective 1 not started"));
Assert.assertEquals(Boolean.FALSE, c.get());
Assert.assertEquals(Boolean.FALSE, c.value());
}
@Test
@ -74,7 +94,7 @@ public class ConstraintsCheckerTest {
Constraint<Boolean> c = constraintChecker.isLoopInvokationAllowed();
Assert.assertEquals(true, c.getReasons().contains("No valid basal rate read from pump"));
Assert.assertEquals(Boolean.FALSE, c.get());
Assert.assertEquals(Boolean.FALSE, c.value());
}
// isClosedLoopAllowed tests
@ -85,7 +105,7 @@ public class ConstraintsCheckerTest {
Constraint<Boolean> c = constraintChecker.isClosedLoopAllowed();
Assert.assertEquals(true, c.getReasons().contains("Running dev version. Closed loop is disabled."));
Assert.assertEquals(Boolean.FALSE, c.get());
Assert.assertEquals(Boolean.FALSE, c.value());
}
@Test
@ -94,7 +114,7 @@ public class ConstraintsCheckerTest {
Constraint<Boolean> c = constraintChecker.isClosedLoopAllowed();
Assert.assertEquals(true, c.getReasons().contains("Closed loop mode disabled in preferences"));
Assert.assertEquals(Boolean.FALSE, c.get());
Assert.assertEquals(Boolean.FALSE, c.value());
}
@Test
@ -104,7 +124,7 @@ public class ConstraintsCheckerTest {
Constraint<Boolean> c = constraintChecker.isClosedLoopAllowed();
Assert.assertEquals(true, c.getReasons().contains("Objective 4 not started"));
Assert.assertEquals(Boolean.FALSE, c.get());
Assert.assertEquals(Boolean.FALSE, c.value());
}
// isAutosensModeEnabled tests
@ -114,7 +134,7 @@ public class ConstraintsCheckerTest {
Constraint<Boolean> c = constraintChecker.isAutosensModeEnabled();
Assert.assertEquals(true, c.getReasons().contains("Objective 6 not started"));
Assert.assertEquals(Boolean.FALSE, c.get());
Assert.assertEquals(Boolean.FALSE, c.value());
}
// isAMAModeEnabled tests
@ -124,7 +144,7 @@ public class ConstraintsCheckerTest {
Constraint<Boolean> c = constraintChecker.isAMAModeEnabled();
Assert.assertEquals(true, c.getReasons().contains("AMA disabled in preferences"));
Assert.assertEquals(Boolean.FALSE, c.get());
Assert.assertEquals(Boolean.FALSE, c.value());
}
@Test
@ -133,7 +153,7 @@ public class ConstraintsCheckerTest {
Constraint<Boolean> c = constraintChecker.isAMAModeEnabled();
Assert.assertEquals(true, c.getReasons().contains("Objective 7 not started"));
Assert.assertEquals(Boolean.FALSE, c.get());
Assert.assertEquals(Boolean.FALSE, c.value());
}
// isSMBModeEnabled tests
@ -143,7 +163,7 @@ public class ConstraintsCheckerTest {
Constraint<Boolean> c = constraintChecker.isSMBModeEnabled();
Assert.assertEquals(true, c.getReasons().contains("SMB disabled in preferences"));
Assert.assertEquals(Boolean.FALSE, c.get());
Assert.assertEquals(Boolean.FALSE, c.value());
}
@Test
@ -152,7 +172,46 @@ public class ConstraintsCheckerTest {
Constraint<Boolean> c = constraintChecker.isSMBModeEnabled();
Assert.assertEquals(true, c.getReasons().contains("Objective 8 not started"));
Assert.assertEquals(Boolean.FALSE, c.get());
Assert.assertEquals(Boolean.FALSE, c.value());
}
// applyBasalConstraints tests
@Test
public void basalRateShouldBeLimited() 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<Double> d = new Constraint<>(-0.5d);
constraintChecker.applyBasalConstraints(d, profile);
Assert.assertEquals(0d, d.value());
Assert.assertEquals("Limiting basal rate to 0,00 U/h because of basal must be positive value", d.getReasons());
// Apply all limits
d = new Constraint<>(Constants.REALLYHIGHBASALRATE);
constraintChecker.applyBasalConstraints(d, profile);
Assert.assertEquals(0.8d, d.value());
Assert.assertEquals("Limiting basal rate to 1,00 U/h because of max basal settings in preferences\n" +
"Limiting basal rate to 4,00 U/h because of max basal multiplier\n" +
"Limiting basal rate to 3,00 U/h because of max daily basal multiplier\n" +
"Limiting basal rate to 0,80 U/h because of pump limit\n" +
"Limiting basal rate to 0,80 U/h because of pump limit\n" +
"Limiting basal rate to 1,10 U/h because of pump limit", d.getReasons());
}
@Before
@ -168,6 +227,9 @@ public class ConstraintsCheckerTest {
PowerMockito.mockStatic(FabricPrivacy.class);
Context context = mock(Context.class);
when(MainApp.instance().getApplicationContext()).thenReturn(context);
when(MainApp.bus()).thenReturn(bus);
when(MainApp.gs(R.string.pumpisnottempbasalcapable)).thenReturn("Pump is not temp basal capable");
@ -177,17 +239,32 @@ public class ConstraintsCheckerTest {
when(MainApp.gs(R.string.novalidbasalrate)).thenReturn("No valid basal rate read from pump");
when(MainApp.gs(R.string.amadisabledinpreferences)).thenReturn("AMA disabled in preferences");
when(MainApp.gs(R.string.smbdisabledinpreferences)).thenReturn("SMB disabled in preferences");
when(MainApp.gs(R.string.limitingbasalratio)).thenReturn("Limiting basal rate to %.2f U/h because of %s");
when(MainApp.gs(R.string.pumplimit)).thenReturn("pump limit");
when(MainApp.gs(R.string.basalmustbepositivevalue)).thenReturn("basal must be positive value");
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");
PowerMockito.mockStatic(SP.class);
// RS constructor
when(SP.getString(R.string.key_danars_address, "")).thenReturn("");
safetyPlugin = SafetyPlugin.getPlugin();
objectivesPlugin = ObjectivesPlugin.getPlugin();
comboPlugin = ComboPlugin.getPlugin();
danaRPlugin = DanaRPlugin.getPlugin();
danaRSPlugin = DanaRSPlugin.getPlugin();
insightPlugin = InsightPumpPlugin.getPlugin();
ArrayList<PluginBase> constraintsPluginsList = new ArrayList<>();
constraintsPluginsList.add(safetyPlugin);
constraintsPluginsList.add(objectivesPlugin);
constraintsPluginsList.add(comboPlugin);
constraintsPluginsList.add(danaRPlugin);
constraintsPluginsList.add(danaRSPlugin);
constraintsPluginsList.add(insightPlugin);
when(mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class)).thenReturn(constraintsPluginsList);
PowerMockito.mockStatic(SP.class);
}
class MockedBus extends Bus {

View file

@ -7,6 +7,7 @@ import com.squareup.otto.ThreadEnforcer;
import junit.framework.Assert;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -36,7 +37,11 @@ import static org.mockito.Mockito.when;
@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, ToastUtils.class, Context.class})
public class CommandQueueTest extends CommandQueue {
String profileJson = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}";
String validProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}";
Profile profile = new Profile(new JSONObject(validProfile), Constants.MGDL);
public CommandQueueTest() throws JSONException {
}
@Test
public void doTests() throws Exception {
@ -62,7 +67,7 @@ public class CommandQueueTest extends CommandQueue {
Assert.assertEquals(0, size());
// add tempbasal
tempBasalAbsolute(0, 30, true, null);
tempBasalAbsolute(0, 30, true, profile, null);
Assert.assertEquals(1, size());
// add tempbasal percent. it should replace previous TEMPBASAL
@ -83,7 +88,7 @@ public class CommandQueueTest extends CommandQueue {
// add setProfile (command is not queued before unless a ProfileSwitch exists)
// TODO test with profile switch set
setProfile(new Profile(new JSONObject(profileJson), Constants.MGDL), null);
setProfile(profile, null);
Assert.assertEquals(2, size());
// add loadHistory
@ -95,7 +100,7 @@ public class CommandQueueTest extends CommandQueue {
Assert.assertEquals(4, size());
clear();
tempBasalAbsolute(0, 30, true, null);
tempBasalAbsolute(0, 30, true, profile, null);
pickup();
Assert.assertEquals(0, size());
Assert.assertNotNull(performing);