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..471b7735cf 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java @@ -1,13 +1,13 @@ package info.nightscout.androidaps.interfaces; -import info.nightscout.androidaps.plugins.Loop.APSResult; +import info.nightscout.androidaps.interfaces.constrains.BooleanConstraint; /** * Created by mike on 15.06.2016. */ public interface ConstraintsInterface { - boolean isLoopEnabled(); + void limitRunningLoop(BooleanConstraint value); boolean isClosedModeEnabled(); diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/constrains/BooleanConstraint.java b/app/src/main/java/info/nightscout/androidaps/interfaces/constrains/BooleanConstraint.java new file mode 100644 index 0000000000..eda25b9d68 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/constrains/BooleanConstraint.java @@ -0,0 +1,29 @@ +package info.nightscout.androidaps.interfaces.constrains; + +/** + * Created by mike on 19.03.2018. + */ + +public class BooleanConstraint extends Constraint { + boolean value; + + public BooleanConstraint(boolean value) { + this.value = value; + } + + public boolean get() { + return value; + } + + public BooleanConstraint set(boolean value) { + this.value = value; + return this; + } + + public BooleanConstraint set(boolean value, String reason) { + this.value = value; + reason(reason); + return this; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/constrains/Constraint.java b/app/src/main/java/info/nightscout/androidaps/interfaces/constrains/Constraint.java new file mode 100644 index 0000000000..4cc4ef7c79 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/constrains/Constraint.java @@ -0,0 +1,27 @@ +package info.nightscout.androidaps.interfaces.constrains; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by mike on 19.03.2018. + */ + +public class Constraint { + List reasons = new ArrayList<>(); + + public Constraint reason(String reason) { + reasons.add(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); + } + return sb.toString(); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/constrains/DoubleConstraint.java b/app/src/main/java/info/nightscout/androidaps/interfaces/constrains/DoubleConstraint.java new file mode 100644 index 0000000000..211a545219 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/constrains/DoubleConstraint.java @@ -0,0 +1,29 @@ +package info.nightscout.androidaps.interfaces.constrains; + +/** + * Created by mike on 19.03.2018. + */ + +public class DoubleConstraint extends Constraint{ + double value; + + public DoubleConstraint(double value) { + this.value = value; + } + + public Double getDouble() { + return value; + } + + public DoubleConstraint set(double value) { + this.value = value; + return this; + } + + public DoubleConstraint set(double value, String reason) { + this.value = value; + reason(reason); + return this; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/constrains/IntegerConstraint.java b/app/src/main/java/info/nightscout/androidaps/interfaces/constrains/IntegerConstraint.java new file mode 100644 index 0000000000..31d2a76e82 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/constrains/IntegerConstraint.java @@ -0,0 +1,28 @@ +package info.nightscout.androidaps.interfaces.constrains; + +/** + * Created by mike on 19.03.2018. + */ + +public class IntegerConstraint extends Constraint { + int value; + + public IntegerConstraint(int value) { + this.value = value; + } + + public int getInteger() { + return value; + } + + public IntegerConstraint set(int value) { + this.value = value; + return this; + } + + public IntegerConstraint set(int value, String reason) { + this.value = value; + reason(reason); + return this; + } +} 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 e0a8155ffa..3f5283ec48 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 @@ -4,8 +4,6 @@ import android.content.SharedPreferences; import android.preference.PreferenceManager; import android.support.annotation.Nullable; -import org.json.JSONException; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,6 +31,7 @@ import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventAppInitialized; import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.BgSourceInterface; +import info.nightscout.androidaps.interfaces.constrains.BooleanConstraint; import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.PluginBase; @@ -43,7 +42,6 @@ import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; 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.PumpVirtual.VirtualPumpPlugin; import info.nightscout.androidaps.queue.Callback; @@ -451,16 +449,14 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr * Constraints interface **/ @Override - public boolean isLoopEnabled() { - boolean result = true; + public void limitRunningLoop(BooleanConstraint value) { ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); for (PluginBase p : constraintsPlugins) { ConstraintsInterface constrain = (ConstraintsInterface) p; if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue; - result = result && constrain.isLoopEnabled(); + constrain.limitRunningLoop(value); } - return result; } @Override 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..0516cdda51 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,12 @@ 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.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.interfaces.APSInterface; +import info.nightscout.androidaps.interfaces.constrains.BooleanConstraint; import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; @@ -294,8 +294,9 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface { * Constraints interface **/ @Override - public boolean isLoopEnabled() { - return objectives.get(0).started.getTime() > 0; + public void limitRunningLoop(BooleanConstraint value) { + if (objectives.get(0).started.getTime() == 0) + value.set(false, MainApp.gs(R.string.objective1notstarted)); } @Override 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..4062836c48 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 @@ -11,6 +11,7 @@ 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.constrains.BooleanConstraint; import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; @@ -93,8 +94,9 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface { } @Override - public boolean isLoopEnabled() { - return ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; + public void limitRunningLoop(BooleanConstraint value) { + if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable) + value.set(false, MainApp.gs(R.string.pumpisnottempbasalcapable)); } /** 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 5846140b1e..a1ca643adc 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 @@ -23,11 +23,10 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.BgReading; 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.constrains.BooleanConstraint; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; @@ -260,10 +259,13 @@ 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))); + BooleanConstraint loopEnabled = new BooleanConstraint(true); + MainApp.getConfigBuilder().limitRunningLoop(loopEnabled); + + if (!loopEnabled.get()) { + 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(); @@ -297,8 +299,8 @@ 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.rate = MainApp.getConfigBuilder().applyBasalConstraints(resultAfterConstraints.rate); + resultAfterConstraints.smb = MainApp.getConfigBuilder().applyBolusConstraints(resultAfterConstraints.smb); // safety check for multiple SMBs long lastBolusTime = TreatmentsPlugin.getPlugin().getLastBolusTime(); @@ -329,7 +331,7 @@ public class LoopPlugin implements PluginBase { return; } - if (constraintsInterface.isClosedModeEnabled()) { + if (MainApp.getConfigBuilder().isClosedModeEnabled()) { if (result.isChangeRequested()) { final PumpEnactResult waiting = new PumpEnactResult(); waiting.queued = true; 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 ee3a32ad7e..5d60498b32 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; @@ -29,6 +28,7 @@ import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventRefreshOverview; +import info.nightscout.androidaps.interfaces.constrains.BooleanConstraint; import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpDescription; @@ -1407,8 +1407,9 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf private boolean validBasalRateProfileSelectedOnPump = true; @Override - public boolean isLoopEnabled() { - return validBasalRateProfileSelectedOnPump; + public void limitRunningLoop(BooleanConstraint value) { + if (!validBasalRateProfileSelectedOnPump) + value.set(false, MainApp.gs(R.string.novalidbasalrate)); } @Override 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..111919c47d 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 @@ -19,6 +19,7 @@ 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.constrains.BooleanConstraint; import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.DanaRInterface; import info.nightscout.androidaps.interfaces.PluginBase; @@ -436,8 +437,7 @@ public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface, */ @Override - public boolean isLoopEnabled() { - return true; + public void limitRunningLoop(BooleanConstraint value) { } @Override 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..1bc785352d 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 @@ -30,6 +30,7 @@ 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.constrains.BooleanConstraint; import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.DanaRInterface; import info.nightscout.androidaps.interfaces.PluginBase; @@ -274,8 +275,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, // Constraints interface @Override - public boolean isLoopEnabled() { - return true; + public void limitRunningLoop(BooleanConstraint value) { } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPumpPlugin.java index a7c7cb52f4..9889c9723c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPumpPlugin.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.constrains.BooleanConstraint; 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; @@ -1085,8 +1080,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints // Constraints @Override - public boolean isLoopEnabled() { - return true; + public void limitRunningLoop(BooleanConstraint value){ } @Override diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6c1a0b774a..b6c7783ece 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1011,5 +1011,8 @@ ProfileSwitch missing. Please do a profile switch or press \"Activate Profile\" in the LocalProfile. Bolus count TBR count + Objective 1 not started + Pump is not temp basal capable + No valid basal rate read from pump diff --git a/app/src/test/java/info/nightscout/androidaps/interfaces/contraints/BooleanConstraintTest.java b/app/src/test/java/info/nightscout/androidaps/interfaces/contraints/BooleanConstraintTest.java new file mode 100644 index 0000000000..610f3f5519 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/interfaces/contraints/BooleanConstraintTest.java @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.interfaces.contraints; + +import junit.framework.Assert; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.modules.junit4.PowerMockRunner; + +import info.nightscout.androidaps.interfaces.constrains.BooleanConstraint; + +/** + * Created by mike on 19.03.2018. + */ + +@RunWith(PowerMockRunner.class) +public class BooleanConstraintTest { + + @Test + public void doTests() throws Exception { + BooleanConstraint c; + + c = new BooleanConstraint(true); + Assert.assertEquals(true, c.get()); + Assert.assertEquals("", c.getReasons()); + c.set(false); + Assert.assertEquals(false, c.get()); + Assert.assertEquals("", c.getReasons()); + c.set(true, "Set true"); + Assert.assertEquals(true, c.get()); + Assert.assertEquals("Set true", c.getReasons()); + } +} diff --git a/app/src/test/java/info/nightscout/androidaps/interfaces/contraints/DoubleConstraintTest.java b/app/src/test/java/info/nightscout/androidaps/interfaces/contraints/DoubleConstraintTest.java new file mode 100644 index 0000000000..b99376b033 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/interfaces/contraints/DoubleConstraintTest.java @@ -0,0 +1,36 @@ +package info.nightscout.androidaps.interfaces.contraints; + +import junit.framework.Assert; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.modules.junit4.PowerMockRunner; + +import info.nightscout.androidaps.interfaces.constrains.DoubleConstraint; + +/** + * Created by mike on 19.03.2018. + */ + +@RunWith(PowerMockRunner.class) +public class DoubleConstraintTest { + + @Test + public void doTests() throws Exception { + DoubleConstraint c; + + c = new DoubleConstraint(10d); + Assert.assertEquals(10d, c.getDouble()); + Assert.assertEquals("", c.getReasons()); + c.set(11d); + Assert.assertEquals(11d, c.getDouble()); + Assert.assertEquals("", c.getReasons()); + c.set(9d, "Set 9d"); + Assert.assertEquals(9d, c.getDouble()); + Assert.assertEquals("Set 9d", c.getReasons()); + c.set(8d, "Set 8d"); + Assert.assertEquals(8d, c.getDouble()); + Assert.assertEquals("Set 9d\nSet 8d", c.getReasons()); + + } +} diff --git a/app/src/test/java/info/nightscout/androidaps/interfaces/contraints/IntegerConstraintTest.java b/app/src/test/java/info/nightscout/androidaps/interfaces/contraints/IntegerConstraintTest.java new file mode 100644 index 0000000000..910021e305 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/interfaces/contraints/IntegerConstraintTest.java @@ -0,0 +1,34 @@ +package info.nightscout.androidaps.interfaces.contraints; + +import junit.framework.Assert; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.modules.junit4.PowerMockRunner; + +import info.nightscout.androidaps.interfaces.constrains.BooleanConstraint; +import info.nightscout.androidaps.interfaces.constrains.IntegerConstraint; + +/** + * Created by mike on 19.03.2018. + */ + +@RunWith(PowerMockRunner.class) +public class IntegerConstraintTest { + + @Test + public void doTests() throws Exception { + IntegerConstraint c; + + c = new IntegerConstraint(10); + Assert.assertEquals(10, c.getInteger()); + Assert.assertEquals("", c.getReasons()); + c.set(11); + Assert.assertEquals(11, c.getInteger()); + Assert.assertEquals("", c.getReasons()); + c.set(9, "Set 9"); + Assert.assertEquals(9, c.getInteger()); + Assert.assertEquals("Set 9", c.getReasons()); + + } +}