wip
This commit is contained in:
parent
cb438934b6
commit
fc60edc15a
5 changed files with 168 additions and 57 deletions
|
@ -161,7 +161,6 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
// TODO would it be useful to have a 'last error' field in the ui showing the most recent
|
||||
// failed command? the next command that runs successful with will override this error
|
||||
log.warn("Pump still in error state, but alarm raised recently, so not triggering again: " + localLastCmdResult.message);
|
||||
refreshDataFromPump("from Error Recovery");
|
||||
}
|
||||
}
|
||||
SystemClock.sleep(5 * 1000);
|
||||
|
@ -265,9 +264,8 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
return lastCmdResult != null ? new Date(lastCmdResult.completionTime) : new Date(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
CommandResult commandResult = runCommand("Syncing pump state", new CommandExecution() {
|
||||
private void initializePump() {
|
||||
CommandResult commandResult = runCommand("Checking pump history", false, new CommandExecution() {
|
||||
@Override
|
||||
public CommandResult execute() {
|
||||
return ruffyScripter.readHistory(
|
||||
|
@ -279,6 +277,12 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
}
|
||||
});
|
||||
|
||||
if (!commandResult.success || commandResult.history == null) {
|
||||
// TODO error case, command
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO opt, construct PumpHistoryRequest to requset only what needs updating
|
||||
boolean syncNeeded = false;
|
||||
|
||||
// last bolus
|
||||
|
@ -340,7 +344,7 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
// TODO check this is eithor called regularly even with other commansd being fired; if not,
|
||||
// request this periodically
|
||||
@Override
|
||||
public void refreshDataFromPump(String reason) {
|
||||
public synchronized void refreshDataFromPump(String reason) {
|
||||
log.debug("RefreshDataFromPump called");
|
||||
|
||||
// if Android is sluggish this might get called before ruffy is bound
|
||||
|
@ -356,13 +360,17 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
// if (notAUserRequest && wasRunAtLeastOnce && ranWithinTheLastMinute) {
|
||||
// log.debug("Not fetching state from pump, since we did already within the last 60 seconds");
|
||||
// } else {
|
||||
runCommand("Refreshing", new CommandExecution() {
|
||||
@Override
|
||||
public CommandResult execute() {
|
||||
return ruffyScripter.readHistory(new PumpHistoryRequest().reservoirLevel(true).bolusHistory(PumpHistoryRequest.LAST));
|
||||
}
|
||||
});
|
||||
// }
|
||||
|
||||
if (pump.lastCmdResult == null) {
|
||||
initializePump();
|
||||
} else {
|
||||
runCommand("Refreshing", new CommandExecution() {
|
||||
@Override
|
||||
public CommandResult execute() {
|
||||
return ruffyScripter.readHistory(new PumpHistoryRequest().reservoirLevel(true).bolusHistory(PumpHistoryRequest.LAST));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// TODO uses profile values for the time being
|
||||
|
@ -637,6 +645,11 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
}
|
||||
|
||||
private CommandResult runCommand(String status, CommandExecution commandExecution) {
|
||||
return runCommand(status, true, commandExecution);
|
||||
|
||||
}
|
||||
|
||||
private CommandResult runCommand(String status, boolean checkTbrMisMatch, CommandExecution commandExecution) {
|
||||
MainApp.bus().post(new EventComboPumpUpdateGUI(status));
|
||||
CommandResult commandResult = commandExecution.execute();
|
||||
|
||||
|
@ -654,7 +667,9 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
pump.state = commandResult.state;
|
||||
|
||||
// TODO are there cases when this check should NOT be performed? perform this explicitly or have a flag to skip this?
|
||||
checkForTbrMismatch();
|
||||
if (checkTbrMisMatch) {
|
||||
checkForTbrMismatch();
|
||||
}
|
||||
|
||||
|
||||
// TODO not propely set all the time ...
|
||||
|
@ -685,6 +700,10 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
// TODO check if this works with pump suspend, esp. around pump suspend there'll be syncing to do;
|
||||
|
||||
TemporaryBasal aapsTbr = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
|
||||
// if (true) {
|
||||
//
|
||||
// // not yet
|
||||
// } else
|
||||
if (aapsTbr == null && pump.state.tbrActive) {
|
||||
// pump runs TBR AAPS is unaware off
|
||||
// => fetch full history so the full TBR is added to treatments
|
||||
|
@ -723,7 +742,12 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
}
|
||||
|
||||
private void runFullSync() {
|
||||
CommandResult commandResult = runCommand("Syncing full pump history", new CommandExecution() {
|
||||
// TODO separate fetching and comparing
|
||||
if (1 == 1 ) {
|
||||
log.error("Skipping full sync - not implemented yet");
|
||||
return;
|
||||
}
|
||||
CommandResult commandResult = runCommand("Syncing full pump history", false, new CommandExecution() {
|
||||
@Override
|
||||
public CommandResult execute() {
|
||||
return ruffyScripter.readHistory(
|
||||
|
|
|
@ -16,6 +16,8 @@ public interface RuffyCommands {
|
|||
/** Confirms an active alarm on the pump. The state returned is the state after the alarm
|
||||
* has been confirmed. The message field contains the displayed error message that was
|
||||
* confirmed. */
|
||||
// TODO multiple alarms can occur -> empty battery, stops pump -> tbr cancelled
|
||||
// return them as history.errors?
|
||||
CommandResult takeOverAlarm();
|
||||
|
||||
boolean isPumpAvailable();
|
||||
|
|
|
@ -38,19 +38,19 @@ public class PumpHistory {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PumpHistory{" +
|
||||
"reservoirLevel=" + reservoirLevel +
|
||||
", bolusHistory=" + bolusHistory +
|
||||
", tbrHistory=" + tbrHistory +
|
||||
", errorHistory=" + errorHistory +
|
||||
", tddHistory=" + tddHistory +
|
||||
'}';
|
||||
}
|
||||
|
||||
public PumpHistory tddHistory(List<Tdd> tddHistory) {
|
||||
this.tddHistory = tddHistory;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PumpHistory{" +
|
||||
"reservoirLevel=" + reservoirLevel +
|
||||
", bolusHistory=" + bolusHistory.size() +
|
||||
", tbrHistory=" + tbrHistory.size() +
|
||||
", errorHistory=" + errorHistory.size() +
|
||||
", tddHistory=" + tddHistory.size() +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ public class RuffyScripter implements RuffyCommands {
|
|||
|
||||
private volatile long lastCmdExecutionTime;
|
||||
private volatile Command activeCmd = null;
|
||||
private volatile int retries = 0;
|
||||
|
||||
private boolean started = false;
|
||||
|
||||
|
@ -221,14 +222,14 @@ public class RuffyScripter implements RuffyCommands {
|
|||
public void returnToRootMenu() {
|
||||
// returning to main menu using the 'back' key does not cause a vibration
|
||||
while (getCurrentMenu().getType() != MenuType.MAIN_MENU && getCurrentMenu().getType() != MenuType.STOP) {
|
||||
if (getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) {
|
||||
String errorMsg = (String) getCurrentMenu().getAttribute(MenuAttribute.MESSAGE);
|
||||
confirmAlert(errorMsg, 1000);
|
||||
// TODO this isn't gonna work out ... this method can't know if something was enacted ...
|
||||
// gotta keep that state in the command instance
|
||||
throw new CommandException().success(false).enacted(false)
|
||||
.message("Warning/error " + errorMsg + " raised while returning to main menu");
|
||||
}
|
||||
// if (getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) {
|
||||
// String errorMsg = (String) getCurrentMenu().getAttribute(MenuAttribute.MESSAGE);
|
||||
// confirmAlert(errorMsg, 1000);
|
||||
// // TODO this isn't gonna work out ... this method can't know if something was enacted ...
|
||||
// // gotta keep that state in the command instance
|
||||
// throw new CommandException().success(false).enacted(false)
|
||||
// .message("Warning/error " + errorMsg + " raised while returning to main menu");
|
||||
// }
|
||||
log.debug("Going back to main menu, currently at " + getCurrentMenu().getType());
|
||||
pressBackKey();
|
||||
waitForMenuUpdate();
|
||||
|
@ -256,12 +257,12 @@ public class RuffyScripter implements RuffyCommands {
|
|||
synchronized (RuffyScripter.class) {
|
||||
try {
|
||||
activeCmd = cmd;
|
||||
retries = 3;
|
||||
long connectStart = System.currentTimeMillis();
|
||||
ensureConnected();
|
||||
final RuffyScripter scripter = this;
|
||||
final Returnable returnable = new Returnable();
|
||||
Thread cmdThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
class CommandRunner {
|
||||
public void run() {
|
||||
try {
|
||||
// check if pump is an an error state
|
||||
|
@ -315,6 +316,12 @@ public class RuffyScripter implements RuffyCommands {
|
|||
lastCmdExecutionTime = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
}
|
||||
Thread cmdThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
new CommandRunner().run();
|
||||
}
|
||||
}, cmd.toString());
|
||||
long executionStart = System.currentTimeMillis();
|
||||
cmdThread.start();
|
||||
|
@ -323,6 +330,7 @@ public class RuffyScripter implements RuffyCommands {
|
|||
// (to fail before the next loop iteration issues the next command)
|
||||
long dynamicTimeout = System.currentTimeMillis() + 90 * 1000;
|
||||
long overallTimeout = System.currentTimeMillis() + 4 * 60 * 1000;
|
||||
int retries = 3;
|
||||
while (cmdThread.isAlive()) {
|
||||
log.trace("Waiting for running command to complete");
|
||||
SystemClock.sleep(500);
|
||||
|
@ -341,6 +349,22 @@ public class RuffyScripter implements RuffyCommands {
|
|||
return new CommandResult().success(false).enacted(false).message("Command stalled, check pump!");
|
||||
}
|
||||
}
|
||||
if (!ruffyService.isConnected()) {
|
||||
if (retries > 0) {
|
||||
retries--;
|
||||
cmdThread.interrupt();
|
||||
reconnect();
|
||||
cmdThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
new CommandRunner().run();
|
||||
}
|
||||
}, cmd.toString());
|
||||
cmdThread.start();
|
||||
dynamicTimeout = System.currentTimeMillis() + 90 * 1000;
|
||||
overallTimeout = System.currentTimeMillis() + 4 * 60 * 1000;
|
||||
}
|
||||
}
|
||||
if (now > overallTimeout) {
|
||||
String msg = "Command " + cmd + " timed out after 4 min, check pump!";
|
||||
log.error(msg);
|
||||
|
@ -358,10 +382,21 @@ public class RuffyScripter implements RuffyCommands {
|
|||
log.debug("Command result: " + returnable.cmdResult);
|
||||
return returnable.cmdResult;
|
||||
} catch (CommandException e) {
|
||||
return e.toCommandResult();
|
||||
CommandResult commandResult = e.toCommandResult();
|
||||
if (commandResult.state == null) commandResult.state = readPumpStateInternal();
|
||||
return commandResult;
|
||||
} catch (Exception e) {
|
||||
// TODO catching E here AND in CommandRunner?
|
||||
// TODO detect and report pump warnings/errors differently?
|
||||
log.error("Error in ruffyscripter/ruffy", e);
|
||||
try {
|
||||
return new CommandResult()
|
||||
.exception(e)
|
||||
.message("Unexpected exception communication with ruffy: " + e.getMessage())
|
||||
.state(readPumpStateInternal());
|
||||
} catch (Exception e1) {
|
||||
// nothing more we can try
|
||||
}
|
||||
return new CommandResult().exception(e).message("Unexpected exception communication with ruffy: " + e.getMessage());
|
||||
} finally {
|
||||
activeCmd = null;
|
||||
|
@ -369,6 +404,37 @@ public class RuffyScripter implements RuffyCommands {
|
|||
}
|
||||
}
|
||||
|
||||
/** On connection lost the pump raises an error immediately (when setting a TBR or giving a bolus),
|
||||
* there's no timeout. But: a reconnect is still possible which can then confirm the alarm and
|
||||
* foward it to an app.*/
|
||||
public void reconnect() {
|
||||
// try {
|
||||
log.debug("Connection was lost, trying to reconnect");
|
||||
ensureConnected();
|
||||
if (getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) {
|
||||
String message = (String) getCurrentMenu().getAttribute(MenuAttribute.MESSAGE);
|
||||
if (activeCmd instanceof BolusCommand && message.equals("BOLUS CANCELLED")
|
||||
|| (activeCmd instanceof CancelTbrCommand || activeCmd instanceof SetTbrCommand)
|
||||
&& message.equals("TBR CANCELLED")) {
|
||||
// confirm alert
|
||||
verifyMenuIsDisplayed(MenuType.WARNING_OR_ERROR);
|
||||
pressCheckKey();
|
||||
// dismiss alert
|
||||
verifyMenuIsDisplayed(MenuType.WARNING_OR_ERROR);
|
||||
pressCheckKey();
|
||||
waitForMenuToBeLeft(MenuType.WARNING_OR_ERROR);
|
||||
// TODO multiple alarms can be raised, e.g. if pump enters STOP mode due
|
||||
// to battery_empty, that alert is raised and then causes a TBR CANCELLED
|
||||
// if one was running
|
||||
// TODO report those errors back!
|
||||
// ... need a more controlled way to 'assemble' return data
|
||||
// like adding a CommandResult field to a command and merge stuff into it?
|
||||
}
|
||||
|
||||
}
|
||||
returnToRootMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* If there's an issue, this times out eventually and throws a CommandException
|
||||
*/
|
||||
|
@ -405,7 +471,23 @@ public class RuffyScripter implements RuffyCommands {
|
|||
// if the user just pressed a button on the combo, the screen needs to time first
|
||||
// before a connection is possible. In that case, it takes 45s before the
|
||||
// connection comes up.
|
||||
waitForMenuUpdate(90, "Timeout connecting to pump");
|
||||
// waitForMenuUpdate(90, "Timeout connecting to pump");
|
||||
long timeoutExpired = System.currentTimeMillis() + 90 * 1000;
|
||||
long initialUpdateTime = menuLastUpdated;
|
||||
long again = System.currentTimeMillis() + 30 * 1000;
|
||||
while (initialUpdateTime == menuLastUpdated) {
|
||||
if (System.currentTimeMillis() > timeoutExpired) {
|
||||
throw new CommandException().message("Timeout connecting to pump");
|
||||
}
|
||||
SystemClock.sleep(50);
|
||||
if (again < System.currentTimeMillis()) {
|
||||
// TODO test
|
||||
ruffyService.doRTDisconnect();
|
||||
SystemClock.sleep(2000);
|
||||
ruffyService.doRTConnect();
|
||||
again = System.currentTimeMillis() + 30 * 1000;
|
||||
}
|
||||
}
|
||||
} catch (CommandException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
|
@ -527,7 +609,7 @@ public class RuffyScripter implements RuffyCommands {
|
|||
// @Override
|
||||
// public void doStep() {
|
||||
log.debug("Pressing up key");
|
||||
pressKey(Key.UP, 2000);
|
||||
pressKey(Key.UP);
|
||||
log.debug("Releasing up key");
|
||||
// }
|
||||
// });
|
||||
|
@ -535,25 +617,25 @@ public class RuffyScripter implements RuffyCommands {
|
|||
|
||||
public void pressDownKey() {
|
||||
log.debug("Pressing down key");
|
||||
pressKey(Key.DOWN, 2000);
|
||||
pressKey(Key.DOWN);
|
||||
log.debug("Releasing down key");
|
||||
}
|
||||
|
||||
public void pressCheckKey() {
|
||||
log.debug("Pressing check key");
|
||||
pressKey(Key.CHECK, 2000);
|
||||
pressKey(Key.CHECK);
|
||||
log.debug("Releasing check key");
|
||||
}
|
||||
|
||||
public void pressMenuKey() {
|
||||
log.debug("Pressing menu key");
|
||||
pressKey(Key.MENU, 2000);
|
||||
pressKey(Key.MENU);
|
||||
log.debug("Releasing menu key");
|
||||
}
|
||||
|
||||
public void pressBackKey() {
|
||||
log.debug("Pressing back key");
|
||||
pressKey(Key.BACK, 2000);
|
||||
pressKey(Key.BACK);
|
||||
log.debug("Releasing back key");
|
||||
}
|
||||
|
||||
|
@ -646,38 +728,36 @@ public class RuffyScripter implements RuffyCommands {
|
|||
}
|
||||
}
|
||||
|
||||
private void pressKey(final byte key, long timeout) {
|
||||
private void pressKey(final byte key) {
|
||||
try {
|
||||
ruffyService.rtSendKey(key, true);
|
||||
SystemClock.sleep(200);
|
||||
ruffyService.rtSendKey(Key.NO_KEY, true);
|
||||
// if (timeout > 0) {
|
||||
// synchronized (keylock) {
|
||||
// keylock.wait(timeout);
|
||||
// }
|
||||
// } else {
|
||||
// synchronized (keylock) {
|
||||
// keynotwait++;
|
||||
// }
|
||||
// }
|
||||
} catch (Exception e) {
|
||||
throw new CommandException().exception(e).message("Error while pressing buttons");
|
||||
}
|
||||
}
|
||||
|
||||
public void navigateToMenu(MenuType desiredMenu) {
|
||||
MenuType startedFrom = getCurrentMenu().getType();
|
||||
boolean movedOnce = false;
|
||||
// MenuType startedFrom = getCurrentMenu().getType();
|
||||
// boolean movedOnce = false;
|
||||
int retries = 20;
|
||||
while (getCurrentMenu().getType() != desiredMenu) {
|
||||
retries --;
|
||||
MenuType currentMenuType = getCurrentMenu().getType();
|
||||
log.debug("Navigating to menu " + desiredMenu + ", current menu: " + currentMenuType);
|
||||
if (movedOnce && currentMenuType == startedFrom) {
|
||||
// if (movedOnce && currentMenuType == startedFrom) {
|
||||
// throw new CommandException().message("Menu not found searching for " + desiredMenu
|
||||
// + ". Check menu settings on your pump to ensure it's not hidden.");
|
||||
// }
|
||||
if (retries == 0) {
|
||||
throw new CommandException().message("Menu not found searching for " + desiredMenu
|
||||
+ ". Check menu settings on your pump to ensure it's not hidden.");
|
||||
}
|
||||
pressMenuKey();
|
||||
waitForMenuToBeLeft(currentMenuType);
|
||||
movedOnce = true;
|
||||
// waitForMenuToBeLeft(currentMenuType);
|
||||
SystemClock.sleep(200);
|
||||
// movedOnce = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import android.bluetooth.BluetoothServerSocket;
|
|||
import android.bluetooth.BluetoothSocket;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -94,6 +95,10 @@ public class BTConnection {
|
|||
|
||||
public void connect(PumpData pumpData, int retries)
|
||||
{
|
||||
// if (pumpData == null) {
|
||||
// Log.e("JOE", "pumpdata null 1");
|
||||
// return;
|
||||
// }
|
||||
this.pumpData = pumpData;
|
||||
connect(pumpData.getPumpMac(),retries);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue