diff --git a/Combo-Setup.md b/README-Combo.md
similarity index 89%
rename from Combo-Setup.md
rename to README-Combo.md
index e009eb5909..e8f55d03a9 100644
--- a/Combo-Setup.md
+++ b/README-Combo.md
@@ -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
_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/_
+
+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
diff --git a/app/src/main/java/info/nightscout/androidaps/Constants.java b/app/src/main/java/info/nightscout/androidaps/Constants.java
index e37a5b4b9f..a2a5e58761 100644
--- a/app/src/main/java/info/nightscout/androidaps/Constants.java
+++ b/app/src/main/java/info/nightscout/androidaps/Constants.java
@@ -1,7 +1,5 @@
package info.nightscout.androidaps;
-import com.j256.ormlite.stmt.query.In;
-
/**
* Created by mike on 07.06.2016.
*/
@@ -24,7 +22,7 @@ public class Constants {
public static final int hoursToKeepInDatabase = 72;
public static final int daysToKeepHistoryInDatabase = 30;
- public static final long keepAliveMsecs = 5 * 60 * 1000L;
+ public static final long keepAliveMsecs = 60 * 1000L;
// SMS COMMUNICATOR
public static final long remoteBolusMinDistance = 15 * 60 * 1000L;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java
index dcf1da68d1..3aa3930d08 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java
@@ -30,7 +30,8 @@ import info.nightscout.utils.DecimalFormatter;
public class ComboFragment extends SubscriberFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(ComboFragment.class);
- private TextView statusView;
+ private TextView stateView;
+ private TextView activityView;
private TextView batteryView;
private TextView reservoirView;
private TextView lastConnectionView;
@@ -44,7 +45,8 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis
Bundle savedInstanceState) {
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);
reservoirView = (TextView) view.findViewById(R.id.combo_insulinstate);
lastConnectionView = (TextView) view.findViewById(R.id.combo_lastconnection);
@@ -70,52 +72,48 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis
});
thread.start();
break;
- case R.id.combo_history:
- // TODO show popup with warnings/errors from the pump
+ case R.id.combo_error_history:
+ // TODO show popup with pump errors and comm problems
break;
case R.id.combo_stats:
- // TODO show TDD stats from the pump
+ // TODO show TDD stats from the pump (later)
break;
}
}
@Subscribe
public void onStatusEvent(final EventComboPumpUpdateGUI ev) {
- if (ev.status != null) {
- Activity activity = getActivity();
- if (activity != null)
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- statusView.setText(ev.status);
- statusView.setTextColor(Color.WHITE);
- }
- });
- } else {
- updateGUI();
- }
+ updateGUI();
}
public void updateGUI() {
- Activity activity = getActivity();
+ final Activity activity = getActivity();
+ log.debug("aCtI: activity available? " + (activity != null));
if (activity != null)
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
ComboPlugin plugin = ComboPlugin.getPlugin();
+
+ // activity
+ String activity = plugin.getPump().activity;
+ activityView.setText(activity != null ? activity : "Idle");
+
if (plugin.isInitialized()) {
// status
- statusView.setText(plugin.getPump().state.getStateSummary());
- if (plugin.getPump().state.errorMsg != null) {
- statusView.setTextColor(Color.RED);
+ PumpState ps = plugin.getPump().state;
+ stateView.setText(plugin.getPump().state.getStateSummary());
+ if (plugin.getPump().state.errorMsg != null
+ || ps.insulinState == PumpState.EMPTY
+ || ps.batteryState == PumpState.EMPTY) {
+ stateView.setTextColor(Color.RED);
} else if (plugin.getPump().state.suspended) {
- statusView.setTextColor(Color.YELLOW);
+ stateView.setTextColor(Color.YELLOW);
} else {
- statusView.setTextColor(Color.WHITE);
+ stateView.setTextColor(Color.WHITE);
}
// battery
- PumpState ps = plugin.getPump().state;
if (ps.batteryState == PumpState.EMPTY) {
batteryView.setText("{fa-battery-empty}");
batteryView.setTextColor(Color.RED);
@@ -143,15 +141,14 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis
if (lastCmdResult != null) {
String minAgo = DateUtil.minAgo(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) {
- lastConnectionView.setText(
- "No successful connection" +
- "\nwithin the last " + minAgo + " min");
+ lastConnectionView.setText("No connection for " + minAgo + " min");
lastConnectionView.setTextColor(Color.RED);
}
if (plugin.getPump().lastConnectionAttempt > plugin.getPump().lastSuccessfulConnection) {
- lastConnectionView.setText("" + minAgo + " (" + time + ")" +
- "\nLast connect attempt failed");
+ lastConnectionView.setText("Last connect attempt failed");
lastConnectionView.setTextColor(Color.YELLOW);
} else {
lastConnectionView.setText("" + minAgo + " (" + time + ")");
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java
index 99603853f6..d53f4055d7 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java
@@ -1,13 +1,7 @@
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.support.annotation.NonNull;
-import android.support.v4.app.NotificationCompat;
import org.json.JSONObject;
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.RuffyCommands;
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.Tbr;
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.PumpCombo.events.EventComboPumpUpdateGUI;
import info.nightscout.utils.DateUtil;
-import info.nightscout.utils.SP;
/**
* Created by mike on 05.08.2016.
@@ -205,23 +198,24 @@ public class ComboPlugin implements PluginBase, PumpInterface {
@NonNull
@Override
public Date lastDataTime() {
- CommandResult lastCmdResult = pump.lastCmdResult;
- return lastCmdResult != null ? new Date(lastCmdResult.completionTime) : new Date(0);
+ return new Date(pump.lastSuccessfulConnection);
}
@Override
public synchronized void refreshDataFromPump(String reason) {
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();
- } 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) {
- MainApp.bus().post(new EventComboPumpUpdateGUI(status));
+ private CommandResult runCommand(String activity, boolean checkTbrMisMatch, CommandExecution commandExecution) {
+ pump.activity = activity;
+ MainApp.bus().post(new EventComboPumpUpdateGUI());
+
CommandResult commandResult = commandExecution.execute();
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,
// send next request.
// then request state again ... ?
- if (commandResult.state.errorMsg != null) {
+ // TODO rethink this errorMsg field;
+
+/* if (commandResult.state.errorMsg != null) {
CommandResult takeOverAlarmResult = ruffyScripter.takeOverAlarms();
- for (Error error : takeOverAlarmResult.history.errorHistory) {
+ for (PumpError pumpError : takeOverAlarmResult.history.pumpErrorHistory) {
MainApp.bus().post(new EventNewNotification(
- new Notification(Notification.COMBO_PUMP_ERROR,
- "Pump alarm: " + error.message, Notification.URGENT)));
+ new Notification(Notification.COMBO_PUMP_ALARM,
+ "Pump alarm: " + pumpError.message, Notification.URGENT)));
}
commandResult.state = takeOverAlarmResult.state;
- }
+ }*/
pump.lastCmdResult = commandResult;
pump.state = commandResult.state;
@@ -632,20 +630,21 @@ public class ComboPlugin implements PluginBase, PumpInterface {
log.error("JOE: no!");
} else {
// still crashable ...
+ // TODO only update if command was successful? -> KeepAliveReceiver, triggering alarm on unavaiblae pump
pump.lastCmdResult.completionTime = System.currentTimeMillis();
}
- // TOOD
+ // TODO merge all new history here?
if (commandResult.history != null) {
if (commandResult.history.reservoirLevel != -1) {
pump.reservoirLevel = commandResult.history.reservoirLevel;
}
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());
return commandResult;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPump.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPump.java
index 22b4b6d8a2..202989a27a 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPump.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPump.java
@@ -10,16 +10,17 @@ import de.jotomo.ruffy.spi.history.Bolus;
import de.jotomo.ruffy.spi.history.PumpHistory;
class ComboPump {
- public long lastSuccessfulConnection;
- public long lastConnectionAttempt;
-
+ // TODO actually ... this isn't about successful command execution, but whether we could connect to the pump at all
+ volatile long lastSuccessfulConnection;
+ volatile long lastConnectionAttempt;
@Nullable
volatile CommandResult lastCmdResult;
+
+ public volatile String activity;
@NonNull
volatile PumpState state = new PumpState();
- @NonNull
- volatile PumpHistory history = new PumpHistory();
- @Nullable
- volatile Bolus lastBolus;
volatile int reservoirLevel = -1;
+ @NonNull
+
+ volatile PumpHistory history = new PumpHistory();
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/events/EventComboPumpUpdateGUI.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/events/EventComboPumpUpdateGUI.java
index 5b0755da97..e9bf3f8415 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/events/EventComboPumpUpdateGUI.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/events/EventComboPumpUpdateGUI.java
@@ -5,11 +5,4 @@ package info.nightscout.androidaps.plugins.PumpCombo.events;
*/
public class EventComboPumpUpdateGUI {
- public EventComboPumpUpdateGUI() {}
-
- public EventComboPumpUpdateGUI(String status) {
- this.status = status;
- }
-
- public String status;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java
index 03610d3a2d..860da1aa65 100644
--- a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java
+++ b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java
@@ -68,6 +68,7 @@ public class KeepAliveReceiver extends BroadcastReceiver {
// 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?
// 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);
n.soundId = R.raw.alarm;
MainApp.bus().post(new EventNewNotification(n));
diff --git a/app/src/main/res/layout/combopump_fragment.xml b/app/src/main/res/layout/combopump_fragment.xml
index f728f7ee96..7d208858ff 100644
--- a/app/src/main/res/layout/combopump_fragment.xml
+++ b/app/src/main/res/layout/combopump_fragment.xml
@@ -29,7 +29,7 @@
android:layout_weight="1.5"
android:gravity="end"
android:paddingRight="5dp"
- android:text="Status"
+ android:text="State"
android:textSize="14sp" />
@@ -145,6 +144,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b0c2f32d92..81a0ff2b2c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -269,7 +269,7 @@
DIA [h]Duration of Insulin ActivityFailed to update basal profile
- History
+ ErrorsReloadUploadingE bolus
diff --git a/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/PumpState.java b/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/PumpState.java
index 80ee222ad0..ae70a81b79 100644
--- a/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/PumpState.java
+++ b/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/PumpState.java
@@ -1,10 +1,8 @@
package de.jotomo.ruffy.spi;
-import java.util.Date;
-
/** State displayed on the main screen of the pump. */
public class PumpState {
- public Date timestamp = new Date();
+ public String menu = null;
public boolean tbrActive = false;
/** TBR percentage. 100% means no TBR active, just the normal basal rate running. */
public int tbrPercent = -1;
@@ -30,6 +28,11 @@ public class PumpState {
public int activeBasalProfileNumber;
+ public PumpState menu(String menu) {
+ this.menu = menu;
+ return this;
+ }
+
public PumpState tbrActive(boolean tbrActive) {
this.tbrActive = tbrActive;
return this;
@@ -76,17 +79,19 @@ public class PumpState {
}
public String getStateSummary() {
- if (errorMsg != null)
- return errorMsg;
+ if (menu == null)
+ return "Unreachable";
+ else if (suspended && (batteryState == EMPTY || insulinState == EMPTY))
+ return "Suspended due to error";
else if (suspended)
- return "Suspended";
+ return "Suspended by user";
return "Running";
}
@Override
public String toString() {
return "PumpState{" +
- "timestamp=" + timestamp +
+ "menu=" + menu +
", tbrActive=" + tbrActive +
", tbrPercent=" + tbrPercent +
", tbrRate=" + tbrRate +
diff --git a/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/RuffyCommands.java b/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/RuffyCommands.java
index 42293944a1..e879b7b1d8 100644
--- a/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/RuffyCommands.java
+++ b/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/RuffyCommands.java
@@ -13,14 +13,73 @@ public interface RuffyCommands {
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
- * 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();
+ // 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 isPumpBusy();
+ // start everything with this: read pump state.
+ // see if there's an error active.
CommandResult readPumpState();
CommandResult readHistory(PumpHistoryRequest request);
diff --git a/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/history/Error.java b/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/history/PumpError.java
similarity index 76%
rename from ruffy-spi/src/main/java/de/jotomo/ruffy/spi/history/Error.java
rename to ruffy-spi/src/main/java/de/jotomo/ruffy/spi/history/PumpError.java
index 26b2e26ee0..6cbff4966a 100644
--- a/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/history/Error.java
+++ b/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/history/PumpError.java
@@ -1,12 +1,12 @@
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). */
public final String code;
/** Error message, in the language configured on the pump. */
public final String message;
- public Error(long timestamp, String code, String message) {
+ public PumpError(long timestamp, String code, String message) {
super(timestamp);
this.code = code;
this.message = message;
diff --git a/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/history/PumpHistory.java b/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/history/PumpHistory.java
index 82b7112517..cd2ccd2a60 100644
--- a/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/history/PumpHistory.java
+++ b/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/history/PumpHistory.java
@@ -3,7 +3,6 @@ package de.jotomo.ruffy.spi.history;
import android.support.annotation.NonNull;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
public class PumpHistory {
@@ -13,7 +12,7 @@ public class PumpHistory {
@NonNull
public List tbrHistory = new ArrayList<>();
@NonNull
- public List errorHistory = new ArrayList<>();
+ public List pumpErrorHistory = new ArrayList<>();
@NonNull
public List tddHistory = new ArrayList<>();
@@ -33,8 +32,8 @@ public class PumpHistory {
return this;
}
- public PumpHistory errorHistory(List errorHistory) {
- this.errorHistory = errorHistory;
+ public PumpHistory errorHistory(List pumpErrorHistory) {
+ this.pumpErrorHistory = pumpErrorHistory;
return this;
}
@@ -49,7 +48,7 @@ public class PumpHistory {
"reservoirLevel=" + reservoirLevel +
", bolusHistory=" + bolusHistory.size() +
", tbrHistory=" + tbrHistory.size() +
- ", errorHistory=" + errorHistory.size() +
+ ", pumpErrorHistory=" + pumpErrorHistory.size() +
", tddHistory=" + tddHistory.size() +
'}';
}
diff --git a/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/history/PumpHistoryRequest.java b/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/history/PumpHistoryRequest.java
index 364d0a1327..ac5b211b1a 100644
--- a/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/history/PumpHistoryRequest.java
+++ b/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/history/PumpHistoryRequest.java
@@ -14,7 +14,7 @@ public class PumpHistoryRequest {
public long bolusHistory = SKIP;
public long tbrHistory = SKIP;
- public long errorHistory = SKIP;
+ public long pumpErrorHistory = SKIP;
public long tddHistory = SKIP;
public PumpHistoryRequest reservoirLevel(boolean reservoirLevel) {
@@ -33,7 +33,7 @@ public class PumpHistoryRequest {
}
public PumpHistoryRequest errorHistory(long errorHistory) {
- this.errorHistory = errorHistory;
+ this.pumpErrorHistory = errorHistory;
return this;
}
@@ -48,7 +48,7 @@ public class PumpHistoryRequest {
"reservoirLevel=" + reservoirLevel +
", bolusHistory=" + bolusHistory +
", tbrHistory=" + tbrHistory +
- ", errorHistory=" + errorHistory +
+ ", pumpErrorHistory=" + pumpErrorHistory +
", tddHistory=" + tddHistory +
'}';
}
diff --git a/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java
index b163ea11d8..6f10dae224 100644
--- a/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java
+++ b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java
@@ -29,7 +29,6 @@ import de.jotomo.ruffy.spi.BolusProgressReporter;
import de.jotomo.ruffy.spi.CommandResult;
import de.jotomo.ruffy.spi.PumpState;
import de.jotomo.ruffy.spi.RuffyCommands;
-import de.jotomo.ruffy.spi.history.Error;
import de.jotomo.ruffy.spi.history.PumpHistoryRequest;
import de.jotomo.ruffyscripter.commands.BolusCommand;
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.SetBasalProfileCommand;
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.
// 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());
}
+ // TODO simplify, hard to reason about exists
synchronized (RuffyScripter.class) {
try {
activeCmd = cmd;
long connectStart = System.currentTimeMillis();
ensureConnected();
- final RuffyScripter scripter = this;
final Returnable returnable = new Returnable();
class CommandRunner {
public void run() {
@@ -294,7 +294,7 @@ public class RuffyScripter implements RuffyCommands {
PumpState pumpState = readPumpStateInternal();
log.debug("Pump state before running command: " + pumpState);
long cmdStartTime = System.currentTimeMillis();
- cmd.setScripter(scripter);
+ cmd.setScripter(RuffyScripter.this);
returnable.cmdResult = cmd.execute();
long cmdEndTime = System.currentTimeMillis();
returnable.cmdResult.completionTime = cmdEndTime;
@@ -333,6 +333,11 @@ public class RuffyScripter implements RuffyCommands {
reconnect();
// 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 ...
+
+ // 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() {
@Override
public void run() {
@@ -421,6 +426,11 @@ public class RuffyScripter implements RuffyCommands {
ensureConnected();
if (getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) {
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)) {
log.debug("Confirming alert caused by disconnect: " + errorMessage);
// confirm alert
@@ -454,6 +464,7 @@ public class RuffyScripter implements RuffyCommands {
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();
return getCurrentMenu().getType() == MenuType.MAIN_MENU;
@@ -530,9 +541,12 @@ public class RuffyScripter implements RuffyCommands {
PumpState state = new PumpState();
Menu menu = currentMenu;
if (menu == null) {
- return new PumpState().errorMsg("Menu is not available");
+ return state;
}
+
MenuType menuType = menu.getType();
+ state.menu = menuType.name();
+
if (menuType == MenuType.MAIN_MENU) {
Double tbrPercentage = (Double) menu.getAttribute(MenuAttribute.TBR);
if (tbrPercentage != 100) {
@@ -545,10 +559,6 @@ public class RuffyScripter implements RuffyCommands {
}
state.batteryState = ((int) menu.getAttribute(MenuAttribute.BATTERY_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) {
state.errorMsg = (String) menu.getAttribute(MenuAttribute.MESSAGE);
} else if (menuType == MenuType.STOP) {
@@ -556,14 +566,7 @@ public class RuffyScripter implements RuffyCommands {
state.batteryState = ((int) menu.getAttribute(MenuAttribute.BATTERY_STATE));
state.insulinState = ((int) menu.getAttribute(MenuAttribute.INSULIN_STATE));
} 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();
+ // just return the PumpState with the menu set
}
return state;
}
@@ -619,6 +622,7 @@ public class RuffyScripter implements RuffyCommands {
// 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
// something to deal with connection loses
+ // TODO force reconnect? and retry?
while (currentMenu == null) {
if (System.currentTimeMillis() > timeout) {
throw new CommandException().message("Unable to read current menu");
@@ -630,14 +634,9 @@ public class RuffyScripter implements RuffyCommands {
}
public void pressUpKey() {
-// wrapNoNotTheSubwayKind(new Step() {
-// @Override
-// public void doStep() {
log.debug("Pressing up key");
pressKey(Key.UP);
log.debug("Releasing up key");
-// }
-// });
}
public void pressDownKey() {
@@ -742,7 +741,7 @@ public class RuffyScripter implements RuffyCommands {
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 initialUpdateTime = menuLastUpdated;
while (initialUpdateTime == menuLastUpdated) {
@@ -869,32 +868,7 @@ public class RuffyScripter implements RuffyCommands {
@Override
public CommandResult takeOverAlarms() {
- if (getCurrentMenu().getType() != MenuType.WARNING_OR_ERROR) {
- 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);
+ return runCommand(new TakeOverAlarmsCommand());
}
@Override
diff --git a/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java
index b6517af2d6..ccb2652c03 100644
--- a/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java
+++ b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java
@@ -26,6 +26,11 @@ public class BolusCommand extends BaseCommand {
private final BolusProgressReporter bolusProgressReporter;
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) {
this.bolus = bolus;
this.bolusProgressReporter = bolusProgressReporter;
diff --git a/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/ReadHistoryCommand.java b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/ReadHistoryCommand.java
index 6621b66548..806fe57ca1 100644
--- a/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/ReadHistoryCommand.java
+++ b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/ReadHistoryCommand.java
@@ -1,5 +1,7 @@
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.MenuType;
import org.monkey.d.ruffy.ruffy.driver.display.menu.BolusType;
@@ -30,50 +32,38 @@ public class ReadHistoryCommand extends BaseCommand {
}
if (request.bolusHistory != PumpHistoryRequest.SKIP
|| request.tbrHistory != PumpHistoryRequest.SKIP
- || request.errorHistory != PumpHistoryRequest.SKIP
+ || request.pumpErrorHistory != PumpHistoryRequest.SKIP
|| request.tddHistory != PumpHistoryRequest.SKIP) {
scripter.navigateToMenu(MenuType.MY_DATA_MENU);
scripter.verifyMenuIsDisplayed(MenuType.MY_DATA_MENU);
scripter.pressCheckKey();
+
+ // bolus history
scripter.verifyMenuIsDisplayed(MenuType.BOLUS_DATA);
if (request.bolusHistory != PumpHistoryRequest.SKIP) {
- if (request.bolusHistory == PumpHistoryRequest.LAST) {
- // 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);
+ int totalRecords = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.TOTAL_RECORD);
+ if (totalRecords > 0) {
+ if (request.bolusHistory == PumpHistoryRequest.LAST) {
+ Bolus bolus = readBolusRecord();
+ 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.verifyMenuIsDisplayed(MenuType.ERROR_DATA);
- if (request.errorHistory != PumpHistoryRequest.SKIP) {
+ if (request.pumpErrorHistory != PumpHistoryRequest.SKIP) {
int code = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.WARNING);
String message = (String) scripter.getCurrentMenu().getAttribute(MenuAttribute.MESSAGE);
MenuDate date = (MenuDate) scripter.getCurrentMenu().getAttribute(MenuAttribute.DATE);
MenuTime time = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.TIME);
}
+
+ // tdd history
scripter.pressMenuKey();
scripter.verifyMenuIsDisplayed(MenuType.DAILY_DATA);
if (request.tddHistory != PumpHistoryRequest.SKIP) {
@@ -81,6 +71,8 @@ public class ReadHistoryCommand extends BaseCommand {
MenuDate date = (MenuDate) scripter.getCurrentMenu().getAttribute(MenuAttribute.DATE);
MenuTime time = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.TIME);
}
+
+ // tbr history
scripter.pressMenuKey();
scripter.verifyMenuIsDisplayed(MenuType.TBR_DATA);
if (request.tbrHistory != PumpHistoryRequest.SKIP) {
@@ -90,13 +82,50 @@ public class ReadHistoryCommand extends BaseCommand {
// TODO start or end time?
MenuTime time = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.TIME);
}
+
scripter.pressBackKey();
scripter.returnToRootMenu();
+ scripter.verifyRootMenuIsDisplayed();
}
- scripter.verifyRootMenuIsDisplayed();
+
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() {
scripter.verifyRootMenuIsDisplayed();
scripter.pressCheckKey();
@@ -112,4 +141,13 @@ public class ReadHistoryCommand extends BaseCommand {
public List validateArguments() {
return Collections.emptyList();
}
+
+ @Override
+ public String toString() {
+ return "ReadHistoryCommand{" +
+ "request=" + request +
+ ", history=" + history +
+ '}';
+ }
+
}
diff --git a/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/TakeOverAlarmsCommand.java b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/TakeOverAlarmsCommand.java
new file mode 100644
index 0000000000..c62c655d04
--- /dev/null
+++ b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/TakeOverAlarmsCommand.java
@@ -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 validateArguments() {
+ return Collections.emptyList();
+ }
+}