diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java
index 392f98a5e9..ec3fdc32a0 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java
@@ -32,6 +32,7 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
+import info.nightscout.utils.SP;
/**
* Created by mike on 05.08.2016.
@@ -45,6 +46,8 @@ public class LoopPlugin implements PluginBase {
private boolean fragmentEnabled = false;
private boolean fragmentVisible = true;
+ private long loopSuspendedTill = 0L; // end of manual loop suspend
+
public class LastRun {
public APSResult request = null;
public APSResult constraintsProcessed = null;
@@ -64,6 +67,7 @@ public class LoopPlugin implements PluginBase {
sHandler = new Handler(sHandlerThread.getLooper());
}
MainApp.bus().register(this);
+ loopSuspendedTill = SP.getLong("loopSuspendedTill", 0L);
}
@Override
@@ -127,6 +131,44 @@ public class LoopPlugin implements PluginBase {
invoke("EventNewBG", true);
}
+ public long suspendedTo() {
+ return loopSuspendedTill;
+ }
+
+ public void suspendTo(long endTime) {
+ loopSuspendedTill = endTime;
+ SP.putLong("loopSuspendedTill", loopSuspendedTill);
+ }
+
+ public int minutesToEndOfSuspend() {
+ if (loopSuspendedTill == 0)
+ return 0;
+
+ long now = new Date().getTime();
+ long msecDiff = loopSuspendedTill - now;
+
+ if (loopSuspendedTill <= now) { // time exceeded
+ suspendTo(0L);
+ return 0;
+ }
+
+ return (int) (msecDiff / 60d / 1000d);
+ }
+
+ public boolean isSuspended() {
+ if (loopSuspendedTill == 0)
+ return false;
+
+ long now = new Date().getTime();
+
+ if (loopSuspendedTill <= now) { // time exceeded
+ suspendTo(0L);
+ return false;
+ }
+
+ return true;
+ }
+
public void invoke(String initiator, boolean allowNotification) {
try {
if (Config.logFunctionCalls)
@@ -140,15 +182,21 @@ public class LoopPlugin implements PluginBase {
final ConfigBuilderPlugin configBuilder = MainApp.getConfigBuilder();
APSResult result = null;
+ if (configBuilder == null || !isEnabled(PluginBase.LOOP))
+ return;
+
+ if (isSuspended()) {
+ log.debug(MainApp.sResources.getString(R.string.loopsuspended));
+ MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.loopsuspended)));
+ return;
+ }
+
if (configBuilder.isSuspended()) {
log.debug(MainApp.sResources.getString(R.string.pumpsuspended));
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.pumpsuspended)));
return;
}
- if (configBuilder == null || !isEnabled(PluginBase.LOOP))
- return;
-
// Check if pump info is loaded
if (configBuilder.getBaseBasalRate() < 0.01d) return;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java
index a10fbca206..f449dc18d1 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java
@@ -18,8 +18,10 @@ import android.support.v7.app.AlertDialog;
import android.support.v7.widget.CardView;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
+import android.view.ContextMenu;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
@@ -95,6 +97,7 @@ import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.Round;
import info.nightscout.utils.SP;
+import info.nightscout.utils.ToastUtils;
public class OverviewFragment extends Fragment {
@@ -310,6 +313,133 @@ public class OverviewFragment extends Fragment {
return view;
}
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, v, menuInfo);
+ final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop();
+ if (activeloop == null)
+ return;
+ menu.setHeaderTitle(MainApp.sResources.getString(R.string.loop));
+ if (activeloop.isEnabled(PluginBase.LOOP)) {
+ menu.add(MainApp.sResources.getString(R.string.disabledloop));
+ if (!activeloop.isSuspended()) {
+ menu.add(MainApp.sResources.getString(R.string.suspendloopfor1h));
+ menu.add(MainApp.sResources.getString(R.string.suspendloopfor2h));
+ menu.add(MainApp.sResources.getString(R.string.suspendloopfor3h));
+ menu.add(MainApp.sResources.getString(R.string.suspendloopfor10h));
+ menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor30m));
+ menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor1h));
+ menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor2h));
+ menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor3h));
+ } else {
+ menu.add(MainApp.sResources.getString(R.string.resume));
+ }
+ }
+ if (!activeloop.isEnabled(PluginBase.LOOP))
+ menu.add(MainApp.sResources.getString(R.string.enabledloop));
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop();
+ if (item.getTitle() == MainApp.sResources.getString(R.string.disabledloop)) {
+ activeloop.setFragmentEnabled(PluginBase.LOOP, false);
+ activeloop.setFragmentVisible(PluginBase.LOOP, false);
+ MainApp.getConfigBuilder().storeSettings();
+ MainApp.bus().post(new EventRefreshGui(false));
+ return true;
+ } else if (item.getTitle() == MainApp.sResources.getString(R.string.enabledloop)) {
+ activeloop.setFragmentEnabled(PluginBase.LOOP, true);
+ activeloop.setFragmentVisible(PluginBase.LOOP, true);
+ MainApp.getConfigBuilder().storeSettings();
+ MainApp.bus().post(new EventRefreshGui(false));
+ return true;
+ } else if (item.getTitle() == MainApp.sResources.getString(R.string.resume)) {
+ activeloop.suspendTo(0L);
+ sHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal();
+ if (!result.success) {
+ ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
+ }
+ MainApp.bus().post(new EventRefreshGui(false));
+ }
+ });
+ return true;
+ } else if (item.getTitle() == MainApp.sResources.getString(R.string.suspendloopfor1h)) {
+ activeloop.suspendTo(new Date().getTime() + 60L * 60 * 1000);
+ MainApp.bus().post(new EventRefreshGui(false));
+ return true;
+ } else if (item.getTitle() == MainApp.sResources.getString(R.string.suspendloopfor2h)) {
+ activeloop.suspendTo(new Date().getTime() + 2 * 60L * 60 * 1000);
+ MainApp.bus().post(new EventRefreshGui(false));
+ return true;
+ } else if (item.getTitle() == MainApp.sResources.getString(R.string.suspendloopfor3h)) {
+ activeloop.suspendTo(new Date().getTime() + 3 * 60L * 60 * 1000);
+ MainApp.bus().post(new EventRefreshGui(false));
+ return true;
+ } else if (item.getTitle() == MainApp.sResources.getString(R.string.suspendloopfor10h)) {
+ activeloop.suspendTo(new Date().getTime() + 10 * 60L * 60 * 1000);
+ MainApp.bus().post(new EventRefreshGui(false));
+ return true;
+ } else if (item.getTitle() == MainApp.sResources.getString(R.string.disconnectpumpfor30m)) {
+ activeloop.suspendTo(new Date().getTime() + 30L * 60 * 1000);
+ sHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 30);
+ if (!result.success) {
+ ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
+ }
+ MainApp.bus().post(new EventRefreshGui(false));
+ }
+ });
+ return true;
+ } else if (item.getTitle() == MainApp.sResources.getString(R.string.disconnectpumpfor1h)) {
+ activeloop.suspendTo(new Date().getTime() + 1 * 60L * 60 * 1000);
+ sHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 60);
+ if (!result.success) {
+ ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
+ }
+ MainApp.bus().post(new EventRefreshGui(false));
+ }
+ });
+ return true;
+ } else if (item.getTitle() == MainApp.sResources.getString(R.string.disconnectpumpfor2h)) {
+ activeloop.suspendTo(new Date().getTime() + 2 * 60L * 60 * 1000);
+ sHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 2 * 60);
+ if (!result.success) {
+ ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
+ }
+ MainApp.bus().post(new EventRefreshGui(false));
+ }
+ });
+ return true;
+ } else if (item.getTitle() == MainApp.sResources.getString(R.string.disconnectpumpfor3h)) {
+ activeloop.suspendTo(new Date().getTime() + 3 * 60L * 60 * 1000);
+ sHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 3 * 60);
+ if (!result.success) {
+ ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
+ }
+ MainApp.bus().post(new EventRefreshGui(false));
+ }
+ });
+ return true;
+ }
+
+ return super.onContextItemSelected(item);
+ }
+
void processQuickWizard() {
final BgReading actualBg = GlucoseStatus.actualBg();
if (MainApp.getConfigBuilder() == null || ConfigBuilderPlugin.getActiveProfile() == null) // app not initialized yet
@@ -410,6 +540,7 @@ public class OverviewFragment extends Fragment {
super.onPause();
MainApp.bus().unregister(this);
sLoopHandler.removeCallbacksAndMessages(null);
+ unregisterForContextMenu(apsModeView);
}
@Override
@@ -424,6 +555,7 @@ public class OverviewFragment extends Fragment {
}
};
sLoopHandler.postDelayed(sRefreshLoop, 60 * 1000L);
+ registerForContextMenu(apsModeView);
updateGUIIfVisible();
}
@@ -562,7 +694,11 @@ public class OverviewFragment extends Fragment {
apsModeView.setBackgroundResource(R.drawable.loopmodeborder);
apsModeView.setTextColor(Color.BLACK);
final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop();
- if (pump.isSuspended()) {
+ if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isSuspended()) {
+ apsModeView.setBackgroundResource(R.drawable.loopmodesuspendedborder);
+ apsModeView.setText(String.format(MainApp.sResources.getString(R.string.loopsuspendedfor), activeloop.minutesToEndOfSuspend()));
+ apsModeView.setTextColor(Color.WHITE);
+ } else if (pump.isSuspended()) {
apsModeView.setBackgroundResource(R.drawable.loopmodesuspendedborder);
apsModeView.setText(MainApp.sResources.getString(R.string.pumpsuspended));
apsModeView.setTextColor(Color.WHITE);
@@ -576,10 +712,8 @@ public class OverviewFragment extends Fragment {
apsModeView.setBackgroundResource(R.drawable.loopmodedisabledborder);
apsModeView.setText(MainApp.sResources.getString(R.string.disabledloop));
apsModeView.setTextColor(Color.WHITE);
-
}
-
-
+/*
apsModeView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
@@ -600,7 +734,7 @@ public class OverviewFragment extends Fragment {
}
});
apsModeView.setLongClickable(true);
-
+*/
} else {
apsModeView.setVisibility(View.GONE);
}
diff --git a/app/src/main/java/info/nightscout/utils/SP.java b/app/src/main/java/info/nightscout/utils/SP.java
index cce1df9474..9bed316195 100644
--- a/app/src/main/java/info/nightscout/utils/SP.java
+++ b/app/src/main/java/info/nightscout/utils/SP.java
@@ -61,7 +61,11 @@ public class SP {
}
static public long getLong(String key, Long defaultValue) {
- return SafeParse.stringToLong(sharedPreferences.getString(key, defaultValue.toString()));
+ try {
+ return sharedPreferences.getLong(key, defaultValue);
+ } catch (Exception e) {
+ return SafeParse.stringToLong(sharedPreferences.getString(key, defaultValue.toString()));
+ }
}
static public void putBoolean(String key, boolean value) {
@@ -82,9 +86,9 @@ public class SP {
editor.apply();
}
- static public void putString(String key, String value) {
+ static public void putLong(String key, long value) {
SharedPreferences.Editor editor = sharedPreferences.edit();
- editor.putString(key, value);
+ editor.putLong(key, value);
editor.apply();
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 955c02017f..8c79783784 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -139,6 +139,7 @@
Closed Loop
Open Loop
Loop Disabled
+ Loop Enabled
New suggestion available
Unsupported version of NSClient
@@ -557,4 +558,17 @@
Device does not appear to support battery optimization whitelisting!
Please Allow Permission
%s needs battery optimalization whitelisting for proper performance
+ Loop suspended
+ Suspended (%d m)
+ Loop menu
+ Suspend loop for 1h
+ Suspend loop for 2h
+ Suspend loop for 3h
+ Suspend loop for 10h
+ Disconnect pump for 30 min
+ Disconnect pump for 1 h
+ Disconnect pump for 2 h
+ Disconnect pump for 3 h
+ Disconnect pump for 10 h
+ Resume