UI and logic tweaking

This commit is contained in:
Milos Kozak 2019-04-18 19:33:23 +02:00
parent bfb39d81e7
commit 89ec81a850
17 changed files with 198 additions and 56 deletions

View file

@ -9,6 +9,9 @@ import org.slf4j.LoggerFactory;
import java.util.Objects; import java.util.Objects;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
@ -191,4 +194,11 @@ public class TempTarget implements Interval {
'}'; '}';
} }
public String friendlyDescription(String units) {
return Profile.toTargetRangeString(low, high, Constants.MGDL, units) +
units +
"@" + MainApp.gs(R.string.mins, durationInMinutes) +
(reason != null && !reason.equals("") ? "(" + reason + ")" : "");
}
} }

View file

@ -77,6 +77,7 @@ public class L {
public static final String CORE = "CORE"; public static final String CORE = "CORE";
public static final String AUTOSENS = "AUTOSENS"; public static final String AUTOSENS = "AUTOSENS";
public static final String AUTOMATION = "AUTOMATION";
public static final String EVENTS = "EVENTS"; public static final String EVENTS = "EVENTS";
public static final String GLUCOSE = "GLUCOSE"; public static final String GLUCOSE = "GLUCOSE";
public static final String BGSOURCE = "BGSOURCE"; public static final String BGSOURCE = "BGSOURCE";
@ -102,6 +103,7 @@ public class L {
private static void initialize() { private static void initialize() {
logElements = new ArrayList<>(); logElements = new ArrayList<>();
logElements.add(new LogElement(APS, true)); logElements.add(new LogElement(APS, true));
logElements.add(new LogElement(AUTOMATION, true));
logElements.add(new LogElement(AUTOSENS, false)); logElements.add(new LogElement(AUTOSENS, false));
logElements.add(new LogElement(BGSOURCE, true)); logElements.add(new LogElement(BGSOURCE, true));
logElements.add(new LogElement(GLUCOSE, false)); logElements.add(new LogElement(GLUCOSE, false));

View file

@ -207,7 +207,7 @@ public class AutomationFragment extends SubscriberFragment {
@Override @Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) { public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
final Action action = mActionList.get(position); final Action action = mActionList.get(position);
holder.actionTitle.setText(action.friendlyName()); holder.actionTitle.setText(action.shortDescription());
holder.layoutText.setOnClickListener(v -> { holder.layoutText.setOnClickListener(v -> {
if (action.hasDialog()) { if (action.hasDialog()) {
EditActionDialog dialog = EditActionDialog.newInstance(action); EditActionDialog dialog = EditActionDialog.newInstance(action);

View file

@ -36,7 +36,7 @@ import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.T; import info.nightscout.androidaps.utils.T;
public class AutomationPlugin extends PluginBase { public class AutomationPlugin extends PluginBase {
private static Logger log = LoggerFactory.getLogger(L.CORE); private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
private final String key_AUTOMATION_EVENTS = "AUTOMATION_EVENTS"; private final String key_AUTOMATION_EVENTS = "AUTOMATION_EVENTS";
static AutomationPlugin plugin = null; static AutomationPlugin plugin = null;
@ -177,6 +177,7 @@ public class AutomationPlugin extends PluginBase {
} }
synchronized void processActions() { synchronized void processActions() {
if (L.isEnabled(L.AUTOMATION))
log.debug("processActions"); log.debug("processActions");
for (AutomationEvent event : getAutomationEvents()) { for (AutomationEvent event : getAutomationEvents()) {
if (event.getTrigger().shouldRun()) { if (event.getTrigger().shouldRun()) {
@ -196,7 +197,8 @@ public class AutomationPlugin extends PluginBase {
sb.append(": "); sb.append(": ");
sb.append(result.comment); sb.append(result.comment);
executionLog.add(sb.toString()); executionLog.add(sb.toString());
log.debug(sb.toString()); if (L.isEnabled(L.AUTOMATION))
log.debug("Executed: " + sb.toString());
MainApp.bus().post(new EventAutomationUpdateGui()); MainApp.bus().post(new EventAutomationUpdateGui());
} }
}); });
@ -204,6 +206,6 @@ public class AutomationPlugin extends PluginBase {
event.getTrigger().executed(DateUtil.now()); event.getTrigger().executed(DateUtil.now());
} }
} }
storeToSP(); // save last run time
} }
} }

View file

@ -13,11 +13,12 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.plugins.general.automation.elements.InputBg; import info.nightscout.androidaps.plugins.general.automation.elements.InputBg;
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration; 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.Label;
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.Callback; import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.JsonHelper; import info.nightscout.androidaps.utils.JsonHelper;
@ -29,7 +30,7 @@ public class ActionStartTempTarget extends Action {
TempTarget tempTarget; TempTarget tempTarget;
public ActionStartTempTarget() { public ActionStartTempTarget() {
value = new InputBg(Constants.MGDL); value = new InputBg(ProfileFunctions.getInstance().getProfileUnits());
} }
@Override @Override
@ -39,7 +40,8 @@ public class ActionStartTempTarget extends Action {
@Override @Override
public String shortDescription() { public String shortDescription() {
return MainApp.gs(R.string.starttemptarget) + ": " + (tempTarget == null ? "null" : tempTarget.toString()); tempTarget = new TempTarget().date(DateUtil.now()).duration((int) duration.getMinutes()).reason(reason).source(Source.USER).low(value.getMgdl()).high(value.getMgdl());
return MainApp.gs(R.string.starttemptarget) + ": " + (tempTarget == null ? "null" : tempTarget.friendlyDescription(value.getUnits()));
} }
@Override @Override

View file

@ -16,9 +16,10 @@ import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.OnClick; import butterknife.OnClick;
import butterknife.Unbinder; import butterknife.Unbinder;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.general.automation.actions.Action; import info.nightscout.androidaps.plugins.general.automation.actions.Action;
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector; import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui;
public class EditActionDialog extends DialogFragment { public class EditActionDialog extends DialogFragment {
private static Action resultAction; private static Action resultAction;
@ -80,6 +81,7 @@ public class EditActionDialog extends DialogFragment {
public void onButtonOk(View view) { public void onButtonOk(View view) {
resultAction.apply(mAction); resultAction.apply(mAction);
dismiss(); dismiss();
MainApp.bus().post(new EventAutomationUpdateGui());
} }
@OnClick(R.id.cancel) @OnClick(R.id.cancel)

View file

@ -12,6 +12,8 @@ import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.squareup.otto.Subscribe;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.OnClick; import butterknife.OnClick;
@ -22,6 +24,7 @@ import info.nightscout.androidaps.plugins.general.automation.AutomationEvent;
import info.nightscout.androidaps.plugins.general.automation.AutomationFragment; import info.nightscout.androidaps.plugins.general.automation.AutomationFragment;
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin; import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin;
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationDataChanged; import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationDataChanged;
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui;
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector; import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
public class EditEventDialog extends DialogFragment { public class EditEventDialog extends DialogFragment {
@ -118,16 +121,23 @@ public class EditEventDialog extends DialogFragment {
dialog.show(getFragmentManager(), "ChooseActionDialog"); dialog.show(getFragmentManager(), "ChooseActionDialog");
}); });
MainApp.bus().register(this);
return view; return view;
} }
@Override @Override
public void onDestroyView() { public void onDestroyView() {
MainApp.bus().unregister(this);
mUnbinder.unbind(); mUnbinder.unbind();
super.onDestroyView(); super.onDestroyView();
} }
@Subscribe
public void onEventAutomationUpdateGui(EventAutomationUpdateGui ignored) {
mActionListAdapter.notifyDataSetChanged();
}
@OnClick(R.id.ok) @OnClick(R.id.ok)
public void onButtonOk(View view) { public void onButtonOk(View view) {
// check for title // check for title

View file

@ -32,7 +32,7 @@ public class Label extends Element {
textViewPre.setText(textPre); textViewPre.setText(textPre);
textViewPre.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, textViewPre.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT)); ViewGroup.LayoutParams.WRAP_CONTENT));
textViewPre.setWidth(MainApp.dpToPx(120)); //textViewPre.setWidth(MainApp.dpToPx(120));
textViewPre.setPadding(px, px, px, px); textViewPre.setPadding(px, px, px, px);
textViewPre.setTypeface(textViewPre.getTypeface(), Typeface.BOLD); textViewPre.setTypeface(textViewPre.getTypeface(), Typeface.BOLD);
layout.addView(textViewPre); layout.addView(textViewPre);
@ -47,7 +47,7 @@ public class Label extends Element {
textViewPost.setText(textPost); textViewPost.setText(textPost);
textViewPost.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, textViewPost.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT)); ViewGroup.LayoutParams.WRAP_CONTENT));
textViewPost.setWidth(MainApp.dpToPx(45)); //textViewPost.setWidth(MainApp.dpToPx(45));
textViewPost.setPadding(px, px, px, px); textViewPost.setPadding(px, px, px, px);
textViewPost.setTypeface(textViewPost.getTypeface(), Typeface.BOLD); textViewPost.setTypeface(textViewPost.getTypeface(), Typeface.BOLD);
layout.addView(textViewPost); layout.addView(textViewPost);

View file

@ -1,7 +1,7 @@
package info.nightscout.androidaps.plugins.general.automation.triggers; package info.nightscout.androidaps.plugins.general.automation.triggers;
import android.support.v4.app.FragmentManager;
import android.content.Context; import android.content.Context;
import android.support.v4.app.FragmentManager;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.view.Gravity; import android.view.Gravity;
@ -17,27 +17,41 @@ import com.google.common.base.Optional;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.JsonHelper; import info.nightscout.androidaps.utils.JsonHelper;
import info.nightscout.androidaps.utils.NumberPicker; import info.nightscout.androidaps.utils.NumberPicker;
import info.nightscout.androidaps.utils.T;
public class TriggerBg extends Trigger { public class TriggerBg extends Trigger {
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
private double threshold = 100.0; // FIXME private double threshold;
private Comparator comparator = Comparator.IS_EQUAL; private Comparator comparator = Comparator.IS_EQUAL;
private String units = ProfileFunctions.getInstance().getProfileUnits(); private String units = ProfileFunctions.getInstance().getProfileUnits();
private long lastRun;
final private TextWatcher textWatcher = new TextWatcher() { final private TextWatcher textWatcher = new TextWatcher() {
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
// TODO: validate inputs if (units.equals(Constants.MMOL)) {
threshold = Math.max(threshold, 4d);
threshold = Math.min(threshold, 15d);
} else {
threshold = Math.max(threshold, 72d);
threshold = Math.min(threshold, 270d);
}
} }
@Override @Override
@ -51,11 +65,13 @@ public class TriggerBg extends Trigger {
public TriggerBg() { public TriggerBg() {
super(); super();
threshold = units.equals(Constants.MGDL) ? 100d : 5.5d;
} }
private TriggerBg(TriggerBg triggerBg) { private TriggerBg(TriggerBg triggerBg) {
super(); super();
comparator = triggerBg.comparator; comparator = triggerBg.comparator;
lastRun = triggerBg.lastRun;
units = triggerBg.units; units = triggerBg.units;
threshold = triggerBg.threshold; threshold = triggerBg.threshold;
} }
@ -77,7 +93,11 @@ public class TriggerBg extends Trigger {
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
if (glucoseStatus == null && comparator.equals(Comparator.IS_NOT_AVAILABLE)) if (glucoseStatus == null && comparator.equals(Comparator.IS_NOT_AVAILABLE))
if (lastRun < DateUtil.now() - T.mins(5).msecs()) {
if (L.isEnabled(L.AUTOMATION))
log.debug("Ready for execution: " + friendlyDescription());
return true; return true;
}
if (glucoseStatus == null) if (glucoseStatus == null)
return false; return false;
@ -91,6 +111,7 @@ public class TriggerBg extends Trigger {
o.put("type", TriggerBg.class.getName()); o.put("type", TriggerBg.class.getName());
JSONObject data = new JSONObject(); JSONObject data = new JSONObject();
data.put("threshold", threshold); data.put("threshold", threshold);
data.put("lastRun", lastRun);
data.put("comparator", comparator.toString()); data.put("comparator", comparator.toString());
data.put("units", units); data.put("units", units);
o.put("data", data); o.put("data", data);
@ -105,6 +126,7 @@ public class TriggerBg extends Trigger {
try { try {
JSONObject d = new JSONObject(data); JSONObject d = new JSONObject(data);
threshold = JsonHelper.safeGetDouble(d, "threshold"); threshold = JsonHelper.safeGetDouble(d, "threshold");
lastRun = JsonHelper.safeGetLong(d, "lastRun");
comparator = Comparator.valueOf(JsonHelper.safeGetString(d, "comparator")); comparator = Comparator.valueOf(JsonHelper.safeGetString(d, "comparator"));
units = JsonHelper.safeGetString(d, "units"); units = JsonHelper.safeGetString(d, "units");
} catch (JSONException e) { } catch (JSONException e) {
@ -122,8 +144,9 @@ public class TriggerBg extends Trigger {
public String friendlyDescription() { public String friendlyDescription() {
if (comparator.equals(Comparator.IS_NOT_AVAILABLE)) if (comparator.equals(Comparator.IS_NOT_AVAILABLE))
return MainApp.gs(R.string.glucoseisnotavailable); return MainApp.gs(R.string.glucoseisnotavailable);
else else {
return MainApp.gs(R.string.glucosecompared, MainApp.gs(comparator.getStringRes()), threshold, units); return MainApp.gs(units.equals(Constants.MGDL) ? R.string.glucosecomparedmgdl : R.string.glucosecomparedmmol, MainApp.gs(comparator.getStringRes()), threshold, units);
}
} }
@Override @Override
@ -145,6 +168,11 @@ public class TriggerBg extends Trigger {
return this; return this;
} }
TriggerBg lastRun(long lastRun) {
this.lastRun = lastRun;
return this;
}
TriggerBg comparator(Comparator comparator) { TriggerBg comparator(Comparator comparator) {
this.comparator = comparator; this.comparator = comparator;
return this; return this;
@ -177,7 +205,8 @@ public class TriggerBg extends Trigger {
} }
@Override @Override
public void onNothingSelected(AdapterView<?> parent) { } public void onNothingSelected(AdapterView<?> parent) {
}
}); });
spinner.setSelection(comparator.ordinal()); spinner.setSelection(comparator.ordinal());
root.addView(spinner); root.addView(spinner);
@ -190,7 +219,11 @@ public class TriggerBg extends Trigger {
// input field for threshold // input field for threshold
NumberPicker numberPicker = new NumberPicker(context, null); NumberPicker numberPicker = new NumberPicker(context, null);
numberPicker.setParams(0d, 0d, (double) 500, 1d, new DecimalFormat("0"), false, textWatcher); double min = units.equals(Constants.MGDL) ? 3 * Constants.MMOLL_TO_MGDL : 3;
double max = units.equals(Constants.MGDL) ? 20 * Constants.MMOLL_TO_MGDL : 20;
double step = units.equals(Constants.MGDL) ? 1 : 0.1d;
DecimalFormat pattern = units.equals(Constants.MGDL) ? new DecimalFormat("0") : new DecimalFormat("0.0");
numberPicker.setParams(0d, min, max, step, pattern, false, textWatcher);
numberPicker.setValue(threshold); numberPicker.setValue(threshold);
numberPicker.setOnValueChangedListener(value -> threshold = value); numberPicker.setOnValueChangedListener(value -> threshold = value);
layout.addView(numberPicker); layout.addView(numberPicker);

View file

@ -1,8 +1,8 @@
package info.nightscout.androidaps.plugins.general.automation.triggers; package info.nightscout.androidaps.plugins.general.automation.triggers;
import android.support.v4.app.FragmentManager;
import android.content.Context; import android.content.Context;
import android.support.annotation.StringRes; import android.support.annotation.StringRes;
import android.support.v4.app.FragmentManager;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.LinearLayout; import android.widget.LinearLayout;
@ -12,6 +12,8 @@ import com.google.common.base.Optional;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
@ -19,10 +21,13 @@ import java.util.List;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.general.automation.AutomationFragment; import info.nightscout.androidaps.plugins.general.automation.AutomationFragment;
import info.nightscout.androidaps.utils.JsonHelper; import info.nightscout.androidaps.utils.JsonHelper;
public class TriggerConnector extends Trigger { public class TriggerConnector extends Trigger {
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
public enum Type { public enum Type {
AND, AND,
OR, OR,
@ -40,7 +45,8 @@ public class TriggerConnector extends Trigger {
return false; return false;
} }
public @StringRes int getStringRes() { public @StringRes
int getStringRes() {
switch (this) { switch (this) {
case OR: case OR:
return R.string.or; return R.string.or;
@ -86,9 +92,13 @@ public class TriggerConnector extends Trigger {
this.connectorType = connectorType; this.connectorType = connectorType;
} }
public void changeConnectorType(Type type) { this.connectorType = type; } public void changeConnectorType(Type type) {
this.connectorType = type;
}
public Type getConnectorType() { return connectorType; } public Type getConnectorType() {
return connectorType;
}
public synchronized void add(Trigger t) { public synchronized void add(Trigger t) {
list.add(t); list.add(t);
@ -131,6 +141,9 @@ public class TriggerConnector extends Trigger {
for (int i = 1; i < list.size(); ++i) { for (int i = 1; i < list.size(); ++i) {
result = connectorType.apply(result, list.get(i).shouldRun()); result = connectorType.apply(result, list.get(i).shouldRun());
} }
if (result)
if (L.isEnabled(L.AUTOMATION))
log.debug("Ready for execution: " + friendlyDescription().replace("\n", " "));
return result; return result;
} }
@ -181,7 +194,7 @@ public class TriggerConnector extends Trigger {
int counter = 0; int counter = 0;
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
for (Trigger t : list) { for (Trigger t : list) {
if (counter++ > 0) result.append(" " + MainApp.gs(friendlyName()) + " "); if (counter++ > 0) result.append("\n" + MainApp.gs(friendlyName()) + "\n");
result.append(t.friendlyDescription()); result.append(t.friendlyDescription());
} }
return result.toString(); return result.toString();

View file

@ -16,18 +16,23 @@ import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.JsonHelper; import info.nightscout.androidaps.utils.JsonHelper;
import info.nightscout.androidaps.utils.T; import info.nightscout.androidaps.utils.T;
public class TriggerRecurringTime extends Trigger { public class TriggerRecurringTime extends Trigger {
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
public enum DayOfWeek { public enum DayOfWeek {
MONDAY, MONDAY,
@ -152,10 +157,13 @@ public class TriggerRecurringTime extends Trigger {
if (isSet(DayOfWeek.fromCalendarInt(scheduledDayOfWeek))) { if (isSet(DayOfWeek.fromCalendarInt(scheduledDayOfWeek))) {
if (DateUtil.now() >= scheduled && DateUtil.now() - scheduled < T.mins(5).msecs()) { if (DateUtil.now() >= scheduled && DateUtil.now() - scheduled < T.mins(5).msecs()) {
if (lastRun < scheduled) if (lastRun < scheduled) {
if (L.isEnabled(L.AUTOMATION))
log.debug("Ready for execution: " + friendlyDescription());
return true; return true;
} }
} }
}
return false; return false;
} }
@ -205,7 +213,29 @@ public class TriggerRecurringTime extends Trigger {
@Override @Override
public String friendlyDescription() { public String friendlyDescription() {
// TODO // TODO
return "Every "; int counter = 0;
StringBuilder sb = new StringBuilder();
sb.append(MainApp.gs(R.string.every));
sb.append(" ");
for (Integer i : getSelectedDays()) {
if (counter > 0)
sb.append(",");
sb.append(MainApp.gs(DayOfWeek.fromCalendarInt(i).getShortName()));
counter++;
}
sb.append(" ");
Calendar scheduledCal = DateUtil.gregorianCalendar();
scheduledCal.set(Calendar.HOUR_OF_DAY, hour);
scheduledCal.set(Calendar.MINUTE, minute);
scheduledCal.set(Calendar.SECOND, 0);
long scheduled = scheduledCal.getTimeInMillis();
sb.append(DateUtil.timeString(scheduled));
if (counter == 0)
return MainApp.gs(R.string.never);
return sb.toString();
} }
@Override @Override

View file

@ -14,22 +14,27 @@ import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.JsonHelper; import info.nightscout.androidaps.utils.JsonHelper;
import info.nightscout.androidaps.utils.T; import info.nightscout.androidaps.utils.T;
public class TriggerTime extends Trigger { public class TriggerTime extends Trigger {
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
private long runAt; private long runAt;
private long lastRun; private long lastRun;
public TriggerTime() { public TriggerTime() {
runAt = DateUtil.now();
} }
private TriggerTime(TriggerTime triggerTime) { private TriggerTime(TriggerTime triggerTime) {
@ -42,7 +47,11 @@ public class TriggerTime extends Trigger {
public boolean shouldRun() { public boolean shouldRun() {
long now = DateUtil.now(); long now = DateUtil.now();
if (now >= runAt && now - runAt < T.mins(5).msecs()) if (now >= runAt && now - runAt < T.mins(5).msecs())
if (lastRun < runAt) {
if (L.isEnabled(L.AUTOMATION))
log.debug("Ready for execution: " + friendlyDescription());
return true; return true;
}
return false; return false;
} }
@ -99,6 +108,11 @@ public class TriggerTime extends Trigger {
return this; return this;
} }
TriggerTime lastRun(long lastRun) {
this.lastRun = lastRun;
return this;
}
@Override @Override
public Trigger duplicate() { public Trigger duplicate() {
return new TriggerTime(this); return new TriggerTime(this);

View file

@ -1339,7 +1339,8 @@
<string name="isnotavailable">is not available</string> <string name="isnotavailable">is not available</string>
<string name="unknown">unknown</string> <string name="unknown">unknown</string>
<string name="glucoseisnotavailable">Glucose is not available</string> <string name="glucoseisnotavailable">Glucose is not available</string>
<string name="glucosecompared">Glucose %1$s %2$.2f %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="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>
@ -1373,6 +1374,9 @@
<string name="notconfigured">Not configured</string> <string name="notconfigured">Not configured</string>
<string name="profileswitchcreated">Profile switch created</string> <string name="profileswitchcreated">Profile switch created</string>
<string name="recurringTime">Recurring time</string> <string name="recurringTime">Recurring time</string>
<string name="every">Every</string>
<string name="never">Never</string>
<string name="mins">%1$dmins</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>

View file

@ -14,25 +14,20 @@ import info.AAPSMocker;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.general.automation.elements.InputBg; import info.nightscout.androidaps.plugins.general.automation.elements.InputBg;
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration; import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
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.Callback;
import info.nightscout.androidaps.utils.SP; import info.nightscout.androidaps.utils.SP;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyDouble;
import static org.mockito.ArgumentMatchers.anyInt;
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({MainApp.class, SP.class, TreatmentsPlugin.class}) @PrepareForTest({MainApp.class, SP.class, TreatmentsPlugin.class, ProfileFunctions.class})
public class ActionStartTempTargetTest { public class ActionStartTempTargetTest {
ActionStartTempTarget actionStartTempTarget = new ActionStartTempTarget(); ActionStartTempTarget actionStartTempTarget;
TreatmentsPlugin treatmentsPlugin; TreatmentsPlugin treatmentsPlugin;
TempTarget tempTargetAdded; TempTarget tempTargetAdded;
@ -43,7 +38,7 @@ public class ActionStartTempTargetTest {
@Test @Test
public void shortDescriptionTest() { public void shortDescriptionTest() {
Assert.assertEquals("Start temp target: null", actionStartTempTarget.shortDescription()); Assert.assertEquals("Start temp target: 100mg/dl@null", actionStartTempTarget.shortDescription());
} }
@Test @Test
@ -86,16 +81,21 @@ public class ActionStartTempTargetTest {
Assert.assertEquals(30, actionStartTempTarget.duration.getMinutes(), 0.001); Assert.assertEquals(30, actionStartTempTarget.duration.getMinutes(), 0.001);
Assert.assertEquals("Test", actionStartTempTarget.reason); Assert.assertEquals("Test", actionStartTempTarget.reason);
} }
@Before @Before
public void prepareTest() { public void prepareTest() {
AAPSMocker.mockMainApp(); AAPSMocker.mockMainApp();
AAPSMocker.mockSP(); AAPSMocker.mockSP();
AAPSMocker.mockStrings(); AAPSMocker.mockStrings();
AAPSMocker.mockBus();
AAPSMocker.mockProfileFunctions();
treatmentsPlugin = AAPSMocker.mockTreatmentPlugin(); treatmentsPlugin = AAPSMocker.mockTreatmentPlugin();
Mockito.doAnswer(invocation -> { Mockito.doAnswer(invocation -> {
tempTargetAdded = invocation.getArgument(0); tempTargetAdded = invocation.getArgument(0);
return null; return null;
}).when(treatmentsPlugin).addToHistoryTempTarget(any(TempTarget.class)); }).when(treatmentsPlugin).addToHistoryTempTarget(any(TempTarget.class));
actionStartTempTarget = new ActionStartTempTarget();
} }
} }

View file

@ -18,22 +18,20 @@ import java.util.List;
import info.AAPSMocker; import info.AAPSMocker;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv; import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.T;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.powermock.api.mockito.PowerMockito.when; import static org.powermock.api.mockito.PowerMockito.when;
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({MainApp.class, Bus.class, ProfileFunctions.class, DateUtil.class, IobCobCalculatorPlugin.class}) @PrepareForTest({MainApp.class, Bus.class, ProfileFunctions.class, DateUtil.class, IobCobCalculatorPlugin.class})
public class TriggerBgTest { public class TriggerBgTest {
long now = 1514766900000L;
@Test @Test
public void shouldRunTest() { public void shouldRunTest() {
when(IobCobCalculatorPlugin.getPlugin().getBgReadings()).thenReturn(generateOneCurrentRecordBgData()); when(IobCobCalculatorPlugin.getPlugin().getBgReadings()).thenReturn(generateOneCurrentRecordBgData());
@ -62,9 +60,13 @@ public class TriggerBgTest {
Assert.assertFalse(t.shouldRun()); Assert.assertFalse(t.shouldRun());
t = new TriggerBg().comparator(Trigger.Comparator.IS_NOT_AVAILABLE); t = new TriggerBg().comparator(Trigger.Comparator.IS_NOT_AVAILABLE);
Assert.assertTrue(t.shouldRun()); Assert.assertTrue(t.shouldRun());
t = new TriggerBg().units(Constants.MGDL).threshold(214).comparator(Trigger.Comparator.IS_EQUAL).lastRun(now - 1);
Assert.assertFalse(t.shouldRun());
} }
String bgJson = "{\"data\":{\"comparator\":\"IS_EQUAL\",\"threshold\":4.1,\"units\":\"mmol\"},\"type\":\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerBg\"}"; String bgJson = "{\"data\":{\"comparator\":\"IS_EQUAL\",\"lastRun\":0,\"threshold\":4.1,\"units\":\"mmol\"},\"type\":\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerBg\"}";
@Test @Test
public void toJSONTest() { public void toJSONTest() {
@ -90,14 +92,14 @@ public class TriggerBgTest {
AAPSMocker.mockProfileFunctions(); AAPSMocker.mockProfileFunctions();
PowerMockito.mockStatic(DateUtil.class); PowerMockito.mockStatic(DateUtil.class);
when(DateUtil.now()).thenReturn(1514766900000L + T.mins(1).msecs()); when(DateUtil.now()).thenReturn(now);
} }
List<BgReading> generateOneCurrentRecordBgData() { List<BgReading> generateOneCurrentRecordBgData() {
List<BgReading> list = new ArrayList<>(); List<BgReading> list = new ArrayList<>();
try { try {
list.add(new BgReading(new NSSgv(new JSONObject("{\"mgdl\":214,\"mills\":1514766900000,\"direction\":\"Flat\"}")))); list.add(new BgReading(new NSSgv(new JSONObject("{\"mgdl\":214,\"mills\":" + (now - 1) + ",\"direction\":\"Flat\"}"))));
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
} }

View file

@ -3,13 +3,19 @@ package info.nightscout.androidaps.plugins.general.automation.triggers;
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.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.modules.junit4.PowerMockRunner;
import info.AAPSMocker;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.utils.SP;
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({}) @PrepareForTest({MainApp.class, L.class, SP.class})
public class TriggerConnectorTest { public class TriggerConnectorTest {
@Test @Test
@ -86,6 +92,7 @@ public class TriggerConnectorTest {
t.add(new TriggerConnector()); t.add(new TriggerConnector());
Assert.assertEquals(oneItem, t.toJSON()); Assert.assertEquals(oneItem, t.toJSON());
} }
@Test @Test
public void fromJSONTest() throws JSONException { public void fromJSONTest() throws JSONException {
TriggerConnector t = new TriggerConnector(); TriggerConnector t = new TriggerConnector();
@ -95,4 +102,11 @@ public class TriggerConnectorTest {
Assert.assertEquals(1, t2.size()); Assert.assertEquals(1, t2.size());
Assert.assertTrue(t2.get(0) instanceof TriggerConnector); Assert.assertTrue(t2.get(0) instanceof TriggerConnector);
} }
@Before
public void prepareMock() {
AAPSMocker.mockMainApp();
AAPSMocker.mockSP();
AAPSMocker.mockL();
}
} }

View file

@ -38,6 +38,10 @@ public class TriggerTimeTest {
t = new TriggerTime().runAt(now + T.mins(1).msecs()); t = new TriggerTime().runAt(now + T.mins(1).msecs());
Assert.assertFalse(t.shouldRun()); Assert.assertFalse(t.shouldRun());
// already run
t = new TriggerTime().runAt(now - T.mins(1).msecs()).lastRun(now - 1);
Assert.assertFalse(t.shouldRun());
} }
String timeJson = "{\"data\":{\"runAt\":1514766840000,\"lastRun\":0},\"type\":\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerTime\"}"; String timeJson = "{\"data\":{\"runAt\":1514766840000,\"lastRun\":0},\"type\":\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerTime\"}";