- fix Multi connect

- add key sent with 2500ms wait on keypress
- fix Timing and npes in setTBR
- make ruffyScripter not reinit every time
- fix menu npe
This commit is contained in:
Sandra Keßler 2017-08-04 11:53:51 +02:00
parent 4147e7f6a1
commit 6981276cab
6 changed files with 113 additions and 118 deletions

View file

@ -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();
}

View file

@ -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*/

View file

@ -15,11 +15,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Objects;
import de.jotomo.ruffyscripter.commands.Command;
import de.jotomo.ruffyscripter.commands.CommandException;
import de.jotomo.ruffyscripter.commands.CommandResult;
import de.jotomo.ruffyscripter.commands.ReadPumpStateCommand;
import de.jotomo.ruffyscripter.commands.SetTbrCommand;
// TODO regularly read "My data" history (boluses, TBR) to double check all commands ran successfully.
// Automatically compare against AAPS db, or log all requests in the PumpInterface (maybe Milos
@ -34,7 +36,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;
@ -49,15 +51,18 @@ public class RuffyScripter {
private boolean started = false;
public RuffyScripter(final IRuffyService ruffyService) {
this.ruffyService = ruffyService;
public RuffyScripter() {
}
public void start() {
public void start(IRuffyService newService) {
try {
ruffyService.addHandler(mHandler);
idleDisconnectMonitorThread.start();
started = true;
if(newService!=null) {
this.ruffyService = newService;
idleDisconnectMonitorThread.start();
started = true;
try{newService.addHandler(mHandler);}catch (Exception e){}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -66,11 +71,6 @@ public class RuffyScripter {
public void stop() {
if (started) {
started=false;
try {
ruffyService.removeHandler(mHandler);
} catch (Exception e) {
log.warn("Removing IRTHandler from Ruffy service failed, ignoring", e);
}
}
}
@ -78,6 +78,7 @@ public class RuffyScripter {
return started;
}
private boolean canDisconnect = false;
private Thread idleDisconnectMonitorThread = new Thread(new Runnable() {
@Override
public void run() {
@ -91,12 +92,17 @@ 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 (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;
@ -127,6 +133,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");
@ -149,7 +160,7 @@ 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());
@ -166,16 +177,37 @@ 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)
{
keylock.notify();
}
}
@Override
public String getServiceIdentifier() throws RemoteException {
return this.toString();
}
};
private Object keylock = new Object();
public boolean isPumpBusy() {
return activeCmd != null;
}
public void unbind() {
if(ruffyService!=null)
try{ruffyService.removeHandler(mHandler);}catch (Exception e){}
this.ruffyService = null;
}
private static class Returnable {
CommandResult cmdResult;
}
@ -323,7 +355,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
@ -403,8 +436,12 @@ public class RuffyScripter {
private void pressKey(final byte key) {
try {
ruffyService.rtSendKey(key, true);
SystemClock.sleep(200);
//SystemClock.sleep(200);
ruffyService.rtSendKey(Key.NO_KEY, true);
synchronized (keylock)
{
keylock.wait(2500);
}
} catch (Exception e) {
throw new CommandException().exception(e).message("Error while pressing buttons");
}

View file

@ -107,7 +107,7 @@ public class SetTbrCommand implements Command {
switch (state)
{
case BEFORE:
if(scripter.currentMenu.getType()==MenuType.MAIN_MENU)
if(scripter.currentMenu!=null && scripter.currentMenu.getType()==MenuType.MAIN_MENU)
{
updateState(MAIN,120);
lastMenu = MenuType.MAIN_MENU;
@ -115,7 +115,7 @@ public class SetTbrCommand implements Command {
}
break;
case MAIN:
if(scripter.currentMenu.getType()==MenuType.TBR_MENU)
if(scripter.currentMenu!=null && scripter.currentMenu.getType()==MenuType.TBR_MENU)
{
updateState(TBR,30);
scripter.pressCheckKey();
@ -126,46 +126,31 @@ public class SetTbrCommand implements Command {
e.printStackTrace();
}
}
else if(scripter.currentMenu.getType()!=lastMenu)
else if(scripter.currentMenu!=null && scripter.currentMenu.getType()!=lastMenu)
{
lastMenu = scripter.currentMenu.getType();
updateState(MAIN,30);
scripter.pressMenuKey();
log.debug("found Menu:"+lastMenu+" -> state:MAIN");
try {
Thread.sleep(750);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else
{
scripter.pressMenuKey();
try {
Thread.sleep(750);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case TBR:
if(scripter.currentMenu.getType()==MenuType.TBR_SET)
if(scripter.currentMenu!=null && scripter.currentMenu.getType()==MenuType.TBR_SET)
{
updateState(SET_TBR,60);
}
else
{
scripter.pressMenuKey();
try {
Thread.sleep(750);
} catch (InterruptedException e) {
e.printStackTrace();
}
updateState(TBR,60);
}
break;
case SET_TBR:
if(scripter.currentMenu.getType()==MenuType.TBR_SET)
if(scripter.currentMenu!=null && scripter.currentMenu.getType()==MenuType.TBR_SET)
{
Object percentageObj = scripter.currentMenu.getAttribute(MenuAttribute.BASAL_RATE);
if(percentageObj != null && percentageObj instanceof Double)
@ -175,21 +160,11 @@ public class SetTbrCommand implements Command {
{
scripter.pressUpKey();
updateState(SET_TBR,30);
try {
Thread.sleep(750);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else if(currentPercentage > percentage)
{
scripter.pressDownKey();
updateState(SET_TBR,30);
try {
Thread.sleep(750);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else
{
@ -205,15 +180,10 @@ public class SetTbrCommand implements Command {
}
}
}
else if(scripter.currentMenu.getType()==MenuType.TBR_DURATION)
else if(scripter.currentMenu!=null && scripter.currentMenu.getType()==MenuType.TBR_DURATION)
{
scripter.pressMenuKey();
updateState(TBR,60);
try {
Thread.sleep(750);
} catch (InterruptedException e) {
e.printStackTrace();
}
updateState(SET_TBR,60);
}
else
{
@ -221,7 +191,7 @@ public class SetTbrCommand implements Command {
}
break;
case SET_TIME:
if(scripter.currentMenu.getType()==MenuType.TBR_DURATION)
if(scripter.currentMenu!=null && scripter.currentMenu.getType()==MenuType.TBR_DURATION)
{
Object durationObj = scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME);
if(durationObj != null && durationObj instanceof MenuTime)
@ -232,43 +202,23 @@ public class SetTbrCommand implements Command {
{
scripter.pressUpKey();
updateState(SET_TIME,30);
try {
Thread.sleep(750);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else if(currentDuration > duration)
{
scripter.pressDownKey();
updateState(SET_TIME,30);
try {
Thread.sleep(750);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else
{
scripter.pressCheckKey();
updateState(SET, 30);
try {
Thread.sleep(750);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
else if(scripter.currentMenu.getType()==MenuType.TBR_SET)
else if(scripter.currentMenu!=null && scripter.currentMenu.getType()==MenuType.TBR_SET)
{
scripter.pressMenuKey();
updateState(SET_TIME,60);
try {
Thread.sleep(750);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else
{
@ -276,18 +226,13 @@ public class SetTbrCommand implements Command {
}
break;
case SET:
if(scripter.currentMenu.getType()==MenuType.WARNING_OR_ERROR)
if(scripter.currentMenu!=null && scripter.currentMenu.getType()==MenuType.WARNING_OR_ERROR)
{
lastMenu = scripter.currentMenu.getType();
scripter.pressCheckKey();
updateState(SET, 30);
try {
Thread.sleep(750);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else if(scripter.currentMenu.getType()==MenuType.MAIN_MENU) {
else if(scripter.currentMenu!=null && scripter.currentMenu.getType()==MenuType.MAIN_MENU) {
Object setPercentage = scripter.currentMenu.getAttribute(MenuAttribute.TBR);
Object setDuration = scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME);
if (setPercentage== null ||setDuration==null) {

View file

@ -85,6 +85,7 @@ public class ComboPlugin implements PluginBase, PumpInterface {
MainApp.bus().register(this);
bindRuffyService();
startAlerter();
ruffyScripter = new RuffyScripter();
}
private void definePumpCapabilities() {
@ -169,11 +170,6 @@ public class ComboPlugin implements PluginBase, PumpInterface {
private boolean bindRuffyService() {
if(ruffyScripter != null)
{
log.debug("ruffy service already connected!");
return false;
}
Context context = MainApp.instance().getApplicationContext();
boolean boundSucceeded = false;
@ -186,6 +182,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);
@ -194,16 +191,22 @@ 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) {
try {
Thread.sleep(250);
} catch (Exception e) {
}
bindRuffyService();
}
}
};
boundSucceeded = context.bindService(intent, mRuffyServiceConnection, Context.BIND_AUTO_CREATE);
@ -217,7 +220,10 @@ public class ComboPlugin implements PluginBase, PumpInterface {
return true;
}
private boolean keepUnbound = false;
private void unbindRuffyService() {
keepUnbound = true;
ruffyScripter.unbind();
MainApp.instance().getApplicationContext().unbindService(mRuffyServiceConnection);
}

View file

@ -35,30 +35,32 @@ public class Menu implements Parcelable{
String clas = in.readString();
String value = in.readString();
MenuAttribute a = MenuAttribute.valueOf(attr);
Object o = null;
if (Integer.class.toString().equals(clas)) {
o = new Integer(value);
} else if (Double.class.toString().equals(clas)) {
o = new Double(value);
} else if (Boolean.class.toString().equals(clas)) {
o = new Boolean(value);
} else if (MenuDate.class.toString().equals(clas)) {
o = new MenuDate(value);
} else if (MenuTime.class.toString().equals(clas)) {
o = new MenuTime(value);
} else if (MenuBlink.class.toString().equals(clas)) {
o = new MenuBlink();
} else if (BolusType.class.toString().equals(clas)) {
o = BolusType.valueOf(value);
} else if (String.class.toString().equals(clas)) {
o = new String(value);
}
if(attr!=null && clas!=null && value!=null) {
MenuAttribute a = MenuAttribute.valueOf(attr);
Object o = null;
if (Integer.class.toString().equals(clas)) {
o = new Integer(value);
} else if (Double.class.toString().equals(clas)) {
o = new Double(value);
} else if (Boolean.class.toString().equals(clas)) {
o = new Boolean(value);
} else if (MenuDate.class.toString().equals(clas)) {
o = new MenuDate(value);
} else if (MenuTime.class.toString().equals(clas)) {
o = new MenuTime(value);
} else if (MenuBlink.class.toString().equals(clas)) {
o = new MenuBlink();
} else if (BolusType.class.toString().equals(clas)) {
o = BolusType.valueOf(value);
} else if (String.class.toString().equals(clas)) {
o = new String(value);
}
if (o != null) {
attributes.put(a, o);
} else {
Log.e("MenuIn", "failed to parse: " + attr + " / " + clas + " / " + value);
if (o != null) {
attributes.put(a, o);
} else {
Log.e("MenuIn", "failed to parse: " + attr + " / " + clas + " / " + value);
}
}
}catch(Exception e)
{