commit
55d1dd0847
15 changed files with 502 additions and 150 deletions
|
@ -221,7 +221,7 @@ public class TemporaryBasal implements Interval {
|
|||
|
||||
public IobTotal iobCalc(long time, Profile profile) {
|
||||
|
||||
if(isFakeExtended){
|
||||
if (isFakeExtended) {
|
||||
log.error("iobCalc should only be called on Extended boluses separately");
|
||||
return new IobTotal(time);
|
||||
}
|
||||
|
@ -292,7 +292,7 @@ public class TemporaryBasal implements Interval {
|
|||
}
|
||||
|
||||
public double tempBasalConvertedToAbsolute(long time, Profile profile) {
|
||||
if(isFakeExtended){
|
||||
if (isFakeExtended) {
|
||||
return profile.getBasal(time) + netExtendedRate;
|
||||
} else if (isAbsolute) {
|
||||
return absoluteRate;
|
||||
|
@ -301,6 +301,16 @@ public class TemporaryBasal implements Interval {
|
|||
}
|
||||
}
|
||||
|
||||
public int tempBasalConvertedToPercent(long time, Profile profile) {
|
||||
if (isFakeExtended) {
|
||||
return (int) ((profile.getBasal(time) + netExtendedRate) / profile.getBasal(time)) * 100;
|
||||
} else if (isAbsolute) {
|
||||
return (int) (absoluteRate / profile.getBasal(time)) * 100;
|
||||
} else {
|
||||
return percentRate;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "TemporaryBasal{" +
|
||||
"date=" + date +
|
||||
|
@ -318,12 +328,12 @@ public class TemporaryBasal implements Interval {
|
|||
}
|
||||
|
||||
public String toStringFull() {
|
||||
if(isFakeExtended){
|
||||
if (isFakeExtended) {
|
||||
|
||||
Profile profile = ProfileFunctions.getInstance().getProfile();
|
||||
Double currentBasalRate = profile.getBasal();
|
||||
double rate = (currentBasalRate == null)?0d:(currentBasalRate+netExtendedRate);
|
||||
return getCalcuatedPercentageIfNeeded() + DecimalFormatter.to2Decimal(rate) + "U/h ("+DecimalFormatter.to2Decimal(netExtendedRate)+"E) @" +
|
||||
double rate = (currentBasalRate == null) ? 0d : (currentBasalRate + netExtendedRate);
|
||||
return getCalcuatedPercentageIfNeeded() + DecimalFormatter.to2Decimal(rate) + "U/h (" + DecimalFormatter.to2Decimal(netExtendedRate) + "E) @" +
|
||||
DateUtil.timeString(date) +
|
||||
" " + getRealDuration() + "/" + durationInMinutes + "'";
|
||||
} else if (isAbsolute) {
|
||||
|
@ -344,17 +354,17 @@ public class TemporaryBasal implements Interval {
|
|||
if (isFakeExtended) {
|
||||
Profile profile = ProfileFunctions.getInstance().getProfile();
|
||||
Double currentBasalRate = profile.getBasal();
|
||||
rate = (currentBasalRate == null)?0d:(currentBasalRate+netExtendedRate);
|
||||
} else if (isAbsolute){
|
||||
rate = (currentBasalRate == null) ? 0d : (currentBasalRate + netExtendedRate);
|
||||
} else if (isAbsolute) {
|
||||
rate = absoluteRate;
|
||||
}
|
||||
|
||||
if(SP.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false) && SP.getBoolean(R.string.key_danar_useextended, false)){
|
||||
if (SP.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false) && SP.getBoolean(R.string.key_danar_useextended, false)) {
|
||||
Profile profile = ProfileFunctions.getInstance().getProfile();
|
||||
if(profile != null) {
|
||||
if (profile != null) {
|
||||
double basal = profile.getBasal();
|
||||
if(basal != 0){
|
||||
return Math.round(rate*100d/basal) + "%";
|
||||
if (basal != 0) {
|
||||
return Math.round(rate * 100d / basal) + "%";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -364,24 +374,24 @@ public class TemporaryBasal implements Interval {
|
|||
}
|
||||
}
|
||||
|
||||
private String getCalcuatedPercentageIfNeeded(){
|
||||
private String getCalcuatedPercentageIfNeeded() {
|
||||
if (isAbsolute || isFakeExtended) {
|
||||
|
||||
double rate = 0d;
|
||||
if (isFakeExtended) {
|
||||
Profile profile = ProfileFunctions.getInstance().getProfile();
|
||||
Double currentBasalRate = profile.getBasal();
|
||||
rate = (currentBasalRate == null)?0d:(currentBasalRate+netExtendedRate);
|
||||
} else if (isAbsolute){
|
||||
rate = (currentBasalRate == null) ? 0d : (currentBasalRate + netExtendedRate);
|
||||
} else if (isAbsolute) {
|
||||
rate = absoluteRate;
|
||||
}
|
||||
|
||||
if(SP.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false) && SP.getBoolean(R.string.key_danar_useextended, false)){
|
||||
if (SP.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false) && SP.getBoolean(R.string.key_danar_useextended, false)) {
|
||||
Profile profile = ProfileFunctions.getInstance().getProfile();
|
||||
if(profile != null) {
|
||||
if (profile != null) {
|
||||
double basal = profile.getBasal();
|
||||
if(basal != 0){
|
||||
return Math.round(rate*100d/basal) + "% ";
|
||||
if (basal != 0) {
|
||||
return Math.round(rate * 100d / basal) + "% ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -396,8 +406,8 @@ public class TemporaryBasal implements Interval {
|
|||
if (isFakeExtended) {
|
||||
Profile profile = ProfileFunctions.getInstance().getProfile();
|
||||
Double currentBasalRate = profile.getBasal();
|
||||
rate = (currentBasalRate == null)?0d:(currentBasalRate+netExtendedRate);
|
||||
} else if (isAbsolute){
|
||||
rate = (currentBasalRate == null) ? 0d : (currentBasalRate + netExtendedRate);
|
||||
} else if (isAbsolute) {
|
||||
rate = absoluteRate;
|
||||
}
|
||||
return DecimalFormatter.to2Decimal(rate) + "U/h ";
|
||||
|
|
|
@ -126,7 +126,7 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
|
|||
|
||||
PumpInterface pump = MainApp.getConfigBuilder().getActivePump();
|
||||
// check for pump max
|
||||
if (pump != null) {
|
||||
if (pump != null && pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) {
|
||||
double pumpLimit = pump.getPumpDescription().pumpType.getTbrSettings().getMaxDose();
|
||||
absoluteRate.setIfSmaller(pumpLimit, String.format(MainApp.gs(R.string.limitingbasalratio), pumpLimit, MainApp.gs(R.string.pumplimit)), this);
|
||||
}
|
||||
|
@ -151,6 +151,7 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
|
|||
percentRate.copyReasons(absoluteConstraint);
|
||||
|
||||
PumpInterface pump = MainApp.getConfigBuilder().getActivePump();
|
||||
|
||||
Integer percentRateAfterConst = Double.valueOf(absoluteConstraint.value() / currentBasal * 100).intValue();
|
||||
if (pump != null) {
|
||||
if (percentRateAfterConst < 100)
|
||||
|
@ -161,6 +162,11 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
|
|||
|
||||
percentRate.set(percentRateAfterConst, String.format(MainApp.gs(R.string.limitingpercentrate), percentRateAfterConst, MainApp.gs(R.string.pumplimit)), this);
|
||||
|
||||
if (pump != null && pump.getPumpDescription().tempBasalStyle == PumpDescription.PERCENT) {
|
||||
double pumpLimit = pump.getPumpDescription().pumpType.getTbrSettings().getMaxDose();
|
||||
percentRate.setIfSmaller((int) pumpLimit, String.format(MainApp.gs(R.string.limitingbasalratio), pumpLimit, MainApp.gs(R.string.pumplimit)), this);
|
||||
}
|
||||
|
||||
return percentRate;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,11 +15,16 @@ import java.util.List;
|
|||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||
import info.nightscout.androidaps.interfaces.Constraint;
|
||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions;
|
||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
|
||||
/**
|
||||
|
@ -31,6 +36,8 @@ public class APSResult {
|
|||
public long date = 0;
|
||||
public String reason;
|
||||
public double rate;
|
||||
public int percent;
|
||||
public boolean usePercent = false;
|
||||
public int duration;
|
||||
public boolean tempBasalRequested = false;
|
||||
public boolean bolusRequested = false;
|
||||
|
@ -43,8 +50,39 @@ public class APSResult {
|
|||
public Constraint<Double> inputConstraints;
|
||||
|
||||
public Constraint<Double> rateConstraint;
|
||||
public Constraint<Integer> percentConstraint;
|
||||
public Constraint<Double> smbConstraint;
|
||||
|
||||
public APSResult rate(double rate) {
|
||||
this.rate = rate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public APSResult duration(int duration) {
|
||||
this.duration = duration;
|
||||
return this;
|
||||
}
|
||||
|
||||
public APSResult percent(int percent) {
|
||||
this.percent = percent;
|
||||
return this;
|
||||
}
|
||||
|
||||
public APSResult tempBasalRequested(boolean tempBasalRequested) {
|
||||
this.tempBasalRequested = tempBasalRequested;
|
||||
return this;
|
||||
}
|
||||
|
||||
public APSResult usePercent(boolean usePercent) {
|
||||
this.usePercent = usePercent;
|
||||
return this;
|
||||
}
|
||||
|
||||
public APSResult json(JSONObject json) {
|
||||
this.json = json;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||
|
@ -55,6 +93,10 @@ public class APSResult {
|
|||
ret = MainApp.gs(R.string.canceltemp) + "\n";
|
||||
else if (rate == -1)
|
||||
ret = MainApp.gs(R.string.let_temp_basal_run) + "\n";
|
||||
else if (usePercent)
|
||||
ret = MainApp.gs(R.string.rate) + ": " + DecimalFormatter.to2Decimal(percent) + "% " +
|
||||
"(" + DecimalFormatter.to2Decimal(percent * pump.getBaseBasalRate() / 100d) + " U/h)\n" +
|
||||
MainApp.gs(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration) + " min\n";
|
||||
else
|
||||
ret = MainApp.gs(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " +
|
||||
"(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%) \n" +
|
||||
|
@ -80,6 +122,10 @@ public class APSResult {
|
|||
ret = MainApp.gs(R.string.canceltemp) + "<br>";
|
||||
else if (rate == -1)
|
||||
ret = MainApp.gs(R.string.let_temp_basal_run) + "<br>";
|
||||
else if (usePercent)
|
||||
ret = "<b>" + MainApp.gs(R.string.rate) + "</b>: " + DecimalFormatter.to2Decimal(percent) + "% " +
|
||||
"(" + DecimalFormatter.to2Decimal(percent * pump.getBaseBasalRate() / 100d) + " U/h)<br>" +
|
||||
"<b>" + MainApp.gs(R.string.duration) + "</b>: " + DecimalFormatter.to2Decimal(duration) + " min<br>";
|
||||
else
|
||||
ret = "<b>" + MainApp.gs(R.string.rate) + "</b>: " + DecimalFormatter.to2Decimal(rate) + " U/h " +
|
||||
"(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%) <br>" +
|
||||
|
@ -101,21 +147,33 @@ public class APSResult {
|
|||
|
||||
public APSResult clone() {
|
||||
APSResult newResult = new APSResult();
|
||||
newResult.reason = reason;
|
||||
doClone(newResult);
|
||||
return newResult;
|
||||
}
|
||||
|
||||
protected void doClone(APSResult newResult) {
|
||||
newResult.date = date;
|
||||
newResult.reason = reason != null ? new String(reason) : null;
|
||||
newResult.rate = rate;
|
||||
newResult.duration = duration;
|
||||
newResult.tempBasalRequested = tempBasalRequested;
|
||||
newResult.bolusRequested = bolusRequested;
|
||||
newResult.iob = iob;
|
||||
newResult.json = json;
|
||||
try {
|
||||
newResult.json = new JSONObject(json.toString());
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
newResult.hasPredictions = hasPredictions;
|
||||
newResult.smb = smb;
|
||||
newResult.deliverAt = deliverAt;
|
||||
newResult.rateConstraint = rateConstraint;
|
||||
newResult.smbConstraint = smbConstraint;
|
||||
return newResult;
|
||||
newResult.percent = percent;
|
||||
newResult.usePercent = usePercent;
|
||||
}
|
||||
|
||||
|
||||
public JSONObject json() {
|
||||
JSONObject json = new JSONObject();
|
||||
try {
|
||||
|
@ -228,6 +286,112 @@ public class APSResult {
|
|||
}
|
||||
|
||||
public boolean isChangeRequested() {
|
||||
Constraint<Boolean> closedLoopEnabled = MainApp.getConstraintChecker().isClosedLoopAllowed();
|
||||
// closed loop mode: handle change at driver level
|
||||
if (closedLoopEnabled.value()) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("DEFAULT: Closed mode");
|
||||
return tempBasalRequested || bolusRequested;
|
||||
}
|
||||
|
||||
// open loop mode: try to limit request
|
||||
if (!tempBasalRequested && !bolusRequested) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("FALSE: No request");
|
||||
return false;
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now);
|
||||
PumpInterface pump = MainApp.getConfigBuilder().getActivePump();
|
||||
Profile profile = ProfileFunctions.getInstance().getProfile();
|
||||
|
||||
if (usePercent) {
|
||||
if (activeTemp == null && percent == 100) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("FALSE: No temp running, asking cancel temp");
|
||||
return false;
|
||||
}
|
||||
if (activeTemp != null && Math.abs(percent - activeTemp.tempBasalConvertedToPercent(now, profile)) < pump.getPumpDescription().basalStep) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("FALSE: Temp equal");
|
||||
return false;
|
||||
}
|
||||
// always report zerotemp
|
||||
if (percent == 0) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("TRUE: Zero temp");
|
||||
return true;
|
||||
}
|
||||
// always report hightemp
|
||||
if (pump != null && pump.getPumpDescription().tempBasalStyle == PumpDescription.PERCENT) {
|
||||
double pumpLimit = pump.getPumpDescription().pumpType.getTbrSettings().getMaxDose();
|
||||
if (percent == pumpLimit) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("TRUE: Pump limit");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// report change bigger than 30%
|
||||
if (activeTemp != null) {
|
||||
double percentToBeSmallChange = 30;
|
||||
percentToBeSmallChange /= 100;
|
||||
double change = percent / (double) activeTemp.tempBasalConvertedToPercent(now, profile);
|
||||
double lowThreshold = 1 - percentToBeSmallChange;
|
||||
double highThreshold = 1 + percentToBeSmallChange;
|
||||
|
||||
if (change < lowThreshold || change > highThreshold) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("TRUE: Outside allowed range " + (change * 100) + "%");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("FALSE");
|
||||
return false;
|
||||
} else {
|
||||
if (activeTemp == null && rate == pump.getBaseBasalRate()) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("FALSE: No temp running, asking cancel temp");
|
||||
return false;
|
||||
}
|
||||
if (activeTemp != null && Math.abs(rate - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < pump.getPumpDescription().basalStep) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("FALSE: Temp equal");
|
||||
return false;
|
||||
}
|
||||
// always report zerotemp
|
||||
if (rate == 0) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("TRUE: Zero temp");
|
||||
return true;
|
||||
}
|
||||
// always report hightemp
|
||||
if (pump != null && pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) {
|
||||
double pumpLimit = pump.getPumpDescription().pumpType.getTbrSettings().getMaxDose();
|
||||
if (rate == pumpLimit) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("TRUE: Pump limit");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// report change bigger than 30%
|
||||
if (activeTemp != null) {
|
||||
double percentToBeSmallChange = 30;
|
||||
percentToBeSmallChange /= 100;
|
||||
double change = rate / activeTemp.tempBasalConvertedToAbsolute(now, profile);
|
||||
double lowThreshold = 1 - percentToBeSmallChange;
|
||||
double highThreshold = 1 + percentToBeSmallChange;
|
||||
|
||||
if (change < lowThreshold || change > highThreshold) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("TRUE: Outside allowed range " + (change * 100) + "%");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("FALSE");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ import info.nightscout.androidaps.interfaces.Constraint;
|
|||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
|
@ -51,6 +52,7 @@ import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui;
|
|||
import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
|
||||
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload;
|
||||
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
|
||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||
import info.nightscout.androidaps.plugins.Wear.ActionStringHandler;
|
||||
import info.nightscout.androidaps.events.EventAcceptOpenLoopChange;
|
||||
|
@ -58,6 +60,7 @@ import info.nightscout.androidaps.queue.Callback;
|
|||
import info.nightscout.androidaps.queue.commands.Command;
|
||||
import info.nightscout.utils.FabricPrivacy;
|
||||
import info.nightscout.utils.SP;
|
||||
import info.nightscout.utils.T;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
/**
|
||||
|
@ -148,8 +151,6 @@ public class LoopPlugin extends PluginBase {
|
|||
* sources and currently only a new BG should trigger a loop run. Hence we return early if
|
||||
* the event causing the calculation is not EventNewBg.
|
||||
* <p>
|
||||
* Callers of {@link info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin#runCalculation(String, long, boolean, Event)}
|
||||
* are sources triggering a calculation which triggers this method upon completion.
|
||||
*/
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventAutosensCalculationFinished ev) {
|
||||
|
@ -305,16 +306,26 @@ public class LoopPlugin extends PluginBase {
|
|||
return;
|
||||
}
|
||||
|
||||
// Prepare for pumps using % basals
|
||||
if (pump.getPumpDescription().tempBasalStyle == PumpDescription.PERCENT) {
|
||||
result.usePercent = true;
|
||||
}
|
||||
result.percent = (int) (result.rate / profile.getBasal() * 100);
|
||||
|
||||
// check rate for constrais
|
||||
final APSResult resultAfterConstraints = result.clone();
|
||||
resultAfterConstraints.rateConstraint = new Constraint<>(resultAfterConstraints.rate);
|
||||
resultAfterConstraints.rate = MainApp.getConstraintChecker().applyBasalConstraints(resultAfterConstraints.rateConstraint, profile).value();
|
||||
|
||||
resultAfterConstraints.percentConstraint = new Constraint<>(resultAfterConstraints.percent);
|
||||
resultAfterConstraints.percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(resultAfterConstraints.percentConstraint, profile).value();
|
||||
|
||||
resultAfterConstraints.smbConstraint = new Constraint<>(resultAfterConstraints.smb);
|
||||
resultAfterConstraints.smb = MainApp.getConstraintChecker().applyBolusConstraints(resultAfterConstraints.smbConstraint).value();
|
||||
|
||||
// safety check for multiple SMBs
|
||||
long lastBolusTime = TreatmentsPlugin.getPlugin().getLastBolusTime();
|
||||
if (lastBolusTime != 0 && lastBolusTime + 3 * 60 * 1000 > System.currentTimeMillis()) {
|
||||
if (lastBolusTime != 0 && lastBolusTime + T.mins(3).msecs() > System.currentTimeMillis()) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("SMB requsted but still in 3 min interval");
|
||||
resultAfterConstraints.smb = 0;
|
||||
|
@ -347,7 +358,7 @@ public class LoopPlugin extends PluginBase {
|
|||
Constraint<Boolean> closedLoopEnabled = MainApp.getConstraintChecker().isClosedLoopAllowed();
|
||||
|
||||
if (closedLoopEnabled.value()) {
|
||||
if (result.isChangeRequested()
|
||||
if (resultAfterConstraints.isChangeRequested()
|
||||
&& !ConfigBuilderPlugin.getCommandQueue().bolusInQueue()
|
||||
&& !ConfigBuilderPlugin.getCommandQueue().isRunning(Command.CommandType.BOLUS)) {
|
||||
final PumpEnactResult waiting = new PumpEnactResult();
|
||||
|
@ -390,7 +401,7 @@ public class LoopPlugin extends PluginBase {
|
|||
lastRun.smbSetByPump = null;
|
||||
}
|
||||
} else {
|
||||
if (result.isChangeRequested() && allowNotification) {
|
||||
if (resultAfterConstraints.isChangeRequested() && allowNotification) {
|
||||
NotificationCompat.Builder builder =
|
||||
new NotificationCompat.Builder(MainApp.instance().getApplicationContext(), CHANNEL_ID);
|
||||
builder.setSmallIcon(R.drawable.notif_icon)
|
||||
|
@ -466,8 +477,12 @@ public class LoopPlugin extends PluginBase {
|
|||
|
||||
/**
|
||||
* expect absolute request and allow both absolute and percent response based on pump capabilities
|
||||
* TODO: update pump drivers to support APS request in %
|
||||
*/
|
||||
|
||||
public void applyTBRRequest(APSResult request, Profile profile, Callback callback) {
|
||||
boolean allowPercentage = VirtualPumpPlugin.getPlugin().isEnabled(PluginType.PUMP);
|
||||
|
||||
if (!request.tempBasalRequested) {
|
||||
if (callback != null) {
|
||||
callback.result(new PumpEnactResult().enacted(false).success(true).comment(MainApp.gs(R.string.nochangerequested))).run();
|
||||
|
@ -478,9 +493,6 @@ public class LoopPlugin extends PluginBase {
|
|||
PumpInterface pump = MainApp.getConfigBuilder().getActivePump();
|
||||
TreatmentsInterface activeTreatments = TreatmentsPlugin.getPlugin();
|
||||
|
||||
request.rateConstraint = new Constraint<>(request.rate);
|
||||
request.rate = MainApp.getConstraintChecker().applyBasalConstraints(request.rateConstraint, profile).value();
|
||||
|
||||
if (!pump.isInitialized()) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("applyAPSRequest: " + MainApp.gs(R.string.pumpNotInitialized));
|
||||
|
@ -504,6 +516,37 @@ public class LoopPlugin extends PluginBase {
|
|||
|
||||
long now = System.currentTimeMillis();
|
||||
TemporaryBasal activeTemp = activeTreatments.getTempBasalFromHistory(now);
|
||||
if (request.usePercent && allowPercentage) {
|
||||
if (request.percent == 100 && request.duration == 0) {
|
||||
if (activeTemp != null) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("applyAPSRequest: cancelTempBasal()");
|
||||
MainApp.getConfigBuilder().getCommandQueue().cancelTempBasal(false, callback);
|
||||
} else {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("applyAPSRequest: Basal set correctly");
|
||||
if (callback != null) {
|
||||
callback.result(new PumpEnactResult().percent(request.percent).duration(0)
|
||||
.enacted(false).success(true).comment(MainApp.gs(R.string.basal_set_correctly))).run();
|
||||
}
|
||||
}
|
||||
} else if (activeTemp != null
|
||||
&& activeTemp.getPlannedRemainingMinutes() > 5
|
||||
&& request.duration - activeTemp.getPlannedRemainingMinutes() < 30
|
||||
&& request.percent == activeTemp.percentRate) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("applyAPSRequest: Temp basal set correctly");
|
||||
if (callback != null) {
|
||||
callback.result(new PumpEnactResult().percent(request.percent)
|
||||
.enacted(false).success(true).duration(activeTemp.getPlannedRemainingMinutes())
|
||||
.comment(MainApp.gs(R.string.let_temp_basal_run))).run();
|
||||
}
|
||||
} else {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("applyAPSRequest: tempBasalPercent()");
|
||||
MainApp.getConfigBuilder().getCommandQueue().tempBasalPercent(request.percent, request.duration, false, profile, callback);
|
||||
}
|
||||
} else {
|
||||
if ((request.rate == 0 && request.duration == 0) || Math.abs(request.rate - pump.getBaseBasalRate()) < pump.getPumpDescription().basalStep) {
|
||||
if (activeTemp != null) {
|
||||
if (L.isEnabled(L.APS))
|
||||
|
@ -534,6 +577,7 @@ public class LoopPlugin extends PluginBase {
|
|||
MainApp.getConfigBuilder().getCommandQueue().tempBasalAbsolute(request.rate, request.duration, false, profile, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void applySMBRequest(APSResult request, Callback callback) {
|
||||
if (!request.bolusRequested) {
|
||||
|
|
|
@ -55,21 +55,10 @@ public class DetermineBasalResultAMA extends APSResult {
|
|||
@Override
|
||||
public DetermineBasalResultAMA clone() {
|
||||
DetermineBasalResultAMA newResult = new DetermineBasalResultAMA();
|
||||
newResult.reason = reason;
|
||||
newResult.rate = rate;
|
||||
newResult.duration = duration;
|
||||
newResult.tempBasalRequested = tempBasalRequested;
|
||||
newResult.rate = rate;
|
||||
newResult.duration = duration;
|
||||
doClone(newResult);
|
||||
|
||||
try {
|
||||
newResult.json = new JSONObject(json.toString());
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
newResult.eventualBG = eventualBG;
|
||||
newResult.snoozeBG = snoozeBG;
|
||||
newResult.date = date;
|
||||
return newResult;
|
||||
}
|
||||
|
||||
|
|
|
@ -203,17 +203,6 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface {
|
|||
// Fix bug determine basal
|
||||
if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress())
|
||||
determineBasalResultAMA.tempBasalRequested = false;
|
||||
// limit requests on openloop mode
|
||||
if (!MainApp.getConstraintChecker().isClosedLoopAllowed().value()) {
|
||||
long now = System.currentTimeMillis();
|
||||
TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now);
|
||||
if (activeTemp != null && determineBasalResultAMA.rate == 0 && determineBasalResultAMA.duration == 0) {
|
||||
// going to cancel
|
||||
} else if (activeTemp != null && Math.abs(determineBasalResultAMA.rate - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < 0.1) {
|
||||
determineBasalResultAMA.tempBasalRequested = false;
|
||||
} else if (activeTemp == null && Math.abs(determineBasalResultAMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1)
|
||||
determineBasalResultAMA.tempBasalRequested = false;
|
||||
}
|
||||
|
||||
determineBasalResultAMA.iob = iobArray[0];
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import info.nightscout.androidaps.plugins.Loop.APSResult;
|
|||
public class DetermineBasalResultMA extends APSResult {
|
||||
private static Logger log = LoggerFactory.getLogger(L.APS);
|
||||
|
||||
public JSONObject json = new JSONObject();
|
||||
private double eventualBG;
|
||||
private double snoozeBG;
|
||||
private String mealAssist;
|
||||
|
@ -56,19 +55,8 @@ public class DetermineBasalResultMA extends APSResult {
|
|||
@Override
|
||||
public DetermineBasalResultMA clone() {
|
||||
DetermineBasalResultMA newResult = new DetermineBasalResultMA();
|
||||
newResult.reason = new String(reason);
|
||||
newResult.rate = rate;
|
||||
newResult.duration = duration;
|
||||
newResult.tempBasalRequested = isChangeRequested();
|
||||
newResult.rate = rate;
|
||||
newResult.duration = duration;
|
||||
newResult.tempBasalRequested = isChangeRequested();
|
||||
doClone(newResult);
|
||||
|
||||
try {
|
||||
newResult.json = new JSONObject(json.toString());
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
newResult.eventualBG = eventualBG;
|
||||
newResult.snoozeBG = snoozeBG;
|
||||
newResult.mealAssist = mealAssist;
|
||||
|
|
|
@ -182,16 +182,6 @@ public class OpenAPSMAPlugin extends PluginBase implements APSInterface {
|
|||
// Fix bug determinef basal
|
||||
if (determineBasalResultMA.rate == 0d && determineBasalResultMA.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress())
|
||||
determineBasalResultMA.tempBasalRequested = false;
|
||||
// limit requests on openloop mode
|
||||
if (!MainApp.getConstraintChecker().isClosedLoopAllowed().value()) {
|
||||
TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now);
|
||||
if (activeTemp != null && determineBasalResultMA.rate == 0 && determineBasalResultMA.duration == 0) {
|
||||
// going to cancel
|
||||
} else if (activeTemp != null && Math.abs(determineBasalResultMA.rate - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < 0.1) {
|
||||
determineBasalResultMA.tempBasalRequested = false;
|
||||
} else if (activeTemp == null && Math.abs(determineBasalResultMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1)
|
||||
determineBasalResultMA.tempBasalRequested = false;
|
||||
}
|
||||
|
||||
determineBasalResultMA.iob = iobTotal;
|
||||
|
||||
|
|
|
@ -14,8 +14,6 @@ public class DetermineBasalResultSMB extends APSResult {
|
|||
|
||||
private double eventualBG;
|
||||
private double snoozeBG;
|
||||
//public double insulinReq;
|
||||
//public double carbsReq;
|
||||
|
||||
DetermineBasalResultSMB(JSONObject result) {
|
||||
this();
|
||||
|
@ -70,24 +68,10 @@ public class DetermineBasalResultSMB extends APSResult {
|
|||
@Override
|
||||
public DetermineBasalResultSMB clone() {
|
||||
DetermineBasalResultSMB newResult = new DetermineBasalResultSMB();
|
||||
newResult.reason = reason;
|
||||
newResult.rate = rate;
|
||||
newResult.duration = duration;
|
||||
newResult.tempBasalRequested = tempBasalRequested;
|
||||
newResult.bolusRequested = bolusRequested;
|
||||
newResult.rate = rate;
|
||||
newResult.duration = duration;
|
||||
newResult.smb = smb;
|
||||
newResult.deliverAt = deliverAt;
|
||||
doClone(newResult);
|
||||
|
||||
try {
|
||||
newResult.json = new JSONObject(json.toString());
|
||||
} catch (JSONException e) {
|
||||
log.error("Error clone parsing determine-basal result", e);
|
||||
}
|
||||
newResult.eventualBG = eventualBG;
|
||||
newResult.snoozeBG = snoozeBG;
|
||||
newResult.date = date;
|
||||
return newResult;
|
||||
}
|
||||
|
||||
|
|
|
@ -225,16 +225,6 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface {
|
|||
// Fix bug determine basal
|
||||
if (determineBasalResultSMB.rate == 0d && determineBasalResultSMB.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress())
|
||||
determineBasalResultSMB.tempBasalRequested = false;
|
||||
// limit requests on openloop mode
|
||||
if (!MainApp.getConstraintChecker().isClosedLoopAllowed().value()) {
|
||||
TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now);
|
||||
if (activeTemp != null && determineBasalResultSMB.rate == 0 && determineBasalResultSMB.duration == 0) {
|
||||
// going to cancel
|
||||
} else if (activeTemp != null && Math.abs(determineBasalResultSMB.rate - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < 0.1) {
|
||||
determineBasalResultSMB.tempBasalRequested = false;
|
||||
} else if (activeTemp == null && Math.abs(determineBasalResultSMB.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1)
|
||||
determineBasalResultSMB.tempBasalRequested = false;
|
||||
}
|
||||
|
||||
determineBasalResultSMB.iob = iobArray[0];
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ public enum PumpType {
|
|||
Insulet_Omnipod("Insulet Omnipod", 0.05d, null, //
|
||||
new DoseSettings(0.05d, 30, 8*60, 0.05d), //
|
||||
PumpTempBasalType.Absolute, //
|
||||
new DoseSettings(0.05d, 30, 12*60, 0d, 5.0d), PumpCapability.BasalRate_Duration30minAllowed, // cannot exceed max basal rate 30u/hr
|
||||
new DoseSettings(0.05d, 30, 12*60, 0d, 30.0d), PumpCapability.BasalRate_Duration30minAllowed, // cannot exceed max basal rate 30u/hr
|
||||
0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities),
|
||||
|
||||
// Medtronic
|
||||
|
|
|
@ -2,7 +2,6 @@ package info;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import com.squareup.otto.Bus;
|
||||
|
||||
|
@ -10,7 +9,6 @@ import org.json.JSONException;
|
|||
import org.json.JSONObject;
|
||||
import org.junit.Assert;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
|
@ -21,11 +19,10 @@ import info.nightscout.androidaps.data.ConstraintChecker;
|
|||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.data.ProfileStore;
|
||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
import info.nightscout.androidaps.interfaces.Constraint;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.DbLogger;
|
||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentService;
|
||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||
import info.nightscout.androidaps.queue.CommandQueue;
|
||||
|
@ -33,10 +30,8 @@ import info.nightscout.utils.SP;
|
|||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyDouble;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
@ -117,9 +112,10 @@ public class AAPSMocker {
|
|||
when(MainApp.getConfigBuilder()).thenReturn(configBuilderPlugin);
|
||||
}
|
||||
|
||||
public static void mockConstraintsChecker() {
|
||||
public static ConstraintChecker mockConstraintsChecker() {
|
||||
ConstraintChecker constraintChecker = mock(ConstraintChecker.class);
|
||||
when(MainApp.getConstraintChecker()).thenReturn(constraintChecker);
|
||||
return constraintChecker;
|
||||
}
|
||||
|
||||
public static void mockBus() {
|
||||
|
@ -139,7 +135,7 @@ public class AAPSMocker {
|
|||
when(L.isEnabled(any())).thenReturn(true);
|
||||
}
|
||||
|
||||
public static void mockNSUpload(){
|
||||
public static void mockNSUpload() {
|
||||
PowerMockito.mockStatic(NSUpload.class);
|
||||
}
|
||||
|
||||
|
@ -159,11 +155,16 @@ public class AAPSMocker {
|
|||
when(ConfigBuilderPlugin.getCommandQueue()).thenReturn(queue);
|
||||
}
|
||||
|
||||
public static TreatmentsPlugin mockTreatmentPlugin() {
|
||||
PowerMockito.mockStatic(TreatmentsPlugin.class);
|
||||
TreatmentsPlugin treatmentsPlugin = PowerMockito.mock(TreatmentsPlugin.class);
|
||||
when(TreatmentsPlugin.getPlugin()).thenReturn(treatmentsPlugin);
|
||||
return treatmentsPlugin;
|
||||
}
|
||||
|
||||
public static void mockTreatmentService() throws Exception {
|
||||
TreatmentService treatmentService = PowerMockito.mock(TreatmentService.class);
|
||||
TreatmentsPlugin treatmentsPlugin = PowerMockito.mock(TreatmentsPlugin.class);
|
||||
PowerMockito.whenNew(TreatmentService.class).withNoArguments().thenReturn(treatmentService);
|
||||
when(TreatmentsPlugin.getPlugin()).thenReturn(treatmentsPlugin);
|
||||
}
|
||||
|
||||
public static Profile getValidProfile() {
|
||||
|
@ -193,6 +194,14 @@ public class AAPSMocker {
|
|||
return profileStore;
|
||||
}
|
||||
|
||||
public static void mockProfileFunctions() {
|
||||
PowerMockito.mockStatic(ProfileFunctions.class);
|
||||
ProfileFunctions profileFunctions = PowerMockito.mock(ProfileFunctions.class);
|
||||
PowerMockito.when(ProfileFunctions.getInstance()).thenReturn(profileFunctions);
|
||||
profile = getValidProfile();
|
||||
PowerMockito.when(ProfileFunctions.getInstance().getProfile()).thenReturn(profile);
|
||||
}
|
||||
|
||||
private static MockedBus bus = new MockedBus();
|
||||
|
||||
public static void prepareMockedBus() {
|
||||
|
|
|
@ -156,7 +156,7 @@ public class ConstraintsCheckerTest {
|
|||
// Apply all limits
|
||||
Constraint<Double> d = constraintChecker.getMaxBasalAllowed(AAPSMocker.getValidProfile());
|
||||
Assert.assertEquals(0.8d, d.value());
|
||||
Assert.assertEquals(7, d.getReasonList().size());
|
||||
Assert.assertEquals(6, d.getReasonList().size());
|
||||
Assert.assertEquals("DanaR: Limiting basal rate to 0.80 U/h because of pump limit", d.getMostLimitedReasons());
|
||||
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ public class ConstraintsCheckerTest {
|
|||
// Apply all limits
|
||||
Constraint<Integer> i = constraintChecker.getMaxBasalPercentAllowed(AAPSMocker.getValidProfile());
|
||||
Assert.assertEquals((Integer) 100, i.value());
|
||||
Assert.assertEquals(10, i.getReasonList().size()); // 7x Safety & RS & R & Insight
|
||||
Assert.assertEquals(9, i.getReasonList().size()); // 6x Safety & RS & R & Insight
|
||||
Assert.assertEquals("Safety: Limiting percent rate to 100% because of pump limit", i.getMostLimitedReasons());
|
||||
|
||||
}
|
||||
|
|
|
@ -112,8 +112,7 @@ public class SafetyPluginTest {
|
|||
Assert.assertEquals("Safety: Limiting basal rate to 1.00 U/h because of max value in preferences\n" +
|
||||
"Safety: Limiting basal rate to 4.00 U/h because of max basal multiplier\n" +
|
||||
"Safety: Limiting basal rate to 3.00 U/h because of max daily basal multiplier\n" +
|
||||
"Safety: Limiting basal rate to 2.00 U/h because of hard limit\n" +
|
||||
"Safety: Limiting basal rate to 500.00 U/h because of pump limit", c.getReasons());
|
||||
"Safety: Limiting basal rate to 2.00 U/h because of hard limit", c.getReasons());
|
||||
Assert.assertEquals("Safety: Limiting basal rate to 1.00 U/h because of max value in preferences", c.getMostLimitedReasons());
|
||||
|
||||
}
|
||||
|
@ -145,7 +144,6 @@ public class SafetyPluginTest {
|
|||
"Safety: Limiting basal rate to 4.00 U/h because of max basal multiplier\n" +
|
||||
"Safety: Limiting basal rate to 3.00 U/h because of max daily basal multiplier\n" +
|
||||
"Safety: Limiting basal rate to 2.00 U/h because of hard limit\n" +
|
||||
"Safety: Limiting basal rate to 500.00 U/h because of pump limit\n" +
|
||||
"Safety: Limiting percent rate to 100% because of pump limit", i.getReasons());
|
||||
Assert.assertEquals("Safety: Limiting percent rate to 100% because of pump limit", i.getMostLimitedReasons());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
package info.nightscout.androidaps.plugins.Loop;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
import info.AAPSMocker;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.data.ConstraintChecker;
|
||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||
import info.nightscout.androidaps.interfaces.Constraint;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions;
|
||||
import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType;
|
||||
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
|
||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||
import info.nightscout.utils.JsonHelper;
|
||||
import info.nightscout.utils.SP;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.powermock.api.mockito.PowerMockito.when;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, SP.class, Context.class, ProfileFunctions.class, TreatmentsPlugin.class, L.class})
|
||||
public class APSResultTest {
|
||||
VirtualPumpPlugin virtualPumpPlugin;
|
||||
TreatmentsPlugin treatmentsPlugin;
|
||||
Constraint<Boolean> closedLoopEnabled = new Constraint<>(false);
|
||||
|
||||
@Test
|
||||
public void isChangeRequestedTest() {
|
||||
APSResult apsResult = new APSResult();
|
||||
|
||||
// BASAL RATE IN TEST PROFILE IS 1U/h
|
||||
|
||||
// **** PERCENT pump ****
|
||||
virtualPumpPlugin.getPumpDescription().setPumpDescription(PumpType.Cellnovo1); // % based
|
||||
apsResult.usePercent(true);
|
||||
|
||||
// closed loop mode return original request
|
||||
closedLoopEnabled.set(true);
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(null);
|
||||
apsResult.tempBasalRequested(false);
|
||||
Assert.assertEquals(false, apsResult.isChangeRequested());
|
||||
apsResult.tempBasalRequested(true).percent(200).duration(30);
|
||||
Assert.assertEquals(true, apsResult.isChangeRequested());
|
||||
|
||||
// open loop
|
||||
closedLoopEnabled.set(false);
|
||||
// no change requested
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(null);
|
||||
apsResult.tempBasalRequested(false);
|
||||
Assert.assertEquals(false, apsResult.isChangeRequested());
|
||||
|
||||
// request 100% when no temp is running
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(null);
|
||||
apsResult.tempBasalRequested(true).percent(100).duration(30);
|
||||
Assert.assertEquals(false , apsResult.isChangeRequested());
|
||||
|
||||
// request equal temp
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(new TemporaryBasal().percent(70).duration(30));
|
||||
apsResult.tempBasalRequested(true).percent(70).duration(30);
|
||||
Assert.assertEquals(false , apsResult.isChangeRequested());
|
||||
|
||||
// request zero temp
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(new TemporaryBasal().percent(10).duration(30));
|
||||
apsResult.tempBasalRequested(true).percent(0).duration(30);
|
||||
Assert.assertEquals(true , apsResult.isChangeRequested());
|
||||
|
||||
// request high temp
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(new TemporaryBasal().percent(190).duration(30));
|
||||
apsResult.tempBasalRequested(true).percent(200).duration(30);
|
||||
Assert.assertEquals(true , apsResult.isChangeRequested());
|
||||
|
||||
// request slightly different temp
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(new TemporaryBasal().percent(70).duration(30));
|
||||
apsResult.tempBasalRequested(true).percent(80).duration(30);
|
||||
Assert.assertEquals(false , apsResult.isChangeRequested());
|
||||
|
||||
// request different temp
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(new TemporaryBasal().percent(70).duration(30));
|
||||
apsResult.tempBasalRequested(true).percent(120).duration(30);
|
||||
Assert.assertEquals(true , apsResult.isChangeRequested());
|
||||
|
||||
// it should work with absolute temps too
|
||||
// request different temp
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(new TemporaryBasal().absolute(1).duration(30));
|
||||
apsResult.tempBasalRequested(true).percent(100).duration(30);
|
||||
Assert.assertEquals(false , apsResult.isChangeRequested());
|
||||
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(new TemporaryBasal().absolute(2).duration(30));
|
||||
apsResult.tempBasalRequested(true).percent(50).duration(30);
|
||||
Assert.assertEquals(true , apsResult.isChangeRequested());
|
||||
|
||||
// **** ABSOLUTE pump ****
|
||||
virtualPumpPlugin.getPumpDescription().setPumpDescription(PumpType.Medtronic_515_715); // U/h based
|
||||
apsResult.usePercent(false);
|
||||
|
||||
// open loop
|
||||
closedLoopEnabled.set(false);
|
||||
// request 100% when no temp is running
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(null);
|
||||
apsResult.tempBasalRequested(true).rate(1).duration(30);
|
||||
Assert.assertEquals(false , apsResult.isChangeRequested());
|
||||
|
||||
// request equal temp
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(new TemporaryBasal().absolute(2).duration(30));
|
||||
apsResult.tempBasalRequested(true).rate(2).duration(30);
|
||||
Assert.assertEquals(false , apsResult.isChangeRequested());
|
||||
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(new TemporaryBasal().percent(200).duration(30));
|
||||
apsResult.tempBasalRequested(true).rate(2).duration(30);
|
||||
Assert.assertEquals(false , apsResult.isChangeRequested());
|
||||
|
||||
// request zero temp
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(new TemporaryBasal().absolute(0.1d).duration(30));
|
||||
apsResult.tempBasalRequested(true).rate(0).duration(30);
|
||||
Assert.assertEquals(true , apsResult.isChangeRequested());
|
||||
|
||||
// request high temp
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(new TemporaryBasal().absolute(34.9).duration(30));
|
||||
apsResult.tempBasalRequested(true).rate(35).duration(30);
|
||||
Assert.assertEquals(true , apsResult.isChangeRequested());
|
||||
|
||||
// request slightly different temp
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(new TemporaryBasal().absolute(1.1d).duration(30));
|
||||
apsResult.tempBasalRequested(true).rate(1.2d).duration(30);
|
||||
Assert.assertEquals(false , apsResult.isChangeRequested());
|
||||
|
||||
// request different temp
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(new TemporaryBasal().absolute(1.1d).duration(30));
|
||||
apsResult.tempBasalRequested(true).rate(1.5d).duration(30);
|
||||
Assert.assertEquals(true , apsResult.isChangeRequested());
|
||||
|
||||
// it should work with percent temps too
|
||||
// request different temp
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(new TemporaryBasal().percent(110).duration(30));
|
||||
apsResult.tempBasalRequested(true).rate(1.1d).duration(30);
|
||||
Assert.assertEquals(false , apsResult.isChangeRequested());
|
||||
|
||||
when(treatmentsPlugin.getTempBasalFromHistory(anyLong())).thenReturn(new TemporaryBasal().percent(200).duration(30));
|
||||
apsResult.tempBasalRequested(true).rate(0.5d).duration(30);
|
||||
Assert.assertEquals(true , apsResult.isChangeRequested());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloneTest() {
|
||||
APSResult apsResult = new APSResult();
|
||||
apsResult.rate(10);
|
||||
|
||||
APSResult apsResult2 = apsResult.clone();
|
||||
Assert.assertEquals(apsResult.rate, apsResult2.rate, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jsonTest() {
|
||||
closedLoopEnabled.set(true);
|
||||
APSResult apsResult = new APSResult();
|
||||
apsResult.rate(20).tempBasalRequested(true);
|
||||
Assert.assertEquals(20d, JsonHelper.safeGetDouble(apsResult.json(), "rate"), 0d);
|
||||
|
||||
apsResult.rate(20).tempBasalRequested(false);
|
||||
Assert.assertEquals(false, apsResult.json().has("rate"));
|
||||
}
|
||||
|
||||
@Before
|
||||
public void prepareMock() throws Exception {
|
||||
AAPSMocker.mockMainApp();
|
||||
AAPSMocker.mockConfigBuilder();
|
||||
AAPSMocker.mockSP();
|
||||
AAPSMocker.mockStrings();
|
||||
AAPSMocker.mockBus();
|
||||
AAPSMocker.mockProfileFunctions();
|
||||
AAPSMocker.mockTreatmentService();
|
||||
AAPSMocker.mockL();
|
||||
treatmentsPlugin = AAPSMocker.mockTreatmentPlugin();
|
||||
ConstraintChecker constraintChecker = AAPSMocker.mockConstraintsChecker();
|
||||
|
||||
virtualPumpPlugin = VirtualPumpPlugin.getPlugin();
|
||||
when(ConfigBuilderPlugin.getActivePump()).thenReturn(virtualPumpPlugin);
|
||||
|
||||
when(constraintChecker.isClosedLoopAllowed()).thenReturn(closedLoopEnabled);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue