Misc improvements:

* Make command execution (RuffyScripter/ComoboPlugin.runCommand) more robust (I still suck at threading).
* Return all possible states in PumpState
* Add absolute TBR to PumpState
* Add NoOpCommand to fetch state data from pump
* Display returned pump state in Combo fragment/tab.
This commit is contained in:
Johannes Mockenhaupt 2017-07-15 18:40:01 +02:00
parent f251427d1b
commit 8ecf6922f7
No known key found for this signature in database
GPG key ID: 9E1EA6AF7BBBB0D1
6 changed files with 142 additions and 66 deletions

View file

@ -108,6 +108,7 @@ public class RuffyScripter {
private volatile Command activeCmd = null;
public CommandResult runCommand(final Command cmd) {
synchronized (this) {
try {
if (isPumpBusy()) {
return new CommandResult().message("Pump is busy");
@ -117,8 +118,6 @@ public class RuffyScripter {
// TODO reuse thread, scheduler ...
Thread cmdThread;
// TODO make this a safe lock
synchronized (this) {
cmdResult = null;
activeCmd = cmd;
// wait till pump is ready for input
@ -126,7 +125,8 @@ public class RuffyScripter {
// check if pump is an an error state
if (currentMenu != null && currentMenu.getType() == MenuType.WARNING_OR_ERROR) {
try {
return new CommandResult().message("Pump is in an error state: " + currentMenu.getAttribute(MenuAttribute.MESSAGE));
PumpState pumpState = readPumpState();
return new CommandResult().message("Pump is in an error state: " + currentMenu.getAttribute(MenuAttribute.MESSAGE)).state(pumpState);
} catch (Exception e) {
return new CommandResult().message("Pump is in an error state, reading the error state resulted in the attached exception").exception(e);
}
@ -147,7 +147,6 @@ public class RuffyScripter {
}
});
cmdThread.start();
}
// TODO really?
long timeout = System.currentTimeMillis() + 90 * 1000;
@ -158,7 +157,6 @@ public class RuffyScripter {
log.error("Running command " + activeCmd + " timed out");
cmdThread.interrupt();
activeCmd = null;
cmdResult = null;
return new CommandResult().success(false).enacted(false).message("Command timed out");
}
}
@ -167,13 +165,14 @@ public class RuffyScripter {
cmdResult.state = readPumpState();
}
log.debug("Command result: " + cmdResult);
CommandResult r = cmdResult;
cmdResult = null;
return r;
return cmdResult;
} catch (CommandException e) {
return e.toCommandResult();
} catch (Exception e) {
return new CommandResult().exception(e).message("Unexpected exception communication with ruffy");
} finally {
activeCmd = null;
}
}
}
@ -288,7 +287,7 @@ public class RuffyScripter {
if (System.currentTimeMillis() > timeout) {
throw new CommandException().message("Timeout waiting for menu " + menuType + " to be left");
}
SystemClock.sleep(50);
SystemClock.sleep(10);
}
}
@ -312,16 +311,31 @@ public class RuffyScripter {
}
private PumpState readPumpState() {
verifyMenuIsDisplayed(MenuType.MAIN_MENU);
PumpState state = new PumpState();
Double tbrPercentage = (Double) currentMenu.getAttribute(MenuAttribute.TBR);
Menu menu = this.currentMenu;
MenuType menuType = menu.getType();
if (menuType == MenuType.MAIN_MENU) {
Double tbrPercentage = (Double) menu.getAttribute(MenuAttribute.TBR);
if (tbrPercentage != 100) {
state.tbrActive = true;
Double displayedTbr = (Double) currentMenu.getAttribute(MenuAttribute.TBR);
Double displayedTbr = (Double) menu.getAttribute(MenuAttribute.TBR);
state.tbrPercent = displayedTbr.intValue();
MenuTime durationMenuTime = ((MenuTime) currentMenu.getAttribute(MenuAttribute.RUNTIME));
MenuTime durationMenuTime = ((MenuTime) menu.getAttribute(MenuAttribute.RUNTIME));
state.tbrRemainingDuration = durationMenuTime.getHour() * 60 + durationMenuTime.getMinute();
state.tbrRate = ((double) currentMenu.getAttribute(MenuAttribute.BASAL_RATE));
state.tbrRate = ((double) menu.getAttribute(MenuAttribute.BASAL_RATE));
}
} else if (menuType == MenuType.WARNING_OR_ERROR) {
state.isErrorOrWarning = true;
state.errorMsg = (String) menu.getAttribute(MenuAttribute.MESSAGE);
} else {
StringBuilder sb = new StringBuilder();
for (MenuAttribute menuAttribute : menu.attributes()) {
sb.append(menuAttribute);
sb.append(": ");
sb.append(menu.getAttribute(menuAttribute));
sb.append("\n");
}
state.errorMsg = "Pump is on menu " + menuType + ", listing attributes: \n" + sb.toString();
}
return state;
}

View file

@ -1,4 +1,15 @@
package de.jotomo.ruffyscripter.commands;
public class NoOpCommand {
import de.jotomo.ruffyscripter.RuffyScripter;
public class NoOpCommand implements Command {
@Override
public CommandResult execute(RuffyScripter ruffyScripter) {
return new CommandResult().success(true).enacted(false).message("Returning pump state only");
}
@Override
public String toString() {
return "NoOpCommand{}";
}
}

View file

@ -9,6 +9,7 @@ public class PumpState {
public Date timestamp = new Date();
public boolean tbrActive = false;
public int tbrPercent = -1;
public double tbrRate = -1;
public int tbrRemainingDuration = -1;
public boolean isErrorOrWarning = false;
public String errorMsg;
@ -23,6 +24,11 @@ public class PumpState {
return this;
}
public PumpState tbrRate(double tbrRate) {
this.tbrRate = tbrRate;
return this;
}
public PumpState tbrRemainingDuration(int tbrRemainingDuration) {
this.tbrRemainingDuration = tbrRemainingDuration;
return this;
@ -43,6 +49,7 @@ public class PumpState {
return "PumpState{" +
"tbrActive=" + tbrActive +
", tbrPercent=" + tbrPercent +
", tbrRate=" + tbrRate +
", tbrRemainingDuration=" + tbrRemainingDuration +
", isErrorOrWarning=" + isErrorOrWarning +
", errorMsg=" + errorMsg +

View file

@ -9,6 +9,7 @@ import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextView;
import com.squareup.otto.Subscribe;
@ -33,11 +34,15 @@ public class ComboFragment extends Fragment {
return comboPlugin;
}
private EditText statusText;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.combopump_fragment, container, false);
statusText = (EditText) view.findViewById(R.id.comboStatusEditText);
updateGUI();
return view;
}
@ -65,9 +70,17 @@ public class ComboFragment extends Fragment {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
// your rendering code here
if (getPlugin() == null) {
statusText.setText("Initializing");
} else {
StringBuilder sb = new StringBuilder();
sb.append(getPlugin().statusSummary);
if (getPlugin().pumpState != null) {
sb.append("\n\n");
sb.append(getPlugin().pumpState.toString().replaceAll(",", "\n"));
}
statusText.setText(sb.toString());
}
}
});
}

View file

@ -23,7 +23,7 @@ import de.jotomo.ruffyscripter.commands.BolusCommand;
import de.jotomo.ruffyscripter.commands.CancelTbrCommand;
import de.jotomo.ruffyscripter.commands.Command;
import de.jotomo.ruffyscripter.commands.CommandResult;
import de.jotomo.ruffyscripter.commands.ReadStateCommand;
import de.jotomo.ruffyscripter.commands.NoOpCommand;
import de.jotomo.ruffyscripter.commands.SetTbrCommand;
import de.jotomo.ruffyscripter.commands.PumpState;
import info.nightscout.androidaps.BuildConfig;
@ -36,11 +36,11 @@ import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.PumpCombo.events.EventComboPumpUpdateGUI;
import info.nightscout.utils.DateUtil;
/**
@ -59,7 +59,9 @@ public class ComboPlugin implements PluginBase, PumpInterface {
private ServiceConnection mRuffyServiceConnection;
@Nullable
private volatile PumpState pumpState;
volatile PumpState pumpState;
volatile String statusSummary = "Initializing";
private static PumpEnactResult OPERATION_NOT_SUPPORTED = new PumpEnactResult();
@ -96,6 +98,12 @@ public class ComboPlugin implements PluginBase, PumpInterface {
public void onServiceConnected(ComponentName name, IBinder service) {
ruffyScripter = new RuffyScripter(IRuffyService.Stub.asInterface(service));
log.debug("ruffy serivce connected");
new Thread(new Runnable() {
@Override
public void run() {
runCommand(new NoOpCommand());
}
}).start();
}
@Override
@ -299,10 +307,14 @@ public class ComboPlugin implements PluginBase, PumpInterface {
}
private CommandResult runCommand(Command command) {
synchronized (this) {
// TODO use this to dispatch methods to a service thread, like DanaRs executionService
// will be required when doing multiple commands in sequence.
// Alternatively provide 'composite commands' to return everything needed in one go?
try {
statusSummary = "Busy running " + command;
pumpState = null;
MainApp.bus().post(new EventComboPumpUpdateGUI());
CommandResult commandResult = ruffyScripter.runCommand(command);
if (commandResult.success && commandResult.state != null) {
pumpState = commandResult.state;
@ -310,7 +322,12 @@ public class ComboPlugin implements PluginBase, PumpInterface {
return commandResult;
} finally {
lastCmdTime = new Date();
statusSummary = pumpState != null && !pumpState.isErrorOrWarning
? "Idle"
: "Error: " + pumpState.errorMsg;
ruffyScripter.disconnect();
MainApp.bus().post(new EventComboPumpUpdateGUI());
}
}
}
@ -358,7 +375,6 @@ public class ComboPlugin implements PluginBase, PumpInterface {
log.debug("Rounded requested percentage from " + percent + " to " + rounded);
percent = rounded;
}
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingtempbasal)));
CommandResult commandResult = runCommand(new SetTbrCommand(percent, durationInMinutes));
if (commandResult.enacted) {
TemporaryBasal tempStart = new TemporaryBasal(System.currentTimeMillis());
@ -387,10 +403,10 @@ public class ComboPlugin implements PluginBase, PumpInterface {
return OPERATION_NOT_SUPPORTED;
}
// TODO untested, probably not working
@Override
public PumpEnactResult cancelTempBasal() {
log.debug("cancelTempBasal called");
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal)));
CommandResult commandResult = runCommand(new CancelTbrCommand());
if (commandResult.enacted) {
TemporaryBasal tempStop = new TemporaryBasal(System.currentTimeMillis());
@ -422,13 +438,20 @@ public class ComboPlugin implements PluginBase, PumpInterface {
JSONObject status = new JSONObject();
JSONObject extended = new JSONObject();
try {
status.put("status", "normal");
status.put("status", statusSummary);
extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION);
try {
extended.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName());
} catch (Exception e) {
}
status.put("timestamp", DateUtil.toISOString(new Date()));
status.put("timestamp", lastCmdTime);
if (pumpState != null) {
extended.put("TempBasalAbsoluteRate", pumpState.tbrRate);
// TODO best guess at this point ...
extended.put("TempBasalStart", DateUtil.dateAndTimeString(System.currentTimeMillis() - (pumpState.tbrRemainingDuration - 15 * 60 * 1000)));
extended.put("TempBasalRemaining", pumpState.tbrRemainingDuration);
}
// more info here .... look at dana plugin
@ -454,7 +477,7 @@ public class ComboPlugin implements PluginBase, PumpInterface {
@Override
public String shortStatus(boolean veryShort) {
return deviceID();
return statusSummary;
}
@Override

View file

@ -17,4 +17,12 @@
</ScrollView>
<TextView
android:id="@+id/comboStatusEditText"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:ems="10"
android:textAlignment="center"
android:layout_gravity="center_horizontal"/>
</FrameLayout>