- 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 fail(String message);
void requestBluetooth(); void requestBluetooth();
boolean canDisconnect();
void rtStopped(); void rtStopped();
void rtStarted(); void rtStarted();
void rtClearDisplay(); void rtClearDisplay();
void rtUpdateDisplay(in byte[] quarter, int which); void rtUpdateDisplay(in byte[] quarter, int which);
void rtDisplayHandleMenu(in Menu menu); void rtDisplayHandleMenu(in Menu menu, in int sequence);
void rtDisplayHandleNoMenu(); 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 * @return 0 if successful, -1 otherwise
*/ */
int doRTConnect(); int doRTConnect(IRTHandler handler);
/** Disconnect from the pump */ /** Disconnect from the pump */
void doRTDisconnect(); void doRTDisconnect(IRTHandler handler);
/*What's the meaning of 'changed'? /*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*/ * 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 org.slf4j.LoggerFactory;
import java.util.List; import java.util.List;
import java.util.Objects;
import de.jotomo.ruffyscripter.commands.Command; import de.jotomo.ruffyscripter.commands.Command;
import de.jotomo.ruffyscripter.commands.CommandException; import de.jotomo.ruffyscripter.commands.CommandException;
import de.jotomo.ruffyscripter.commands.CommandResult; import de.jotomo.ruffyscripter.commands.CommandResult;
import de.jotomo.ruffyscripter.commands.ReadPumpStateCommand; 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. // 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 // 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 static final Logger log = LoggerFactory.getLogger(RuffyScripter.class);
private final IRuffyService ruffyService; private IRuffyService ruffyService;
private final long connectionTimeOutMs = 5000; private final long connectionTimeOutMs = 5000;
private String unrecoverableError = null; private String unrecoverableError = null;
@ -49,15 +51,18 @@ public class RuffyScripter {
private boolean started = false; private boolean started = false;
public RuffyScripter(final IRuffyService ruffyService) { public RuffyScripter() {
this.ruffyService = ruffyService;
} }
public void start() { public void start(IRuffyService newService) {
try { try {
ruffyService.addHandler(mHandler); if(newService!=null) {
idleDisconnectMonitorThread.start(); this.ruffyService = newService;
started = true; idleDisconnectMonitorThread.start();
started = true;
try{newService.addHandler(mHandler);}catch (Exception e){}
}
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -66,11 +71,6 @@ public class RuffyScripter {
public void stop() { public void stop() {
if (started) { if (started) {
started=false; 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; return started;
} }
private boolean canDisconnect = false;
private Thread idleDisconnectMonitorThread = new Thread(new Runnable() { private Thread idleDisconnectMonitorThread = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -91,12 +92,17 @@ public class RuffyScripter {
&& now > lastDisconnect + 15 * 1000) { && now > lastDisconnect + 15 * 1000) {
log.debug("Disconnecting after " + (connectionTimeOutMs / 1000) + "s inactivity timeout"); log.debug("Disconnecting after " + (connectionTimeOutMs / 1000) + "s inactivity timeout");
lastDisconnect = now; lastDisconnect = now;
ruffyService.doRTDisconnect(); canDisconnect=true;
ruffyService.doRTDisconnect(mHandler);
connected = false; connected = false;
lastDisconnect = System.currentTimeMillis(); lastDisconnect = System.currentTimeMillis();
// don't attempt anything fancy in the next 10s, let the pump settle // don't attempt anything fancy in the next 10s, let the pump settle
SystemClock.sleep(10 * 1000); SystemClock.sleep(10 * 1000);
} }
else
{
canDisconnect=false;
}
} catch (Exception e) { } catch (Exception e) {
// TODO do we need to catch this exception somewhere else too? right now it's // 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; // 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"); log.trace("Ruffy invoked requestBluetooth callback");
} }
@Override
public boolean canDisconnect() throws RemoteException {
return canDisconnect;
}
@Override @Override
public void rtStopped() throws RemoteException { public void rtStopped() throws RemoteException {
log.debug("rtStopped callback invoked"); log.debug("rtStopped callback invoked");
@ -149,7 +160,7 @@ public class RuffyScripter {
} }
@Override @Override
public void rtDisplayHandleMenu(Menu menu) throws RemoteException { public void rtDisplayHandleMenu(Menu menu, int sequence) throws RemoteException {
// method is called every ~500ms // method is called every ~500ms
log.debug("rtDisplayHandleMenu: " + menu.getType()); log.debug("rtDisplayHandleMenu: " + menu.getType());
@ -166,16 +177,37 @@ public class RuffyScripter {
} }
@Override @Override
public void rtDisplayHandleNoMenu() throws RemoteException { public void rtDisplayHandleNoMenu(int sequence) throws RemoteException {
log.debug("rtDisplayHandleNoMenu callback invoked"); 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() { public boolean isPumpBusy() {
return activeCmd != null; return activeCmd != null;
} }
public void unbind() {
if(ruffyService!=null)
try{ruffyService.removeHandler(mHandler);}catch (Exception e){}
this.ruffyService = null;
}
private static class Returnable { private static class Returnable {
CommandResult cmdResult; CommandResult cmdResult;
} }
@ -323,7 +355,8 @@ public class RuffyScripter {
SystemClock.sleep(10 * 1000); 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("Connect init successful: " + connectInitSuccessful);
log.debug("Waiting for first menu update to be sent"); log.debug("Waiting for first menu update to be sent");
// Note: there was an 'if(currentMenu == null)' around the next call, since // 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) { private void pressKey(final byte key) {
try { try {
ruffyService.rtSendKey(key, true); ruffyService.rtSendKey(key, true);
SystemClock.sleep(200); //SystemClock.sleep(200);
ruffyService.rtSendKey(Key.NO_KEY, true); ruffyService.rtSendKey(Key.NO_KEY, true);
synchronized (keylock)
{
keylock.wait(2500);
}
} catch (Exception e) { } catch (Exception e) {
throw new CommandException().exception(e).message("Error while pressing buttons"); throw new CommandException().exception(e).message("Error while pressing buttons");
} }

View file

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

View file

@ -85,6 +85,7 @@ public class ComboPlugin implements PluginBase, PumpInterface {
MainApp.bus().register(this); MainApp.bus().register(this);
bindRuffyService(); bindRuffyService();
startAlerter(); startAlerter();
ruffyScripter = new RuffyScripter();
} }
private void definePumpCapabilities() { private void definePumpCapabilities() {
@ -169,11 +170,6 @@ public class ComboPlugin implements PluginBase, PumpInterface {
private boolean bindRuffyService() { private boolean bindRuffyService() {
if(ruffyScripter != null)
{
log.debug("ruffy service already connected!");
return false;
}
Context context = MainApp.instance().getApplicationContext(); Context context = MainApp.instance().getApplicationContext();
boolean boundSucceeded = false; boolean boundSucceeded = false;
@ -186,6 +182,7 @@ public class ComboPlugin implements PluginBase, PumpInterface {
// full path to the driver // full path to the driver
// in the logs this service is mentioned as (note the slash) // in the logs this service is mentioned as (note the slash)
// "org.monkey.d.ruffy.ruffy/.driver.Ruffy" // "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" "org.monkey.d.ruffy.ruffy.driver.Ruffy"
)); ));
context.startService(intent); context.startService(intent);
@ -194,16 +191,22 @@ public class ComboPlugin implements PluginBase, PumpInterface {
@Override @Override
public void onServiceConnected(ComponentName name, IBinder service) { public void onServiceConnected(ComponentName name, IBinder service) {
ruffyScripter = new RuffyScripter(IRuffyService.Stub.asInterface(service)); keepUnbound=false;
ruffyScripter.start(); ruffyScripter.start(IRuffyService.Stub.asInterface(service));
log.debug("ruffy serivce connected"); log.debug("ruffy serivce connected");
} }
@Override @Override
public void onServiceDisconnected(ComponentName name) { public void onServiceDisconnected(ComponentName name) {
ruffyScripter.stop(); ruffyScripter.stop();
ruffyScripter = null;
log.debug("ruffy service disconnected"); log.debug("ruffy service disconnected");
if(!keepUnbound) {
try {
Thread.sleep(250);
} catch (Exception e) {
}
bindRuffyService();
}
} }
}; };
boundSucceeded = context.bindService(intent, mRuffyServiceConnection, Context.BIND_AUTO_CREATE); boundSucceeded = context.bindService(intent, mRuffyServiceConnection, Context.BIND_AUTO_CREATE);
@ -217,7 +220,10 @@ public class ComboPlugin implements PluginBase, PumpInterface {
return true; return true;
} }
private boolean keepUnbound = false;
private void unbindRuffyService() { private void unbindRuffyService() {
keepUnbound = true;
ruffyScripter.unbind();
MainApp.instance().getApplicationContext().unbindService(mRuffyServiceConnection); MainApp.instance().getApplicationContext().unbindService(mRuffyServiceConnection);
} }

View file

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