Support pump suspend status (and misc other ...).

This commit is contained in:
Johannes Mockenhaupt 2017-10-19 19:08:48 +02:00
parent 523de96c8c
commit c29b4d13a3
No known key found for this signature in database
GPG key ID: 9E1EA6AF7BBBB0D1
21 changed files with 541 additions and 557 deletions

View file

@ -1,5 +1,7 @@
package info.nightscout.androidaps.interfaces;
import android.support.annotation.NonNull;
import org.json.JSONObject;
import java.util.Date;
@ -24,6 +26,7 @@ public interface PumpInterface {
int setNewBasalProfile(Profile profile);
boolean isThisProfileSet(Profile profile);
@NonNull
Date lastDataTime();
void refreshDataFromPump(String reason);

View file

@ -189,7 +189,7 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
@Override
public void onClick(View view) {
FragmentManager manager = getFragmentManager();
FragmentManager manager = getChildFragmentManager();
final PumpInterface pump = MainApp.getConfigBuilder();
switch (view.getId()) {
case R.id.actions_profileswitch:

View file

@ -4,7 +4,7 @@ package info.nightscout.androidaps.plugins.PumpCombo;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.os.SystemClock;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -16,87 +16,67 @@ import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import de.jotomo.ruffy.spi.CommandResult;
import de.jotomo.ruffy.spi.PumpState;
import de.jotomo.ruffy.spi.history.Bolus;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.PumpCombo.events.EventComboPumpUpdateGUI;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
public class ComboFragment extends Fragment implements View.OnClickListener {
public class ComboFragment extends SubscriberFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(ComboFragment.class);
// TODO rename to sync, shall sync everything, purge an ongoing alert and raise an AAPS notification for it
private TextView statusView;
private TextView batteryView;
private TextView reservoirView;
private TextView lastConnectionView;
private TextView lastBolusView;
private TextView basaBasalRateView;
private TextView tempBasalText;
private Button refresh;
// TODO create tabs: Status/Overview (like Dana), Errors, Stats (TDD)
// boluses, tbrs, refills, battery change ... all covered already by Treatments, CP,
// boluses & tbrs are synced from pump;
// profile: will also be viewable already, no need to duplicate;
private TextView statusText;
private TextView tbrPercentageText;
private TextView tbrDurationText;
private TextView tbrRateText;
private TextView pumpErrorText;
private TextView lastCmdText;
private TextView lastCmdTimeText;
private TextView lastCmdResultText;
private TextView lastCmdDurationText;
private TextView pumpstateBatteryText;
private TextView insulinstateText;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.combopump_fragment, container, false);
statusView = (TextView) view.findViewById(R.id.combo_status);
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);
lastBolusView = (TextView) view.findViewById(R.id.combo_lastbolus);
basaBasalRateView = (TextView) view.findViewById(R.id.combo_basabasalrate);
tempBasalText = (TextView) view.findViewById(R.id.combo_temp_basal);
refresh = (Button) view.findViewById(R.id.combo_refresh);
statusText = (TextView) view.findViewById(R.id.combo_status);
tbrPercentageText = (TextView) view.findViewById(R.id.combo_tbr_percentage);
tbrDurationText = (TextView) view.findViewById(R.id.combo_tbr_duration);
tbrRateText = (TextView) view.findViewById(R.id.combo_tbr_rate);
pumpErrorText = (TextView) view.findViewById(R.id.combo_pump_error);
lastCmdText = (TextView) view.findViewById(R.id.combo_last_command);
lastCmdTimeText = (TextView) view.findViewById(R.id.combo_last_command_time);
lastCmdResultText = (TextView) view.findViewById(R.id.combo_last_command_result);
lastCmdDurationText = (TextView) view.findViewById(R.id.combo_last_command_duration);
pumpstateBatteryText = (TextView) view.findViewById(R.id.combo_pumpstate_battery);
insulinstateText = (TextView) view.findViewById(R.id.combo_insulinstate);
refresh.setOnClickListener(this);
updateGUI();
return view;
}
@Override
public void onPause() {
super.onPause();
MainApp.bus().unregister(this);
}
@Override
public void onResume() {
super.onResume();
MainApp.bus().register(this);
updateGUI();
}
@Subscribe
public void onStatusEvent(final EventComboPumpUpdateGUI ev) {
updateGUI();
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.combo_refresh:
/* Activity activity = getActivity();
if (activity != null) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
statusView.setText("Refreshing");
}
});
}*/
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
@ -108,6 +88,22 @@ public class ComboFragment extends Fragment implements View.OnClickListener {
}
}
@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);
}
});
} else {
updateGUI();
}
}
public void updateGUI() {
Activity activity = getActivity();
if (activity != null)
@ -115,63 +111,108 @@ public class ComboFragment extends Fragment implements View.OnClickListener {
@Override
public void run() {
ComboPlugin plugin = ComboPlugin.getPlugin();
if (plugin.getPump().lastCmdResult != null)
statusText.setText(plugin.getPump().state.getStateSummary());
if (plugin.getPump().lastCmdResult == null) {
statusView.setText("Initializing");
} else {
statusView.setText(plugin.getPump().state.getStateSummary());
}
if (plugin.getPump().state.errorMsg != null) {
statusView.setTextColor(Color.RED);
} else {
statusView.setTextColor(Color.WHITE);
}
// ???
if (plugin.isInitialized()) {
PumpState ps = plugin.getPump().state;
if (ps != null) {
boolean tbrActive = ps.tbrPercent != -1 && ps.tbrPercent != 100;
if (tbrActive) {
tbrPercentageText.setText("" + ps.tbrPercent + "%");
tbrDurationText.setText("" + ps.tbrRemainingDuration + " min");
tbrRateText.setText("" + ps.tbrRate + " U/h");
// tbrPercentageText.setText("" + ps.tbrPercent + "%");
// tbrDurationText.setText("" + ps.tbrRemainingDuration + " min");
// tbrRateText.setText("" + ps.tbrRate + " U/h");
} else {
tbrPercentageText.setText("Default basal rate running");
tbrDurationText.setText("");
tbrRateText.setText("");
// tbrPercentageText.setText("Default basal rate running");
// tbrDurationText.setText("");
// tbrRateText.setText("");
}
pumpErrorText.setText(ps.errorMsg != null ? ps.errorMsg : "");
// pumpErrorText.setText(ps.errorMsg != null ? ps.errorMsg : "");
if (ps.batteryState == PumpState.EMPTY) {
pumpstateBatteryText.setText("{fa-battery-empty}");
pumpstateBatteryText.setTextColor(Color.RED);
batteryView.setText("{fa-battery-empty}");
batteryView.setTextColor(Color.RED);
} else if (ps.batteryState == PumpState.LOW) {
pumpstateBatteryText.setText("{fa-battery-quarter}");
pumpstateBatteryText.setTextColor(Color.YELLOW);
batteryView.setText("{fa-battery-quarter}");
batteryView.setTextColor(Color.YELLOW);
} else {
pumpstateBatteryText.setText("{fa-battery-full}");
pumpstateBatteryText.setTextColor(Color.WHITE);
batteryView.setText("{fa-battery-full}");
batteryView.setTextColor(Color.WHITE);
}
switch (ps.insulinState) {
case 0: insulinstateText.setText("ok");
insulinstateText.setTextColor(Color.WHITE);
case 0:
reservoirView.setText("ok");
break;
case 1: insulinstateText.setText("low");
insulinstateText.setTextColor(Color.YELLOW);
case 1:
reservoirView.setText("low");
break;
case 2: insulinstateText.setText("empty");
insulinstateText.setTextColor(Color.RED);
case 2:
reservoirView.setText("empty");
break;
}
int reservoirLevel = plugin.getPump().history.reservoirLevel;
insulinstateText.setText(reservoirLevel == - 1 ? "" : "" + reservoirLevel + " U");
reservoirView.setText(reservoirLevel == -1 ? "" : "" + reservoirLevel + " U");
}
if (plugin.getPump().lastCmdResult != null) {
CommandResult lastCmdResult = plugin.getPump().lastCmdResult;
lastConnectionView.setText(
"4 m ago (18:58)"
// new Date(lastCmdResult.completionTime).toLocaleString()
);
}
plugin.getPump().history.bolusHistory.add(new Bolus(System.currentTimeMillis() - 7 * 60 * 1000, 12.8d));
if (!plugin.getPump().history.bolusHistory.isEmpty()) {
Bolus bolus = plugin.getPump().history.bolusHistory.get(0);
// double agoHours = agoMsec / 60d / 60d / 1000d;
// if (agoHours < 6) // max 6h back
if (bolus.timestamp + 6 * 60 * 60 * 1000 < System.currentTimeMillis()) {
lastBolusView.setText("");
} else {
// TODO only if !SMB; also: bolus history: should only be used to sync to DB;
// remember that datum someplace else?
long agoMsc = System.currentTimeMillis() - bolus.timestamp;
double agoHours = agoMsc / 60d / 60d / 1000d;
lastBolusView.setText(DateUtil.timeString(bolus.timestamp) +
" (" + DecimalFormatter.to1Decimal(agoHours) + " " + MainApp.sResources.getString(R.string.hoursago) + ") " +
DecimalFormatter.to2Decimal(bolus.amount) + " U");
lastBolusView.setText("12.80 U (15 m ago, 19:04)"); // (19:04)");
}
}
basaBasalRateView.setText(DecimalFormatter.to2Decimal(plugin.getBaseBasalRate()) + " U/h");
TemporaryBasal temporaryBasal = new TemporaryBasal(System.currentTimeMillis());
temporaryBasal.percentRate = 420;
temporaryBasal.durationInMinutes = 20;
tempBasalText.setText(temporaryBasal.toStringFull());
tempBasalText.setText("420% 5/20' (18:45)");
CommandResult lastCmdResult1 = plugin.getPump().lastCmdResult;
String lastCmd = lastCmdResult1.request;
if (lastCmd != null) {
lastCmdText.setText(lastCmd);
lastCmdTimeText.setText(plugin.getPump().lastCmdTime.toLocaleString());
// lastCmdText.setText(lastCmd);
// lastCmdTimeText.setText(plugin.getPump().lastCmdTime.toLocaleString());
} else {
lastCmdText.setText("");
lastCmdTimeText.setText("");
// lastCmdText.setText("");
// lastCmdTimeText.setText("");
}
if (lastCmdResult1.message != null) {
lastCmdResultText.setText(lastCmdResult1.message);
lastCmdDurationText.setText(lastCmdResult1.duration);
// lastCmdResultText.setText(lastCmdResult1.message);
// lastCmdDurationText.setText(lastCmdResult1.duration);
} else {
lastCmdResultText.setText("");
lastCmdDurationText.setText("");
// lastCmdResultText.setText("");
// lastCmdDurationText.setText("");
}
}
}

View file

@ -15,7 +15,12 @@ import org.slf4j.LoggerFactory;
import java.util.Date;
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.PumpHistoryRequest;
import de.jotomo.ruffyscripter.RuffyCommandsV1Impl;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
@ -30,11 +35,6 @@ import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.plugins.PumpCombo.events.EventComboPumpUpdateGUI;
import de.jotomo.ruffyscripter.RuffyCommandsV1Impl;
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 info.nightscout.utils.DateUtil;
import info.nightscout.utils.SP;
@ -226,19 +226,17 @@ public class ComboPlugin implements PluginBase, PumpInterface {
@Override
public boolean isInitialized() {
// consider initialized when the pump's state was initially fetched,
// after that lastCmd* variables will have values
return pump.lastCmdTime.getTime() > 0;
return pump.lastCmdResult != null;
}
@Override
public boolean isSuspended() {
return pump.state != null && pump.state.suspended;
return pump.state.suspended;
}
@Override
public boolean isBusy() {
return ruffyScripter.isPumpBusy();
return ruffyScripter.isPumpBusy() && !pump.state.suspended;
}
// TODO
@ -255,7 +253,8 @@ public class ComboPlugin implements PluginBase, PumpInterface {
@Override
public Date lastDataTime() {
return pump.lastCmdTime;
CommandResult lastCmdResult = pump.lastCmdResult;
return lastCmdResult != null ? new Date(lastCmdResult.completionTime) : new Date(0);
}
// this method is regularly called from info.nightscout.androidaps.receivers.KeepAliveReceiver
@ -271,18 +270,19 @@ public class ComboPlugin implements PluginBase, PumpInterface {
return;
}
// TODO
boolean notAUserRequest = !reason.toLowerCase().contains("user");
boolean wasRunAtLeastOnce = pump.lastCmdTime.getTime() > 0;
boolean ranWithinTheLastMinute = System.currentTimeMillis() < pump.lastCmdTime.getTime() + 60 * 1000;
boolean wasRunAtLeastOnce = pump.lastCmdResult != null;
boolean ranWithinTheLastMinute = wasRunAtLeastOnce && System.currentTimeMillis() < pump.lastCmdResult.completionTime + 60 * 1000;
if (notAUserRequest && wasRunAtLeastOnce && ranWithinTheLastMinute) {
log.debug("Not fetching state from pump, since we did already within the last 60 seconds");
} else {
CommandResult commandResult = ruffyScripter.readPumpState();
pump.lastCmdResult = commandResult;
pump.lastCmdTime = new Date(commandResult.completionTime);
CommandResult reservoirQueryResult = ruffyScripter.readHistory(new PumpHistoryRequest().reservoirLevel(true));
pump.history = reservoirQueryResult.history;
MainApp.bus().post(new EventComboPumpUpdateGUI());
runCommand("Refreshing", new CommandExecution() {
@Override
public CommandResult execute() {
return ruffyScripter.readHistory(new PumpHistoryRequest().reservoirLevel(true));
}
});
}
}
@ -324,7 +324,9 @@ public class ComboPlugin implements PluginBase, PumpInterface {
}
};
/** Updates Treatment records with carbs and boluses and delivers a bolus if needed */
/**
* Updates Treatment records with carbs and boluses and delivers a bolus if needed
*/
@Override
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
try {
@ -369,11 +371,13 @@ public class ComboPlugin implements PluginBase, PumpInterface {
}
@NonNull
private PumpEnactResult deliverBolus(DetailedBolusInfo detailedBolusInfo) {
CommandResult bolusCmdResult = ruffyScripter.deliverBolus(detailedBolusInfo.insulin, bolusProgressReporter);
pump.lastCmdResult = bolusCmdResult;
pump.lastCmdTime = new Date(bolusCmdResult.completionTime);
MainApp.bus().post(new EventComboPumpUpdateGUI());
private PumpEnactResult deliverBolus(final DetailedBolusInfo detailedBolusInfo) {
CommandResult bolusCmdResult = runCommand("Bolusing", new CommandExecution() {
@Override
public CommandResult execute() {
return ruffyScripter.deliverBolus(detailedBolusInfo.insulin, bolusProgressReporter);
}
});
PumpEnactResult pumpEnactResult = new PumpEnactResult();
pumpEnactResult.success = bolusCmdResult.success;
@ -422,7 +426,7 @@ public class ComboPlugin implements PluginBase, PumpInterface {
// Note: AAPS calls this only for setting a temp basal issued by the user
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes) {
public PumpEnactResult setTempBasalPercent(Integer percent, final Integer durationInMinutes) {
log.debug("setTempBasalPercent called with " + percent + "% for " + durationInMinutes + "min");
int adjustedPercent = percent;
@ -438,10 +442,14 @@ public class ComboPlugin implements PluginBase, PumpInterface {
adjustedPercent = rounded.intValue();
}
CommandResult commandResult = ruffyScripter.setTbr(adjustedPercent, durationInMinutes);
pump.lastCmdResult = commandResult;
pump.lastCmdTime = new Date(commandResult.completionTime);
MainApp.bus().post(new EventComboPumpUpdateGUI());
final int finalAdjustedPercent = adjustedPercent;
CommandResult commandResult = runCommand("Setting TBR", new CommandExecution() {
@Override
public CommandResult execute() {
return ruffyScripter.setTbr(finalAdjustedPercent, durationInMinutes);
}
}
);
if (commandResult.enacted) {
TemporaryBasal tempStart = new TemporaryBasal(commandResult.completionTime);
@ -488,10 +496,12 @@ public class ComboPlugin implements PluginBase, PumpInterface {
if (activeTemp == null || userRequested) {
/* v1 compatibility to sync DB to pump if they diverged (activeTemp == null) */
log.debug("cancelTempBasal: hard-cancelling TBR since user requested");
commandResult = ruffyScripter.cancelTbr();
pump.lastCmdResult = commandResult;
pump.lastCmdTime = new Date(commandResult.completionTime);
MainApp.bus().post(new EventComboPumpUpdateGUI());
commandResult = runCommand("Cancelling TBR", new CommandExecution() {
@Override
public CommandResult execute() {
return ruffyScripter.cancelTbr();
}
});
if (commandResult.enacted) {
tempBasal = new TemporaryBasal(commandResult.completionTime);
@ -512,12 +522,14 @@ public class ComboPlugin implements PluginBase, PumpInterface {
} else {
// Set a fake neutral temp to avoid TBR cancel alert. Decide 90% vs 110% based on
// on whether the TBR we're cancelling is above or below 100%.
int percentage = (activeTemp.percentRate > 100) ? 110 : 90;
final int percentage = (activeTemp.percentRate > 100) ? 110 : 90;
log.debug("cancelTempBasal: changing tbr to " + percentage + "% for 15 mins.");
commandResult = ruffyScripter.setTbr(percentage, 15);
pump.lastCmdResult = commandResult;
pump.lastCmdTime = new Date(commandResult.completionTime);
MainApp.bus().post(new EventComboPumpUpdateGUI());
commandResult = runCommand("Setting TBR", new CommandExecution() {
@Override
public CommandResult execute() {
return ruffyScripter.setTbr(percentage, 15);
}
});
if (commandResult.enacted) {
tempBasal = new TemporaryBasal(commandResult.completionTime);
@ -541,6 +553,23 @@ public class ComboPlugin implements PluginBase, PumpInterface {
return pumpEnactResult;
}
interface CommandExecution {
CommandResult execute();
}
private CommandResult runCommand(String status, CommandExecution commandExecution) {
MainApp.bus().post(new EventComboPumpUpdateGUI(status));
// TODO handle running into WARNING_OR_ERROR ... or scripter? purge it
CommandResult commandResult = commandExecution.execute();
pump.lastCmdResult = commandResult;
pump.state = commandResult.state;
// TOOD
if (commandResult.history != null)
pump.history = commandResult.history;
MainApp.bus().post(new EventComboPumpUpdateGUI());
return commandResult;
}
@Override
public PumpEnactResult cancelExtendedBolus() {
return OPERATION_NOT_SUPPORTED;
@ -550,7 +579,8 @@ public class ComboPlugin implements PluginBase, PumpInterface {
// TODO v2 add battery, reservoir info when we start reading that and clean up the code
@Override
public JSONObject getJSONStatus() {
if (pump.lastCmdTime.getTime() + 5 * 60 * 1000L < System.currentTimeMillis()) {
CommandResult lastCmdResult = pump.lastCmdResult;
if (lastCmdResult == null || lastCmdResult.completionTime + 5 * 60 * 1000L < System.currentTimeMillis()) {
return null;
}
@ -564,7 +594,7 @@ public class ComboPlugin implements PluginBase, PumpInterface {
extendedJson.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName());
} catch (Exception e) {
}
statusJson.put("timestamp", pump.lastCmdTime);
statusJson.put("timestamp", lastCmdResult.completionTime);
PumpState ps = pump.state;
if (ps != null) {
@ -582,7 +612,7 @@ public class ComboPlugin implements PluginBase, PumpInterface {
pumpJson.put("status", statusJson);
pumpJson.put("extended", extendedJson);
pumpJson.put("clock", DateUtil.toISOString(pump.lastCmdTime));
pumpJson.put("clock", DateUtil.toISOString(lastCmdResult.completionTime));
return pumpJson;
} catch (Exception e) {

View file

@ -13,7 +13,7 @@ class ComboPump {
@Nullable
volatile CommandResult lastCmdResult;
@NonNull
volatile Date lastCmdTime = new Date(0);
volatile PumpState state = new PumpState();
@NonNull
volatile PumpHistory history = new PumpHistory();
}

View file

@ -5,4 +5,11 @@ package info.nightscout.androidaps.plugins.PumpCombo.events;
*/
public class EventComboPumpUpdateGUI {
public EventComboPumpUpdateGUI() {}
public EventComboPumpUpdateGUI(String status) {
this.status = status;
}
public String status;
}

View file

@ -4,6 +4,10 @@
android:layout_height="match_parent"
tools:context=".plugins.PumpCombo.ComboFragment">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
@ -14,12 +18,6 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/combo_refresh"
style="?android:attr/buttonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Refresh" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -28,7 +26,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:layout_weight="1.5"
android:gravity="end"
android:paddingRight="5dp"
android:text="Status"
@ -52,7 +50,7 @@
android:gravity="start"
android:paddingLeft="5dp"
android:textColor="@android:color/white"
android:text="Initializing"
android:text=""
android:textSize="14sp" />
</LinearLayout>
@ -74,369 +72,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:gravity="end"
android:paddingRight="5dp"
android:text="TBR percentage"
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_tbr_percentage"
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
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="2"
android:gravity="end"
android:paddingRight="5dp"
android:text="TBR duration"
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_tbr_duration"
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
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="2"
android:gravity="end"
android:paddingRight="5dp"
android:text="TBR rate"
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_tbr_rate"
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
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="2"
android:gravity="end"
android:paddingRight="5dp"
android:text="Pump error"
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_pump_error"
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
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="2"
android:gravity="end"
android:paddingRight="5dp"
android:text="Last command"
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_last_command"
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
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="2"
android:gravity="end"
android:paddingRight="5dp"
android:text="Command time"
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_last_command_time"
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
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="2"
android:gravity="end"
android:paddingRight="5dp"
android:text="Command result"
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_last_command_result"
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
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="2"
android:gravity="end"
android:paddingRight="5dp"
android:text="Command duration"
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_last_command_duration"
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
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="2"
android:layout_weight="1.5"
android:gravity="end"
android:paddingRight="5dp"
android:text="Battery"
@ -458,7 +94,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="20sp"
android:textSize="14sp"
android:paddingLeft="5dp"
android:gravity="start"
android:text="" />
@ -482,7 +118,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:layout_weight="1.5"
android:gravity="end"
android:paddingRight="5dp"
android:text="Reservoir"
@ -519,7 +155,239 @@
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="@string/pump_lastconnection_label"
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_lastconnection"
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
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="@string/pump_lastbolus_label"
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_lastbolus"
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
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="@string/pump_basebasalrate_label"
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_basabasalrate"
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
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="@string/pump_tempbasal_label"
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_temp_basal"
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
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>
</ScrollView>
<LinearLayout
android:id="@+id/combo_buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/combo_refresh"
style="@style/ButtonSmallFontStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableTop="@drawable/icon_actions_refill"
android:paddingLeft="0dp"
android:paddingRight="0dp"
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
android:id="@+id/combo_stats"
style="@style/ButtonSmallFontStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableTop="@drawable/icon_danarstats"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/combo_stats" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
</FrameLayout>

View file

@ -761,5 +761,7 @@
<string name="combo_disable_alarms">Disable alarms</string>
<string name="combo_disable_alarms_summary">Ignore all errors encountered while communicating with the pump. Alarms raised by the pump (including those caused by AndroidAPS) will still be raised on the pump.</string>
<string name="bolusprogramming">Programming pump for bolusing</string>
<string name="combo_refresh">Refresh</string>
<string name="combo_stats">Stats</string>
</resources>

View file

@ -81,7 +81,7 @@ public class PumpState {
return "Suspended";
else if (errorMsg != null)
return errorMsg;
return "Normal";
return "Running";
}
@Override

View file

@ -2,19 +2,20 @@ 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 {
public int reservoirLevel = -1;
@NonNull
public List<Bolus> bolusHistory = Collections.emptyList();
public List<Bolus> bolusHistory = new ArrayList<>();
@NonNull
public List<Tbr> tbrHistory = Collections.emptyList();
public List<Tbr> tbrHistory = new ArrayList<>();
@NonNull
public List<Error> errorHistory = Collections.emptyList();
public List<Error> errorHistory = new ArrayList<>();
@NonNull
public List<Tdd> tddHistory = Collections.emptyList();
public List<Tdd> tddHistory = new ArrayList<>();
public PumpHistory reservoirLevel(int reservoirLevel) {
this.reservoirLevel = reservoirLevel

View file

@ -8,6 +8,7 @@ public class PumpHistoryRequest {
Either the timestamp of the last known record to fetch all newer records,
or one of the constants to read no history or all of it.
*/
public static final long LAST = -2;
public static final long SKIP = -1;
public static final long FULL = 0;

View file

@ -34,7 +34,6 @@ import de.jotomo.ruffyscripter.commands.BolusCommand;
import de.jotomo.ruffyscripter.commands.CancelTbrCommand;
import de.jotomo.ruffyscripter.commands.Command;
import de.jotomo.ruffyscripter.commands.CommandException;
import de.jotomo.ruffyscripter.commands.GetPumpStateCommand;
import de.jotomo.ruffyscripter.commands.ReadBasalProfileCommand;
import de.jotomo.ruffyscripter.commands.ReadHistoryCommand;
import de.jotomo.ruffyscripter.commands.ReadPumpStateCommand;
@ -219,9 +218,9 @@ public class RuffyScripter implements RuffyCommands {
return runCommand(new ReadPumpStateCommand());
}
public void returnToMainMenu() {
public void returnToRootMenu() {
// returning to main menu using the 'back' key does not cause a vibration
while (getCurrentMenu().getType() != MenuType.MAIN_MENU) {
while (getCurrentMenu().getType() != MenuType.MAIN_MENU && getCurrentMenu().getType() != MenuType.STOP) {
if (getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) {
String errorMsg = (String) getCurrentMenu().getAttribute(MenuAttribute.MESSAGE);
confirmAlert(errorMsg, 1000);
@ -293,13 +292,11 @@ public class RuffyScripter implements RuffyCommands {
// level to handle state and logic.
// For now, when changing cartridges and such: tell AAPS to stop the loop, change cartridge and resume the loop.
if (currentMenu == null || currentMenu.getType() == MenuType.STOP) {
if (cmd instanceof GetPumpStateCommand) {
returnable.cmdResult = new CommandResult().success(true).enacted(false);
} else {
if (cmd.needsRunMode()) {
returnable.cmdResult = new CommandResult().success(false).enacted(false).message("Pump is suspended");
}
return;
}
}
log.debug("Connection ready to execute cmd " + cmd);
PumpState pumpState = readPumpStateInternal();
log.debug("Pump state before running command: " + pumpState);
@ -718,6 +715,18 @@ public class RuffyScripter implements RuffyCommands {
}
}
public void verifyRootMenuIsDisplayed() {
int retries = 600;
while (getCurrentMenu().getType() != MenuType.MAIN_MENU && getCurrentMenu().getType() != MenuType.STOP) {
if (retries > 0) {
SystemClock.sleep(100);
retries = retries - 1;
} else {
throw new CommandException().message("Invalid pump state, expected to be in menu MAIN or STOP but current menu is " + currentMenu.getType());
}
}
}
@SuppressWarnings("unchecked")
public <T> T readBlinkingValue(Class<T> expectedType, MenuAttribute attribute) {
int retries = 5;

View file

@ -22,4 +22,9 @@ public abstract class BaseCommand implements Command {
public boolean isCancellable() {
return canBeCancelled;
}
@Override
public boolean needsRunMode() {
return false;
}
}

View file

@ -54,7 +54,7 @@ public class BolusCommand extends BaseCommand {
if (cancelRequested) {
bolusProgressReporter.report(STOPPING, 0, 0);
scripter.returnToMainMenu();
scripter.returnToRootMenu();
bolusProgressReporter.report(STOPPED, 0, 0);
return new CommandResult().success(true).enacted(false)
.message("Bolus cancelled as per user request with no insulin delivered");
@ -192,7 +192,7 @@ public class BolusCommand extends BaseCommand {
log.debug("Bolus record in history confirms delivered bolus");
// TODO how would this call fail? more generally ......
scripter.returnToMainMenu();
scripter.returnToRootMenu();
if (scripter.getCurrentMenu().getType() != MenuType.MAIN_MENU) {
throw new CommandException().success(false).enacted(true)
.message("Bolus was correctly delivered and checked against history, but we "
@ -262,6 +262,11 @@ public class BolusCommand extends BaseCommand {
bolusProgressReporter.report(STOPPING, 0, 0);
}
@Override
public boolean needsRunMode() {
return true;
}
@Override
public String toString() {
return "BolusCommand{" +

View file

@ -57,6 +57,11 @@ public class CancelTbrCommand extends BaseCommand {
}
}
@Override
public boolean needsRunMode() {
return true;
}
@Override
public String toString() {
return "CancelTbrCommand{}";

View file

@ -16,4 +16,5 @@ public interface Command {
CommandResult execute();
List<String> validateArguments();
void setScripter(RuffyScripter scripter);
boolean needsRunMode();
}

View file

@ -6,7 +6,7 @@ import java.util.List;
import de.jotomo.ruffyscripter.RuffyScripter;
import de.jotomo.ruffy.spi.CommandResult;
public class ReadBasalProfileCommand implements Command {
public class ReadBasalProfileCommand extends BaseCommand {
private final int number;
public ReadBasalProfileCommand(int number) {

View file

@ -16,6 +16,7 @@ import de.jotomo.ruffy.spi.history.PumpHistoryRequest;
public class ReadHistoryCommand extends BaseCommand {
private final PumpHistoryRequest request;
private final PumpHistory history = new PumpHistory();
public ReadHistoryCommand(PumpHistoryRequest request) {
this.request = request;
@ -23,11 +24,10 @@ public class ReadHistoryCommand extends BaseCommand {
@Override
public CommandResult execute() {
PumpHistory history = new PumpHistory();
if (request.reservoirLevel)
readReservoirLevel(history);
if (request.reservoirLevel) {
readReservoirLevel();
}
if (request.bolusHistory != PumpHistoryRequest.SKIP
|| request.bolusHistory != PumpHistoryRequest.SKIP
|| request.tbrHistory != PumpHistoryRequest.SKIP
|| request.errorHistory != PumpHistoryRequest.SKIP
|| request.tddHistory != PumpHistoryRequest.SKIP) {
@ -81,19 +81,20 @@ public class ReadHistoryCommand extends BaseCommand {
// TODO start or end time?
MenuTime time = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.TIME);
}
scripter.returnToMainMenu();
scripter.returnToRootMenu();
}
scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU);
scripter.verifyRootMenuIsDisplayed();
return new CommandResult().success(true).enacted(false).history(history);
}
private void readReservoirLevel(PumpHistory history) {
scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU);
private void readReservoirLevel() {
scripter.verifyRootMenuIsDisplayed();
scripter.pressCheckKey();
scripter.waitForMenuToBeLeft(MenuType.MAIN_MENU);
scripter.waitForMenuToBeLeft(MenuType.STOP);
scripter.verifyMenuIsDisplayed(MenuType.QUICK_INFO);
int remainingInsulin = ((Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.REMAINING_INSULIN)).intValue();
scripter.returnToMainMenu();
scripter.returnToRootMenu();
history.reservoirLevel = remainingInsulin;
}

View file

@ -6,10 +6,10 @@ import java.util.List;
import de.jotomo.ruffy.spi.CommandResult;
import de.jotomo.ruffyscripter.RuffyScripter;
public class ReadPumpStateCommand implements Command {
public class ReadPumpStateCommand extends BaseCommand {
@Override
public CommandResult execute() {
return new CommandResult().success(true).enacted(false);
return new CommandResult().success(true).enacted(false).state(scripter.readPumpStateInternal());
}
@Override

View file

@ -6,7 +6,7 @@ import de.jotomo.ruffy.spi.BasalProfile;
import de.jotomo.ruffyscripter.RuffyScripter;
import de.jotomo.ruffy.spi.CommandResult;
public class SetBasalProfileCommand implements Command {
public class SetBasalProfileCommand extends BaseCommand {
public SetBasalProfileCommand(BasalProfile basalProfile) {
}

View file

@ -267,6 +267,11 @@ public class SetTbrCommand extends BaseCommand {
return scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE).longValue();
}
@Override
public boolean needsRunMode() {
return true;
}
@Override
public String toString() {
return "SetTbrCommand{" +