remove readstatus prior every command
This commit is contained in:
parent
99d83a60f4
commit
5a00b68f68
9 changed files with 203 additions and 55 deletions
|
@ -229,6 +229,10 @@ public class MainApp extends Application {
|
|||
return sBus;
|
||||
}
|
||||
|
||||
public static String gs(int id) {
|
||||
return sResources.getString(id);
|
||||
}
|
||||
|
||||
public static MainApp instance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ public class Profile {
|
|||
}
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.invalidprofile));
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.invalidprofile));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,6 +386,8 @@ public class Profile {
|
|||
}
|
||||
|
||||
public BasalValue[] getBasalValues() {
|
||||
if (basal_v == null)
|
||||
basal_v = convertToSparseArray(basal);
|
||||
BasalValue[] ret = new BasalValue[basal_v.size()];
|
||||
|
||||
for (Integer index = 0; index < basal_v.size(); index++) {
|
||||
|
|
|
@ -421,23 +421,6 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
@Override
|
||||
public PumpDescription getPumpDescription() {
|
||||
if (activePump != null)
|
||||
return activePump.getPumpDescription();
|
||||
else {
|
||||
PumpDescription emptyDescription = new PumpDescription();
|
||||
emptyDescription.isBolusCapable = false;
|
||||
emptyDescription.isExtendedBolusCapable = false;
|
||||
emptyDescription.isSetBasalProfileCapable = false;
|
||||
emptyDescription.isTempBasalCapable = true; // needs to be true before real driver is selected
|
||||
emptyDescription.isRefillingCapable = false;
|
||||
return emptyDescription;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Constraints interface
|
||||
**/
|
||||
|
|
|
@ -258,6 +258,7 @@ public class DanaRSService extends Service {
|
|||
MainApp.bus().post(bolusingEvent);
|
||||
SystemClock.sleep(1000);
|
||||
}
|
||||
// do not call loadEvents() directly, reconnection may be needed
|
||||
ConfigBuilderPlugin.getCommandQueue().loadEvents(new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
|
|
@ -424,6 +424,7 @@ public class DanaRv2ExecutionService extends Service {
|
|||
MainApp.bus().post(bolusingEvent);
|
||||
SystemClock.sleep(1000);
|
||||
}
|
||||
// do not call loadEvents() directly, reconnection may be needed
|
||||
ConfigBuilderPlugin.getCommandQueue().loadEvents(new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.queue;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Html;
|
||||
|
@ -37,42 +38,41 @@ import info.nightscout.androidaps.queue.commands.CommandTempBasalPercent;
|
|||
|
||||
/**
|
||||
* Created by mike on 08.11.2017.
|
||||
*
|
||||
* <p>
|
||||
* DATA FLOW:
|
||||
* ---------
|
||||
*
|
||||
* <p>
|
||||
* (request) - > ConfigBuilder.getCommandQueue().bolus(...)
|
||||
*
|
||||
* <p>
|
||||
* app no longer waits for result but passes Callback
|
||||
*
|
||||
* <p>
|
||||
* request is added to queue, if another request of the same type already exists in queue, it's removed prior adding
|
||||
* but if request of the same type is currently executed (probably important only for bolus which is running long time), new request is declined
|
||||
* new QueueThread is created and started if current if finished
|
||||
* CommandReadStatus is added automatically before command if queue is empty
|
||||
*
|
||||
* <p>
|
||||
* biggest change is we don't need exec pump commands in Handler because it's finished immediately
|
||||
* command queueing if not realized by stacking in different Handlers and threads anymore but by internal queue with better control
|
||||
*
|
||||
* <p>
|
||||
* QueueThread calls ConfigBuilder#connect which is passed to getActivePump().connect
|
||||
* connect should be executed on background and return immediately. afterwards isConnecting() is expected to be true
|
||||
*
|
||||
* <p>
|
||||
* while isConnecting() == true GUI is updated by posting connection progress
|
||||
*
|
||||
* <p>
|
||||
* if connect is successful: isConnected() becomes true, isConnecting() becomes false
|
||||
* CommandQueue starts calling execute() of commands. execute() is expected to be blocking (return after finish).
|
||||
* callback with result is called after finish automatically
|
||||
* CommandQueue starts calling execute() of commands. execute() is expected to be blocking (return after finish).
|
||||
* callback with result is called after finish automatically
|
||||
* if connect failed: isConnected() becomes false, isConnecting() becomes false
|
||||
* connect() is called again
|
||||
*
|
||||
* connect() is called again
|
||||
* <p>
|
||||
* when queue is empty, disconnect is called
|
||||
*
|
||||
*/
|
||||
|
||||
public class CommandQueue {
|
||||
private static Logger log = LoggerFactory.getLogger(CommandQueue.class);
|
||||
|
||||
private LinkedList<Command> queue = new LinkedList<>();
|
||||
private Command performing;
|
||||
protected Command performing;
|
||||
|
||||
private QueueThread thread = null;
|
||||
|
||||
|
@ -94,10 +94,19 @@ public class CommandQueue {
|
|||
}
|
||||
}
|
||||
|
||||
private synchronized boolean isLastScheduled(Command.CommandType type) {
|
||||
if (queue.size() > 0 && queue.get(queue.size() - 1).commandType == type) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private synchronized void inject(Command command) {
|
||||
// inject as a first command
|
||||
queue.addFirst(command);
|
||||
}
|
||||
|
||||
private synchronized void add(Command command) {
|
||||
// inject reading of status when adding first command to the queue
|
||||
if (queue.size() == 0 && command.commandType != Command.CommandType.READSTATUS)
|
||||
queue.add(new CommandReadStatus("Queue", null));
|
||||
queue.add(command);
|
||||
}
|
||||
|
||||
|
@ -128,7 +137,7 @@ public class CommandQueue {
|
|||
|
||||
// After new command added to the queue
|
||||
// start thread again if not already running
|
||||
private synchronized void notifyAboutNewCommand() {
|
||||
protected synchronized void notifyAboutNewCommand() {
|
||||
if (thread == null || thread.getState() == Thread.State.TERMINATED) {
|
||||
thread = new QueueThread(this);
|
||||
thread.start();
|
||||
|
@ -166,17 +175,7 @@ public class CommandQueue {
|
|||
MainApp.bus().post(new EventBolusRequested(detailedBolusInfo.insulin));
|
||||
|
||||
// Bring up bolus progress dialog
|
||||
if (detailedBolusInfo.context != null) {
|
||||
BolusProgressDialog bolusProgressDialog = new BolusProgressDialog();
|
||||
bolusProgressDialog.setInsulin(detailedBolusInfo.insulin);
|
||||
bolusProgressDialog.show(((AppCompatActivity) detailedBolusInfo.context).getSupportFragmentManager(), "BolusProgress");
|
||||
} else {
|
||||
Intent i = new Intent();
|
||||
i.putExtra("insulin", detailedBolusInfo.insulin);
|
||||
i.setClass(MainApp.instance(), BolusProgressHelperActivity.class);
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
MainApp.instance().startActivity(i);
|
||||
}
|
||||
showBolusProgressDialog(detailedBolusInfo.insulin, detailedBolusInfo.context);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -231,7 +230,7 @@ public class CommandQueue {
|
|||
return false;
|
||||
}
|
||||
|
||||
Double rateAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(insulin);
|
||||
Double rateAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(insulin);
|
||||
|
||||
// remove all unfinished
|
||||
removeAll(Command.CommandType.EXTENDEDBOLUS);
|
||||
|
@ -326,11 +325,12 @@ public class CommandQueue {
|
|||
|
||||
// returns true if command is queued
|
||||
public boolean readStatus(String reason, Callback callback) {
|
||||
//if (isRunning(Command.CommandType.READSTATUS)) {
|
||||
// if (callback != null)
|
||||
// callback.result(executingNowError()).run();
|
||||
// return false;
|
||||
//}
|
||||
if (isLastScheduled(Command.CommandType.READSTATUS)) {
|
||||
log.debug("QUEUE: READSTATUS " + reason + " ignored as duplicated");
|
||||
if (callback != null)
|
||||
callback.result(executingNowError()).run();
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove all unfinished
|
||||
//removeAll(Command.CommandType.READSTATUS);
|
||||
|
@ -409,4 +409,18 @@ public class CommandQueue {
|
|||
} else return true;
|
||||
}
|
||||
|
||||
protected void showBolusProgressDialog(Double insulin, Context context) {
|
||||
if (context != null) {
|
||||
BolusProgressDialog bolusProgressDialog = new BolusProgressDialog();
|
||||
bolusProgressDialog.setInsulin(insulin);
|
||||
bolusProgressDialog.show(((AppCompatActivity) context).getSupportFragmentManager(), "BolusProgress");
|
||||
} else {
|
||||
Intent i = new Intent();
|
||||
i.putExtra("insulin", insulin);
|
||||
i.setClass(MainApp.instance(), BolusProgressHelperActivity.class);
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
MainApp.instance().startActivity(i);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ public abstract class Command {
|
|||
public void cancel() {
|
||||
PumpEnactResult result = new PumpEnactResult();
|
||||
result.success = false;
|
||||
result.comment = MainApp.sResources.getString(R.string.connectiontimedout);
|
||||
result.comment = MainApp.gs(R.string.connectiontimedout);
|
||||
if (callback != null)
|
||||
callback.result(result).run();
|
||||
}
|
||||
|
|
|
@ -27,6 +27,6 @@ public class CommandReadStatus extends Command {
|
|||
|
||||
@Override
|
||||
public String status() {
|
||||
return "READSTATUS";
|
||||
return "READSTATUS " + reason;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
package info.nightscout.androidaps.queue;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Html;
|
||||
|
||||
import com.squareup.otto.Bus;
|
||||
import com.squareup.otto.ThreadEnforcer;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.json.JSONObject;
|
||||
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.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
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.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Created by mike on 14.01.2018.
|
||||
*/
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({MainApp.class, ConfigBuilderPlugin.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\"}";
|
||||
|
||||
@Test
|
||||
public void doTests() throws Exception {
|
||||
prepareMock(0d, 0);
|
||||
|
||||
// start with empty queue
|
||||
Assert.assertEquals(0, size());
|
||||
|
||||
// add bolus command
|
||||
bolus(new DetailedBolusInfo(), null);
|
||||
Assert.assertEquals(1, size());
|
||||
|
||||
// add READSTATUS
|
||||
readStatus("anyString", null);
|
||||
Assert.assertEquals(2, size());
|
||||
|
||||
// adding another bolus should remove the first one (size still == 2)
|
||||
bolus(new DetailedBolusInfo(), null);
|
||||
Assert.assertEquals(2, size());
|
||||
|
||||
// clear the queue should reset size
|
||||
clear();
|
||||
Assert.assertEquals(0, size());
|
||||
|
||||
// add tempbasal
|
||||
tempBasalAbsolute(0, 30, true, null);
|
||||
Assert.assertEquals(1, size());
|
||||
|
||||
// add tempbasal percent. it should replace previous TEMPBASAL
|
||||
tempBasalPercent(0, 30, true, null);
|
||||
Assert.assertEquals(1, size());
|
||||
|
||||
// add extended bolus
|
||||
extendedBolus(1, 30, null);
|
||||
Assert.assertEquals(2, size());
|
||||
|
||||
// add cancel temp basal should remove previous 2 temp basal setting
|
||||
extendedBolus(1, 30, null);
|
||||
Assert.assertEquals(2, size());
|
||||
|
||||
// cancel extended bolus should replace previous extended
|
||||
extendedBolus(1, 30, null);
|
||||
Assert.assertEquals(2, size());
|
||||
|
||||
// add setProfile
|
||||
setProfile(new Profile(new JSONObject(profileJson), Constants.MGDL), null);
|
||||
Assert.assertEquals(3, size());
|
||||
|
||||
// add loadHistory
|
||||
loadHistory((byte) 0, null);
|
||||
Assert.assertEquals(4, size());
|
||||
|
||||
// add loadEvents
|
||||
loadEvents(null);
|
||||
Assert.assertEquals(5, size());
|
||||
|
||||
clear();
|
||||
tempBasalAbsolute(0, 30, true, null);
|
||||
pickup();
|
||||
Assert.assertEquals(0, size());
|
||||
Assert.assertNotNull(performing);
|
||||
Assert.assertEquals(Command.CommandType.TEMPBASAL, performing.commandType);
|
||||
resetPerforming();
|
||||
Assert.assertNull(performing);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
PowerMockito.mockStatic(ConfigBuilderPlugin.class);
|
||||
PumpInterface pump = MDIPlugin.getPlugin();
|
||||
when(ConfigBuilderPlugin.getActivePump()).thenReturn(pump);
|
||||
|
||||
PowerMockito.mockStatic(MainApp.class);
|
||||
MainApp mainApp = mock(MainApp.class);
|
||||
when(MainApp.getConfigBuilder()).thenReturn(configBuilderPlugin);
|
||||
when(MainApp.instance()).thenReturn(mainApp);
|
||||
|
||||
PowerMockito.mockStatic(ToastUtils.class);
|
||||
Context context = mock(Context.class);
|
||||
String message = null;
|
||||
PowerMockito.doNothing().when(ToastUtils.class, "showToastInUiThread", context, message);
|
||||
|
||||
Bus bus = new Bus(ThreadEnforcer.ANY);
|
||||
|
||||
when(MainApp.bus()).thenReturn(bus);
|
||||
when(MainApp.gs(0)).thenReturn("");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void notifyAboutNewCommand() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showBolusProgressDialog(Double insulin, Context context) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isThisProfileSet(Profile profile) {
|
||||
return false;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue