Reject SMB if bolus is queued/running or outdated. Fixes 1068.

This commit is contained in:
Johannes Mockenhaupt 2018-06-20 22:08:44 +02:00
parent af8e1fb32f
commit 49b84fb550
No known key found for this signature in database
GPG key ID: 9E1EA6AF7BBBB0D1
4 changed files with 68 additions and 7 deletions

View file

@ -10,6 +10,7 @@ import java.util.Date;
import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
/** /**
* Created by mike on 29.05.2017. * Created by mike on 29.05.2017.
@ -17,6 +18,7 @@ import info.nightscout.androidaps.db.Source;
public class DetailedBolusInfo { public class DetailedBolusInfo {
public long date = System.currentTimeMillis(); public long date = System.currentTimeMillis();
public long lastKnownBolusTime;
public String eventType = CareportalEvent.MEALBOLUS; public String eventType = CareportalEvent.MEALBOLUS;
public double insulin = 0; public double insulin = 0;
public double carbs = 0; public double carbs = 0;

View file

@ -520,6 +520,7 @@ public class ConfigBuilderPlugin extends PluginBase {
// deliver SMB // deliver SMB
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.lastKnownBolusTime = activeTreatments.getLastBolusTime();
detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS; detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS;
detailedBolusInfo.insulin = request.smb; detailedBolusInfo.insulin = request.smb;
detailedBolusInfo.isSMB = true; detailedBolusInfo.isSMB = true;

View file

@ -26,6 +26,7 @@ import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressHelperAc
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.commands.Command; import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.androidaps.queue.commands.CommandBolus; import info.nightscout.androidaps.queue.commands.CommandBolus;
import info.nightscout.androidaps.queue.commands.CommandCancelExtendedBolus; import info.nightscout.androidaps.queue.commands.CommandCancelExtendedBolus;
@ -177,6 +178,18 @@ public class CommandQueue {
public synchronized boolean bolus(DetailedBolusInfo detailedBolusInfo, Callback callback) { public synchronized boolean bolus(DetailedBolusInfo detailedBolusInfo, Callback callback) {
Command.CommandType type = detailedBolusInfo.isSMB ? Command.CommandType.SMB_BOLUS : Command.CommandType.BOLUS; Command.CommandType type = detailedBolusInfo.isSMB ? Command.CommandType.SMB_BOLUS : Command.CommandType.BOLUS;
if (type == Command.CommandType.SMB_BOLUS) {
if (isRunning(Command.CommandType.BOLUS) || bolusInQueue()) {
log.debug("Rejecting SMB since a bolus is queue/running");
return false;
}
if (detailedBolusInfo.lastKnownBolusTime < TreatmentsPlugin.getPlugin().getLastBolusTime()) {
log.debug("Rejecting bolus, another bolus was issued since request time");
return false;
}
}
if(type.equals(Command.CommandType.BOLUS) && detailedBolusInfo.carbs > 0 && detailedBolusInfo.insulin == 0){ if(type.equals(Command.CommandType.BOLUS) && detailedBolusInfo.carbs > 0 && detailedBolusInfo.insulin == 0){
type = Command.CommandType.CARBS_ONLY_TREATMENT; type = Command.CommandType.CARBS_ONLY_TREATMENT;
//Carbs only can be added in parallel as they can be "in the future". //Carbs only can be added in parallel as they can be "in the future".

View file

@ -15,6 +15,8 @@ import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.modules.junit4.PowerMockRunner;
import java.util.Date;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.ConstraintChecker; import info.nightscout.androidaps.data.ConstraintChecker;
@ -24,9 +26,11 @@ import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin; import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.commands.Command; import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.utils.ToastUtils; import info.nightscout.utils.ToastUtils;
import static info.nightscout.utils.DateUtil.now;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ -36,7 +40,7 @@ import static org.mockito.Mockito.when;
*/ */
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, ToastUtils.class, Context.class}) @PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, ToastUtils.class, Context.class, TreatmentsPlugin.class})
public class CommandQueueTest extends CommandQueue { public class CommandQueueTest extends CommandQueue {
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\"}"; 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\"}";
@ -142,6 +146,11 @@ public class CommandQueueTest extends CommandQueue {
when(MainApp.bus()).thenReturn(bus); when(MainApp.bus()).thenReturn(bus);
when(MainApp.gs(0)).thenReturn(""); when(MainApp.gs(0)).thenReturn("");
PowerMockito.mockStatic(TreatmentsPlugin.class);
TreatmentsPlugin treatmentsPlugin = mock(TreatmentsPlugin.class);
when(TreatmentsPlugin.getPlugin()).thenReturn(treatmentsPlugin);
when(treatmentsPlugin.getLastBolusTime()).thenReturn(new Date(100, 0,1 ).getTime());
} }
@Override @Override
@ -159,21 +168,57 @@ public class CommandQueueTest extends CommandQueue {
@Test @Test
public void callingCancelAllBolusesClearsQueue() throws Exception { public void callingCancelAllBolusesClearsQueue() throws Exception {
// given
prepareMock(0d, 0); prepareMock(0d, 0);
// add normal and SMB-bolus to queue
Assert.assertEquals(0, size()); Assert.assertEquals(0, size());
DetailedBolusInfo smb = new DetailedBolusInfo();
smb.lastKnownBolusTime = now();
smb.isSMB = true;
bolus(smb, null);
bolus(new DetailedBolusInfo(), null);
Assert.assertEquals(2, size());
// when
cancelAllBoluses();
// then
Assert.assertEquals(0, size());
}
@Test
public void smbIsRejectedIfABolusIsQueued() throws Exception {
// given
prepareMock(0d, 0);
Assert.assertEquals(0, size());
// when
bolus(new DetailedBolusInfo(), null); bolus(new DetailedBolusInfo(), null);
DetailedBolusInfo smb = new DetailedBolusInfo(); DetailedBolusInfo smb = new DetailedBolusInfo();
smb.isSMB = true; smb.isSMB = true;
bolus(smb, null); boolean queued = bolus(smb, null);
Assert.assertEquals(2, size()); // then
Assert.assertFalse(queued);
Assert.assertEquals(size(), 1);
}
// cancelling all boluses clear all boluses from the queue @Test
cancelAllBoluses(); public void smbIsRejectedIfLastKnownBolusIsOutdated() throws Exception {
// given
prepareMock(0d, 0);
Assert.assertEquals(0, size()); Assert.assertEquals(0, size());
// when
DetailedBolusInfo bolus = new DetailedBolusInfo();
bolus.isSMB = true;
bolus.lastKnownBolusTime = 0;
boolean queued = bolus(bolus, null);
// then
Assert.assertFalse(queued);
Assert.assertEquals(size(), 0);
} }
} }