AutomationPlugin:processActions and some tweaking

This commit is contained in:
Milos Kozak 2019-03-31 21:54:31 +02:00
parent 350e23647e
commit 5a555cdfba
19 changed files with 255 additions and 29 deletions

View file

@ -20,6 +20,8 @@ import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;
import com.squareup.otto.Subscribe;
import java.util.HashSet;
import java.util.List;
@ -33,6 +35,7 @@ import info.nightscout.androidaps.plugins.general.automation.actions.Action;
import info.nightscout.androidaps.plugins.general.automation.dialogs.ChooseTriggerDialog;
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditActionDialog;
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog;
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui;
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger;
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
@ -40,6 +43,8 @@ public class AutomationFragment extends SubscriberFragment {
@BindView(R.id.eventListView)
RecyclerView mEventListView;
@BindView(R.id.logView)
TextView mLogView;
private EventListAdapter mEventListAdapter;
@ -62,11 +67,24 @@ public class AutomationFragment extends SubscriberFragment {
return view;
}
@Subscribe
public void onEvent(EventAutomationUpdateGui unused) {
updateGUI();
}
@Override
public void updateGUI() {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(() -> mEventListAdapter.notifyDataSetChanged());
activity.runOnUiThread(() -> {
mEventListAdapter.notifyDataSetChanged();
StringBuilder sb = new StringBuilder();
for (String l : AutomationPlugin.getPlugin().executionLog) {
sb.append(l);
sb.append("\n");
}
mLogView.setText(sb.toString());
});
}
@OnClick(R.id.fabAddEvent)
@ -317,7 +335,8 @@ public class AutomationFragment extends SubscriberFragment {
}
@Override
public void onNothingSelected(AdapterView<?> parent) { }
public void onNothingSelected(AdapterView<?> parent) {
}
});
mRootLayout.addView(spinner);
}

View file

@ -2,10 +2,16 @@ package info.nightscout.androidaps.plugins.general.automation;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.os.Handler;
import com.squareup.otto.Subscribe;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@ -18,11 +24,21 @@ import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.general.automation.actions.Action;
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationDataChanged;
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.services.LocationService;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.T;
public class AutomationPlugin extends PluginBase {
private static Logger log = LoggerFactory.getLogger(L.CORE);
private final String key_AUTOMATION_EVENTS = "AUTOMATION_EVENTS";
static AutomationPlugin plugin = null;
public static AutomationPlugin getPlugin() {
@ -35,6 +51,16 @@ public class AutomationPlugin extends PluginBase {
private EventLocationChange eventLocationChange;
private EventChargingState eventChargingState;
private EventNetworkChange eventNetworkChange;
List<String> executionLog = new ArrayList<>();
private Handler loopHandler = new Handler();
private Runnable refreshLoop = new Runnable() {
@Override
public void run() {
processActions();
loopHandler.postDelayed(refreshLoop, T.mins(1).msecs());
}
};
private AutomationPlugin() {
super(new PluginDescription()
@ -54,10 +80,13 @@ public class AutomationPlugin extends PluginBase {
MainApp.bus().register(this);
super.onStart();
loadFromSP();
loopHandler.postDelayed(refreshLoop, T.mins(1).msecs());
}
@Override
protected void onStop() {
loopHandler.removeCallbacks(refreshLoop);
Context context = MainApp.instance().getApplicationContext();
context.stopService(new Intent(context, LocationService.class));
@ -80,6 +109,36 @@ public class AutomationPlugin extends PluginBase {
return eventNetworkChange;
}
private void storeToSP() {
JSONArray array = new JSONArray();
try {
for (AutomationEvent event : getAutomationEvents()) {
array.put(new JSONObject(event.toJSON()));
}
} catch (JSONException e) {
e.printStackTrace();
}
SP.putString(key_AUTOMATION_EVENTS, array.toString());
}
private void loadFromSP() {
automationEvents.clear();
String data = SP.getString(key_AUTOMATION_EVENTS, "");
if (!data.equals("")) {
try {
JSONArray array = new JSONArray(data);
for (int i = 0; i < array.length(); i++) {
JSONObject o = array.getJSONObject(i);
AutomationEvent event = new AutomationEvent().fromJSON(o.toString());
automationEvents.add(event);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
@Subscribe
public void onEventPreferenceChange(EventPreferenceChange e) {
if (e.isChanged(R.string.key_location)) {
@ -89,6 +148,11 @@ public class AutomationPlugin extends PluginBase {
}
}
@Subscribe
public void onEvent(EventAutomationDataChanged e) {
storeToSP();
}
@Subscribe
public void onEventLocationChange(EventLocationChange e) {
eventLocationChange = e;
@ -112,9 +176,33 @@ public class AutomationPlugin extends PluginBase {
processActions();
}
// TODO keepalive
void processActions() {
synchronized void processActions() {
log.debug("processActions");
for (AutomationEvent event : getAutomationEvents()) {
if (event.getTrigger().shouldRun()) {
List<Action> actions = event.getActions();
for (Action action : actions) {
action.doAction(new Callback() {
@Override
public void run() {
StringBuilder sb = new StringBuilder();
sb.append(DateUtil.timeString(DateUtil.now()));
sb.append(" ");
sb.append(result.success ? "" : "X");
sb.append(" ");
sb.append(event.getTitle());
sb.append(": ");
sb.append(action.shortDescription());
sb.append(": ");
sb.append(result.comment);
executionLog.add(sb.toString());
log.debug(sb.toString());
MainApp.bus().post(new EventAutomationUpdateGui());
}
});
}
}
}
}
}

View file

@ -9,11 +9,43 @@ import org.json.JSONObject;
import info.nightscout.androidaps.queue.Callback;
/*
Action ideas:
* cancel temp target
* change preference setting
* enable/disable plugin
* create notification
* create ugly alarm
* create profile switch
* set/cancel tbr
* set/cancel extended bolus
* run bolus wizard
Trigger ideas:
* location (close to)
* connected to specific wifi
* internet available/not available
* nsclient connected/disconnected
* iob
* cob
* autosens value
* delta, short delta, long delta
* last bolus ago
* is tbr running
* bolus wizard result
* loop is enabled, disabled, suspended, running
*/
public abstract class Action {
public abstract int friendlyName();
public abstract String shortDescription();
abstract void doAction(Callback callback);
public abstract void doAction(Callback callback);
public void generateDialog(LinearLayout root) { }

View file

@ -18,7 +18,12 @@ public class ActionLoopDisable extends Action {
}
@Override
void doAction(Callback callback) {
public String shortDescription() {
return MainApp.gs(R.string.disableloop);
}
@Override
public void doAction(Callback callback) {
if (LoopPlugin.getPlugin().isEnabled(PluginType.LOOP)) {
LoopPlugin.getPlugin().setPluginEnabled(PluginType.LOOP, false);
ConfigBuilderPlugin.getPlugin().storeSettings("ActionLoopDisable");

View file

@ -18,7 +18,12 @@ public class ActionLoopEnable extends Action {
}
@Override
void doAction(Callback callback) {
public String shortDescription() {
return MainApp.gs(R.string.enableloop);
}
@Override
public void doAction(Callback callback) {
if (!LoopPlugin.getPlugin().isEnabled(PluginType.LOOP)) {
LoopPlugin.getPlugin().setPluginEnabled(PluginType.LOOP, true);
ConfigBuilderPlugin.getPlugin().storeSettings("ActionLoopEnable");

View file

@ -18,7 +18,12 @@ public class ActionLoopResume extends Action {
}
@Override
void doAction(Callback callback) {
public String shortDescription() {
return MainApp.gs(R.string.resumeloop);
}
@Override
public void doAction(Callback callback) {
if (LoopPlugin.getPlugin().isSuspended()) {
LoopPlugin.getPlugin().suspendTo(0);
ConfigBuilderPlugin.getPlugin().storeSettings("ActionLoopResume");

View file

@ -21,7 +21,12 @@ public class ActionLoopSuspend extends Action {
}
@Override
void doAction(Callback callback) {
public String shortDescription() {
return MainApp.gs(R.string.suspendloop);
}
@Override
public void doAction(Callback callback) {
if (!LoopPlugin.getPlugin().isSuspended()) {
LoopPlugin.getPlugin().suspendLoop(minutes);
MainApp.bus().post(new EventRefreshOverview("ActionLoopSuspend"));

View file

@ -26,6 +26,7 @@ public class ActionStartTempTarget extends Action {
String reason = "";
InputBg value;
InputDuration duration = new InputDuration(0, InputDuration.TimeUnit.MINUTES);
TempTarget tempTarget;
public ActionStartTempTarget() {
value = new InputBg(Constants.MGDL);
@ -41,8 +42,13 @@ public class ActionStartTempTarget extends Action {
}
@Override
void doAction(Callback callback) {
TempTarget tempTarget = new TempTarget().date(DateUtil.now()).duration((int)duration.getMinutes()).reason(reason).source(Source.USER).low(value.getMgdl()).high(value.getMgdl());
public String shortDescription() {
return MainApp.gs(R.string.resumeloop) + ": " + tempTarget.toString();
}
@Override
public void doAction(Callback callback) {
tempTarget = new TempTarget().date(DateUtil.now()).duration((int)duration.getMinutes()).reason(reason).source(Source.USER).low(value.getMgdl()).high(value.getMgdl());
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
if (callback != null)
callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();

View file

@ -16,10 +16,12 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.general.automation.AutomationEvent;
import info.nightscout.androidaps.plugins.general.automation.AutomationFragment;
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin;
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationDataChanged;
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
public class EditEventDialog extends DialogFragment {
@ -82,6 +84,7 @@ public class EditEventDialog extends DialogFragment {
mAddNew = savedInstanceState.getBoolean("addNew");
} else if (mAddNew) {
mEvent.setTrigger(new TriggerConnector(TriggerConnector.Type.OR));
}
// event title
@ -159,6 +162,7 @@ public class EditEventDialog extends DialogFragment {
if (mClickListener != null) mClickListener.onClick(mEvent);
dismiss();
MainApp.bus().post(new EventAutomationDataChanged());
}
@OnClick(R.id.cancel)

View file

@ -0,0 +1,6 @@
package info.nightscout.androidaps.plugins.general.automation.events;
import info.nightscout.androidaps.events.Event;
public class EventAutomationDataChanged extends Event {
}

View file

@ -0,0 +1,6 @@
package info.nightscout.androidaps.plugins.general.automation.events;
import info.nightscout.androidaps.events.Event;
public class EventAutomationUpdateGui extends Event {
}

View file

@ -106,11 +106,19 @@ public class DateUtil {
}
public static String timeString(Date date) {
return new DateTime(date).toString(DateTimeFormat.shortTime());
String format = "hh:mma";
if (android.text.format.DateFormat.is24HourFormat(MainApp.instance())) {
format = "HH:mm";
}
return new DateTime(date).toString(DateTimeFormat.forPattern(format));
}
public static String timeString(long mills) {
return new DateTime(mills).toString(DateTimeFormat.shortTime());
String format = "hh:mma";
if (android.text.format.DateFormat.is24HourFormat(MainApp.instance())) {
format = "HH:mm";
}
return new DateTime(mills).toString(DateTimeFormat.forPattern(format));
}
public static String timeFullString(long mills) {

View file

@ -28,6 +28,13 @@
android:src="@drawable/ic_add_black_24dp"
android:backgroundTint="@color/defaulttext"/>
<TextView
android:id="@+id/logView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="Log" />
</RelativeLayout>
</FrameLayout>

View file

@ -33,6 +33,11 @@ public class ActionLoopDisableTest {
Assert.assertEquals(R.string.disableloop, actionLoopDisable.friendlyName());
}
@Test
public void shortDescriptionTest() {
Assert.assertEquals(R.string.disableloop, actionLoopDisable.friendlyName());
}
@Test
public void iconTest() {
Assert.assertEquals(Optional.of(R.drawable.ic_stop_24dp), actionLoopDisable.icon());

View file

@ -33,6 +33,11 @@ public class ActionLoopEnableTest {
Assert.assertEquals(R.string.enableloop, actionLoopEnable.friendlyName());
}
@Test
public void shortDescriptionTest() {
Assert.assertEquals(R.string.enableloop, actionLoopEnable.friendlyName());
}
@Test
public void iconTest() {
Assert.assertEquals(Optional.of(R.drawable.ic_play_circle_outline_24dp), actionLoopEnable.icon());

View file

@ -30,6 +30,11 @@ public class ActionLoopResumeTest {
Assert.assertEquals(R.string.resumeloop, actionLoopResume.friendlyName());
}
@Test
public void shortDescriptionTest() {
Assert.assertEquals(R.string.resumeloop, actionLoopResume.friendlyName());
}
@Test
public void iconTest() {
Assert.assertEquals(Optional.of(R.drawable.ic_replay_24dp), actionLoopResume.icon());

View file

@ -34,6 +34,11 @@ public class ActionLoopSuspendTest {
Assert.assertEquals(R.string.suspendloop, actionLoopSuspend.friendlyName());
}
@Test
public void shortDescriptionTest() {
Assert.assertEquals(R.string.suspendloop, actionLoopSuspend.friendlyName());
}
@Test
public void iconTest() {
Assert.assertEquals(Optional.of(R.drawable.ic_pause_circle_outline_24dp), actionLoopSuspend.icon());

View file

@ -41,6 +41,11 @@ public class ActionStartTempTargetTest {
Assert.assertEquals(R.string.starttemptarget, actionStartTempTarget.friendlyName());
}
@Test
public void shortDescriptionTest() {
Assert.assertEquals(R.string.starttemptarget, actionStartTempTarget.friendlyName());
}
@Test
public void iconTest() {
Assert.assertEquals(Optional.of(R.drawable.icon_cp_cgm_target), actionStartTempTarget.icon());

View file

@ -22,7 +22,12 @@ public class ActionTest extends Action {
}
@Override
void doAction(Callback callback) {
public String shortDescription() {
return null;
}
@Override
public void doAction(Callback callback) {
}
@Override