diff --git a/app/build.gradle b/app/build.gradle index 83820ab57d..8366358e50 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -47,6 +47,11 @@ def generateGitBuild = { -> return stringBuilder.toString() } +tasks.matching {it instanceof Test}.all { + testLogging.events = ["failed", "skipped"] + testLogging.exceptionFormat = "full" +} + android { compileSdkVersion 27 buildToolsVersion "${supportLibraryVersion}" @@ -97,21 +102,6 @@ android { buildConfigField "boolean", "APS", "true" buildConfigField "boolean", "PUMPDRIVERS", "true" buildConfigField "boolean", "NSCLIENTOLNY", "false" - buildConfigField "boolean", "CLOSEDLOOP", "true" - buildConfigField "boolean", "G5UPLOADER", "false" - buildConfigField "boolean", "PUMPCONTROL", "false" - } - openloop { - dimension "standard" - resValue "string", "app_name", "AndroidAPS" - versionName version - manifestPlaceholders = [ - appIcon: "@mipmap/blueowl" - ] - buildConfigField "boolean", "APS", "true" - buildConfigField "boolean", "PUMPDRIVERS", "true" - buildConfigField "boolean", "NSCLIENTOLNY", "false" - buildConfigField "boolean", "CLOSEDLOOP", "false" buildConfigField "boolean", "G5UPLOADER", "false" buildConfigField "boolean", "PUMPCONTROL", "false" } @@ -125,7 +115,6 @@ android { buildConfigField "boolean", "APS", "false" buildConfigField "boolean", "PUMPDRIVERS", "true" buildConfigField "boolean", "NSCLIENTOLNY", "false" - buildConfigField "boolean", "CLOSEDLOOP", "false" buildConfigField "boolean", "G5UPLOADER", "false" buildConfigField "boolean", "PUMPCONTROL", "true" } @@ -139,7 +128,6 @@ android { buildConfigField "boolean", "APS", "false" buildConfigField "boolean", "PUMPDRIVERS", "false" buildConfigField "boolean", "NSCLIENTOLNY", "true" - buildConfigField "boolean", "CLOSEDLOOP", "false" buildConfigField "boolean", "G5UPLOADER", "false" buildConfigField "boolean", "PUMPCONTROL", "false" } @@ -153,7 +141,6 @@ android { buildConfigField "boolean", "APS", "false" buildConfigField "boolean", "PUMPDRIVERS", "false" buildConfigField "boolean", "NSCLIENTOLNY", "false" - buildConfigField "boolean", "CLOSEDLOOP", "false" buildConfigField "boolean", "G5UPLOADER", "true" buildConfigField "boolean", "PUMPCONTROL", "false" } diff --git a/app/src/main/java/info/nightscout/androidaps/Constants.java b/app/src/main/java/info/nightscout/androidaps/Constants.java index 0729e9d4b1..1fe9431397 100644 --- a/app/src/main/java/info/nightscout/androidaps/Constants.java +++ b/app/src/main/java/info/nightscout/androidaps/Constants.java @@ -12,10 +12,11 @@ public class Constants { public static final double defaultDIA = 3d; - public static final double basalAbsoluteOnlyForCheckLimit = 10101010d; - public static final Integer basalPercentOnlyForCheckLimit = 10101010; - public static final double bolusOnlyForCheckLimit = 10101010d; - public static final Integer carbsOnlyForCheckLimit = 10101010; + public static final Double REALLYHIGHBASALRATE = 1111111d; + public static final Integer REALLYHIGHPERCENTBASALRATE = 1111111; + public static final double REALLYHIGHBOLUS = 1111111d; + public static final Integer REALLYHIGHCARBS = 1111111; + public static final double REALLYHIGHIOB = 1111111d; public static final Integer notificationID = 556677; diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index 5087fefefa..d369b13fa7 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -25,6 +25,7 @@ import java.util.ArrayList; import ch.qos.logback.classic.LoggerContext; import info.nightscout.androidaps.Services.Intents; +import info.nightscout.androidaps.data.ConstraintChecker; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.PluginBase; @@ -59,7 +60,7 @@ import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; -import info.nightscout.androidaps.plugins.PumpInsight.InsightPumpPlugin; +import info.nightscout.androidaps.plugins.PumpInsight.InsightPlugin; import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin; import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin; @@ -79,7 +80,6 @@ import info.nightscout.androidaps.receivers.KeepAliveReceiver; import info.nightscout.androidaps.receivers.NSAlarmReceiver; import info.nightscout.utils.FabricPrivacy; import info.nightscout.utils.NSUpload; -import info.nightscout.utils.SP; import io.fabric.sdk.android.Fabric; @@ -93,6 +93,7 @@ public class MainApp extends Application { private static DatabaseHelper sDatabaseHelper = null; private static ConfigBuilderPlugin sConfigBuilder = null; + private static ConstraintChecker sConstraintsChecker = null; private static ArrayList pluginsList = null; @@ -109,6 +110,7 @@ public class MainApp extends Application { super.onCreate(); sInstance = this; sResources = getResources(); + sConstraintsChecker = new ConstraintChecker(this); try { if (FabricPrivacy.fabricEnabled()) { @@ -154,7 +156,7 @@ public class MainApp extends Application { if (Config.HWPUMPS) pluginsList.add(DanaRv2Plugin.getPlugin()); if (Config.HWPUMPS) pluginsList.add(DanaRSPlugin.getPlugin()); pluginsList.add(CareportalPlugin.getPlugin()); - if (Config.HWPUMPS && engineeringMode) pluginsList.add(InsightPumpPlugin.getPlugin()); // <-- Enable Insight plugin here + if (Config.HWPUMPS && engineeringMode) pluginsList.add(InsightPlugin.getPlugin()); // <-- Enable Insight plugin here if (Config.HWPUMPS && engineeringMode) pluginsList.add(ComboPlugin.getPlugin()); // <-- Enable Combo plugin here if (Config.MDI) pluginsList.add(MDIPlugin.getPlugin()); if (Config.VIRTUALPUMP) pluginsList.add(VirtualPumpPlugin.getPlugin()); @@ -191,13 +193,14 @@ public class MainApp extends Application { MainApp.getConfigBuilder().initialize(); } NSUpload.uploadAppStart(); + if (Config.NSCLIENT) FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-NSClient")); else if (Config.G5UPLOADER) FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-G5Uploader")); else if (Config.PUMPCONTROL) FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-PumpControl")); - else if (MainApp.getConfigBuilder().isClosedModeEnabled()) + else if (MainApp.getConstraintChecker().isClosedLoopAllowed().value()) FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-ClosedLoop")); else FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-OpenLoop")); @@ -293,6 +296,10 @@ public class MainApp extends Application { return sConfigBuilder; } + public static ConstraintChecker getConstraintChecker() { + return sConstraintsChecker; + } + public static ArrayList getPluginsList() { return pluginsList; } diff --git a/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java b/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java index 0f712c787f..12eb5a1daf 100644 --- a/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java @@ -14,7 +14,6 @@ import android.text.TextUtils; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventRefreshGui; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin; import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin; import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin; @@ -22,6 +21,7 @@ import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin; import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin; +import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; @@ -65,7 +65,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre if (key.equals("short_tabtitles")) { MainApp.bus().post(new EventRefreshGui()); } - if (key.equals("openapsama_useautosens") && SP.getBoolean("openapsama_useautosens", false)) { + if (key.equals(MainApp.gs(R.string.key_openapsama_useautosens)) && SP.getBoolean(R.string.key_openapsama_useautosens, false)) { OKDialog.show(this, MainApp.sResources.getString(R.string.configbuilder_sensitivity), MainApp.sResources.getString(R.string.sensitivity_warning), null); } updatePrefSummary(myPreferenceFragment.getPreference(key)); diff --git a/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java b/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java new file mode 100644 index 0000000000..d984e3277f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java @@ -0,0 +1,180 @@ +package info.nightscout.androidaps.data; + +import java.util.ArrayList; + +import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.interfaces.Constraint; +import info.nightscout.androidaps.interfaces.ConstraintsInterface; +import info.nightscout.androidaps.interfaces.PluginBase; + +/** + * Created by mike on 19.03.2018. + */ + +public class ConstraintChecker implements ConstraintsInterface { + + private MainApp mainApp; + + public ConstraintChecker(MainApp mainApp) { + this.mainApp = mainApp; + } + + + public Constraint isLoopInvokationAllowed() { + return isLoopInvokationAllowed(new Constraint<>(true)); + } + + public Constraint isClosedLoopAllowed() { + return isClosedLoopAllowed(new Constraint<>(true)); + } + + public Constraint isAutosensModeEnabled() { + return isAutosensModeEnabled(new Constraint<>(true)); + } + + public Constraint isAMAModeEnabled() { + return isAMAModeEnabled(new Constraint<>(true)); + } + + public Constraint isSMBModeEnabled() { + return isSMBModeEnabled(new Constraint<>(true)); + } + + public Constraint getMaxBasalAllowed(Profile profile) { + return applyBasalConstraints(new Constraint<>(Constants.REALLYHIGHBASALRATE), profile); + } + + public Constraint getMaxBasalPercentAllowed(Profile profile) { + return applyBasalPercentConstraints(new Constraint<>(Constants.REALLYHIGHPERCENTBASALRATE), profile); + } + + public Constraint getMaxBolusAllowed() { + return applyBolusConstraints(new Constraint<>(Constants.REALLYHIGHBOLUS)); + } + + public Constraint getMaxCarbsAllowed() { + return applyCarbsConstraints(new Constraint<>(Constants.REALLYHIGHCARBS)); + } + + public Constraint getMaxIOBAllowed() { + return applyMaxIOBConstraints(new Constraint<>(Constants.REALLYHIGHIOB)); + } + + @Override + public Constraint isLoopInvokationAllowed(Constraint value) { + + ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constraint = (ConstraintsInterface) p; + if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; + constraint.isLoopInvokationAllowed(value); + } + return value; + } + + @Override + public Constraint isClosedLoopAllowed(Constraint value) { + + ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constraint = (ConstraintsInterface) p; + if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; + constraint.isClosedLoopAllowed(value); + } + return value; + } + + @Override + public Constraint isAutosensModeEnabled(Constraint value) { + + ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constraint = (ConstraintsInterface) p; + if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; + constraint.isAutosensModeEnabled(value); + } + return value; + } + + @Override + public Constraint isAMAModeEnabled(Constraint value) { + + ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constrain = (ConstraintsInterface) p; + if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; + constrain.isAMAModeEnabled(value); + } + return value; + } + + @Override + public Constraint isSMBModeEnabled(Constraint value) { + + ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constraint = (ConstraintsInterface) p; + if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; + constraint.isSMBModeEnabled(value); + } + return value; + } + + @Override + public Constraint applyBasalConstraints(Constraint absoluteRate, Profile profile) { + ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constraint = (ConstraintsInterface) p; + if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; + constraint.applyBasalConstraints(absoluteRate, profile); + } + return absoluteRate; + } + + @Override + public Constraint applyBasalPercentConstraints(Constraint percentRate, Profile profile) { + ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constrain = (ConstraintsInterface) p; + if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; + constrain.applyBasalPercentConstraints(percentRate, profile); + } + return percentRate; + } + + @Override + public Constraint applyBolusConstraints(Constraint insulin) { + ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constrain = (ConstraintsInterface) p; + if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; + constrain.applyBolusConstraints(insulin); + } + return insulin; + } + + @Override + public Constraint applyCarbsConstraints(Constraint carbs) { + ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constrain = (ConstraintsInterface) p; + if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; + constrain.applyCarbsConstraints(carbs); + } + return carbs; + } + + @Override + public Constraint applyMaxIOBConstraints(Constraint maxIob) { + ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constrain = (ConstraintsInterface) p; + if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; + constrain.applyMaxIOBConstraints(maxIob); + } + return maxIob; + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/Constraint.java b/app/src/main/java/info/nightscout/androidaps/interfaces/Constraint.java new file mode 100644 index 0000000000..58e6045bd1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/Constraint.java @@ -0,0 +1,117 @@ +package info.nightscout.androidaps.interfaces; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by mike on 19.03.2018. + */ + +public class Constraint { + private static Logger log = LoggerFactory.getLogger(Constraint.class); + + T value; + T originalValue; + + List reasons = new ArrayList<>(); + List mostLimiting = new ArrayList<>(); + + public Constraint(T value) { + this.value = value; + this.originalValue = value; + } + + public T value() { + return value; + } + + public T originalValue() { + return originalValue; + } + + public Constraint set(T value) { + this.value = value; + this.originalValue = value; + return this; + } + + public Constraint set(T value, String reason, Object from) { + this.value = value; + addReason(reason, from); + addMostLimingReason(reason, from); + return this; + } + + public Constraint setIfSmaller(T value, String reason, Object from) { + if (value.compareTo(this.value) < 0) { + this.value = value; + mostLimiting.clear(); + addMostLimingReason(reason, from); + } + if (value.compareTo(this.originalValue) < 0) { + addReason(reason, from); + } + return this; + } + + public Constraint setIfGreater(T value, String reason, Object from) { + if (value.compareTo(this.value) > 0) { + this.value = value; + mostLimiting.clear(); + addMostLimingReason(reason, from); + } + if (value.compareTo(this.originalValue) > 0) { + addReason(reason, from); + } + return this; + } + + public Constraint addReason(String reason, Object from) { + reasons.add(from.getClass().getSimpleName().replace("Plugin", "") + ": " + reason); + return this; + } + + public Constraint addMostLimingReason(String reason, Object from) { + mostLimiting.add(from.getClass().getSimpleName().replace("Plugin", "") + ": " + reason); + return this; + } + + public String getReasons() { + StringBuilder sb = new StringBuilder(); + int count = 0; + for (String r : reasons) { + if (count++ != 0) sb.append("\n"); + sb.append(r); + } + log.debug("Limiting origial value: " + originalValue + " to " + value + ". Reason: " + sb.toString()); + return sb.toString(); + } + + public List getReasonList() { + return reasons; + } + + public String getMostLimitedReasons() { + StringBuilder sb = new StringBuilder(); + int count = 0; + for (String r : mostLimiting) { + if (count++ != 0) sb.append("\n"); + sb.append(r); + } + log.debug("Limiting origial value: " + originalValue + " to " + value + ". Reason: " + sb.toString()); + return sb.toString(); + } + + public List getMostLimitedReasonList() { + return mostLimiting; + } + + public void copyReasons(Constraint another) { + for (String s: another.getReasonList()) { + reasons.add(s); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java index aac7918bdc..4918cbfacf 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java @@ -1,30 +1,50 @@ package info.nightscout.androidaps.interfaces; -import info.nightscout.androidaps.plugins.Loop.APSResult; +import info.nightscout.androidaps.data.Profile; /** * Created by mike on 15.06.2016. */ public interface ConstraintsInterface { - boolean isLoopEnabled(); + default Constraint isLoopInvokationAllowed(Constraint value) { + return value; + } - boolean isClosedModeEnabled(); + default Constraint isClosedLoopAllowed(Constraint value) { + return value; + } - boolean isAutosensModeEnabled(); + default Constraint isAutosensModeEnabled(Constraint value) { + return value; + } - boolean isAMAModeEnabled(); + default Constraint isAMAModeEnabled(Constraint value) { + return value; + } - boolean isSMBModeEnabled(); + default Constraint isSMBModeEnabled(Constraint value) { + return value; + } - Double applyBasalConstraints(Double absoluteRate); + default Constraint applyBasalConstraints(Constraint absoluteRate, Profile profile) { + return absoluteRate; + } - Integer applyBasalConstraints(Integer percentRate); + default Constraint applyBasalPercentConstraints(Constraint percentRate, Profile profile) { + return percentRate; + } - Double applyBolusConstraints(Double insulin); + default Constraint applyBolusConstraints(Constraint insulin) { + return insulin; + } - Integer applyCarbsConstraints(Integer carbs); + default Constraint applyCarbsConstraints(Constraint carbs) { + return carbs; + } - Double applyMaxIOBConstraints(Double maxIob); + default Constraint applyMaxIOBConstraints(Constraint maxIob) { + return maxIob; + }; } diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java index 08db6210d4..75101b2413 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java @@ -28,7 +28,7 @@ public interface PluginBase { boolean canBeHidden(int type); boolean hasFragment(); boolean showInList(int type); - void setFragmentEnabled(int type, boolean fragmentEnabled); + void setPluginEnabled(int type, boolean fragmentEnabled); void setFragmentVisible(int type, boolean fragmentVisible); int getPreferencesId(); } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java index 45666cf4ae..10d5c58655 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java @@ -35,8 +35,8 @@ public interface PumpInterface { PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo); void stopBolusDelivering(); - PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew); - PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew); + PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew); + PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew); PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes); //some pumps might set a very short temp close to 100% as cancelling a temp can be noisy //when the cancel request is requested by the user (forced), the pump should always do a real cancel diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsPlugin.java index 3c71626e64..3de3acbf18 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsPlugin.java @@ -65,7 +65,7 @@ public class ActionsPlugin implements PluginBase { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == GENERAL) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java index 8297e28412..c0e668439c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java @@ -21,11 +21,11 @@ import org.slf4j.LoggerFactory; import java.text.DecimalFormat; -import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity; import info.nightscout.androidaps.queue.Callback; @@ -60,7 +60,7 @@ public class FillDialog extends DialogFragment implements OnClickListener { getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); - Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit); + Double maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value(); double bolusstep = ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep; editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_insulinamount); editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, new DecimalFormat("0.00"), false); @@ -138,7 +138,7 @@ public class FillDialog extends DialogFragment implements OnClickListener { String confirmMessage = getString(R.string.fillwarning) + "\n"; - Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(insulin); + Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value(); confirmMessage += getString(R.string.bolus) + ": " + insulinAfterConstraints + "U"; if (insulinAfterConstraints - insulin != 0) confirmMessage += "\n" + getString(R.string.constraintapllied); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewExtendedBolusDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewExtendedBolusDialog.java index e2bcbe2acd..04dd783b04 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewExtendedBolusDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewExtendedBolusDialog.java @@ -17,9 +17,9 @@ import org.slf4j.LoggerFactory; import java.text.DecimalFormat; -import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity; import info.nightscout.androidaps.queue.Callback; @@ -43,7 +43,7 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli View view = inflater.inflate(R.layout.overview_newextendedbolus_dialog, container, false); - Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit); + Double maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value(); editInsulin = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_insulin); editInsulin.setParams(0d, 0d, maxInsulin, 0.1d, new DecimalFormat("0.00"), false); @@ -70,7 +70,7 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli String confirmMessage = getString(R.string.setextendedbolusquestion); - Double insulinAfterConstraint = MainApp.getConfigBuilder().applyBolusConstraints(insulin); + Double insulinAfterConstraint = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value(); confirmMessage += " " + insulinAfterConstraint + " U "; confirmMessage += getString(R.string.duration) + " " + durationInMinutes + "min ?"; if (insulinAfterConstraint - insulin != 0d) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewTempBasalDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewTempBasalDialog.java index 8e5c1737c9..fb00879ae4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewTempBasalDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewTempBasalDialog.java @@ -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.getConfigBuilder().applyBasalConstraints(basalPercentInput); + percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(basalPercentInput), profile).value(); 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.getConfigBuilder().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) @@ -157,9 +162,9 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi } }; if (setAsPercent) { - ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(finalBasalPercent, finalDurationInMinutes, true, callback); + ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(finalBasalPercent, finalDurationInMinutes, true, profile, callback); } else { - ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(finalBasal, finalDurationInMinutes, true, callback); + ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(finalBasal, finalDurationInMinutes, true, profile, callback); } FabricPrivacy.getInstance().logCustom(new CustomEvent("TempBasal")); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalPlugin.java index a72fc200ea..1cfd5822ab 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalPlugin.java @@ -71,7 +71,7 @@ public class CareportalPlugin implements PluginBase { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == GENERAL) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java index 99fc44341b..3c77532e11 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java @@ -51,15 +51,15 @@ 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; import info.nightscout.androidaps.queue.Callback; -import info.nightscout.utils.FabricPrivacy; import info.nightscout.utils.DateUtil; +import info.nightscout.utils.FabricPrivacy; import info.nightscout.utils.NSUpload; import info.nightscout.utils.NumberPicker; -import info.nightscout.utils.OKDialog; import info.nightscout.utils.SP; import info.nightscout.utils.SafeParse; import info.nightscout.utils.Translator; @@ -272,11 +272,11 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick } }); - Integer maxCarbs = MainApp.getConfigBuilder().applyCarbsConstraints(Constants.carbsOnlyForCheckLimit); + Integer maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value(); editCarbs = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_carbsinput); editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false); - Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit); + Double maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value(); editInsulin = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_insulininput); editInsulin.setParams(0d, 0d, maxInsulin, 0.05d, new DecimalFormat("0.00"), false); @@ -303,7 +303,9 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick } }; - Integer maxPercent = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalPercentOnlyForCheckLimit); + Integer maxPercent = 200; + if (profile != null) + maxPercent = MainApp.getConstraintChecker().getMaxBasalPercentAllowed(profile).value(); editPercent = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_percentinput); editPercent.setParams(0d, 0d, (double) maxPercent, 5d, new DecimalFormat("0"), true, percentTextWatcher); @@ -325,7 +327,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick } }; - Double maxAbsolute = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalAbsoluteOnlyForCheckLimit); + Double maxAbsolute = MainApp.getConstraintChecker().getMaxBasalAllowed(profile).value(); editAbsolute = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_absoluteinput); editAbsolute.setParams(0d, 0d, maxAbsolute, 0.05d, new DecimalFormat("0.00"), true, absoluteTextWatcher); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java index 8d4c74d607..fd224531b4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java @@ -235,7 +235,7 @@ public class ConfigBuilderFragment extends Fragment { public void onClick(View v) { CheckBox cb = (CheckBox) v; PluginBase plugin = (PluginBase) cb.getTag(); - plugin.setFragmentEnabled(type, cb.isChecked()); + plugin.setPluginEnabled(type, cb.isChecked()); plugin.setFragmentVisible(type, cb.isChecked()); onEnabledCategoryChanged(plugin, type); configBuilderPlugin.storeSettings(); @@ -316,7 +316,7 @@ public class ConfigBuilderFragment extends Fragment { if (type == PluginBase.INSULIN || type == PluginBase.PUMP || type == PluginBase.TREATMENT || type == PluginBase.PROFILE || type == PluginBase.SENSITIVITY) if (pluginList.size() < 2) { holder.checkboxEnabled.setEnabled(false); - plugin.setFragmentEnabled(type, true); + plugin.setPluginEnabled(type, true); getPlugin().storeSettings(); } @@ -390,21 +390,21 @@ public class ConfigBuilderFragment extends Fragment { if (p.getName().equals(changedPlugin.getName())) { // this is new selected } else { - p.setFragmentEnabled(type, false); + p.setPluginEnabled(type, false); p.setFragmentVisible(type, false); } } } else { // enable first plugin in list if (type == PluginBase.PUMP) - MainApp.getSpecificPlugin(VirtualPumpPlugin.class).setFragmentEnabled(type, true); + MainApp.getSpecificPlugin(VirtualPumpPlugin.class).setPluginEnabled(type, true); else if (type == PluginBase.INSULIN) - MainApp.getSpecificPlugin(InsulinFastactingPlugin.class).setFragmentEnabled(type, true); + MainApp.getSpecificPlugin(InsulinFastactingPlugin.class).setPluginEnabled(type, true); else if (type == PluginBase.SENSITIVITY) - MainApp.getSpecificPlugin(SensitivityOref0Plugin.class).setFragmentEnabled(type, true); + MainApp.getSpecificPlugin(SensitivityOref0Plugin.class).setPluginEnabled(type, true); else if (type == PluginBase.PROFILE) - MainApp.getSpecificPlugin(NSProfilePlugin.class).setFragmentEnabled(type, true); + MainApp.getSpecificPlugin(NSProfilePlugin.class).setPluginEnabled(type, true); else - pluginsInCategory.get(0).setFragmentEnabled(type, true); + pluginsInCategory.get(0).setPluginEnabled(type, true); } setViews(); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java index 7f24aac23f..8818c11921 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java @@ -31,7 +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.ConstraintsInterface; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.ProfileInterface; @@ -46,13 +46,12 @@ import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; import info.nightscout.androidaps.queue.Callback; import info.nightscout.androidaps.queue.CommandQueue; import info.nightscout.utils.NSUpload; -import info.nightscout.utils.SP; import info.nightscout.utils.ToastUtils; /** * Created by mike on 05.08.2016. */ -public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, TreatmentsInterface { +public class ConfigBuilderPlugin implements PluginBase, TreatmentsInterface { private static Logger log = LoggerFactory.getLogger(ConfigBuilderPlugin.class); private static BgSourceInterface activeBgSource; @@ -129,7 +128,7 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { // Always enabled } @@ -179,7 +178,7 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr String settingEnabled = "ConfigBuilder_" + type + "_" + p.getClass().getSimpleName() + "_Enabled"; String settingVisible = "ConfigBuilder_" + type + "_" + p.getClass().getSimpleName() + "_Visible"; if (SP.contains(settingEnabled)) - p.setFragmentEnabled(type, SP.getBoolean(settingEnabled, true)); + p.setPluginEnabled(type, SP.getBoolean(settingEnabled, true)); if (SP.contains(settingVisible)) p.setFragmentVisible(type, SP.getBoolean(settingVisible, true) && SP.getBoolean(settingEnabled, true)); } catch (Exception e) { @@ -339,7 +338,7 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr found = p; } else if (p.isEnabled(type)) { // set others disabled - p.setFragmentEnabled(type, false); + p.setPluginEnabled(type, false); } } // If none enabled, enable first one @@ -357,7 +356,9 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr } PumpInterface pump = getActivePump(); - request.rate = applyBasalConstraints(request.rate); + + request.rateConstraint = new Constraint<>(request.rate); + request.rate = MainApp.getConstraintChecker().applyBasalConstraints(request.rateConstraint, profile).value(); if (!pump.isInitialized()) { log.debug("applyAPSRequest: " + MainApp.sResources.getString(R.string.pumpNotInitialized)); @@ -407,7 +408,7 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr } 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); } } @@ -460,134 +461,6 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr getCommandQueue().bolus(detailedBolusInfo, callback); } - /** - * Constraints interface - **/ - @Override - public boolean isLoopEnabled() { - boolean result = true; - - ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); - for (PluginBase p : constraintsPlugins) { - ConstraintsInterface constrain = (ConstraintsInterface) p; - if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; - result = result && constrain.isLoopEnabled(); - } - return result; - } - - @Override - public boolean isClosedModeEnabled() { - boolean result = true; - - ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); - for (PluginBase p : constraintsPlugins) { - ConstraintsInterface constrain = (ConstraintsInterface) p; - if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; - result = result && constrain.isClosedModeEnabled(); - } - return result; - } - - @Override - public boolean isAutosensModeEnabled() { - boolean result = true; - - ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); - for (PluginBase p : constraintsPlugins) { - ConstraintsInterface constrain = (ConstraintsInterface) p; - if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; - result = result && constrain.isAutosensModeEnabled(); - } - return result; - } - - @Override - public boolean isAMAModeEnabled() { - boolean result = SP.getBoolean("openapsama_useautosens", false); - - ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); - for (PluginBase p : constraintsPlugins) { - ConstraintsInterface constrain = (ConstraintsInterface) p; - if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; - result = result && constrain.isAMAModeEnabled(); - } - return result; - } - - @Override - public boolean isSMBModeEnabled() { - boolean result = true; // TODO update for SMB // SP.getBoolean("openapsama_useautosens", false); - - ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); - for (PluginBase p : constraintsPlugins) { - ConstraintsInterface constrain = (ConstraintsInterface) p; - if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; - result = result && constrain.isSMBModeEnabled(); - } - return result; - } - - @Override - public Double applyBasalConstraints(Double absoluteRate) { - Double rateAfterConstrain = absoluteRate; - ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); - for (PluginBase p : constraintsPlugins) { - ConstraintsInterface constrain = (ConstraintsInterface) p; - if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; - rateAfterConstrain = Math.min(constrain.applyBasalConstraints(absoluteRate), rateAfterConstrain); - } - return rateAfterConstrain; - } - - @Override - public Integer applyBasalConstraints(Integer percentRate) { - Integer rateAfterConstrain = percentRate; - ArrayList 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); - } - return rateAfterConstrain; - } - - @Override - public Double applyBolusConstraints(Double insulin) { - Double insulinAfterConstrain = insulin; - ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); - for (PluginBase p : constraintsPlugins) { - ConstraintsInterface constrain = (ConstraintsInterface) p; - if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; - insulinAfterConstrain = Math.min(constrain.applyBolusConstraints(insulin), insulinAfterConstrain); - } - return insulinAfterConstrain; - } - - @Override - public Integer applyCarbsConstraints(Integer carbs) { - Integer carbsAfterConstrain = carbs; - ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); - for (PluginBase p : constraintsPlugins) { - ConstraintsInterface constrain = (ConstraintsInterface) p; - if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; - carbsAfterConstrain = Math.min(constrain.applyCarbsConstraints(carbs), carbsAfterConstrain); - } - return carbsAfterConstrain; - } - - @Override - public Double applyMaxIOBConstraints(Double maxIob) { - Double maxIobAfterConstrain = maxIob; - ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); - for (PluginBase p : constraintsPlugins) { - ConstraintsInterface constrain = (ConstraintsInterface) p; - if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; - maxIobAfterConstrain = Math.min(constrain.applyMaxIOBConstraints(maxIob), maxIobAfterConstrain); - } - return maxIobAfterConstrain; - } - // ****** Treatments interface ***** @Override public void updateTotalIOBTreatments() { @@ -823,9 +696,9 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr return null; } - public void disconnectPump(int durationInMinutes) { + public void disconnectPump(int durationInMinutes, Profile profile) { getActiveLoop().disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L); - getCommandQueue().tempBasalPercent(0, durationInMinutes, true, new Callback() { + getCommandQueue().tempBasalPercent(0, durationInMinutes, true, profile, new Callback() { @Override public void run() { if (!result.success) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java index 3b0891680d..ba67fbe8d3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java @@ -10,12 +10,14 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; -import info.nightscout.androidaps.BuildConfig; 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.Profile; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.interfaces.APSInterface; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; @@ -67,7 +69,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface { @Override public String getNameShort() { - String name = MainApp.sResources.getString(R.string.objectives_shortname); + String name = MainApp.gs(R.string.objectives_shortname); if (!name.trim().isEmpty()) { //only if translation exists return name; @@ -102,7 +104,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { } @Override @@ -115,7 +117,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface { return -1; } - class Objective { + public class Objective { Integer num; String objective; String gate; @@ -131,6 +133,18 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface { this.durationInDays = durationInDays; this.accomplished = accomplished; } + + public void setStarted(Date started) { + this.started = started; + } + + boolean isStarted() { + return started.getTime() > 0; + } + + boolean isFinished() { + return accomplished.getTime() != 0; + } } // Objective 0 @@ -169,26 +183,27 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface { apsEnabled = true; return new RequirementResult(hasBGData && bgIsAvailableInNS && pumpStatusIsAvailableInNS && NSClientInternalPlugin.getPlugin().hasWritePermission() && LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP) && apsEnabled && vpUploadNeeded, - MainApp.sResources.getString(R.string.objectives_bgavailableinns) + ": " + yesOrNo(bgIsAvailableInNS) - + "\n" + MainApp.sResources.getString(R.string.nsclienthaswritepermission) + ": " + yesOrNo(NSClientInternalPlugin.getPlugin().hasWritePermission()) - + (isVirtualPump ? "\n" + MainApp.sResources.getString(R.string.virtualpump_uploadstatus_title) + ": " + yesOrNo(vpUploadEnabled) : "") - + "\n" + MainApp.sResources.getString(R.string.objectives_pumpstatusavailableinns) + ": " + yesOrNo(pumpStatusIsAvailableInNS) - + "\n" + MainApp.sResources.getString(R.string.hasbgdata) + ": " + yesOrNo(hasBGData) - + "\n" + MainApp.sResources.getString(R.string.loopenabled) + ": " + yesOrNo(LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP)) - + "\n" + MainApp.sResources.getString(R.string.apsselected) + ": " + yesOrNo(apsEnabled) + MainApp.gs(R.string.objectives_bgavailableinns) + ": " + yesOrNo(bgIsAvailableInNS) + + "\n" + MainApp.gs(R.string.nsclienthaswritepermission) + ": " + yesOrNo(NSClientInternalPlugin.getPlugin().hasWritePermission()) + + (isVirtualPump ? "\n" + MainApp.gs(R.string.virtualpump_uploadstatus_title) + ": " + yesOrNo(vpUploadEnabled) : "") + + "\n" + MainApp.gs(R.string.objectives_pumpstatusavailableinns) + ": " + yesOrNo(pumpStatusIsAvailableInNS) + + "\n" + MainApp.gs(R.string.hasbgdata) + ": " + yesOrNo(hasBGData) + + "\n" + MainApp.gs(R.string.loopenabled) + ": " + yesOrNo(LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP)) + + "\n" + MainApp.gs(R.string.apsselected) + ": " + yesOrNo(apsEnabled) ); case 1: return new RequirementResult(manualEnacts >= manualEnactsNeeded, - MainApp.sResources.getString(R.string.objectives_manualenacts) + ": " + manualEnacts + "/" + manualEnactsNeeded); + MainApp.gs(R.string.objectives_manualenacts) + ": " + manualEnacts + "/" + manualEnactsNeeded); case 2: return new RequirementResult(true, ""); case 3: - boolean closedModeEnabled = SafetyPlugin.getPlugin().isClosedModeEnabled(); - return new RequirementResult(closedModeEnabled, MainApp.sResources.getString(R.string.closedmodeenabled) + ": " + yesOrNo(closedModeEnabled)); + Constraint closedLoopEnabled = new Constraint<>(true); + SafetyPlugin.getPlugin().isClosedLoopAllowed(closedLoopEnabled); + return new RequirementResult(closedLoopEnabled.value(), MainApp.gs(R.string.closedmodeenabled) + ": " + yesOrNo(closedLoopEnabled.value())); case 4: - double maxIOB = MainApp.getConfigBuilder().applyMaxIOBConstraints(1000d); + double maxIOB = MainApp.getConstraintChecker().getMaxIOBAllowed().value(); boolean maxIobSet = maxIOB > 0; - return new RequirementResult(maxIobSet, MainApp.sResources.getString(R.string.maxiobset) + ": " + yesOrNo(maxIobSet)); + return new RequirementResult(maxIobSet, MainApp.gs(R.string.maxiobset) + ": " + yesOrNo(maxIobSet)); default: return new RequirementResult(true, ""); } @@ -202,49 +217,49 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface { objectives = new ArrayList<>(); objectives.add(new Objective(0, - MainApp.sResources.getString(R.string.objectives_0_objective), - MainApp.sResources.getString(R.string.objectives_0_gate), + MainApp.gs(R.string.objectives_0_objective), + MainApp.gs(R.string.objectives_0_gate), new Date(0), 0, // 0 day new Date(0))); objectives.add(new Objective(1, - MainApp.sResources.getString(R.string.objectives_1_objective), - MainApp.sResources.getString(R.string.objectives_1_gate), + MainApp.gs(R.string.objectives_1_objective), + MainApp.gs(R.string.objectives_1_gate), new Date(0), 7, // 7 days new Date(0))); objectives.add(new Objective(2, - MainApp.sResources.getString(R.string.objectives_2_objective), - MainApp.sResources.getString(R.string.objectives_2_gate), + MainApp.gs(R.string.objectives_2_objective), + MainApp.gs(R.string.objectives_2_gate), new Date(0), 0, // 0 days new Date(0))); objectives.add(new Objective(3, - MainApp.sResources.getString(R.string.objectives_3_objective), - MainApp.sResources.getString(R.string.objectives_3_gate), + MainApp.gs(R.string.objectives_3_objective), + MainApp.gs(R.string.objectives_3_gate), new Date(0), 5, // 5 days new Date(0))); objectives.add(new Objective(4, - MainApp.sResources.getString(R.string.objectives_4_objective), - MainApp.sResources.getString(R.string.objectives_4_gate), + MainApp.gs(R.string.objectives_4_objective), + MainApp.gs(R.string.objectives_4_gate), new Date(0), 1, new Date(0))); objectives.add(new Objective(5, - MainApp.sResources.getString(R.string.objectives_5_objective), - MainApp.sResources.getString(R.string.objectives_5_gate), + MainApp.gs(R.string.objectives_5_objective), + MainApp.gs(R.string.objectives_5_gate), new Date(0), 7, new Date(0))); objectives.add(new Objective(6, - MainApp.sResources.getString(R.string.objectives_6_objective), + MainApp.gs(R.string.objectives_6_objective), "", new Date(0), 28, new Date(0))); objectives.add(new Objective(7, - MainApp.sResources.getString(R.string.objectives_7_objective), + MainApp.gs(R.string.objectives_7_objective), "", new Date(0), 28, @@ -294,60 +309,45 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface { * Constraints interface **/ @Override - public boolean isLoopEnabled() { - return objectives.get(0).started.getTime() > 0; + public Constraint isLoopInvokationAllowed(Constraint value) { + if (!objectives.get(0).isStarted()) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 1), this); + return value; } @Override - public boolean isClosedModeEnabled() { - return objectives.get(3).started.getTime() > 0; + public Constraint isClosedLoopAllowed(Constraint value) { + if (!objectives.get(3).isStarted()) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 4), this); + return value; } @Override - public boolean isAutosensModeEnabled() { - return objectives.get(5).started.getTime() > 0; + public Constraint isAutosensModeEnabled(Constraint value) { + if (!objectives.get(5).isStarted()) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 6), this); + return value; } @Override - public boolean isAMAModeEnabled() { - return objectives.get(6).started.getTime() > 0; + public Constraint isAMAModeEnabled(Constraint value) { + if (!objectives.get(6).isStarted()) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 7), this); + return value; } @Override - public boolean isSMBModeEnabled() { - return objectives.get(7).started.getTime() > 0; + public Constraint isSMBModeEnabled(Constraint value) { + if (!objectives.get(7).isStarted()) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 8), this); + return value; } @Override - public Double applyMaxIOBConstraints(Double maxIob) { - if (objectives.get(3).started.getTime() > 0 && objectives.get(3).accomplished.getTime() == 0) { - if (Config.logConstraintsChanges) - log.debug("Limiting maxIOB " + maxIob + " to " + 0 + "U"); - return 0d; - } else { - return maxIob; - } + public Constraint applyMaxIOBConstraints(Constraint maxIob) { + if (objectives.get(3).isStarted() && !objectives.get(3).isFinished()) + maxIob.set(0d, String.format(MainApp.gs(R.string.objectivenotfinished), 4), this); + return maxIob; } - @Override - public Double applyBasalConstraints(Double absoluteRate) { - return absoluteRate; - } - - @Override - public Integer applyBasalConstraints(Integer percentRate) { - return percentRate; - } - - @Override - public Double applyBolusConstraints(Double insulin) { - return insulin; - } - - @Override - public Integer applyCarbsConstraints(Integer carbs) { - return carbs; - } - - } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java index 41a7c1eb00..5c792c9405 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java @@ -3,17 +3,17 @@ package info.nightscout.androidaps.plugins.ConstraintsSafety; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Objects; - -import info.nightscout.androidaps.BuildConfig; -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.Profile; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; +import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin; +import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin; +import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.HardLimits; import info.nightscout.utils.Round; import info.nightscout.utils.SP; @@ -79,7 +79,7 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { } @@ -92,142 +92,118 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface { return R.xml.pref_safety; } - @Override - public boolean isLoopEnabled() { - return ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; - } - /** * Constraints interface **/ @Override - public boolean isClosedModeEnabled() { - if (!MainApp.isEngineeringModeOrRelease()) return false; + public Constraint isLoopInvokationAllowed(Constraint value) { + if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable) + value.set(false, MainApp.gs(R.string.pumpisnottempbasalcapable), this); + return value; + } + + @Override + public Constraint isClosedLoopAllowed(Constraint value) { + if (!MainApp.isEngineeringModeOrRelease()) + value.set(false, MainApp.gs(R.string.closed_loop_disabled_on_dev_branch), this); + String mode = SP.getString("aps_mode", "open"); - return mode.equals("closed") && BuildConfig.CLOSEDLOOP; + if (!mode.equals("closed")) + value.set(false, MainApp.gs(R.string.closedmodedisabledinpreferences), this); + return value; } @Override - public boolean isAutosensModeEnabled() { - return true; + public Constraint isAutosensModeEnabled(Constraint value) { + boolean enabled = SP.getBoolean(R.string.key_openapsama_useautosens, false); + if (!enabled) + value.set(false, MainApp.gs(R.string.autosensdisabledinpreferences), this); + return value; } @Override - public boolean isAMAModeEnabled() { - return true; + public Constraint isSMBModeEnabled(Constraint value) { + boolean enabled = SP.getBoolean(R.string.key_use_smb, false); + if (!enabled) + value.set(false, MainApp.gs(R.string.smbdisabledinpreferences), this); + return value; } @Override - public boolean isSMBModeEnabled() { - return true; - } + public Constraint applyBasalConstraints(Constraint absoluteRate, Profile profile) { - @Override - public Double applyBasalConstraints(Double absoluteRate) { - Double origAbsoluteRate = absoluteRate; - Double maxBasal = SP.getDouble("openapsma_max_basal", 1d); + absoluteRate.setIfGreater(0d, String.format(MainApp.gs(R.string.limitingbasalratio), 0d, MainApp.gs(R.string.itmustbepositivevalue)), this); - Profile profile = MainApp.getConfigBuilder().getProfile(); - if (profile == null) return absoluteRate; - if (absoluteRate < 0) absoluteRate = 0d; + 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.maxvalueinpreferences)), this); - 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)), this); + + Double maxBasalFromDaily = SP.getDouble(R.string.key_openapsama_max_daily_safety_multiplier, 3d); + double maxFromDaily = Math.floor(profile.getMaxDailyBasal() * maxBasalFromDaily * 100) / 100; + absoluteRate.setIfSmaller(maxFromDaily, String.format(MainApp.gs(R.string.limitingbasalratio), maxFromDaily, MainApp.gs(R.string.maxdailybasalmultiplier)), this); + + absoluteRate.setIfSmaller(HardLimits.maxBasal(), String.format(MainApp.gs(R.string.limitingbasalratio), HardLimits.maxBasal(), MainApp.gs(R.string.hardlimit)), this); return absoluteRate; } @Override - public Integer applyBasalConstraints(Integer percentRate) { - Integer origPercentRate = percentRate; - Double maxBasal = SP.getDouble("openapsma_max_basal", 1d); + public Constraint applyBasalPercentConstraints(Constraint percentRate, Profile profile) { - Profile profile = MainApp.getConfigBuilder().getProfile(); - if (profile == null) return percentRate; Double currentBasal = profile.getBasal(); + Double absoluteRate = currentBasal * ((double) percentRate.originalValue() / 100); - Double absoluteRate = currentBasal * ((double) percentRate / 100); + percentRate.addReason("Percent rate " + percentRate.originalValue() + "% recalculated to " + DecimalFormatter.to2Decimal(absoluteRate) + " U/h with current basal " + DecimalFormatter.to2Decimal(currentBasal) + " U/h", this); - if (Config.logConstraintsChanges) - log.debug("Percent rate " + percentRate + "% recalculated to " + absoluteRate + "U/h with current basal " + currentBasal + "U/h"); + Constraint absoluteConstraint = new Constraint<>(absoluteRate); + applyBasalConstraints(absoluteConstraint, profile); + percentRate.copyReasons(absoluteConstraint); - 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); - // Check percentRate but absolute rate too, because we know real current basal in pump - Double origRate = absoluteRate; - if (absoluteRate > maxBasal) { - absoluteRate = maxBasal; - if (Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) - log.debug("Limiting rate " + origRate + " by maxBasal preference to " + absoluteRate + "U/h"); - } - if (absoluteRate > maxBasalMult * profile.getBasal()) { - absoluteRate = Math.floor(maxBasalMult * profile.getBasal() * 100) / 100; - if (Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) - log.debug("Limiting rate " + origRate + " by maxBasalMult to " + absoluteRate + "U/h"); - } - if (absoluteRate > profile.getMaxDailyBasal() * maxBasalFromDaily) { - absoluteRate = profile.getMaxDailyBasal() * maxBasalFromDaily; - if (Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) - log.debug("Limiting rate " + origRate + " by 3 * maxDailyBasal to " + absoluteRate + "U/h"); - } - - Integer percentRateAfterConst = new Double(absoluteRate / currentBasal * 100).intValue(); + Integer percentRateAfterConst = Double.valueOf(absoluteConstraint.value() / currentBasal * 100).intValue(); if (percentRateAfterConst < 100) percentRateAfterConst = Round.ceilTo((double) percentRateAfterConst, 10d).intValue(); else percentRateAfterConst = Round.floorTo((double) percentRateAfterConst, 10d).intValue(); - if (Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) - log.debug("Recalculated percent rate " + percentRate + "% to " + percentRateAfterConst + "%"); - return percentRateAfterConst; + percentRate.set(percentRateAfterConst, String.format(MainApp.gs(R.string.limitingpercentrate), percentRateAfterConst, MainApp.gs(R.string.pumplimit)), this); + + return percentRate; } @Override - public Double applyBolusConstraints(Double insulin) { - try { - Double maxBolus = SP.getDouble("treatmentssafety_maxbolus", 3d); + public Constraint applyBolusConstraints(Constraint insulin) { + insulin.setIfGreater(0d, String.format(MainApp.gs(R.string.limitingbolus), 0d, MainApp.gs(R.string.itmustbepositivevalue)), this); - if (insulin < 0) insulin = 0d; - if (insulin > maxBolus) insulin = maxBolus; - } catch (Exception e) { - insulin = 0d; - } - if (insulin > HardLimits.maxBolus()) insulin = HardLimits.maxBolus(); + Double maxBolus = SP.getDouble(R.string.key_treatmentssafety_maxbolus, 3d); + insulin.setIfSmaller(maxBolus, String.format(MainApp.gs(R.string.limitingbolus), maxBolus, MainApp.gs(R.string.maxvalueinpreferences)), this); + + insulin.setIfSmaller(HardLimits.maxBolus(), String.format(MainApp.gs(R.string.limitingbolus), HardLimits.maxBolus(), MainApp.gs(R.string.hardlimit)), this); return insulin; } @Override - public Integer applyCarbsConstraints(Integer carbs) { - try { - Integer maxCarbs = SP.getInt("treatmentssafety_maxcarbs", 48); + public Constraint applyCarbsConstraints(Constraint carbs) { + carbs.setIfGreater(0, String.format(MainApp.gs(R.string.limitingcarbs), 0, MainApp.gs(R.string.itmustbepositivevalue)), this); + + Integer maxCarbs = SP.getInt(R.string.key_treatmentssafety_maxcarbs, 48); + carbs.setIfSmaller(maxCarbs, String.format(MainApp.gs(R.string.limitingcarbs), maxCarbs, MainApp.gs(R.string.maxvalueinpreferences)), this); - if (carbs < 0) carbs = 0; - if (carbs > maxCarbs) carbs = maxCarbs; - } catch (Exception e) { - carbs = 0; - } return carbs; } @Override - public Double applyMaxIOBConstraints(Double maxIob) { + public Constraint applyMaxIOBConstraints(Constraint maxIob) { + double maxIobPref = SP.getDouble(R.string.key_openapsma_max_iob, 1.5d); + maxIob.setIfSmaller(maxIobPref, String.format(MainApp.gs(R.string.limitingiob), maxIobPref, MainApp.gs(R.string.maxvalueinpreferences)), this); + + if (OpenAPSMAPlugin.getPlugin().isEnabled(PluginBase.APS)) + maxIob.setIfSmaller(HardLimits.maxIobAMA(), String.format(MainApp.gs(R.string.limitingiob), HardLimits.maxIobAMA(), MainApp.gs(R.string.hardlimit)), this); + if (OpenAPSAMAPlugin.getPlugin().isEnabled(PluginBase.APS)) + maxIob.setIfSmaller(HardLimits.maxIobAMA(), String.format(MainApp.gs(R.string.limitingiob), HardLimits.maxIobAMA(), MainApp.gs(R.string.hardlimit)), this); + if (OpenAPSSMBPlugin.getPlugin().isEnabled(PluginBase.APS)) + maxIob.setIfSmaller(HardLimits.maxIobSMB(), String.format(MainApp.gs(R.string.limitingiob), HardLimits.maxIobSMB(), MainApp.gs(R.string.hardlimit)), this); return maxIob; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodPlugin.java index 64517a19a5..2f7337566e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodPlugin.java @@ -73,7 +73,7 @@ public class FoodPlugin implements PluginBase { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == GENERAL) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinFastactingPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinFastactingPlugin.java index 6218a2ecfe..bb9c035115 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinFastactingPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinFastactingPlugin.java @@ -71,7 +71,7 @@ public class InsulinFastactingPlugin implements PluginBase, InsulinInterface { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == INSULIN) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinFastactingProlongedPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinFastactingProlongedPlugin.java index d336786f49..6afb867ec9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinFastactingProlongedPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinFastactingProlongedPlugin.java @@ -72,7 +72,7 @@ public class InsulinFastactingProlongedPlugin implements PluginBase, InsulinInte } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == INSULIN) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefFreePeakPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefFreePeakPlugin.java index 3cc2e6b9ca..76667d3ad7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefFreePeakPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefFreePeakPlugin.java @@ -59,7 +59,7 @@ public class InsulinOrefFreePeakPlugin extends InsulinOrefBasePlugin { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == INSULIN) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefRapidActingPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefRapidActingPlugin.java index cae9ac540d..86af7f8130 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefRapidActingPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefRapidActingPlugin.java @@ -58,7 +58,7 @@ public class InsulinOrefRapidActingPlugin extends InsulinOrefBasePlugin { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == INSULIN) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefUltraRapidActingPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefUltraRapidActingPlugin.java index 0d390a3ba2..0c24bb1034 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefUltraRapidActingPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefUltraRapidActingPlugin.java @@ -58,7 +58,7 @@ public class InsulinOrefUltraRapidActingPlugin extends InsulinOrefBasePlugin { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == INSULIN) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java index c60991253c..0009287354 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java @@ -117,7 +117,7 @@ public class IobCobCalculatorPlugin implements PluginBase { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java index 7eab0e7722..9b851c64c1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java @@ -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,11 @@ public class APSResult { public double smb = 0d; // super micro bolus in units public long deliverAt = 0; + public Constraint inputConstraints; + + public Constraint rateConstraint; + public Constraint smbConstraint; + @Override public String toString() { final PumpInterface pump = ConfigBuilderPlugin.getActivePump(); @@ -76,8 +82,8 @@ public class APSResult { ret = MainApp.sResources.getString(R.string.let_temp_basal_run) + "
"; else ret = "" + MainApp.sResources.getString(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " + - "(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%)
" + - "" + MainApp.sResources.getString(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration) + " min
"; + "(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%)
" + + "" + MainApp.sResources.getString(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration) + " min
"; // smb if (smb != 0) @@ -101,6 +107,12 @@ public class APSResult { newResult.tempBasalRequested = tempBasalRequested; 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; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java index c9b60ab3d6..19ed6496e7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java @@ -20,6 +20,7 @@ import butterknife.ButterKnife; import butterknife.OnClick; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui; import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui; @@ -40,6 +41,8 @@ public class LoopFragment extends SubscriberFragment { TextView requestView; @BindView(R.id.loop_constraintsprocessed) TextView constraintsProcessedView; + @BindView(R.id.loop_constraints) + TextView constraintsView; @BindView(R.id.loop_tbrsetbypump) TextView tbrSetByPumpView; @BindView(R.id.loop_smbsetbypump) @@ -85,14 +88,26 @@ public class LoopFragment extends SubscriberFragment { Activity activity = getActivity(); if (activity != null) activity.runOnUiThread(() -> { - if (LoopPlugin.lastRun != null) { - requestView.setText(LoopPlugin.lastRun.request != null ? LoopPlugin.lastRun.request.toSpanned() : ""); - constraintsProcessedView.setText(LoopPlugin.lastRun.constraintsProcessed != null ? LoopPlugin.lastRun.constraintsProcessed.toSpanned() : ""); - sourceView.setText(LoopPlugin.lastRun.source != null ? LoopPlugin.lastRun.source : ""); - lastRunView.setText(LoopPlugin.lastRun.lastAPSRun != null && LoopPlugin.lastRun.lastAPSRun.getTime() != 0 ? LoopPlugin.lastRun.lastAPSRun.toLocaleString() : ""); - lastEnactView.setText(LoopPlugin.lastRun.lastEnact != null && LoopPlugin.lastRun.lastEnact.getTime() != 0 ? LoopPlugin.lastRun.lastEnact.toLocaleString() : ""); - tbrSetByPumpView.setText(LoopPlugin.lastRun.tbrSetByPump != null ? LoopPlugin.lastRun.tbrSetByPump.toSpanned() : ""); - smbSetByPumpView.setText(LoopPlugin.lastRun.smbSetByPump != null ? LoopPlugin.lastRun.smbSetByPump.toSpanned() : ""); + LoopPlugin.LastRun lastRun = LoopPlugin.lastRun; + if (lastRun != null) { + requestView.setText(lastRun.request != null ? lastRun.request.toSpanned() : ""); + constraintsProcessedView.setText(lastRun.constraintsProcessed != null ? lastRun.constraintsProcessed.toSpanned() : ""); + sourceView.setText(lastRun.source != null ? lastRun.source : ""); + lastRunView.setText(lastRun.lastAPSRun != null && lastRun.lastAPSRun.getTime() != 0 ? lastRun.lastAPSRun.toLocaleString() : ""); + lastEnactView.setText(lastRun.lastEnact != null && lastRun.lastEnact.getTime() != 0 ? lastRun.lastEnact.toLocaleString() : ""); + tbrSetByPumpView.setText(lastRun.tbrSetByPump != null ? lastRun.tbrSetByPump.toSpanned() : ""); + smbSetByPumpView.setText(lastRun.smbSetByPump != null ? lastRun.smbSetByPump.toSpanned() : ""); + + String constraints = ""; + if (lastRun.constraintsProcessed != null) { + Constraint allConstraints = new Constraint<>(0d); + if (lastRun.constraintsProcessed.rateConstraint != null) + allConstraints.copyReasons(lastRun.constraintsProcessed.rateConstraint); + if (lastRun.constraintsProcessed.smbConstraint != null) + allConstraints.copyReasons(lastRun.constraintsProcessed.smbConstraint); + constraints = allConstraints.getMostLimitedReasons(); + } + constraintsView.setText(constraints); } }); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java index e727ce9f7e..c2f765e47e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java @@ -26,9 +26,9 @@ import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.interfaces.APSInterface; -import info.nightscout.androidaps.interfaces.ConstraintsInterface; 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.events.EventAutosensCalculationFinished; import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui; @@ -46,7 +46,7 @@ import info.nightscout.utils.SP; public class LoopPlugin implements PluginBase { private static Logger log = LoggerFactory.getLogger(LoopPlugin.class); - private static LoopPlugin loopPlugin; + protected static LoopPlugin loopPlugin; public static LoopPlugin getPlugin() { if (loopPlugin == null) { @@ -55,7 +55,7 @@ public class LoopPlugin implements PluginBase { return loopPlugin; } - private boolean fragmentEnabled = false; + private boolean pluginEnabled = false; private boolean fragmentVisible = false; private long loopSuspendedTill = 0L; // end of manual loop suspend @@ -94,12 +94,12 @@ public class LoopPlugin implements PluginBase { @Override public String getName() { - return MainApp.instance().getString(R.string.loop); + return MainApp.instance().gs(R.string.loop); } @Override public String getNameShort() { - String name = MainApp.sResources.getString(R.string.loop_shortname); + String name = MainApp.gs(R.string.loop_shortname); if (!name.trim().isEmpty()) { //only if translation exists return name; @@ -111,7 +111,7 @@ public class LoopPlugin implements PluginBase { @Override public boolean isEnabled(int type) { boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; - return type == LOOP && fragmentEnabled && pumpCapable; + return type == LOOP && pluginEnabled && pumpCapable; } @Override @@ -136,8 +136,8 @@ public class LoopPlugin implements PluginBase { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { - if (type == LOOP) this.fragmentEnabled = fragmentEnabled; + public void setPluginEnabled(int type, boolean pluginEnabled) { + if (type == LOOP) this.pluginEnabled = pluginEnabled; } @Override @@ -152,7 +152,7 @@ public class LoopPlugin implements PluginBase { @Subscribe public void onStatusEvent(final EventTreatmentChange ev) { - if (ev.treatment == null || !ev.treatment.isSMB){ + if (ev.treatment == null || !ev.treatment.isSMB) { invoke("EventTreatmentChange", true); } } @@ -255,10 +255,12 @@ public class LoopPlugin implements PluginBase { try { if (Config.logFunctionCalls) log.debug("invoke from " + initiator); - ConstraintsInterface constraintsInterface = MainApp.getConfigBuilder(); - if (!constraintsInterface.isLoopEnabled()) { - log.debug(MainApp.sResources.getString(R.string.loopdisabled)); - MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.loopdisabled))); + Constraint loopEnabled = MainApp.getConstraintChecker().isLoopInvokationAllowed(); + + if (!loopEnabled.value()) { + String message = MainApp.sResources.getString(R.string.loopdisabled) + "\n" + loopEnabled.getReasons(); + log.debug(message); + MainApp.bus().post(new EventLoopSetLastRunGui(message)); return; } final PumpInterface pump = ConfigBuilderPlugin.getActivePump(); @@ -292,8 +294,10 @@ public class LoopPlugin implements PluginBase { // check rate for constrais final APSResult resultAfterConstraints = result.clone(); - resultAfterConstraints.rate = constraintsInterface.applyBasalConstraints(resultAfterConstraints.rate); - resultAfterConstraints.smb = constraintsInterface.applyBolusConstraints(resultAfterConstraints.smb); + resultAfterConstraints.rateConstraint = new Constraint<>(resultAfterConstraints.rate); + resultAfterConstraints.rate = MainApp.getConstraintChecker().applyBasalConstraints(resultAfterConstraints.rateConstraint, 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(); @@ -324,7 +328,9 @@ public class LoopPlugin implements PluginBase { return; } - if (constraintsInterface.isClosedModeEnabled()) { + Constraint closedLoopEnabled = MainApp.getConstraintChecker().isClosedLoopAllowed(); + + if (closedLoopEnabled.value()) { if (result.isChangeRequested()) { final PumpEnactResult waiting = new PumpEnactResult(); waiting.queued = true; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientInternalPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientInternalPlugin.java index a51ea18cc7..162c33381f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientInternalPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientInternalPlugin.java @@ -126,7 +126,7 @@ public class NSClientInternalPlugin implements PluginBase { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == GENERAL) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java index 5fc7809f4e..0c92df635c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java @@ -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.getConfigBuilder().isAMAModeEnabled()) { + if (MainApp.getConstraintChecker().isAutosensModeEnabled().value()) { mAutosensData = new JSONObject(); mAutosensData.put("ratio", autosensDataRatio); } else { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java index f2d792d9e9..4c69a347b4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java @@ -8,6 +8,7 @@ import java.io.IOException; import java.util.Date; 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; @@ -17,6 +18,7 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.interfaces.APSInterface; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; @@ -74,7 +76,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { @Override public boolean isEnabled(int type) { - boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; + boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump() != null && ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; return type == APS && fragmentEnabled && pumpCapable; } @@ -110,7 +112,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == APS) this.fragmentEnabled = fragmentEnabled; } @@ -173,8 +175,7 @@ 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 maxBasal = MainApp.getConstraintChecker().getMaxBasalAllowed(profile).value(); double minBg = Profile.toMgdl(profile.getTargetLow(), units); double maxBg = Profile.toMgdl(profile.getTargetHigh(), units); double targetBg = Profile.toMgdl(profile.getTarget(), units); @@ -191,7 +192,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { MealData mealData = MainApp.getConfigBuilder().getMealData(); Profiler.log(log, "getMealData()", startPart); - maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob); + double maxIob = MainApp.getConstraintChecker().getMaxIOBAllowed().value(); minBg = HardLimits.verifyHardLimits(minBg, "minBg", HardLimits.VERY_HARD_LIMIT_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_MIN_BG[1]); maxBg = HardLimits.verifyHardLimits(maxBg, "maxBg", HardLimits.VERY_HARD_LIMIT_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_MAX_BG[1]); @@ -207,9 +208,6 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { } - maxIob = HardLimits.verifyHardLimits(maxIob, "maxIob", 0, HardLimits.maxIobAMA()); - maxBasal = HardLimits.verifyHardLimits(maxBasal, "max_basal", 0.1, HardLimits.maxBasal()); - if (!HardLimits.checkOnlyHardLimits(profile.getDia(), "dia", HardLimits.MINDIA, HardLimits.MAXDIA)) return; if (!HardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(profile.secondsFromMidnight()), "carbratio", HardLimits.MINIC, HardLimits.MAXIC)) @@ -222,7 +220,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { return; startPart = new Date(); - if (MainApp.getConfigBuilder().isAMAModeEnabled()) { + if (MainApp.getConstraintChecker().isAutosensModeEnabled().value()) { lastAutosensResult = IobCobCalculatorPlugin.getPlugin().detectSensitivityWithLock(IobCobCalculatorPlugin.oldestDataAvailable(), System.currentTimeMillis()); } else { lastAutosensResult = new AutosensResult(); @@ -248,10 +246,10 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress()) determineBasalResultAMA.tempBasalRequested = false; // limit requests on openloop mode - if (!MainApp.getConfigBuilder().isClosedModeEnabled()) { + if (!MainApp.getConstraintChecker().isClosedLoopAllowed().value()) { long now = System.currentTimeMillis(); TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(now); - if (activeTemp != null && determineBasalResultAMA.rate == 0 && determineBasalResultAMA.duration == 0) { + 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; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java index a8a6628743..7fb7a3e207 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java @@ -8,6 +8,7 @@ import java.io.IOException; import java.util.Date; 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; @@ -17,6 +18,7 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.interfaces.APSInterface; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; @@ -29,7 +31,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; @@ -75,13 +76,13 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { @Override public boolean isEnabled(int type) { - boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; + boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump() != null && ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; return type == APS && fragmentEnabled && pumpCapable; } @Override public boolean isVisibleInTabs(int type) { - boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; + boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump() != null && ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; return type == APS && fragmentVisible && pumpCapable; } @@ -111,7 +112,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == APS) this.fragmentEnabled = fragmentEnabled; } @@ -174,8 +175,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 maxBasal = MainApp.getConstraintChecker().getMaxBasalAllowed(profile).value(); + double minBg = Profile.toMgdl(profile.getTargetLow(), units); double maxBg = Profile.toMgdl(profile.getTargetHigh(), units); double targetBg = Profile.toMgdl(profile.getTarget(), units); @@ -193,7 +194,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { MealData mealData = MainApp.getConfigBuilder().getMealData(); - maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob); + double maxIob = MainApp.getConstraintChecker().getMaxIOBAllowed().value(); Profiler.log(log, "MA data gathering", start); minBg = verifyHardLimits(minBg, "minBg", HardLimits.VERY_HARD_LIMIT_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_MIN_BG[1]); @@ -207,9 +208,6 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { targetBg = verifyHardLimits(tempTarget.target(), "targetBg", HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]); } - maxIob = verifyHardLimits(maxIob, "maxIob", 0, HardLimits.maxIobAMA()); - maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, HardLimits.maxBasal()); - if (!checkOnlyHardLimits(profile.getDia(), "dia", HardLimits.MINDIA, HardLimits.MAXDIA)) return; if (!checkOnlyHardLimits(profile.getIcTimeFromMidnight(profile.secondsFromMidnight()), "carbratio", HardLimits.MINIC, HardLimits.MAXIC)) @@ -237,7 +235,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { if (determineBasalResultMA.rate == 0d && determineBasalResultMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress()) determineBasalResultMA.tempBasalRequested = false; // limit requests on openloop mode - if (!MainApp.getConfigBuilder().isClosedModeEnabled()) { + if (!MainApp.getConstraintChecker().isClosedLoopAllowed().value()) { TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(now); if (activeTemp != null && determineBasalResultMA.rate == 0 && determineBasalResultMA.duration == 0) { // going to cancel diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java index 9df54b34d3..e644b13dc9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java @@ -27,12 +27,10 @@ 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.PluginBase; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.Loop.ScriptReader; import info.nightscout.androidaps.plugins.OpenAPSMA.LoggerCallback; -import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin; import info.nightscout.utils.SP; import info.nightscout.utils.SafeParse; @@ -229,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); @@ -246,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 = SP.getBoolean(R.string.key_use_smb, false) && MainApp.getConfigBuilder().isClosedModeEnabled(); + 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)); @@ -302,7 +300,7 @@ public class DetermineBasalAdapterSMBJS { mMealData.put("lastCarbTime", mealData.lastCarbTime); - if (MainApp.getConfigBuilder().isAMAModeEnabled()) { + if (MainApp.getConstraintChecker().isAutosensModeEnabled().value()) { mAutosensData = new JSONObject(); mAutosensData.put("ratio", autosensDataRatio); } else { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBFragment.java index 6c720adc48..dcba600fb4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBFragment.java @@ -16,6 +16,9 @@ import org.json.JSONException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.plugins.Common.SubscriberFragment; @@ -24,19 +27,32 @@ import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateRes import info.nightscout.utils.FabricPrivacy; import info.nightscout.utils.JSONFormatter; -public class OpenAPSSMBFragment extends SubscriberFragment implements View.OnClickListener { +public class OpenAPSSMBFragment extends SubscriberFragment { private static Logger log = LoggerFactory.getLogger(OpenAPSSMBFragment.class); + @BindView(R.id.openapsma_run) Button run; + @BindView(R.id.openapsma_lastrun) TextView lastRunView; + @BindView(R.id.openapsma_constraints) + TextView constraintsView; + @BindView(R.id.openapsma_glucosestatus) TextView glucoseStatusView; + @BindView(R.id.openapsma_currenttemp) TextView currentTempView; + @BindView(R.id.openapsma_iobdata) TextView iobDataView; + @BindView(R.id.openapsma_profile) TextView profileView; + @BindView(R.id.openapsma_mealdata) TextView mealDataView; + @BindView(R.id.openapsma_autosensdata) TextView autosensDataView; + @BindView(R.id.openapsma_result) TextView resultView; + @BindView(R.id.openapsma_scriptdebugdata) TextView scriptdebugView; + @BindView(R.id.openapsma_request) TextView requestView; @Override @@ -44,32 +60,14 @@ public class OpenAPSSMBFragment extends SubscriberFragment implements View.OnCli Bundle savedInstanceState) { View view = inflater.inflate(R.layout.openapsama_fragment, container, false); - run = (Button) view.findViewById(R.id.openapsma_run); - run.setOnClickListener(this); - lastRunView = (TextView) view.findViewById(R.id.openapsma_lastrun); - glucoseStatusView = (TextView) view.findViewById(R.id.openapsma_glucosestatus); - currentTempView = (TextView) view.findViewById(R.id.openapsma_currenttemp); - iobDataView = (TextView) view.findViewById(R.id.openapsma_iobdata); - profileView = (TextView) view.findViewById(R.id.openapsma_profile); - mealDataView = (TextView) view.findViewById(R.id.openapsma_mealdata); - autosensDataView = (TextView) view.findViewById(R.id.openapsma_autosensdata); - scriptdebugView = (TextView) view.findViewById(R.id.openapsma_scriptdebugdata); - resultView = (TextView) view.findViewById(R.id.openapsma_result); - requestView = (TextView) view.findViewById(R.id.openapsma_request); - - updateGUI(); + unbinder = ButterKnife.bind(this, view); return view; } - @Override - public void onClick(View view) { - switch (view.getId()) { - case R.id.openapsma_run: - OpenAPSSMBPlugin.getPlugin().invoke("OpenAPSSMB button"); - FabricPrivacy.getInstance().logCustom(new CustomEvent("OpenAPS_SMB_Run")); - break; - } - + @OnClick(R.id.openapsma_run) + public void onRunClick() { + OpenAPSSMBPlugin.getPlugin().invoke("OpenAPSSMB button"); + FabricPrivacy.getInstance().logCustom(new CustomEvent("OpenAPS_SMB_Run")); } @Subscribe @@ -109,6 +107,8 @@ public class OpenAPSSMBFragment extends SubscriberFragment implements View.OnCli profileView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getProfileParam())); mealDataView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getMealDataParam())); scriptdebugView.setText(determineBasalAdapterSMBJS.getScriptDebug()); + if (lastAPSResult != null && lastAPSResult.inputConstraints != null) + constraintsView.setText(lastAPSResult.inputConstraints.getReasons()); } if (plugin.lastAPSRun != null) { lastRunView.setText(plugin.lastAPSRun.toLocaleString()); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java index 778b9d5849..c0b57a80d4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java @@ -8,6 +8,7 @@ import java.io.IOException; import java.util.Date; 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; @@ -17,6 +18,7 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.interfaces.APSInterface; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; @@ -79,7 +81,7 @@ public class OpenAPSSMBPlugin implements PluginBase, APSInterface { @Override public boolean isEnabled(int type) { - boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; + boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump() != null && ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; return type == APS && fragmentEnabled && pumpCapable; } @@ -115,7 +117,7 @@ public class OpenAPSSMBPlugin implements PluginBase, APSInterface { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == APS) this.fragmentEnabled = fragmentEnabled; } @@ -178,8 +180,11 @@ 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); + Constraint inputConstraints = new Constraint<>(0d); // fake. only for collecting all results + + Constraint maxBasalConstraint = MainApp.getConstraintChecker().getMaxBasalAllowed(profile); + inputConstraints.copyReasons(maxBasalConstraint); + double maxBasal = maxBasalConstraint.value(); double minBg = Profile.toMgdl(profile.getTargetLow(), units); double maxBg = Profile.toMgdl(profile.getTargetHigh(), units); double targetBg = Profile.toMgdl(profile.getTarget(), units); @@ -196,7 +201,7 @@ public class OpenAPSSMBPlugin implements PluginBase, APSInterface { MealData mealData = MainApp.getConfigBuilder().getMealData(); Profiler.log(log, "getMealData()", startPart); - maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob); + double maxIob = MainApp.getConstraintChecker().getMaxIOBAllowed().value(); minBg = verifyHardLimits(minBg, "minBg", HardLimits.VERY_HARD_LIMIT_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_MIN_BG[1]); maxBg = verifyHardLimits(maxBg, "maxBg", HardLimits.VERY_HARD_LIMIT_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_MAX_BG[1]); @@ -212,9 +217,6 @@ public class OpenAPSSMBPlugin implements PluginBase, APSInterface { } - maxIob = verifyHardLimits(maxIob, "maxIob", 0, HardLimits.maxIobSMB()); - maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, HardLimits.maxBasal()); - if (!checkOnlyHardLimits(profile.getDia(), "dia", HardLimits.MINDIA, HardLimits.MAXDIA)) return; if (!checkOnlyHardLimits(profile.getIcTimeFromMidnight(profile.secondsFromMidnight()), "carbratio", HardLimits.MINIC, HardLimits.MAXIC)) return; @@ -224,7 +226,7 @@ public class OpenAPSSMBPlugin implements PluginBase, APSInterface { if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, HardLimits.maxBasal())) return; startPart = new Date(); - if (MainApp.getConfigBuilder().isAMAModeEnabled()) { + if (MainApp.getConstraintChecker().isAutosensModeEnabled().value()) { lastAutosensResult = IobCobCalculatorPlugin.getPlugin().detectSensitivityWithLock(IobCobCalculatorPlugin.oldestDataAvailable(), System.currentTimeMillis()); } else { lastAutosensResult = new AutosensResult(); @@ -253,7 +255,7 @@ public class OpenAPSSMBPlugin implements PluginBase, APSInterface { if (determineBasalResultSMB.rate == 0d && determineBasalResultSMB.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress()) determineBasalResultSMB.tempBasalRequested = false; // limit requests on openloop mode - if (!MainApp.getConfigBuilder().isClosedModeEnabled()) { + if (!MainApp.getConstraintChecker().isClosedLoopAllowed().value()) { TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(now); if (activeTemp != null && determineBasalResultSMB.rate == 0 && determineBasalResultSMB.duration == 0) { // going to cancel @@ -271,6 +273,8 @@ public class OpenAPSSMBPlugin implements PluginBase, APSInterface { log.error("Unhandled exception", e); } + determineBasalResultSMB.inputConstraints = inputConstraints; + lastDetermineBasalAdapterSMBJS = determineBasalAdapterSMBJS; lastAPSResult = determineBasalResultSMB; lastAPSRun = new Date(now); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java index 3c068b79d7..a17470eb2c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java @@ -43,6 +43,7 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.DateUtil; @@ -120,7 +121,7 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); - maxCarbs = MainApp.getConfigBuilder().applyCarbsConstraints(Constants.carbsOnlyForCheckLimit); + maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value(); editCarbs = view.findViewById(R.id.newcarb_carbsamount); @@ -303,7 +304,7 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D okClicked = true; try { final Integer carbs = SafeParse.stringToInt(editCarbs.getText()); - Integer carbsAfterConstraints = MainApp.getConfigBuilder().applyCarbsConstraints(carbs); + Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(carbs)).value(); List actions = new LinkedList<>(); if (carbs > 0) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewInsulinDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewInsulinDialog.java index f72e1c1e87..11eabfb3c6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewInsulinDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewInsulinDialog.java @@ -44,6 +44,7 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.DateUtil; @@ -119,7 +120,7 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener, getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); - maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit); + maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value(); editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newinsulin_amount); @@ -223,7 +224,7 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener, try { Double insulin = SafeParse.stringToDouble(editInsulin.getText()); - Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(insulin); + Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value(); List actions = new LinkedList<>(); if (insulin > 0) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialog.java index d17dfdd0b8..72776b58e9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialog.java @@ -31,6 +31,7 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.FabricPrivacy; @@ -95,8 +96,8 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); - maxCarbs = MainApp.getConfigBuilder().applyCarbsConstraints(Constants.carbsOnlyForCheckLimit); - maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit); + maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value(); + maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value(); editCarbs = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_carbsamount); editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_insulinamount); @@ -128,8 +129,8 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene String confirmMessage = MainApp.gs(R.string.entertreatmentquestion) + "
"; - Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(insulin); - Integer carbsAfterConstraints = MainApp.getConfigBuilder().applyCarbsConstraints(carbs); + Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value(); + Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(carbs)).value(); if (insulin > 0) { confirmMessage += MainApp.gs(R.string.bolus) + ": " + "" + insulinAfterConstraints + "U" + ""; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java index 56f2276327..34980b054a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java @@ -52,16 +52,17 @@ import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.events.EventFeatureRunning; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventRefreshOverview; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.queue.Callback; -import info.nightscout.utils.FabricPrivacy; import info.nightscout.utils.BolusWizard; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.FabricPrivacy; import info.nightscout.utils.NumberPicker; import info.nightscout.utils.SP; import info.nightscout.utils.SafeParse; @@ -236,8 +237,8 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com superbolusCheckbox.setVisibility(SP.getBoolean(R.string.key_usesuperbolus, false) ? View.VISIBLE : View.GONE); - Integer maxCarbs = MainApp.getConfigBuilder().applyCarbsConstraints(Constants.carbsOnlyForCheckLimit); - Double maxCorrection = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit); + Integer maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value(); + Double maxCorrection = MainApp.getConstraintChecker().getMaxBolusAllowed().value(); editBg.setParams(0d, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false, textWatcher); editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher); @@ -296,13 +297,15 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com return; } okClicked = true; - if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) { + final Profile profile = MainApp.getConfigBuilder().getProfile(); + + if (profile != null && (calculatedTotalInsulin > 0d || calculatedCarbs > 0d)) { DecimalFormat formatNumber2decimalplaces = new DecimalFormat("0.00"); String confirmMessage = getString(R.string.entertreatmentquestion); - Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(calculatedTotalInsulin); - Integer carbsAfterConstraints = MainApp.getConfigBuilder().applyCarbsConstraints(calculatedCarbs); + Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(calculatedTotalInsulin)).value(); + Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(calculatedCarbs)).value(); confirmMessage += "
" + getString(R.string.bolus) + ": " + "" + formatNumber2decimalplaces.format(insulinAfterConstraints) + "U" + ""; confirmMessage += "
" + getString(R.string.carbs) + ": " + carbsAfterConstraints + "g"; @@ -341,7 +344,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com activeloop.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); MainApp.bus().post(new EventRefreshOverview("WizardDialog")); } - ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 120, true, new Callback() { + ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 120, true, profile, new Callback() { @Override public void run() { if (!result.success) { @@ -458,13 +461,13 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com Double c_bg = SafeParse.stringToDouble(editBg.getText()); Integer c_carbs = SafeParse.stringToInt(editCarbs.getText()); Double c_correction = SafeParse.stringToDouble(editCorr.getText()); - Double corrAfterConstraint = MainApp.getConfigBuilder().applyBolusConstraints(c_correction); + Double corrAfterConstraint = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(c_correction)).value(); if (c_correction - corrAfterConstraint != 0) { // c_correction != corrAfterConstraint doesn't work editCorr.setValue(0d); ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.bolusconstraintapplied)); return; } - Integer carbsAfterConstraint = MainApp.getConfigBuilder().applyCarbsConstraints(c_carbs); + Integer carbsAfterConstraint = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(c_carbs)).value(); if (c_carbs - carbsAfterConstraint != 0) { editCarbs.setValue(0d); ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.carbsconstraintapplied)); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java index e90a77c524..dc0cb27ed7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java @@ -87,6 +87,7 @@ import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; @@ -439,7 +440,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, if (v == apsModeView) { final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); final PumpDescription pumpDescription = ConfigBuilderPlugin.getActivePump().getPumpDescription(); - if (activeloop == null) + if (activeloop == null || !MainApp.getConfigBuilder().isProfileValid("ContexMenuCreation")) return; menu.setHeaderTitle(MainApp.sResources.getString(R.string.loop)); if (activeloop.isEnabled(PluginBase.LOOP)) { @@ -473,9 +474,12 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, @Override public boolean onContextItemSelected(MenuItem item) { + final Profile profile = MainApp.getConfigBuilder().getProfile(); + if (profile == null) + return true; final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); if (item.getTitle().equals(MainApp.sResources.getString(R.string.disableloop))) { - activeloop.setFragmentEnabled(PluginBase.LOOP, false); + activeloop.setPluginEnabled(PluginBase.LOOP, false); activeloop.setFragmentVisible(PluginBase.LOOP, false); MainApp.getConfigBuilder().storeSettings(); updateGUI("suspendmenu"); @@ -490,7 +494,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, NSUpload.uploadOpenAPSOffline(24 * 60); // upload 24h, we don't know real duration return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.enableloop))) { - activeloop.setFragmentEnabled(PluginBase.LOOP, true); + activeloop.setPluginEnabled(PluginBase.LOOP, true); activeloop.setFragmentVisible(PluginBase.LOOP, true); MainApp.getConfigBuilder().storeSettings(); updateGUI("suspendmenu"); @@ -526,23 +530,23 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, updateGUI("suspendmenu"); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor15m))) { - MainApp.getConfigBuilder().disconnectPump(15); + MainApp.getConfigBuilder().disconnectPump(15, profile); updateGUI("suspendmenu"); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor30m))) { - MainApp.getConfigBuilder().disconnectPump(30); + MainApp.getConfigBuilder().disconnectPump(30, profile); updateGUI("suspendmenu"); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor1h))) { - MainApp.getConfigBuilder().disconnectPump(60); + MainApp.getConfigBuilder().disconnectPump(60, profile); updateGUI("suspendmenu"); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor2h))) { - MainApp.getConfigBuilder().disconnectPump(120); + MainApp.getConfigBuilder().disconnectPump(120, profile); updateGUI("suspendmenu"); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor3h))) { - MainApp.getConfigBuilder().disconnectPump(180); + MainApp.getConfigBuilder().disconnectPump(180, profile); updateGUI("suspendmenu"); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.careportal_profileswitch))) { @@ -723,8 +727,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, DecimalFormat formatNumber2decimalplaces = new DecimalFormat("0.00"); String confirmMessage = getString(R.string.entertreatmentquestion); - Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(wizard.calculatedTotalInsulin); - Integer carbsAfterConstraints = MainApp.getConfigBuilder().applyCarbsConstraints(quickWizardEntry.carbs()); + Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(wizard.calculatedTotalInsulin)).value(); + Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(quickWizardEntry.carbs())).value(); confirmMessage += "\n" + getString(R.string.bolus) + ": " + formatNumber2decimalplaces.format(insulinAfterConstraints) + "U"; confirmMessage += "\n" + getString(R.string.carbs) + ": " + carbsAfterConstraints + "g"; @@ -760,7 +764,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, activeloop.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); MainApp.bus().post(new EventRefreshOverview("WizardDialog")); } - ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 120, true, new Callback() { + ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 120, true, profile, new Callback() { @Override public void run() { if (!result.success) { @@ -1016,6 +1020,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } } + Constraint closedLoopEnabled = MainApp.getConstraintChecker().isClosedLoopAllowed(); + // open loop mode final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun; if (Config.APS && pump.getPumpDescription().isTempBasalCapable) { @@ -1036,7 +1042,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 (MainApp.getConfigBuilder().isClosedModeEnabled()) { + if (closedLoopEnabled.value()) { apsModeView.setText(MainApp.sResources.getString(R.string.closedloop)); } else { apsModeView.setText(MainApp.sResources.getString(R.string.openloop)); @@ -1066,7 +1072,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, // **** Temp button **** if (acceptTempLayout != null) { - boolean showAcceptButton = !MainApp.getConfigBuilder().isClosedModeEnabled(); // 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 diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java index 8b276f937d..376ee9ca87 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java @@ -96,7 +96,7 @@ public class OverviewPlugin implements PluginBase { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { // Always enabled } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java index 26d5851865..282b3e16a7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java @@ -94,7 +94,7 @@ public class PersistentNotificationPlugin implements PluginBase { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (getType() == type) { this.fragmentEnabled = fragmentEnabled; enableDisableNotification(fragmentEnabled); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java index 69272cc2ae..c59537ad6b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java @@ -107,7 +107,7 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == PROFILE) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java index c2d7cfabfc..a50e47b998 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java @@ -96,7 +96,7 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == PROFILE) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java index b538a28512..92f810c3a0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java @@ -102,7 +102,7 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == PROFILE) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java index afefbe80da..c8e5fcdbe4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java @@ -4,7 +4,6 @@ import android.os.SystemClock; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.CustomEvent; import org.json.JSONObject; @@ -33,6 +32,7 @@ import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; @@ -221,7 +221,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == PUMP) this.fragmentEnabled = fragmentEnabled; } @@ -424,7 +424,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf return; } pump.basalProfile = readBasalResult.basalProfile; - validBasalRateProfileSelectedOnPump = true; + setValidBasalRateProfileSelectedOnPump(true); pump.initialized = true; MainApp.bus().post(new EventInitializationChanged()); @@ -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); @@ -764,7 +764,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf * is or isn't running at the moment */ @Override - public PumpEnactResult setTempBasalPercent(Integer percent, final Integer durationInMinutes, boolean forceNew) { + public PumpEnactResult setTempBasalPercent(Integer percent, final Integer durationInMinutes, Profile profile, boolean forceNew) { return setTempBasalPercent(percent, durationInMinutes); } @@ -925,7 +925,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf if (commandResult.success) { pump.lastSuccessfulCmdTime = System.currentTimeMillis(); if (validBasalRateProfileSelectedOnPump && commandResult.state.unsafeUsageDetected == PumpState.UNSUPPORTED_BASAL_RATE_PROFILE) { - validBasalRateProfileSelectedOnPump = false; + setValidBasalRateProfileSelectedOnPump(false); Notification n = new Notification(Notification.COMBO_PUMP_ALARM, MainApp.gs(R.string.combo_force_disabled_notification), Notification.URGENT); @@ -945,6 +945,10 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf return commandResult; } + public void setValidBasalRateProfileSelectedOnPump(boolean value) { + validBasalRateProfileSelectedOnPump = value; + } + /** * Returns the command result of running ReadPumpState if it wasn't successful, indicating * an error condition. Returns null otherwise. @@ -1422,52 +1426,16 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf private boolean validBasalRateProfileSelectedOnPump = true; @Override - public boolean isLoopEnabled() { - return validBasalRateProfileSelectedOnPump; + public Constraint isLoopInvokationAllowed(Constraint value) { + if (!validBasalRateProfileSelectedOnPump) + value.set(false, MainApp.gs(R.string.novalidbasalrate), this); + return value; } @Override - public boolean isClosedModeEnabled() { - return true; - } - - @Override - public boolean isAutosensModeEnabled() { - return true; - } - - @Override - public boolean isAMAModeEnabled() { - return true; - } - - @Override - public boolean isSMBModeEnabled() { - return true; - } - - @Override - public Double applyBasalConstraints(Double absoluteRate) { - return absoluteRate; - } - - @Override - public Integer applyBasalConstraints(Integer percentRate) { - return percentRate; - } - - @Override - public Double applyBolusConstraints(Double insulin) { - return insulin; - } - - @Override - public Integer applyCarbsConstraints(Integer carbs) { - return carbs; - } - - @Override - public Double applyMaxIOBConstraints(Double maxIob) { - return lowSuspendOnlyLoopEnforcedUntil < System.currentTimeMillis() ? maxIob : 0; + public Constraint applyMaxIOBConstraints(Constraint maxIob) { + if (lowSuspendOnlyLoopEnforcedUntil > System.currentTimeMillis()) + maxIob.setIfSmaller(0d, String.format(MainApp.gs(R.string.limitingmaxiob), 0d, MainApp.gs(R.string.unsafeusage)), this); + return maxIob; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java index b57b8543f4..910a7a8b28 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java @@ -7,11 +7,9 @@ import org.json.JSONObject; import org.slf4j.Logger; import java.util.Date; -import java.util.Objects; import info.nightscout.androidaps.BuildConfig; 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.Profile; @@ -19,13 +17,13 @@ import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.DanaRInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.notifications.Notification; @@ -107,16 +105,16 @@ public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface, } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == PluginBase.PROFILE) mPluginProfileEnabled = fragmentEnabled; else if (type == PluginBase.PUMP) mPluginPumpEnabled = fragmentEnabled; // if pump profile was enabled need to switch to another too if (type == PluginBase.PUMP && !fragmentEnabled && mPluginProfileEnabled) { - setFragmentEnabled(PluginBase.PROFILE, false); + setPluginEnabled(PluginBase.PROFILE, false); setFragmentVisible(PluginBase.PROFILE, false); - NSProfilePlugin.getPlugin().setFragmentEnabled(PluginBase.PROFILE, true); + NSProfilePlugin.getPlugin().setPluginEnabled(PluginBase.PROFILE, true); NSProfilePlugin.getPlugin().setFragmentVisible(PluginBase.PROFILE, true); } } @@ -214,10 +212,9 @@ public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface, } @Override - public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) { + public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) { PumpEnactResult result = new PumpEnactResult(); - ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); - percent = configBuilderPlugin.applyBasalConstraints(percent); + percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(percent), profile).value(); if (percent < 0) { result.isTempCancel = false; result.enacted = false; @@ -229,7 +226,7 @@ public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface, if (percent > getPumpDescription().maxTempPercent) percent = getPumpDescription().maxTempPercent; long now = System.currentTimeMillis(); - TemporaryBasal runningTB = MainApp.getConfigBuilder().getRealTempBasalFromHistory(now); + TemporaryBasal runningTB = MainApp.getConfigBuilder().getRealTempBasalFromHistory(now); if (runningTB != null && runningTB.percentRate == percent && !enforceNew) { result.enacted = false; result.success = true; @@ -265,8 +262,7 @@ public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface, @Override public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { - ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); - insulin = configBuilderPlugin.applyBolusConstraints(insulin); + insulin = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value(); // needs to be rounded int durationInHalfHours = Math.max(durationInMinutes / 30, 1); insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep); @@ -293,7 +289,8 @@ public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface, result.isTempCancel = false; result.duration = pump.extendedBolusRemainingMinutes; result.absolute = pump.extendedBolusAbsoluteRate; - if (! SP.getBoolean("danar_useextended", false)) result.bolusDelivered = pump.extendedBolusAmount; + if (!SP.getBoolean("danar_useextended", false)) + result.bolusDelivered = pump.extendedBolusAmount; result.isPercent = false; if (Config.logPumpActions) log.debug("setExtendedBolus: OK"); @@ -436,80 +433,27 @@ public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface, */ @Override - public boolean isLoopEnabled() { - return true; - } - - @Override - public boolean isClosedModeEnabled() { - return true; - } - - @Override - public boolean isAutosensModeEnabled() { - return true; - } - - @Override - public boolean isAMAModeEnabled() { - return true; - } - - @Override - public boolean isSMBModeEnabled() { - return true; - } - - @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 applyBasalConstraints(Constraint absoluteRate, Profile profile) { + if (pump != null) + absoluteRate.setIfSmaller(pump.maxBasal, String.format(MainApp.gs(R.string.limitingbasalratio), pump.maxBasal, MainApp.gs(R.string.pumplimit)), this); return absoluteRate; } - @SuppressWarnings("PointlessBooleanExpression") @Override - public Integer applyBasalConstraints(Integer percentRate) { - Integer origPercentRate = percentRate; - if (percentRate < 0) percentRate = 0; - if (percentRate > getPumpDescription().maxTempPercent) - percentRate = getPumpDescription().maxTempPercent; - if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) - log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%"); + public Constraint applyBasalPercentConstraints(Constraint percentRate, Profile profile) { + percentRate.setIfGreater(0, String.format(MainApp.gs(R.string.limitingpercentrate), 0, MainApp.gs(R.string.itmustbepositivevalue)), this); + percentRate.setIfSmaller(getPumpDescription().maxTempPercent, String.format(MainApp.gs(R.string.limitingpercentrate), getPumpDescription().maxTempPercent, MainApp.gs(R.string.pumplimit)), this); + return percentRate; } - @SuppressWarnings("PointlessBooleanExpression") @Override - public Double applyBolusConstraints(Double insulin) { - double origInsulin = insulin; - if (pump != null) { - if (insulin > pump.maxBolus) { - insulin = pump.maxBolus; - if (Config.logConstraintsChanges && origInsulin != Constants.bolusOnlyForCheckLimit) - log.debug("Limiting bolus " + origInsulin + "U by pump constraint to " + insulin + "U"); - } - } + public Constraint applyBolusConstraints(Constraint insulin) { + if (pump != null) + insulin.setIfSmaller(pump.maxBolus, String.format(MainApp.gs(R.string.limitingbolus), pump.maxBolus, MainApp.gs(R.string.pumplimit)), this); return insulin; } - @Override - public Integer applyCarbsConstraints(Integer carbs) { - return carbs; - } - - @Override - public Double applyMaxIOBConstraints(Double maxIob) { - return maxIob; - } - @Nullable @Override public ProfileStore getProfile() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java index 7be12e0cb5..ce1a5c392c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java @@ -14,14 +14,15 @@ 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.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService; import info.nightscout.utils.Round; import info.nightscout.utils.SP; @@ -131,8 +132,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin { @Override public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { - ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); - detailedBolusInfo.insulin = configBuilderPlugin.applyBolusConstraints(detailedBolusInfo.insulin); + detailedBolusInfo.insulin = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value(); if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { Treatment t = new Treatment(); t.isSMB = detailedBolusInfo.isSMB; @@ -162,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()) { @@ -171,8 +171,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin { PumpEnactResult result = new PumpEnactResult(); - ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); - absoluteRate = configBuilderPlugin.applyBasalConstraints(absoluteRate); + absoluteRate = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(absoluteRate), profile).value(); final boolean doTempOff = getBaseBasalRate() - absoluteRate == 0d; final boolean doLowTemp = absoluteRate < getBaseBasalRate(); @@ -250,7 +249,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin { // Convert duration from minutes to hours if (Config.logPumpActions) log.debug("setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)"); - return setTempBasalPercent(percentRate, durationInMinutes, false); + return setTempBasalPercent(percentRate, durationInMinutes, profile, false); } if (doExtendedTemp) { // Check if some temp is already in progress @@ -269,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 = configBuilderPlugin.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 diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java index 0e6a3e814a..9173794199 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java @@ -3,9 +3,9 @@ package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.utils.HardLimits; public class MsgBolusStart extends MessageBase { @@ -19,9 +19,7 @@ public class MsgBolusStart extends MessageBase { this(); // HARDCODED LIMIT - amount = MainApp.getConfigBuilder().applyBolusConstraints(amount); - if (amount < 0) amount = 0d; - if (amount > HardLimits.maxBolus()) amount = HardLimits.maxBolus(); + amount = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(amount)).value(); AddParamInt((int) (amount * 100)); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStartWithSpeed.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStartWithSpeed.java index b04d501ef0..3a33e9f866 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStartWithSpeed.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStartWithSpeed.java @@ -5,6 +5,7 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.utils.HardLimits; public class MsgBolusStartWithSpeed extends MessageBase { @@ -18,9 +19,7 @@ public class MsgBolusStartWithSpeed extends MessageBase { this(); // HARDCODED LIMIT - amount = MainApp.getConfigBuilder().applyBolusConstraints(amount); - if (amount < 0) amount = 0d; - if (amount > HardLimits.maxBolus()) amount = HardLimits.maxBolus(); + amount = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(amount)).value(); AddParamInt((int) (amount * 100)); AddParamByte((byte) speed); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java index ee0a9c8aaf..93f66aa200 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java @@ -31,17 +31,17 @@ public class MsgInitConnStatusTime extends MessageBase { MainApp.bus().post(new EventNewNotification(notification)); MainApp.getSpecificPlugin(DanaRPlugin.class).disconnect("Wrong Model"); log.debug("Wrong model selected. Switching to Korean DanaR"); - MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentEnabled(PluginBase.PUMP, true); + MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setPluginEnabled(PluginBase.PUMP, true); MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginBase.PUMP, true); - MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentEnabled(PluginBase.PUMP, false); + MainApp.getSpecificPlugin(DanaRPlugin.class).setPluginEnabled(PluginBase.PUMP, false); MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentVisible(PluginBase.PUMP, false); DanaRPump.reset(); // mark not initialized //If profile coming from pump, switch it as well if(MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginBase.PROFILE)){ - (MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, false); - (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, true); + (MainApp.getSpecificPlugin(DanaRPlugin.class)).setPluginEnabled(PluginBase.PROFILE, false); + (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setPluginEnabled(PluginBase.PROFILE, true); } MainApp.getConfigBuilder().storeSettings(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStart.java index 484078825e..420f0ccbf9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStart.java @@ -3,9 +3,9 @@ package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.utils.HardLimits; public class MsgSetExtendedBolusStart extends MessageBase { @@ -21,9 +21,7 @@ public class MsgSetExtendedBolusStart extends MessageBase { // HARDCODED LIMITS if (halfhours < 1) halfhours = 1; if (halfhours > 16) halfhours = 16; - amount = MainApp.getConfigBuilder().applyBolusConstraints(amount); - if (amount < 0d) amount = 0d; - if (amount > HardLimits.maxBolus()) amount = HardLimits.maxBolus(); + amount = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(amount)).value(); AddParamInt((int) (amount * 100)); AddParamByte(halfhours); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java index 0a35d56a17..6462afbe79 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java @@ -14,14 +14,15 @@ 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.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.AbstractDanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaRKorean.services.DanaRKoreanExecutionService; import info.nightscout.utils.Round; @@ -132,8 +133,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { @Override public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { - ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); - detailedBolusInfo.insulin = configBuilderPlugin.applyBolusConstraints(detailedBolusInfo.insulin); + detailedBolusInfo.insulin = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value(); if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { Treatment t = new Treatment(); t.isSMB = detailedBolusInfo.isSMB; @@ -163,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()) { @@ -172,8 +172,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { PumpEnactResult result = new PumpEnactResult(); - ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); - absoluteRate = configBuilderPlugin.applyBasalConstraints(absoluteRate); + absoluteRate = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(absoluteRate), profile).value(); final boolean doTempOff = getBaseBasalRate() - absoluteRate == 0d; final boolean doLowTemp = absoluteRate < getBaseBasalRate(); @@ -251,7 +250,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { // Convert duration from minutes to hours if (Config.logPumpActions) log.debug("setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)"); - return setTempBasalPercent(percentRate, durationInMinutes, false); + return setTempBasalPercent(percentRate, durationInMinutes, profile,false); } if (doExtendedTemp) { // Check if some temp is already in progress @@ -270,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 = configBuilderPlugin.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 diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java index 89ccb7ae60..6e2b66d2d0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java @@ -33,17 +33,17 @@ public class MsgInitConnStatusTime_k extends MessageBase { MainApp.bus().post(new EventNewNotification(notification)); DanaRKoreanPlugin.getPlugin().disconnect("Wrong Model"); log.debug("Wrong model selected. Switching to export DanaR"); - MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentEnabled(PluginBase.PUMP, false); + MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setPluginEnabled(PluginBase.PUMP, false); MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginBase.PUMP, false); - MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentEnabled(PluginBase.PUMP, true); + MainApp.getSpecificPlugin(DanaRPlugin.class).setPluginEnabled(PluginBase.PUMP, true); MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentVisible(PluginBase.PUMP, true); DanaRPump.reset(); // mark not initialized //If profile coming from pump, switch it as well if (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginBase.PROFILE)) { - (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, false); - (MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, true); + (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setPluginEnabled(PluginBase.PROFILE, false); + (MainApp.getSpecificPlugin(DanaRPlugin.class)).setPluginEnabled(PluginBase.PROFILE, true); } MainApp.getConfigBuilder().storeSettings(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java index 48838117c6..126c8a63a0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java @@ -15,11 +15,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Date; -import java.util.Objects; import info.nightscout.androidaps.BuildConfig; 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.DetailedBolusInfo; @@ -30,17 +28,17 @@ 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.interfaces.Constraint; import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.DanaRInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRFragment; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; @@ -115,16 +113,16 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == PluginBase.PROFILE) this.fragmentProfileEnabled = fragmentEnabled; else if (type == PluginBase.PUMP) this.fragmentPumpEnabled = fragmentEnabled; // if pump profile was enabled need to switch to another too if (type == PluginBase.PUMP && !fragmentEnabled && this.fragmentProfileEnabled) { - setFragmentEnabled(PluginBase.PROFILE, false); + setPluginEnabled(PluginBase.PROFILE, false); setFragmentVisible(PluginBase.PROFILE, false); - MainApp.getSpecificPlugin(NSProfilePlugin.class).setFragmentEnabled(PluginBase.PROFILE, true); + MainApp.getSpecificPlugin(NSProfilePlugin.class).setPluginEnabled(PluginBase.PROFILE, true); MainApp.getSpecificPlugin(NSProfilePlugin.class).setFragmentVisible(PluginBase.PROFILE, true); } } @@ -274,77 +272,28 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, // Constraints interface @Override - public boolean isLoopEnabled() { - return true; - } - - @Override - public boolean isClosedModeEnabled() { - return true; - } - - @Override - public boolean isAutosensModeEnabled() { - return true; - } - - @Override - public boolean isAMAModeEnabled() { - return true; - } - - @Override - public boolean isSMBModeEnabled() { - return true; - } - - @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 applyBasalConstraints(Constraint absoluteRate, Profile profile) { + if (pump != null) + absoluteRate.setIfSmaller(pump.maxBasal, String.format(MainApp.gs(R.string.limitingbasalratio), pump.maxBasal, MainApp.gs(R.string.pumplimit)), this); return absoluteRate; } @Override - public Integer applyBasalConstraints(Integer percentRate) { - Integer origPercentRate = percentRate; - if (percentRate < 0) percentRate = 0; - if (percentRate > getPumpDescription().maxTempPercent) - percentRate = getPumpDescription().maxTempPercent; - if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) - log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%"); + public Constraint applyBasalPercentConstraints(Constraint percentRate, Profile profile) { + percentRate.setIfGreater(0, String.format(MainApp.gs(R.string.limitingpercentrate), 0, MainApp.gs(R.string.itmustbepositivevalue)), this); + percentRate.setIfSmaller(getPumpDescription().maxTempPercent, String.format(MainApp.gs(R.string.limitingpercentrate), getPumpDescription().maxTempPercent, MainApp.gs(R.string.pumplimit)), this); + return percentRate; } + @Override - public Double applyBolusConstraints(Double insulin) { - double origInsulin = insulin; - if (pump != null) { - if (insulin > pump.maxBolus) { - insulin = pump.maxBolus; - if (Config.logConstraintsChanges && origInsulin != Constants.bolusOnlyForCheckLimit) - log.debug("Limiting bolus " + origInsulin + "U by pump constraint to " + insulin + "U"); - } - } + public Constraint applyBolusConstraints(Constraint insulin) { + if (pump != null) + insulin.setIfSmaller(pump.maxBolus, String.format(MainApp.gs(R.string.limitingbolus), pump.maxBolus, MainApp.gs(R.string.pumplimit)), this); return insulin; } - @Override - public Integer applyCarbsConstraints(Integer carbs) { - return carbs; - } - - @Override - public Double applyMaxIOBConstraints(Double maxIob) { - return maxIob; - } - // Profile interface @Nullable @@ -450,8 +399,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, @Override public synchronized PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { - ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); - detailedBolusInfo.insulin = configBuilderPlugin.applyBolusConstraints(detailedBolusInfo.insulin); + detailedBolusInfo.insulin = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value(); if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0); int speed = 12; @@ -513,7 +461,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 @@ -523,8 +471,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, PumpEnactResult result = new PumpEnactResult(); - ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); - absoluteRate = configBuilderPlugin.applyBasalConstraints(absoluteRate); + absoluteRate = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(absoluteRate), profile).value(); final boolean doTempOff = getBaseBasalRate() - absoluteRate == 0d; final boolean doLowTemp = absoluteRate < getBaseBasalRate(); @@ -594,10 +541,9 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, } @Override - public synchronized PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) { + public synchronized PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) { PumpEnactResult result = new PumpEnactResult(); - ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); - percent = configBuilderPlugin.applyBasalConstraints(percent); + percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(percent), profile).value(); if (percent < 0) { result.isTempCancel = false; result.enacted = false; @@ -672,8 +618,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, @Override public synchronized PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { - ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); - insulin = configBuilderPlugin.applyBolusConstraints(insulin); + insulin = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value(); // needs to be rounded int durationInHalfHours = Math.max(durationInMinutes / 30, 1); insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Start.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Start.java index 4c5cc23ef3..12f2fa95c6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Start.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Start.java @@ -1,11 +1,13 @@ package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +import com.cozmo.danar.util.BleCommandUtil; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; -import com.cozmo.danar.util.BleCommandUtil; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.utils.HardLimits; public class DanaRS_Packet_Bolus_Set_Step_Bolus_Start extends DanaRS_Packet { @@ -26,9 +28,7 @@ public class DanaRS_Packet_Bolus_Set_Step_Bolus_Start extends DanaRS_Packet { this(); // HARDCODED LIMIT - amount = MainApp.getConfigBuilder().applyBolusConstraints(amount); - if (amount < 0) amount = 0d; - if (amount > HardLimits.maxBolus()) amount = HardLimits.maxBolus(); + amount = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(amount)).value(); this.amount = amount; this.speed = speed; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java index c1a6bb54da..3f372de5db 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java @@ -14,12 +14,13 @@ 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.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage; import info.nightscout.androidaps.plugins.PumpDanaR.AbstractDanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaRv2.services.DanaRv2ExecutionService; @@ -121,8 +122,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { // Pump interface @Override public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { - ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); - detailedBolusInfo.insulin = configBuilderPlugin.applyBolusConstraints(detailedBolusInfo.insulin); + detailedBolusInfo.insulin = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value(); if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { // v2 stores end time for bolus, we need to adjust time // default delivery speed is 12 sec/U @@ -185,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()) { @@ -194,8 +194,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { PumpEnactResult result = new PumpEnactResult(); - ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); - absoluteRate = configBuilderPlugin.applyBasalConstraints(absoluteRate); + absoluteRate = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(absoluteRate), profile).value(); final boolean doTempOff = getBaseBasalRate() - absoluteRate == 0d; final boolean doLowTemp = absoluteRate < getBaseBasalRate(); @@ -263,10 +262,9 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { } @Override - public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) { + public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) { PumpEnactResult result = new PumpEnactResult(); - ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); - percent = configBuilderPlugin.applyBasalConstraints(percent); + percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(percent), profile).value(); if (percent < 0) { result.isTempCancel = false; result.enacted = false; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java index 336230faf8..fe84ea8114 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java @@ -3,8 +3,6 @@ package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Date; - import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -45,17 +43,17 @@ public class MsgCheckValue_v2 extends MessageBase { MainApp.bus().post(new EventNewNotification(notification)); MainApp.getSpecificPlugin(DanaRPlugin.class).disconnect("Wrong Model"); log.debug("Wrong model selected. Switching to Korean DanaR"); - MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentEnabled(PluginBase.PUMP, true); + MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setPluginEnabled(PluginBase.PUMP, true); MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginBase.PUMP, true); - MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentEnabled(PluginBase.PUMP, false); + MainApp.getSpecificPlugin(DanaRPlugin.class).setPluginEnabled(PluginBase.PUMP, false); MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentVisible(PluginBase.PUMP, false); DanaRPump.reset(); // mark not initialized //If profile coming from pump, switch it as well if(MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginBase.PROFILE)){ - (MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, false); - (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, true); + (MainApp.getSpecificPlugin(DanaRPlugin.class)).setPluginEnabled(PluginBase.PROFILE, false); + (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setPluginEnabled(PluginBase.PROFILE, true); } MainApp.getConfigBuilder().storeSettings(); @@ -70,15 +68,15 @@ public class MsgCheckValue_v2 extends MessageBase { MainApp.bus().post(new EventNewNotification(notification)); DanaRKoreanPlugin.getPlugin().disconnect("Wrong Model"); log.debug("Wrong model selected. Switching to non APS DanaR"); - (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setFragmentEnabled(PluginBase.PUMP, false); + (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setPluginEnabled(PluginBase.PUMP, false); (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setFragmentVisible(PluginBase.PUMP, false); - (MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PUMP, true); + (MainApp.getSpecificPlugin(DanaRPlugin.class)).setPluginEnabled(PluginBase.PUMP, true); (MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentVisible(PluginBase.PUMP, true); //If profile coming from pump, switch it as well if(MainApp.getSpecificPlugin(DanaRv2Plugin.class).isEnabled(PluginBase.PROFILE)){ - (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setFragmentEnabled(PluginBase.PROFILE, false); - (MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, true); + (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setPluginEnabled(PluginBase.PROFILE, false); + (MainApp.getSpecificPlugin(DanaRPlugin.class)).setPluginEnabled(PluginBase.PROFILE, true); } MainApp.getConfigBuilder().storeSettings(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPumpAsyncAdapter.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightAsyncAdapter.java similarity index 91% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPumpAsyncAdapter.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightAsyncAdapter.java index 6f48934059..3759a3f721 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPumpAsyncAdapter.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightAsyncAdapter.java @@ -8,7 +8,7 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightPumpCallback; +import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightCallback; import static info.nightscout.androidaps.plugins.PumpInsight.utils.Helpers.getWakeLock; import static info.nightscout.androidaps.plugins.PumpInsight.utils.Helpers.msSince; @@ -22,11 +22,11 @@ import static info.nightscout.androidaps.plugins.PumpInsight.utils.Helpers.tsl; * */ -public class InsightPumpAsyncAdapter { +public class InsightAsyncAdapter { - private final ConcurrentHashMap commandResults = new ConcurrentHashMap<>(); + private final ConcurrentHashMap commandResults = new ConcurrentHashMap<>(); - InsightPumpAsyncAdapter() { + InsightAsyncAdapter() { MainApp.bus().register(this); } @@ -36,7 +36,7 @@ public class InsightPumpAsyncAdapter { } @Subscribe - public void onStatusEvent(final EventInsightPumpCallback ev) { + public void onStatusEvent(final EventInsightCallback ev) { log("Received callback event: " + ev.toString()); commandResults.put(ev.request_uuid, ev); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPumpFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightFragment.java similarity index 89% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPumpFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightFragment.java index 3dfcb9b0a3..156c8271e3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPumpFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightFragment.java @@ -19,14 +19,14 @@ import java.util.List; import info.nightscout.androidaps.R; import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightPumpUpdateGui; +import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightUpdateGui; import info.nightscout.androidaps.plugins.PumpInsight.utils.StatusItem; import info.nightscout.androidaps.plugins.PumpInsight.utils.ui.StatusItemViewAdapter; import info.nightscout.utils.FabricPrivacy; -public class InsightPumpFragment extends SubscriberFragment { - private static final Logger log = LoggerFactory.getLogger(InsightPumpFragment.class); +public class InsightFragment extends SubscriberFragment { + private static final Logger log = LoggerFactory.getLogger(InsightFragment.class); private static final Handler sLoopHandler = new Handler(); private static volatile boolean refresh = false; private static volatile boolean pending = false; @@ -88,7 +88,7 @@ public class InsightPumpFragment extends SubscriberFragment { @Subscribe - public void onStatusEvent(final EventInsightPumpUpdateGui ev) { + public void onStatusEvent(final EventInsightUpdateGui ev) { updateGUI(); } @@ -99,8 +99,8 @@ public class InsightPumpFragment extends SubscriberFragment { activity.runOnUiThread(new Runnable() { @Override public void run() { - final InsightPumpPlugin insightPumpPlugin = InsightPumpPlugin.getPlugin(); - final List l = insightPumpPlugin.getStatusItems(refresh); + final InsightPlugin insightPlugin = InsightPlugin.getPlugin(); + final List l = insightPlugin.getStatusItems(refresh); holder.removeAllViews(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPumpPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java index a7c7cb52f4..2506e5321d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java @@ -1,10 +1,5 @@ package info.nightscout.androidaps.plugins.PumpInsight; -import android.os.Handler; -import android.util.Log; - -import com.j256.ormlite.stmt.query.In; - import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; @@ -27,11 +22,11 @@ import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; @@ -41,8 +36,8 @@ import info.nightscout.androidaps.plugins.PumpInsight.connector.Connector; import info.nightscout.androidaps.plugins.PumpInsight.connector.SetTBRTaskRunner; import info.nightscout.androidaps.plugins.PumpInsight.connector.StatusTaskRunner; import info.nightscout.androidaps.plugins.PumpInsight.connector.WriteBasalProfileTaskRunner; -import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightPumpCallback; -import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightPumpUpdateGui; +import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightCallback; +import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightUpdateGui; import info.nightscout.androidaps.plugins.PumpInsight.history.HistoryReceiver; import info.nightscout.androidaps.plugins.PumpInsight.history.LiveHistory; import info.nightscout.androidaps.plugins.PumpInsight.utils.Helpers; @@ -70,26 +65,25 @@ import static info.nightscout.androidaps.plugins.PumpInsight.history.PumpIdCache /** * Created by jamorham on 23/01/2018. - * + *

* Connects to SightRemote app service using SightParser library - * + *

* SightRemote and SightParser created by Tebbe Ubben - * + *

* Original proof of concept SightProxy by jamorham - * */ @SuppressWarnings("AccessStaticViaInstance") -public class InsightPumpPlugin implements PluginBase, PumpInterface, ConstraintsInterface { +public class InsightPlugin implements PluginBase, PumpInterface, ConstraintsInterface { private static final long BUSY_WAIT_TIME = 20000; static Integer batteryPercent = 0; static Integer reservoirInUnits = 0; static boolean initialized = false; private static volatile boolean update_pending = false; - private static Logger log = LoggerFactory.getLogger(InsightPumpPlugin.class); - private static volatile InsightPumpPlugin plugin; - private final InsightPumpAsyncAdapter async = new InsightPumpAsyncAdapter(); + private static Logger log = LoggerFactory.getLogger(InsightPlugin.class); + private static volatile InsightPlugin plugin; + private final InsightAsyncAdapter async = new InsightAsyncAdapter(); private StatusTaskRunner.Result statusResult; private long statusResultTime = -1; private Date lastDataTime = new Date(0); @@ -102,8 +96,8 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints private volatile boolean connector_enabled = false; private List profileBlocks; - private InsightPumpPlugin() { - log("InsightPumpPlugin instantiated"); + private InsightPlugin() { + log("InsightPlugin instantiated"); pumpDescription.isBolusCapable = true; pumpDescription.bolusStep = 0.05d; // specification says 0.05U up to 2U then 0.1U @ 2-5U 0.2U @ 10-20U 0.5U 10-20U (are these just UI restrictions?) @@ -135,7 +129,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints } - public static InsightPumpPlugin getPlugin() { + public static InsightPlugin getPlugin() { if (plugin == null) { createInstance(); } @@ -145,7 +139,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints private static synchronized void createInstance() { if (plugin == null) { log("creating instance"); - plugin = new InsightPumpPlugin(); + plugin = new InsightPlugin(); } } @@ -156,10 +150,10 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints private static void updateGui() { update_pending = false; - MainApp.bus().post(new EventInsightPumpUpdateGui()); + MainApp.bus().post(new EventInsightUpdateGui()); } - private static void pushCallbackEvent(EventInsightPumpCallback e) { + private static void pushCallbackEvent(EventInsightCallback e) { MainApp.bus().post(e); } @@ -190,7 +184,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints @Override public String getFragmentClass() { - return InsightPumpFragment.class.getName(); + return InsightFragment.class.getName(); } @Override @@ -237,7 +231,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == PUMP) { if (fragmentEnabled) { enableConnector(); @@ -295,7 +289,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints @Override public void connect(String reason) { - log("InsightPumpPlugin::connect()"); + log("InsightPlugin::connect()"); try { if (!connector.isPumpConnected()) { if (Helpers.ratelimit("insight-connect-timer", 40)) { @@ -317,7 +311,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints @Override public void disconnect(String reason) { - log("InsightPumpPlugin::disconnect()"); + log("InsightPlugin::disconnect()"); try { if (!SP.getBoolean("insight_always_connected", false)) { log("Requesting disconnect"); @@ -332,7 +326,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints @Override public void stopConnecting() { - log("InsightPumpPlugin::stopConnecting()"); + log("InsightPlugin::stopConnecting()"); try { if (isConnecting()) { if (!SP.getBoolean("insight_always_connected", false)) { @@ -360,7 +354,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(); @@ -380,6 +374,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(); @@ -395,7 +393,8 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints for (int i = 0; i < profile.getBasalValues().length; i++) { Profile.BasalValue basalValue = profile.getBasalValues()[i]; Profile.BasalValue nextValue = null; - if (profile.getBasalValues().length > i + 1) nextValue = profile.getBasalValues()[i + 1]; + if (profile.getBasalValues().length > i + 1) + nextValue = profile.getBasalValues()[i + 1]; profileBlocks.add(new BRProfileBlock.ProfileBlock((((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60), Helpers.roundDouble(basalValue.value, 2))); log("setNewBasalProfile: " + basalValue.value + " for " + Integer.toString(((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60)); } @@ -425,12 +424,15 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints BRProfileBlock.ProfileBlock profileBlock = profileBlocks.get(i); Profile.BasalValue basalValue = profile.getBasalValues()[i]; Profile.BasalValue nextValue = null; - if (profile.getBasalValues().length > i + 1) nextValue = profile.getBasalValues()[i + 1]; + if (profile.getBasalValues().length > i + 1) + nextValue = profile.getBasalValues()[i + 1]; log("isThisProfileSet - Comparing block: Pump: " + profileBlock.getAmount() + " for " + profileBlock.getDuration() + " Profile: " + basalValue.value + " for " + Integer.toString(((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60)); - if (profileBlock.getDuration() * 60 != (nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) return false; + if (profileBlock.getDuration() * 60 != (nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) + return false; //Allow a little imprecision due to rounding errors - if (Math.abs(profileBlock.getAmount() - Helpers.roundDouble(basalValue.value, 2)) >= 0.01D) return false; + if (Math.abs(profileBlock.getAmount() - Helpers.roundDouble(basalValue.value, 2)) >= 0.01D) + return false; } return true; } @@ -485,7 +487,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints Treatment t = new Treatment(); t.isSMB = detailedBolusInfo.isSMB; final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); - bolusingEvent.t = t; + bolusingEvent.t = t; bolusingEvent.status = String.format(MainApp.sResources.getString(R.string.bolusdelivering), 0F); bolusingEvent.bolusId = bolusId; bolusingEvent.percent = 0; @@ -517,9 +519,12 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); ActiveBolusesMessage activeBolusesMessage = (ActiveBolusesMessage) mstatus.getResponseObject(); ActiveBolus activeBolus = null; - if (activeBolusesMessage.getBolus1() != null && activeBolusesMessage.getBolus1().getBolusID() == bolusingEvent.bolusId) activeBolus = activeBolusesMessage.getBolus1(); - else if (activeBolusesMessage.getBolus2() != null && activeBolusesMessage.getBolus2().getBolusID() == bolusingEvent.bolusId) activeBolus = activeBolusesMessage.getBolus2(); - else if (activeBolusesMessage.getBolus3() != null && activeBolusesMessage.getBolus3().getBolusID() == bolusingEvent.bolusId) activeBolus = activeBolusesMessage.getBolus3(); + if (activeBolusesMessage.getBolus1() != null && activeBolusesMessage.getBolus1().getBolusID() == bolusingEvent.bolusId) + activeBolus = activeBolusesMessage.getBolus1(); + else if (activeBolusesMessage.getBolus2() != null && activeBolusesMessage.getBolus2().getBolusID() == bolusingEvent.bolusId) + activeBolus = activeBolusesMessage.getBolus2(); + else if (activeBolusesMessage.getBolus3() != null && activeBolusesMessage.getBolus3().getBolusID() == bolusingEvent.bolusId) + activeBolus = activeBolusesMessage.getBolus3(); if (activeBolus == null) break; else { bolusingEvent.percent = (int) (100D / activeBolus.getInitialAmount() * (activeBolus.getInitialAmount() - activeBolus.getLeftoverAmount())); @@ -548,7 +553,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(); @@ -567,7 +572,6 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints if (percent_amount > 250) percent_amount = 250; - final SetTBRTaskRunner task = new SetTBRTaskRunner(connector.getServiceConnector(), percent_amount, durationInMinutes); final UUID cmd = aSyncTaskRunner(task, "Set TBR abs: " + absoluteRate + " " + durationInMinutes + "m"); @@ -612,7 +616,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints @Override - public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) { + public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) { log("Set TBR %"); percent = (int) Math.round(((double) percent) / 10d) * 10; @@ -1007,7 +1011,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints // if (!isConnected()) return false; //if (isBusy()) return false; log("asyncSinglecommand called: " + name); - final EventInsightPumpCallback event = new EventInsightPumpCallback(); + final EventInsightCallback event = new EventInsightCallback(); new Thread() { @Override public void run() { @@ -1046,7 +1050,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints // if (!isConnected()) return false; //if (isBusy()) return false; log("asyncTaskRunner called: " + name); - final EventInsightPumpCallback event = new EventInsightPumpCallback(); + final EventInsightCallback event = new EventInsightCallback(); new Thread() { @Override public void run() { @@ -1085,54 +1089,26 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints // Constraints @Override - public boolean isLoopEnabled() { - return true; + public Constraint applyBasalConstraints(Constraint absoluteRate, Profile profile) { + if (statusResult != null) { + absoluteRate.setIfSmaller(statusResult.maximumBasalAmount, String.format(MainApp.gs(R.string.limitingbasalratio), statusResult.maximumBasalAmount, MainApp.gs(R.string.pumplimit)), this); + } + return absoluteRate; } @Override - public boolean isClosedModeEnabled() { - return true; + public Constraint applyBasalPercentConstraints(Constraint percentRate, Profile profile) { + percentRate.setIfGreater(0, String.format(MainApp.gs(R.string.limitingpercentrate), 0, MainApp.gs(R.string.itmustbepositivevalue)), this); + percentRate.setIfSmaller(getPumpDescription().maxTempPercent, String.format(MainApp.gs(R.string.limitingpercentrate), getPumpDescription().maxTempPercent, MainApp.gs(R.string.pumplimit)), this); + + return percentRate; } @Override - public boolean isAutosensModeEnabled() { - return true; + public Constraint applyBolusConstraints(Constraint insulin) { + if (statusResult != null) + insulin.setIfSmaller(statusResult.maximumBolusAmount, String.format(MainApp.gs(R.string.limitingbolus), statusResult.maximumBolusAmount, MainApp.gs(R.string.pumplimit)), this); + return insulin; } - @Override - public boolean isAMAModeEnabled() { - return true; - } - - @Override - public boolean isSMBModeEnabled() { - return true; - } - - @Override - public Double applyBasalConstraints(Double absoluteRate) { - return Math.min(absoluteRate, statusResult != null ? statusResult.maximumBasalAmount : 0); - } - - @Override - public Integer applyBasalConstraints(Integer percentRate) { - return Math.min(percentRate, pumpDescription.maxTempPercent); - } - - @Override - public Double applyBolusConstraints(Double insulin) { - return Math.min(insulin, statusResult != null ? statusResult.maximumBolusAmount : 0); - } - - @Override - public Integer applyCarbsConstraints(Integer carbs) { - return carbs; - } - - @Override - public Double applyMaxIOBConstraints(Double maxIob) { - return maxIob; - } - - } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/Mstatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/Mstatus.java index 57e6da7f2a..8797325f7c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/Mstatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/Mstatus.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.plugins.PumpInsight; -import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightPumpCallback; +import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightCallback; /** * Created by jamorham on 01/02/2018. @@ -11,7 +11,7 @@ import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightPumpCal class Mstatus { Cstatus cstatus = Cstatus.UNKNOWN; - EventInsightPumpCallback event; + EventInsightCallback event; // comment field preparation for results String getCommandComment() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/Connector.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/Connector.java index 311e487b9f..a96c98a39a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/Connector.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/Connector.java @@ -14,7 +14,7 @@ import java.util.Map; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventFeatureRunning; -import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightPumpUpdateGui; +import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightUpdateGui; import info.nightscout.androidaps.plugins.PumpInsight.history.HistoryReceiver; import info.nightscout.androidaps.plugins.PumpInsight.history.LiveHistory; import info.nightscout.androidaps.plugins.PumpInsight.utils.Helpers; @@ -76,7 +76,7 @@ public class Connector { extendKeepAliveIfActive(); } - MainApp.bus().post(new EventInsightPumpUpdateGui()); + MainApp.bus().post(new EventInsightUpdateGui()); } else { log("Same status as before: " + status); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightPumpCallback.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightCallback.java similarity index 86% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightPumpCallback.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightCallback.java index 964270cb45..16cb5af457 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightPumpCallback.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightCallback.java @@ -7,7 +7,7 @@ import info.nightscout.androidaps.events.Event; /** * Created by jamorham on 23/01/2018. */ -public class EventInsightPumpCallback extends Event { +public class EventInsightCallback extends Event { public UUID request_uuid; public boolean success = false; @@ -15,7 +15,7 @@ public class EventInsightPumpCallback extends Event { public int response_id = -1; public Object response_object = null; - public EventInsightPumpCallback() { + public EventInsightCallback() { request_uuid = UUID.randomUUID(); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightPumpUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightUpdateGui.java similarity index 72% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightPumpUpdateGui.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightUpdateGui.java index 79e975ac31..3741c607c4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightPumpUpdateGui.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightUpdateGui.java @@ -5,5 +5,5 @@ import info.nightscout.androidaps.events.EventUpdateGui; /** * Created by jamorham on 23/01/2018. */ -public class EventInsightPumpUpdateGui extends EventUpdateGui { +public class EventInsightUpdateGui extends EventUpdateGui { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java index 0d726b5dcd..407edc298a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java @@ -90,7 +90,7 @@ public class MDIPlugin implements PluginBase, PumpInterface { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == PUMP) this.fragmentEnabled = fragmentEnabled; } @@ -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); @@ -204,7 +204,7 @@ public class MDIPlugin implements PluginBase, PumpInterface { } @Override - public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) { + public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) { PumpEnactResult result = new PumpEnactResult(); result.success = false; result.comment = MainApp.instance().getString(R.string.pumperror); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java index 0a38477808..00ff2fc7a4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java @@ -151,7 +151,7 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == PUMP) this.fragmentEnabled = fragmentEnabled; } @@ -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(); @@ -313,7 +313,7 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { } @Override - public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) { + public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) { TreatmentsInterface treatmentsInterface = MainApp.getConfigBuilder(); PumpEnactResult result = new PumpEnactResult(); if (MainApp.getConfigBuilder().isTempBasalInProgress()) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java index 067ecdef8f..e321e98f1e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java @@ -88,7 +88,7 @@ public class SensitivityAAPSPlugin implements PluginBase, SensitivityInterface{ } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == SENSITIVITY) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java index 5c6188788c..bcac02f51c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java @@ -87,7 +87,7 @@ public class SensitivityOref0Plugin implements PluginBase, SensitivityInterface } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == SENSITIVITY) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java index d80510d8a8..7b2592c7e8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java @@ -84,7 +84,7 @@ public class SensitivityWeightedAveragePlugin implements PluginBase, Sensitivity } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == SENSITIVITY) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java index 01f883e6d6..a67c8d4212 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java @@ -29,11 +29,12 @@ 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; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS; @@ -176,7 +177,7 @@ public class SmsCommunicatorPlugin implements PluginBase { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == GENERAL) this.fragmentEnabled = fragmentEnabled; } @@ -285,7 +286,7 @@ public class SmsCommunicatorPlugin implements PluginBase { case "STOP": LoopPlugin loopPlugin = MainApp.getSpecificPlugin(LoopPlugin.class); if (loopPlugin != null && loopPlugin.isEnabled(PluginBase.LOOP)) { - loopPlugin.setFragmentEnabled(PluginBase.LOOP, false); + loopPlugin.setPluginEnabled(PluginBase.LOOP, false); ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() { @Override public void run() { @@ -303,7 +304,7 @@ public class SmsCommunicatorPlugin implements PluginBase { case "START": loopPlugin = MainApp.getSpecificPlugin(LoopPlugin.class); if (loopPlugin != null && !loopPlugin.isEnabled(PluginBase.LOOP)) { - loopPlugin.setFragmentEnabled(PluginBase.LOOP, true); + loopPlugin.setPluginEnabled(PluginBase.LOOP, true); reply = MainApp.sResources.getString(R.string.smscommunicator_loophasbeenenabled); sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_START")); @@ -418,18 +419,24 @@ public class SmsCommunicatorPlugin implements PluginBase { } } else { tempBasal = SafeParse.stringToDouble(splited[1]); - tempBasal = MainApp.getConfigBuilder().applyBasalConstraints(tempBasal); - if (remoteCommandsAllowed) { - passCode = generatePasscode(); - reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_basalreplywithcode), tempBasal, passCode); - receivedSms.processed = true; - resetWaitingMessages(); - sendSMS(tempBasalWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, new Date(), passCode)); - tempBasalWaitingForConfirmation.tempBasal = tempBasal; - FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Basal")); - } else { - reply = MainApp.sResources.getString(R.string.smscommunicator_remotebasalnotallowed); + 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); + receivedSms.processed = true; + resetWaitingMessages(); + sendSMS(tempBasalWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, new Date(), passCode)); + tempBasalWaitingForConfirmation.tempBasal = tempBasal; + FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Basal")); + } else { + reply = MainApp.sResources.getString(R.string.smscommunicator_remotebasalnotallowed); + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + } } } } @@ -443,7 +450,7 @@ public class SmsCommunicatorPlugin implements PluginBase { sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); } else if (splited.length > 1) { amount = SafeParse.stringToDouble(splited[1]); - amount = MainApp.getConfigBuilder().applyBolusConstraints(amount); + amount = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(amount)).value(); if (amount > 0d && remoteCommandsAllowed) { passCode = generatePasscode(); reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_bolusreplywithcode), amount, passCode); @@ -503,20 +510,22 @@ 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() { - @Override - public void run() { - if (result.success) { - String reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_tempbasalset), result.absolute, result.duration); - reply += "\n" + ConfigBuilderPlugin.getActivePump().shortStatus(true); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); - } else { - String reply = MainApp.sResources.getString(R.string.smscommunicator_tempbasalfailed); - reply += "\n" + ConfigBuilderPlugin.getActivePump().shortStatus(true); - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + 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) { + String reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_tempbasalset), result.absolute, result.duration); + reply += "\n" + ConfigBuilderPlugin.getActivePump().shortStatus(true); + sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); + } else { + String reply = MainApp.sResources.getString(R.string.smscommunicator_tempbasalfailed); + reply += "\n" + ConfigBuilderPlugin.getActivePump().shortStatus(true); + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + } } - } - }); + }); } else if (cancelTempBasalWaitingForConfirmation != null && !cancelTempBasalWaitingForConfirmation.processed && cancelTempBasalWaitingForConfirmation.confirmCode.equals(splited[0]) && System.currentTimeMillis() - cancelTempBasalWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { cancelTempBasalWaitingForConfirmation.processed = true; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceDexcomG5/SourceDexcomG5Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceDexcomG5/SourceDexcomG5Plugin.java index 8b9734cb79..719b2eb1f4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceDexcomG5/SourceDexcomG5Plugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceDexcomG5/SourceDexcomG5Plugin.java @@ -68,7 +68,7 @@ public class SourceDexcomG5Plugin implements PluginBase, BgSourceInterface { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == BGSOURCE) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceGlimp/SourceGlimpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceGlimp/SourceGlimpPlugin.java index eb9a6b1c6b..719a4b3059 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceGlimp/SourceGlimpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceGlimp/SourceGlimpPlugin.java @@ -68,7 +68,7 @@ public class SourceGlimpPlugin implements PluginBase, BgSourceInterface { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == BGSOURCE) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceMM640g/SourceMM640gPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceMM640g/SourceMM640gPlugin.java index 1111c8c9eb..38b787d750 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceMM640g/SourceMM640gPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceMM640g/SourceMM640gPlugin.java @@ -68,7 +68,7 @@ public class SourceMM640gPlugin implements PluginBase, BgSourceInterface { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == BGSOURCE) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceNSClient/SourceNSClientPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceNSClient/SourceNSClientPlugin.java index f43c44047e..bbc1759735 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceNSClient/SourceNSClientPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceNSClient/SourceNSClientPlugin.java @@ -70,7 +70,7 @@ public class SourceNSClientPlugin implements PluginBase, BgSourceInterface { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == BGSOURCE) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceXdrip/SourceXdripPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceXdrip/SourceXdripPlugin.java index 532492d40e..66e8d470fd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceXdrip/SourceXdripPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceXdrip/SourceXdripPlugin.java @@ -69,7 +69,7 @@ public class SourceXdripPlugin implements PluginBase, BgSourceInterface { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == BGSOURCE) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java index bc697817d5..8254293c4d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java @@ -113,7 +113,7 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == TREATMENT) this.fragmentEnabled = fragmentEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java index b304490e22..190df0a692 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java @@ -1,6 +1,5 @@ package info.nightscout.androidaps.plugins.Wear; -import android.Manifest; import android.os.HandlerThread; import android.support.annotation.NonNull; @@ -26,8 +25,8 @@ import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.interfaces.APSInterface; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Actions.dialogs.FillDialog; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; @@ -94,7 +93,7 @@ public class ActionStringHandler { } else { return; } - Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(amount); + Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(amount)).value(); rMessage += MainApp.instance().getString(R.string.primefill) + ": " + insulinAfterConstraints + "U"; if (insulinAfterConstraints - amount != 0) rMessage += "\n" + MainApp.instance().getString(R.string.constraintapllied); @@ -105,7 +104,7 @@ public class ActionStringHandler { ////////////////////////////////////////////// PRIME/FILL double amount = SafeParse.stringToDouble(act[1]); - Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(amount); + Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(amount)).value(); rMessage += MainApp.instance().getString(R.string.primefill) + ": " + insulinAfterConstraints + "U"; if (insulinAfterConstraints - amount != 0) rMessage += "\n" + MainApp.instance().getString(R.string.constraintapllied); @@ -116,8 +115,8 @@ public class ActionStringHandler { ////////////////////////////////////////////// BOLUS double insulin = SafeParse.stringToDouble(act[1]); int carbs = SafeParse.stringToInt(act[2]); - Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(insulin); - Integer carbsAfterConstraints = MainApp.getConfigBuilder().applyCarbsConstraints(carbs); + Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value(); + Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(carbs)).value(); rMessage += MainApp.instance().getString(R.string.bolus) + ": " + insulinAfterConstraints + "U\n"; rMessage += MainApp.instance().getString(R.string.carbs) + ": " + carbsAfterConstraints + "g"; @@ -181,7 +180,7 @@ public class ActionStringHandler { } else if ("wizard".equals(act[0])) { ////////////////////////////////////////////// WIZARD Integer carbsBeforeConstraints = SafeParse.stringToInt(act[1]); - Integer carbsAfterConstraints = MainApp.getConfigBuilder().applyCarbsConstraints(carbsBeforeConstraints); + Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(carbsBeforeConstraints)).value(); if (carbsAfterConstraints - carbsBeforeConstraints != 0) { sendError("Carb constraint violation!"); @@ -209,7 +208,7 @@ public class ActionStringHandler { BolusWizard bolusWizard = new BolusWizard(); bolusWizard.doCalc(profile, null, carbsAfterConstraints, 0d, useBG ? bgReading.valueToUnits(profile.getUnits()) : 0d, 0d, percentage, useBolusIOB, useBasalIOB, false, false); - Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(bolusWizard.calculatedTotalInsulin); + Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(bolusWizard.calculatedTotalInsulin)).value(); if (insulinAfterConstraints - bolusWizard.calculatedTotalInsulin != 0) { sendError("Insulin contraint violation!" + "\nCannot deliver " + format.format(bolusWizard.calculatedTotalInsulin) + "!"); @@ -436,7 +435,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.getConfigBuilder().isClosedModeEnabled()) { + if (MainApp.getConstraintChecker().isClosedLoopAllowed().value()) { ret += "CLOSED LOOP\n"; } else { ret += "OPEN LOOP\n"; @@ -536,7 +535,7 @@ public class ActionStringHandler { if ("fill".equals(act[0])) { Double amount = SafeParse.stringToDouble(act[1]); - Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(amount); + Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(amount)).value(); if (amount - insulinAfterConstraints != 0) { ToastUtils.showToastInUiThread(MainApp.instance(), "aborting: previously applied constraint changed"); sendError("aborting: previously applied constraint changed"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java index 5f11fc5fda..f37effebe3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java @@ -107,7 +107,7 @@ public class WearPlugin implements PluginBase { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == GENERAL) { this.fragmentEnabled = fragmentEnabled; if (watchUS != null) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java index 76e8ac9e4d..d2df702cd4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java @@ -117,7 +117,7 @@ public class StatuslinePlugin implements PluginBase { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { if (type == GENERAL) { this.fragmentEnabled = fragmentEnabled; diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java index 748ada61f6..2b89113da4 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java @@ -18,13 +18,14 @@ 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; import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressHelperActivity; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.queue.commands.Command; import info.nightscout.androidaps.queue.commands.CommandBolus; import info.nightscout.androidaps.queue.commands.CommandCancelExtendedBolus; @@ -165,8 +166,8 @@ public class CommandQueue { removeAll(type); // apply constraints - detailedBolusInfo.insulin = MainApp.getConfigBuilder().applyBolusConstraints(detailedBolusInfo.insulin); - detailedBolusInfo.carbs = MainApp.getConfigBuilder().applyCarbsConstraints((int) detailedBolusInfo.carbs); + detailedBolusInfo.insulin = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value(); + detailedBolusInfo.carbs = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>((int) detailedBolusInfo.carbs)).value(); // add new command to queue if (detailedBolusInfo.isSMB) { @@ -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.getConfigBuilder().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(); @@ -207,7 +208,7 @@ public class CommandQueue { } // returns true if command is queued - public boolean tempBasalPercent(int percent, int durationInMinutes, boolean enforceNew, Callback callback) { + public boolean tempBasalPercent(Integer percent, int durationInMinutes, boolean enforceNew, Profile profile, Callback callback) { if (isRunning(Command.CommandType.TEMPBASAL)) { if (callback != null) callback.result(executingNowError()).run(); @@ -217,10 +218,10 @@ public class CommandQueue { // remove all unfinished removeAll(Command.CommandType.TEMPBASAL); - Integer percentAfterConstraints = MainApp.getConfigBuilder().applyBasalConstraints(percent); + Integer percentAfterConstraints = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(percent), profile).value(); // add new command to queue - add(new CommandTempBasalPercent(percentAfterConstraints, durationInMinutes, enforceNew, callback)); + add(new CommandTempBasalPercent(percentAfterConstraints, durationInMinutes, enforceNew, profile, callback)); notifyAboutNewCommand(); @@ -235,7 +236,7 @@ public class CommandQueue { return false; } - Double rateAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(insulin); + Double rateAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value(); // remove all unfinished removeAll(Command.CommandType.EXTENDEDBOLUS); diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalAbsolute.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalAbsolute.java index 28dc728174..35c2435558 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalAbsolute.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalAbsolute.java @@ -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) diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalPercent.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalPercent.java index 15f8849cd2..bbb421e128 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalPercent.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalPercent.java @@ -4,6 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.queue.Callback; @@ -18,18 +19,20 @@ public class CommandTempBasalPercent extends Command { int durationInMinutes; int percent; boolean enforceNew; + Profile profile; - public CommandTempBasalPercent(int percent, int durationInMinutes, boolean enforceNew, Callback callback) { + public CommandTempBasalPercent(int percent, int durationInMinutes, boolean enforceNew, Profile profile, Callback callback) { commandType = CommandType.TEMPBASAL; this.percent = percent; this.durationInMinutes = durationInMinutes; this.enforceNew = enforceNew; + this.profile = profile; this.callback = callback; } @Override public void execute() { - PumpEnactResult r = ConfigBuilderPlugin.getActivePump().setTempBasalPercent(percent, durationInMinutes, enforceNew); + PumpEnactResult r = ConfigBuilderPlugin.getActivePump().setTempBasalPercent(percent, durationInMinutes, profile, enforceNew); if (Config.logCongigBuilderActions) log.debug("setTempBasalPercent percent: " + percent + " durationInMinutes: " + durationInMinutes + " success: " + r.success + " enacted: " + r.enacted); if (callback != null) diff --git a/app/src/main/java/info/nightscout/utils/HardLimits.java b/app/src/main/java/info/nightscout/utils/HardLimits.java index a277148d11..8e1a05db0d 100644 --- a/app/src/main/java/info/nightscout/utils/HardLimits.java +++ b/app/src/main/java/info/nightscout/utils/HardLimits.java @@ -49,13 +49,13 @@ public class HardLimits { String sp_age = SP.getString(R.string.key_age, ""); int age; - if (sp_age.equals(MainApp.sResources.getString(R.string.key_child))) + if (sp_age.equals(MainApp.gs(R.string.key_child))) age = CHILD; - else if (sp_age.equals(MainApp.sResources.getString(R.string.key_teenage))) + else if (sp_age.equals(MainApp.gs(R.string.key_teenage))) age = TEENAGE; - else if (sp_age.equals(MainApp.sResources.getString(R.string.key_adult))) + else if (sp_age.equals(MainApp.gs(R.string.key_adult))) age = ADULT; - else if (sp_age.equals(MainApp.sResources.getString(R.string.key_resistantadult))) + else if (sp_age.equals(MainApp.gs(R.string.key_resistantadult))) age = RESISTANTADULT; else age = ADULT; @@ -88,9 +88,9 @@ public class HardLimits { if (newvalue < lowLimit || newvalue > highLimit) { newvalue = Math.max(newvalue, lowLimit); newvalue = Math.min(newvalue, highLimit); - String msg = String.format(MainApp.sResources.getString(R.string.valueoutofrange), valueName); + String msg = String.format(MainApp.gs(R.string.valueoutofrange), valueName); msg += ".\n"; - msg += String.format(MainApp.sResources.getString(R.string.valuelimitedto), value, newvalue); + msg += String.format(MainApp.gs(R.string.valuelimitedto), value, newvalue); log.error(msg); NSUpload.uploadError(msg); ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), msg, R.raw.error); diff --git a/app/src/main/res/layout/configbuilder_fragment.xml b/app/src/main/res/layout/configbuilder_fragment.xml index 2b2a7ef185..90e0026418 100644 --- a/app/src/main/res/layout/configbuilder_fragment.xml +++ b/app/src/main/res/layout/configbuilder_fragment.xml @@ -184,7 +184,7 @@ android:layout_marginBottom="5dp" android:background="@color/mdtp_circle_color" android:paddingLeft="5dp" - android:text="@string/configbuilder_constraints" + android:text="@string/constraints" android:textAllCaps="true" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="@android:color/black" diff --git a/app/src/main/res/layout/insightpump_fragment.xml b/app/src/main/res/layout/insightpump_fragment.xml index 4d3d580336..2ab1a50d2a 100644 --- a/app/src/main/res/layout/insightpump_fragment.xml +++ b/app/src/main/res/layout/insightpump_fragment.xml @@ -2,7 +2,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context="info.nightscout.androidaps.plugins.PumpInsight.InsightPumpFragment"> + tools:context="info.nightscout.androidaps.plugins.PumpInsight.InsightFragment"> + + + + + + + + + + + + + + + + + + + + + + Общи дни Минимална продължителност - Ограничения + Ограничения Loop Loop APS diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index a62329ae4b..4ce126527c 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -47,7 +47,7 @@ Konfigurace APS Zdroj glykémie - Omezení + Omezení Obecné Smyčka Profil @@ -734,7 +734,7 @@ Použít super mikro bolusy místo dočasných bazálů pro zrychlení účinku Detekce neoznámených jídel Insight - Pumpa Insight + Insight Stav Změněno PUMPA ZASTAVENA diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index bbe2ed5497..0bad8b97e0 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -141,7 +141,7 @@ Eingegeben durch Anderes Split - Beschränkungen + Beschränkungen Generell Behandlungen Beschränkungen angewendet! diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 1b7fdf8022..d071fa7f8e 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -86,7 +86,7 @@ Γενικά ημέρες Ελάχ.Διάρκεια - Περιορισμοί + Περιορισμοί Κύκλωμα Κύκλωμα APS diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index af936ed618..ee63a899c3 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -78,7 +78,7 @@ General días Duración mínima - Restricciones + Restricciones Lazo Lazo APS diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 67ecda2b0f..2d0d2ff32d 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -81,7 +81,7 @@ Général Jours Durée minimale - Restrictions + Restrictions Loop Loop APS diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 352f802ee6..3c738259b3 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -71,7 +71,7 @@ Configurazione Strutturale APS Origine glicemia - Costrizione + Costrizione Generale Insulina Loop diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 46f1cb3525..89d0dca30d 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -84,7 +84,7 @@ 일반 최소기간 - 제한 + 제한 Loop Loop APS diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index ca73dcbffa..86cab639c4 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -129,7 +129,7 @@ Configurator APS BG bron - Beperkingen + Beperkingen Algemeen Insuline curve Ledig wachtrij diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index aca835b34d..e6ade785bb 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -83,7 +83,7 @@ General zile Durată minimă - Constrângeri + Constrângeri Loop Loop diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index ddc446b62c..f1e03c7251 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -84,7 +84,7 @@ конфигуратор APS источник СК - ограничения + ограничения общее инсулин замкнутый цикл diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 669f96e4e9..47bd827e0a 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -84,7 +84,7 @@ Konfigurationsverktyg APS BG Källa - Begränsningar + Begränsningar Generell Insulin Loop diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ffe1df0bc9..4ff9bce87d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -89,7 +89,7 @@ General days Minimal duration - Constraints + Constraints Loop Loop @@ -430,9 +430,7 @@ Advanced Settings Model: %02X Protocol: %02X Code: %02X Profile - max_daily_safety_multiplier 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 that’s what is discussed about “3x max daily; 4x current” for safety caps. - current_basal_safety_multiplier 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. autosens_max 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. @@ -962,7 +960,34 @@ ProfileSwitch missing. Please do a profile switch or press \"Activate Profile\" in the LocalProfile. Bolus count TBR count + Objective %d not started + Objective %d not finished + Pump is not temp basal capable + No valid basal rate read from pump + Closed loop mode disabled in preferences + Autosens disabled in preferences + SMB disabled in preferences + Limiting max basal rate to %.2f U/h because of %s + pump limit + openapsma_max_basal + openapsama_current_basal_safety_multiplier + openapsama_max_daily_safety_multiplier + it must be positive value + max basal multiplier + max daily basal multiplier + openapsma_max_iob A bolus was delivered within the last 3 minutes, skipping SMB Basal set correctly + Limiting max percent rate to %d%% because of %s + treatmentssafety_maxbolus + Limiting bolus to %.1f U because of %s + Limiting max IOB to %.1f U because of %s + Limiting carbs to %d g because of %s + Limiting IOB to %.1f U because of %s + max value in preferences + hard limit + treatmentssafety_maxcarbs + unsafe usage + openapsama_useautosens diff --git a/app/src/main/res/xml/pref_advanced.xml b/app/src/main/res/xml/pref_advanced.xml index cc0d496943..260e2c5135 100644 --- a/app/src/main/res/xml/pref_advanced.xml +++ b/app/src/main/res/xml/pref_advanced.xml @@ -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" /> diff --git a/app/src/main/res/xml/pref_openapsama.xml b/app/src/main/res/xml/pref_openapsama.xml index 7dfcf7ad72..944f057919 100644 --- a/app/src/main/res/xml/pref_openapsama.xml +++ b/app/src/main/res/xml/pref_openapsama.xml @@ -7,19 +7,19 @@ diff --git a/app/src/main/res/xml/pref_openapssmb.xml b/app/src/main/res/xml/pref_openapssmb.xml index da0b64a91c..098d874eaa 100644 --- a/app/src/main/res/xml/pref_openapssmb.xml +++ b/app/src/main/res/xml/pref_openapssmb.xml @@ -6,13 +6,13 @@ android:title="@string/openapssmb"> diff --git a/app/src/main/res/xml/pref_safety.xml b/app/src/main/res/xml/pref_safety.xml index 1cf759487d..e906c92608 100644 --- a/app/src/main/res/xml/pref_safety.xml +++ b/app/src/main/res/xml/pref_safety.xml @@ -6,13 +6,13 @@ diff --git a/app/src/test/java/info/AAPSMocker.java b/app/src/test/java/info/AAPSMocker.java new file mode 100644 index 0000000000..a39fd4595e --- /dev/null +++ b/app/src/test/java/info/AAPSMocker.java @@ -0,0 +1,96 @@ +package info; + +import android.content.Context; + +import com.squareup.otto.Bus; + +import org.json.JSONException; +import org.json.JSONObject; +import org.powermock.api.mockito.PowerMockito; + +import java.util.Locale; + +import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.utils.SP; + +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Created by mike on 23.03.2018. + */ + +public class AAPSMocker { + static 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\"}"; + static Profile profile; + + public static void mockStrings() { + Locale.setDefault(new Locale("en", "US")); + + when(MainApp.gs(R.string.closed_loop_disabled_on_dev_branch)).thenReturn("Running dev version. Closed loop is disabled."); + when(MainApp.gs(R.string.closedmodedisabledinpreferences)).thenReturn("Closed loop mode disabled in preferences"); + when(MainApp.gs(R.string.objectivenotstarted)).thenReturn("Objective %d not started"); + when(MainApp.gs(R.string.novalidbasalrate)).thenReturn("No valid basal rate read from pump"); + when(MainApp.gs(R.string.autosensdisabledinpreferences)).thenReturn("Autosens 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.itmustbepositivevalue)).thenReturn("it must be positive value"); + when(MainApp.gs(R.string.maxvalueinpreferences)).thenReturn("max value in preferences"); + when(MainApp.gs(R.string.maxbasalmultiplier)).thenReturn("max basal multiplier"); + when(MainApp.gs(R.string.maxdailybasalmultiplier)).thenReturn("max daily basal multiplier"); + when(MainApp.gs(R.string.limitingpercentrate)).thenReturn("Limiting percent rate to %d%% because of %s"); + when(MainApp.gs(R.string.pumplimit)).thenReturn("pump limit"); + when(MainApp.gs(R.string.limitingbolus)).thenReturn("Limiting bolus to %.1f U because of %s"); + when(MainApp.gs(R.string.hardlimit)).thenReturn("hard limit"); + when(MainApp.gs(R.string.key_child)).thenReturn("child"); + when(MainApp.gs(R.string.limitingcarbs)).thenReturn("Limiting carbs to %d g because of %s"); + when(MainApp.gs(R.string.limitingiob)).thenReturn("Limiting IOB to %.1f U because of %s"); + when(MainApp.gs(R.string.pumpisnottempbasalcapable)).thenReturn("Pump is not temp basal capable"); + when(MainApp.gs(R.string.loop)).thenReturn("Loop"); + when(MainApp.gs(R.string.loop_shortname)).thenReturn("LOOP"); + } + + public static MainApp mockMainApp() { + PowerMockito.mockStatic(MainApp.class); + MainApp mainApp = mock(MainApp.class); + when(MainApp.instance()).thenReturn(mainApp); + return mainApp; + } + + public static void mockConfigBuilder() { + PowerMockito.mockStatic(ConfigBuilderPlugin.class); + ConfigBuilderPlugin configBuilderPlugin = mock(ConfigBuilderPlugin.class); + when(MainApp.getConfigBuilder()).thenReturn(configBuilderPlugin); + } + + public static void mockBus() { + Bus bus = PowerMockito.mock(Bus.class); + when(MainApp.bus()).thenReturn(bus); + } + + public static void mockSP() { + PowerMockito.mockStatic(SP.class); + when(SP.getLong(anyInt(), anyLong())).thenReturn(0L); + when(SP.getBoolean(anyInt(), anyBoolean())).thenReturn(false); + when(SP.getInt(anyInt(), anyInt())).thenReturn(0); + } + + public static void mockApplicationContext() { + Context context = mock(Context.class); + when(MainApp.instance().getApplicationContext()).thenReturn(context); + } + + public static Profile getValidProfile() throws JSONException { + if (profile == null) + profile = new Profile(new JSONObject(validProfile), Constants.MGDL); + return profile; + } +} diff --git a/app/src/test/java/info/nightscout/androidaps/PumpDanaR/DanaRPluginTest.java b/app/src/test/java/info/nightscout/androidaps/PumpDanaR/DanaRPluginTest.java new file mode 100644 index 0000000000..33b5dad925 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/PumpDanaR/DanaRPluginTest.java @@ -0,0 +1,76 @@ +package info.nightscout.androidaps.PumpDanaR; + +import android.content.Context; + +import junit.framework.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.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.interfaces.Constraint; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.utils.SP; +import info.nightscout.utils.ToastUtils; + +import static org.mockito.Mockito.when; + +/** + * Created by mike on 23.03.2018. + */ + +@RunWith(PowerMockRunner.class) +@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, ToastUtils.class, Context.class, SP.class}) +public class DanaRPluginTest { + + DanaRPlugin danaRPlugin; + + @Test + public void basalRateShouldBeLimited() throws Exception { + danaRPlugin.setPluginEnabled(PluginBase.PUMP, true); + danaRPlugin.setPluginEnabled(PluginBase.PUMP, true); + DanaRPump.getInstance().maxBasal = 0.8d; + + Constraint c = new Constraint<>(Constants.REALLYHIGHBASALRATE); + danaRPlugin.applyBasalConstraints(c, AAPSMocker.getValidProfile()); + Assert.assertEquals(0.8d, c.value()); + Assert.assertEquals("DanaR: Limiting basal rate to 0.80 U/h because of pump limit", c.getReasons()); + Assert.assertEquals("DanaR: Limiting basal rate to 0.80 U/h because of pump limit", c.getMostLimitedReasons()); + } + + @Test + public void percentBasalRateShouldBeLimited() throws Exception { + danaRPlugin.setPluginEnabled(PluginBase.PUMP, true); + danaRPlugin.setPluginEnabled(PluginBase.PUMP, true); + DanaRPump.getInstance().maxBasal = 0.8d; + + Constraint c = new Constraint<>(Constants.REALLYHIGHPERCENTBASALRATE); + danaRPlugin.applyBasalPercentConstraints(c, AAPSMocker.getValidProfile()); + Assert.assertEquals((Integer) 200, c.value()); + Assert.assertEquals("DanaR: Limiting percent rate to 200% because of pump limit", c.getReasons()); + Assert.assertEquals("DanaR: Limiting percent rate to 200% because of pump limit", c.getMostLimitedReasons()); + } + + @Before + public void prepareMocks() throws Exception { + AAPSMocker.mockMainApp(); + AAPSMocker.mockConfigBuilder(); + AAPSMocker.mockBus(); + AAPSMocker.mockStrings(); + AAPSMocker.mockApplicationContext(); + AAPSMocker.mockSP(); + + when(SP.getString(R.string.key_danars_address, "")).thenReturn(""); + + danaRPlugin = DanaRPlugin.getPlugin(); + } +} diff --git a/app/src/test/java/info/nightscout/androidaps/data/ProfileTest.java b/app/src/test/java/info/nightscout/androidaps/data/ProfileTest.java index ee04a6613a..664515d45d 100644 --- a/app/src/test/java/info/nightscout/androidaps/data/ProfileTest.java +++ b/app/src/test/java/info/nightscout/androidaps/data/ProfileTest.java @@ -13,6 +13,7 @@ import org.powermock.modules.junit4.PowerMockRunner; import org.skyscreamer.jsonassert.JSONAssert; import java.util.Calendar; +import java.util.Locale; import java.util.TimeZone; import info.nightscout.androidaps.Constants; @@ -133,9 +134,9 @@ public class ProfileTest { // Test timeshift functionality p = new Profile(new JSONObject(validProfile), 100, 1); Assert.assertEquals( - "00:00 110,0 mmol/U\n" + - "01:00 100,0 mmol/U\n" + - "03:00 110,0 mmol/U", p.getIsfList().replace(".", ",")); + "00:00 110.0 mmol/U\n" + + "01:00 100.0 mmol/U\n" + + "03:00 110.0 mmol/U", p.getIsfList()); // Test hour alignment MainApp.getConfigBuilder().getActivePump().getPumpDescription().is30minBasalRatesCapable = false; @@ -146,6 +147,7 @@ public class ProfileTest { } private void prepareMock() throws Exception { + Locale.setDefault(new Locale("en", "US")); ConfigBuilderPlugin configBuilderPlugin = mock(ConfigBuilderPlugin.class); PowerMockito.mockStatic(ConfigBuilderPlugin.class); diff --git a/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintTest.java b/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintTest.java new file mode 100644 index 0000000000..23352a57f9 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintTest.java @@ -0,0 +1,50 @@ +package info.nightscout.androidaps.interfaces; + +import junit.framework.Assert; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.modules.junit4.PowerMockRunner; + +/** + * Created by mike on 19.03.2018. + */ + +@RunWith(PowerMockRunner.class) +public class ConstraintTest { + + @Test + public void doTests() throws Exception { + Constraint b = new Constraint<>(true); + Assert.assertEquals(Boolean.TRUE, b.value()); + Assert.assertEquals("", b.getReasons()); + Assert.assertEquals("", b.getMostLimitedReasons()); + b.set(false); + Assert.assertEquals(Boolean.FALSE, b.value()); + Assert.assertEquals("", b.getReasons()); + Assert.assertEquals("", b.getMostLimitedReasons()); + b.set(true, "Set true", this); + Assert.assertEquals(Boolean.TRUE, b.value()); + Assert.assertEquals("ConstraintTest: Set true", b.getReasons()); + Assert.assertEquals("ConstraintTest: Set true", b.getMostLimitedReasons()); + b.set(false, "Set false", this); + Assert.assertEquals(Boolean.FALSE, b.value()); + Assert.assertEquals("ConstraintTest: Set true\nConstraintTest: Set false", b.getReasons()); + Assert.assertEquals("ConstraintTest: Set true\nConstraintTest: Set false", b.getMostLimitedReasons()); + + Constraint d = new Constraint<>(10d); + d.set(5d, "Set 5d", this); + Assert.assertEquals(5d, d.value()); + Assert.assertEquals("ConstraintTest: Set 5d", d.getReasons()); + Assert.assertEquals("ConstraintTest: Set 5d", d.getMostLimitedReasons()); + d.setIfSmaller(6d, "Set 6d", this); + Assert.assertEquals(5d, d.value()); + Assert.assertEquals("ConstraintTest: Set 5d\nConstraintTest: Set 6d", d.getReasons()); + Assert.assertEquals("ConstraintTest: Set 5d", d.getMostLimitedReasons()); + d.setIfSmaller(4d, "Set 4d", this); + Assert.assertEquals(4d, d.value()); + Assert.assertEquals("ConstraintTest: Set 5d\nConstraintTest: Set 6d\nConstraintTest: Set 4d", d.getReasons()); + Assert.assertEquals("ConstraintTest: Set 4d", d.getMostLimitedReasons()); + Assert.assertEquals(10d, d.originalValue()); + } +} diff --git a/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.java b/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.java new file mode 100644 index 0000000000..46b8bb7a53 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.java @@ -0,0 +1,280 @@ +package info.nightscout.androidaps.interfaces; + +import android.content.Context; + +import com.squareup.otto.Bus; + +import junit.framework.Assert; + +import org.json.JSONException; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.util.ArrayList; +import java.util.Date; + +import info.AAPSMocker; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.ConstraintChecker; +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.OpenAPSAMA.OpenAPSAMAPlugin; +import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin; +import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin; +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.InsightPlugin; +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; + +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, Context.class, OpenAPSMAPlugin.class, OpenAPSAMAPlugin.class, OpenAPSSMBPlugin.class}) +public class ConstraintsCheckerTest { + + VirtualPumpPlugin pump = new VirtualPumpPlugin(); + ConstraintChecker constraintChecker; + + SafetyPlugin safetyPlugin; + ObjectivesPlugin objectivesPlugin; + ComboPlugin comboPlugin; + DanaRPlugin danaRPlugin; + DanaRSPlugin danaRSPlugin; + InsightPlugin insightPlugin; + + boolean notificationSent = false; + + public ConstraintsCheckerTest() throws JSONException { + } + + @Test + public void isLoopInvokationAllowedTest() throws Exception { + comboPlugin.setPluginEnabled(PluginBase.PUMP, true); + comboPlugin.setValidBasalRateProfileSelectedOnPump(false); + + Constraint c = constraintChecker.isLoopInvokationAllowed(); + Assert.assertEquals(true, c.getReasonList().size() == 2); // Combo & Objectives + Assert.assertEquals(true, c.getMostLimitedReasonList().size() == 2); // Combo & Objectives + Assert.assertEquals(Boolean.FALSE, c.value()); + } + + @Test + public void isClosedLoopAllowedTest() throws Exception { + when(SP.getString("aps_mode", "open")).thenReturn("closed"); + objectivesPlugin.objectives.get(3).setStarted(new Date(0)); + + Constraint c = constraintChecker.isClosedLoopAllowed(); + Assert.assertEquals(true, c.getReasonList().size() == 2); // Safety & Objectives + Assert.assertEquals(true, c.getMostLimitedReasonList().size() == 2); // Safety & Objectives + Assert.assertEquals(Boolean.FALSE, c.value()); + + when(SP.getString("aps_mode", "open")).thenReturn("open"); + c = constraintChecker.isClosedLoopAllowed(); + Assert.assertEquals(true, c.getReasonList().size() == 3); // 2x Safety & Objectives + Assert.assertEquals(true, c.getMostLimitedReasonList().size() == 3); // 2x Safety & Objectives + Assert.assertEquals(Boolean.FALSE, c.value()); + } + + @Test + public void isAutosensModeEnabledTest() throws Exception { + objectivesPlugin.objectives.get(5).setStarted(new Date(0)); + when(SP.getBoolean(R.string.key_openapsama_useautosens, false)).thenReturn(false); + + Constraint c = constraintChecker.isAutosensModeEnabled(); + Assert.assertEquals(true, c.getReasonList().size() == 2); // Safety & Objectives + Assert.assertEquals(true, c.getMostLimitedReasonList().size() == 2); // Safety & Objectives + Assert.assertEquals(Boolean.FALSE, c.value()); + } + + @Test + public void isAMAModeEnabledTest() throws Exception { + objectivesPlugin.objectives.get(6).setStarted(new Date(0)); + + Constraint c = constraintChecker.isAMAModeEnabled(); + Assert.assertEquals(true, c.getReasonList().size() == 1); // Objectives + Assert.assertEquals(true, c.getMostLimitedReasonList().size() == 1); // Objectives + Assert.assertEquals(Boolean.FALSE, c.value()); + } + + @Test + public void isSMBModeEnabledTest() throws Exception { + objectivesPlugin.objectives.get(7).setStarted(new Date(0)); + when(SP.getBoolean(R.string.key_use_smb, false)).thenReturn(false); + + Constraint c = constraintChecker.isSMBModeEnabled(); + Assert.assertEquals(true, c.getReasonList().size() == 2); // Safety & Objectives + Assert.assertEquals(true, c.getMostLimitedReasonList().size() == 2); // Safety & Objectives + Assert.assertEquals(Boolean.FALSE, c.value()); + } + + // applyBasalConstraints tests + @Test + public void basalRateShouldBeLimited() throws Exception { + // DanaR, RS + danaRPlugin.setPluginEnabled(PluginBase.PUMP, true); + danaRSPlugin.setPluginEnabled(PluginBase.PUMP, true); + DanaRPump.getInstance().maxBasal = 0.8d; + + // Insight + insightPlugin.setPluginEnabled(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); + when(SP.getString(R.string.key_age, "")).thenReturn("child"); + + // Apply all limits + Constraint d = constraintChecker.getMaxBasalAllowed(AAPSMocker.getValidProfile()); + Assert.assertEquals(0.8d, d.value()); + Assert.assertEquals(true, d.getReasonList().size() == 7); // 4x Safety & RS & R & Insight + Assert.assertEquals("DanaR: Limiting basal rate to 0.80 U/h because of pump limit", d.getMostLimitedReasons()); + + } + + @Test + public void percentBasalRateShouldBeLimited() throws Exception { + // DanaR, RS + danaRPlugin.setPluginEnabled(PluginBase.PUMP, true); + danaRSPlugin.setPluginEnabled(PluginBase.PUMP, true); + DanaRPump.getInstance().maxBasal = 0.8d; + + // Insight + insightPlugin.setPluginEnabled(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); + when(SP.getString(R.string.key_age, "")).thenReturn("child"); + + // Apply all limits + Constraint i = constraintChecker.getMaxBasalPercentAllowed(AAPSMocker.getValidProfile()); + Assert.assertEquals((Integer) 100, i.value()); + Assert.assertEquals(true, i.getReasonList().size() == 9); // 6x Safety & RS & R & Insight + Assert.assertEquals("Safety: Limiting percent rate to 100% because of pump limit", i.getMostLimitedReasons()); + + } + + // applyBolusConstraints tests + @Test + public void bolusAmountShouldBeLimited() throws Exception { + // DanaR, RS + danaRPlugin.setPluginEnabled(PluginBase.PUMP, true); + danaRSPlugin.setPluginEnabled(PluginBase.PUMP, true); + DanaRPump.getInstance().maxBolus = 6d; + + // Insight + insightPlugin.setPluginEnabled(PluginBase.PUMP, true); + StatusTaskRunner.Result result = new StatusTaskRunner.Result(); + result.maximumBolusAmount = 7d; + insightPlugin.setStatusResult(result); + + // No limit by default + when(SP.getDouble(R.string.key_treatmentssafety_maxbolus, 3d)).thenReturn(3d); + when(SP.getString(R.string.key_age, "")).thenReturn("child"); + + // Apply all limits + Constraint d = constraintChecker.getMaxBolusAllowed(); + Assert.assertEquals(3d, d.value()); + Assert.assertEquals(true, d.getReasonList().size() == 5); // 2x Safety & RS & R & Insight + Assert.assertEquals("Safety: Limiting bolus to 3.0 U because of max value in preferences", d.getMostLimitedReasons()); + + } + + // applyCarbsConstraints tests + @Test + public void carbsAmountShouldBeLimited() throws Exception { + // No limit by default + when(SP.getInt(R.string.key_treatmentssafety_maxcarbs, 48)).thenReturn(48); + + // Apply all limits + Constraint i = constraintChecker.getMaxCarbsAllowed(); + Assert.assertEquals((Integer) 48, i.value()); + Assert.assertEquals(true, i.getReasonList().size() == 1); + Assert.assertEquals("Safety: Limiting carbs to 48 g because of max value in preferences", i.getMostLimitedReasons()); + } + + // applyMaxIOBConstraints tests + @Test + public void iobShouldBeLimited() throws Exception { + // No limit by default + when(SP.getDouble(R.string.key_openapsma_max_iob, 1.5d)).thenReturn(1.5d); + when(SP.getString(R.string.key_age, "")).thenReturn("teenage"); + OpenAPSMAPlugin.getPlugin().setPluginEnabled(PluginBase.APS, true); + OpenAPSAMAPlugin.getPlugin().setPluginEnabled(PluginBase.APS, true); + OpenAPSSMBPlugin.getPlugin().setPluginEnabled(PluginBase.APS, true); + + // Apply all limits + Constraint d = constraintChecker.getMaxIOBAllowed(); + Assert.assertEquals(1.5d, d.value()); + Assert.assertEquals(true, d.getReasonList().size() == 4); + Assert.assertEquals("Safety: Limiting IOB to 1.5 U because of max value in preferences", d.getMostLimitedReasons()); + + } + + @Before + public void prepareMock() throws Exception { + + PowerMockito.mockStatic(FabricPrivacy.class); + + MainApp mainApp = AAPSMocker.mockMainApp(); + AAPSMocker.mockConfigBuilder(); + AAPSMocker.mockApplicationContext(); + AAPSMocker.mockBus(); + AAPSMocker.mockStrings(); + AAPSMocker.mockSP(); + + // RS constructor + when(SP.getString(R.string.key_danars_address, "")).thenReturn(""); + + //SafetyPlugin + when(MainApp.getConfigBuilder().getActivePump()).thenReturn(pump); + + constraintChecker = new ConstraintChecker(mainApp); + + safetyPlugin = SafetyPlugin.getPlugin(); + objectivesPlugin = ObjectivesPlugin.getPlugin(); + comboPlugin = ComboPlugin.getPlugin(); + danaRPlugin = DanaRPlugin.getPlugin(); + danaRSPlugin = DanaRSPlugin.getPlugin(); + insightPlugin = InsightPlugin.getPlugin(); + ArrayList 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); + + } + + class MockedBus extends Bus { + @Override + public void post(Object event) { + notificationSent = true; + } + } + +} diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPluginTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPluginTest.java new file mode 100644 index 0000000000..116fd3fee6 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPluginTest.java @@ -0,0 +1,90 @@ +package info.nightscout.androidaps.plugins.ConstraintsObjectives; + +import junit.framework.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 java.util.Date; + +import info.AAPSMocker; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.interfaces.Constraint; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.utils.SP; + +/** + * Created by mike on 23.03.2018. + */ + +@RunWith(PowerMockRunner.class) +@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, SP.class}) +public class ObjectivesPluginTest { + + ObjectivesPlugin objectivesPlugin; + + @Test + public void notStartedObjectivesShouldLimitLoopInvokation() throws Exception { + objectivesPlugin.objectives.get(0).setStarted(new Date(0)); + + Constraint c = new Constraint<>(true); + c = objectivesPlugin.isLoopInvokationAllowed(c); + Assert.assertEquals("Objectives: Objective 1 not started", c.getReasons()); + Assert.assertEquals(Boolean.FALSE, c.value()); + objectivesPlugin.objectives.get(0).setStarted(new Date()); + } + + @Test + public void notStartedObjective4ShouldLimitClosedLoop() throws Exception { + objectivesPlugin.objectives.get(3).setStarted(new Date(0)); + + Constraint c = new Constraint<>(true); + c = objectivesPlugin.isClosedLoopAllowed(c); + Assert.assertEquals(true, c.getReasons().contains("Objective 4 not started")); + Assert.assertEquals(Boolean.FALSE, c.value()); + } + + @Test + public void notStartedObjective6ShouldLimitAutosensMode() throws Exception { + objectivesPlugin.objectives.get(5).setStarted(new Date(0)); + + Constraint c = new Constraint<>(true); + c = objectivesPlugin.isAutosensModeEnabled(c); + Assert.assertEquals(true, c.getReasons().contains("Objective 6 not started")); + Assert.assertEquals(Boolean.FALSE, c.value()); + } + + @Test + public void notStartedObjective7ShouldLimitAMAMode() throws Exception { + objectivesPlugin.objectives.get(6).setStarted(new Date(0)); + + Constraint c = new Constraint<>(true); + c = objectivesPlugin.isAMAModeEnabled(c); + Assert.assertEquals(true, c.getReasons().contains("Objective 7 not started")); + Assert.assertEquals(Boolean.FALSE, c.value()); + } + + @Test + public void notStartedObjective8ShouldLimitSMBMode() throws Exception { + objectivesPlugin.objectives.get(7).setStarted(new Date(0)); + + Constraint c = new Constraint<>(true); + c = objectivesPlugin.isSMBModeEnabled(c); + Assert.assertEquals(true, c.getReasons().contains("Objective 8 not started")); + Assert.assertEquals(Boolean.FALSE, c.value()); + } + + @Before + public void prepareMock() { + AAPSMocker.mockMainApp(); + AAPSMocker.mockConfigBuilder(); + AAPSMocker.mockBus(); + AAPSMocker.mockSP(); + AAPSMocker.mockStrings(); + + objectivesPlugin = ObjectivesPlugin.getPlugin(); + } +} diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPluginTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPluginTest.java new file mode 100644 index 0000000000..4b45734b2a --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPluginTest.java @@ -0,0 +1,214 @@ +package info.nightscout.androidaps.plugins.ConstraintsSafety; + +import android.content.Context; + +import junit.framework.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.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.interfaces.Constraint; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; +import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin; +import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin; +import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; +import info.nightscout.utils.SP; + +import static org.mockito.Mockito.when; + +/** + * Created by mike on 23.03.2018. + */ + +@RunWith(PowerMockRunner.class) +@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, SP.class, Context.class}) +public class SafetyPluginTest { + + VirtualPumpPlugin pump = new VirtualPumpPlugin(); + SafetyPlugin safetyPlugin; + + @Test + public void pumpDescriptionShouldLimitLoopInvokation() throws Exception { + pump.getPumpDescription().isTempBasalCapable = false; + + Constraint c = new Constraint<>(true); + c = safetyPlugin.isLoopInvokationAllowed(c); + Assert.assertEquals("Safety: Pump is not temp basal capable", c.getReasons()); + Assert.assertEquals(Boolean.FALSE, c.value()); + } + + @Test + public void disabledEngineeringModeShouldLimitClosedLoop() throws Exception { + when(SP.getString("aps_mode", "open")).thenReturn("closed"); + when(MainApp.isEngineeringModeOrRelease()).thenReturn(false); + + Constraint c = new Constraint<>(true); + c = safetyPlugin.isClosedLoopAllowed(c); + Assert.assertEquals(true, c.getReasons().contains("Running dev version. Closed loop is disabled.")); + Assert.assertEquals(Boolean.FALSE, c.value()); + } + + @Test + public void setOpenLoopInPreferencesShouldLimitClosedLoop() throws Exception { + when(SP.getString("aps_mode", "open")).thenReturn("open"); + + Constraint c = new Constraint<>(true); + c = safetyPlugin.isClosedLoopAllowed(c); + Assert.assertEquals(true, c.getReasons().contains("Closed loop mode disabled in preferences")); + Assert.assertEquals(Boolean.FALSE, c.value()); + } + + @Test + public void notEnabledSMBInPreferencesDisablesSMB() throws Exception { + when(SP.getBoolean(R.string.key_use_smb, false)).thenReturn(false); + + Constraint c = new Constraint<>(true); + c = safetyPlugin.isSMBModeEnabled(c); + Assert.assertEquals(true, c.getReasons().contains("SMB disabled in preferences")); + Assert.assertEquals(Boolean.FALSE, c.value()); + } + + @Test + public void basalRateShouldBeLimited() throws Exception { + 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); + when(SP.getString(R.string.key_age, "")).thenReturn("child"); + + Constraint c = new Constraint<>(Constants.REALLYHIGHBASALRATE); + safetyPlugin.applyBasalConstraints(c, AAPSMocker.getValidProfile()); + Assert.assertEquals(1d, c.value()); + 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", c.getReasons()); + Assert.assertEquals("Safety: Limiting basal rate to 1.00 U/h because of max value in preferences", c.getMostLimitedReasons()); + + } + + @Test + public void doNotAllowNegativeBasalRate() throws Exception { + when(SP.getString(R.string.key_age, "")).thenReturn("child"); + + Constraint d = new Constraint<>(-0.5d); + safetyPlugin.applyBasalConstraints(d, AAPSMocker.getValidProfile()); + Assert.assertEquals(0d, d.value()); + Assert.assertEquals("Safety: Limiting basal rate to 0.00 U/h because of it must be positive value", d.getReasons()); + } + + @Test + public void percentBasalRateShouldBeLimited() throws Exception { + // 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); + when(SP.getString(R.string.key_age, "")).thenReturn("child"); + + + Constraint i = new Constraint<>(Constants.REALLYHIGHPERCENTBASALRATE); + safetyPlugin.applyBasalPercentConstraints(i, AAPSMocker.getValidProfile()); + Assert.assertEquals((Integer) 100, i.value()); + Assert.assertEquals("Safety: Percent rate 1111111% recalculated to 11111.11 U/h with current basal 1.00 U/h\n" + + "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 percent rate to 100% because of pump limit", i.getReasons()); + Assert.assertEquals("Safety: Limiting percent rate to 100% because of pump limit", i.getMostLimitedReasons()); + } + + @Test + public void doNotAllowNegativePercentBasalRate() throws Exception { + when(SP.getString(R.string.key_age, "")).thenReturn("child"); + + Constraint i = new Constraint<>(-22); + safetyPlugin.applyBasalPercentConstraints(i, AAPSMocker.getValidProfile()); + Assert.assertEquals((Integer) 0, i.value()); + Assert.assertEquals("Safety: Percent rate -22% recalculated to -0.22 U/h with current basal 1.00 U/h\n" + + "Safety: Limiting basal rate to 0.00 U/h because of it must be positive value\n" + + "Safety: Limiting percent rate to 0% because of pump limit", i.getReasons()); + Assert.assertEquals("Safety: Limiting percent rate to 0% because of pump limit", i.getMostLimitedReasons()); + } + + @Test + public void bolusAmountShouldBeLimited() throws Exception { + when(SP.getDouble(R.string.key_treatmentssafety_maxbolus, 3d)).thenReturn(3d); + when(SP.getString(R.string.key_age, "")).thenReturn("child"); + + Constraint d = new Constraint<>(Constants.REALLYHIGHBOLUS); + d = safetyPlugin.applyBolusConstraints(d); + Assert.assertEquals(3d, d.value()); + Assert.assertEquals("Safety: Limiting bolus to 3.0 U because of max value in preferences\n" + + "Safety: Limiting bolus to 5.0 U because of hard limit", d.getReasons()); + Assert.assertEquals("Safety: Limiting bolus to 3.0 U because of max value in preferences", d.getMostLimitedReasons()); + } + + @Test + public void doNotAllowNegativeBolusAmount() throws Exception { + when(SP.getDouble(R.string.key_treatmentssafety_maxbolus, 3d)).thenReturn(3d); + when(SP.getString(R.string.key_age, "")).thenReturn("child"); + + Constraint d = new Constraint<>(-22d); + d = safetyPlugin.applyBolusConstraints(d); + Assert.assertEquals(0d, d.value()); + Assert.assertEquals("Safety: Limiting bolus to 0.0 U because of it must be positive value", d.getReasons()); + Assert.assertEquals("Safety: Limiting bolus to 0.0 U because of it must be positive value", d.getMostLimitedReasons()); + } + + @Test + public void carbsAmountShouldBeLimited() throws Exception { + // No limit by default + when(SP.getInt(R.string.key_treatmentssafety_maxcarbs, 48)).thenReturn(48); + + // Negative carbs not allowed + Constraint i = new Constraint<>(-22); + safetyPlugin.applyCarbsConstraints(i); + Assert.assertEquals((Integer) 0, i.value()); + Assert.assertEquals("Safety: Limiting carbs to 0 g because of it must be positive value", i.getReasons()); + + // Apply all limits + i = safetyPlugin.applyCarbsConstraints(new Constraint<>(Constants.REALLYHIGHCARBS)); + Assert.assertEquals((Integer) 48, i.value()); + Assert.assertEquals("Safety: Limiting carbs to 48 g because of max value in preferences", i.getReasons()); + } + + @Test + public void iobShouldBeLimited() throws Exception { + when(SP.getDouble(R.string.key_openapsma_max_iob, 1.5d)).thenReturn(1.5d); + when(SP.getString(R.string.key_age, "")).thenReturn("teenage"); + OpenAPSMAPlugin.getPlugin().setPluginEnabled(PluginBase.APS, true); + OpenAPSAMAPlugin.getPlugin().setPluginEnabled(PluginBase.APS, true); + OpenAPSSMBPlugin.getPlugin().setPluginEnabled(PluginBase.APS, true); + + // Apply all limits + Constraint d = new Constraint<>(Constants.REALLYHIGHIOB); + d = safetyPlugin.applyMaxIOBConstraints(d); + Assert.assertEquals(1.5d, d.value()); + Assert.assertEquals("Safety: Limiting IOB to 1.5 U because of max value in preferences\n" + + "Safety: Limiting IOB to 7.0 U because of hard limit\n" + + "Safety: Limiting IOB to 7.0 U because of hard limit\n" + + "Safety: Limiting IOB to 12.0 U because of hard limit", d.getReasons()); + Assert.assertEquals("Safety: Limiting IOB to 1.5 U because of max value in preferences", d.getMostLimitedReasons()); + } + + @Before + public void prepareMock() { + AAPSMocker.mockMainApp(); + AAPSMocker.mockConfigBuilder(); + AAPSMocker.mockSP(); + AAPSMocker.mockStrings(); + + when(MainApp.getConfigBuilder().getActivePump()).thenReturn(pump); + + safetyPlugin = SafetyPlugin.getPlugin(); + } +} diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePluginTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePluginTest.java index 83e9442364..7dd40883fa 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePluginTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePluginTest.java @@ -137,7 +137,7 @@ public class InsulinOrefBasePluginTest extends InsulinOrefBasePlugin { } @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { + public void setPluginEnabled(int type, boolean fragmentEnabled) { } diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/Loop/LoopPluginTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/Loop/LoopPluginTest.java new file mode 100644 index 0000000000..d533782f13 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/plugins/Loop/LoopPluginTest.java @@ -0,0 +1,110 @@ +package info.nightscout.androidaps.plugins.Loop; + +import android.content.Context; + +import com.squareup.otto.Bus; + +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.R; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.events.EventTreatmentChange; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; +import info.nightscout.utils.SP; + +import static org.powermock.api.mockito.PowerMockito.when; + +/** + * Created by mike on 23.03.2018. + */ + +@RunWith(PowerMockRunner.class) +@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, SP.class, Context.class}) +public class LoopPluginTest { + + VirtualPumpPlugin virtualPumpPlugin; + LoopPlugin loopPlugin; + MockedBus bus; + + @Test + public void testPluginInterface() { + Assert.assertEquals(LoopFragment.class.getName(), loopPlugin.getFragmentClass()); + Assert.assertEquals(PluginBase.LOOP, loopPlugin.getType()); + Assert.assertEquals("Loop", loopPlugin.getName()); + Assert.assertEquals("LOOP", loopPlugin.getNameShort()); + Assert.assertEquals(true, loopPlugin.canBeHidden(PluginBase.LOOP)); + Assert.assertEquals(true, loopPlugin.hasFragment()); + Assert.assertEquals(true, loopPlugin.showInList(PluginBase.LOOP)); + Assert.assertEquals(R.xml.pref_closedmode, loopPlugin.getPreferencesId()); + + // Plugin is disabled by default + Assert.assertEquals(false, loopPlugin.isEnabled(PluginBase.LOOP)); + loopPlugin.setPluginEnabled(PluginBase.LOOP, true); + Assert.assertEquals(true, loopPlugin.isEnabled(PluginBase.LOOP)); + + // No temp basal capable pump should disable plugin + virtualPumpPlugin.getPumpDescription().isTempBasalCapable = false; + Assert.assertEquals(false, loopPlugin.isEnabled(PluginBase.LOOP)); + virtualPumpPlugin.getPumpDescription().isTempBasalCapable = true; + + + // Fragment is hidden by default + Assert.assertEquals(false, loopPlugin.isVisibleInTabs(PluginBase.LOOP)); + loopPlugin.setFragmentVisible(PluginBase.LOOP, true); + Assert.assertEquals(true, loopPlugin.isVisibleInTabs(PluginBase.LOOP)); + + } + +/* *********** not working + @Test + public void eventTreatmentChangeShouldTriggerInvoke() { + + // Unregister tested plugin to prevent calling real invoke + MainApp.bus().unregister(loopPlugin); + + class MockedLoopPlugin extends LoopPlugin { + boolean invokeCalled = false; + + @Override + public void invoke(String initiator, boolean allowNotification) { + invokeCalled = true; + } + + } + + MockedLoopPlugin mockedLoopPlugin = new MockedLoopPlugin(); + Treatment t = new Treatment(); + bus.post(new EventTreatmentChange(t)); + Assert.assertEquals(true, mockedLoopPlugin.invokeCalled); + } +*/ + @Before + public void prepareMock() { + AAPSMocker.mockMainApp(); + AAPSMocker.mockConfigBuilder(); + AAPSMocker.mockSP(); + AAPSMocker.mockStrings(); + + bus = new MockedBus(); + when(MainApp.bus()).thenReturn(bus); + + loopPlugin = LoopPlugin.getPlugin(); + virtualPumpPlugin = VirtualPumpPlugin.getPlugin(); + + when(ConfigBuilderPlugin.getActivePump()).thenReturn(virtualPumpPlugin); + } + + class MockedBus extends Bus { + } + + +} diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPluginTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPluginTest.java index a87cbbfbd4..2e856029f9 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPluginTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPluginTest.java @@ -2,62 +2,68 @@ package info.nightscout.androidaps.plugins.PumpCombo; import android.content.Context; -import com.squareup.otto.Bus; -import com.squareup.otto.ThreadEnforcer; - import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; 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.interfaces.Constraint; +import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Bolus; import info.nightscout.utils.ToastUtils; import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; @RunWith(PowerMockRunner.class) -@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, ConfigBuilderPlugin.class, ToastUtils.class, Context.class}) +@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, ToastUtils.class, Context.class}) public class ComboPluginTest { - @Before - public void prepareMocks() throws Exception { - ConfigBuilderPlugin configBuilderPlugin = mock(ConfigBuilderPlugin.class); - PowerMockito.mockStatic(ConfigBuilderPlugin.class); + ComboPlugin comboPlugin; - PowerMockito.mockStatic(MainApp.class); - MainApp mainApp = mock(MainApp.class); - when(MainApp.getConfigBuilder()).thenReturn(configBuilderPlugin); - when(MainApp.instance()).thenReturn(mainApp); - Bus bus = new Bus(ThreadEnforcer.ANY); - when(MainApp.bus()).thenReturn(bus); - when(MainApp.gs(0)).thenReturn(""); + @Test + public void invalidBasalRateOnComboPumpShouldLimitLoopInvokation() throws Exception { + comboPlugin.setPluginEnabled(PluginBase.PUMP, true); + comboPlugin.setValidBasalRateProfileSelectedOnPump(false); + + Constraint c = new Constraint<>(true); + c = comboPlugin.isLoopInvokationAllowed(c); + Assert.assertEquals("Combo: No valid basal rate read from pump", c.getReasons()); + Assert.assertEquals(Boolean.FALSE, c.value()); + comboPlugin.setPluginEnabled(PluginBase.PUMP, false); } @Test public void calculateFakePumpTimestamp() throws Exception { - ComboPlugin plugin = ComboPlugin.getPlugin(); long now = System.currentTimeMillis(); long pumpTimestamp = now - now % 1000; // same timestamp, different bolus leads to different fake timestamp Assert.assertNotEquals( - plugin.calculateFakeBolusDate(new Bolus(pumpTimestamp, 0.1, true)), - plugin.calculateFakeBolusDate(new Bolus(pumpTimestamp, 0.3, true)) + comboPlugin.calculateFakeBolusDate(new Bolus(pumpTimestamp, 0.1, true)), + comboPlugin.calculateFakeBolusDate(new Bolus(pumpTimestamp, 0.3, true)) ); // different timestamp, same bolus leads to different fake timestamp Assert.assertNotEquals( - plugin.calculateFakeBolusDate(new Bolus(pumpTimestamp, 0.3, true)), - plugin.calculateFakeBolusDate(new Bolus(pumpTimestamp + 60 * 1000, 0.3, true)) + comboPlugin.calculateFakeBolusDate(new Bolus(pumpTimestamp, 0.3, true)), + comboPlugin.calculateFakeBolusDate(new Bolus(pumpTimestamp + 60 * 1000, 0.3, true)) ); // generated timestamp has second-precision Bolus bolus = new Bolus(pumpTimestamp, 0.2, true); - long calculatedTimestamp = plugin.calculateFakeBolusDate(bolus); + long calculatedTimestamp = comboPlugin.calculateFakeBolusDate(bolus); assertEquals(calculatedTimestamp, calculatedTimestamp - calculatedTimestamp % 1000); } + + @Before + public void prepareMocks() throws Exception { + AAPSMocker.mockMainApp(); + AAPSMocker.mockConfigBuilder(); + AAPSMocker.mockBus(); + AAPSMocker.mockStrings(); + + comboPlugin = ComboPlugin.getPlugin(); + } } \ No newline at end of file diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPluginTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPluginTest.java new file mode 100644 index 0000000000..1b88e7d025 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPluginTest.java @@ -0,0 +1,75 @@ +package info.nightscout.androidaps.plugins.PumpDanaRS; + +import android.content.Context; + +import junit.framework.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.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.interfaces.Constraint; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.utils.SP; +import info.nightscout.utils.ToastUtils; + +import static org.mockito.Mockito.when; + +/** + * Created by mike on 23.03.2018. + */ + +@RunWith(PowerMockRunner.class) +@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, ToastUtils.class, Context.class, SP.class}) +public class DanaRSPluginTest { + + DanaRSPlugin danaRSPlugin; + + @Test + public void basalRateShouldBeLimited() throws Exception { + danaRSPlugin.setPluginEnabled(PluginBase.PUMP, true); + danaRSPlugin.setPluginEnabled(PluginBase.PUMP, true); + DanaRPump.getInstance().maxBasal = 0.8d; + + Constraint c = new Constraint<>(Constants.REALLYHIGHBASALRATE); + danaRSPlugin.applyBasalConstraints(c, AAPSMocker.getValidProfile()); + Assert.assertEquals(0.8d, c.value()); + Assert.assertEquals("DanaRS: Limiting basal rate to 0.80 U/h because of pump limit", c.getReasons()); + Assert.assertEquals("DanaRS: Limiting basal rate to 0.80 U/h because of pump limit", c.getMostLimitedReasons()); + } + + @Test + public void percentBasalRateShouldBeLimited() throws Exception { + danaRSPlugin.setPluginEnabled(PluginBase.PUMP, true); + danaRSPlugin.setPluginEnabled(PluginBase.PUMP, true); + DanaRPump.getInstance().maxBasal = 0.8d; + + Constraint c = new Constraint<>(Constants.REALLYHIGHPERCENTBASALRATE); + danaRSPlugin.applyBasalPercentConstraints(c, AAPSMocker.getValidProfile()); + Assert.assertEquals((Integer) 200, c.value()); + Assert.assertEquals("DanaRS: Limiting percent rate to 200% because of pump limit", c.getReasons()); + Assert.assertEquals("DanaRS: Limiting percent rate to 200% because of pump limit", c.getMostLimitedReasons()); + } + + @Before + public void prepareMocks() throws Exception { + AAPSMocker.mockMainApp(); + AAPSMocker.mockConfigBuilder(); + AAPSMocker.mockBus(); + AAPSMocker.mockStrings(); + AAPSMocker.mockApplicationContext(); + AAPSMocker.mockSP(); + + when(SP.getString(R.string.key_danars_address, "")).thenReturn(""); + + danaRSPlugin = DanaRSPlugin.getPlugin(); + } +} diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPluginTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPluginTest.java new file mode 100644 index 0000000000..a93757af87 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPluginTest.java @@ -0,0 +1,56 @@ +package info.nightscout.androidaps.plugins.PumpInsight; + +import android.content.Context; + +import junit.framework.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.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.interfaces.Constraint; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.PumpInsight.connector.StatusTaskRunner; +import info.nightscout.utils.ToastUtils; + +/** + * Created by mike on 23.03.2018. + */ + +@RunWith(PowerMockRunner.class) +@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, ToastUtils.class, Context.class}) +public class InsightPluginTest { + + InsightPlugin insightPlugin; + + @Test + public void basalRateShouldBeLimited() throws Exception { + insightPlugin.setPluginEnabled(PluginBase.PUMP, true); + StatusTaskRunner.Result result = new StatusTaskRunner.Result(); + result.maximumBasalAmount = 1.1d; + insightPlugin.setStatusResult(result); + + Constraint c = new Constraint<>(Constants.REALLYHIGHBASALRATE); + insightPlugin.applyBasalConstraints(c, AAPSMocker.getValidProfile()); + Assert.assertEquals(1.1d, c.value()); + Assert.assertEquals("Insight: Limiting basal rate to 1.10 U/h because of pump limit", c.getReasons()); + Assert.assertEquals("Insight: Limiting basal rate to 1.10 U/h because of pump limit", c.getMostLimitedReasons()); + } + + @Before + public void prepareMocks() throws Exception { + AAPSMocker.mockMainApp(); + AAPSMocker.mockConfigBuilder(); + AAPSMocker.mockBus(); + AAPSMocker.mockStrings(); + + insightPlugin = InsightPlugin.getPlugin(); + } + +} diff --git a/app/src/test/java/info/nightscout/androidaps/queue/CommandQueueTest.java b/app/src/test/java/info/nightscout/androidaps/queue/CommandQueueTest.java index 8f9cd75f51..9f89fe1ec0 100644 --- a/app/src/test/java/info/nightscout/androidaps/queue/CommandQueueTest.java +++ b/app/src/test/java/info/nightscout/androidaps/queue/CommandQueueTest.java @@ -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; @@ -16,14 +17,17 @@ import org.powermock.modules.junit4.PowerMockRunner; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.data.ConstraintChecker; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin; import info.nightscout.androidaps.queue.commands.Command; import info.nightscout.utils.ToastUtils; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -35,7 +39,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 { @@ -61,11 +69,11 @@ 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 - tempBasalPercent(0, 30, true, null); + tempBasalPercent(0, 30, true, profile, null); Assert.assertEquals(1, size()); // add extended bolus @@ -82,7 +90,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 @@ -94,7 +102,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); @@ -105,8 +113,7 @@ public class CommandQueueTest extends CommandQueue { private void prepareMock(Double insulin, Integer carbs) throws Exception { ConfigBuilderPlugin configBuilderPlugin = mock(ConfigBuilderPlugin.class); - when(configBuilderPlugin.applyBolusConstraints(insulin)).thenReturn(insulin); - when(configBuilderPlugin.applyCarbsConstraints(carbs)).thenReturn(carbs); + ConstraintChecker constraintChecker = mock(ConstraintChecker.class); PowerMockito.mockStatic(ConfigBuilderPlugin.class); PumpInterface pump = MDIPlugin.getPlugin(); @@ -115,8 +122,17 @@ public class CommandQueueTest extends CommandQueue { PowerMockito.mockStatic(MainApp.class); MainApp mainApp = mock(MainApp.class); when(MainApp.getConfigBuilder()).thenReturn(configBuilderPlugin); + when(MainApp.getConstraintChecker()).thenReturn(constraintChecker); when(MainApp.isEngineeringModeOrRelease()).thenReturn(true); when(MainApp.instance()).thenReturn(mainApp); + Constraint bolusConstraint = new Constraint<>(0d); + when(MainApp.getConstraintChecker().applyBolusConstraints(any())).thenReturn(bolusConstraint); + Constraint carbsConstraint = new Constraint<>(0); + when(MainApp.getConstraintChecker().applyCarbsConstraints(any())).thenReturn(carbsConstraint); + Constraint rateConstraint = new Constraint<>(0d); + when(MainApp.getConstraintChecker().applyBasalConstraints(any(), any())).thenReturn(rateConstraint); + Constraint percentageConstraint = new Constraint<>(0); + when(MainApp.getConstraintChecker().applyBasalPercentConstraints(any(), any())).thenReturn(percentageConstraint); PowerMockito.mockStatic(ToastUtils.class); Context context = mock(Context.class); diff --git a/app/src/test/java/info/nightscout/utils/TimeListEditTest.java b/app/src/test/java/info/nightscout/utils/TimeListEditTest.java deleted file mode 100644 index 8fd387eebd..0000000000 --- a/app/src/test/java/info/nightscout/utils/TimeListEditTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package info.nightscout.utils; - -import android.content.Context; -import android.view.LayoutInflater; - -import org.json.JSONArray; -import org.junit.Test; -import org.mockito.Mock; - -import java.lang.reflect.Method; -import java.text.DecimalFormat; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.when; - -/** - * Created by mike on 30.12.2016. - */ -public class TimeListEditTest { - - /* - JSONArray data = new JSONArray(); - JSONArray data2 = new JSONArray(); - TimeListEdit tle = new TimeListEdit(null, null, 0, "Test1", data, "ic", null, new DecimalFormat("0.00")); - TimeListEdit tle2 = new TimeListEdit(null, null, 0, "Test2", data2, "ic", "ic2", new DecimalFormat("0.00")); - - - @Test - public void doArrayTest() throws Exception { - tle.addItem(0, 0, 0.1, 0); - tle.addItem(1, 60 * 60, 0.2, 0); - assertEquals(2, tle.itemsCount()); - - tle.editItem(0, 2 * 60 * 60, 1, 0); - assertEquals(2, tle.itemsCount()); - assertEquals(1d, tle.value1(0), 0.00001d); - assertEquals( 2 * 60 * 60, tle.secondFromMidnight(0)); - tle.removeItem(0); - assertEquals(0.2d, tle.value1(0), 0.00001d); - assertEquals(0, tle.value2(0), 0.00001d); - assertEquals(60 * 60, tle.secondFromMidnight(0)); - - //System.out.print(tle2.toString()); - assertEquals(0, tle2.itemsCount()); - tle2.addItem(0, 0, 1, 2); - assertEquals(1, tle2.itemsCount()); - assertEquals(0, tle2.secondFromMidnight(0)); - assertEquals(1d, tle2.value1(0), 0.00001d); - assertEquals(2d, tle2.value2(0), 0.00001d); - } - - */ - @Test - public void fakeTest() throws Exception { - } - -} \ No newline at end of file