Merge pull request #2610 from Tornado-Tim/LGS

Add an explicit Low Glucose Suspend mode
This commit is contained in:
Milos Kozak 2020-05-02 12:19:11 +02:00 committed by GitHub
commit 9428717876
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 55 additions and 5 deletions

View file

@ -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> 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<Boolean> 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;

View file

@ -98,7 +98,7 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
@NonNull @Override
public Constraint<Boolean> isClosedLoopAllowed(@NonNull Constraint<Boolean> 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<Double> applyMaxIOBConstraints(@NonNull Constraint<Double> 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;
}

View file

@ -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))
}

View file

@ -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

View file

@ -4,10 +4,12 @@
<string-array name="aps_modeArray">
<item>@string/closedloop</item>
<item>@string/openloop</item>
<item>@string/lowglucosesuspend</item>
</string-array>
<string-array name="aps_modeValues" translatable="false">
<item>closed</item>
<item>open</item>
<item>lgs</item>
</string-array>
<string-array name="unitsArray">

View file

@ -86,6 +86,7 @@
<color name="ribbonCritical">#ff0400</color>
<color name="ribbonTextDefault">#FFFFFF</color>
<color name="ribbonTextWarning">#303030</color>
<color name="ribbonUnusual">#01017A</color>
<color name="ribbonTextCritical">#FFFFFF</color>
<color name="splashBackground">#2E2E2E</color>

View file

@ -187,10 +187,12 @@
<string name="closedloop">Closed Loop</string>
<string name="openloop">Open Loop</string>
<string name="lowglucosesuspend">Low Glucose Suspend</string>
<string name="disabledloop">Loop Disabled</string>
<string name="disableloop">Disable loop</string>
<string name="enableloop">Enable loop</string>
<string name="lgs">LGS</string>
<string name="openloop_newsuggestion">New suggestion available</string>
<string name="unsupportednsversion">Unsupported version of Nightscout</string>
<string name="loopdisabled">LOOP DISABLED BY CONSTRAINTS</string>

View file

@ -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)

View file

@ -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)

View file

@ -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")