Merge branch 'tbrDurationFix' into 'develop'
Tbr duration fix See merge request !16
This commit is contained in:
commit
6732d4ff75
|
@ -44,7 +44,7 @@ android {
|
|||
minSdkVersion 21
|
||||
targetSdkVersion 23
|
||||
versionCode 1500
|
||||
version "1.5g"
|
||||
version "1.5g-combo-dev"
|
||||
buildConfigField "String", "VERSION", '"' + version + '"'
|
||||
buildConfigField "String", "BUILDVERSION", generateGitBuild()
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ public class RuffyScripterInstrumentedTest {
|
|||
|
||||
private static Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
private static ServiceConnection mRuffyServiceConnection;
|
||||
private static RuffyScripter ruffyScripter;
|
||||
private static RuffyScripter ruffyScripter = new RuffyScripter();
|
||||
|
||||
@BeforeClass
|
||||
public static void bindRuffy() {
|
||||
|
@ -64,7 +64,7 @@ public class RuffyScripterInstrumentedTest {
|
|||
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
ruffyScripter = new RuffyScripter(IRuffyService.Stub.asInterface(service));
|
||||
ruffyScripter.start(IRuffyService.Stub.asInterface(service));
|
||||
log.debug("ruffy serivce connected");
|
||||
}
|
||||
|
||||
|
|
|
@ -10,12 +10,17 @@ interface IRTHandler {
|
|||
void fail(String message);
|
||||
|
||||
void requestBluetooth();
|
||||
boolean canDisconnect();
|
||||
void rtStopped();
|
||||
void rtStarted();
|
||||
|
||||
void rtClearDisplay();
|
||||
void rtUpdateDisplay(in byte[] quarter, int which);
|
||||
|
||||
void rtDisplayHandleMenu(in Menu menu);
|
||||
void rtDisplayHandleNoMenu();
|
||||
void rtDisplayHandleMenu(in Menu menu, in int sequence);
|
||||
void rtDisplayHandleNoMenu(in int sequence);
|
||||
|
||||
void keySent(in int sequence);
|
||||
|
||||
String getServiceIdentifier();
|
||||
}
|
||||
|
|
|
@ -13,10 +13,10 @@ interface IRuffyService {
|
|||
*
|
||||
* @return 0 if successful, -1 otherwise
|
||||
*/
|
||||
int doRTConnect();
|
||||
int doRTConnect(IRTHandler handler);
|
||||
|
||||
/** Disconnect from the pump */
|
||||
void doRTDisconnect();
|
||||
void doRTDisconnect(IRTHandler handler);
|
||||
|
||||
/*What's the meaning of 'changed'?
|
||||
* changed means if a button state has been changed, like btton pressed is a change and button release another*/
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package de.jotomo.ruffyscripter;
|
||||
|
||||
import android.os.DeadObjectException;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
|
||||
|
@ -35,7 +34,7 @@ public class RuffyScripter {
|
|||
private static final Logger log = LoggerFactory.getLogger(RuffyScripter.class);
|
||||
|
||||
|
||||
private final IRuffyService ruffyService;
|
||||
private IRuffyService ruffyService;
|
||||
private final long connectionTimeOutMs = 5000;
|
||||
private String unrecoverableError = null;
|
||||
|
||||
|
@ -50,27 +49,48 @@ public class RuffyScripter {
|
|||
|
||||
private boolean started = false;
|
||||
|
||||
public RuffyScripter(final IRuffyService ruffyService) {
|
||||
this.ruffyService = ruffyService;
|
||||
private final Object keylock = new Object();
|
||||
private int keynotwait = 0;
|
||||
|
||||
private final Object screenlock = new Object();
|
||||
|
||||
public RuffyScripter() {
|
||||
|
||||
}
|
||||
|
||||
public void start() {
|
||||
public void start(IRuffyService newService) {
|
||||
try {
|
||||
ruffyService.addHandler(mHandler);
|
||||
if (ruffyService != null) {
|
||||
try {
|
||||
ruffyService.removeHandler(mHandler);
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
if (newService != null) {
|
||||
this.ruffyService = newService;
|
||||
// TODO this'll be done better in v2 via ConnectionManager
|
||||
if (idleDisconnectMonitorThread.getState() == Thread.State.NEW) {
|
||||
idleDisconnectMonitorThread.start();
|
||||
}
|
||||
started = true;
|
||||
} catch (RemoteException e) {
|
||||
newService.addHandler(mHandler);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (started) {
|
||||
try {
|
||||
started = false;
|
||||
// TODO ruffy removes dead handlers automatically by now.
|
||||
// still, check this when going through recovery logic
|
||||
/* try {
|
||||
ruffyService.removeHandler(mHandler);
|
||||
} catch (RemoteException e) {
|
||||
log.warn("Removing IRTHandler from Ruffy service failed, ignoring", e);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,6 +98,7 @@ public class RuffyScripter {
|
|||
return started;
|
||||
}
|
||||
|
||||
private boolean canDisconnect = false;
|
||||
private Thread idleDisconnectMonitorThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -91,20 +112,22 @@ public class RuffyScripter {
|
|||
&& now > lastDisconnect + 15 * 1000) {
|
||||
log.debug("Disconnecting after " + (connectionTimeOutMs / 1000) + "s inactivity timeout");
|
||||
lastDisconnect = now;
|
||||
ruffyService.doRTDisconnect();
|
||||
canDisconnect = true;
|
||||
ruffyService.doRTDisconnect(mHandler);
|
||||
connected = false;
|
||||
lastDisconnect = System.currentTimeMillis();
|
||||
// don't attempt anything fancy in the next 10s, let the pump settle
|
||||
SystemClock.sleep(10 * 1000);
|
||||
} else {
|
||||
canDisconnect = false;
|
||||
}
|
||||
} catch (DeadObjectException doe) {
|
||||
} catch (Exception e) {
|
||||
// TODO do we need to catch this exception somewhere else too? right now it's
|
||||
// converted into a command failure, but it's not classified as unrecoverable;
|
||||
// eventually we might try to recover ... check docs, there's also another
|
||||
// execption we should watch interacting with a remote service.
|
||||
// SecurityException was the other, when there's an AIDL mismatch;
|
||||
unrecoverableError = "Ruffy service went away";
|
||||
} catch (RemoteException e) {
|
||||
//unrecoverableError = "Ruffy service went away";
|
||||
log.debug("Exception in idle disconnect monitor thread, carrying on", e);
|
||||
}
|
||||
SystemClock.sleep(1000);
|
||||
|
@ -128,6 +151,11 @@ public class RuffyScripter {
|
|||
log.trace("Ruffy invoked requestBluetooth callback");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDisconnect() throws RemoteException {
|
||||
return canDisconnect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rtStopped() throws RemoteException {
|
||||
log.debug("rtStopped callback invoked");
|
||||
|
@ -150,13 +178,19 @@ public class RuffyScripter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void rtDisplayHandleMenu(Menu menu) throws RemoteException {
|
||||
public void rtDisplayHandleMenu(Menu menu, int sequence) throws RemoteException {
|
||||
// method is called every ~500ms
|
||||
log.debug("rtDisplayHandleMenu: " + menu.getType());
|
||||
log.debug("rtDisplayHandleMenu: " + menu);
|
||||
|
||||
currentMenu = menu;
|
||||
menuLastUpdated = System.currentTimeMillis();
|
||||
|
||||
synchronized (screenlock) {
|
||||
screenlock.notifyAll();
|
||||
}
|
||||
|
||||
// TODO v2 switch to using IRuffyService.isConnected, rather than guessing connectivity state
|
||||
// passed on screen updates
|
||||
connected = true;
|
||||
|
||||
// note that a WARNING_OR_ERROR menu can be a valid temporary state (cancelling TBR)
|
||||
|
@ -167,16 +201,42 @@ public class RuffyScripter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void rtDisplayHandleNoMenu() throws RemoteException {
|
||||
public void rtDisplayHandleNoMenu(int sequence) throws RemoteException {
|
||||
log.debug("rtDisplayHandleNoMenu callback invoked");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void keySent(int sequence) throws RemoteException {
|
||||
synchronized (keylock) {
|
||||
if (keynotwait > 0)
|
||||
keynotwait--;
|
||||
else
|
||||
keylock.notify();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceIdentifier() throws RemoteException {
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public boolean isPumpBusy() {
|
||||
return activeCmd != null;
|
||||
}
|
||||
|
||||
public void unbind() {
|
||||
if (ruffyService != null)
|
||||
try {
|
||||
ruffyService.removeHandler(mHandler);
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
this.ruffyService = null;
|
||||
}
|
||||
|
||||
private static class Returnable {
|
||||
CommandResult cmdResult;
|
||||
}
|
||||
|
@ -304,7 +364,9 @@ public class RuffyScripter {
|
|||
}
|
||||
}
|
||||
|
||||
/** If there's an issue, this times out eventually and throws a CommandException */
|
||||
/**
|
||||
* If there's an issue, this times out eventually and throws a CommandException
|
||||
*/
|
||||
private void ensureConnected() {
|
||||
try {
|
||||
boolean menuUpdateRecentlyReceived = currentMenu != null && menuLastUpdated + 1000 > System.currentTimeMillis();
|
||||
|
@ -324,7 +386,8 @@ public class RuffyScripter {
|
|||
SystemClock.sleep(10 * 1000);
|
||||
}
|
||||
|
||||
boolean connectInitSuccessful = ruffyService.doRTConnect() == 0;
|
||||
canDisconnect = false;
|
||||
boolean connectInitSuccessful = ruffyService.doRTConnect(mHandler) == 0;
|
||||
log.debug("Connect init successful: " + connectInitSuccessful);
|
||||
log.debug("Waiting for first menu update to be sent");
|
||||
// Note: there was an 'if(currentMenu == null)' around the next call, since
|
||||
|
@ -337,7 +400,7 @@ public class RuffyScripter {
|
|||
// before a connection is possible. In that case, it takes 45s before the
|
||||
// connection comes up.
|
||||
waitForMenuUpdate(90);
|
||||
} catch (RemoteException e) {
|
||||
} catch (Exception e) {
|
||||
throw new CommandException().exception(e).message("Unexpected exception while initiating/restoring pump connection");
|
||||
}
|
||||
}
|
||||
|
@ -347,42 +410,98 @@ public class RuffyScripter {
|
|||
// so this class can focus on providing a connection to run commands
|
||||
// (or maybe reconsider putting it into a base class)
|
||||
|
||||
private static class Key {
|
||||
static byte NO_KEY = (byte) 0x00;
|
||||
static byte MENU = (byte) 0x03;
|
||||
static byte CHECK = (byte) 0x0C;
|
||||
static byte UP = (byte) 0x30;
|
||||
static byte DOWN = (byte) 0xC0;
|
||||
public static class Key {
|
||||
public static byte NO_KEY = (byte) 0x00;
|
||||
public static byte MENU = (byte) 0x03;
|
||||
public static byte CHECK = (byte) 0x0C;
|
||||
public static byte UP = (byte) 0x30;
|
||||
public static byte DOWN = (byte) 0xC0;
|
||||
public static byte BACK = (byte) 0x33;
|
||||
}
|
||||
|
||||
public void pressUpKey() {
|
||||
log.debug("Pressing up key");
|
||||
pressKey(Key.UP);
|
||||
pressKey(Key.UP, 2000);
|
||||
log.debug("Releasing up key");
|
||||
}
|
||||
|
||||
public void pressDownKey() {
|
||||
log.debug("Pressing down key");
|
||||
pressKey(Key.DOWN);
|
||||
pressKey(Key.DOWN, 2000);
|
||||
log.debug("Releasing down key");
|
||||
}
|
||||
|
||||
public void pressCheckKey() {
|
||||
log.debug("Pressing check key");
|
||||
pressKey(Key.CHECK);
|
||||
pressKey(Key.CHECK, 2000);
|
||||
log.debug("Releasing check key");
|
||||
}
|
||||
|
||||
public void pressMenuKey() {
|
||||
log.debug("Pressing menu key");
|
||||
pressKey(Key.MENU);
|
||||
pressKey(Key.MENU, 2000);
|
||||
log.debug("Releasing menu key");
|
||||
}
|
||||
|
||||
public void pressBackKey() {
|
||||
log.debug("Pressing back key");
|
||||
pressKey(Key.BACK, 2000);
|
||||
log.debug("Releasing back key");
|
||||
}
|
||||
|
||||
public boolean waitForScreenUpdate(long timeout) {
|
||||
synchronized (screenlock) {
|
||||
try {
|
||||
screenlock.wait(timeout);
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean goToMainTypeScreen(MenuType screen, long timeout) {
|
||||
long start = System.currentTimeMillis();
|
||||
while ((currentMenu == null || currentMenu.getType() != screen) && start + timeout > System.currentTimeMillis()) {
|
||||
if (currentMenu != null && currentMenu.getType() == MenuType.WARNING_OR_ERROR) {
|
||||
throw new CommandException().message("Warning/errors raised by pump, please check pump");
|
||||
// since warnings and errors can occur at any time, they should be dealt with in
|
||||
// a more general way, see the handleMenuUpdate callback above
|
||||
//FIXME bad thing to do :D
|
||||
// yup, commenting this out since I don't want an occlusionn alert to hidden by this :-)
|
||||
//pressCheckKey();
|
||||
} else if (currentMenu != null && !currentMenu.getType().isMaintype()) {
|
||||
pressBackKey();
|
||||
} else
|
||||
pressMenuKey();
|
||||
waitForScreenUpdate(250);
|
||||
}
|
||||
return currentMenu != null && currentMenu.getType() == screen;
|
||||
}
|
||||
|
||||
public boolean enterMenu(MenuType startType, MenuType targetType, byte key, long timeout) {
|
||||
if (currentMenu.getType() == targetType)
|
||||
return true;
|
||||
if (currentMenu == null || currentMenu.getType() != startType)
|
||||
return false;
|
||||
long start = System.currentTimeMillis();
|
||||
pressKey(key, 2000);
|
||||
while ((currentMenu == null || currentMenu.getType() != targetType) && start + timeout > System.currentTimeMillis()) {
|
||||
waitForScreenUpdate(100);
|
||||
}
|
||||
return currentMenu != null && currentMenu.getType() == targetType;
|
||||
}
|
||||
|
||||
public void step(int steps, byte key, long timeout) {
|
||||
for (int i = 0; i < Math.abs(steps); i++)
|
||||
pressKey(key, timeout);
|
||||
}
|
||||
|
||||
// TODO v2, rework these two methods: waitForMenuUpdate shoud only be used by commands
|
||||
// then anything longer than a few seconds is an error;
|
||||
// only ensureConnected() uses the method with the timeout parameter; inline that code,
|
||||
// so we can use a custom timeout and give a better error message in case of failure
|
||||
|
||||
/**
|
||||
* Wait until the menu update is in
|
||||
*/
|
||||
|
@ -401,12 +520,21 @@ public class RuffyScripter {
|
|||
}
|
||||
}
|
||||
|
||||
private void pressKey(final byte key) {
|
||||
private void pressKey(final byte key, long timeout) {
|
||||
try {
|
||||
ruffyService.rtSendKey(key, true);
|
||||
SystemClock.sleep(100);
|
||||
//SystemClock.sleep(200);
|
||||
ruffyService.rtSendKey(Key.NO_KEY, true);
|
||||
} catch (RemoteException e) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
package de.jotomo.ruffyscripter.commands;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import de.jotomo.ruffyscripter.PumpState;
|
||||
import de.jotomo.ruffyscripter.RuffyScripter;
|
||||
|
||||
public class GetBasalCommand implements Command {
|
||||
private static final Logger log = LoggerFactory.getLogger(GetBasalCommand.class);
|
||||
|
||||
private RuffyScripter scripter;
|
||||
|
||||
public GetBasalCommand() {}
|
||||
|
||||
@Override
|
||||
public List<String> validateArguments() {
|
||||
List<String> violations = new ArrayList<>();
|
||||
|
||||
return violations;
|
||||
}
|
||||
|
||||
// private void tick()
|
||||
// {
|
||||
// switch (state)
|
||||
// {
|
||||
// case BEFORE:
|
||||
// if(scripter.currentMenu!=null && scripter.currentMenu.getType()==MenuType.MAIN_MENU)
|
||||
// {
|
||||
// updateState(MAIN,120);
|
||||
// lastMenu = MenuType.MAIN_MENU;
|
||||
// log.debug("found MAIN_MENU -> state:MAIN");
|
||||
// retries=3;
|
||||
// }
|
||||
// break;
|
||||
// case MAIN:
|
||||
// if(retries>0)
|
||||
// if(scripter.goToMainTypeScreen(MenuType.BASAL_1_MENU,30000))
|
||||
// {
|
||||
// if(scripter.enterMenu(MenuType.BASAL_1_MENU,MenuType.BASAL_TOTAL, RuffyScripter.Key.CHECK,2000))
|
||||
// {
|
||||
// updateState(BASAL_OVERVIEW, 30);
|
||||
// retries=0;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// retries--;
|
||||
// else
|
||||
// updateState(ERROR,30);
|
||||
// break;
|
||||
// case BASAL_OVERVIEW:
|
||||
// if(scripter.currentMenu.getType()==MenuType.BASAL_TOTAL && scripter.currentMenu.getAttribute(MenuAttribute.BASAL_TOTAL)!=null && (Integer)scripter.currentMenu.getAttribute(MenuAttribute.BASAL_SELECTED)==1)
|
||||
// {
|
||||
// basalTotal = (Double)scripter.currentMenu.getAttribute(MenuAttribute.BASAL_TOTAL);
|
||||
// if(scripter.enterMenu(MenuType.BASAL_TOTAL,MenuType.BASAL_SET, RuffyScripter.Key.MENU,3000))
|
||||
// {
|
||||
// updateState(READ_BASAL,30);
|
||||
// retries = 96;
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// case READ_BASAL:
|
||||
// if(scripter.currentMenu.getType()==MenuType.BASAL_SET && scripter.currentMenu.getAttribute(MenuAttribute.BASAL_START)!=null) {
|
||||
// Object rateObj = scripter.currentMenu.getAttribute(MenuAttribute.BASAL_RATE);
|
||||
// MenuTime time = (MenuTime) scripter.currentMenu.getAttribute(MenuAttribute.BASAL_START);
|
||||
// if (rateObj instanceof Double) {
|
||||
// rate.put(time.getHour(), (Double) rateObj);
|
||||
// }
|
||||
// boolean complete = true;
|
||||
// for (int t = 0; t < 24; t++) {
|
||||
// if (rate.get(t) == null)
|
||||
// complete = false;
|
||||
// }
|
||||
// if (retries > 0) {
|
||||
// if (complete) {
|
||||
// scripter.pressBackKey();
|
||||
// updateState(AFTER, 30);
|
||||
// } else {
|
||||
// retries--;
|
||||
// scripter.pressMenuKey();
|
||||
// scripter.waitForScreenUpdate(250);
|
||||
// }
|
||||
// } else {
|
||||
// updateState(ERROR, 30);
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// case ERROR:
|
||||
// case AFTER:
|
||||
// scripter.goToMainMenuScreen(MenuType.MAIN_MENU,2000);
|
||||
// synchronized(GetBasalCommand.this) {
|
||||
// GetBasalCommand.this.notify();
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
@Override
|
||||
public CommandResult execute(RuffyScripter scripter, PumpState initialPumpState) {
|
||||
try {
|
||||
Map<Integer,Double> rate = new HashMap<>();
|
||||
|
||||
for(int i = 0; i < 24;i++)
|
||||
{
|
||||
Log.v("BASAL_RATE","BASAL_RATE from "+String.format("%02d",i)+":00 = "+rate.get(i));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("failed to get basal",e);
|
||||
return new CommandResult().success(false).message("failed to get basal: "+e.getMessage());
|
||||
}
|
||||
return new CommandResult().success(true).enacted(true).message("Basal Rate was read");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GetTbrCommand{}";
|
||||
}
|
||||
}
|
|
@ -15,6 +15,12 @@ import java.util.Locale;
|
|||
import de.jotomo.ruffyscripter.PumpState;
|
||||
import de.jotomo.ruffyscripter.RuffyScripter;
|
||||
|
||||
import static org.monkey.d.ruffy.ruffy.driver.display.MenuType.MAIN_MENU;
|
||||
import static org.monkey.d.ruffy.ruffy.driver.display.MenuType.TBR_DURATION;
|
||||
import static org.monkey.d.ruffy.ruffy.driver.display.MenuType.TBR_MENU;
|
||||
import static org.monkey.d.ruffy.ruffy.driver.display.MenuType.TBR_SET;
|
||||
import static org.monkey.d.ruffy.ruffy.driver.display.MenuType.WARNING_OR_ERROR;
|
||||
|
||||
public class SetTbrCommand implements Command {
|
||||
private static final Logger log = LoggerFactory.getLogger(SetTbrCommand.class);
|
||||
|
||||
|
@ -56,239 +62,205 @@ public class SetTbrCommand implements Command {
|
|||
@Override
|
||||
public CommandResult execute(RuffyScripter scripter, PumpState initialPumpState) {
|
||||
try {
|
||||
enterTbrMenu(scripter);
|
||||
inputTbrPercentage(scripter);
|
||||
verifyDisplayedTbrPercentage(scripter);
|
||||
|
||||
if (percentage == 100) {
|
||||
cancelTbrAndConfirmCancellationWarning(scripter);
|
||||
} else {
|
||||
// switch to TBR_DURATION menu by pressing menu key
|
||||
scripter.verifyMenuIsDisplayed(MenuType.TBR_SET);
|
||||
scripter.pressMenuKey();
|
||||
scripter.waitForMenuUpdate();
|
||||
scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION);
|
||||
|
||||
inputTbrDuration(scripter);
|
||||
verifyDisplayedTbrDuration(scripter);
|
||||
|
||||
// confirm TBR
|
||||
scripter.pressCheckKey();
|
||||
scripter.waitForMenuToBeLeft(MenuType.TBR_DURATION);
|
||||
log.debug("1. going from " + scripter.currentMenu + " to TBR_MENU");
|
||||
int retries = 5;
|
||||
while (!scripter.goToMainTypeScreen(TBR_MENU, 3000)) {
|
||||
retries--;
|
||||
if (retries == 0)
|
||||
throw new CommandException().message("not able to find TBR_MENU: stuck in " + scripter.currentMenu);
|
||||
SystemClock.sleep(500);
|
||||
if (scripter.currentMenu.getType() == TBR_MENU)
|
||||
break;
|
||||
}
|
||||
|
||||
scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU,
|
||||
"Pump did not return to MAIN_MEU after setting TBR. " +
|
||||
"Check pump manually, the TBR might not have been set/cancelled.");
|
||||
if (scripter.currentMenu.getType() != TBR_MENU)
|
||||
throw new CommandException().message("not able to find TBR_MENU: stuck in " + scripter.currentMenu);
|
||||
|
||||
log.debug("2. entering " + scripter.currentMenu);
|
||||
retries = 5;
|
||||
while (!scripter.enterMenu(TBR_MENU, MenuType.TBR_SET, RuffyScripter.Key.CHECK, 2000)) {
|
||||
retries--;
|
||||
if (retries == 0)
|
||||
throw new CommandException().message("not able to find TBR_SET: stuck in " + scripter.currentMenu);
|
||||
SystemClock.sleep(500);
|
||||
if (scripter.currentMenu.getType() == TBR_SET)
|
||||
break;
|
||||
if (scripter.currentMenu.getType() == TBR_DURATION) {
|
||||
scripter.pressMenuKey();
|
||||
scripter.waitForScreenUpdate(1000);
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("SetTbrCommand: 3. getting/setting basal percentage in " + scripter.currentMenu);
|
||||
retries = 30;
|
||||
|
||||
double currentPercentage = -100;
|
||||
while (currentPercentage != percentage && retries >= 0) {
|
||||
retries--;
|
||||
Object percentageObj = scripter.currentMenu.getAttribute(MenuAttribute.BASAL_RATE);
|
||||
|
||||
if (percentageObj != null && (percentageObj instanceof Double)) {
|
||||
currentPercentage = ((Double) percentageObj).doubleValue();
|
||||
|
||||
if (currentPercentage != percentage) {
|
||||
int requestedPercentage = (int) percentage;
|
||||
int actualPercentage = (int) currentPercentage;
|
||||
int steps = (requestedPercentage - actualPercentage) / 10;
|
||||
log.debug("Adjusting basal(" + requestedPercentage + "/" + actualPercentage + ") with " + steps + " steps and " + retries + " retries left");
|
||||
scripter.step(steps, (steps < 0 ? RuffyScripter.Key.DOWN : RuffyScripter.Key.UP), 500);
|
||||
scripter.waitForScreenUpdate(1000);
|
||||
}
|
||||
|
||||
// check main menu shows the same values we just set
|
||||
if (percentage == 100) {
|
||||
verifyMainMenuShowsNoActiveTbr(scripter);
|
||||
return new CommandResult().success(true).enacted(true).message("TBR was cancelled");
|
||||
} else {
|
||||
verifyMainMenuShowsExpectedTbrActive(scripter);
|
||||
currentPercentage = -100;
|
||||
}
|
||||
scripter.waitForScreenUpdate(1000);
|
||||
}
|
||||
if (currentPercentage < 0 || retries < 0)
|
||||
throw new CommandException().message("unable to set basal percentage");
|
||||
|
||||
log.debug("4. checking basal percentage in " + scripter.currentMenu);
|
||||
scripter.waitForScreenUpdate(1000);
|
||||
currentPercentage = -1000;
|
||||
retries = 10;
|
||||
while (currentPercentage < 0 && retries >= 0) {
|
||||
retries--;
|
||||
Object percentageObj = scripter.currentMenu.getAttribute(MenuAttribute.BASAL_RATE);
|
||||
|
||||
if (percentageObj != null && (percentageObj instanceof Double)) {
|
||||
currentPercentage = ((Double) percentageObj).doubleValue();
|
||||
} else {
|
||||
scripter.waitForScreenUpdate(1000);
|
||||
}
|
||||
}
|
||||
|
||||
if (retries < 0 || currentPercentage != percentage)
|
||||
throw new CommandException().message("Unable to set percentage. Requested: " + percentage + ", value displayed on pump: " + currentPercentage);
|
||||
|
||||
if (currentPercentage != 100) {
|
||||
log.debug("5. change to TBR_DURATION from " + scripter.currentMenu);
|
||||
retries = 5;
|
||||
while (retries >= 0 && !scripter.enterMenu(TBR_SET, MenuType.TBR_DURATION, RuffyScripter.Key.MENU, 2000)) {
|
||||
retries--;
|
||||
if (retries == 0)
|
||||
throw new CommandException().message("not able to find TBR_SET: stuck in " + scripter.currentMenu);
|
||||
SystemClock.sleep(500);
|
||||
if (scripter.currentMenu.getType() == TBR_DURATION)
|
||||
break;
|
||||
if (scripter.currentMenu.getType() == TBR_SET) {
|
||||
scripter.pressMenuKey();
|
||||
scripter.waitForScreenUpdate(1000);
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("6. getting/setting duration in " + scripter.currentMenu);
|
||||
retries = 30;
|
||||
|
||||
double currentDuration = -100;
|
||||
while (currentDuration != duration && retries >= 0) {
|
||||
retries--;
|
||||
Object durationObj = scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME);
|
||||
log.debug("Requested time: " + duration + " actual time: " + durationObj);
|
||||
if (durationObj != null && durationObj instanceof MenuTime) {
|
||||
MenuTime time = (MenuTime) durationObj;
|
||||
currentDuration = (time.getHour() * 60) + time.getMinute();
|
||||
if (currentDuration != duration) {
|
||||
int requestedDuration = (int) duration;
|
||||
int actualDuration = (int) currentDuration;
|
||||
int steps = (requestedDuration - actualDuration) / 15;
|
||||
if (currentDuration + (steps * 15) < requestedDuration)
|
||||
steps++;
|
||||
else if (currentDuration + (steps * 15) > requestedDuration)
|
||||
steps--;
|
||||
log.debug("Adjusting duration(" + requestedDuration + "/" + actualDuration + ") with " + steps + " steps and " + retries + " retries left");
|
||||
scripter.step(steps, (steps > 0 ? RuffyScripter.Key.UP : RuffyScripter.Key.DOWN), 500);
|
||||
scripter.waitForScreenUpdate(1000);
|
||||
}
|
||||
}
|
||||
scripter.waitForScreenUpdate(1000);
|
||||
}
|
||||
if (currentDuration < 0 || retries < 0)
|
||||
throw new CommandException().message("unable to set duration, requested:" + duration + ", displayed on pump: " + currentDuration);
|
||||
|
||||
log.debug("7. checking duration in " + scripter.currentMenu);
|
||||
scripter.waitForScreenUpdate(1000);
|
||||
currentDuration = -1000;
|
||||
retries = 10;
|
||||
while (currentDuration < 0 && retries >= 0) {
|
||||
retries--;
|
||||
Object durationObj = scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME);
|
||||
|
||||
if (durationObj != null && durationObj instanceof MenuTime) {
|
||||
MenuTime time = (MenuTime) durationObj;
|
||||
currentDuration = (time.getHour() * 60) + time.getMinute();
|
||||
} else
|
||||
scripter.waitForScreenUpdate(1000);
|
||||
}
|
||||
if (retries < 0 || currentDuration != duration)
|
||||
throw new CommandException().message("wrong duration! Requested: " + duration + ", displayed on pump: " + currentDuration);
|
||||
}
|
||||
|
||||
log.debug("8. confirming TBR om " + scripter.currentMenu);
|
||||
retries = 5;
|
||||
while (retries >= 0 && (scripter.currentMenu.getType() == TBR_DURATION || scripter.currentMenu.getType() == TBR_SET)) {
|
||||
retries--;
|
||||
scripter.pressCheckKey();
|
||||
scripter.waitForScreenUpdate(1000);
|
||||
}
|
||||
if (retries < 0 || scripter.currentMenu.getType() == TBR_DURATION || scripter.currentMenu.getType() == TBR_SET)
|
||||
throw new CommandException().message("failed setting basal!");
|
||||
retries = 10;
|
||||
boolean cancelledError = true;
|
||||
if (percentage == 100)
|
||||
cancelledError = false;
|
||||
while (retries >= 0 && scripter.currentMenu.getType() != MAIN_MENU) {
|
||||
// TODO how probable is it, that a totally unrelated error (like occlusion alert)
|
||||
// is raised at this point, which we'd cancel together with the TBR cancelled alert?
|
||||
if (percentage == 100 && scripter.currentMenu.getType() == WARNING_OR_ERROR) {
|
||||
scripter.pressCheckKey();
|
||||
retries++;
|
||||
cancelledError = true;
|
||||
scripter.waitForScreenUpdate(1000);
|
||||
} else {
|
||||
retries--;
|
||||
if (scripter.currentMenu.getType() == MAIN_MENU && cancelledError)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("9. verifying the main menu display the TBR we just set/cancelled");
|
||||
if (retries < 0 || scripter.currentMenu.getType() != MAIN_MENU)
|
||||
throw new CommandException().message("failed going to main!");
|
||||
|
||||
Object percentageObj = scripter.currentMenu.getAttribute(MenuAttribute.TBR);
|
||||
Object durationObj = scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME);
|
||||
|
||||
if (percentage == 100) {
|
||||
if (percentageObj != null || durationObj != null)
|
||||
throw new CommandException().message("TBR cancelled, but main menu shows a running TBR");
|
||||
|
||||
return new CommandResult().success(true).enacted(true).message("TBR was cancelled");
|
||||
}
|
||||
|
||||
if (percentageObj == null || !(percentageObj instanceof Double))
|
||||
throw new CommandException().message("not percentage");
|
||||
|
||||
if (((double) percentageObj) != percentage)
|
||||
throw new CommandException().message("wrong percentage set!");
|
||||
|
||||
if (durationObj == null || !(durationObj instanceof MenuTime))
|
||||
throw new CommandException().message("not time");
|
||||
|
||||
MenuTime t = (MenuTime) durationObj;
|
||||
if (t.getMinute() + (60 * t.getHour()) > duration || t.getMinute() + (60 * t.getHour()) < duration - 5)
|
||||
throw new CommandException().message("wrong time set!");
|
||||
|
||||
|
||||
return new CommandResult().success(true).enacted(true).message(
|
||||
String.format(Locale.US, "TBR set to %d%% for %d min", percentage, duration));
|
||||
}
|
||||
|
||||
} catch (CommandException e) {
|
||||
return e.toCommandResult();
|
||||
}
|
||||
}
|
||||
|
||||
private void enterTbrMenu(RuffyScripter scripter) {
|
||||
scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU);
|
||||
scripter.navigateToMenu(MenuType.TBR_MENU);
|
||||
scripter.verifyMenuIsDisplayed(MenuType.TBR_MENU);
|
||||
scripter.pressCheckKey();
|
||||
scripter.waitForMenuUpdate();
|
||||
scripter.verifyMenuIsDisplayed(MenuType.TBR_SET);
|
||||
}
|
||||
|
||||
private void inputTbrPercentage(RuffyScripter scripter) {
|
||||
scripter.verifyMenuIsDisplayed(MenuType.TBR_SET);
|
||||
long currentPercent = readDisplayedTbrPercentage(scripter);
|
||||
log.debug("Current TBR %: " + currentPercent);
|
||||
long percentageChange = percentage - currentPercent;
|
||||
long percentageSteps = percentageChange / 10;
|
||||
boolean increasePercentage = true;
|
||||
if (percentageSteps < 0) {
|
||||
increasePercentage = false;
|
||||
percentageSteps = Math.abs(percentageSteps);
|
||||
}
|
||||
log.debug("Pressing " + (increasePercentage ? "up" : "down") + " " + percentageSteps + " times");
|
||||
for (int i = 0; i < percentageSteps; i++) {
|
||||
scripter.verifyMenuIsDisplayed(MenuType.TBR_SET);
|
||||
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
|
||||
// up to 1100ms. Plus some extra time to be sure
|
||||
SystemClock.sleep(2000);
|
||||
}
|
||||
|
||||
private void verifyDisplayedTbrPercentage(RuffyScripter scripter) {
|
||||
scripter.verifyMenuIsDisplayed(MenuType.TBR_SET);
|
||||
long displayedPercentage = readDisplayedTbrPercentage(scripter);
|
||||
if (displayedPercentage != percentage) {
|
||||
log.debug("Final displayed TBR percentage: " + displayedPercentage);
|
||||
throw new CommandException().message("Failed to set TBR percentage");
|
||||
}
|
||||
|
||||
// check again to ensure the displayed value hasn't change due to due scrolling taking extremely long
|
||||
SystemClock.sleep(2000);
|
||||
long refreshedDisplayedTbrPecentage = readDisplayedTbrPercentage(scripter);
|
||||
if (displayedPercentage != refreshedDisplayedTbrPecentage) {
|
||||
throw new CommandException().message("Failed to set TBR percentage: " +
|
||||
"percentage changed after input stopped from "
|
||||
+ displayedPercentage + " -> " + refreshedDisplayedTbrPecentage);
|
||||
}
|
||||
}
|
||||
|
||||
private long readDisplayedTbrPercentage(RuffyScripter scripter) {
|
||||
// TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded
|
||||
Object percentageObj = scripter.currentMenu.getAttribute(MenuAttribute.BASAL_RATE);
|
||||
// this as a bit hacky, the display value is blinking, so we might catch that, so
|
||||
// keep trying till we get the Double we want
|
||||
while (!(percentageObj instanceof Double)) {
|
||||
scripter.waitForMenuUpdate();
|
||||
percentageObj = scripter.currentMenu.getAttribute(MenuAttribute.BASAL_RATE);
|
||||
}
|
||||
return ((Double) percentageObj).longValue();
|
||||
}
|
||||
|
||||
private void inputTbrDuration(RuffyScripter scripter) {
|
||||
scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION);
|
||||
long currentDuration = readDisplayedTbrDuration(scripter);
|
||||
if (currentDuration % 15 != 0) {
|
||||
// The duration displayed is how long an active TBR will still run,
|
||||
// which might be something like 0:13, hence not in 15 minute steps.
|
||||
// Pressing up will go to the next higher 15 minute step.
|
||||
// Don't press down, from 0:13 it can't go down, so press up.
|
||||
// Pressing up from 23:59 works to go to 24:00.
|
||||
scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION);
|
||||
scripter.pressUpKey();
|
||||
scripter.waitForMenuUpdate();
|
||||
currentDuration = readDisplayedTbrDuration(scripter);
|
||||
}
|
||||
log.debug("Current TBR duration: " + currentDuration);
|
||||
long durationChange = duration - currentDuration;
|
||||
long durationSteps = durationChange / 15;
|
||||
boolean increaseDuration = true;
|
||||
if (durationSteps < 0) {
|
||||
increaseDuration = false;
|
||||
durationSteps = Math.abs(durationSteps);
|
||||
}
|
||||
log.debug("Pressing " + (increaseDuration ? "up" : "down") + " " + durationSteps + " times");
|
||||
for (int i = 0; i < durationSteps; i++) {
|
||||
scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION);
|
||||
if (increaseDuration) 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
|
||||
// up to 1100ms. Plus some extra time to be sure
|
||||
SystemClock.sleep(2000);
|
||||
}
|
||||
|
||||
private void verifyDisplayedTbrDuration(RuffyScripter scripter) {
|
||||
scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION);
|
||||
long displayedDuration = readDisplayedTbrDuration(scripter);
|
||||
if (displayedDuration != duration) {
|
||||
log.debug("Final displayed TBR duration: " + displayedDuration);
|
||||
throw new CommandException().message("Failed to set TBR duration");
|
||||
}
|
||||
|
||||
// check again to ensure the displayed value hasn't change due to due scrolling taking extremely long
|
||||
SystemClock.sleep(2000);
|
||||
long refreshedDisplayedTbrDuration = readDisplayedTbrDuration(scripter);
|
||||
if (displayedDuration != refreshedDisplayedTbrDuration) {
|
||||
throw new CommandException().message("Failed to set TBR duration: " +
|
||||
"duration changed after input stopped from "
|
||||
+ displayedDuration + " -> " + refreshedDisplayedTbrDuration);
|
||||
}
|
||||
}
|
||||
|
||||
private long readDisplayedTbrDuration(RuffyScripter scripter) {
|
||||
// TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded
|
||||
scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION);
|
||||
Object durationObj = scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME);
|
||||
// this as a bit hacky, the display value is blinking, so we might catch that, so
|
||||
// keep trying till we get the Double we want
|
||||
while (!(durationObj instanceof MenuTime)) {
|
||||
scripter.waitForMenuUpdate();
|
||||
durationObj = scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME);
|
||||
}
|
||||
MenuTime duration = (MenuTime) durationObj;
|
||||
return duration.getHour() * 60 + duration.getMinute();
|
||||
}
|
||||
|
||||
private void cancelTbrAndConfirmCancellationWarning(RuffyScripter scripter) {
|
||||
// confirm entered TBR
|
||||
scripter.verifyMenuIsDisplayed(MenuType.TBR_SET);
|
||||
scripter.pressCheckKey();
|
||||
|
||||
// A "TBR CANCELLED alert" is only raised by the pump when the remaining time is
|
||||
// greater than 60s (displayed as 0:01, the pump goes from there to finished.
|
||||
// We could read the remaining duration from MAIN_MENU, but by the time we're here,
|
||||
// the pumup could have moved from 0:02 to 0:01, so instead, check if a "TBR CANCELLED" alert
|
||||
// is raised and if so dismiss it
|
||||
long inFiveSeconds = System.currentTimeMillis() + 5 * 1000;
|
||||
boolean alertProcessed = false;
|
||||
while (System.currentTimeMillis() < inFiveSeconds && !alertProcessed) {
|
||||
if (scripter.currentMenu.getType() == MenuType.WARNING_OR_ERROR) {
|
||||
// Check the raised alarm is TBR CANCELLED, so we're not accidentally cancelling
|
||||
// a different alarm that might be raised at the same time.
|
||||
// Note that the message is permanently displayed, while the error code is blinking.
|
||||
// A wait till the error code can be read results in the code hanging, despite
|
||||
// menu updates coming in, so just check the message.
|
||||
// TODO v2 this only works when the pump's language is English
|
||||
String errorMsg = (String) scripter.currentMenu.getAttribute(MenuAttribute.MESSAGE);
|
||||
if (!errorMsg.equals("TBR CANCELLED")) {
|
||||
throw new CommandException().success(false).enacted(false)
|
||||
.message("An alert other than the expected TBR CANCELLED was raised by the pump: "
|
||||
+ errorMsg + ". Please check the pump.");
|
||||
}
|
||||
// confirm "TBR CANCELLED" alert
|
||||
scripter.verifyMenuIsDisplayed(MenuType.WARNING_OR_ERROR);
|
||||
scripter.pressCheckKey();
|
||||
// dismiss "TBR CANCELLED" alert
|
||||
scripter.verifyMenuIsDisplayed(MenuType.WARNING_OR_ERROR);
|
||||
scripter.pressCheckKey();
|
||||
scripter.waitForMenuToBeLeft(MenuType.WARNING_OR_ERROR);
|
||||
alertProcessed = true;
|
||||
}
|
||||
SystemClock.sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyMainMenuShowsNoActiveTbr(RuffyScripter scripter) {
|
||||
scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU);
|
||||
Double tbrPercentage = (Double) scripter.currentMenu.getAttribute(MenuAttribute.TBR);
|
||||
boolean runtimeDisplayed = scripter.currentMenu.attributes().contains(MenuAttribute.RUNTIME);
|
||||
if (tbrPercentage != 100 || runtimeDisplayed) {
|
||||
throw new CommandException().message("Cancelling TBR failed, TBR is still set according to MAIN_MENU");
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyMainMenuShowsExpectedTbrActive(RuffyScripter scripter) {
|
||||
scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU);
|
||||
// new TBR set; percentage and duration must be displayed ...
|
||||
if (!scripter.currentMenu.attributes().contains(MenuAttribute.TBR) ||
|
||||
!scripter.currentMenu.attributes().contains(MenuAttribute.RUNTIME)) {
|
||||
throw new CommandException().message("Setting TBR failed, according to MAIN_MENU no TBR is active");
|
||||
}
|
||||
Double mmTbrPercentage = (Double) scripter.currentMenu.getAttribute(MenuAttribute.TBR);
|
||||
MenuTime mmTbrDuration = (MenuTime) scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME);
|
||||
// ... and be the same as what we set
|
||||
// note that displayed duration might have already counted down, e.g. from 30 minutes to
|
||||
// 29 minutes and 59 seconds, so that 29 minutes are displayed
|
||||
int mmTbrDurationInMinutes = mmTbrDuration.getHour() * 60 + mmTbrDuration.getMinute();
|
||||
if (mmTbrPercentage != percentage || (mmTbrDurationInMinutes != duration && mmTbrDurationInMinutes + 1 != duration)) {
|
||||
throw new CommandException().message("Setting TBR failed, TBR in MAIN_MENU differs from expected");
|
||||
} catch (Exception e) {
|
||||
log.error("got exception: ", e);
|
||||
return new CommandResult().success(false).message("failed to wait: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -91,6 +91,7 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
MainApp.bus().register(this);
|
||||
bindRuffyService();
|
||||
startAlerter();
|
||||
ruffyScripter = new RuffyScripter();
|
||||
}
|
||||
|
||||
private void definePumpCapabilities() {
|
||||
|
@ -163,7 +164,10 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
mgr.notify(id, notificationBuilder.build());
|
||||
lastAlarmTime = now;
|
||||
} else {
|
||||
// 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);
|
||||
|
@ -172,7 +176,8 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
}, "combo-alerter").start();
|
||||
}
|
||||
|
||||
private void bindRuffyService() {
|
||||
private boolean bindRuffyService() {
|
||||
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
boolean boundSucceeded = false;
|
||||
|
||||
|
@ -185,6 +190,7 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
// full path to the driver
|
||||
// in the logs this service is mentioned as (note the slash)
|
||||
// "org.monkey.d.ruffy.ruffy/.driver.Ruffy"
|
||||
//org.monkey.d.ruffy.ruffy is the base package identifier and /.driver.Ruffy the service within the package
|
||||
"org.monkey.d.ruffy.ruffy.driver.Ruffy"
|
||||
));
|
||||
context.startService(intent);
|
||||
|
@ -193,16 +199,19 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
ruffyScripter = new RuffyScripter(IRuffyService.Stub.asInterface(service));
|
||||
ruffyScripter.start();
|
||||
keepUnbound=false;
|
||||
ruffyScripter.start(IRuffyService.Stub.asInterface(service));
|
||||
log.debug("ruffy serivce connected");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
ruffyScripter.stop();
|
||||
ruffyScripter = null;
|
||||
log.debug("ruffy service disconnected");
|
||||
if(!keepUnbound) {
|
||||
SystemClock.sleep(250);
|
||||
bindRuffyService();
|
||||
}
|
||||
}
|
||||
};
|
||||
boundSucceeded = context.bindService(intent, mRuffyServiceConnection, Context.BIND_AUTO_CREATE);
|
||||
|
@ -213,9 +222,13 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
if (!boundSucceeded) {
|
||||
statusSummary = "No connection to ruffy. Pump control not available.";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean keepUnbound = false;
|
||||
private void unbindRuffyService() {
|
||||
keepUnbound = true;
|
||||
ruffyScripter.unbind();
|
||||
MainApp.instance().getApplicationContext().unbindService(mRuffyServiceConnection);
|
||||
}
|
||||
|
||||
|
@ -414,6 +427,7 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
MainApp.bus().post(new EventComboPumpUpdateGUI());
|
||||
|
||||
CommandResult commandResult = ruffyScripter.runCommand(command);
|
||||
// TODO extract this into a recovery method and check the logic of restarting and rebinding ruffy
|
||||
if (!commandResult.success && commandResult.exception != null) {
|
||||
log.error("CommandResult has exception, rebinding ruffy service", commandResult.exception);
|
||||
|
||||
|
@ -421,6 +435,12 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
try {
|
||||
unbindRuffyService();
|
||||
SystemClock.sleep(5000);
|
||||
} catch (Exception e) {
|
||||
/*String msg = "No connection to ruffy. Pump control not available.";
|
||||
statusSummary = msg;
|
||||
return new CommandResult().message(msg);*/
|
||||
}
|
||||
try {
|
||||
bindRuffyService();
|
||||
SystemClock.sleep(5000);
|
||||
} catch (Exception e) {
|
||||
|
@ -502,6 +522,7 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
}
|
||||
|
||||
CommandResult commandResult = runCommand(new SetTbrCommand(adjustedPercent, durationInMinutes));
|
||||
|
||||
if (commandResult.enacted) {
|
||||
TemporaryBasal tempStart = new TemporaryBasal(commandResult.completionTime);
|
||||
// TODO commandResult.state.tbrRemainingDuration might already display 29 if 30 was set, since 29:59 is shown as 29 ...
|
||||
|
@ -542,6 +563,7 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
|||
final TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
|
||||
|
||||
if (activeTemp == null || userRequested) {
|
||||
/* v1 compatibility to sync DB to pump if they diverged (activeTemp == null) */
|
||||
log.debug("cancelTempBasal: hard-cancelling TBR since user requested");
|
||||
commandResult = runCommand(new CancelTbrCommand());
|
||||
if (commandResult.enacted) {
|
||||
|
|
|
@ -35,6 +35,7 @@ public class Menu implements Parcelable{
|
|||
String clas = in.readString();
|
||||
String value = in.readString();
|
||||
|
||||
if(attr!=null && clas!=null && value!=null) {
|
||||
MenuAttribute a = MenuAttribute.valueOf(attr);
|
||||
Object o = null;
|
||||
if (Integer.class.toString().equals(clas)) {
|
||||
|
@ -60,6 +61,7 @@ public class Menu implements Parcelable{
|
|||
} else {
|
||||
Log.e("MenuIn", "failed to parse: " + attr + " / " + clas + " / " + value);
|
||||
}
|
||||
}
|
||||
}catch(Exception e)
|
||||
{
|
||||
Log.e("MenuIn","Exception in read",e);
|
||||
|
@ -120,4 +122,12 @@ public class Menu implements Parcelable{
|
|||
return new Menu[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String to = "Menu: "+getType()+" atr:";
|
||||
for(MenuAttribute atr : attributes())
|
||||
to+=atr.toString()+"="+getAttribute(atr)+";";
|
||||
return to;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,38 +5,47 @@ package org.monkey.d.ruffy.ruffy.driver.display;
|
|||
*/
|
||||
|
||||
public enum MenuType {
|
||||
MAIN_MENU,
|
||||
STOP_MENU,
|
||||
BOLUS_MENU,
|
||||
BOLUS_ENTER,
|
||||
EXTENDED_BOLUS_MENU,
|
||||
BOLUS_DURATION,
|
||||
MULTIWAVE_BOLUS_MENU,
|
||||
IMMEDIATE_BOLUS,
|
||||
TBR_MENU,
|
||||
MY_DATA_MENU,
|
||||
BASAL_MENU,
|
||||
BASAL_1_MENU,
|
||||
BASAL_2_MENU,
|
||||
BASAL_3_MENU,
|
||||
BASAL_4_MENU,
|
||||
BASAL_5_MENU,
|
||||
DATE_AND_TIME_MENU,
|
||||
ALARM_MENU,
|
||||
MENU_SETTINGS_MENU,
|
||||
BLUETOOTH_MENU,
|
||||
THERAPY_MENU,
|
||||
PUMP_MENU,
|
||||
QUICK_INFO,
|
||||
BOLUS_DATA,
|
||||
DAILY_DATA,
|
||||
TBR_DATA,
|
||||
ERROR_DATA,
|
||||
TBR_SET,
|
||||
TBR_DURATION,
|
||||
STOP,
|
||||
START_MENU,
|
||||
BASAL_TOTAL,
|
||||
BASAL_SET,
|
||||
WARNING_OR_ERROR,
|
||||
MAIN_MENU(true),
|
||||
STOP_MENU(true),
|
||||
BOLUS_MENU(true),
|
||||
BOLUS_ENTER(false),
|
||||
EXTENDED_BOLUS_MENU(true),
|
||||
BOLUS_DURATION(false),
|
||||
MULTIWAVE_BOLUS_MENU(true),
|
||||
IMMEDIATE_BOLUS(false),
|
||||
TBR_MENU(true),
|
||||
MY_DATA_MENU(true),
|
||||
BASAL_MENU(true),
|
||||
BASAL_1_MENU(true),
|
||||
BASAL_2_MENU(true),
|
||||
BASAL_3_MENU(true),
|
||||
BASAL_4_MENU(true),
|
||||
BASAL_5_MENU(true),
|
||||
DATE_AND_TIME_MENU(true),
|
||||
ALARM_MENU(true),
|
||||
MENU_SETTINGS_MENU(true),
|
||||
BLUETOOTH_MENU(true),
|
||||
THERAPY_MENU(true),
|
||||
PUMP_MENU(true),
|
||||
QUICK_INFO(false),
|
||||
BOLUS_DATA(false),
|
||||
DAILY_DATA(false),
|
||||
TBR_DATA(false),
|
||||
ERROR_DATA(false),
|
||||
TBR_SET(false),
|
||||
TBR_DURATION(false),
|
||||
STOP(false),
|
||||
START_MENU(false),
|
||||
BASAL_TOTAL(false),
|
||||
BASAL_SET(false),
|
||||
WARNING_OR_ERROR(false),;
|
||||
|
||||
private boolean maintype = false;
|
||||
MenuType(boolean b) {
|
||||
maintype=b;
|
||||
}
|
||||
|
||||
public boolean isMaintype() {
|
||||
return maintype;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue