TriggerIob, more fixes
This commit is contained in:
parent
a08f01e69b
commit
27783fe33e
13 changed files with 437 additions and 69 deletions
|
@ -1,5 +1,7 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.actions;
|
package info.nightscout.androidaps.plugins.general.automation.actions;
|
||||||
|
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
@ -10,10 +12,14 @@ import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
import info.nightscout.androidaps.events.EventRefreshOverview;
|
import info.nightscout.androidaps.events.EventRefreshOverview;
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Label;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
|
||||||
import info.nightscout.androidaps.queue.Callback;
|
import info.nightscout.androidaps.queue.Callback;
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper;
|
||||||
|
|
||||||
public class ActionLoopSuspend extends Action {
|
public class ActionLoopSuspend extends Action {
|
||||||
public int minutes;
|
public InputDuration minutes = new InputDuration(0, InputDuration.TimeUnit.MINUTES);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int friendlyName() {
|
public int friendlyName() {
|
||||||
|
@ -22,13 +28,13 @@ public class ActionLoopSuspend extends Action {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String shortDescription() {
|
public String shortDescription() {
|
||||||
return MainApp.gs(R.string.suspendloop);
|
return MainApp.gs(R.string.suspendloopforXmin, minutes.getMinutes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doAction(Callback callback) {
|
public void doAction(Callback callback) {
|
||||||
if (!LoopPlugin.getPlugin().isSuspended()) {
|
if (!LoopPlugin.getPlugin().isSuspended()) {
|
||||||
LoopPlugin.getPlugin().suspendLoop(minutes);
|
LoopPlugin.getPlugin().suspendLoop(minutes.getMinutes());
|
||||||
MainApp.bus().post(new EventRefreshOverview("ActionLoopSuspend"));
|
MainApp.bus().post(new EventRefreshOverview("ActionLoopSuspend"));
|
||||||
if (callback != null)
|
if (callback != null)
|
||||||
callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
|
callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
|
||||||
|
@ -48,7 +54,7 @@ public class ActionLoopSuspend extends Action {
|
||||||
JSONObject o = new JSONObject();
|
JSONObject o = new JSONObject();
|
||||||
JSONObject data = new JSONObject();
|
JSONObject data = new JSONObject();
|
||||||
try {
|
try {
|
||||||
data.put("minutes", minutes);
|
data.put("minutes", minutes.getMinutes());
|
||||||
o.put("type", this.getClass().getName());
|
o.put("type", this.getClass().getName());
|
||||||
o.put("data", data);
|
o.put("data", data);
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
|
@ -61,11 +67,24 @@ public class ActionLoopSuspend extends Action {
|
||||||
public Action fromJSON(String data) {
|
public Action fromJSON(String data) {
|
||||||
try {
|
try {
|
||||||
JSONObject o = new JSONObject(data);
|
JSONObject o = new JSONObject(data);
|
||||||
minutes = o.getInt("minutes");
|
minutes.setMinutes(JsonHelper.safeGetInt(o,"minutes"));
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDialog() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateDialog(LinearLayout root) {
|
||||||
|
|
||||||
|
new LayoutBuilder()
|
||||||
|
.add(new Label(MainApp.gs(R.string.careportal_newnstreatment_duration_min_label), "", minutes))
|
||||||
|
.build(root);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class ActionStartTempTarget extends Action {
|
||||||
reason = JsonHelper.safeGetString(d, "reason");
|
reason = JsonHelper.safeGetString(d, "reason");
|
||||||
value.setUnits(JsonHelper.safeGetString(d, "units"));
|
value.setUnits(JsonHelper.safeGetString(d, "units"));
|
||||||
value.setMgdl(JsonHelper.safeGetInt(d, "valueInMg"));
|
value.setMgdl(JsonHelper.safeGetInt(d, "valueInMg"));
|
||||||
duration.setMinutes(JsonHelper.safeGetDouble(d, "durationInMinutes"));
|
duration.setMinutes(JsonHelper.safeGetInt(d, "durationInMinutes"));
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import butterknife.Unbinder;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger;
|
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger;
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerBg;
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerBg;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerIob;
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerRecurringTime;
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerRecurringTime;
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerTime;
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerTime;
|
||||||
|
|
||||||
|
@ -29,9 +30,10 @@ public class ChooseTriggerDialog extends DialogFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final List<Trigger> triggerDummyObjects = new ArrayList<Trigger>() {{
|
private static final List<Trigger> triggerDummyObjects = new ArrayList<Trigger>() {{
|
||||||
add(new TriggerBg());
|
|
||||||
add(new TriggerTime());
|
add(new TriggerTime());
|
||||||
add(new TriggerRecurringTime());
|
add(new TriggerRecurringTime());
|
||||||
|
add(new TriggerBg());
|
||||||
|
add(new TriggerIob());
|
||||||
}};
|
}};
|
||||||
|
|
||||||
private Unbinder mUnbinder;
|
private Unbinder mUnbinder;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.dialogs;
|
package info.nightscout.androidaps.plugins.general.automation.dialogs;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.design.widget.TextInputEditText;
|
import android.support.design.widget.TextInputEditText;
|
||||||
|
@ -135,7 +136,9 @@ public class EditEventDialog extends DialogFragment {
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onEventAutomationUpdateGui(EventAutomationUpdateGui ignored) {
|
public void onEventAutomationUpdateGui(EventAutomationUpdateGui ignored) {
|
||||||
mActionListAdapter.notifyDataSetChanged();
|
Activity activity = getActivity();
|
||||||
|
if (activity != null)
|
||||||
|
activity.runOnUiThread(() -> mActionListAdapter.notifyDataSetChanged());
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnClick(R.id.ok)
|
@OnClick(R.id.ok)
|
||||||
|
|
|
@ -13,9 +13,9 @@ public class InputDuration extends Element {
|
||||||
}
|
}
|
||||||
|
|
||||||
private TimeUnit unit;
|
private TimeUnit unit;
|
||||||
private double value;
|
private int value;
|
||||||
|
|
||||||
public InputDuration(double value, TimeUnit unit) {
|
public InputDuration(int value, TimeUnit unit) {
|
||||||
this.unit = unit;
|
this.unit = unit;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,8 @@ public class InputDuration extends Element {
|
||||||
// Hours
|
// Hours
|
||||||
numberPicker.setParams(0d, 0d, 24d, 1d, new DecimalFormat("0"), false);
|
numberPicker.setParams(0d, 0d, 24d, 1d, new DecimalFormat("0"), false);
|
||||||
}
|
}
|
||||||
numberPicker.setValue(value);
|
numberPicker.setValue((double) value);
|
||||||
numberPicker.setOnValueChangedListener(value -> this.value = value);
|
numberPicker.setOnValueChangedListener(value -> this.value = (int) value);
|
||||||
root.addView(numberPicker);
|
root.addView(numberPicker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,19 +43,19 @@ public class InputDuration extends Element {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMinutes(double value) {
|
public void setMinutes(int value) {
|
||||||
if (unit.equals(TimeUnit.MINUTES)) {
|
if (unit.equals(TimeUnit.MINUTES)) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
} else {
|
} else {
|
||||||
this.value = value / 60d;
|
this.value = value / 60;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getMinutes() {
|
public int getMinutes() {
|
||||||
if (unit.equals(TimeUnit.MINUTES)) {
|
if (unit.equals(TimeUnit.MINUTES)) {
|
||||||
return value;
|
return value;
|
||||||
} else {
|
} else {
|
||||||
return value * 60d;
|
return value * 60;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,16 +96,24 @@ public class TriggerBg extends Trigger {
|
||||||
public synchronized boolean shouldRun() {
|
public synchronized boolean shouldRun() {
|
||||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||||
|
|
||||||
if (glucoseStatus == null && comparator.equals(Comparator.IS_NOT_AVAILABLE))
|
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
||||||
if (lastRun < DateUtil.now() - T.mins(5).msecs()) {
|
return false;
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
if (glucoseStatus == null && comparator.equals(Comparator.IS_NOT_AVAILABLE)) {
|
||||||
return true;
|
if (L.isEnabled(L.AUTOMATION))
|
||||||
}
|
log.debug("Ready for execution: " + friendlyDescription());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (glucoseStatus == null)
|
if (glucoseStatus == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return comparator.check(glucoseStatus.glucose, Profile.toMgdl(threshold, units));
|
boolean doRun = comparator.check(glucoseStatus.glucose, Profile.toMgdl(threshold, units));
|
||||||
|
if (doRun) {
|
||||||
|
if (L.isEnabled(L.AUTOMATION))
|
||||||
|
log.debug("Ready for execution: " + friendlyDescription());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,212 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.IobTotal;
|
||||||
|
import info.nightscout.androidaps.data.Profile;
|
||||||
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil;
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper;
|
||||||
|
import info.nightscout.androidaps.utils.NumberPicker;
|
||||||
|
import info.nightscout.androidaps.utils.T;
|
||||||
|
|
||||||
|
public class TriggerIob extends Trigger {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
||||||
|
|
||||||
|
private double threshold;
|
||||||
|
private Comparator comparator = Comparator.IS_EQUAL;
|
||||||
|
private long lastRun;
|
||||||
|
|
||||||
|
final TextWatcher textWatcher = new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
threshold = Math.max(threshold, -20d);
|
||||||
|
threshold = Math.min(threshold, 20d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public TriggerIob() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerIob(TriggerIob triggerIob) {
|
||||||
|
super();
|
||||||
|
comparator = triggerIob.comparator;
|
||||||
|
lastRun = triggerIob.lastRun;
|
||||||
|
threshold = triggerIob.threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getThreshold() {
|
||||||
|
return threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comparator getComparator() {
|
||||||
|
return comparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLastRun() {
|
||||||
|
return lastRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized boolean shouldRun() {
|
||||||
|
Profile profile = ProfileFunctions.getInstance().getProfile();
|
||||||
|
if (profile == null)
|
||||||
|
return false;
|
||||||
|
IobTotal iob = IobCobCalculatorPlugin.getPlugin().calculateFromTreatmentsAndTempsSynchronized(DateUtil.now(), profile);
|
||||||
|
|
||||||
|
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
boolean doRun = comparator.check(iob.iob, threshold);
|
||||||
|
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", TriggerIob.class.getName());
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("threshold", threshold);
|
||||||
|
data.put("lastRun", lastRun);
|
||||||
|
data.put("comparator", comparator.toString());
|
||||||
|
o.put("data", data);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Trigger fromJSON(String data) {
|
||||||
|
try {
|
||||||
|
JSONObject d = new JSONObject(data);
|
||||||
|
threshold = JsonHelper.safeGetDouble(d, "threshold");
|
||||||
|
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
||||||
|
comparator = Comparator.valueOf(JsonHelper.safeGetString(d, "comparator"));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return R.string.iob;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String friendlyDescription() {
|
||||||
|
return MainApp.gs(R.string.iobcompared, MainApp.gs(comparator.getStringRes()), threshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.of(R.drawable.remove); // TODO icon
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void executed(long time) {
|
||||||
|
lastRun = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Trigger duplicate() {
|
||||||
|
return new TriggerIob(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerIob threshold(double threshold) {
|
||||||
|
this.threshold = threshold;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerIob lastRun(long lastRun) {
|
||||||
|
this.lastRun = lastRun;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerIob comparator(Comparator comparator) {
|
||||||
|
this.comparator = comparator;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View createView(Context context, FragmentManager fragmentManager) {
|
||||||
|
LinearLayout root = (LinearLayout) super.createView(context, fragmentManager);
|
||||||
|
|
||||||
|
// spinner for comparator
|
||||||
|
Spinner spinner = new Spinner(context);
|
||||||
|
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_item, Comparator.labels());
|
||||||
|
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
spinner.setAdapter(spinnerArrayAdapter);
|
||||||
|
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
);
|
||||||
|
spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
|
||||||
|
spinner.setLayoutParams(spinnerParams);
|
||||||
|
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
comparator = Comparator.values()[position];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected(AdapterView<?> parent) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
spinner.setSelection(comparator.ordinal());
|
||||||
|
root.addView(spinner);
|
||||||
|
|
||||||
|
// horizontal layout
|
||||||
|
LinearLayout layout = new LinearLayout(context);
|
||||||
|
layout.setOrientation(LinearLayout.HORIZONTAL);
|
||||||
|
layout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
root.addView(layout);
|
||||||
|
|
||||||
|
// input field for threshold
|
||||||
|
NumberPicker numberPicker = new NumberPicker(context, null);
|
||||||
|
numberPicker.setParams(0d, -20d, 20d, 0.1d, new DecimalFormat("0.0"), true, textWatcher);
|
||||||
|
numberPicker.setValue(threshold);
|
||||||
|
numberPicker.setOnValueChangedListener(value -> threshold = value);
|
||||||
|
layout.addView(numberPicker);
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,7 +36,7 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="if:"/>
|
android:text="@string/condition"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/editTrigger"
|
android:id="@+id/editTrigger"
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="then:"/>
|
android:text="@string/action"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/editAction"
|
android:id="@+id/editAction"
|
||||||
|
|
|
@ -1,40 +1,35 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
tools:context="info.nightscout.androidaps.plugins.general.automation.AutomationFragment">
|
tools:context="info.nightscout.androidaps.plugins.general.automation.AutomationFragment">
|
||||||
|
|
||||||
<RelativeLayout
|
<android.support.v7.widget.RecyclerView
|
||||||
|
android:id="@+id/eventListView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:layout_above="@+id/logView"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_marginBottom="-100dp" />
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<android.support.design.widget.FloatingActionButton
|
||||||
android:id="@+id/eventListView"
|
android:id="@+id/fabAddEvent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_alignParentTop="true" />
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:backgroundTint="@color/defaulttext"
|
||||||
|
android:src="@drawable/ic_add_black_24dp" />
|
||||||
|
|
||||||
<android.support.design.widget.FloatingActionButton
|
<TextView
|
||||||
android:id="@+id/fabAddEvent"
|
android:id="@+id/logView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="100dp"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true" />
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:src="@drawable/ic_add_black_24dp"
|
|
||||||
android:backgroundTint="@color/defaulttext"/>
|
|
||||||
|
|
||||||
<TextView
|
</RelativeLayout>
|
||||||
android:id="@+id/logView"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentBottom="true"
|
|
||||||
android:text="Log" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
|
@ -591,6 +591,7 @@
|
||||||
<string name="suspendloopfor2h">Suspend loop for 2h</string>
|
<string name="suspendloopfor2h">Suspend loop for 2h</string>
|
||||||
<string name="suspendloopfor3h">Suspend loop for 3h</string>
|
<string name="suspendloopfor3h">Suspend loop for 3h</string>
|
||||||
<string name="suspendloopfor10h">Suspend loop for 10 h</string>
|
<string name="suspendloopfor10h">Suspend loop for 10 h</string>
|
||||||
|
<string name="suspendloopforXmin">Suspend loop for %1$d min</string>
|
||||||
<string name="disconnectpumpfor15m">Disconnect pump for 15 min</string>
|
<string name="disconnectpumpfor15m">Disconnect pump for 15 min</string>
|
||||||
<string name="disconnectpumpfor30m">Disconnect pump for 30 min</string>
|
<string name="disconnectpumpfor30m">Disconnect pump for 30 min</string>
|
||||||
<string name="disconnectpumpfor1h">Disconnect pump for 1 h</string>
|
<string name="disconnectpumpfor1h">Disconnect pump for 1 h</string>
|
||||||
|
@ -1341,6 +1342,7 @@
|
||||||
<string name="glucoseisnotavailable">Glucose is not available</string>
|
<string name="glucoseisnotavailable">Glucose is not available</string>
|
||||||
<string name="glucosecomparedmgdl">Glucose %1$s %2$.0f %3$s</string>
|
<string name="glucosecomparedmgdl">Glucose %1$s %2$.0f %3$s</string>
|
||||||
<string name="glucosecomparedmmol">Glucose %1$s %2$.1f %3$s</string>
|
<string name="glucosecomparedmmol">Glucose %1$s %2$.1f %3$s</string>
|
||||||
|
<string name="iobcompared">IOB %1$s %2$.1f</string>
|
||||||
<string name="and">And</string>
|
<string name="and">And</string>
|
||||||
<string name="or">Or</string>
|
<string name="or">Or</string>
|
||||||
<string name="xor">Exclusive or</string>
|
<string name="xor">Exclusive or</string>
|
||||||
|
@ -1377,6 +1379,8 @@
|
||||||
<string name="every">Every</string>
|
<string name="every">Every</string>
|
||||||
<string name="never">Never</string>
|
<string name="never">Never</string>
|
||||||
<string name="mins">%1$dmins</string>
|
<string name="mins">%1$dmins</string>
|
||||||
|
<string name="condition">Condition:</string>
|
||||||
|
<string name="action">Action:</string>
|
||||||
<plurals name="objective_days">
|
<plurals name="objective_days">
|
||||||
<item quantity="one">%1$d day</item>
|
<item quantity="one">%1$d day</item>
|
||||||
<item quantity="other">%1$d days</item>
|
<item quantity="other">%1$d days</item>
|
||||||
|
|
|
@ -10,7 +10,6 @@ import com.squareup.otto.Bus;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.mockito.stubbing.Answer;
|
|
||||||
import org.powermock.api.mockito.PowerMockito;
|
import org.powermock.api.mockito.PowerMockito;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -27,14 +26,12 @@ import info.nightscout.androidaps.logging.L;
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
|
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo;
|
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||||
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin;
|
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin;
|
||||||
import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin;
|
import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin;
|
||||||
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin;
|
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin;
|
||||||
import info.nightscout.androidaps.plugins.treatments.TreatmentService;
|
import info.nightscout.androidaps.plugins.treatments.TreatmentService;
|
||||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||||
import info.nightscout.androidaps.queue.Callback;
|
|
||||||
import info.nightscout.androidaps.queue.CommandQueue;
|
import info.nightscout.androidaps.queue.CommandQueue;
|
||||||
import info.nightscout.androidaps.utils.SP;
|
import info.nightscout.androidaps.utils.SP;
|
||||||
|
|
||||||
|
@ -42,7 +39,6 @@ import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.anyLong;
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
import static org.mockito.Mockito.doAnswer;
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
|
|
@ -12,18 +12,13 @@ import org.powermock.modules.junit4.PowerMockRunner;
|
||||||
import info.AAPSMocker;
|
import info.AAPSMocker;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.interfaces.PluginType;
|
|
||||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
|
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
|
||||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
|
|
||||||
import info.nightscout.androidaps.queue.Callback;
|
import info.nightscout.androidaps.queue.Callback;
|
||||||
import info.nightscout.androidaps.utils.SP;
|
import info.nightscout.androidaps.utils.SP;
|
||||||
|
|
||||||
import static org.powermock.api.mockito.PowerMockito.mock;
|
|
||||||
import static org.powermock.api.mockito.PowerMockito.when;
|
|
||||||
|
|
||||||
@RunWith(PowerMockRunner.class)
|
@RunWith(PowerMockRunner.class)
|
||||||
@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, SP.class, NSUpload.class})
|
@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, SP.class, NSUpload.class})
|
||||||
public class ActionLoopSuspendTest {
|
public class ActionLoopSuspendTest {
|
||||||
|
@ -36,7 +31,8 @@ public class ActionLoopSuspendTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shortDescriptionTest() {
|
public void shortDescriptionTest() {
|
||||||
Assert.assertEquals("Suspend loop", actionLoopSuspend.shortDescription());
|
actionLoopSuspend.minutes = new InputDuration(30, InputDuration.TimeUnit.MINUTES);
|
||||||
|
Assert.assertEquals(null, actionLoopSuspend.shortDescription()); // string not in AAPSMocker
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -46,7 +42,7 @@ public class ActionLoopSuspendTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doActionTest() {
|
public void doActionTest() {
|
||||||
actionLoopSuspend.minutes = 30;
|
actionLoopSuspend.minutes = new InputDuration(30, InputDuration.TimeUnit.MINUTES);
|
||||||
|
|
||||||
LoopPlugin.getPlugin().suspendTo(0);
|
LoopPlugin.getPlugin().suspendTo(0);
|
||||||
actionLoopSuspend.doAction(new Callback() {
|
actionLoopSuspend.doAction(new Callback() {
|
||||||
|
@ -67,10 +63,10 @@ public class ActionLoopSuspendTest {
|
||||||
@Test
|
@Test
|
||||||
public void applyTest() {
|
public void applyTest() {
|
||||||
ActionLoopSuspend a = new ActionLoopSuspend();
|
ActionLoopSuspend a = new ActionLoopSuspend();
|
||||||
a.minutes = 20;
|
a.minutes = new InputDuration(20, InputDuration.TimeUnit.MINUTES);
|
||||||
ActionLoopSuspend b = new ActionLoopSuspend();
|
ActionLoopSuspend b = new ActionLoopSuspend();
|
||||||
b.apply(a);
|
b.apply(a);
|
||||||
Assert.assertEquals(20, b.minutes);
|
Assert.assertEquals(20, b.minutes.getMinutes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
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.data.IobTotal;
|
||||||
|
import info.nightscout.androidaps.data.Profile;
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
|
import static org.powermock.api.mockito.PowerMockito.when;
|
||||||
|
|
||||||
|
@RunWith(PowerMockRunner.class)
|
||||||
|
@PrepareForTest({MainApp.class, Bus.class, ProfileFunctions.class, DateUtil.class, IobCobCalculatorPlugin.class})
|
||||||
|
public class TriggerIobTest {
|
||||||
|
|
||||||
|
long now = 1514766900000L;
|
||||||
|
IobCobCalculatorPlugin iobCobCalculatorPlugin;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldRunTest() {
|
||||||
|
PowerMockito.when(iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(anyLong(), any(Profile.class))).thenReturn(generateIobRecordData());
|
||||||
|
|
||||||
|
TriggerIob t = new TriggerIob().threshold(1.1d).comparator(Trigger.Comparator.IS_EQUAL);
|
||||||
|
Assert.assertFalse(t.shouldRun());
|
||||||
|
t = new TriggerIob().threshold(1d).comparator(Trigger.Comparator.IS_EQUAL);
|
||||||
|
Assert.assertTrue(t.shouldRun());
|
||||||
|
t = new TriggerIob().threshold(0.8d).comparator(Trigger.Comparator.IS_GREATER);
|
||||||
|
Assert.assertTrue(t.shouldRun());
|
||||||
|
t = new TriggerIob().threshold(0.8d).comparator(Trigger.Comparator.IS_EQUAL_OR_GREATER);
|
||||||
|
Assert.assertTrue(t.shouldRun());
|
||||||
|
t = new TriggerIob().threshold(0.9d).comparator(Trigger.Comparator.IS_EQUAL_OR_GREATER);
|
||||||
|
Assert.assertTrue(t.shouldRun());
|
||||||
|
t = new TriggerIob().threshold(1.2d).comparator(Trigger.Comparator.IS_EQUAL_OR_LESSER);
|
||||||
|
Assert.assertTrue(t.shouldRun());
|
||||||
|
t = new TriggerIob().threshold(1.1d).comparator(Trigger.Comparator.IS_EQUAL);
|
||||||
|
Assert.assertFalse(t.shouldRun());
|
||||||
|
t = new TriggerIob().threshold(1d).comparator(Trigger.Comparator.IS_EQUAL_OR_LESSER);
|
||||||
|
Assert.assertTrue(t.shouldRun());
|
||||||
|
t = new TriggerIob().threshold(0.9d).comparator(Trigger.Comparator.IS_EQUAL_OR_LESSER);
|
||||||
|
Assert.assertFalse(t.shouldRun());
|
||||||
|
|
||||||
|
t = new TriggerIob().threshold(1d).comparator(Trigger.Comparator.IS_EQUAL).lastRun(now - 1);
|
||||||
|
Assert.assertFalse(t.shouldRun());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void textWatcherTest() {
|
||||||
|
TriggerIob t = new TriggerIob().threshold(-30d);
|
||||||
|
t.textWatcher.beforeTextChanged(null, 0, 0, 0);
|
||||||
|
t.textWatcher.onTextChanged(null, 0, 0, 0);
|
||||||
|
t.textWatcher.afterTextChanged(null);
|
||||||
|
Assert.assertEquals(-20d, t.getThreshold(), 0.01d);
|
||||||
|
|
||||||
|
t = new TriggerIob().threshold(300d);
|
||||||
|
t.textWatcher.afterTextChanged(null);
|
||||||
|
Assert.assertEquals(20d, t.getThreshold(), 0.01d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void copyConstructorTest() {
|
||||||
|
TriggerIob t = new TriggerIob().threshold(213).comparator(Trigger.Comparator.IS_EQUAL_OR_LESSER);
|
||||||
|
TriggerIob t1 = (TriggerIob) t.duplicate();
|
||||||
|
Assert.assertEquals(213d, t.getThreshold(), 0.01d);
|
||||||
|
Assert.assertEquals(Trigger.Comparator.IS_EQUAL_OR_LESSER, t.getComparator());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void executeTest() {
|
||||||
|
TriggerIob t = new TriggerIob().threshold(213).comparator(Trigger.Comparator.IS_EQUAL_OR_LESSER);
|
||||||
|
t.executed(1);
|
||||||
|
Assert.assertEquals(1l, t.getLastRun());
|
||||||
|
}
|
||||||
|
|
||||||
|
String bgJson = "{\"data\":{\"comparator\":\"IS_EQUAL\",\"lastRun\":0,\"threshold\":4.1},\"type\":\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerIob\"}";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void toJSONTest() {
|
||||||
|
TriggerIob t = new TriggerIob().threshold(4.1d).comparator(Trigger.Comparator.IS_EQUAL);
|
||||||
|
Assert.assertEquals(bgJson, t.toJSON());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void fromJSONTest() throws JSONException {
|
||||||
|
TriggerIob t = new TriggerIob().threshold(4.1d).comparator(Trigger.Comparator.IS_EQUAL);
|
||||||
|
|
||||||
|
TriggerIob t2 = (TriggerIob) Trigger.instantiate(new JSONObject(t.toJSON()));
|
||||||
|
Assert.assertEquals(Trigger.Comparator.IS_EQUAL, t2.getComparator());
|
||||||
|
Assert.assertEquals(4.1d, t2.getThreshold(), 0.01d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void iconTest() {
|
||||||
|
Assert.assertEquals(Optional.of(R.drawable.remove), new TriggerIob().icon());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void mock() {
|
||||||
|
AAPSMocker.mockMainApp();
|
||||||
|
AAPSMocker.mockBus();
|
||||||
|
iobCobCalculatorPlugin = AAPSMocker.mockIobCobCalculatorPlugin();
|
||||||
|
AAPSMocker.mockProfileFunctions();
|
||||||
|
|
||||||
|
PowerMockito.mockStatic(DateUtil.class);
|
||||||
|
when(DateUtil.now()).thenReturn(now);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
IobTotal generateIobRecordData() {
|
||||||
|
IobTotal iobTotal = new IobTotal(1);
|
||||||
|
iobTotal.iob = 1;
|
||||||
|
return iobTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue