diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java index fefd50f132..93fcef0f0b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java @@ -68,6 +68,7 @@ import info.nightscout.androidaps.utils.FabricPrivacy; import info.nightscout.androidaps.utils.T; import info.nightscout.androidaps.utils.resources.ResourceHelper; import info.nightscout.androidaps.utils.sharedPreferences.SP; +import info.nightscout.androidaps.utils.HardLimits; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.schedulers.Schedulers; @@ -88,6 +89,7 @@ public class LoopPlugin extends PluginBase { private final IobCobCalculatorPlugin iobCobCalculatorPlugin; private final ReceiverStatusStore receiverStatusStore; private final FabricPrivacy fabricPrivacy; + private final HardLimits hardLimits; private CompositeDisposable disposable = new CompositeDisposable(); @@ -132,7 +134,8 @@ public class LoopPlugin extends PluginBase { Lazy actionStringHandler, // TODO Adrian use RxBus instead of Lazy IobCobCalculatorPlugin iobCobCalculatorPlugin, ReceiverStatusStore receiverStatusStore, - FabricPrivacy fabricPrivacy + FabricPrivacy fabricPrivacy, + HardLimits hardLimits ) { super(new PluginDescription() .mainType(PluginType.LOOP) @@ -158,6 +161,7 @@ public class LoopPlugin extends PluginBase { this.iobCobCalculatorPlugin = iobCobCalculatorPlugin; this.receiverStatusStore = receiverStatusStore; this.fabricPrivacy = fabricPrivacy; + this.hardLimits = hardLimits; loopSuspendedTill = sp.getLong("loopSuspendedTill", 0L); isSuperBolus = sp.getBoolean("isSuperBolus", false); @@ -288,6 +292,21 @@ public class LoopPlugin extends PluginBase { return true; } + public boolean isLGS(){ + Constraint closedLoopEnabled = constraintChecker.isClosedLoopAllowed(); + Double MaxIOBallowed = constraintChecker.getMaxIOBAllowed().value(); + String APSmode = sp.getString(R.string.key_aps_mode, "open"); + PumpInterface pump = activePlugin.getActivePump(); + boolean isLGS = false; + + if (!isSuspended() && !pump.isSuspended()) + if (closedLoopEnabled.value()) + if ((MaxIOBallowed.equals(hardLimits.getMAXIOB_LGS())) || (APSmode.equals("lgs"))) + isLGS = true; + + return isLGS; + } + public boolean isSuperBolus() { if (loopSuspendedTill == 0) return false; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.java index a32b7233e1..ab325f1f0c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.java @@ -98,7 +98,7 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface { @NonNull @Override public Constraint isClosedLoopAllowed(@NonNull Constraint value) { String mode = sp.getString(R.string.key_aps_mode, "open"); - if (!mode.equals("closed")) + if ((mode.equals("open"))) value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.closedmodedisabledinpreferences), this); if (!buildHelper.isEngineeringModeOrRelease()) { @@ -266,6 +266,7 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface { @NonNull @Override public Constraint applyMaxIOBConstraints(@NonNull Constraint maxIob) { double maxIobPref; + String apsmode = sp.getString(R.string.key_aps_mode, "open"); if (openAPSSMBPlugin.isEnabled(PluginType.APS)) maxIobPref = sp.getDouble(R.string.key_openapssmb_max_iob, 3d); else @@ -276,6 +277,9 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface { maxIob.setIfSmaller(getAapsLogger(), hardLimits.maxIobAMA(), String.format(getResourceHelper().gs(R.string.limitingiob), hardLimits.maxIobAMA(), getResourceHelper().gs(R.string.hardlimit)), this); if (openAPSSMBPlugin.isEnabled(PluginType.APS)) maxIob.setIfSmaller(getAapsLogger(), hardLimits.maxIobSMB(), String.format(getResourceHelper().gs(R.string.limitingiob), hardLimits.maxIobSMB(), getResourceHelper().gs(R.string.hardlimit)), this); + if ((apsmode.equals("lgs"))) + maxIob.setIfSmaller(getAapsLogger(), hardLimits.getMAXIOB_LGS(), String.format(getResourceHelper().gs(R.string.limitingiob), hardLimits.getMAXIOB_LGS(), getResourceHelper().gs(R.string.lowglucosesuspend)), this); + return maxIob; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt index cc3f881a13..962e443c66 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt @@ -622,8 +622,17 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList } loopPlugin.isEnabled(PluginType.LOOP) -> { - overview_apsmode?.text = if (closedLoopEnabled.value()) resourceHelper.gs(R.string.closedloop) else resourceHelper.gs(R.string.openloop) - overview_apsmode?.setBackgroundColor(resourceHelper.gc(R.color.ribbonDefault)) + val isLGS = loopPlugin.isLGS + overview_apsmode?.text = + if (closedLoopEnabled.value()) + if (isLGS) + resourceHelper.gs(R.string.lgs) + else + resourceHelper.gs(R.string.closedloop) + else + resourceHelper.gs(R.string.openloop) + + overview_apsmode?.setBackgroundColor(if (isLGS) resourceHelper.gc(R.color.ribbonUnusual) else resourceHelper.gc(R.color.ribbonDefault)) overview_apsmode?.setTextColor(resourceHelper.gc(R.color.ribbonTextDefault)) } diff --git a/app/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt b/app/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt index 48eba49112..c9e2835ceb 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt @@ -45,6 +45,10 @@ class HardLimits @Inject constructor( val MAXIOB_SMB = doubleArrayOf(3.0, 7.0, 12.0, 25.0) val MAXBASAL = doubleArrayOf(2.0, 5.0, 10.0, 12.0) + //LGS Hard limits + //No IOB at all + val MAXIOB_LGS = 0.0 + private fun loadAge(): Int { val sp_age = sp.getString(R.string.key_age, "") val age: Int diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 04d78d3406..d11a14eefd 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -4,10 +4,12 @@ @string/closedloop @string/openloop + @string/lowglucosesuspend closed open + lgs diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 8d1b977fea..d30a19a76e 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -86,6 +86,7 @@ #ff0400 #FFFFFF #303030 + #01017A #FFFFFF #2E2E2E diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b0f6821b69..45ed657b64 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -187,10 +187,12 @@ Closed Loop Open Loop + Low Glucose Suspend Loop Disabled Disable loop Enable loop + LGS New suggestion available Unsupported version of Nightscout LOOP DISABLED BY CONSTRAINTS diff --git a/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.kt b/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.kt index cd090dbde4..7698cc6844 100644 --- a/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.kt @@ -310,6 +310,7 @@ class ConstraintsCheckerTest : TestBaseWithProfile() { @Test fun iobAMAShouldBeLimited() { // No limit by default + `when`(sp.getString(R.string.key_aps_mode, "open")).thenReturn("closed") `when`(sp.getDouble(R.string.key_openapsma_max_iob, 1.5)).thenReturn(1.5) `when`(sp.getString(R.string.key_age, "")).thenReturn("teenage") openAPSAMAPlugin.setPluginEnabled(PluginType.APS, true) @@ -325,6 +326,7 @@ class ConstraintsCheckerTest : TestBaseWithProfile() { @Test fun iobSMBShouldBeLimited() { // No limit by default + `when`(sp.getString(R.string.key_aps_mode, "open")).thenReturn("closed") `when`(sp.getDouble(R.string.key_openapssmb_max_iob, 3.0)).thenReturn(3.0) `when`(sp.getString(R.string.key_age, "")).thenReturn("teenage") openAPSSMBPlugin.setPluginEnabled(PluginType.APS, true) diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/aps/loop/LoopPluginTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/aps/loop/LoopPluginTest.kt index dbfa209d11..40495880a3 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/aps/loop/LoopPluginTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/aps/loop/LoopPluginTest.kt @@ -19,6 +19,7 @@ import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.receivers.ReceiverStatusStore import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import org.junit.Assert @@ -49,11 +50,15 @@ class LoopPluginTest : TestBase() { @Mock lateinit var fabricPrivacy: FabricPrivacy @Mock lateinit var receiverStatusStore: ReceiverStatusStore + private lateinit var hardLimits: HardLimits + lateinit var loopPlugin: LoopPlugin val injector = HasAndroidInjector { AndroidInjector { } } @Before fun prepareMock() { - loopPlugin = LoopPlugin(injector, aapsLogger, rxBus, sp, constraintChecker, resourceHelper, profileFunction, context, commandQueue, activePlugin, treatmentsPlugin, virtualPumpPlugin, actionStringHandler, iobCobCalculatorPlugin, receiverStatusStore, fabricPrivacy) + hardLimits = HardLimits(aapsLogger, rxBus, sp, resourceHelper, context) + + loopPlugin = LoopPlugin(injector, aapsLogger, rxBus, sp, constraintChecker, resourceHelper, profileFunction, context, commandQueue, activePlugin, treatmentsPlugin, virtualPumpPlugin, actionStringHandler, iobCobCalculatorPlugin, receiverStatusStore, fabricPrivacy, hardLimits) `when`(activePlugin.getActivePump()).thenReturn(virtualPumpPlugin) } @@ -61,6 +66,7 @@ class LoopPluginTest : TestBase() { fun testPluginInterface() { `when`(resourceHelper.gs(R.string.loop)).thenReturn("Loop") `when`(resourceHelper.gs(R.string.loop_shortname)).thenReturn("LOOP") + `when`(sp.getString(R.string.key_aps_mode, "open")).thenReturn("closed") val pumpDescription = PumpDescription() `when`(virtualPumpPlugin.pumpDescription).thenReturn(pumpDescription) Assert.assertEquals(LoopFragment::class.java.name, loopPlugin.pluginDescription.fragmentClass) diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPluginTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPluginTest.kt index 9da162a301..3e36b8bca0 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPluginTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPluginTest.kt @@ -230,6 +230,7 @@ class SafetyPluginTest : TestBaseWithProfile() { } @Test fun iobShouldBeLimited() { + `when`(sp.getString(R.string.key_aps_mode, "open")).thenReturn("closed") `when`(sp.getDouble(R.string.key_openapsma_max_iob, 1.5)).thenReturn(1.5) `when`(sp.getString(R.string.key_age, "")).thenReturn("teenage")