Merge branch 'bolus-progress' into rework
* bolus-progress: wip wip wip more more Remove TODOs for extended bolus. wip cancelling Initial take on bolus cancellation. Initial take on bolus progress reporting. Add alternative SetTbrCommand for pumps with different behaviour. Formatting.
This commit is contained in:
commit
4d2fa19ad4
12 changed files with 236 additions and 112 deletions
|
@ -1,5 +1,7 @@
|
||||||
package de.jotomo.ruffyscripter;
|
package de.jotomo.ruffyscripter;
|
||||||
|
|
||||||
/** The history data read from "My data" */
|
/**
|
||||||
|
* The history data read from "My data"
|
||||||
|
*/
|
||||||
public class History {
|
public class History {
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package de.jotomo.ruffyscripter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by adrian on 26/07/17.
|
* Created by adrian on 26/07/17.
|
||||||
*
|
* <p>
|
||||||
* Contains the capabilities of the current pump model.
|
* Contains the capabilities of the current pump model.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -11,11 +11,12 @@ public class PumpState {
|
||||||
public int tbrPercent = -1;
|
public int tbrPercent = -1;
|
||||||
public double tbrRate = -1;
|
public double tbrRate = -1;
|
||||||
public int tbrRemainingDuration = -1;
|
public int tbrRemainingDuration = -1;
|
||||||
/** This is the error message (if any) displayed by the pump if there is an alarm,
|
/**
|
||||||
e.g. if a "TBR cancelled alarm" is active, the value will be "TBR CANCELLED".
|
* This is the error message (if any) displayed by the pump if there is an alarm,
|
||||||
Generally, an error code is also displayed, but it flashes and it might take
|
* e.g. if a "TBR cancelled alarm" is active, the value will be "TBR CANCELLED".
|
||||||
longer to read that and the pump connection gets interrupted if we're not
|
* Generally, an error code is also displayed, but it flashes and it might take
|
||||||
reacting quickly.
|
* longer to read that and the pump connection gets interrupted if we're not
|
||||||
|
* reacting quickly.
|
||||||
*/
|
*/
|
||||||
public String errorMsg;
|
public String errorMsg;
|
||||||
public boolean suspended;
|
public boolean suspended;
|
||||||
|
|
|
@ -344,6 +344,7 @@ public class RuffyScripter {
|
||||||
} catch (CommandException e) {
|
} catch (CommandException e) {
|
||||||
return e.toCommandResult();
|
return e.toCommandResult();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
// TODO detect and report pump warnings/errors differently?
|
||||||
log.error("Error in ruffyscripter/ruffy", e);
|
log.error("Error in ruffyscripter/ruffy", e);
|
||||||
return new CommandResult().exception(e).message("Unexpected exception communication with ruffy: " + e.getMessage());
|
return new CommandResult().exception(e).message("Unexpected exception communication with ruffy: " + e.getMessage());
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -528,6 +529,26 @@ public class RuffyScripter {
|
||||||
log.debug("Releasing back key");
|
log.debug("Releasing back key");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void pressKeyMs(final byte key, long ms) {
|
||||||
|
long stepMs = 100;
|
||||||
|
try {
|
||||||
|
log.debug("Scroll: Pressing key for " + ms + " ms with step " + stepMs + " ms");
|
||||||
|
ruffyService.rtSendKey(key, true);
|
||||||
|
ruffyService.rtSendKey(key, false);
|
||||||
|
while (ms > stepMs) {
|
||||||
|
SystemClock.sleep(stepMs);
|
||||||
|
ruffyService.rtSendKey(key, false);
|
||||||
|
ms -= stepMs;
|
||||||
|
}
|
||||||
|
SystemClock.sleep(ms);
|
||||||
|
ruffyService.rtSendKey(Key.NO_KEY, true);
|
||||||
|
log.debug("Releasing key");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CommandException().exception(e).message("Error while pressing buttons");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean waitForScreenUpdate(long timeout) {
|
public boolean waitForScreenUpdate(long timeout) {
|
||||||
synchronized (screenlock) {
|
synchronized (screenlock) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -11,12 +11,23 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import de.jotomo.ruffyscripter.PumpState;
|
||||||
|
import de.jotomo.ruffyscripter.RuffyScripter;
|
||||||
|
|
||||||
|
import static de.jotomo.ruffyscripter.commands.BolusCommand.ProgressReportCallback.State.DELIVERING;
|
||||||
|
import static de.jotomo.ruffyscripter.commands.BolusCommand.ProgressReportCallback.State.STOPPED;
|
||||||
|
import static de.jotomo.ruffyscripter.commands.BolusCommand.ProgressReportCallback.State.STOPPING;
|
||||||
|
import static de.jotomo.ruffyscripter.commands.BolusCommand.ProgressReportCallback.State.DELIVERED;
|
||||||
|
|
||||||
public class BolusCommand extends BaseCommand {
|
public class BolusCommand extends BaseCommand {
|
||||||
private static final Logger log = LoggerFactory.getLogger(BolusCommand.class);
|
private static final Logger log = LoggerFactory.getLogger(BolusCommand.class);
|
||||||
|
|
||||||
private final double bolus;
|
private final double bolus;
|
||||||
|
private final ProgressReportCallback progressReportCallback;
|
||||||
|
private volatile boolean cancelRequested;
|
||||||
|
|
||||||
public BolusCommand(double bolus) {
|
public BolusCommand(double bolus, ProgressReportCallback progressReportCallback) {
|
||||||
|
this.progressReportCallback = progressReportCallback;
|
||||||
this.bolus = bolus;
|
this.bolus = bolus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,31 +45,103 @@ public class BolusCommand extends BaseCommand {
|
||||||
@Override
|
@Override
|
||||||
public CommandResult execute() {
|
public CommandResult execute() {
|
||||||
try {
|
try {
|
||||||
|
// TODO read reservoir level and reject request if reservoir < bolus
|
||||||
enterBolusMenu();
|
enterBolusMenu();
|
||||||
|
|
||||||
inputBolusAmount();
|
inputBolusAmount();
|
||||||
verifyDisplayedBolusAmount();
|
verifyDisplayedBolusAmount();
|
||||||
|
|
||||||
|
if (cancelRequested) {
|
||||||
|
progressReportCallback.report(STOPPING, 0, 0);
|
||||||
|
scripter.goToMainTypeScreen(MenuType.MAIN_MENU, 30 * 1000);
|
||||||
|
progressReportCallback.report(STOPPED, 0, 0);
|
||||||
|
return new CommandResult().success(true).enacted(false)
|
||||||
|
.message("Bolus cancelled as per user request with no insulin delivered");
|
||||||
|
}
|
||||||
|
|
||||||
// confirm bolus
|
// confirm bolus
|
||||||
scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER);
|
scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER);
|
||||||
scripter.pressCheckKey();
|
scripter.pressCheckKey();
|
||||||
|
|
||||||
// the pump displays the entered bolus and waits a bit to let user check and cancel
|
// the pump displays the entered bolus and waits a few seconds to let user check and cancel
|
||||||
scripter.waitForMenuToBeLeft(MenuType.BOLUS_ENTER);
|
while (scripter.getCurrentMenu().getType() == MenuType.BOLUS_ENTER) {
|
||||||
|
if (cancelRequested) {
|
||||||
|
progressReportCallback.report(STOPPING, 0, 0);
|
||||||
|
scripter.pressUpKey();
|
||||||
|
// wait up to 1s for a BOLUS_CANCELLED alert, if it doesn't happen we missed
|
||||||
|
// the window, simply continue and let the next cancel attempt try its luck
|
||||||
|
boolean alertWasCancelled = confirmAlert("BOLUS CANCELLED", 1000);
|
||||||
|
if (alertWasCancelled) {
|
||||||
|
progressReportCallback.report(STOPPED, 0, 0);
|
||||||
|
return new CommandResult().success(true).enacted(false)
|
||||||
|
.message("Bolus cancelled as per user request with no insulin delivered");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SystemClock.sleep(10);
|
||||||
|
}
|
||||||
scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU,
|
scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU,
|
||||||
"Pump did not return to MAIN_MEU from BOLUS_ENTER to deliver bolus. "
|
"Pump did not return to MAIN_MEU from BOLUS_ENTER to deliver bolus. "
|
||||||
+ "Check pump manually, the bolus might not have been delivered.");
|
+ "Check pump manually, the bolus might not have been delivered.");
|
||||||
|
|
||||||
|
progressReportCallback.report(DELIVERING, 0, 0);
|
||||||
|
Double bolusRemaining = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_REMAINING);
|
||||||
|
double lastBolusReported = 0;
|
||||||
|
boolean lowCartdrigeAlarmTriggered = false;
|
||||||
// wait for bolus delivery to complete; the remaining units to deliver are counted
|
// wait for bolus delivery to complete; the remaining units to deliver are counted
|
||||||
// down and are displayed on the main menu.
|
// down and are displayed on the main menu.
|
||||||
Double bolusRemaining = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_REMAINING);
|
// TODO extract into method
|
||||||
|
|
||||||
|
// TODO 'low cartrdige' alarm must be handled inside, since the bolus continues regardless;
|
||||||
|
// it must be claread so we can see the remaining bolus again;
|
||||||
while (bolusRemaining != null) {
|
while (bolusRemaining != null) {
|
||||||
log.debug("Delivering bolus, remaining: " + bolusRemaining);
|
if (cancelRequested) {
|
||||||
|
progressReportCallback.report(STOPPING, 0, 0);
|
||||||
|
scripter.pressKeyMs(RuffyScripter.Key.UP, 3000);
|
||||||
|
progressReportCallback.report(STOPPED, 0, 0);
|
||||||
|
// if the bolus finished while we attempted to cancel it, there'll be no alarm
|
||||||
|
long timeout = System.currentTimeMillis() + 2000;
|
||||||
|
while (scripter.getCurrentMenu().getType() != MenuType.WARNING_OR_ERROR && System.currentTimeMillis() < timeout) {
|
||||||
|
SystemClock.sleep(10);
|
||||||
|
}
|
||||||
|
while (scripter.getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) {
|
||||||
|
// TODO make this cleaner, extract method, needed below too
|
||||||
|
scripter.pressCheckKey();
|
||||||
SystemClock.sleep(200);
|
SystemClock.sleep(200);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (lastBolusReported != bolusRemaining) {
|
||||||
|
log.debug("Delivering bolus, remaining: " + bolusRemaining);
|
||||||
|
int percentDelivered = (int) (100 - (bolusRemaining / bolus * 100));
|
||||||
|
progressReportCallback.report(DELIVERING, percentDelivered, bolus - bolusRemaining);
|
||||||
|
lastBolusReported = bolusRemaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scripter.getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) {
|
||||||
|
String message = (String) scripter.getCurrentMenu().getAttribute(MenuAttribute.MESSAGE);
|
||||||
|
if (message.equals("LOW CARTRIDGE")) {
|
||||||
|
lowCartdrigeAlarmTriggered = true;
|
||||||
|
confirmAlert("LOW CARTRIDGE", 2000);
|
||||||
|
} else {
|
||||||
|
// any other alert
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SystemClock.sleep(50);
|
||||||
bolusRemaining = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_REMAINING);
|
bolusRemaining = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_REMAINING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wait up to 2s for any possible warning to be raised, if not raised already
|
||||||
|
long minWait = System.currentTimeMillis() + 2 * 1000;
|
||||||
|
while (scripter.getCurrentMenu().getType() != MenuType.WARNING_OR_ERROR || System.currentTimeMillis() < minWait) {
|
||||||
|
SystemClock.sleep(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
// process warnings (confirm them, report back to AAPS about them)
|
||||||
|
while (scripter.getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR || System.currentTimeMillis() < minWait) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
// TODO what if we hit 'cartridge low' alert here? is it immediately displayed or after the bolus?
|
// TODO what if we hit 'cartridge low' alert here? is it immediately displayed or after the bolus?
|
||||||
// TODO how are error states reported back to the caller that occur outside of calls in genal? Low battery, low cartridge?
|
// TODO how are error states reported back to the caller that occur outside of calls in genal? Low battery, low cartridge?
|
||||||
|
|
||||||
|
@ -67,6 +150,9 @@ public class BolusCommand extends BaseCommand {
|
||||||
"Bolus delivery did not complete as expected. "
|
"Bolus delivery did not complete as expected. "
|
||||||
+ "Check pump manually, the bolus might not have been delivered.");
|
+ "Check pump manually, the bolus might not have been delivered.");
|
||||||
|
|
||||||
|
|
||||||
|
// TODO report back what was read from history
|
||||||
|
|
||||||
// read last bolus record; those menus display static data and therefore
|
// read last bolus record; those menus display static data and therefore
|
||||||
// only a single menu update is sent
|
// only a single menu update is sent
|
||||||
scripter.navigateToMenu(MenuType.MY_DATA_MENU);
|
scripter.navigateToMenu(MenuType.MY_DATA_MENU);
|
||||||
|
@ -81,6 +167,8 @@ public class BolusCommand extends BaseCommand {
|
||||||
.message("Bolus was delivered, but unable to confirm it with history record");
|
.message("Bolus was delivered, but unable to confirm it with history record");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO check date so we don't pick a false record if the previous bolus had the same amount;
|
||||||
|
// also, report back partial bolus. Just call ReadHsstory(timestamp, boluses=true) cmd ...
|
||||||
double lastBolusInHistory = (double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS);
|
double lastBolusInHistory = (double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS);
|
||||||
if (Math.abs(bolus - lastBolusInHistory) > 0.05) {
|
if (Math.abs(bolus - lastBolusInHistory) > 0.05) {
|
||||||
throw new CommandException().success(false).enacted(true)
|
throw new CommandException().success(false).enacted(true)
|
||||||
|
@ -89,12 +177,13 @@ public class BolusCommand extends BaseCommand {
|
||||||
}
|
}
|
||||||
log.debug("Bolus record in history confirms delivered bolus");
|
log.debug("Bolus record in history confirms delivered bolus");
|
||||||
|
|
||||||
// leave menu to go back to main menu
|
if (!scripter.goToMainTypeScreen(MenuType.MAIN_MENU, 15 * 1000)) {
|
||||||
scripter.pressCheckKey();
|
throw new CommandException().success(false).enacted(true)
|
||||||
scripter.waitForMenuToBeLeft(MenuType.BOLUS_DATA);
|
.message("Bolus was correctly delivered and checked against history, but we "
|
||||||
scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU,
|
|
||||||
"Bolus was correctly delivered and checked against history, but we "
|
|
||||||
+ "did not return the main menu successfully.");
|
+ "did not return the main menu successfully.");
|
||||||
|
}
|
||||||
|
|
||||||
|
progressReportCallback.report(DELIVERED, 100, bolus);
|
||||||
|
|
||||||
return new CommandResult().success(true).enacted(true)
|
return new CommandResult().success(true).enacted(true)
|
||||||
.message(String.format(Locale.US, "Delivered %02.1f U", bolus));
|
.message(String.format(Locale.US, "Delivered %02.1f U", bolus));
|
||||||
|
@ -103,6 +192,13 @@ public class BolusCommand extends BaseCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO confirmAlarms? and report back which were cancelled?
|
||||||
|
|
||||||
|
private boolean confirmAlert(String alertText, int maxWaitTillExpectedAlert) {
|
||||||
|
// TODO
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void enterBolusMenu() {
|
private void enterBolusMenu() {
|
||||||
scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU);
|
scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU);
|
||||||
scripter.navigateToMenu(MenuType.BOLUS_MENU);
|
scripter.navigateToMenu(MenuType.BOLUS_MENU);
|
||||||
|
@ -150,4 +246,15 @@ public class BolusCommand extends BaseCommand {
|
||||||
"bolus=" + bolus +
|
"bolus=" + bolus +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ProgressReportCallback {
|
||||||
|
enum State {
|
||||||
|
DELIVERING,
|
||||||
|
DELIVERED,
|
||||||
|
STOPPING,
|
||||||
|
STOPPED
|
||||||
|
}
|
||||||
|
|
||||||
|
void report(State state, int percent, double delivered);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import de.jotomo.ruffyscripter.RuffyScripter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for all commands to be executed by the pump.
|
* Interface for all commands to be executed by the pump.
|
||||||
*
|
* <p>
|
||||||
* Note on cammond methods and timing: a method shall wait before and after executing
|
* Note on cammond methods and timing: a method shall wait before and after executing
|
||||||
* as necessary to not cause timing issues, so the caller can just call methods in
|
* as necessary to not cause timing issues, so the caller can just call methods in
|
||||||
* sequence, letting the methods take care of waits.
|
* sequence, letting the methods take care of waits.
|
||||||
|
|
|
@ -6,7 +6,8 @@ public class CommandException extends RuntimeException {
|
||||||
public Exception exception = null;
|
public Exception exception = null;
|
||||||
public String message = null;
|
public String message = null;
|
||||||
|
|
||||||
public CommandException() {}
|
public CommandException() {
|
||||||
|
}
|
||||||
|
|
||||||
public CommandException success(boolean success) {
|
public CommandException success(boolean success) {
|
||||||
this.success = success;
|
this.success = success;
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class CommandResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandResult completionTime(long completionTime) {
|
public CommandResult completionTime(long completionTime) {
|
||||||
this.completionTime = completionTime ;
|
this.completionTime = completionTime;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ public class GetBasalRateProfileCommand extends BaseCommand {
|
||||||
return violations;
|
return violations;
|
||||||
}
|
}
|
||||||
|
|
||||||
// private void tick()
|
// private void tick()
|
||||||
// {
|
// {
|
||||||
// switch (state)
|
// switch (state)
|
||||||
// {
|
// {
|
||||||
|
@ -103,15 +103,14 @@ public class GetBasalRateProfileCommand extends BaseCommand {
|
||||||
@Override
|
@Override
|
||||||
public CommandResult execute() {
|
public CommandResult execute() {
|
||||||
try {
|
try {
|
||||||
Map<Integer,Double> rate = new HashMap<>();
|
Map<Integer, Double> rate = new HashMap<>();
|
||||||
|
|
||||||
for(int i = 0; i < 24;i++)
|
for (int i = 0; i < 24; i++) {
|
||||||
{
|
Log.v("BASAL_RATE", "BASAL_RATE from " + String.format("%02d", i) + ":00 = " + rate.get(i));
|
||||||
Log.v("BASAL_RATE","BASAL_RATE from "+String.format("%02d",i)+":00 = "+rate.get(i));
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("failed to get basal",e);
|
log.error("failed to get basal", e);
|
||||||
return new CommandResult().success(false).message("failed to get basal: "+e.getMessage());
|
return new CommandResult().success(false).message("failed to get basal: " + e.getMessage());
|
||||||
}
|
}
|
||||||
return new CommandResult().success(true).enacted(true).message("Basal Rate was read");
|
return new CommandResult().success(true).enacted(true).message("Basal Rate was read");
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,6 +120,10 @@ public class SetTbrCommandAlt extends BaseCommand {
|
||||||
if (increasePercentage) scripter.pressUpKey();
|
if (increasePercentage) scripter.pressUpKey();
|
||||||
else scripter.pressDownKey();
|
else scripter.pressDownKey();
|
||||||
SystemClock.sleep(100);
|
SystemClock.sleep(100);
|
||||||
|
if (increasePercentage) scripter.pressUpKey();
|
||||||
|
else scripter.pressDownKey();
|
||||||
|
SystemClock.sleep(100);
|
||||||
|
log.debug("Push #" + (i + 1));
|
||||||
}
|
}
|
||||||
// Give the pump time to finish any scrolling that might still be going on, can take
|
// Give the pump time to finish any scrolling that might still be going on, can take
|
||||||
// up to 1100ms. Plus some extra time to be sure
|
// up to 1100ms. Plus some extra time to be sure
|
||||||
|
@ -269,7 +273,7 @@ public class SetTbrCommandAlt extends BaseCommand {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getClass().getSimpleName() + "{" +
|
return "SetTbrCommand{" +
|
||||||
"percentage=" + percentage +
|
"percentage=" + percentage +
|
||||||
", duration=" + duration +
|
", duration=" + duration +
|
||||||
'}';
|
'}';
|
||||||
|
|
|
@ -77,6 +77,9 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
||||||
|
|
||||||
private ComboPump pump = new ComboPump();
|
private ComboPump pump = new ComboPump();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private volatile BolusCommand runningBolusCommand;
|
||||||
|
|
||||||
private static PumpEnactResult OPERATION_NOT_SUPPORTED = new PumpEnactResult();
|
private static PumpEnactResult OPERATION_NOT_SUPPORTED = new PumpEnactResult();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
@ -97,7 +100,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
||||||
pumpDescription.isBolusCapable = true;
|
pumpDescription.isBolusCapable = true;
|
||||||
pumpDescription.bolusStep = 0.1d;
|
pumpDescription.bolusStep = 0.1d;
|
||||||
|
|
||||||
pumpDescription.isExtendedBolusCapable = false; // TODO GL#70
|
pumpDescription.isExtendedBolusCapable = false;
|
||||||
pumpDescription.extendedBolusStep = 0.1d;
|
pumpDescription.extendedBolusStep = 0.1d;
|
||||||
pumpDescription.extendedBolusDurationStep = 15;
|
pumpDescription.extendedBolusDurationStep = 15;
|
||||||
pumpDescription.extendedBolusMaxDuration = 12 * 60;
|
pumpDescription.extendedBolusMaxDuration = 12 * 60;
|
||||||
|
@ -127,7 +130,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
||||||
* The alerter frequently checks the result of the last executed command via the lastCmdResult
|
* The alerter frequently checks the result of the last executed command via the lastCmdResult
|
||||||
* field and shows a notification with sound and vibration if an error occurred.
|
* field and shows a notification with sound and vibration if an error occurred.
|
||||||
* More details on the error can then be looked up in the Combo tab.
|
* More details on the error can then be looked up in the Combo tab.
|
||||||
*
|
* <p>
|
||||||
* The alarm is re-raised every 5 minutes for as long as the error persist. As soon
|
* The alarm is re-raised every 5 minutes for as long as the error persist. As soon
|
||||||
* as a command succeeds no more new alerts are raised.
|
* as a command succeeds no more new alerts are raised.
|
||||||
*/
|
*/
|
||||||
|
@ -203,7 +206,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
keepUnbound=false;
|
keepUnbound = false;
|
||||||
ruffyScripter.start(IRuffyService.Stub.asInterface(service));
|
ruffyScripter.start(IRuffyService.Stub.asInterface(service));
|
||||||
log.debug("ruffy serivce connected");
|
log.debug("ruffy serivce connected");
|
||||||
}
|
}
|
||||||
|
@ -213,7 +216,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
||||||
log.debug("ruffy service disconnected");
|
log.debug("ruffy service disconnected");
|
||||||
// try to reconnect ruffy service unless unbind was explicitly requested
|
// try to reconnect ruffy service unless unbind was explicitly requested
|
||||||
// via unbindRuffyService
|
// via unbindRuffyService
|
||||||
if(!keepUnbound) {
|
if (!keepUnbound) {
|
||||||
SystemClock.sleep(250);
|
SystemClock.sleep(250);
|
||||||
bindRuffyService();
|
bindRuffyService();
|
||||||
}
|
}
|
||||||
|
@ -231,6 +234,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean keepUnbound = false;
|
private boolean keepUnbound = false;
|
||||||
|
|
||||||
private void unbindRuffyService() {
|
private void unbindRuffyService() {
|
||||||
keepUnbound = true;
|
keepUnbound = true;
|
||||||
ruffyScripter.unbind();
|
ruffyScripter.unbind();
|
||||||
|
@ -363,20 +367,64 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
||||||
return basal;
|
return basal;
|
||||||
}
|
}
|
||||||
|
|
||||||
// what a mess: pump integration code reading carb info from Detailed**Bolus**Info,
|
private static BolusCommand.ProgressReportCallback bolusProgressReportCallback = new BolusCommand.ProgressReportCallback() {
|
||||||
// writing carb treatments to the history table. What's PumpEnactResult for again?
|
@Override
|
||||||
|
public void report(BolusCommand.ProgressReportCallback.State state, int percent, double delivered) {
|
||||||
|
EventOverviewBolusProgress enent = EventOverviewBolusProgress.getInstance();
|
||||||
|
switch (state) {
|
||||||
|
case DELIVERING:
|
||||||
|
enent.status = String.format(MainApp.sResources.getString(R.string.bolusdelivering), delivered);
|
||||||
|
break;
|
||||||
|
case DELIVERED:
|
||||||
|
enent.status = String.format(MainApp.sResources.getString(R.string.bolusdelivered), delivered);
|
||||||
|
break;
|
||||||
|
case STOPPING:
|
||||||
|
enent.status = MainApp.sResources.getString(R.string.bolusstopping);
|
||||||
|
break;
|
||||||
|
case STOPPED:
|
||||||
|
enent.status = MainApp.sResources.getString(R.string.bolusstopped);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
enent.percent = percent;
|
||||||
|
MainApp.bus().post(enent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Updates Treatment records with carbs and boluses and delivers a bolus if needed */
|
||||||
@Override
|
@Override
|
||||||
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
|
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
|
||||||
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
|
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
|
||||||
if (detailedBolusInfo.insulin > 0) {
|
if (detailedBolusInfo.insulin > 0) {
|
||||||
// bolus needed, ask pump to deliver it
|
// bolus needed, ask pump to deliver it
|
||||||
if (!Config.comboSplitBoluses) {
|
|
||||||
return deliverBolus(detailedBolusInfo);
|
// TODO read history to ensure there are no boluses delivered on the pump we aren't
|
||||||
|
// aware of and haven't included in the bolus calulation
|
||||||
|
|
||||||
|
// Note that the BolusCommand sends progress updates to the bolusProgressReporterCallback,
|
||||||
|
// which then posts appropriate events on the bus, so in this branch no posts are needed
|
||||||
|
runningBolusCommand = new BolusCommand(detailedBolusInfo.insulin, bolusProgressReportCallback);
|
||||||
|
CommandResult bolusCmdResult = runCommand(runningBolusCommand);
|
||||||
|
runningBolusCommand = null;
|
||||||
|
PumpEnactResult pumpEnactResult = new PumpEnactResult();
|
||||||
|
pumpEnactResult.success = bolusCmdResult.success;
|
||||||
|
pumpEnactResult.enacted = bolusCmdResult.enacted;
|
||||||
|
pumpEnactResult.comment = bolusCmdResult.message;
|
||||||
|
|
||||||
|
// if enacted by pump, add bolus and carbs to treatment history
|
||||||
|
if (pumpEnactResult.enacted) {
|
||||||
|
pumpEnactResult.bolusDelivered = detailedBolusInfo.insulin;
|
||||||
|
pumpEnactResult.carbsDelivered = detailedBolusInfo.carbs;
|
||||||
|
|
||||||
|
detailedBolusInfo.date = bolusCmdResult.completionTime;
|
||||||
|
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
|
||||||
} else {
|
} else {
|
||||||
return deliverSplittedBolus(detailedBolusInfo);
|
pumpEnactResult.bolusDelivered = 0d;
|
||||||
|
pumpEnactResult.carbsDelivered = 0d;
|
||||||
}
|
}
|
||||||
|
return pumpEnactResult;
|
||||||
} else {
|
} else {
|
||||||
// no bolus required, carb only treatment
|
// no bolus required, carb only treatment
|
||||||
|
SystemClock.sleep(6000);
|
||||||
PumpEnactResult pumpEnactResult = new PumpEnactResult();
|
PumpEnactResult pumpEnactResult = new PumpEnactResult();
|
||||||
pumpEnactResult.success = true;
|
pumpEnactResult.success = true;
|
||||||
pumpEnactResult.enacted = true;
|
pumpEnactResult.enacted = true;
|
||||||
|
@ -403,60 +451,10 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@Override
|
||||||
private PumpEnactResult deliverBolus(DetailedBolusInfo detailedBolusInfo) {
|
public void stopBolusDelivering() {
|
||||||
CommandResult bolusCmdResult = runCommand(new BolusCommand(detailedBolusInfo.insulin));
|
BolusCommand localRunningBolusCommand = runningBolusCommand;
|
||||||
PumpEnactResult pumpEnactResult = new PumpEnactResult();
|
if (localRunningBolusCommand != null) localRunningBolusCommand.requestCancellation();
|
||||||
pumpEnactResult.success = bolusCmdResult.success;
|
|
||||||
pumpEnactResult.enacted = bolusCmdResult.enacted;
|
|
||||||
pumpEnactResult.comment = bolusCmdResult.message;
|
|
||||||
|
|
||||||
// if enacted, add bolus and carbs to treatment history
|
|
||||||
if (pumpEnactResult.enacted) {
|
|
||||||
// TODO if no error occurred, the requested bolus is what the pump delievered,
|
|
||||||
// that has been checked. If an error occurred, we should check how much insulin
|
|
||||||
// was delivered, e.g. when the cartridge went empty mid-bolus
|
|
||||||
// For the first iteration, the alert the pump raises must suffice
|
|
||||||
pumpEnactResult.bolusDelivered = detailedBolusInfo.insulin;
|
|
||||||
pumpEnactResult.carbsDelivered = detailedBolusInfo.carbs;
|
|
||||||
|
|
||||||
detailedBolusInfo.date = bolusCmdResult.completionTime;
|
|
||||||
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
|
|
||||||
} else {
|
|
||||||
pumpEnactResult.bolusDelivered = 0d;
|
|
||||||
pumpEnactResult.carbsDelivered = 0d;
|
|
||||||
}
|
|
||||||
return pumpEnactResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private PumpEnactResult deliverSplittedBolus(DetailedBolusInfo detailedBolusInfo) {
|
|
||||||
// split up bolus into 2 U parts
|
|
||||||
PumpEnactResult pumpEnactResult = new PumpEnactResult();
|
|
||||||
pumpEnactResult.success = true;
|
|
||||||
pumpEnactResult.enacted = true;
|
|
||||||
pumpEnactResult.bolusDelivered = 0d;
|
|
||||||
pumpEnactResult.carbsDelivered = detailedBolusInfo.carbs;
|
|
||||||
pumpEnactResult.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
|
||||||
|
|
||||||
double remainingBolus = detailedBolusInfo.insulin;
|
|
||||||
int split = 1;
|
|
||||||
while (remainingBolus > 0.05) {
|
|
||||||
double bolus = remainingBolus > 2 ? 2 : remainingBolus;
|
|
||||||
DetailedBolusInfo bolusInfo = new DetailedBolusInfo();
|
|
||||||
bolusInfo.insulin = bolus;
|
|
||||||
bolusInfo.isValid = false;
|
|
||||||
log.debug("Delivering split bolus #" + split + " with " + bolus + " U");
|
|
||||||
PumpEnactResult bolusResult = deliverBolus(bolusInfo);
|
|
||||||
if (!bolusResult.success) {
|
|
||||||
return bolusResult;
|
|
||||||
}
|
|
||||||
pumpEnactResult.bolusDelivered += bolus;
|
|
||||||
remainingBolus -= 2;
|
|
||||||
split++;
|
|
||||||
}
|
|
||||||
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
|
|
||||||
return pumpEnactResult;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CommandResult runCommand(Command command) {
|
private CommandResult runCommand(Command command) {
|
||||||
|
@ -492,13 +490,6 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
||||||
return commandResult;
|
return commandResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopBolusDelivering() {
|
|
||||||
// there's no way to stop the combo once delivery has started
|
|
||||||
// but before that, we could interrupt the command thread ... pause
|
|
||||||
// till pump times out or raises an error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: AAPS calls this only to enact OpenAPS recommendations
|
// Note: AAPS calls this only to enact OpenAPS recommendations
|
||||||
@Override
|
@Override
|
||||||
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force) {
|
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force) {
|
||||||
|
@ -528,10 +519,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
||||||
adjustedPercent = rounded.intValue();
|
adjustedPercent = rounded.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
Command cmd = !Config.comboUseAlternateSetTbrCommand
|
CommandResult commandResult = runCommand(new SetTbrCommand(adjustedPercent, durationInMinutes));
|
||||||
? new SetTbrCommand(adjustedPercent, durationInMinutes)
|
|
||||||
: new SetTbrCommandAlt(adjustedPercent, durationInMinutes);
|
|
||||||
CommandResult commandResult = runCommand(cmd);
|
|
||||||
|
|
||||||
if (commandResult.enacted) {
|
if (commandResult.enacted) {
|
||||||
TemporaryBasal tempStart = new TemporaryBasal(commandResult.completionTime);
|
TemporaryBasal tempStart = new TemporaryBasal(commandResult.completionTime);
|
||||||
|
@ -585,7 +573,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
||||||
tempBasal.source = Source.USER;
|
tempBasal.source = Source.USER;
|
||||||
pumpEnactResult.isTempCancel = true;
|
pumpEnactResult.isTempCancel = true;
|
||||||
}
|
}
|
||||||
} else if ((activeTemp.percentRate >= 90 && activeTemp.percentRate <= 110) && activeTemp.getPlannedRemainingMinutes() <= 15 ) {
|
} else if ((activeTemp.percentRate >= 90 && activeTemp.percentRate <= 110) && activeTemp.getPlannedRemainingMinutes() <= 15) {
|
||||||
// Let fake neutral temp keep running (see below)
|
// Let fake neutral temp keep running (see below)
|
||||||
log.debug("cancelTempBasal: skipping changing tbr since it already is at " + activeTemp.percentRate + "% and running for another " + activeTemp.getPlannedRemainingMinutes() + " mins.");
|
log.debug("cancelTempBasal: skipping changing tbr since it already is at " + activeTemp.percentRate + "% and running for another " + activeTemp.getPlannedRemainingMinutes() + " mins.");
|
||||||
pumpEnactResult.comment = "cancelTempBasal skipping changing tbr since it already is at " + activeTemp.percentRate + "% and running for another " + activeTemp.getPlannedRemainingMinutes() + " mins.";
|
pumpEnactResult.comment = "cancelTempBasal skipping changing tbr since it already is at " + activeTemp.percentRate + "% and running for another " + activeTemp.getPlannedRemainingMinutes() + " mins.";
|
||||||
|
@ -598,7 +586,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
||||||
} else {
|
} else {
|
||||||
// Set a fake neutral temp to avoid TBR cancel alert. Decide 90% vs 110% based on
|
// Set a fake neutral temp to avoid TBR cancel alert. Decide 90% vs 110% based on
|
||||||
// on whether the TBR we're cancelling is above or below 100%.
|
// on whether the TBR we're cancelling is above or below 100%.
|
||||||
long percentage = (activeTemp.percentRate > 100) ? 110:90;
|
long percentage = (activeTemp.percentRate > 100) ? 110 : 90;
|
||||||
log.debug("cancelTempBasal: changing tbr to " + percentage + "% for 15 mins.");
|
log.debug("cancelTempBasal: changing tbr to " + percentage + "% for 15 mins.");
|
||||||
commandResult = runCommand(new SetTbrCommand(percentage, 15));
|
commandResult = runCommand(new SetTbrCommand(percentage, 15));
|
||||||
if (commandResult.enacted) {
|
if (commandResult.enacted) {
|
||||||
|
@ -623,7 +611,6 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
||||||
return pumpEnactResult;
|
return pumpEnactResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
|
||||||
@Override
|
@Override
|
||||||
public PumpEnactResult cancelExtendedBolus() {
|
public PumpEnactResult cancelExtendedBolus() {
|
||||||
return OPERATION_NOT_SUPPORTED;
|
return OPERATION_NOT_SUPPORTED;
|
||||||
|
@ -713,12 +700,12 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
||||||
ToastUtils.showToastInUiThread(MainApp.instance(), "Ruffy not initialized.");
|
ToastUtils.showToastInUiThread(MainApp.instance(), "Ruffy not initialized.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isBusy()){
|
if (isBusy()) {
|
||||||
ToastUtils.showToastInUiThread(MainApp.instance(), "Pump busy!");
|
ToastUtils.showToastInUiThread(MainApp.instance(), "Pump busy!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CommandResult result = runCommand(new DetermineCapabilitiesCommand());
|
CommandResult result = runCommand(new DetermineCapabilitiesCommand());
|
||||||
if (result.success){
|
if (result.success) {
|
||||||
pumpDescription.maxTempPercent = (int) result.capabilities.maxTempPercent;
|
pumpDescription.maxTempPercent = (int) result.capabilities.maxTempPercent;
|
||||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance());
|
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance());
|
||||||
SharedPreferences.Editor editor = preferences.edit();
|
SharedPreferences.Editor editor = preferences.edit();
|
||||||
|
|
|
@ -704,5 +704,7 @@
|
||||||
<string name="activate_profile">ACTIVATE PROFILE</string>
|
<string name="activate_profile">ACTIVATE PROFILE</string>
|
||||||
<string name="date">Date</string>
|
<string name="date">Date</string>
|
||||||
<string name="invalid">INVALID</string>
|
<string name="invalid">INVALID</string>
|
||||||
|
<string name="bolusstopping">Stopping bolus delivery</string>
|
||||||
|
<string name="bolusstopped">Bolus delivery stopped</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue