2017-11-10 00:27:18 +01:00
|
|
|
package info.nightscout.androidaps.queue;
|
|
|
|
|
2018-01-14 21:42:36 +01:00
|
|
|
import android.content.Context;
|
2017-11-11 23:03:31 +01:00
|
|
|
import android.content.Intent;
|
2018-02-18 11:53:41 +01:00
|
|
|
import android.os.SystemClock;
|
2017-11-10 00:27:18 +01:00
|
|
|
import android.text.Html;
|
|
|
|
import android.text.Spanned;
|
|
|
|
|
2019-10-01 00:00:22 +02:00
|
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
|
|
|
2017-11-10 00:27:18 +01:00
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
|
|
import java.util.LinkedList;
|
|
|
|
|
|
|
|
import info.nightscout.androidaps.MainApp;
|
|
|
|
import info.nightscout.androidaps.R;
|
|
|
|
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
|
|
|
import info.nightscout.androidaps.data.Profile;
|
|
|
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
2017-11-20 23:39:12 +01:00
|
|
|
import info.nightscout.androidaps.events.EventBolusRequested;
|
2018-03-20 22:09:22 +01:00
|
|
|
import info.nightscout.androidaps.interfaces.Constraint;
|
2017-11-20 23:39:12 +01:00
|
|
|
import info.nightscout.androidaps.interfaces.PumpInterface;
|
2018-07-29 14:39:56 +02:00
|
|
|
import info.nightscout.androidaps.logging.L;
|
2019-10-01 00:00:22 +02:00
|
|
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
2019-02-28 23:16:50 +01:00
|
|
|
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
|
|
|
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
2019-04-10 17:24:16 +02:00
|
|
|
import info.nightscout.androidaps.plugins.general.overview.dialogs.BolusProgressDialog;
|
|
|
|
import info.nightscout.androidaps.plugins.general.overview.dialogs.BolusProgressHelperActivity;
|
2019-02-28 23:16:50 +01:00
|
|
|
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusprogressIfRunning;
|
|
|
|
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification;
|
|
|
|
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
|
|
|
|
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
|
|
|
|
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
2017-11-11 14:05:29 +01:00
|
|
|
import info.nightscout.androidaps.queue.commands.Command;
|
|
|
|
import info.nightscout.androidaps.queue.commands.CommandBolus;
|
|
|
|
import info.nightscout.androidaps.queue.commands.CommandCancelExtendedBolus;
|
|
|
|
import info.nightscout.androidaps.queue.commands.CommandCancelTempBasal;
|
|
|
|
import info.nightscout.androidaps.queue.commands.CommandExtendedBolus;
|
2019-01-18 22:40:08 +01:00
|
|
|
import info.nightscout.androidaps.queue.commands.CommandInsightSetTBROverNotification;
|
2017-11-22 22:09:58 +01:00
|
|
|
import info.nightscout.androidaps.queue.commands.CommandLoadEvents;
|
2017-11-11 14:05:29 +01:00
|
|
|
import info.nightscout.androidaps.queue.commands.CommandLoadHistory;
|
2018-03-14 00:57:48 +01:00
|
|
|
import info.nightscout.androidaps.queue.commands.CommandLoadTDDs;
|
2017-11-11 14:05:29 +01:00
|
|
|
import info.nightscout.androidaps.queue.commands.CommandReadStatus;
|
2017-12-01 18:41:24 +01:00
|
|
|
import info.nightscout.androidaps.queue.commands.CommandSMBBolus;
|
2017-11-11 14:05:29 +01:00
|
|
|
import info.nightscout.androidaps.queue.commands.CommandSetProfile;
|
2018-06-06 18:29:40 +02:00
|
|
|
import info.nightscout.androidaps.queue.commands.CommandSetUserSettings;
|
2019-01-18 22:40:08 +01:00
|
|
|
import info.nightscout.androidaps.queue.commands.CommandStartPump;
|
|
|
|
import info.nightscout.androidaps.queue.commands.CommandStopPump;
|
2017-11-11 14:05:29 +01:00
|
|
|
import info.nightscout.androidaps.queue.commands.CommandTempBasalAbsolute;
|
|
|
|
import info.nightscout.androidaps.queue.commands.CommandTempBasalPercent;
|
2017-11-10 00:27:18 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Created by mike on 08.11.2017.
|
2018-01-14 21:42:36 +01:00
|
|
|
* <p>
|
2017-11-11 14:05:29 +01:00
|
|
|
* DATA FLOW:
|
|
|
|
* ---------
|
2018-01-14 21:42:36 +01:00
|
|
|
* <p>
|
2017-11-11 14:05:29 +01:00
|
|
|
* (request) - > ConfigBuilder.getCommandQueue().bolus(...)
|
2018-01-14 21:42:36 +01:00
|
|
|
* <p>
|
2017-11-11 14:05:29 +01:00
|
|
|
* app no longer waits for result but passes Callback
|
2018-01-14 21:42:36 +01:00
|
|
|
* <p>
|
2017-11-11 14:05:29 +01:00
|
|
|
* 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
|
2018-01-14 21:42:36 +01:00
|
|
|
* <p>
|
2017-11-11 14:05:29 +01:00
|
|
|
* 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
|
2018-01-14 21:42:36 +01:00
|
|
|
* <p>
|
2017-11-11 14:05:29 +01:00
|
|
|
* 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
|
2018-01-14 21:42:36 +01:00
|
|
|
* <p>
|
2017-11-11 14:05:29 +01:00
|
|
|
* while isConnecting() == true GUI is updated by posting connection progress
|
2018-01-14 21:42:36 +01:00
|
|
|
* <p>
|
2017-11-11 14:05:29 +01:00
|
|
|
* if connect is successful: isConnected() becomes true, isConnecting() becomes false
|
2018-01-14 21:42:36 +01:00
|
|
|
* CommandQueue starts calling execute() of commands. execute() is expected to be blocking (return after finish).
|
|
|
|
* callback with result is called after finish automatically
|
2017-11-11 14:05:29 +01:00
|
|
|
* if connect failed: isConnected() becomes false, isConnecting() becomes false
|
2018-01-14 21:42:36 +01:00
|
|
|
* connect() is called again
|
|
|
|
* <p>
|
2017-11-11 14:05:29 +01:00
|
|
|
* when queue is empty, disconnect is called
|
2017-11-10 00:27:18 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
public class CommandQueue {
|
2018-07-29 14:39:56 +02:00
|
|
|
private Logger log = LoggerFactory.getLogger(L.PUMPQUEUE);
|
2017-11-10 00:27:18 +01:00
|
|
|
|
2018-05-04 21:13:49 +02:00
|
|
|
private final LinkedList<Command> queue = new LinkedList<>();
|
2018-07-28 23:38:39 +02:00
|
|
|
Command performing;
|
2017-11-10 00:27:18 +01:00
|
|
|
|
2017-11-11 14:05:29 +01:00
|
|
|
private QueueThread thread = null;
|
2017-11-10 00:27:18 +01:00
|
|
|
|
|
|
|
private PumpEnactResult executingNowError() {
|
2018-05-02 13:46:38 +02:00
|
|
|
return new PumpEnactResult().success(false).enacted(false).comment(MainApp.gs(R.string.executingrightnow));
|
2017-11-10 00:27:18 +01:00
|
|
|
}
|
|
|
|
|
2018-03-28 19:33:41 +02:00
|
|
|
public boolean isRunning(Command.CommandType type) {
|
2017-11-11 14:05:29 +01:00
|
|
|
if (performing != null && performing.commandType == type)
|
2017-11-10 00:27:18 +01:00
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
private synchronized void removeAll(Command.CommandType type) {
|
2019-10-08 09:52:55 +02:00
|
|
|
synchronized (queue) {
|
|
|
|
for (int i = queue.size() - 1; i >= 0; i--) {
|
|
|
|
if (queue.get(i).commandType == type) {
|
|
|
|
queue.remove(i);
|
|
|
|
}
|
2017-11-10 00:27:18 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-14 21:42:36 +01:00
|
|
|
private synchronized boolean isLastScheduled(Command.CommandType type) {
|
2019-10-08 09:52:55 +02:00
|
|
|
synchronized (queue) {
|
|
|
|
if (queue.size() > 0 && queue.get(queue.size() - 1).commandType == type) {
|
|
|
|
return true;
|
|
|
|
}
|
2018-01-14 21:42:36 +01:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
private synchronized void inject(Command command) {
|
|
|
|
// inject as a first command
|
2018-07-29 14:39:56 +02:00
|
|
|
if (L.isEnabled(L.PUMPQUEUE))
|
2018-07-27 12:17:29 +02:00
|
|
|
log.debug("Adding as first: " + command.getClass().getSimpleName() + " - " + command.status());
|
2019-10-08 09:52:55 +02:00
|
|
|
synchronized (queue) {
|
|
|
|
queue.addFirst(command);
|
|
|
|
}
|
2018-01-14 21:42:36 +01:00
|
|
|
}
|
|
|
|
|
2017-11-10 00:27:18 +01:00
|
|
|
private synchronized void add(Command command) {
|
2018-07-29 14:39:56 +02:00
|
|
|
if (L.isEnabled(L.PUMPQUEUE))
|
2018-07-27 12:17:29 +02:00
|
|
|
log.debug("Adding: " + command.getClass().getSimpleName() + " - " + command.status());
|
2019-10-08 09:52:55 +02:00
|
|
|
synchronized (queue) {
|
|
|
|
queue.add(command);
|
|
|
|
}
|
2017-11-10 00:27:18 +01:00
|
|
|
}
|
|
|
|
|
2017-11-11 14:05:29 +01:00
|
|
|
synchronized void pickup() {
|
2019-10-08 09:52:55 +02:00
|
|
|
synchronized (queue) {
|
|
|
|
performing = queue.poll();
|
|
|
|
}
|
2017-11-10 00:27:18 +01:00
|
|
|
}
|
|
|
|
|
2017-11-11 14:05:29 +01:00
|
|
|
synchronized void clear() {
|
|
|
|
performing = null;
|
2019-10-08 09:52:55 +02:00
|
|
|
synchronized (queue) {
|
|
|
|
for (int i = 0; i < queue.size(); i++) {
|
|
|
|
queue.get(i).cancel();
|
|
|
|
}
|
|
|
|
queue.clear();
|
2017-11-11 14:05:29 +01:00
|
|
|
}
|
2017-11-10 00:27:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public int size() {
|
|
|
|
return queue.size();
|
|
|
|
}
|
|
|
|
|
2019-04-29 11:36:30 +02:00
|
|
|
Command performing() {
|
2017-11-10 00:27:18 +01:00
|
|
|
return performing;
|
|
|
|
}
|
|
|
|
|
2019-04-29 11:36:30 +02:00
|
|
|
void resetPerforming() {
|
2017-11-10 00:27:18 +01:00
|
|
|
performing = null;
|
|
|
|
}
|
|
|
|
|
2017-11-11 14:05:29 +01:00
|
|
|
// After new command added to the queue
|
|
|
|
// start thread again if not already running
|
2018-01-14 21:42:36 +01:00
|
|
|
protected synchronized void notifyAboutNewCommand() {
|
2018-04-01 12:34:41 +02:00
|
|
|
while (thread != null && thread.getState() != Thread.State.TERMINATED && thread.waitingForDisconnect) {
|
2018-07-29 14:39:56 +02:00
|
|
|
if (L.isEnabled(L.PUMPQUEUE))
|
2018-07-27 12:17:29 +02:00
|
|
|
log.debug("Waiting for previous thread finish");
|
2018-04-01 12:34:41 +02:00
|
|
|
SystemClock.sleep(500);
|
|
|
|
}
|
2017-11-11 14:05:29 +01:00
|
|
|
if (thread == null || thread.getState() == Thread.State.TERMINATED) {
|
|
|
|
thread = new QueueThread(this);
|
2017-11-10 00:27:18 +01:00
|
|
|
thread.start();
|
2018-07-29 14:39:56 +02:00
|
|
|
if (L.isEnabled(L.PUMPQUEUE))
|
2018-07-27 12:17:29 +02:00
|
|
|
log.debug("Starting new thread");
|
2018-04-01 12:34:41 +02:00
|
|
|
} else {
|
2018-07-29 14:39:56 +02:00
|
|
|
if (L.isEnabled(L.PUMPQUEUE))
|
2018-07-27 12:17:29 +02:00
|
|
|
log.debug("Thread is already running");
|
2017-11-11 14:05:29 +01:00
|
|
|
}
|
2017-11-10 00:27:18 +01:00
|
|
|
}
|
|
|
|
|
2018-08-21 19:53:59 +02:00
|
|
|
public void independentConnect(String reason, Callback callback) {
|
|
|
|
if (L.isEnabled(L.PUMPQUEUE))
|
|
|
|
log.debug("Starting new queue");
|
2017-12-03 20:10:54 +01:00
|
|
|
CommandQueue tempCommandQueue = new CommandQueue();
|
|
|
|
tempCommandQueue.readStatus(reason, callback);
|
|
|
|
}
|
|
|
|
|
2018-07-27 12:17:29 +02:00
|
|
|
public synchronized boolean bolusInQueue() {
|
|
|
|
if (isRunning(Command.CommandType.BOLUS)) return true;
|
2019-10-08 09:52:55 +02:00
|
|
|
synchronized (queue) {
|
|
|
|
for (int i = 0; i < queue.size(); i++) {
|
|
|
|
if (queue.get(i).commandType == Command.CommandType.BOLUS) {
|
|
|
|
return true;
|
|
|
|
}
|
2018-05-04 12:23:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-11-10 00:27:18 +01:00
|
|
|
// returns true if command is queued
|
2018-05-04 12:23:51 +02:00
|
|
|
public synchronized boolean bolus(DetailedBolusInfo detailedBolusInfo, Callback callback) {
|
2017-12-01 18:41:24 +01:00
|
|
|
Command.CommandType type = detailedBolusInfo.isSMB ? Command.CommandType.SMB_BOLUS : Command.CommandType.BOLUS;
|
|
|
|
|
2018-06-20 22:08:44 +02:00
|
|
|
if (type == Command.CommandType.SMB_BOLUS) {
|
2019-07-31 14:56:30 +02:00
|
|
|
if (isRunning(Command.CommandType.BOLUS) || isRunning(Command.CommandType.SMB_BOLUS) || bolusInQueue()) {
|
2018-07-29 14:39:56 +02:00
|
|
|
if (L.isEnabled(L.PUMPQUEUE))
|
2018-07-27 12:17:29 +02:00
|
|
|
log.debug("Rejecting SMB since a bolus is queue/running");
|
2018-06-20 22:08:44 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (detailedBolusInfo.lastKnownBolusTime < TreatmentsPlugin.getPlugin().getLastBolusTime()) {
|
2018-07-29 14:39:56 +02:00
|
|
|
if (L.isEnabled(L.PUMPQUEUE))
|
2018-07-27 12:17:29 +02:00
|
|
|
log.debug("Rejecting bolus, another bolus was issued since request time");
|
2018-06-20 22:08:44 +02:00
|
|
|
return false;
|
|
|
|
}
|
2019-07-31 14:56:30 +02:00
|
|
|
removeAll(Command.CommandType.SMB_BOLUS);
|
2018-06-20 22:08:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-27 12:17:29 +02:00
|
|
|
if (type.equals(Command.CommandType.BOLUS) && detailedBolusInfo.carbs > 0 && detailedBolusInfo.insulin == 0) {
|
2018-04-18 16:13:02 +02:00
|
|
|
type = Command.CommandType.CARBS_ONLY_TREATMENT;
|
|
|
|
//Carbs only can be added in parallel as they can be "in the future".
|
|
|
|
} else {
|
|
|
|
if (isRunning(type)) {
|
|
|
|
if (callback != null)
|
|
|
|
callback.result(executingNowError()).run();
|
|
|
|
return false;
|
|
|
|
}
|
2017-11-10 00:27:18 +01:00
|
|
|
|
2018-04-18 16:13:02 +02:00
|
|
|
// remove all unfinished boluses
|
|
|
|
removeAll(type);
|
|
|
|
}
|
2017-11-10 00:27:18 +01:00
|
|
|
|
2017-12-12 22:30:42 +01:00
|
|
|
// apply constraints
|
2018-03-21 23:01:30 +01:00
|
|
|
detailedBolusInfo.insulin = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value();
|
2018-03-22 10:31:07 +01:00
|
|
|
detailedBolusInfo.carbs = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>((int) detailedBolusInfo.carbs)).value();
|
2017-12-12 22:30:42 +01:00
|
|
|
|
2017-11-10 00:27:18 +01:00
|
|
|
// add new command to queue
|
2017-12-20 17:35:39 +01:00
|
|
|
if (detailedBolusInfo.isSMB) {
|
2017-12-01 18:41:24 +01:00
|
|
|
add(new CommandSMBBolus(detailedBolusInfo, callback));
|
2017-12-20 17:35:39 +01:00
|
|
|
} else {
|
2018-04-18 16:13:02 +02:00
|
|
|
add(new CommandBolus(detailedBolusInfo, callback, type));
|
2018-07-27 12:17:29 +02:00
|
|
|
if (type.equals(Command.CommandType.BOLUS)) {
|
2018-04-18 16:23:40 +02:00
|
|
|
// Bring up bolus progress dialog (start here, so the dialog is shown when the bolus is requested,
|
|
|
|
// not when the Bolus command is starting. The command closes the dialog upon completion).
|
|
|
|
showBolusProgressDialog(detailedBolusInfo.insulin, detailedBolusInfo.context);
|
|
|
|
// Notify Wear about upcoming bolus
|
2019-10-14 23:49:53 +02:00
|
|
|
RxBus.INSTANCE.send(new EventBolusRequested(detailedBolusInfo.insulin));
|
2018-04-18 16:23:40 +02:00
|
|
|
}
|
2017-12-20 17:35:39 +01:00
|
|
|
}
|
2017-11-10 00:27:18 +01:00
|
|
|
|
|
|
|
notifyAboutNewCommand();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-01-18 22:40:08 +01:00
|
|
|
public void stopPump(Callback callback) {
|
|
|
|
add(new CommandStopPump(callback));
|
|
|
|
notifyAboutNewCommand();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void startPump(Callback callback) {
|
|
|
|
add(new CommandStartPump(callback));
|
|
|
|
notifyAboutNewCommand();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setTBROverNotification(Callback callback, boolean enable) {
|
|
|
|
add(new CommandInsightSetTBROverNotification(callback, enable));
|
|
|
|
notifyAboutNewCommand();
|
|
|
|
}
|
|
|
|
|
2018-05-13 23:44:12 +02:00
|
|
|
public synchronized void cancelAllBoluses() {
|
2018-08-03 11:02:46 +02:00
|
|
|
if (!isRunning(Command.CommandType.BOLUS)) {
|
|
|
|
MainApp.bus().post(new EventDismissBolusprogressIfRunning(new PumpEnactResult().success(true).enacted(false)));
|
|
|
|
}
|
2018-05-13 23:44:12 +02:00
|
|
|
removeAll(Command.CommandType.BOLUS);
|
|
|
|
removeAll(Command.CommandType.SMB_BOLUS);
|
2018-09-17 17:43:42 +02:00
|
|
|
ConfigBuilderPlugin.getPlugin().getActivePump().stopBolusDelivering();
|
2018-05-13 23:44:12 +02:00
|
|
|
}
|
|
|
|
|
2017-11-10 00:27:18 +01:00
|
|
|
// returns true if command is queued
|
2018-03-20 22:09:22 +01:00
|
|
|
public boolean tempBasalAbsolute(double absoluteRate, int durationInMinutes, boolean enforceNew, Profile profile, Callback callback) {
|
2018-04-20 18:05:37 +02:00
|
|
|
if (!enforceNew && isRunning(Command.CommandType.TEMPBASAL)) {
|
2017-11-11 14:05:29 +01:00
|
|
|
if (callback != null)
|
|
|
|
callback.result(executingNowError()).run();
|
2017-11-10 00:27:18 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-11-11 14:05:29 +01:00
|
|
|
// remove all unfinished
|
2017-11-10 00:27:18 +01:00
|
|
|
removeAll(Command.CommandType.TEMPBASAL);
|
|
|
|
|
2018-03-20 22:09:22 +01:00
|
|
|
Double rateAfterConstraints = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(absoluteRate), profile).value();
|
2017-11-20 23:39:12 +01:00
|
|
|
|
2017-11-10 00:27:18 +01:00
|
|
|
// add new command to queue
|
2018-03-20 22:09:22 +01:00
|
|
|
add(new CommandTempBasalAbsolute(rateAfterConstraints, durationInMinutes, enforceNew, profile, callback));
|
2017-11-10 00:27:18 +01:00
|
|
|
|
|
|
|
notifyAboutNewCommand();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns true if command is queued
|
2018-03-21 20:24:02 +01:00
|
|
|
public boolean tempBasalPercent(Integer percent, int durationInMinutes, boolean enforceNew, Profile profile, Callback callback) {
|
2018-04-20 18:05:37 +02:00
|
|
|
if (!enforceNew && isRunning(Command.CommandType.TEMPBASAL)) {
|
2017-11-11 14:05:29 +01:00
|
|
|
if (callback != null)
|
|
|
|
callback.result(executingNowError()).run();
|
2017-11-10 00:27:18 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-11-11 14:05:29 +01:00
|
|
|
// remove all unfinished
|
2017-11-10 00:27:18 +01:00
|
|
|
removeAll(Command.CommandType.TEMPBASAL);
|
|
|
|
|
2018-03-21 20:24:02 +01:00
|
|
|
Integer percentAfterConstraints = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(percent), profile).value();
|
2017-11-20 23:39:12 +01:00
|
|
|
|
2017-11-10 00:27:18 +01:00
|
|
|
// add new command to queue
|
2018-03-21 20:24:02 +01:00
|
|
|
add(new CommandTempBasalPercent(percentAfterConstraints, durationInMinutes, enforceNew, profile, callback));
|
2017-11-10 00:27:18 +01:00
|
|
|
|
|
|
|
notifyAboutNewCommand();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns true if command is queued
|
|
|
|
public boolean extendedBolus(double insulin, int durationInMinutes, Callback callback) {
|
2017-11-11 14:05:29 +01:00
|
|
|
if (isRunning(Command.CommandType.EXTENDEDBOLUS)) {
|
|
|
|
if (callback != null)
|
|
|
|
callback.result(executingNowError()).run();
|
2017-11-10 00:27:18 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-09-01 22:45:15 +02:00
|
|
|
Double rateAfterConstraints = MainApp.getConstraintChecker().applyExtendedBolusConstraints(new Constraint<>(insulin)).value();
|
2017-11-20 23:39:12 +01:00
|
|
|
|
|
|
|
// remove all unfinished
|
2017-11-10 00:27:18 +01:00
|
|
|
removeAll(Command.CommandType.EXTENDEDBOLUS);
|
|
|
|
|
|
|
|
// add new command to queue
|
2017-11-20 23:39:12 +01:00
|
|
|
add(new CommandExtendedBolus(rateAfterConstraints, durationInMinutes, callback));
|
2017-11-10 00:27:18 +01:00
|
|
|
|
|
|
|
notifyAboutNewCommand();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns true if command is queued
|
|
|
|
public boolean cancelTempBasal(boolean enforceNew, Callback callback) {
|
2018-04-20 18:05:37 +02:00
|
|
|
if (!enforceNew && isRunning(Command.CommandType.TEMPBASAL)) {
|
2017-11-11 14:05:29 +01:00
|
|
|
if (callback != null)
|
|
|
|
callback.result(executingNowError()).run();
|
2017-11-10 00:27:18 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-11-11 14:05:29 +01:00
|
|
|
// remove all unfinished
|
2017-11-10 00:27:18 +01:00
|
|
|
removeAll(Command.CommandType.TEMPBASAL);
|
|
|
|
|
|
|
|
// add new command to queue
|
|
|
|
add(new CommandCancelTempBasal(enforceNew, callback));
|
|
|
|
|
|
|
|
notifyAboutNewCommand();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns true if command is queued
|
|
|
|
public boolean cancelExtended(Callback callback) {
|
2017-11-11 14:05:29 +01:00
|
|
|
if (isRunning(Command.CommandType.EXTENDEDBOLUS)) {
|
|
|
|
if (callback != null)
|
|
|
|
callback.result(executingNowError()).run();
|
2017-11-10 00:27:18 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-11-11 14:05:29 +01:00
|
|
|
// remove all unfinished
|
2017-11-10 00:27:18 +01:00
|
|
|
removeAll(Command.CommandType.EXTENDEDBOLUS);
|
|
|
|
|
|
|
|
// add new command to queue
|
|
|
|
add(new CommandCancelExtendedBolus(callback));
|
|
|
|
|
|
|
|
notifyAboutNewCommand();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns true if command is queued
|
|
|
|
public boolean setProfile(Profile profile, Callback callback) {
|
2018-04-05 10:02:57 +02:00
|
|
|
if (isThisProfileSet(profile)) {
|
2018-07-29 14:39:56 +02:00
|
|
|
if (L.isEnabled(L.PUMPQUEUE))
|
2018-07-27 12:17:29 +02:00
|
|
|
log.debug("Correct profile already set");
|
2018-04-05 10:02:57 +02:00
|
|
|
if (callback != null)
|
|
|
|
callback.result(new PumpEnactResult().success(true).enacted(false)).run();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-03-18 17:38:05 +01:00
|
|
|
if (!MainApp.isEngineeringModeOrRelease()) {
|
2018-05-02 13:46:38 +02:00
|
|
|
Notification notification = new Notification(Notification.NOT_ENG_MODE_OR_RELEASE, MainApp.gs(R.string.not_eng_mode_or_release), Notification.URGENT);
|
2019-10-01 00:00:22 +02:00
|
|
|
RxBus.INSTANCE.send(new EventNewNotification(notification));
|
2018-03-15 23:00:08 +01:00
|
|
|
if (callback != null)
|
2019-04-15 16:48:18 +02:00
|
|
|
callback.result(new PumpEnactResult().success(false).enacted(false).comment(MainApp.gs(R.string.not_eng_mode_or_release))).run();
|
2018-03-15 23:00:08 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-11-20 23:39:12 +01:00
|
|
|
// Compare with pump limits
|
2019-06-06 22:15:57 +02:00
|
|
|
Profile.ProfileValue[] basalValues = profile.getBasalValues();
|
2018-09-17 17:43:42 +02:00
|
|
|
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
|
2017-11-20 23:39:12 +01:00
|
|
|
|
2019-06-06 22:15:57 +02:00
|
|
|
for (Profile.ProfileValue basalValue : basalValues) {
|
2017-12-06 17:11:34 +01:00
|
|
|
if (basalValue.value < pump.getPumpDescription().basalMinimumRate) {
|
2018-05-02 13:46:38 +02:00
|
|
|
Notification notification = new Notification(Notification.BASAL_VALUE_BELOW_MINIMUM, MainApp.gs(R.string.basalvaluebelowminimum), Notification.URGENT);
|
2019-10-01 00:00:22 +02:00
|
|
|
RxBus.INSTANCE.send(new EventNewNotification(notification));
|
2017-11-20 23:39:12 +01:00
|
|
|
if (callback != null)
|
2019-04-15 16:48:18 +02:00
|
|
|
callback.result(new PumpEnactResult().success(false).enacted(false).comment(MainApp.gs(R.string.basalvaluebelowminimum))).run();
|
2017-11-20 23:39:12 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-01 00:00:22 +02:00
|
|
|
RxBus.INSTANCE.send(new EventDismissNotification(Notification.BASAL_VALUE_BELOW_MINIMUM));
|
2017-11-20 23:39:12 +01:00
|
|
|
|
|
|
|
// remove all unfinished
|
2017-11-10 00:27:18 +01:00
|
|
|
removeAll(Command.CommandType.BASALPROFILE);
|
|
|
|
|
|
|
|
// add new command to queue
|
|
|
|
add(new CommandSetProfile(profile, callback));
|
|
|
|
|
|
|
|
notifyAboutNewCommand();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-11-11 14:05:29 +01:00
|
|
|
// returns true if command is queued
|
|
|
|
public boolean readStatus(String reason, Callback callback) {
|
2018-01-14 21:42:36 +01:00
|
|
|
if (isLastScheduled(Command.CommandType.READSTATUS)) {
|
2018-07-29 14:39:56 +02:00
|
|
|
if (L.isEnabled(L.PUMPQUEUE))
|
2018-07-27 12:17:29 +02:00
|
|
|
log.debug("READSTATUS " + reason + " ignored as duplicated");
|
2018-01-14 21:42:36 +01:00
|
|
|
if (callback != null)
|
|
|
|
callback.result(executingNowError()).run();
|
|
|
|
return false;
|
|
|
|
}
|
2017-11-11 14:05:29 +01:00
|
|
|
|
|
|
|
// remove all unfinished
|
2017-12-20 20:45:21 +01:00
|
|
|
//removeAll(Command.CommandType.READSTATUS);
|
2017-11-11 14:05:29 +01:00
|
|
|
|
|
|
|
// add new command to queue
|
|
|
|
add(new CommandReadStatus(reason, callback));
|
|
|
|
|
|
|
|
notifyAboutNewCommand();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-03-30 19:36:50 +01:00
|
|
|
|
|
|
|
public synchronized boolean statusInQueue() {
|
|
|
|
if (isRunning(Command.CommandType.READSTATUS))
|
|
|
|
return true;
|
2019-10-08 09:52:55 +02:00
|
|
|
synchronized (queue) {
|
|
|
|
for (int i = 0; i < queue.size(); i++) {
|
|
|
|
if (queue.get(i).commandType == Command.CommandType.READSTATUS) {
|
|
|
|
return true;
|
|
|
|
}
|
2019-03-30 19:36:50 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-11-11 14:05:29 +01:00
|
|
|
// returns true if command is queued
|
|
|
|
public boolean loadHistory(byte type, Callback callback) {
|
|
|
|
if (isRunning(Command.CommandType.LOADHISTORY)) {
|
|
|
|
if (callback != null)
|
|
|
|
callback.result(executingNowError()).run();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove all unfinished
|
|
|
|
removeAll(Command.CommandType.LOADHISTORY);
|
|
|
|
|
|
|
|
// add new command to queue
|
|
|
|
add(new CommandLoadHistory(type, callback));
|
|
|
|
|
|
|
|
notifyAboutNewCommand();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-06-06 18:29:40 +02:00
|
|
|
// returns true if command is queued
|
2018-06-12 23:43:04 +02:00
|
|
|
public boolean setUserOptions(Callback callback) {
|
2018-06-06 18:29:40 +02:00
|
|
|
if (isRunning(Command.CommandType.SETUSERSETTINGS)) {
|
|
|
|
if (callback != null)
|
|
|
|
callback.result(executingNowError()).run();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove all unfinished
|
|
|
|
removeAll(Command.CommandType.SETUSERSETTINGS);
|
|
|
|
|
|
|
|
// add new command to queue
|
|
|
|
add(new CommandSetUserSettings(callback));
|
|
|
|
|
|
|
|
notifyAboutNewCommand();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-03-14 00:57:48 +01:00
|
|
|
// returns true if command is queued
|
|
|
|
public boolean loadTDDs(Callback callback) {
|
|
|
|
if (isRunning(Command.CommandType.LOADHISTORY)) {
|
|
|
|
if (callback != null)
|
|
|
|
callback.result(executingNowError()).run();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove all unfinished
|
|
|
|
removeAll(Command.CommandType.LOADHISTORY);
|
|
|
|
|
|
|
|
// add new command to queue
|
|
|
|
add(new CommandLoadTDDs(callback));
|
|
|
|
|
|
|
|
notifyAboutNewCommand();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-11-22 22:09:58 +01:00
|
|
|
// returns true if command is queued
|
|
|
|
public boolean loadEvents(Callback callback) {
|
|
|
|
if (isRunning(Command.CommandType.LOADEVENTS)) {
|
|
|
|
if (callback != null)
|
|
|
|
callback.result(executingNowError()).run();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove all unfinished
|
|
|
|
removeAll(Command.CommandType.LOADEVENTS);
|
|
|
|
|
|
|
|
// add new command to queue
|
|
|
|
add(new CommandLoadEvents(callback));
|
|
|
|
|
|
|
|
notifyAboutNewCommand();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-11-11 14:05:29 +01:00
|
|
|
public Spanned spannedStatus() {
|
2017-11-10 00:27:18 +01:00
|
|
|
String s = "";
|
2017-11-21 23:00:53 +01:00
|
|
|
int line = 0;
|
2019-10-08 09:52:55 +02:00
|
|
|
Command perf = performing;
|
|
|
|
if (perf != null) {
|
|
|
|
s += "<b>" + perf.status() + "</b>";
|
2017-11-21 23:00:53 +01:00
|
|
|
line++;
|
2017-11-10 00:27:18 +01:00
|
|
|
}
|
2019-10-08 09:52:55 +02:00
|
|
|
synchronized (queue) {
|
|
|
|
for (int i = 0; i < queue.size(); i++) {
|
|
|
|
if (line != 0)
|
|
|
|
s += "<br>";
|
|
|
|
s += queue.get(i).status();
|
|
|
|
line++;
|
|
|
|
}
|
2017-11-10 00:27:18 +01:00
|
|
|
}
|
|
|
|
return Html.fromHtml(s);
|
|
|
|
}
|
|
|
|
|
2017-11-20 23:39:12 +01:00
|
|
|
public boolean isThisProfileSet(Profile profile) {
|
2018-09-17 17:43:42 +02:00
|
|
|
PumpInterface activePump = ConfigBuilderPlugin.getPlugin().getActivePump();
|
2018-07-30 14:21:11 +02:00
|
|
|
Profile current = ProfileFunctions.getInstance().getProfile();
|
2018-03-17 08:12:07 +01:00
|
|
|
if (activePump != null && current != null) {
|
2017-11-20 23:39:12 +01:00
|
|
|
boolean result = activePump.isThisProfileSet(profile);
|
|
|
|
if (!result) {
|
2018-07-29 14:39:56 +02:00
|
|
|
if (L.isEnabled(L.PUMPQUEUE)) {
|
2018-07-27 12:17:29 +02:00
|
|
|
log.debug("Current profile: " + current.toString());
|
|
|
|
log.debug("New profile: " + profile.toString());
|
|
|
|
}
|
2017-11-20 23:39:12 +01:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
} else return true;
|
|
|
|
}
|
|
|
|
|
2018-01-14 21:42:36 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-10 00:27:18 +01:00
|
|
|
}
|