wip
This commit is contained in:
parent
e895ba65eb
commit
b47559647f
18 changed files with 364 additions and 185 deletions
|
@ -52,3 +52,18 @@ Testing:
|
||||||
- Try to reproduce and open a ticket, add tag if any, otherwise add the hash of the commit used (right-click on the branch name select
|
- Try to reproduce and open a ticket, add tag if any, otherwise add the hash of the commit used (right-click on the branch name select
|
||||||
_Copy revision number_ or use _git show_ on the command-line) the branch name. Attach the log to the issue and label it as a bug.
|
_Copy revision number_ or use _git show_ on the command-line) the branch name. Attach the log to the issue and label it as a bug.
|
||||||
The logs can be found in _/storage/emulated/0/Android/data/info.nightscout.androidaps/_
|
The logs can be found in _/storage/emulated/0/Android/data/info.nightscout.androidaps/_
|
||||||
|
|
||||||
|
v2 usage
|
||||||
|
- When a BOLUS/TBR CANCELLED alert starts on the pump during bolusing or setting a TBR, this is caused by disconnect
|
||||||
|
between pump and phone. The app will try to reconnect and confirm the alert and then retry the last action. Therefore,
|
||||||
|
such an alarm shall be ignored (cancelling it is not a big issue, but will lead to the currently active action to
|
||||||
|
have to wait till the pump's display turns off before it can reconnect to the pump).
|
||||||
|
If the pump's alarm continues, the last action might have failed, in which case the user needs to confirm the alarm
|
||||||
|
|
||||||
|
v3 TODOs
|
||||||
|
- Reading and displaying TDDs
|
||||||
|
|
||||||
|
Maybes:
|
||||||
|
- reading/writing basal profiles to pump
|
||||||
|
- splitted bolus/slower bolus delivery
|
||||||
|
- extended bolus support
|
|
@ -1,7 +1,5 @@
|
||||||
package info.nightscout.androidaps;
|
package info.nightscout.androidaps;
|
||||||
|
|
||||||
import com.j256.ormlite.stmt.query.In;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 07.06.2016.
|
* Created by mike on 07.06.2016.
|
||||||
*/
|
*/
|
||||||
|
@ -24,7 +22,7 @@ public class Constants {
|
||||||
public static final int hoursToKeepInDatabase = 72;
|
public static final int hoursToKeepInDatabase = 72;
|
||||||
public static final int daysToKeepHistoryInDatabase = 30;
|
public static final int daysToKeepHistoryInDatabase = 30;
|
||||||
|
|
||||||
public static final long keepAliveMsecs = 5 * 60 * 1000L;
|
public static final long keepAliveMsecs = 60 * 1000L;
|
||||||
|
|
||||||
// SMS COMMUNICATOR
|
// SMS COMMUNICATOR
|
||||||
public static final long remoteBolusMinDistance = 15 * 60 * 1000L;
|
public static final long remoteBolusMinDistance = 15 * 60 * 1000L;
|
||||||
|
|
|
@ -30,7 +30,8 @@ import info.nightscout.utils.DecimalFormatter;
|
||||||
public class ComboFragment extends SubscriberFragment implements View.OnClickListener {
|
public class ComboFragment extends SubscriberFragment implements View.OnClickListener {
|
||||||
private static Logger log = LoggerFactory.getLogger(ComboFragment.class);
|
private static Logger log = LoggerFactory.getLogger(ComboFragment.class);
|
||||||
|
|
||||||
private TextView statusView;
|
private TextView stateView;
|
||||||
|
private TextView activityView;
|
||||||
private TextView batteryView;
|
private TextView batteryView;
|
||||||
private TextView reservoirView;
|
private TextView reservoirView;
|
||||||
private TextView lastConnectionView;
|
private TextView lastConnectionView;
|
||||||
|
@ -44,7 +45,8 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.combopump_fragment, container, false);
|
View view = inflater.inflate(R.layout.combopump_fragment, container, false);
|
||||||
|
|
||||||
statusView = (TextView) view.findViewById(R.id.combo_status);
|
stateView = (TextView) view.findViewById(R.id.combo_state);
|
||||||
|
activityView = (TextView) view.findViewById(R.id.combo_activity);
|
||||||
batteryView = (TextView) view.findViewById(R.id.combo_pumpstate_battery);
|
batteryView = (TextView) view.findViewById(R.id.combo_pumpstate_battery);
|
||||||
reservoirView = (TextView) view.findViewById(R.id.combo_insulinstate);
|
reservoirView = (TextView) view.findViewById(R.id.combo_insulinstate);
|
||||||
lastConnectionView = (TextView) view.findViewById(R.id.combo_lastconnection);
|
lastConnectionView = (TextView) view.findViewById(R.id.combo_lastconnection);
|
||||||
|
@ -70,52 +72,48 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis
|
||||||
});
|
});
|
||||||
thread.start();
|
thread.start();
|
||||||
break;
|
break;
|
||||||
case R.id.combo_history:
|
case R.id.combo_error_history:
|
||||||
// TODO show popup with warnings/errors from the pump
|
// TODO show popup with pump errors and comm problems
|
||||||
break;
|
break;
|
||||||
case R.id.combo_stats:
|
case R.id.combo_stats:
|
||||||
// TODO show TDD stats from the pump
|
// TODO show TDD stats from the pump (later)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onStatusEvent(final EventComboPumpUpdateGUI ev) {
|
public void onStatusEvent(final EventComboPumpUpdateGUI ev) {
|
||||||
if (ev.status != null) {
|
updateGUI();
|
||||||
Activity activity = getActivity();
|
|
||||||
if (activity != null)
|
|
||||||
activity.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
statusView.setText(ev.status);
|
|
||||||
statusView.setTextColor(Color.WHITE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
updateGUI();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateGUI() {
|
public void updateGUI() {
|
||||||
Activity activity = getActivity();
|
final Activity activity = getActivity();
|
||||||
|
log.debug("aCtI: activity available? " + (activity != null));
|
||||||
if (activity != null)
|
if (activity != null)
|
||||||
activity.runOnUiThread(new Runnable() {
|
activity.runOnUiThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
ComboPlugin plugin = ComboPlugin.getPlugin();
|
ComboPlugin plugin = ComboPlugin.getPlugin();
|
||||||
|
|
||||||
|
// activity
|
||||||
|
String activity = plugin.getPump().activity;
|
||||||
|
activityView.setText(activity != null ? activity : "Idle");
|
||||||
|
|
||||||
if (plugin.isInitialized()) {
|
if (plugin.isInitialized()) {
|
||||||
// status
|
// status
|
||||||
statusView.setText(plugin.getPump().state.getStateSummary());
|
PumpState ps = plugin.getPump().state;
|
||||||
if (plugin.getPump().state.errorMsg != null) {
|
stateView.setText(plugin.getPump().state.getStateSummary());
|
||||||
statusView.setTextColor(Color.RED);
|
if (plugin.getPump().state.errorMsg != null
|
||||||
|
|| ps.insulinState == PumpState.EMPTY
|
||||||
|
|| ps.batteryState == PumpState.EMPTY) {
|
||||||
|
stateView.setTextColor(Color.RED);
|
||||||
} else if (plugin.getPump().state.suspended) {
|
} else if (plugin.getPump().state.suspended) {
|
||||||
statusView.setTextColor(Color.YELLOW);
|
stateView.setTextColor(Color.YELLOW);
|
||||||
} else {
|
} else {
|
||||||
statusView.setTextColor(Color.WHITE);
|
stateView.setTextColor(Color.WHITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// battery
|
// battery
|
||||||
PumpState ps = plugin.getPump().state;
|
|
||||||
if (ps.batteryState == PumpState.EMPTY) {
|
if (ps.batteryState == PumpState.EMPTY) {
|
||||||
batteryView.setText("{fa-battery-empty}");
|
batteryView.setText("{fa-battery-empty}");
|
||||||
batteryView.setTextColor(Color.RED);
|
batteryView.setTextColor(Color.RED);
|
||||||
|
@ -143,15 +141,14 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis
|
||||||
if (lastCmdResult != null) {
|
if (lastCmdResult != null) {
|
||||||
String minAgo = DateUtil.minAgo(lastCmdResult.completionTime);
|
String minAgo = DateUtil.minAgo(lastCmdResult.completionTime);
|
||||||
String time = DateUtil.timeString(lastCmdResult.completionTime);
|
String time = DateUtil.timeString(lastCmdResult.completionTime);
|
||||||
|
// TODO must not be within if (lastCmdResult) so we can complain if NO command ever worked; also move from completionTime to new times
|
||||||
|
// TODO check all access to completionTime. useful anymore?
|
||||||
if (plugin.getPump().lastSuccessfulConnection < System.currentTimeMillis() + 30 * 60 * 1000) {
|
if (plugin.getPump().lastSuccessfulConnection < System.currentTimeMillis() + 30 * 60 * 1000) {
|
||||||
lastConnectionView.setText(
|
lastConnectionView.setText("No connection for " + minAgo + " min");
|
||||||
"No successful connection" +
|
|
||||||
"\nwithin the last " + minAgo + " min");
|
|
||||||
lastConnectionView.setTextColor(Color.RED);
|
lastConnectionView.setTextColor(Color.RED);
|
||||||
}
|
}
|
||||||
if (plugin.getPump().lastConnectionAttempt > plugin.getPump().lastSuccessfulConnection) {
|
if (plugin.getPump().lastConnectionAttempt > plugin.getPump().lastSuccessfulConnection) {
|
||||||
lastConnectionView.setText("" + minAgo + " (" + time + ")" +
|
lastConnectionView.setText("Last connect attempt failed");
|
||||||
"\nLast connect attempt failed");
|
|
||||||
lastConnectionView.setTextColor(Color.YELLOW);
|
lastConnectionView.setTextColor(Color.YELLOW);
|
||||||
} else {
|
} else {
|
||||||
lastConnectionView.setText("" + minAgo + " (" + time + ")");
|
lastConnectionView.setText("" + minAgo + " (" + time + ")");
|
||||||
|
|
|
@ -1,13 +1,7 @@
|
||||||
package info.nightscout.androidaps.plugins.PumpCombo;
|
package info.nightscout.androidaps.plugins.PumpCombo;
|
||||||
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.media.RingtoneManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v4.app.NotificationCompat;
|
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -22,7 +16,7 @@ import de.jotomo.ruffy.spi.CommandResult;
|
||||||
import de.jotomo.ruffy.spi.PumpState;
|
import de.jotomo.ruffy.spi.PumpState;
|
||||||
import de.jotomo.ruffy.spi.RuffyCommands;
|
import de.jotomo.ruffy.spi.RuffyCommands;
|
||||||
import de.jotomo.ruffy.spi.history.Bolus;
|
import de.jotomo.ruffy.spi.history.Bolus;
|
||||||
import de.jotomo.ruffy.spi.history.Error;
|
import de.jotomo.ruffy.spi.history.PumpError;
|
||||||
import de.jotomo.ruffy.spi.history.PumpHistoryRequest;
|
import de.jotomo.ruffy.spi.history.PumpHistoryRequest;
|
||||||
import de.jotomo.ruffy.spi.history.Tbr;
|
import de.jotomo.ruffy.spi.history.Tbr;
|
||||||
import de.jotomo.ruffyscripter.RuffyCommandsV1Impl;
|
import de.jotomo.ruffyscripter.RuffyCommandsV1Impl;
|
||||||
|
@ -44,7 +38,6 @@ import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
|
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
|
||||||
import info.nightscout.androidaps.plugins.PumpCombo.events.EventComboPumpUpdateGUI;
|
import info.nightscout.androidaps.plugins.PumpCombo.events.EventComboPumpUpdateGUI;
|
||||||
import info.nightscout.utils.DateUtil;
|
import info.nightscout.utils.DateUtil;
|
||||||
import info.nightscout.utils.SP;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 05.08.2016.
|
* Created by mike on 05.08.2016.
|
||||||
|
@ -205,23 +198,24 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public Date lastDataTime() {
|
public Date lastDataTime() {
|
||||||
CommandResult lastCmdResult = pump.lastCmdResult;
|
return new Date(pump.lastSuccessfulConnection);
|
||||||
return lastCmdResult != null ? new Date(lastCmdResult.completionTime) : new Date(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void refreshDataFromPump(String reason) {
|
public synchronized void refreshDataFromPump(String reason) {
|
||||||
log.debug("RefreshDataFromPump called");
|
log.debug("RefreshDataFromPump called");
|
||||||
|
|
||||||
if (pump.lastCmdResult == null) {
|
boolean firstRun = pump.lastCmdResult == null;
|
||||||
|
|
||||||
|
runCommand("Refreshing", new CommandExecution() {
|
||||||
|
@Override
|
||||||
|
public CommandResult execute() {
|
||||||
|
return ruffyScripter.readHistory(new PumpHistoryRequest().reservoirLevel(true).bolusHistory(PumpHistoryRequest.LAST));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (firstRun) {
|
||||||
initializePump();
|
initializePump();
|
||||||
} else {
|
|
||||||
runCommand("Refreshing", new CommandExecution() {
|
|
||||||
@Override
|
|
||||||
public CommandResult execute() {
|
|
||||||
return ruffyScripter.readHistory(new PumpHistoryRequest().reservoirLevel(true).bolusHistory(PumpHistoryRequest.LAST));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,8 +579,10 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CommandResult runCommand(String status, boolean checkTbrMisMatch, CommandExecution commandExecution) {
|
private CommandResult runCommand(String activity, boolean checkTbrMisMatch, CommandExecution commandExecution) {
|
||||||
MainApp.bus().post(new EventComboPumpUpdateGUI(status));
|
pump.activity = activity;
|
||||||
|
MainApp.bus().post(new EventComboPumpUpdateGUI());
|
||||||
|
|
||||||
CommandResult commandResult = commandExecution.execute();
|
CommandResult commandResult = commandExecution.execute();
|
||||||
|
|
||||||
if (commandResult.success) {
|
if (commandResult.success) {
|
||||||
|
@ -606,17 +602,19 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
||||||
// get the current state, then decide what makes sense to do further, if anything,
|
// get the current state, then decide what makes sense to do further, if anything,
|
||||||
// send next request.
|
// send next request.
|
||||||
// then request state again ... ?
|
// then request state again ... ?
|
||||||
if (commandResult.state.errorMsg != null) {
|
// TODO rethink this errorMsg field;
|
||||||
|
|
||||||
|
/* if (commandResult.state.errorMsg != null) {
|
||||||
CommandResult takeOverAlarmResult = ruffyScripter.takeOverAlarms();
|
CommandResult takeOverAlarmResult = ruffyScripter.takeOverAlarms();
|
||||||
|
|
||||||
for (Error error : takeOverAlarmResult.history.errorHistory) {
|
for (PumpError pumpError : takeOverAlarmResult.history.pumpErrorHistory) {
|
||||||
MainApp.bus().post(new EventNewNotification(
|
MainApp.bus().post(new EventNewNotification(
|
||||||
new Notification(Notification.COMBO_PUMP_ERROR,
|
new Notification(Notification.COMBO_PUMP_ALARM,
|
||||||
"Pump alarm: " + error.message, Notification.URGENT)));
|
"Pump alarm: " + pumpError.message, Notification.URGENT)));
|
||||||
}
|
}
|
||||||
|
|
||||||
commandResult.state = takeOverAlarmResult.state;
|
commandResult.state = takeOverAlarmResult.state;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
pump.lastCmdResult = commandResult;
|
pump.lastCmdResult = commandResult;
|
||||||
pump.state = commandResult.state;
|
pump.state = commandResult.state;
|
||||||
|
@ -632,20 +630,21 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
||||||
log.error("JOE: no!");
|
log.error("JOE: no!");
|
||||||
} else {
|
} else {
|
||||||
// still crashable ...
|
// still crashable ...
|
||||||
|
// TODO only update if command was successful? -> KeepAliveReceiver, triggering alarm on unavaiblae pump
|
||||||
pump.lastCmdResult.completionTime = System.currentTimeMillis();
|
pump.lastCmdResult.completionTime = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TOOD
|
// TODO merge all new history here?
|
||||||
if (commandResult.history != null) {
|
if (commandResult.history != null) {
|
||||||
if (commandResult.history.reservoirLevel != -1) {
|
if (commandResult.history.reservoirLevel != -1) {
|
||||||
pump.reservoirLevel = commandResult.history.reservoirLevel;
|
pump.reservoirLevel = commandResult.history.reservoirLevel;
|
||||||
}
|
}
|
||||||
pump.history = commandResult.history;
|
pump.history = commandResult.history;
|
||||||
if (pump.history.bolusHistory.size() > 0) {
|
|
||||||
pump.lastBolus = pump.history.bolusHistory.get(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO in the event of an error schedule a resync
|
||||||
|
|
||||||
|
pump.activity = null;
|
||||||
MainApp.bus().post(new EventComboPumpUpdateGUI());
|
MainApp.bus().post(new EventComboPumpUpdateGUI());
|
||||||
return commandResult;
|
return commandResult;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,16 +10,17 @@ import de.jotomo.ruffy.spi.history.Bolus;
|
||||||
import de.jotomo.ruffy.spi.history.PumpHistory;
|
import de.jotomo.ruffy.spi.history.PumpHistory;
|
||||||
|
|
||||||
class ComboPump {
|
class ComboPump {
|
||||||
public long lastSuccessfulConnection;
|
// TODO actually ... this isn't about successful command execution, but whether we could connect to the pump at all
|
||||||
public long lastConnectionAttempt;
|
volatile long lastSuccessfulConnection;
|
||||||
|
volatile long lastConnectionAttempt;
|
||||||
@Nullable
|
@Nullable
|
||||||
volatile CommandResult lastCmdResult;
|
volatile CommandResult lastCmdResult;
|
||||||
|
|
||||||
|
public volatile String activity;
|
||||||
@NonNull
|
@NonNull
|
||||||
volatile PumpState state = new PumpState();
|
volatile PumpState state = new PumpState();
|
||||||
@NonNull
|
|
||||||
volatile PumpHistory history = new PumpHistory();
|
|
||||||
@Nullable
|
|
||||||
volatile Bolus lastBolus;
|
|
||||||
volatile int reservoirLevel = -1;
|
volatile int reservoirLevel = -1;
|
||||||
|
@NonNull
|
||||||
|
|
||||||
|
volatile PumpHistory history = new PumpHistory();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,4 @@ package info.nightscout.androidaps.plugins.PumpCombo.events;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class EventComboPumpUpdateGUI {
|
public class EventComboPumpUpdateGUI {
|
||||||
public EventComboPumpUpdateGUI() {}
|
|
||||||
|
|
||||||
public EventComboPumpUpdateGUI(String status) {
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String status;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ public class KeepAliveReceiver extends BroadcastReceiver {
|
||||||
// fixing the problem takes longer (or is not immediately possible because the pump was forgotten)?
|
// fixing the problem takes longer (or is not immediately possible because the pump was forgotten)?
|
||||||
// suppress this for another 25m if the message was dismissed?
|
// suppress this for another 25m if the message was dismissed?
|
||||||
// The alarm sound is played back as regular media, that means it might be muted if sound level is at 0
|
// The alarm sound is played back as regular media, that means it might be muted if sound level is at 0
|
||||||
|
// a simple 'Enable/disable alarms' button on the actions tab?
|
||||||
Notification n = new Notification(Notification.PUMP_UNREACHABLE, "Pump unreachable", Notification.URGENT);
|
Notification n = new Notification(Notification.PUMP_UNREACHABLE, "Pump unreachable", Notification.URGENT);
|
||||||
n.soundId = R.raw.alarm;
|
n.soundId = R.raw.alarm;
|
||||||
MainApp.bus().post(new EventNewNotification(n));
|
MainApp.bus().post(new EventNewNotification(n));
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
android:layout_weight="1.5"
|
android:layout_weight="1.5"
|
||||||
android:gravity="end"
|
android:gravity="end"
|
||||||
android:paddingRight="5dp"
|
android:paddingRight="5dp"
|
||||||
android:text="Status"
|
android:text="State"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -43,14 +43,13 @@
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/combo_status"
|
android:id="@+id/combo_state"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:gravity="start"
|
android:gravity="start"
|
||||||
android:paddingLeft="5dp"
|
android:paddingLeft="5dp"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:text="Initializating"
|
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@ -145,6 +144,51 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="2dip"
|
||||||
|
android:layout_marginBottom="5dp"
|
||||||
|
android:layout_marginLeft="20dp"
|
||||||
|
android:layout_marginRight="20dp"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:background="@color/listdelimiter" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1.5"
|
||||||
|
android:gravity="end"
|
||||||
|
android:paddingRight="5dp"
|
||||||
|
android:text="Activity"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="5dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:paddingEnd="2dp"
|
||||||
|
android:paddingStart="2dp"
|
||||||
|
android:text=":"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/combo_activity"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="start"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:textColor="@android:color/white"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="2dip"
|
android:layout_height="2dip"
|
||||||
|
@ -316,17 +360,6 @@
|
||||||
android:paddingRight="0dp"
|
android:paddingRight="0dp"
|
||||||
android:text="@string/combo_refresh" />
|
android:text="@string/combo_refresh" />
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/combo_history"
|
|
||||||
style="@style/ButtonSmallFontStyle"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:drawableTop="@drawable/icon_danarhistory"
|
|
||||||
android:paddingLeft="0dp"
|
|
||||||
android:paddingRight="0dp"
|
|
||||||
android:text="@string/pump_history" />
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/combo_stats"
|
android:id="@+id/combo_stats"
|
||||||
style="@style/ButtonSmallFontStyle"
|
style="@style/ButtonSmallFontStyle"
|
||||||
|
@ -336,8 +369,20 @@
|
||||||
android:drawableTop="@drawable/icon_danarstats"
|
android:drawableTop="@drawable/icon_danarstats"
|
||||||
android:paddingLeft="0dp"
|
android:paddingLeft="0dp"
|
||||||
android:paddingRight="0dp"
|
android:paddingRight="0dp"
|
||||||
|
android:visibility="gone"
|
||||||
android:text="@string/combo_stats" />
|
android:text="@string/combo_stats" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/combo_error_history"
|
||||||
|
style="@style/ButtonSmallFontStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:drawableTop="@drawable/icon_cp_aaps_offline"
|
||||||
|
android:paddingLeft="0dp"
|
||||||
|
android:paddingRight="0dp"
|
||||||
|
android:text="@string/pump_errors_history" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -269,7 +269,7 @@
|
||||||
<string name="danarprofile_dia">DIA [h]</string>
|
<string name="danarprofile_dia">DIA [h]</string>
|
||||||
<string name="danarprofile_dia_summary">Duration of Insulin Activity</string>
|
<string name="danarprofile_dia_summary">Duration of Insulin Activity</string>
|
||||||
<string name="failedupdatebasalprofile">Failed to update basal profile</string>
|
<string name="failedupdatebasalprofile">Failed to update basal profile</string>
|
||||||
<string name="pump_history">History</string>
|
<string name="pump_errors_history">Errors</string>
|
||||||
<string name="danar_historyreload">Reload</string>
|
<string name="danar_historyreload">Reload</string>
|
||||||
<string name="uploading">Uploading</string>
|
<string name="uploading">Uploading</string>
|
||||||
<string name="danar_ebolus">E bolus</string>
|
<string name="danar_ebolus">E bolus</string>
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
package de.jotomo.ruffy.spi;
|
package de.jotomo.ruffy.spi;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/** State displayed on the main screen of the pump. */
|
/** State displayed on the main screen of the pump. */
|
||||||
public class PumpState {
|
public class PumpState {
|
||||||
public Date timestamp = new Date();
|
public String menu = null;
|
||||||
public boolean tbrActive = false;
|
public boolean tbrActive = false;
|
||||||
/** TBR percentage. 100% means no TBR active, just the normal basal rate running. */
|
/** TBR percentage. 100% means no TBR active, just the normal basal rate running. */
|
||||||
public int tbrPercent = -1;
|
public int tbrPercent = -1;
|
||||||
|
@ -30,6 +28,11 @@ public class PumpState {
|
||||||
|
|
||||||
public int activeBasalProfileNumber;
|
public int activeBasalProfileNumber;
|
||||||
|
|
||||||
|
public PumpState menu(String menu) {
|
||||||
|
this.menu = menu;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public PumpState tbrActive(boolean tbrActive) {
|
public PumpState tbrActive(boolean tbrActive) {
|
||||||
this.tbrActive = tbrActive;
|
this.tbrActive = tbrActive;
|
||||||
return this;
|
return this;
|
||||||
|
@ -76,17 +79,19 @@ public class PumpState {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStateSummary() {
|
public String getStateSummary() {
|
||||||
if (errorMsg != null)
|
if (menu == null)
|
||||||
return errorMsg;
|
return "Unreachable";
|
||||||
|
else if (suspended && (batteryState == EMPTY || insulinState == EMPTY))
|
||||||
|
return "Suspended due to error";
|
||||||
else if (suspended)
|
else if (suspended)
|
||||||
return "Suspended";
|
return "Suspended by user";
|
||||||
return "Running";
|
return "Running";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "PumpState{" +
|
return "PumpState{" +
|
||||||
"timestamp=" + timestamp +
|
"menu=" + menu +
|
||||||
", tbrActive=" + tbrActive +
|
", tbrActive=" + tbrActive +
|
||||||
", tbrPercent=" + tbrPercent +
|
", tbrPercent=" + tbrPercent +
|
||||||
", tbrRate=" + tbrRate +
|
", tbrRate=" + tbrRate +
|
||||||
|
|
|
@ -13,14 +13,73 @@ public interface RuffyCommands {
|
||||||
|
|
||||||
CommandResult cancelTbr();
|
CommandResult cancelTbr();
|
||||||
|
|
||||||
|
// TODO read Dana code wrt to syncing and such
|
||||||
|
|
||||||
/** Confirms an active alarm on the pump. The state returned is the state after the alarm
|
/** Confirms an active alarm on the pump. The state returned is the state after the alarm
|
||||||
* has been confirmed. Confirmed alerts are returned in history.errorHistory. */
|
* has been confirmed. Confirmed alerts are returned in history.pumpErrorHistory. */
|
||||||
|
@Deprecated
|
||||||
|
// TODO rename to confirmActiveAlarm (single)
|
||||||
|
// add a field activeAlarm to PumpState and put logic in ComboPlugin.
|
||||||
CommandResult takeOverAlarms();
|
CommandResult takeOverAlarms();
|
||||||
|
// let this be an actual command in RS? or extend readPumpState wit ha flag to return confirmed errors?
|
||||||
|
|
||||||
|
/* plan:
|
||||||
|
|
||||||
|
let errors ring on the pump (all require interacting with the pump anyways and they
|
||||||
|
should not be subject to errors in AAPS/ruffy.
|
||||||
|
|
||||||
|
When connecting to the pump, read the current state. If a warning(s) is ongoing
|
||||||
|
confirm it and forward it and let AAPS display it.
|
||||||
|
Check if a previous command failed (tbr/bolus) and if so, DON'T report a warning
|
||||||
|
caused by an interrupted command.
|
||||||
|
Put the logic in AAPS: don't have readPumpState automatically confirm anything,
|
||||||
|
but read state, call takeOverAlarm(alarm)
|
||||||
|
|
||||||
|
concrete warnings???
|
||||||
|
tbr cancelled => we can almost always just confirm this, we sync aaps if neded
|
||||||
|
bolus => basically the same with SMBs, for user-initiated boluses and error should be reported
|
||||||
|
properly, but that should work since it's interactive and PumpEneact result is
|
||||||
|
or should be checked (verify it is)
|
||||||
|
deliwerTreatment knows if it's SMB or not, whether it's okay to dismiss bolus cancelled alarm.
|
||||||
|
|
||||||
|
battery low => always forward (not configurable, whole point is to make AAPS master)
|
||||||
|
cartridge low => always forward
|
||||||
|
|
||||||
|
when sync detects a significant mismatch it should alert?
|
||||||
|
big bolus on pump aaps didn't knew about???
|
||||||
|
removing a big bolus in aaps db since it's not in pump history? warn? aaps bug.
|
||||||
|
|
||||||
|
==> think this whole comm errors thing through (incl. auto/reconnect, auto-confirm
|
||||||
|
), on LoD - 1 and go back to coding after that
|
||||||
|
|
||||||
|
open: dealing with low cartridge/battery during bolus.
|
||||||
|
also: dealing with empty cartridge/battery alarms we let ring (force resync
|
||||||
|
when 'next possible'. force resync when coming from a suspended state, or any
|
||||||
|
error state in general.
|
||||||
|
if cartridge is low, check reservoir before each bolus and don't attempt
|
||||||
|
to bolus if not enough in reservoir for bolus?
|
||||||
|
(testers: bolus with cartridge very low to run in such scenarios - forget the
|
||||||
|
cartridge is low).
|
||||||
|
|
||||||
|
so: * confirm pump warnings; for tbr/bolus cancelled caused by connection loss don't
|
||||||
|
report them to the user (on disconnect set a flag 'error caused by us' or use.
|
||||||
|
also note connection lose and force history resync if appropriate(?) (LAST).
|
||||||
|
* stuff low warnings: confirm, show in combo tab and give overview notification
|
||||||
|
* keepaliver receiver raises an urgent error if there have been no pump comms in
|
||||||
|
> 25m
|
||||||
|
* errors always ring on the pump, are critical and require the pump to be interacted
|
||||||
|
with, so they're not confirmed. if encountered, they're read and also reported as
|
||||||
|
urgent on the phone. cancel again if we see the user has confirmed them on the pump?
|
||||||
|
(parent monitoring, needing to see an error).
|
||||||
|
make Combo->Status red and "Occlusion" for errors?
|
||||||
|
*/
|
||||||
|
|
||||||
boolean isPumpAvailable();
|
boolean isPumpAvailable();
|
||||||
|
|
||||||
boolean isPumpBusy();
|
boolean isPumpBusy();
|
||||||
|
|
||||||
|
// start everything with this: read pump state.
|
||||||
|
// see if there's an error active.
|
||||||
CommandResult readPumpState();
|
CommandResult readPumpState();
|
||||||
|
|
||||||
CommandResult readHistory(PumpHistoryRequest request);
|
CommandResult readHistory(PumpHistoryRequest request);
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package de.jotomo.ruffy.spi.history;
|
package de.jotomo.ruffy.spi.history;
|
||||||
|
|
||||||
public class Error extends HistoryRecord {
|
public class PumpError extends HistoryRecord {
|
||||||
/** Code is an E for error or W for warning, followed by a single digit, e.g. W7 (TBR cancelled). */
|
/** Code is an E for error or W for warning, followed by a single digit, e.g. W7 (TBR cancelled). */
|
||||||
public final String code;
|
public final String code;
|
||||||
/** Error message, in the language configured on the pump. */
|
/** Error message, in the language configured on the pump. */
|
||||||
public final String message;
|
public final String message;
|
||||||
|
|
||||||
public Error(long timestamp, String code, String message) {
|
public PumpError(long timestamp, String code, String message) {
|
||||||
super(timestamp);
|
super(timestamp);
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.message = message;
|
this.message = message;
|
|
@ -3,7 +3,6 @@ package de.jotomo.ruffy.spi.history;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class PumpHistory {
|
public class PumpHistory {
|
||||||
|
@ -13,7 +12,7 @@ public class PumpHistory {
|
||||||
@NonNull
|
@NonNull
|
||||||
public List<Tbr> tbrHistory = new ArrayList<>();
|
public List<Tbr> tbrHistory = new ArrayList<>();
|
||||||
@NonNull
|
@NonNull
|
||||||
public List<Error> errorHistory = new ArrayList<>();
|
public List<PumpError> pumpErrorHistory = new ArrayList<>();
|
||||||
@NonNull
|
@NonNull
|
||||||
public List<Tdd> tddHistory = new ArrayList<>();
|
public List<Tdd> tddHistory = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -33,8 +32,8 @@ public class PumpHistory {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PumpHistory errorHistory(List<Error> errorHistory) {
|
public PumpHistory errorHistory(List<PumpError> pumpErrorHistory) {
|
||||||
this.errorHistory = errorHistory;
|
this.pumpErrorHistory = pumpErrorHistory;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +48,7 @@ public class PumpHistory {
|
||||||
"reservoirLevel=" + reservoirLevel +
|
"reservoirLevel=" + reservoirLevel +
|
||||||
", bolusHistory=" + bolusHistory.size() +
|
", bolusHistory=" + bolusHistory.size() +
|
||||||
", tbrHistory=" + tbrHistory.size() +
|
", tbrHistory=" + tbrHistory.size() +
|
||||||
", errorHistory=" + errorHistory.size() +
|
", pumpErrorHistory=" + pumpErrorHistory.size() +
|
||||||
", tddHistory=" + tddHistory.size() +
|
", tddHistory=" + tddHistory.size() +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ public class PumpHistoryRequest {
|
||||||
|
|
||||||
public long bolusHistory = SKIP;
|
public long bolusHistory = SKIP;
|
||||||
public long tbrHistory = SKIP;
|
public long tbrHistory = SKIP;
|
||||||
public long errorHistory = SKIP;
|
public long pumpErrorHistory = SKIP;
|
||||||
public long tddHistory = SKIP;
|
public long tddHistory = SKIP;
|
||||||
|
|
||||||
public PumpHistoryRequest reservoirLevel(boolean reservoirLevel) {
|
public PumpHistoryRequest reservoirLevel(boolean reservoirLevel) {
|
||||||
|
@ -33,7 +33,7 @@ public class PumpHistoryRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public PumpHistoryRequest errorHistory(long errorHistory) {
|
public PumpHistoryRequest errorHistory(long errorHistory) {
|
||||||
this.errorHistory = errorHistory;
|
this.pumpErrorHistory = errorHistory;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ public class PumpHistoryRequest {
|
||||||
"reservoirLevel=" + reservoirLevel +
|
"reservoirLevel=" + reservoirLevel +
|
||||||
", bolusHistory=" + bolusHistory +
|
", bolusHistory=" + bolusHistory +
|
||||||
", tbrHistory=" + tbrHistory +
|
", tbrHistory=" + tbrHistory +
|
||||||
", errorHistory=" + errorHistory +
|
", pumpErrorHistory=" + pumpErrorHistory +
|
||||||
", tddHistory=" + tddHistory +
|
", tddHistory=" + tddHistory +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ import de.jotomo.ruffy.spi.BolusProgressReporter;
|
||||||
import de.jotomo.ruffy.spi.CommandResult;
|
import de.jotomo.ruffy.spi.CommandResult;
|
||||||
import de.jotomo.ruffy.spi.PumpState;
|
import de.jotomo.ruffy.spi.PumpState;
|
||||||
import de.jotomo.ruffy.spi.RuffyCommands;
|
import de.jotomo.ruffy.spi.RuffyCommands;
|
||||||
import de.jotomo.ruffy.spi.history.Error;
|
|
||||||
import de.jotomo.ruffy.spi.history.PumpHistoryRequest;
|
import de.jotomo.ruffy.spi.history.PumpHistoryRequest;
|
||||||
import de.jotomo.ruffyscripter.commands.BolusCommand;
|
import de.jotomo.ruffyscripter.commands.BolusCommand;
|
||||||
import de.jotomo.ruffyscripter.commands.CancelTbrCommand;
|
import de.jotomo.ruffyscripter.commands.CancelTbrCommand;
|
||||||
|
@ -40,6 +39,7 @@ import de.jotomo.ruffyscripter.commands.ReadHistoryCommand;
|
||||||
import de.jotomo.ruffyscripter.commands.ReadPumpStateCommand;
|
import de.jotomo.ruffyscripter.commands.ReadPumpStateCommand;
|
||||||
import de.jotomo.ruffyscripter.commands.SetBasalProfileCommand;
|
import de.jotomo.ruffyscripter.commands.SetBasalProfileCommand;
|
||||||
import de.jotomo.ruffyscripter.commands.SetTbrCommand;
|
import de.jotomo.ruffyscripter.commands.SetTbrCommand;
|
||||||
|
import de.jotomo.ruffyscripter.commands.TakeOverAlarmsCommand;
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -256,12 +256,12 @@ public class RuffyScripter implements RuffyCommands {
|
||||||
return new CommandResult().message(Joiner.on("\n").join(violations)).state(readPumpStateInternal());
|
return new CommandResult().message(Joiner.on("\n").join(violations)).state(readPumpStateInternal());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO simplify, hard to reason about exists
|
||||||
synchronized (RuffyScripter.class) {
|
synchronized (RuffyScripter.class) {
|
||||||
try {
|
try {
|
||||||
activeCmd = cmd;
|
activeCmd = cmd;
|
||||||
long connectStart = System.currentTimeMillis();
|
long connectStart = System.currentTimeMillis();
|
||||||
ensureConnected();
|
ensureConnected();
|
||||||
final RuffyScripter scripter = this;
|
|
||||||
final Returnable returnable = new Returnable();
|
final Returnable returnable = new Returnable();
|
||||||
class CommandRunner {
|
class CommandRunner {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -294,7 +294,7 @@ public class RuffyScripter implements RuffyCommands {
|
||||||
PumpState pumpState = readPumpStateInternal();
|
PumpState pumpState = readPumpStateInternal();
|
||||||
log.debug("Pump state before running command: " + pumpState);
|
log.debug("Pump state before running command: " + pumpState);
|
||||||
long cmdStartTime = System.currentTimeMillis();
|
long cmdStartTime = System.currentTimeMillis();
|
||||||
cmd.setScripter(scripter);
|
cmd.setScripter(RuffyScripter.this);
|
||||||
returnable.cmdResult = cmd.execute();
|
returnable.cmdResult = cmd.execute();
|
||||||
long cmdEndTime = System.currentTimeMillis();
|
long cmdEndTime = System.currentTimeMillis();
|
||||||
returnable.cmdResult.completionTime = cmdEndTime;
|
returnable.cmdResult.completionTime = cmdEndTime;
|
||||||
|
@ -333,6 +333,11 @@ public class RuffyScripter implements RuffyCommands {
|
||||||
reconnect();
|
reconnect();
|
||||||
// TODO at least for bigger boluses we should check history after reconnect to make sure
|
// TODO at least for bigger boluses we should check history after reconnect to make sure
|
||||||
// we haven't issued that bolus within the last 1-2m? in case there's a bug in the code ...
|
// we haven't issued that bolus within the last 1-2m? in case there's a bug in the code ...
|
||||||
|
|
||||||
|
// TODO: only do the reconnect to confirm the alert, then return and let the ComboPlugin decide what to do next;
|
||||||
|
// for bolus: how ... run 'step 2': checking/reading history?! step1 being bolus delivery, so have different resume points? ggrrrmpf
|
||||||
|
// less logic in scripter; just reconnect to confirm alert if needed, then return with error;
|
||||||
|
// let CP read history.LAST to see what actually happened and then resume appropriately.
|
||||||
cmdThread = new Thread(new Runnable() {
|
cmdThread = new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -421,6 +426,11 @@ public class RuffyScripter implements RuffyCommands {
|
||||||
ensureConnected();
|
ensureConnected();
|
||||||
if (getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) {
|
if (getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) {
|
||||||
String errorMessage = (String) getCurrentMenu().getAttribute(MenuAttribute.MESSAGE);
|
String errorMessage = (String) getCurrentMenu().getAttribute(MenuAttribute.MESSAGE);
|
||||||
|
// TODO bolus cancelled is raised BEFORE a bolus is started. if disconnect occurs after
|
||||||
|
// bolus has started (or the user interacts with the pump, the bolus continues.
|
||||||
|
// in that case, reconnecting and restarting the command lets to a DUPLICATE bolus.
|
||||||
|
// add a method restartAllowed(), which accesses a flag bolusDelivering started, which
|
||||||
|
// is set false then?
|
||||||
if (activeCmd.getReconnectAlarm() != null && activeCmd.getReconnectAlarm().equals(errorMessage)) {
|
if (activeCmd.getReconnectAlarm() != null && activeCmd.getReconnectAlarm().equals(errorMessage)) {
|
||||||
log.debug("Confirming alert caused by disconnect: " + errorMessage);
|
log.debug("Confirming alert caused by disconnect: " + errorMessage);
|
||||||
// confirm alert
|
// confirm alert
|
||||||
|
@ -454,6 +464,7 @@ public class RuffyScripter implements RuffyCommands {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// aren't at main_menu after alert anyways? unless bolus i still going (also main_menu); low cartridge on bolus needs to be handled specially, by bolus command
|
||||||
returnToRootMenu();
|
returnToRootMenu();
|
||||||
|
|
||||||
return getCurrentMenu().getType() == MenuType.MAIN_MENU;
|
return getCurrentMenu().getType() == MenuType.MAIN_MENU;
|
||||||
|
@ -530,9 +541,12 @@ public class RuffyScripter implements RuffyCommands {
|
||||||
PumpState state = new PumpState();
|
PumpState state = new PumpState();
|
||||||
Menu menu = currentMenu;
|
Menu menu = currentMenu;
|
||||||
if (menu == null) {
|
if (menu == null) {
|
||||||
return new PumpState().errorMsg("Menu is not available");
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuType menuType = menu.getType();
|
MenuType menuType = menu.getType();
|
||||||
|
state.menu = menuType.name();
|
||||||
|
|
||||||
if (menuType == MenuType.MAIN_MENU) {
|
if (menuType == MenuType.MAIN_MENU) {
|
||||||
Double tbrPercentage = (Double) menu.getAttribute(MenuAttribute.TBR);
|
Double tbrPercentage = (Double) menu.getAttribute(MenuAttribute.TBR);
|
||||||
if (tbrPercentage != 100) {
|
if (tbrPercentage != 100) {
|
||||||
|
@ -545,10 +559,6 @@ public class RuffyScripter implements RuffyCommands {
|
||||||
}
|
}
|
||||||
state.batteryState = ((int) menu.getAttribute(MenuAttribute.BATTERY_STATE));
|
state.batteryState = ((int) menu.getAttribute(MenuAttribute.BATTERY_STATE));
|
||||||
state.insulinState = ((int) menu.getAttribute(MenuAttribute.INSULIN_STATE));
|
state.insulinState = ((int) menu.getAttribute(MenuAttribute.INSULIN_STATE));
|
||||||
// TODO v2, read current base basal rate, which is shown center when no TBR is active.
|
|
||||||
// Check if that holds true when an extended bolus is running.
|
|
||||||
// Add a field to PumpStatus, rather than renaming/overloading tbrRate to mean
|
|
||||||
// either TBR rate or basal rate depending on whether a TBR is active.
|
|
||||||
} else if (menuType == MenuType.WARNING_OR_ERROR) {
|
} else if (menuType == MenuType.WARNING_OR_ERROR) {
|
||||||
state.errorMsg = (String) menu.getAttribute(MenuAttribute.MESSAGE);
|
state.errorMsg = (String) menu.getAttribute(MenuAttribute.MESSAGE);
|
||||||
} else if (menuType == MenuType.STOP) {
|
} else if (menuType == MenuType.STOP) {
|
||||||
|
@ -556,14 +566,7 @@ public class RuffyScripter implements RuffyCommands {
|
||||||
state.batteryState = ((int) menu.getAttribute(MenuAttribute.BATTERY_STATE));
|
state.batteryState = ((int) menu.getAttribute(MenuAttribute.BATTERY_STATE));
|
||||||
state.insulinState = ((int) menu.getAttribute(MenuAttribute.INSULIN_STATE));
|
state.insulinState = ((int) menu.getAttribute(MenuAttribute.INSULIN_STATE));
|
||||||
} else {
|
} else {
|
||||||
StringBuilder sb = new StringBuilder();
|
// just return the PumpState with the menu set
|
||||||
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;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -619,6 +622,7 @@ public class RuffyScripter implements RuffyCommands {
|
||||||
// TODO this is probably due to a disconnect and rtDisconnect having nulled currentMenu.
|
// TODO this is probably due to a disconnect and rtDisconnect having nulled currentMenu.
|
||||||
// This here might just work, but needs a more controlled approach when implementing
|
// This here might just work, but needs a more controlled approach when implementing
|
||||||
// something to deal with connection loses
|
// something to deal with connection loses
|
||||||
|
// TODO force reconnect? and retry?
|
||||||
while (currentMenu == null) {
|
while (currentMenu == null) {
|
||||||
if (System.currentTimeMillis() > timeout) {
|
if (System.currentTimeMillis() > timeout) {
|
||||||
throw new CommandException().message("Unable to read current menu");
|
throw new CommandException().message("Unable to read current menu");
|
||||||
|
@ -630,14 +634,9 @@ public class RuffyScripter implements RuffyCommands {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pressUpKey() {
|
public void pressUpKey() {
|
||||||
// wrapNoNotTheSubwayKind(new Step() {
|
|
||||||
// @Override
|
|
||||||
// public void doStep() {
|
|
||||||
log.debug("Pressing up key");
|
log.debug("Pressing up key");
|
||||||
pressKey(Key.UP);
|
pressKey(Key.UP);
|
||||||
log.debug("Releasing up key");
|
log.debug("Releasing up key");
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pressDownKey() {
|
public void pressDownKey() {
|
||||||
|
@ -742,7 +741,7 @@ public class RuffyScripter implements RuffyCommands {
|
||||||
waitForMenuUpdate(60, "Timeout waiting for menu update");
|
waitForMenuUpdate(60, "Timeout waiting for menu update");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForMenuUpdate(long timeoutInSeconds, String errorMessage) {
|
private void waitForMenuUpdate(long timeoutInSeconds, String errorMessage) {
|
||||||
long timeoutExpired = System.currentTimeMillis() + timeoutInSeconds * 1000;
|
long timeoutExpired = System.currentTimeMillis() + timeoutInSeconds * 1000;
|
||||||
long initialUpdateTime = menuLastUpdated;
|
long initialUpdateTime = menuLastUpdated;
|
||||||
while (initialUpdateTime == menuLastUpdated) {
|
while (initialUpdateTime == menuLastUpdated) {
|
||||||
|
@ -869,32 +868,7 @@ public class RuffyScripter implements RuffyCommands {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandResult takeOverAlarms() {
|
public CommandResult takeOverAlarms() {
|
||||||
if (getCurrentMenu().getType() != MenuType.WARNING_OR_ERROR) {
|
return runCommand(new TakeOverAlarmsCommand());
|
||||||
return new CommandResult().success(false).enacted(false).message("No alarm active on the pump");
|
|
||||||
}
|
|
||||||
while (currentMenu.getType() == MenuType.WARNING_OR_ERROR) {
|
|
||||||
new Error(System.currentTimeMillis(),
|
|
||||||
"",
|
|
||||||
// TODO
|
|
||||||
// codes unqiue across W/E?
|
|
||||||
// (int) currentMenu.getAttribute(MenuAttribute.WARNING),
|
|
||||||
// (int) currentMenu.getAttribute(MenuAttribute.ERROR),
|
|
||||||
(String) currentMenu.getAttribute(MenuAttribute.MESSAGE));
|
|
||||||
}
|
|
||||||
// confirm alert
|
|
||||||
verifyMenuIsDisplayed(MenuType.WARNING_OR_ERROR);
|
|
||||||
pressCheckKey();
|
|
||||||
// dismiss alert
|
|
||||||
verifyMenuIsDisplayed(MenuType.WARNING_OR_ERROR);
|
|
||||||
pressCheckKey();
|
|
||||||
waitForMenuToBeLeft(MenuType.WARNING_OR_ERROR);
|
|
||||||
|
|
||||||
PumpState pumpState = readPumpStateInternal();
|
|
||||||
return new CommandResult()
|
|
||||||
.success(true)
|
|
||||||
.enacted(false /* well, no treatments were enacted ... */)
|
|
||||||
.message(pumpState.errorMsg) // todo yikes?
|
|
||||||
.state(pumpState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -26,6 +26,11 @@ public class BolusCommand extends BaseCommand {
|
||||||
private final BolusProgressReporter bolusProgressReporter;
|
private final BolusProgressReporter bolusProgressReporter;
|
||||||
private volatile boolean cancelRequested;
|
private volatile boolean cancelRequested;
|
||||||
|
|
||||||
|
// TODO make CommandResult a field that is updated as the command progress so that we can
|
||||||
|
// (also) see via cmdResult.enacted if something has been enacted and how safe it is to
|
||||||
|
// restart the command (also checking history of course, but lets double check this cruical
|
||||||
|
// part)
|
||||||
|
|
||||||
public BolusCommand(double bolus, BolusProgressReporter bolusProgressReporter) {
|
public BolusCommand(double bolus, BolusProgressReporter bolusProgressReporter) {
|
||||||
this.bolus = bolus;
|
this.bolus = bolus;
|
||||||
this.bolusProgressReporter = bolusProgressReporter;
|
this.bolusProgressReporter = bolusProgressReporter;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package de.jotomo.ruffyscripter.commands;
|
package de.jotomo.ruffyscripter.commands;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute;
|
import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute;
|
||||||
import org.monkey.d.ruffy.ruffy.driver.display.MenuType;
|
import org.monkey.d.ruffy.ruffy.driver.display.MenuType;
|
||||||
import org.monkey.d.ruffy.ruffy.driver.display.menu.BolusType;
|
import org.monkey.d.ruffy.ruffy.driver.display.menu.BolusType;
|
||||||
|
@ -30,50 +32,38 @@ public class ReadHistoryCommand extends BaseCommand {
|
||||||
}
|
}
|
||||||
if (request.bolusHistory != PumpHistoryRequest.SKIP
|
if (request.bolusHistory != PumpHistoryRequest.SKIP
|
||||||
|| request.tbrHistory != PumpHistoryRequest.SKIP
|
|| request.tbrHistory != PumpHistoryRequest.SKIP
|
||||||
|| request.errorHistory != PumpHistoryRequest.SKIP
|
|| request.pumpErrorHistory != PumpHistoryRequest.SKIP
|
||||||
|| request.tddHistory != PumpHistoryRequest.SKIP) {
|
|| request.tddHistory != PumpHistoryRequest.SKIP) {
|
||||||
scripter.navigateToMenu(MenuType.MY_DATA_MENU);
|
scripter.navigateToMenu(MenuType.MY_DATA_MENU);
|
||||||
scripter.verifyMenuIsDisplayed(MenuType.MY_DATA_MENU);
|
scripter.verifyMenuIsDisplayed(MenuType.MY_DATA_MENU);
|
||||||
scripter.pressCheckKey();
|
scripter.pressCheckKey();
|
||||||
|
|
||||||
|
// bolus history
|
||||||
scripter.verifyMenuIsDisplayed(MenuType.BOLUS_DATA);
|
scripter.verifyMenuIsDisplayed(MenuType.BOLUS_DATA);
|
||||||
if (request.bolusHistory != PumpHistoryRequest.SKIP) {
|
if (request.bolusHistory != PumpHistoryRequest.SKIP) {
|
||||||
if (request.bolusHistory == PumpHistoryRequest.LAST) {
|
int totalRecords = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.TOTAL_RECORD);
|
||||||
// Could also be extended, multiwave:
|
if (totalRecords > 0) {
|
||||||
BolusType bolusType = (BolusType) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_TYPE);
|
if (request.bolusHistory == PumpHistoryRequest.LAST) {
|
||||||
if (!bolusType.equals(BolusType.NORMAL)) {
|
Bolus bolus = readBolusRecord();
|
||||||
throw new CommandException().success(false).enacted(false).message("Unsupported bolus type encountered: " + bolusType);
|
history.bolusHistory.add(bolus);
|
||||||
|
} else {
|
||||||
|
readBolusRecords(request.bolusHistory);
|
||||||
}
|
}
|
||||||
Double bolus = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS);
|
|
||||||
MenuDate date = (MenuDate) scripter.getCurrentMenu().getAttribute(MenuAttribute.DATE);
|
|
||||||
MenuTime time = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.TIME);
|
|
||||||
// TODO handle year changes; if current month == 1 and record date == 12, use $YEAR-1
|
|
||||||
int currentMonth = new Date().getMonth() + 1;
|
|
||||||
int currentYear = new Date().getYear() + 1900;
|
|
||||||
if (currentMonth == 1 && date.getMonth() == 12) {
|
|
||||||
currentYear -= 1;
|
|
||||||
}
|
|
||||||
long recordDate = new Date(currentYear - 1900, date.getMonth() - 1, date.getDay(), time.getHour(), time.getMinute()).getTime();
|
|
||||||
history.bolusHistory.add(new Bolus(recordDate, bolus));
|
|
||||||
|
|
||||||
// int record = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.CURRENT_RECORD);
|
|
||||||
// int totalRecords = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.TOTAL_RECORD);
|
|
||||||
|
|
||||||
/*
|
|
||||||
read displayed date, bolus, add to history
|
|
||||||
while data > last known, press up to go through history
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// error history
|
||||||
scripter.pressMenuKey();
|
scripter.pressMenuKey();
|
||||||
scripter.verifyMenuIsDisplayed(MenuType.ERROR_DATA);
|
scripter.verifyMenuIsDisplayed(MenuType.ERROR_DATA);
|
||||||
if (request.errorHistory != PumpHistoryRequest.SKIP) {
|
if (request.pumpErrorHistory != PumpHistoryRequest.SKIP) {
|
||||||
int code = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.WARNING);
|
int code = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.WARNING);
|
||||||
String message = (String) scripter.getCurrentMenu().getAttribute(MenuAttribute.MESSAGE);
|
String message = (String) scripter.getCurrentMenu().getAttribute(MenuAttribute.MESSAGE);
|
||||||
MenuDate date = (MenuDate) scripter.getCurrentMenu().getAttribute(MenuAttribute.DATE);
|
MenuDate date = (MenuDate) scripter.getCurrentMenu().getAttribute(MenuAttribute.DATE);
|
||||||
MenuTime time = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.TIME);
|
MenuTime time = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.TIME);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tdd history
|
||||||
scripter.pressMenuKey();
|
scripter.pressMenuKey();
|
||||||
scripter.verifyMenuIsDisplayed(MenuType.DAILY_DATA);
|
scripter.verifyMenuIsDisplayed(MenuType.DAILY_DATA);
|
||||||
if (request.tddHistory != PumpHistoryRequest.SKIP) {
|
if (request.tddHistory != PumpHistoryRequest.SKIP) {
|
||||||
|
@ -81,6 +71,8 @@ public class ReadHistoryCommand extends BaseCommand {
|
||||||
MenuDate date = (MenuDate) scripter.getCurrentMenu().getAttribute(MenuAttribute.DATE);
|
MenuDate date = (MenuDate) scripter.getCurrentMenu().getAttribute(MenuAttribute.DATE);
|
||||||
MenuTime time = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.TIME);
|
MenuTime time = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tbr history
|
||||||
scripter.pressMenuKey();
|
scripter.pressMenuKey();
|
||||||
scripter.verifyMenuIsDisplayed(MenuType.TBR_DATA);
|
scripter.verifyMenuIsDisplayed(MenuType.TBR_DATA);
|
||||||
if (request.tbrHistory != PumpHistoryRequest.SKIP) {
|
if (request.tbrHistory != PumpHistoryRequest.SKIP) {
|
||||||
|
@ -90,13 +82,50 @@ public class ReadHistoryCommand extends BaseCommand {
|
||||||
// TODO start or end time?
|
// TODO start or end time?
|
||||||
MenuTime time = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.TIME);
|
MenuTime time = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
scripter.pressBackKey();
|
scripter.pressBackKey();
|
||||||
scripter.returnToRootMenu();
|
scripter.returnToRootMenu();
|
||||||
|
scripter.verifyRootMenuIsDisplayed();
|
||||||
}
|
}
|
||||||
scripter.verifyRootMenuIsDisplayed();
|
|
||||||
return new CommandResult().success(true).enacted(false).history(history);
|
return new CommandResult().success(true).enacted(false).history(history);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void readBolusRecords(long requestedTime) {
|
||||||
|
int record = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.CURRENT_RECORD);
|
||||||
|
int totalRecords = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.TOTAL_RECORD);
|
||||||
|
while (record <= totalRecords) {
|
||||||
|
Bolus bolus = readBolusRecord();
|
||||||
|
if (requestedTime != PumpHistoryRequest.FULL && bolus.timestamp < requestedTime) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
history.bolusHistory.add(bolus);
|
||||||
|
record = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.CURRENT_RECORD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private Bolus readBolusRecord() {
|
||||||
|
// Could also be extended, multiwave
|
||||||
|
BolusType bolusType = (BolusType) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_TYPE);
|
||||||
|
if (!bolusType.equals(BolusType.NORMAL)) {
|
||||||
|
throw new CommandException().success(false).enacted(false).message("Unsupported bolus type encountered: " + bolusType);
|
||||||
|
}
|
||||||
|
// TODO no bolus etc yet? How would that ever look?
|
||||||
|
Double bolus = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS);
|
||||||
|
MenuDate date = (MenuDate) scripter.getCurrentMenu().getAttribute(MenuAttribute.DATE);
|
||||||
|
MenuTime time = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.TIME);
|
||||||
|
|
||||||
|
// TODO handle year changes; if current month == 1 and record date == 12, use $YEAR-1
|
||||||
|
int currentMonth = new Date().getMonth() + 1;
|
||||||
|
int currentYear = new Date().getYear() + 1900;
|
||||||
|
if (currentMonth == 1 && date.getMonth() == 12) {
|
||||||
|
currentYear -= 1;
|
||||||
|
}
|
||||||
|
long recordDate = new Date(currentYear - 1900, date.getMonth() - 1, date.getDay(), time.getHour(), time.getMinute()).getTime();
|
||||||
|
return new Bolus(recordDate, bolus);
|
||||||
|
}
|
||||||
|
|
||||||
private void readReservoirLevel() {
|
private void readReservoirLevel() {
|
||||||
scripter.verifyRootMenuIsDisplayed();
|
scripter.verifyRootMenuIsDisplayed();
|
||||||
scripter.pressCheckKey();
|
scripter.pressCheckKey();
|
||||||
|
@ -112,4 +141,13 @@ public class ReadHistoryCommand extends BaseCommand {
|
||||||
public List<String> validateArguments() {
|
public List<String> validateArguments() {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ReadHistoryCommand{" +
|
||||||
|
"request=" + request +
|
||||||
|
", history=" + history +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
package de.jotomo.ruffyscripter.commands;
|
||||||
|
|
||||||
|
import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute;
|
||||||
|
import org.monkey.d.ruffy.ruffy.driver.display.MenuType;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.jotomo.ruffy.spi.CommandResult;
|
||||||
|
import de.jotomo.ruffy.spi.PumpState;
|
||||||
|
import de.jotomo.ruffy.spi.history.PumpError;
|
||||||
|
|
||||||
|
// TODO rename to ConfirmALarm(alarm) => logic in CP, just report back alarm, then explicitely confirm that one alarm.
|
||||||
|
// multiple alarms oncy occur for errors (battery/cartdige low/occlusion) => let ring.
|
||||||
|
public class TakeOverAlarmsCommand extends BaseCommand {
|
||||||
|
@Override
|
||||||
|
public CommandResult execute() {
|
||||||
|
if (scripter.getCurrentMenu().getType() != MenuType.WARNING_OR_ERROR) {
|
||||||
|
return new CommandResult().success(false).enacted(false).message("No alarm active on the pump");
|
||||||
|
}
|
||||||
|
while (scripter.getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) {
|
||||||
|
new PumpError(System.currentTimeMillis(),
|
||||||
|
"",
|
||||||
|
// TODO
|
||||||
|
// codes unqiue across W/E?
|
||||||
|
// (int) currentMenu.getAttribute(MenuAttribute.WARNING),
|
||||||
|
// (int) currentMenu.getAttribute(MenuAttribute.ERROR),
|
||||||
|
(String) scripter.getCurrentMenu().getAttribute(MenuAttribute.MESSAGE));
|
||||||
|
}
|
||||||
|
// confirm alert
|
||||||
|
scripter.verifyMenuIsDisplayed(MenuType.WARNING_OR_ERROR);
|
||||||
|
scripter.pressCheckKey();
|
||||||
|
// dismiss alert
|
||||||
|
scripter.verifyMenuIsDisplayed(MenuType.WARNING_OR_ERROR);
|
||||||
|
scripter.pressCheckKey();
|
||||||
|
scripter.waitForMenuToBeLeft(MenuType.WARNING_OR_ERROR);
|
||||||
|
|
||||||
|
PumpState pumpState = scripter.readPumpStateInternal();
|
||||||
|
return new CommandResult()
|
||||||
|
.success(true)
|
||||||
|
.enacted(false /* well, no treatments were enacted ... */)
|
||||||
|
// .message(pumpState.errorMsg) // todo yikes?
|
||||||
|
.state(pumpState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> validateArguments() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue