From c8443f10956555cb4d6380f359ebe0aae5117432 Mon Sep 17 00:00:00 2001 From: Roumen Georgiev Date: Fri, 4 Oct 2019 15:16:57 +0300 Subject: [PATCH] TriggerPumpDisconnected: Initial work --- .../general/automation/AutomationPlugin.kt | 3 +- .../triggers/TriggerPumpDisconnected.java | 146 ++++++++++++++++++ app/src/main/res/values/strings.xml | 4 + .../triggers/TriggerPumpDisconnectedTest.java | 112 ++++++++++++++ 4 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerPumpDisconnected.java create mode 100644 app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerPumpDisconnectedTest.java diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt index c4e58a90fa..b2ae16986a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt @@ -220,7 +220,8 @@ object AutomationPlugin : PluginBase(PluginDescription() TriggerWifiSsid(), TriggerLocation(), TriggerAutosensValue(), - TriggerBolusAgo() + TriggerBolusAgo(), + TriggerPumpDisconnected() ) } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerPumpDisconnected.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerPumpDisconnected.java new file mode 100644 index 0000000000..b506b6884c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerPumpDisconnected.java @@ -0,0 +1,146 @@ +package info.nightscout.androidaps.plugins.general.automation.triggers; + +import android.widget.LinearLayout; + +import androidx.fragment.app.FragmentManager; + +import com.google.common.base.Optional; + +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.general.automation.elements.Comparator; +import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration; +import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement; +import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder; +import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.JsonHelper; +import info.nightscout.androidaps.utils.T; + +public class TriggerPumpDisconnected extends Trigger { + private static Logger log = LoggerFactory.getLogger(L.AUTOMATION); + private InputDuration minutesAgo = new InputDuration(0, InputDuration.TimeUnit.MINUTES); + private Comparator comparator = new Comparator(); + + public TriggerPumpDisconnected() { + super(); + } + + private TriggerPumpDisconnected(TriggerPumpDisconnected triggerPumpDisconnected) { + super(); + minutesAgo = new InputDuration(triggerPumpDisconnected.minutesAgo); + lastRun = triggerPumpDisconnected.lastRun; + comparator = new Comparator(triggerPumpDisconnected.comparator); + } + + public double getValue() { + return minutesAgo.getValue(); + } + + public Comparator getComparator() { + return comparator; + } + + @Override + public synchronized boolean shouldRun() { + + if (lastRun > DateUtil.now() - T.mins(5).msecs()) + return false; + long lastConnection = ConfigBuilderPlugin.getPlugin().getActivePump().lastDataTime(); + + if (lastConnection == 0 && comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE) + return true; + + double minutesAgo = (double) (DateUtil.now() - lastConnection) / (60 * 1000); + if (L.isEnabled(L.AUTOMATION)) + log.debug("Last connection min ago: " + minutesAgo); + + boolean doRun = comparator.getValue().check((minutesAgo), getValue()); + if (doRun) { + if (L.isEnabled(L.AUTOMATION)) + log.debug("Ready for execution: " + friendlyDescription()); + return true; + } + return false; + } + + @Override + public synchronized String toJSON() { + JSONObject o = new JSONObject(); + try { + o.put("type", TriggerPumpDisconnected.class.getName()); + JSONObject data = new JSONObject(); + data.put("minutesAgo", getValue()); + data.put("lastRun", lastRun); + data.put("comparator", comparator.getValue().toString()); + o.put("data", data); + } catch (JSONException e) { + e.printStackTrace(); + } + return o.toString(); + } + + @Override + Trigger fromJSON(String data) { + try { + JSONObject d = new JSONObject(data); + minutesAgo.setMinutes(JsonHelper.safeGetInt(d, "minutesAgo")); + lastRun = JsonHelper.safeGetLong(d, "lastRun"); + comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator"))); + } catch (Exception e) { + e.printStackTrace(); + } + return this; + } + + @Override + public int friendlyName() { + return R.string.automation_trigger_pump_disconnected_label; + } + + @Override + public String friendlyDescription() { + return MainApp.gs(R.string.automation_trigger_pump_disconnected_compared, MainApp.gs(comparator.getValue().getStringRes()), (int) getValue()); + } + + @Override + public Optional icon() { + return Optional.of(R.drawable.remove); + } + + @Override + public Trigger duplicate() { + return new TriggerPumpDisconnected(this); + } + + TriggerPumpDisconnected setValue(int requestedValue) { + this.minutesAgo.setMinutes(requestedValue); + return this; + } + + TriggerPumpDisconnected lastRun(long lastRun) { + this.lastRun = lastRun; + return this; + } + + TriggerPumpDisconnected comparator(Comparator.Compare compare) { + this.comparator = new Comparator().setValue(compare); + return this; + } + + @Override + public void generateDialog(LinearLayout root, FragmentManager fragmentManager) { + new LayoutBuilder() + .add(new StaticLabel(R.string.automation_trigger_pump_disconnected_label)) + .add(comparator) + .add(new LabelWithElement(MainApp.gs(R.string.automation_trigger_pump_disconnected_description) + ": ", "", minutesAgo)) + .build(root); + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 25dc61ff45..fc6c37ea5e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1404,6 +1404,7 @@ REMOVE Preconditions: + Operation not supported by pump and/or driver. Operation not YET supported by pump. @@ -1574,6 +1575,9 @@ Set Bolus Change profile to Change profile to %1$s + Last connection to pump + Last connection to pump [minutes ago] + Last connection to pump %1$s %2$s min ago %2$+.2fU]]> diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerPumpDisconnectedTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerPumpDisconnectedTest.java new file mode 100644 index 0000000000..55a31365a0 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerPumpDisconnectedTest.java @@ -0,0 +1,112 @@ +package info.nightscout.androidaps.plugins.general.automation.triggers; + +import com.google.common.base.Optional; +import com.squareup.otto.Bus; + +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import info.AAPSMocker; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.automation.elements.Comparator; +import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; + +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({MainApp.class, Bus.class, ProfileFunctions.class, DateUtil.class, TreatmentsPlugin.class, ConfigBuilderPlugin.class, System.class}) +public class TriggerPumpDisconnectedTest { + + long now = 1514766900000L; + + @Test + public void shouldRunTest() { +// System.currentTimeMillis() is always 0 +// and so is every last connection time + VirtualPumpPlugin virtualPumpPlugin = VirtualPumpPlugin.getPlugin(); + when(ConfigBuilderPlugin.getPlugin().getActivePump()).thenReturn(virtualPumpPlugin); + Assert.assertEquals(0L, virtualPumpPlugin.lastDataTime()); + TriggerPumpDisconnected t = new TriggerPumpDisconnected().setValue(110).comparator(Comparator.Compare.IS_EQUAL).lastRun(now - 1); + Assert.assertFalse(t.shouldRun()); + when(DateUtil.now()).thenReturn(now + (10*60*1000)); // set current time to now + 10 min + t = new TriggerPumpDisconnected().setValue(110).comparator(Comparator.Compare.IS_EQUAL); + Assert.assertEquals(110, t.getValue(), 0.01d); + Assert.assertEquals(Comparator.Compare.IS_EQUAL, t.getComparator().getValue()); + Assert.assertFalse(t.shouldRun()); + t = new TriggerPumpDisconnected().setValue(10).comparator(Comparator.Compare.IS_EQUAL); + Assert.assertEquals(10, t.getValue(), 0.01d); + Assert.assertFalse(t.shouldRun()); // 0 == 10 -> FALSE + t = new TriggerPumpDisconnected().setValue(5).comparator(Comparator.Compare.IS_EQUAL_OR_GREATER); + Assert.assertTrue(t.shouldRun()); // 5 => 0 -> TRUE + t = new TriggerPumpDisconnected().setValue(310).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER); + Assert.assertFalse(t.shouldRun()); // 310 <= 0 -> FALSE + t = new TriggerPumpDisconnected().setValue(420).comparator(Comparator.Compare.IS_EQUAL); + Assert.assertFalse(t.shouldRun()); // 420 == 0 -> FALSE + } + + @Test + public void copyConstructorTest() { + TriggerPumpDisconnected t = new TriggerPumpDisconnected().setValue(213).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER); + TriggerPumpDisconnected t1 = (TriggerPumpDisconnected) t.duplicate(); + Assert.assertEquals(213, t1.getValue(), 0.01d); + Assert.assertEquals(Comparator.Compare.IS_EQUAL_OR_LESSER, t.getComparator().getValue()); + } + + @Test + public void executeTest() { + TriggerPumpDisconnected t = new TriggerPumpDisconnected().setValue(213).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER); + t.executed(1); + Assert.assertEquals(1l, t.getLastRun()); + } + + String LBJson = "{\"data\":{\"comparator\":\"IS_EQUAL\",\"lastRun\":0,\"minutesAgo\":410},\"type\":\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerPumpDisconnected\"}"; + + @Test + public void toJSONTest() { + TriggerPumpDisconnected t = new TriggerPumpDisconnected().setValue(410).comparator(Comparator.Compare.IS_EQUAL); + Assert.assertEquals(LBJson, t.toJSON()); + } + + @Test + public void fromJSONTest() throws JSONException { + TriggerPumpDisconnected t = new TriggerPumpDisconnected().setValue(410).comparator(Comparator.Compare.IS_EQUAL); + + TriggerPumpDisconnected t2 = (TriggerPumpDisconnected) Trigger.instantiate(new JSONObject(t.toJSON())); + Assert.assertEquals(Comparator.Compare.IS_EQUAL, t2.getComparator().getValue()); + Assert.assertEquals(410, t2.getValue(), 0.01d); + } + + @Test + public void iconTest() { + Assert.assertEquals(Optional.of(R.drawable.remove), new TriggerPumpDisconnected().icon()); + } + + @Test + public void friendlyNameTest() { + Assert.assertEquals(R.string.automation_trigger_pump_disconnected_label, new TriggerPumpDisconnected().friendlyName()); + } + + + @Before + public void mock() { + AAPSMocker.mockMainApp(); + AAPSMocker.mockConfigBuilder(); + AAPSMocker.mockBus(); + PowerMockito.mockStatic(DateUtil.class); + when(DateUtil.now()).thenReturn(now); + + } + +}