diff --git a/app/build.gradle b/app/build.gradle index 0294d49f9c..23d04f770c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -149,6 +149,7 @@ dependencies { compile('com.github.tony19:logback-android-classic:1.1.1-6') { exclude group: 'com.google.android', module: 'android' } + compile 'org.apache.commons:commons-lang3:3.6' compile 'org.slf4j:slf4j-api:1.7.12' compile 'com.jjoe64:graphview:4.0.1' compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.1.1' diff --git a/app/src/main/java/com/squareup/otto/LoggingBus.java b/app/src/main/java/com/squareup/otto/LoggingBus.java new file mode 100644 index 0000000000..3417e7dd41 --- /dev/null +++ b/app/src/main/java/com/squareup/otto/LoggingBus.java @@ -0,0 +1,87 @@ +package com.squareup.otto; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import info.nightscout.androidaps.events.Event; + +/** Logs events has they're being posted to and dispatched from the event bus. + * + * A summary of event-receiver calls that occurred so far is logged + * after 10s (after startup) and then again every 60s. + * */ +public class LoggingBus extends Bus { + private static Logger log = LoggerFactory.getLogger(LoggingBus.class); + + private static long everyMinute = System.currentTimeMillis() + 10 * 1000; + private Map> event2Receiver = new HashMap<>(); + + public LoggingBus(ThreadEnforcer enforcer) { + super(enforcer); + } + + @Override + public void post(Object event) { + if (event instanceof DeadEvent) { + log.debug("Event has no receiver: " + ((DeadEvent) event).event + ", source: " + ((DeadEvent) event).source); + return; + } + + if (!(event instanceof Event)) { + log.error("Posted event not an event class: " + event.getClass()); + } + + log.debug("<<< " + event); + try { + StackTraceElement caller = new Throwable().getStackTrace()[1]; + String className = caller.getClassName(); + className = className.substring(className.lastIndexOf(".") + 1); + log.debug(" source: " + className + "." + caller.getMethodName() + ":" + caller.getLineNumber()); + } catch (RuntimeException e) { + log.debug(" source: "); + } + + super.post(event); + } + + @Override + protected void dispatch(Object event, EventHandler wrapper) { + try { + log.debug(">>> " + event); + Field methodField = wrapper.getClass().getDeclaredField("method"); + methodField.setAccessible(true); + Method targetMethod = (Method) methodField.get(wrapper); + String className = targetMethod.getDeclaringClass().getSimpleName(); + String methodName = targetMethod.getName(); + String receiverMethod = className + "." + methodName; + log.debug(" receiver: " + receiverMethod); + + String key = event.getClass().getSimpleName(); + if (!event2Receiver.containsKey(key)) event2Receiver.put(key, new HashSet()); + event2Receiver.get(key).add(receiverMethod); + } catch (ReflectiveOperationException e) { + log.debug(" receiver: "); + } + + if (everyMinute < System.currentTimeMillis()) { + log.debug("***************** Event -> receiver pairings seen so far ****************"); + for (Map.Entry> stringSetEntry : event2Receiver.entrySet()) { + log.debug(" " + stringSetEntry.getKey()); + for (String s : stringSetEntry.getValue()) { + log.debug(" -> " + s); + } + } + log.debug("*************************************************************************"); + everyMinute = System.currentTimeMillis() + 60 * 1000; + } + + super.dispatch(event, wrapper); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/Config.java b/app/src/main/java/info/nightscout/androidaps/Config.java index 2cfc2d96ab..d900da7d43 100644 --- a/app/src/main/java/info/nightscout/androidaps/Config.java +++ b/app/src/main/java/info/nightscout/androidaps/Config.java @@ -34,6 +34,7 @@ public class Config { public static final boolean logPumpActions = true; public static final boolean logCongigBuilderActions = true; public static final boolean logAutosensData = false; + public static final boolean logEvents = false; // DanaR specific public static final boolean logDanaBTComm = true; diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index cafeec6dd6..5e36fffa62 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -13,6 +13,7 @@ import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.CustomEvent; import com.j256.ormlite.android.apptools.OpenHelperManager; import com.squareup.otto.Bus; +import com.squareup.otto.LoggingBus; import com.squareup.otto.ThreadEnforcer; import org.slf4j.Logger; @@ -31,6 +32,7 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin; +import info.nightscout.androidaps.plugins.Food.FoodPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingProlongedPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin; @@ -103,7 +105,8 @@ public class MainApp extends Application { log.info("Version: " + BuildConfig.VERSION_NAME); log.info("BuildVersion: " + BuildConfig.BUILDVERSION); - sBus = new Bus(ThreadEnforcer.ANY); + sBus = Config.logEvents ? new LoggingBus(ThreadEnforcer.ANY) : new Bus(ThreadEnforcer.ANY); + sInstance = this; sResources = getResources(); @@ -149,6 +152,7 @@ public class MainApp extends Application { if (!Config.NSCLIENT) pluginsList.add(SourceGlimpPlugin.getPlugin()); if (Config.SMSCOMMUNICATORENABLED) pluginsList.add(SmsCommunicatorPlugin.getPlugin()); + pluginsList.add(FoodPlugin.getPlugin()); pluginsList.add(WearPlugin.initPlugin(this)); pluginsList.add(StatuslinePlugin.initPlugin(this)); @@ -165,9 +169,6 @@ public class MainApp extends Application { else Answers.getInstance().logCustom(new CustomEvent("AppStart")); - - startKeepAliveService(); - Thread t = new Thread(new Runnable() { @Override public void run() { @@ -175,8 +176,9 @@ public class MainApp extends Application { PumpInterface pump = MainApp.getConfigBuilder(); if (pump != null) pump.refreshDataFromPump("Initialization"); + startKeepAliveService(); } - }); + }, "pump-initialization"); t.start(); } @@ -186,6 +188,9 @@ public class MainApp extends Application { lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_TREATMENT)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_CHANGED_TREATMENT)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_REMOVED_TREATMENT)); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_FOOD)); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_CHANGED_FOOD)); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_REMOVED_FOOD)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_SGV)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_PROFILE)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_STATUS)); @@ -206,12 +211,6 @@ public class MainApp extends Application { private void startKeepAliveService() { if (keepAliveReceiver == null) { keepAliveReceiver = new KeepAliveReceiver(); - if (Config.DANAR) { - startService(new Intent(this, DanaRExecutionService.class)); - startService(new Intent(this, DanaRKoreanExecutionService.class)); - startService(new Intent(this, DanaRv2ExecutionService.class)); - startService(new Intent(this, DanaRSService.class)); - } keepAliveReceiver.setAlarm(this); } } diff --git a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java index dc52107c26..5c152e8060 100644 --- a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java +++ b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java @@ -116,6 +116,9 @@ public class DataService extends IntentService { Intents.ACTION_REMOVED_TREATMENT.equals(action) || Intents.ACTION_NEW_STATUS.equals(action) || Intents.ACTION_NEW_DEVICESTATUS.equals(action) || + Intents.ACTION_NEW_FOOD.equals(action) || + Intents.ACTION_CHANGED_FOOD.equals(action) || + Intents.ACTION_REMOVED_FOOD.equals(action) || Intents.ACTION_NEW_CAL.equals(action) || Intents.ACTION_NEW_MBG.equals(action)) ) { @@ -413,6 +416,56 @@ public class DataService extends IntentService { log.error("Unhandled exception", e); } } + + if (intent.getAction().equals(Intents.ACTION_NEW_FOOD) || intent.getAction().equals(Intents.ACTION_CHANGED_FOOD)) { + try { + if (bundles.containsKey("food")) { + String trstring = bundles.getString("food"); + handleAddChangeFoodRecord(new JSONObject(trstring)); + } + if (bundles.containsKey("foods")) { + String trstring = bundles.getString("foods"); + JSONArray jsonArray = new JSONArray(trstring); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject trJson = jsonArray.getJSONObject(i); + handleAddChangeFoodRecord(trJson); + } + } + } catch (Exception e) { + log.error("Unhandled exception", e); + } + } + + if (intent.getAction().equals(Intents.ACTION_REMOVED_FOOD)) { + try { + if (bundles.containsKey("food")) { + String trstring = bundles.getString("food"); + JSONObject trJson = new JSONObject(trstring); + String _id = trJson.getString("_id"); + handleRemovedFoodRecord(_id); + } + + if (bundles.containsKey("foods")) { + String trstring = bundles.getString("foods"); + JSONArray jsonArray = new JSONArray(trstring); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject trJson = jsonArray.getJSONObject(i); + String _id = trJson.getString("_id"); + handleRemovedFoodRecord(_id); + } + } + } catch (Exception e) { + log.error("Unhandled exception", e); + } + } + } + + private void handleRemovedFoodRecord(String _id) { + MainApp.getDbHelper().foodHelper.deleteFoodById(_id); + } + + public void handleAddChangeFoodRecord(JSONObject trJson) throws JSONException { + MainApp.getDbHelper().foodHelper.createFoodFromJsonIfNotExists(trJson); } private void handleRemovedRecordFromNS(String _id) { diff --git a/app/src/main/java/info/nightscout/androidaps/db/FoodHelper.java b/app/src/main/java/info/nightscout/androidaps/db/FoodHelper.java index fd5406f974..992e328532 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/FoodHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/FoodHelper.java @@ -87,6 +87,8 @@ public class FoodHelper { log.debug("FOOD: Updating record by _id: " + old.toString()); scheduleFoodChange(); return true; + } else { + return false; } } } diff --git a/app/src/main/java/info/nightscout/androidaps/events/Event.java b/app/src/main/java/info/nightscout/androidaps/events/Event.java new file mode 100644 index 0000000000..864d55d6f7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/Event.java @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.events; + +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** Base class for all events posted on the event bus. */ +public abstract class Event { + static { + ReflectionToStringBuilder.setDefaultStyle(ToStringStyle.SHORT_PREFIX_STYLE); + } + + @Override + public String toString() { + return ReflectionToStringBuilder.toString(this); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.java b/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.java index 0f23643fef..9ce91a9a39 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.java @@ -3,5 +3,5 @@ package info.nightscout.androidaps.events; /** * Created by mike on 07.07.2016. */ -public class EventAppExit { +public class EventAppExit extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.java b/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.java index 1f41119b4b..cb727758bb 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.java @@ -4,7 +4,7 @@ package info.nightscout.androidaps.events; * Created by adrian on 07/02/17. */ -public class EventBolusRequested { +public class EventBolusRequested extends Event { private double amount; public EventBolusRequested (double amount){ diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.java index d86fe679fb..9b47ed39cb 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 25.05.2017. */ -public class EventCareportalEventChange { +public class EventCareportalEventChange extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.java index 38331ca581..ad5f558fe8 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 17.02.2017. */ -public class EventConfigBuilderChange { +public class EventConfigBuilderChange extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.java index 78dee60388..8881b0ecc1 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 15.05.2017. */ -public class EventExtendedBolusChange { +public class EventExtendedBolusChange extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.java b/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.java index 075993c530..48e6be3a14 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 20.09.2017. */ -public class EventFoodDatabaseChanged { +public class EventFoodDatabaseChanged extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.java b/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.java index e9a9ce511d..f2bef1d3d0 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 13.12.2016. */ -public class EventInitializationChanged { +public class EventInitializationChanged extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventLoop.java b/app/src/main/java/info/nightscout/androidaps/events/EventLoop.java new file mode 100644 index 0000000000..d694d52537 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventLoop.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.events; + +/** Supeclass for all events concerned with input or output into or from the LoopPlugin. */ +public abstract class EventLoop extends Event { +} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java b/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java index 2d6454406a..2fb9919b00 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java @@ -3,5 +3,5 @@ package info.nightscout.androidaps.events; /** * Created by mike on 05.06.2016. */ -public class EventNewBG { +public class EventNewBG extends EventLoop { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java b/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java index 1309625b98..f26a310b6b 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java @@ -3,5 +3,5 @@ package info.nightscout.androidaps.events; /** * Created by mike on 04.06.2016. */ -public class EventNewBasalProfile { +public class EventNewBasalProfile extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.java index 76da0a4e67..f99cb54568 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.java @@ -5,7 +5,7 @@ import info.nightscout.androidaps.MainApp; /** * Created by mike on 19.06.2016. */ -public class EventPreferenceChange { +public class EventPreferenceChange extends Event { public String changedKey; public EventPreferenceChange(String key) { changedKey = key; diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventProfileSwitchChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventProfileSwitchChange.java index 476a571d70..7bab9d4518 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventProfileSwitchChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventProfileSwitchChange.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 02.06.2017. */ -public class EventProfileSwitchChange { +public class EventProfileSwitchChange extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.java b/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.java index 3cfe7cc6a7..52c3183821 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.java @@ -7,7 +7,7 @@ import info.nightscout.androidaps.R; * Created by mike on 19.02.2017. */ -public class EventPumpStatusChanged { +public class EventPumpStatusChanged extends Event { public static final int CONNECTING = 0; public static final int CONNECTED = 1; public static final int PERFORMING = 2; diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshGui.java b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshGui.java index f20dfb9329..1dae34d2af 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshGui.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshGui.java @@ -3,5 +3,5 @@ package info.nightscout.androidaps.events; /** * Created by mike on 13.06.2016. */ -public class EventRefreshGui { +public class EventRefreshGui extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.java b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.java index bf14f5f585..2ba78fa9ec 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.java @@ -4,7 +4,7 @@ package info.nightscout.androidaps.events; * Created by mike on 16.06.2017. */ -public class EventRefreshOverview { +public class EventRefreshOverview extends Event { public String from; public EventRefreshOverview(String from) { diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.java b/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.java index 20073a7cf0..212e8856d9 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 12.06.2017. */ -public class EventReloadProfileSwitchData { +public class EventReloadProfileSwitchData extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.java b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.java index 38b1b86186..80125cbb4a 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 29.05.2017. */ -public class EventReloadTempBasalData { +public class EventReloadTempBasalData extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.java b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.java index d4ea0d3f70..0ba9b95ad7 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.java @@ -4,7 +4,7 @@ package info.nightscout.androidaps.events; * Created by mike on 29.05.2017. */ -public class EventReloadTreatmentData { +public class EventReloadTreatmentData extends Event { public Object next; public EventReloadTreatmentData(Object next) { diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.java index 5d8f961e75..73660bb00e 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.java @@ -3,5 +3,5 @@ package info.nightscout.androidaps.events; /** * Created by mike on 05.06.2016. */ -public class EventTempBasalChange { +public class EventTempBasalChange extends EventLoop { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.java index d0ef42d830..4e3bf5c5f8 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 13.01.2017. */ -public class EventTempTargetChange { +public class EventTempTargetChange extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java index a8597189bc..439d9a7124 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java @@ -3,5 +3,5 @@ package info.nightscout.androidaps.events; /** * Created by mike on 04.06.2016. */ -public class EventTreatmentChange { +public class EventTreatmentChange extends EventLoop { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/events/EventUpdateGui.java new file mode 100644 index 0000000000..3471d2e851 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventUpdateGui.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.events; + +/** Base class for events to update the UI, mostly a specific tab. */ +public abstract class EventUpdateGui extends Event { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java index 1b976195ae..16cfd89404 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java @@ -138,6 +138,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + if (options==null) return null; getDialog().setTitle(getString(options.eventName)); setStyle(DialogFragment.STYLE_NORMAL, getTheme()); View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodFragment.java new file mode 100644 index 0000000000..558cf0d02f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodFragment.java @@ -0,0 +1,315 @@ +package info.nightscout.androidaps.plugins.Food; + +import android.app.Activity; +import android.content.DialogInterface; +import android.graphics.Paint; +import android.os.Bundle; +import android.support.v7.app.AlertDialog; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import com.crashlytics.android.Crashlytics; +import com.squareup.otto.Subscribe; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.Food; +import info.nightscout.androidaps.events.EventFoodDatabaseChanged; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.utils.NSUpload; +import info.nightscout.utils.SpinnerHelper; + +/** + * Created by mike on 16.10.2017. + */ + +public class FoodFragment extends SubscriberFragment { + private static Logger log = LoggerFactory.getLogger(FoodFragment.class); + + EditText filter; + ImageView clearFilter; + SpinnerHelper category; + SpinnerHelper subcategory; + RecyclerView recyclerView; + + List unfiltered; + List filtered; + ArrayList categories; + ArrayList subcategories; + + final String EMPTY = MainApp.sResources.getString(R.string.none); + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + try { + View view = inflater.inflate(R.layout.food_fragment, container, false); + + filter = (EditText) view.findViewById(R.id.food_filter); + clearFilter = (ImageView) view.findViewById(R.id.food_clearfilter); + category = new SpinnerHelper(view.findViewById(R.id.food_category)); + subcategory = new SpinnerHelper(view.findViewById(R.id.food_subcategory)); + recyclerView = (RecyclerView) view.findViewById(R.id.food_recyclerview); + recyclerView.setHasFixedSize(true); + LinearLayoutManager llm = new LinearLayoutManager(view.getContext()); + recyclerView.setLayoutManager(llm); + + clearFilter.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + filter.setText(""); + category.setSelection(0); + subcategory.setSelection(0); + filterData(); + } + }); + + category.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + fillSubcategories(); + filterData(); + } + + @Override + public void onNothingSelected(AdapterView parent) { + fillSubcategories(); + filterData(); + } + }); + + subcategory.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + filterData(); + } + + @Override + public void onNothingSelected(AdapterView parent) { + filterData(); + } + }); + + filter.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + filterData(); + } + + @Override + public void afterTextChanged(Editable s) { + } + }); + + RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getDbHelper().foodHelper.getFoodData()); + recyclerView.setAdapter(adapter); + + loadData(); + fillCategories(); + fillSubcategories(); + filterData(); + return view; + } catch (Exception e) { + Crashlytics.logException(e); + } + + return null; + } + + @Subscribe + @SuppressWarnings("unused") + public void onStatusEvent(final EventFoodDatabaseChanged ev) { + loadData(); + filterData(); + } + + void loadData() { + unfiltered = MainApp.getDbHelper().foodHelper.getFoodData(); + } + + void fillCategories() { + categories = new ArrayList<>(); + + for (Food f : unfiltered) { + if (f.category != null && !f.category.equals("")) + categories.add(f.category); + } + + // make it unique + categories = new ArrayList<>(new HashSet<>(categories)); + + categories.add(0, MainApp.sResources.getString(R.string.none)); + + ArrayAdapter adapterCategories = new ArrayAdapter<>(getContext(), + R.layout.spinner_centered, categories); + category.setAdapter(adapterCategories); + } + + void fillSubcategories() { + String categoryFilter = category.getSelectedItem().toString(); + subcategories = new ArrayList<>(); + + if (!categoryFilter.equals(EMPTY)) { + for (Food f : unfiltered) { + if (f.category != null && f.category.equals(categoryFilter)) + if (f.subcategory != null && !f.subcategory.equals("")) + subcategories.add(f.subcategory); + } + } + + // make it unique + subcategories = new ArrayList<>(new HashSet<>(subcategories)); + + subcategories.add(0, MainApp.sResources.getString(R.string.none)); + + ArrayAdapter adapterSubcategories = new ArrayAdapter<>(getContext(), + R.layout.spinner_centered, subcategories); + subcategory.setAdapter(adapterSubcategories); + } + + void filterData() { + String textFilter = filter.getText().toString(); + String categoryFilter = category.getSelectedItem().toString(); + String subcategoryFilter = subcategory.getSelectedItem().toString(); + + filtered = new ArrayList<>(); + + for (Food f : unfiltered) { + if (f.name == null || f.category == null || f.subcategory == null) + continue; + + if (!subcategoryFilter.equals(EMPTY) && !f.subcategory.equals(subcategoryFilter)) + continue; + if (!categoryFilter.equals(EMPTY) && !f.category.equals(categoryFilter)) + continue; + if (!textFilter.equals("") && !f.name.toLowerCase().contains(textFilter.toLowerCase())) + continue; + filtered.add(f); + } + + updateGUI(); + } + + @Override + protected void updateGUI() { + Activity activity = getActivity(); + if (activity != null) + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + recyclerView.swapAdapter(new FoodFragment.RecyclerViewAdapter(filtered), true); + } + }); + } + + public class RecyclerViewAdapter extends RecyclerView.Adapter { + + List foodList; + + RecyclerViewAdapter(List foodList) { + this.foodList = foodList; + } + + @Override + public FoodsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.food_item, viewGroup, false); + return new FoodsViewHolder(v); + } + + @Override + public void onBindViewHolder(FoodsViewHolder holder, int position) { + Food food = foodList.get(position); + holder.ns.setVisibility(food._id != null ? View.VISIBLE : View.GONE); + holder.name.setText(food.name); + holder.portion.setText(food.portion + food.units); + holder.carbs.setText(food.carbs + MainApp.sResources.getString(R.string.shortgramm)); + holder.fat.setText(MainApp.sResources.getString(R.string.shortfat) + ": " + food.fat + MainApp.sResources.getString(R.string.shortgramm)); + if (food.fat == 0) + holder.fat.setVisibility(View.INVISIBLE); + holder.protein.setText(MainApp.sResources.getString(R.string.shortprotein) + ": " + food.protein + MainApp.sResources.getString(R.string.shortgramm)); + if (food.protein == 0) + holder.protein.setVisibility(View.INVISIBLE); + holder.energy.setText(MainApp.sResources.getString(R.string.shortenergy) + ": " + food.energy + MainApp.sResources.getString(R.string.shortkilojoul)); + if (food.energy == 0) + holder.energy.setVisibility(View.INVISIBLE); + holder.remove.setTag(food); + } + + @Override + public int getItemCount() { + return foodList.size(); + } + + class FoodsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + TextView name; + TextView portion; + TextView carbs; + TextView fat; + TextView protein; + TextView energy; + TextView ns; + TextView remove; + + FoodsViewHolder(View itemView) { + super(itemView); + name = (TextView) itemView.findViewById(R.id.food_name); + portion = (TextView) itemView.findViewById(R.id.food_portion); + carbs = (TextView) itemView.findViewById(R.id.food_carbs); + fat = (TextView) itemView.findViewById(R.id.food_fat); + protein = (TextView) itemView.findViewById(R.id.food_protein); + energy = (TextView) itemView.findViewById(R.id.food_energy); + ns = (TextView) itemView.findViewById(R.id.ns_sign); + remove = (TextView) itemView.findViewById(R.id.food_remove); + remove.setOnClickListener(this); + remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); + } + + @Override + public void onClick(View v) { + final Food food = (Food) v.getTag(); + switch (v.getId()) { + + case R.id.food_remove: + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); + builder.setMessage(MainApp.sResources.getString(R.string.removerecord) + "\n" + food.name); + builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + final String _id = food._id; + if (_id != null && !_id.equals("")) { + NSUpload.removeFoodFromNS(_id); + } + MainApp.getDbHelper().foodHelper.delete(food); + } + }); + builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null); + builder.show(); + break; + + } + } + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodPlugin.java new file mode 100644 index 0000000000..255b4fd951 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodPlugin.java @@ -0,0 +1,85 @@ +package info.nightscout.androidaps.plugins.Food; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.interfaces.PluginBase; + +/** + * Created by mike on 05.08.2016. + */ +public class FoodPlugin implements PluginBase { + private boolean fragmentEnabled = true; + private boolean fragmentVisible = false; + + private static FoodPlugin plugin = null; + + public static FoodPlugin getPlugin() { + if (plugin == null) + plugin = new FoodPlugin(); + return plugin; + } + + @Override + public String getFragmentClass() { + return FoodFragment.class.getName(); + } + + @Override + public int getType() { + return PluginBase.GENERAL; + } + + @Override + public String getName() { + return MainApp.instance().getString(R.string.food); + } + + @Override + public String getNameShort() { + // use long name as fallback (not visible in tabs) + return getName(); + } + + + @Override + public boolean isEnabled(int type) { + return type == GENERAL && fragmentEnabled; + } + + @Override + public boolean isVisibleInTabs(int type) { + return type == GENERAL && fragmentVisible; + } + + @Override + public boolean canBeHidden(int type) { + return true; + } + + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + + @Override + public void setFragmentEnabled(int type, boolean fragmentEnabled) { + if (type == GENERAL) this.fragmentEnabled = fragmentEnabled; + } + + @Override + public void setFragmentVisible(int type, boolean fragmentVisible) { + if (type == GENERAL) this.fragmentVisible = fragmentVisible; + } + + @Override + public int getPreferencesId() { + return -1; + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventAutosensCalculationFinished.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventAutosensCalculationFinished.java index f2977c90c5..ea73915436 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventAutosensCalculationFinished.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventAutosensCalculationFinished.java @@ -1,8 +1,10 @@ package info.nightscout.androidaps.plugins.IobCobCalculator.events; +import info.nightscout.androidaps.events.EventLoop; + /** * Created by mike on 30.04.2017. */ -public class EventAutosensCalculationFinished { +public class EventAutosensCalculationFinished extends EventLoop { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventNewHistoryData.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventNewHistoryData.java index 7499fad383..8814741099 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventNewHistoryData.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventNewHistoryData.java @@ -1,10 +1,12 @@ package info.nightscout.androidaps.plugins.IobCobCalculator.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 26.04.2017. */ -public class EventNewHistoryData { +public class EventNewHistoryData extends Event { public long time = 0; public EventNewHistoryData(long time) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopSetLastRunGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopSetLastRunGui.java index 7baf556546..1ef5dc4c94 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopSetLastRunGui.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopSetLastRunGui.java @@ -1,9 +1,11 @@ package info.nightscout.androidaps.plugins.Loop.events; +import info.nightscout.androidaps.events.EventUpdateGui; + /** * Created by mike on 05.08.2016. */ -public class EventLoopSetLastRunGui { +public class EventLoopSetLastRunGui extends EventUpdateGui { public String text = null; public EventLoopSetLastRunGui(String text) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopUpdateGui.java index d671b3bd64..d4417dbb12 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopUpdateGui.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopUpdateGui.java @@ -1,7 +1,9 @@ package info.nightscout.androidaps.plugins.Loop.events; +import info.nightscout.androidaps.events.EventUpdateGui; + /** * Created by mike on 05.08.2016. */ -public class EventLoopUpdateGui { +public class EventLoopUpdateGui extends EventUpdateGui { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventNewOpenLoopNotification.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventNewOpenLoopNotification.java index 7a6184e406..001d11661e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventNewOpenLoopNotification.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventNewOpenLoopNotification.java @@ -1,7 +1,9 @@ package info.nightscout.androidaps.plugins.Loop.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 07.08.2016. */ -public class EventNewOpenLoopNotification { +public class EventNewOpenLoopNotification extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSAddAck.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSAddAck.java index 709c53f6d4..e90dce3bec 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSAddAck.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSAddAck.java @@ -7,14 +7,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.events.Event; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientRestart; -import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService; import io.socket.client.Ack; /** * Created by mike on 29.12.2015. */ -public class NSAddAck implements Ack { +public class NSAddAck extends Event implements Ack { private static Logger log = LoggerFactory.getLogger(NSAddAck.class); public String _id = null; public String nsClientID = null; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSAuthAck.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSAuthAck.java index 3c3b173173..56055351d9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSAuthAck.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSAuthAck.java @@ -3,13 +3,14 @@ package info.nightscout.androidaps.plugins.NSClientInternal.acks; import org.json.JSONObject; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.events.Event; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog; import io.socket.client.Ack; /** * Created by mike on 02.01.2016. */ -public class NSAuthAck implements Ack{ +public class NSAuthAck extends Event implements Ack{ public boolean read = false; public boolean write = false; public boolean write_treatment = false; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSPingAck.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSPingAck.java deleted file mode 100644 index 1ec6e3991c..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSPingAck.java +++ /dev/null @@ -1,44 +0,0 @@ -package info.nightscout.androidaps.plugins.NSClientInternal.acks; - -import android.os.SystemClock; - -import org.json.JSONException; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import io.socket.client.Ack; - -/** - * Created by mike on 29.12.2015. - */ -public class NSPingAck implements Ack { - private static Logger log = LoggerFactory.getLogger(NSPingAck.class); - - public long mills = 0; - public boolean received = false; - public boolean auth_received = false; - public boolean read = false; - public boolean write = false; - public boolean write_treatment = false; - - public void call(Object...args) { - JSONObject response = (JSONObject)args[0]; - mills = response.optLong("mills"); - if (response.has("authorization")) { - auth_received = true; - try { - JSONObject authorization = response.getJSONObject("authorization"); - read = authorization.optBoolean("read"); - write = authorization.optBoolean("write"); - write_treatment = authorization.optBoolean("write_treatment"); - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - } - received = true; - synchronized(this) { - this.notify(); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSUpdateAck.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSUpdateAck.java index 5aef754d8c..2bf520da64 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSUpdateAck.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSUpdateAck.java @@ -6,12 +6,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.events.Event; import io.socket.client.Ack; /** * Created by mike on 21.02.2016. */ -public class NSUpdateAck implements Ack { +public class NSUpdateAck extends Event implements Ack { private static Logger log = LoggerFactory.getLogger(NSUpdateAck.class); public boolean result = false; public String _id = null; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientNewLog.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientNewLog.java index 7caafbd28a..82b11a812d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientNewLog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientNewLog.java @@ -1,19 +1,15 @@ package info.nightscout.androidaps.plugins.NSClientInternal.events; -import android.text.Html; -import android.text.Spanned; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.text.SimpleDateFormat; import java.util.Date; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 15.02.2017. */ -public class EventNSClientNewLog { +public class EventNSClientNewLog extends Event { public Date date = new Date(); public String action; public String logText; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientRestart.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientRestart.java index 9bf90be31b..b968878da8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientRestart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientRestart.java @@ -1,8 +1,10 @@ package info.nightscout.androidaps.plugins.NSClientInternal.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 15.02.2017. */ -public class EventNSClientRestart { +public class EventNSClientRestart extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientStatus.java index 6a1c721535..977c0e31fc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientStatus.java @@ -1,9 +1,11 @@ package info.nightscout.androidaps.plugins.NSClientInternal.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 02.01.2016. */ -public class EventNSClientStatus { +public class EventNSClientStatus extends Event { public String status = ""; public EventNSClientStatus(String status) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientUpdateGUI.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientUpdateGUI.java index 8f00bd3424..dd78d2cd28 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientUpdateGUI.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientUpdateGUI.java @@ -1,8 +1,10 @@ package info.nightscout.androidaps.plugins.NSClientInternal.events; +import info.nightscout.androidaps.events.EventUpdateGui; + /** * Created by mike on 17.02.2017. */ -public class EventNSClientUpdateGUI { +public class EventNSClientUpdateGUI extends EventUpdateGui { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateGui.java index 65b3b49d53..40f3c31973 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateGui.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateGui.java @@ -1,7 +1,9 @@ package info.nightscout.androidaps.plugins.OpenAPSMA.events; +import info.nightscout.androidaps.events.EventUpdateGui; + /** * Created by mike on 05.08.2016. */ -public class EventOpenAPSUpdateGui { +public class EventOpenAPSUpdateGui extends EventUpdateGui { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateResultGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateResultGui.java index 2aa2365eff..e65cdd2c57 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateResultGui.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateResultGui.java @@ -1,9 +1,11 @@ package info.nightscout.androidaps.plugins.OpenAPSMA.events; +import info.nightscout.androidaps.events.EventUpdateGui; + /** * Created by mike on 05.08.2016. */ -public class EventOpenAPSUpdateResultGui { +public class EventOpenAPSUpdateResultGui extends EventUpdateGui { public String text = null; public EventOpenAPSUpdateResultGui(String text) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java index 67ab9227ed..8b08d76dd2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java @@ -37,9 +37,7 @@ import com.crashlytics.android.Crashlytics; import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.CustomEvent; import com.jjoe64.graphview.GraphView; -import com.jjoe64.graphview.LabelFormatter; import com.jjoe64.graphview.ValueDependentColor; -import com.jjoe64.graphview.Viewport; import com.jjoe64.graphview.series.BarGraphSeries; import com.jjoe64.graphview.series.DataPoint; import com.jjoe64.graphview.series.LineGraphSeries; @@ -55,7 +53,6 @@ import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; -import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.concurrent.Executors; @@ -77,11 +74,9 @@ import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.ExtendedBolus; -import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventCareportalEventChange; import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventInitializationChanged; @@ -100,7 +95,6 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.IobCobCalculator.events.BasalData; import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification; @@ -114,11 +108,8 @@ import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.AreaGraphSeries; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.DoubleDataPoint; +import info.nightscout.androidaps.plugins.Overview.graphData.GraphData; import info.nightscout.androidaps.plugins.Overview.graphExtensions.FixedLineGraphSeries; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter; import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin; import info.nightscout.androidaps.plugins.Treatments.fragments.ProfileViewerDialog; @@ -128,7 +119,6 @@ import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.NSUpload; import info.nightscout.utils.OKDialog; import info.nightscout.utils.Profiler; -import info.nightscout.utils.Round; import info.nightscout.utils.SP; import info.nightscout.utils.ToastUtils; @@ -939,8 +929,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, return; } - Double lowLine = SP.getDouble("low_mark", 0d); - Double highLine = SP.getDouble("high_mark", 0d); + double lowLine = SP.getDouble("low_mark", 0d); + double highLine = SP.getDouble("high_mark", 0d); //Start with updating the BG as it is unaffected by loop. // **** BG value **** @@ -1007,7 +997,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, tempTargetView.setTextColor(Color.BLACK); tempTargetView.setBackgroundColor(MainApp.sResources.getColor(R.color.tempTargetBackground)); tempTargetView.setVisibility(View.VISIBLE); - tempTargetView.setText(Profile.toTargetRangeString(tempTarget.low, tempTarget.high, Constants.MGDL, units)); + tempTargetView.setText(Profile.toTargetRangeString(tempTarget.low, tempTarget.high, Constants.MGDL, units) + " " + DateUtil.untilString(tempTarget.end())); } else { tempTargetView.setTextColor(Color.WHITE); tempTargetView.setBackgroundColor(MainApp.sResources.getColor(R.color.tempTargetDisabledBackground)); @@ -1251,7 +1241,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } // ****** GRAPH ******* - //log.debug("updateGUI checkpoint 1"); // allign to hours Calendar calendar = Calendar.getInstance(); @@ -1280,464 +1269,82 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, endTime = toTime; } - LineGraphSeries basalsLineSeries = null; - LineGraphSeries absoluteBasalsLineSeries = null; - LineGraphSeries baseBasalsSeries = null; - LineGraphSeries tempBasalsSeries = null; - AreaGraphSeries areaSeries; - LineGraphSeries seriesNow, seriesNow2; - - // **** TEMP BASALS graph **** - Double maxBasalValueFound = 0d; long now = System.currentTimeMillis(); - if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) { - List baseBasalArray = new ArrayList<>(); - List tempBasalArray = new ArrayList<>(); - List basalLineArray = new ArrayList<>(); - List absoluteBasalLineArray = new ArrayList<>(); - double lastLineBasal = 0; - double lastAbsoluteLineBasal = 0; - double lastBaseBasal = 0; - double lastTempBasal = 0; - for (long time = fromTime; time < now; time += 60 * 1000L) { - BasalData basalData = IobCobCalculatorPlugin.getBasalData(time); - double baseBasalValue = basalData.basal; - double absoluteLineValue = baseBasalValue; - double tempBasalValue = 0; - double basal = 0d; - if (basalData.isTempBasalRunning) { - absoluteLineValue = tempBasalValue = basalData.tempBasalAbsolute; - if (tempBasalValue != lastTempBasal) { - tempBasalArray.add(new DataPoint(time, lastTempBasal)); - tempBasalArray.add(new DataPoint(time, basal = tempBasalValue)); - } - if (lastBaseBasal != 0d) { - baseBasalArray.add(new DataPoint(time, lastBaseBasal)); - baseBasalArray.add(new DataPoint(time, 0d)); - lastBaseBasal = 0d; - } - } else { - if (baseBasalValue != lastBaseBasal) { - baseBasalArray.add(new DataPoint(time, lastBaseBasal)); - baseBasalArray.add(new DataPoint(time, basal = baseBasalValue)); - lastBaseBasal = baseBasalValue; - } - if (lastTempBasal != 0) { - tempBasalArray.add(new DataPoint(time, lastTempBasal)); - tempBasalArray.add(new DataPoint(time, 0d)); - } - } - if (baseBasalValue != lastLineBasal) { - basalLineArray.add(new DataPoint(time, lastLineBasal)); - basalLineArray.add(new DataPoint(time, baseBasalValue)); - } - if (absoluteLineValue != lastAbsoluteLineBasal) { - absoluteBasalLineArray.add(new DataPoint(time, lastAbsoluteLineBasal)); - absoluteBasalLineArray.add(new DataPoint(time, basal)); - } + // 2nd graph + // remove old data + iobGraph.getSeries().clear(); - lastAbsoluteLineBasal = absoluteLineValue; - lastLineBasal = baseBasalValue; - lastTempBasal = tempBasalValue; - maxBasalValueFound = Math.max(maxBasalValueFound, basal); - } - basalLineArray.add(new DataPoint(now, lastLineBasal)); - baseBasalArray.add(new DataPoint(now, lastBaseBasal)); - tempBasalArray.add(new DataPoint(now, lastTempBasal)); - absoluteBasalLineArray.add(new DataPoint(now, lastAbsoluteLineBasal)); + GraphData secondGraphData = new GraphData(); - DataPoint[] baseBasal = new DataPoint[baseBasalArray.size()]; - baseBasal = baseBasalArray.toArray(baseBasal); - baseBasalsSeries = new LineGraphSeries<>(baseBasal); - baseBasalsSeries.setDrawBackground(true); - baseBasalsSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.basebasal)); - baseBasalsSeries.setThickness(0); + boolean useIobForScale = false; + boolean useCobForScale = false; + boolean useDevForScale = false; + boolean useRatioForScale = false; - DataPoint[] tempBasal = new DataPoint[tempBasalArray.size()]; - tempBasal = tempBasalArray.toArray(tempBasal); - tempBasalsSeries = new LineGraphSeries<>(tempBasal); - tempBasalsSeries.setDrawBackground(true); - tempBasalsSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.tempbasal)); - tempBasalsSeries.setThickness(0); - - DataPoint[] basalLine = new DataPoint[basalLineArray.size()]; - basalLine = basalLineArray.toArray(basalLine); - basalsLineSeries = new LineGraphSeries<>(basalLine); - Paint paint = new Paint(); - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeWidth(2); - paint.setPathEffect(new DashPathEffect(new float[]{2, 4}, 0)); - paint.setColor(MainApp.sResources.getColor(R.color.basal)); - basalsLineSeries.setCustomPaint(paint); - - DataPoint[] absoluteBasalLine = new DataPoint[absoluteBasalLineArray.size()]; - absoluteBasalLine = absoluteBasalLineArray.toArray(absoluteBasalLine); - absoluteBasalsLineSeries = new LineGraphSeries<>(absoluteBasalLine); - Paint absolutePaint = new Paint(); - absolutePaint.setStyle(Paint.Style.STROKE); - absolutePaint.setStrokeWidth(4); - absolutePaint.setColor(MainApp.sResources.getColor(R.color.basal)); - absoluteBasalsLineSeries.setCustomPaint(absolutePaint); + if (showIobView.isChecked()) { + useIobForScale = true; + } else if (showCobView.isChecked()) { + useCobForScale = true; + } else if (showDeviationsView.isChecked()) { + useDevForScale = true; + } else if (showRatiosView.isChecked()) { + useRatioForScale = true; } - //log.debug("updateGUI checkpoint 2"); - - // **** IOB COB DEV graph **** - class DeviationDataPoint extends DataPoint { - public int color; - - public DeviationDataPoint(double x, double y, int color) { - super(x, y); - this.color = color; - } - } - FixedLineGraphSeries iobSeries; - FixedLineGraphSeries cobSeries; - BarGraphSeries devSeries; - LineGraphSeries ratioSeries; - Double maxIobValueFound = 0d; - Double maxCobValueFound = 0d; - Double maxDevValueFound = 0d; - Double maxRatioValueFound = 0d; + if (showIobView.isChecked()) + secondGraphData.addIob(iobGraph, fromTime, now, useIobForScale, 1d); + if (showCobView.isChecked()) + secondGraphData.addCob(iobGraph, fromTime, now, useCobForScale, useCobForScale ? 1d : 0.5d); + if (showDeviationsView.isChecked()) + secondGraphData.addDeviations(iobGraph, fromTime, now, useDevForScale, 1d); + if (showRatiosView.isChecked()) + secondGraphData.addRatio(iobGraph, fromTime, now, useRatioForScale, 1d); if (showIobView.isChecked() || showCobView.isChecked() || showDeviationsView.isChecked() || showRatiosView.isChecked()) { - //Date start = new Date(); - List iobArray = new ArrayList<>(); - List cobArray = new ArrayList<>(); - List devArray = new ArrayList<>(); - List ratioArray = new ArrayList<>(); - double lastIob = 0; - int lastCob = 0; - for (long time = fromTime; time <= now; time += 5 * 60 * 1000L) { - if (showIobView.isChecked()) { - double iob = IobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time).iob; - if (Math.abs(lastIob - iob) > 0.02) { - if (Math.abs(lastIob - iob) > 0.2) - iobArray.add(new DataPoint(time, lastIob)); - iobArray.add(new DataPoint(time, iob)); - maxIobValueFound = Math.max(maxIobValueFound, Math.abs(iob)); - lastIob = iob; - } - } - if (showCobView.isChecked() || showDeviationsView.isChecked() || showRatiosView.isChecked()) { - AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time); - if (autosensData != null && showCobView.isChecked()) { - int cob = (int) autosensData.cob; - if (cob != lastCob) { - if (autosensData.carbsFromBolus > 0) - cobArray.add(new DataPoint(time, lastCob)); - cobArray.add(new DataPoint(time, cob)); - maxCobValueFound = Math.max(maxCobValueFound, cob); - lastCob = cob; - } - } - if (autosensData != null && showDeviationsView.isChecked()) { - int color = Color.BLACK; // "=" - if (autosensData.pastSensitivity.equals("C")) color = Color.GRAY; - if (autosensData.pastSensitivity.equals("+")) color = Color.GREEN; - if (autosensData.pastSensitivity.equals("-")) color = Color.RED; - devArray.add(new DeviationDataPoint(time, autosensData.deviation, color)); - maxDevValueFound = Math.max(maxDevValueFound, Math.abs(autosensData.deviation)); - } - if (autosensData != null && showRatiosView.isChecked()) { - ratioArray.add(new DataPoint(time, autosensData.autosensRatio)); - maxRatioValueFound = Math.max(maxRatioValueFound, Math.abs(autosensData.autosensRatio)); - } - } - } - //Profiler.log(log, "IOB processed", start); - DataPoint[] iobData = new DataPoint[iobArray.size()]; - iobData = iobArray.toArray(iobData); - iobSeries = new FixedLineGraphSeries<>(iobData); - iobSeries.setDrawBackground(true); - iobSeries.setBackgroundColor(0x80FFFFFF & MainApp.sResources.getColor(R.color.iob)); //50% - iobSeries.setColor(MainApp.sResources.getColor(R.color.iob)); - iobSeries.setThickness(3); - - - Double maxByScale = null; - int graphsToShow = 0; - if (showIobView.isChecked()) { - if (maxByScale == null) maxByScale = maxIobValueFound; - graphsToShow++; - } - if (showCobView.isChecked()) { - if (maxByScale == null) maxByScale = maxCobValueFound; - graphsToShow++; - } - if (showDeviationsView.isChecked()) { - if (maxByScale == null) maxByScale = maxDevValueFound; - graphsToShow++; - } - if (showRatiosView.isChecked()) { - if (maxByScale == null) maxByScale = maxRatioValueFound; - graphsToShow++; - } - - if (graphsToShow > 1) { - if (!maxByScale.equals(maxCobValueFound)) { - List cobArrayRescaled = new ArrayList<>(); - for (int ci = 0; ci < cobArray.size(); ci++) { - cobArrayRescaled.add(new DataPoint(cobArray.get(ci).getX(), cobArray.get(ci).getY() * maxByScale / maxCobValueFound / 2)); - } - cobArray = cobArrayRescaled; - } - if (!maxByScale.equals(maxDevValueFound)) { - List devArrayRescaled = new ArrayList<>(); - for (int ci = 0; ci < devArray.size(); ci++) { - devArrayRescaled.add(new DeviationDataPoint(devArray.get(ci).getX(), devArray.get(ci).getY() * maxByScale / maxDevValueFound, devArray.get(ci).color)); - } - devArray = devArrayRescaled; - } - if (!maxByScale.equals(maxRatioValueFound)) { - List ratioArrayRescaled = new ArrayList<>(); - for (int ci = 0; ci < ratioArray.size(); ci++) { - ratioArrayRescaled.add(new DataPoint(ratioArray.get(ci).getX(), (ratioArray.get(ci).getY() - 1) * maxByScale / maxRatioValueFound)); - } - ratioArray = ratioArrayRescaled; - } - } - - // COB - DataPoint[] cobData = new DataPoint[cobArray.size()]; - cobData = cobArray.toArray(cobData); - cobSeries = new FixedLineGraphSeries<>(cobData); - cobSeries.setDrawBackground(true); - cobSeries.setBackgroundColor(0xB0FFFFFF & MainApp.sResources.getColor(R.color.cob)); //50% - cobSeries.setColor(MainApp.sResources.getColor(R.color.cob)); - cobSeries.setThickness(3); - - // DEVIATIONS - DeviationDataPoint[] devData = new DeviationDataPoint[devArray.size()]; - devData = devArray.toArray(devData); - devSeries = new BarGraphSeries<>(devData); - devSeries.setValueDependentColor(new ValueDependentColor() { - @Override - public int get(DeviationDataPoint data) { - return data.color; - } - }); - - // RATIOS - DataPoint[] ratioData = new DataPoint[ratioArray.size()]; - ratioData = ratioArray.toArray(ratioData); - ratioSeries = new LineGraphSeries<>(ratioData); - ratioSeries.setColor(MainApp.sResources.getColor(R.color.ratio)); - ratioSeries.setThickness(3); - - iobGraph.getSeries().clear(); - - if (showIobView.isChecked() && iobData.length > 0) { - addSeriesWithoutInvalidate(iobSeries, iobGraph); - } - if (showCobView.isChecked() && cobData.length > 0) { - addSeriesWithoutInvalidate(cobSeries, iobGraph); - } - if (showDeviationsView.isChecked() && devData.length > 0) { - addSeriesWithoutInvalidate(devSeries, iobGraph); - } - if (showRatiosView.isChecked() && ratioData.length > 0) { - addSeriesWithoutInvalidate(ratioSeries, iobGraph); - } iobGraph.setVisibility(View.VISIBLE); } else { iobGraph.setVisibility(View.GONE); } - //log.debug("updateGUI checkpoint 3"); // remove old data from graph - bgGraph.getSecondScale().getSeries().clear(); bgGraph.getSeries().clear(); - //log.debug("updateGUI checkpoint 4"); - // **** Area **** - DoubleDataPoint[] areaDataPoints = new DoubleDataPoint[]{ - new DoubleDataPoint(fromTime, lowLine, highLine), - new DoubleDataPoint(endTime, lowLine, highLine) - }; - areaSeries = new AreaGraphSeries<>(areaDataPoints); - addSeriesWithoutInvalidate(areaSeries, bgGraph); - areaSeries.setColor(0); - areaSeries.setDrawBackground(true); - areaSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.inrangebackground)); + GraphData graphData = new GraphData(); + + // **** In range Area **** + graphData.addInRangeArea(bgGraph, fromTime, endTime, lowLine, highLine); + + // **** BG **** + if (showPrediction) + graphData.addBgReadings(bgGraph, fromTime, toTime, lowLine, highLine, (DetermineBasalResultAMA) finalLastRun.constraintsProcessed); + else + graphData.addBgReadings(bgGraph, fromTime, toTime, lowLine, highLine, null); // set manual x bounds to have nice steps - bgGraph.getViewport().setMaxX(endTime); - bgGraph.getViewport().setMinX(fromTime); - bgGraph.getViewport().setXAxisBoundsManual(true); - bgGraph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter(getActivity(), "HH")); - bgGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space - iobGraph.getViewport().setMaxX(endTime); - iobGraph.getViewport().setMinX(fromTime); - iobGraph.getViewport().setXAxisBoundsManual(true); - iobGraph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter(getActivity(), "HH")); - iobGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space + graphData.formatAxis(bgGraph, fromTime, endTime); + secondGraphData.formatAxis(iobGraph, fromTime, endTime); - //log.debug("updateGUI checkpoint 5"); - // **** BG graph **** - List bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true); - List bgListArray = new ArrayList<>(); - - if (bgReadingsArray.size() == 0) { - return; - } - - Iterator it = bgReadingsArray.iterator(); - Double maxBgValue = 0d; - while (it.hasNext()) { - BgReading bg = it.next(); - if (bg.value > maxBgValue) maxBgValue = bg.value; - bgListArray.add(bg); - } - if (showPrediction) { - DetermineBasalResultAMA amaResult = (DetermineBasalResultAMA) finalLastRun.constraintsProcessed; - List predArray = amaResult.getPredictions(); - bgListArray.addAll(predArray); - } - - maxBgValue = Profile.fromMgdlToUnits(maxBgValue, units); - maxBgValue = units.equals(Constants.MGDL) ? Round.roundTo(maxBgValue, 40d) + 80 : Round.roundTo(maxBgValue, 2d) + 4; - if (highLine > maxBgValue) maxBgValue = highLine; - Integer numOfVertLines = units.equals(Constants.MGDL) ? (int) (maxBgValue / 40 + 1) : (int) (maxBgValue / 2 + 1); - - DataPointWithLabelInterface[] bg = new DataPointWithLabelInterface[bgListArray.size()]; - bg = bgListArray.toArray(bg); - - if (bg.length > 0) { - addSeriesWithoutInvalidate(new PointsWithLabelGraphSeries<>(bg), bgGraph); - } - - //log.debug("updateGUI checkpoint 6"); // Treatments - List filteredTreatments = new ArrayList<>(); + graphData.addTreatments(bgGraph, fromTime, endTime); - List treatments = MainApp.getConfigBuilder().getTreatmentsFromHistory(); - - for (int tx = 0; tx < treatments.size(); tx++) { - Treatment t = treatments.get(tx); - if (t.getX() < fromTime || t.getX() > endTime) continue; - t.setY(getNearestBg((long) t.getX(), bgReadingsArray)); - filteredTreatments.add(t); - } - - //log.debug("updateGUI checkpoint 7"); - // ProfileSwitch - List profileSwitches = MainApp.getConfigBuilder().getProfileSwitchesFromHistory().getList(); - - for (int tx = 0; tx < profileSwitches.size(); tx++) { - DataPointWithLabelInterface t = profileSwitches.get(tx); - if (t.getX() < fromTime || t.getX() > endTime) continue; - filteredTreatments.add(t); - } - - //log.debug("updateGUI checkpoint 8"); - // Extended bolus - if (!pump.isFakingTempsByExtendedBoluses()) { - List extendedBoluses = MainApp.getConfigBuilder().getExtendedBolusesFromHistory().getList(); - - for (int tx = 0; tx < extendedBoluses.size(); tx++) { - DataPointWithLabelInterface t = extendedBoluses.get(tx); - if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; - if (t.getDuration() == 0) continue; - t.setY(getNearestBg((long) t.getX(), bgReadingsArray)); - filteredTreatments.add(t); - } - } - - //log.debug("updateGUI checkpoint 9"); - // Careportal - List careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, true); - - for (int tx = 0; tx < careportalEvents.size(); tx++) { - DataPointWithLabelInterface t = careportalEvents.get(tx); - if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; - t.setY(getNearestBg((long) t.getX(), bgReadingsArray)); - filteredTreatments.add(t); - } - - DataPointWithLabelInterface[] treatmentsArray = new DataPointWithLabelInterface[filteredTreatments.size()]; - treatmentsArray = filteredTreatments.toArray(treatmentsArray); - if (treatmentsArray.length > 0) { - addSeriesWithoutInvalidate(new PointsWithLabelGraphSeries<>(treatmentsArray), bgGraph); - } - //log.debug("updateGUI checkpoint 10"); - - // set manual y bounds to have nice steps - bgGraph.getViewport().setMaxY(maxBgValue); - bgGraph.getViewport().setMinY(0); - bgGraph.getViewport().setYAxisBoundsManual(true); - bgGraph.getGridLabelRenderer().setNumVerticalLabels(numOfVertLines); - - // set second scale + // add basal data if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) { - bgGraph.getSecondScale().setMinY(0); - bgGraph.getSecondScale().setMaxY(maxBgValue / lowLine * maxBasalValueFound * 1.2d); - bgGraph.getSecondScale().addSeries(baseBasalsSeries); - bgGraph.getSecondScale().addSeries(tempBasalsSeries); - bgGraph.getSecondScale().addSeries(basalsLineSeries); - bgGraph.getSecondScale().addSeries(absoluteBasalsLineSeries); + graphData.addBasals(bgGraph, fromTime, now, lowLine / graphData.maxY / 1.2d); } - bgGraph.getSecondScale().setLabelFormatter(new LabelFormatter() { - @Override - public String formatLabel(double value, boolean isValueX) { - return ""; - } - @Override - public void setViewport(Viewport viewport) { - - } - }); - - //log.debug("updateGUI checkpoint 11"); // **** NOW line **** - DataPoint[] nowPoints = new DataPoint[]{ - new DataPoint(now, 0), - new DataPoint(now, maxBgValue) - }; - addSeriesWithoutInvalidate(seriesNow = new LineGraphSeries<>(nowPoints), bgGraph); - seriesNow.setDrawDataPoints(false); - DataPoint[] nowPoints2 = new DataPoint[]{ - new DataPoint(now, 0), - new DataPoint(now, maxIobValueFound) - }; - addSeriesWithoutInvalidate(seriesNow2 = new LineGraphSeries<>(nowPoints2), iobGraph); - seriesNow2.setDrawDataPoints(false); - //seriesNow.setThickness(1); - // custom paint to make a dotted line - Paint paint = new Paint(); - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeWidth(2); - paint.setPathEffect(new DashPathEffect(new float[]{10, 20}, 0)); - paint.setColor(Color.WHITE); - seriesNow.setCustomPaint(paint); - seriesNow2.setCustomPaint(paint); + graphData.addNowLine(bgGraph, now); + secondGraphData.addNowLine(iobGraph, now); + + // finaly enforce drawing of graphs bgGraph.onDataChanged(false, false); iobGraph.onDataChanged(false, false); Profiler.log(log, from, updateGUIStart); } - public double getNearestBg(long date, List bgReadingsArray) { - double bg = 0; - String units = MainApp.getConfigBuilder().getProfileUnits(); - for (int r = bgReadingsArray.size() - 1; r >= 0; r--) { - BgReading reading = bgReadingsArray.get(r); - if (reading.date > date) continue; - bg = Profile.fromMgdlToUnits(reading.value, units); - break; - } - return bg; - } - - void addSeriesWithoutInvalidate(Series s, GraphView graph) { - s.onGraphViewAttached(graph); - graph.getSeries().add(s); - } - - //Notifications static class RecyclerViewAdapter extends RecyclerView.Adapter { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissBolusprogressIfRunning.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissBolusprogressIfRunning.java index 9d8435eaf1..af336cd74c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissBolusprogressIfRunning.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissBolusprogressIfRunning.java @@ -1,12 +1,13 @@ package info.nightscout.androidaps.plugins.Overview.events; import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.events.Event; /** * Created by adrian on 20/02/17. */ -public class EventDismissBolusprogressIfRunning { +public class EventDismissBolusprogressIfRunning extends Event { public final PumpEnactResult result; public EventDismissBolusprogressIfRunning(PumpEnactResult result) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissNotification.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissNotification.java index f2414e2a4e..1fa71febbe 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissNotification.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissNotification.java @@ -1,10 +1,12 @@ package info.nightscout.androidaps.plugins.Overview.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 03.12.2016. */ -public class EventDismissNotification { +public class EventDismissNotification extends Event { public int id; public EventDismissNotification(int did) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventNewNotification.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventNewNotification.java index 8a80019f3e..59ad1a335d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventNewNotification.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventNewNotification.java @@ -1,12 +1,13 @@ package info.nightscout.androidaps.plugins.Overview.events; +import info.nightscout.androidaps.events.Event; import info.nightscout.androidaps.plugins.Overview.Notification; /** * Created by mike on 03.12.2016. */ -public class EventNewNotification { +public class EventNewNotification extends Event { public Notification notification; public EventNewNotification(Notification n) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventOverviewBolusProgress.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventOverviewBolusProgress.java index 0882032362..e0fd53a1fd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventOverviewBolusProgress.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventOverviewBolusProgress.java @@ -4,8 +4,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.events.Event; -public class EventOverviewBolusProgress { +public class EventOverviewBolusProgress extends Event { private static Logger log = LoggerFactory.getLogger(EventOverviewBolusProgress.class); public String status = ""; public Treatment t = null; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventQuickWizardChange.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventQuickWizardChange.java index 1a9923f606..b72c2548e2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventQuickWizardChange.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventQuickWizardChange.java @@ -1,8 +1,10 @@ package info.nightscout.androidaps.plugins.Overview.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 20.10.2016. */ -public class EventQuickWizardChange { +public class EventQuickWizardChange extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventSetWakeLock.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventSetWakeLock.java index 519341172d..49ccf9fbfb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventSetWakeLock.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventSetWakeLock.java @@ -1,10 +1,12 @@ package info.nightscout.androidaps.plugins.Overview.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 02.07.2017. */ -public class EventSetWakeLock { +public class EventSetWakeLock extends Event { public boolean lock = false; public EventSetWakeLock(boolean val) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java new file mode 100644 index 0000000000..f4be1fd351 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java @@ -0,0 +1,467 @@ +package info.nightscout.androidaps.plugins.Overview.graphData; + +import android.graphics.Color; +import android.graphics.DashPathEffect; +import android.graphics.Paint; + +import com.jjoe64.graphview.GraphView; +import com.jjoe64.graphview.ValueDependentColor; +import com.jjoe64.graphview.series.BarGraphSeries; +import com.jjoe64.graphview.series.DataPoint; +import com.jjoe64.graphview.series.LineGraphSeries; +import com.jjoe64.graphview.series.Series; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +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.db.BgReading; +import info.nightscout.androidaps.db.CareportalEvent; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.ProfileSwitch; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; +import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.IobCobCalculator.events.BasalData; +import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.AreaGraphSeries; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.DoubleDataPoint; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.FixedLineGraphSeries; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.Scale; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.ScaledDataPoint; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter; +import info.nightscout.utils.Round; + +/** + * Created by mike on 18.10.2017. + */ + +public class GraphData { + + public GraphData() { + units = MainApp.getConfigBuilder().getProfileUnits(); + } + + public double maxY = 0; + private List bgReadingsArray; + private String units; + + public void addBgReadings(GraphView bgGraph, long fromTime, long toTime, double lowLine, double highLine, DetermineBasalResultAMA amaResult) { + double maxBgValue = 0d; + bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true); + List bgListArray = new ArrayList<>(); + + if (bgReadingsArray.size() == 0) { + return; + } + + Iterator it = bgReadingsArray.iterator(); + while (it.hasNext()) { + BgReading bg = it.next(); + if (bg.value > maxBgValue) maxBgValue = bg.value; + bgListArray.add(bg); + } + if (amaResult != null) { + List predArray = amaResult.getPredictions(); + bgListArray.addAll(predArray); + } + + maxBgValue = Profile.fromMgdlToUnits(maxBgValue, units); + maxBgValue = units.equals(Constants.MGDL) ? Round.roundTo(maxBgValue, 40d) + 80 : Round.roundTo(maxBgValue, 2d) + 4; + if (highLine > maxBgValue) maxBgValue = highLine; + int numOfVertLines = units.equals(Constants.MGDL) ? (int) (maxBgValue / 40 + 1) : (int) (maxBgValue / 2 + 1); + + DataPointWithLabelInterface[] bg = new DataPointWithLabelInterface[bgListArray.size()]; + bg = bgListArray.toArray(bg); + + if (bg.length > 0) { + addSeriesWithoutInvalidate(bgGraph, new PointsWithLabelGraphSeries<>(bg)); + } + + maxY = maxBgValue; + // set manual y bounds to have nice steps + bgGraph.getViewport().setMaxY(maxY); + bgGraph.getViewport().setMinY(0); + bgGraph.getViewport().setYAxisBoundsManual(true); + bgGraph.getGridLabelRenderer().setNumVerticalLabels(numOfVertLines); + + } + + public void addInRangeArea(GraphView bgGraph, long fromTime, long toTime, double lowLine, double highLine) { + AreaGraphSeries inRangeAreaSeries; + + DoubleDataPoint[] inRangeAreaDataPoints = new DoubleDataPoint[]{ + new DoubleDataPoint(fromTime, lowLine, highLine), + new DoubleDataPoint(toTime, lowLine, highLine) + }; + inRangeAreaSeries = new AreaGraphSeries<>(inRangeAreaDataPoints); + addSeriesWithoutInvalidate(bgGraph, inRangeAreaSeries); + inRangeAreaSeries.setColor(0); + inRangeAreaSeries.setDrawBackground(true); + inRangeAreaSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.inrangebackground)); + } + + // scale in % of vertical size (like 0.3) + public void addBasals(GraphView bgGraph, long fromTime, long toTime, double scale) { + LineGraphSeries basalsLineSeries; + LineGraphSeries absoluteBasalsLineSeries; + LineGraphSeries baseBasalsSeries; + LineGraphSeries tempBasalsSeries; + + double maxBasalValueFound = 0d; + Scale basalScale = new Scale(); + + List baseBasalArray = new ArrayList<>(); + List tempBasalArray = new ArrayList<>(); + List basalLineArray = new ArrayList<>(); + List absoluteBasalLineArray = new ArrayList<>(); + double lastLineBasal = 0; + double lastAbsoluteLineBasal = 0; + double lastBaseBasal = 0; + double lastTempBasal = 0; + for (long time = fromTime; time < toTime; time += 60 * 1000L) { + BasalData basalData = IobCobCalculatorPlugin.getBasalData(time); + double baseBasalValue = basalData.basal; + double absoluteLineValue = baseBasalValue; + double tempBasalValue = 0; + double basal = 0d; + if (basalData.isTempBasalRunning) { + absoluteLineValue = tempBasalValue = basalData.tempBasalAbsolute; + if (tempBasalValue != lastTempBasal) { + tempBasalArray.add(new ScaledDataPoint(time, lastTempBasal, basalScale)); + tempBasalArray.add(new ScaledDataPoint(time, basal = tempBasalValue, basalScale)); + } + if (lastBaseBasal != 0d) { + baseBasalArray.add(new ScaledDataPoint(time, lastBaseBasal, basalScale)); + baseBasalArray.add(new ScaledDataPoint(time, 0d, basalScale)); + lastBaseBasal = 0d; + } + } else { + if (baseBasalValue != lastBaseBasal) { + baseBasalArray.add(new ScaledDataPoint(time, lastBaseBasal, basalScale)); + baseBasalArray.add(new ScaledDataPoint(time, basal = baseBasalValue, basalScale)); + lastBaseBasal = baseBasalValue; + } + if (lastTempBasal != 0) { + tempBasalArray.add(new ScaledDataPoint(time, lastTempBasal, basalScale)); + tempBasalArray.add(new ScaledDataPoint(time, 0d, basalScale)); + } + } + + if (baseBasalValue != lastLineBasal) { + basalLineArray.add(new ScaledDataPoint(time, lastLineBasal, basalScale)); + basalLineArray.add(new ScaledDataPoint(time, baseBasalValue, basalScale)); + } + if (absoluteLineValue != lastAbsoluteLineBasal) { + absoluteBasalLineArray.add(new ScaledDataPoint(time, lastAbsoluteLineBasal, basalScale)); + absoluteBasalLineArray.add(new ScaledDataPoint(time, basal, basalScale)); + } + + lastAbsoluteLineBasal = absoluteLineValue; + lastLineBasal = baseBasalValue; + lastTempBasal = tempBasalValue; + maxBasalValueFound = Math.max(maxBasalValueFound, basal); + } + + basalLineArray.add(new ScaledDataPoint(toTime, lastLineBasal, basalScale)); + baseBasalArray.add(new ScaledDataPoint(toTime, lastBaseBasal, basalScale)); + tempBasalArray.add(new ScaledDataPoint(toTime, lastTempBasal, basalScale)); + absoluteBasalLineArray.add(new ScaledDataPoint(toTime, lastAbsoluteLineBasal, basalScale)); + + ScaledDataPoint[] baseBasal = new ScaledDataPoint[baseBasalArray.size()]; + baseBasal = baseBasalArray.toArray(baseBasal); + baseBasalsSeries = new LineGraphSeries<>(baseBasal); + baseBasalsSeries.setDrawBackground(true); + baseBasalsSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.basebasal)); + baseBasalsSeries.setThickness(0); + + ScaledDataPoint[] tempBasal = new ScaledDataPoint[tempBasalArray.size()]; + tempBasal = tempBasalArray.toArray(tempBasal); + tempBasalsSeries = new LineGraphSeries<>(tempBasal); + tempBasalsSeries.setDrawBackground(true); + tempBasalsSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.tempbasal)); + tempBasalsSeries.setThickness(0); + + ScaledDataPoint[] basalLine = new ScaledDataPoint[basalLineArray.size()]; + basalLine = basalLineArray.toArray(basalLine); + basalsLineSeries = new LineGraphSeries<>(basalLine); + Paint paint = new Paint(); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(2); + paint.setPathEffect(new DashPathEffect(new float[]{2, 4}, 0)); + paint.setColor(MainApp.sResources.getColor(R.color.basal)); + basalsLineSeries.setCustomPaint(paint); + + ScaledDataPoint[] absoluteBasalLine = new ScaledDataPoint[absoluteBasalLineArray.size()]; + absoluteBasalLine = absoluteBasalLineArray.toArray(absoluteBasalLine); + absoluteBasalsLineSeries = new LineGraphSeries<>(absoluteBasalLine); + Paint absolutePaint = new Paint(); + absolutePaint.setStyle(Paint.Style.STROKE); + absolutePaint.setStrokeWidth(4); + absolutePaint.setColor(MainApp.sResources.getColor(R.color.basal)); + absoluteBasalsLineSeries.setCustomPaint(absolutePaint); + + basalScale.setMultiplier(maxY * scale / maxBasalValueFound); + + addSeriesWithoutInvalidate(bgGraph, baseBasalsSeries); + addSeriesWithoutInvalidate(bgGraph, tempBasalsSeries); + addSeriesWithoutInvalidate(bgGraph, basalsLineSeries); + addSeriesWithoutInvalidate(bgGraph, absoluteBasalsLineSeries); + } + + public void addTreatments(GraphView bgGraph, long fromTime, long endTime) { + List filteredTreatments = new ArrayList<>(); + + List treatments = MainApp.getConfigBuilder().getTreatmentsFromHistory(); + + for (int tx = 0; tx < treatments.size(); tx++) { + Treatment t = treatments.get(tx); + if (t.getX() < fromTime || t.getX() > endTime) continue; + t.setY(getNearestBg((long) t.getX())); + filteredTreatments.add(t); + } + + // ProfileSwitch + List profileSwitches = MainApp.getConfigBuilder().getProfileSwitchesFromHistory().getList(); + + for (int tx = 0; tx < profileSwitches.size(); tx++) { + DataPointWithLabelInterface t = profileSwitches.get(tx); + if (t.getX() < fromTime || t.getX() > endTime) continue; + filteredTreatments.add(t); + } + + // Extended bolus + if (!MainApp.getConfigBuilder().isFakingTempsByExtendedBoluses()) { + List extendedBoluses = MainApp.getConfigBuilder().getExtendedBolusesFromHistory().getList(); + + for (int tx = 0; tx < extendedBoluses.size(); tx++) { + DataPointWithLabelInterface t = extendedBoluses.get(tx); + if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; + if (t.getDuration() == 0) continue; + t.setY(getNearestBg((long) t.getX())); + filteredTreatments.add(t); + } + } + + // Careportal + List careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, true); + + for (int tx = 0; tx < careportalEvents.size(); tx++) { + DataPointWithLabelInterface t = careportalEvents.get(tx); + if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; + t.setY(getNearestBg((long) t.getX())); + filteredTreatments.add(t); + } + + DataPointWithLabelInterface[] treatmentsArray = new DataPointWithLabelInterface[filteredTreatments.size()]; + treatmentsArray = filteredTreatments.toArray(treatmentsArray); + if (treatmentsArray.length > 0) { + addSeriesWithoutInvalidate(bgGraph, new PointsWithLabelGraphSeries<>(treatmentsArray)); + } + } + + double getNearestBg(long date) { + double bg = 0; + for (int r = bgReadingsArray.size() - 1; r >= 0; r--) { + BgReading reading = bgReadingsArray.get(r); + if (reading.date > date) continue; + bg = Profile.fromMgdlToUnits(reading.value, units); + break; + } + return bg; + } + + // scale in % of vertical size (like 0.3) + public void addIob(GraphView graph, long fromTime, long toTime, boolean useForScale, double scale) { + FixedLineGraphSeries iobSeries; + List iobArray = new ArrayList<>(); + Double maxIobValueFound = 0d; + double lastIob = 0; + Scale iobScale = new Scale(); + + for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) { + double iob = IobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time).iob; + if (Math.abs(lastIob - iob) > 0.02) { + if (Math.abs(lastIob - iob) > 0.2) + iobArray.add(new ScaledDataPoint(time, lastIob, iobScale)); + iobArray.add(new ScaledDataPoint(time, iob, iobScale)); + maxIobValueFound = Math.max(maxIobValueFound, Math.abs(iob)); + lastIob = iob; + } + } + + ScaledDataPoint[] iobData = new ScaledDataPoint[iobArray.size()]; + iobData = iobArray.toArray(iobData); + iobSeries = new FixedLineGraphSeries<>(iobData); + iobSeries.setDrawBackground(true); + iobSeries.setBackgroundColor(0x80FFFFFF & MainApp.sResources.getColor(R.color.iob)); //50% + iobSeries.setColor(MainApp.sResources.getColor(R.color.iob)); + iobSeries.setThickness(3); + + if (useForScale) + maxY = maxIobValueFound; + + iobScale.setMultiplier(maxY * scale / maxIobValueFound); + + addSeriesWithoutInvalidate(graph, iobSeries); + } + + // scale in % of vertical size (like 0.3) + public void addCob(GraphView graph, long fromTime, long toTime, boolean useForScale, double scale) { + FixedLineGraphSeries cobSeries; + List cobArray = new ArrayList<>(); + Double maxCobValueFound = 0d; + int lastCob = 0; + Scale cobScale = new Scale(); + + for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) { + AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time); + if (autosensData != null) { + int cob = (int) autosensData.cob; + if (cob != lastCob) { + if (autosensData.carbsFromBolus > 0) + cobArray.add(new ScaledDataPoint(time, lastCob, cobScale)); + cobArray.add(new ScaledDataPoint(time, cob, cobScale)); + maxCobValueFound = Math.max(maxCobValueFound, cob); + lastCob = cob; + } + } + } + + // COB + ScaledDataPoint[] cobData = new ScaledDataPoint[cobArray.size()]; + cobData = cobArray.toArray(cobData); + cobSeries = new FixedLineGraphSeries<>(cobData); + cobSeries.setDrawBackground(true); + cobSeries.setBackgroundColor(0xB0FFFFFF & MainApp.sResources.getColor(R.color.cob)); //50% + cobSeries.setColor(MainApp.sResources.getColor(R.color.cob)); + cobSeries.setThickness(3); + + if (useForScale) + maxY = maxCobValueFound; + + cobScale.setMultiplier(maxY * scale / maxCobValueFound); + + addSeriesWithoutInvalidate(graph, cobSeries); + } + + // scale in % of vertical size (like 0.3) + public void addDeviations(GraphView graph, long fromTime, long toTime, boolean useForScale, double scale) { + class DeviationDataPoint extends ScaledDataPoint { + public int color; + + public DeviationDataPoint(double x, double y, int color, Scale scale) { + super(x, y, scale); + this.color = color; + } + } + + BarGraphSeries devSeries; + List devArray = new ArrayList<>(); + Double maxDevValueFound = 0d; + Scale devScale = new Scale(); + + for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) { + AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time); + if (autosensData != null) { + int color = Color.BLACK; // "=" + if (autosensData.pastSensitivity.equals("C")) color = Color.GRAY; + if (autosensData.pastSensitivity.equals("+")) color = Color.GREEN; + if (autosensData.pastSensitivity.equals("-")) color = Color.RED; + devArray.add(new DeviationDataPoint(time, autosensData.deviation, color, devScale)); + maxDevValueFound = Math.max(maxDevValueFound, Math.abs(autosensData.deviation)); + } + } + + // DEVIATIONS + DeviationDataPoint[] devData = new DeviationDataPoint[devArray.size()]; + devData = devArray.toArray(devData); + devSeries = new BarGraphSeries<>(devData); + devSeries.setValueDependentColor(new ValueDependentColor() { + @Override + public int get(DeviationDataPoint data) { + return data.color; + } + }); + + if (useForScale) + maxY = maxDevValueFound; + + devScale.setMultiplier(maxY * scale / maxDevValueFound); + + addSeriesWithoutInvalidate(graph, devSeries); + } + + // scale in % of vertical size (like 0.3) + public void addRatio(GraphView graph, long fromTime, long toTime, boolean useForScale, double scale) { + LineGraphSeries ratioSeries; + List ratioArray = new ArrayList<>(); + Double maxRatioValueFound = 0d; + Scale ratioScale = new Scale(-1d); + + for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) { + AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time); + if (autosensData != null) { + ratioArray.add(new DataPoint(time, autosensData.autosensRatio)); + maxRatioValueFound = Math.max(maxRatioValueFound, Math.abs(autosensData.autosensRatio)); + } + } + + // RATIOS + DataPoint[] ratioData = new DataPoint[ratioArray.size()]; + ratioData = ratioArray.toArray(ratioData); + ratioSeries = new LineGraphSeries<>(ratioData); + ratioSeries.setColor(MainApp.sResources.getColor(R.color.ratio)); + ratioSeries.setThickness(3); + + if (useForScale) + maxY = maxRatioValueFound; + + ratioScale.setMultiplier(maxY * scale / maxRatioValueFound); + + addSeriesWithoutInvalidate(graph, ratioSeries); + } + + // scale in % of vertical size (like 0.3) + public void addNowLine(GraphView graph, long now) { + LineGraphSeries seriesNow; + DataPoint[] nowPoints = new DataPoint[]{ + new DataPoint(now, 0), + new DataPoint(now, maxY) + }; + + seriesNow = new LineGraphSeries<>(nowPoints); + seriesNow.setDrawDataPoints(false); + // custom paint to make a dotted line + Paint paint = new Paint(); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(2); + paint.setPathEffect(new DashPathEffect(new float[]{10, 20}, 0)); + paint.setColor(Color.WHITE); + seriesNow.setCustomPaint(paint); + + addSeriesWithoutInvalidate(graph, seriesNow); + } + + public void formatAxis(GraphView graph, long fromTime, long endTime) { + graph.getViewport().setMaxX(endTime); + graph.getViewport().setMinX(fromTime); + graph.getViewport().setXAxisBoundsManual(true); + graph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter("HH")); + graph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space + } + + private void addSeriesWithoutInvalidate(GraphView bgGraph, Series s) { + if (!s.isEmpty()) { + s.onGraphViewAttached(bgGraph); + bgGraph.getSeries().add(s); + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/Scale.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/Scale.java new file mode 100644 index 0000000000..4aa1271679 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/Scale.java @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.plugins.Overview.graphExtensions; + +/** + * Created by mike on 18.10.2017. + */ + +public class Scale { + private double multiplier; + private double shift; + + public Scale() { + shift = 0; + } + + public Scale(double shift) { + this.shift = shift; + } + + public void setMultiplier(double value) { + this.multiplier = value; + } + + public double transform(double original) { + return original * multiplier + shift; + } + + public double getShift() { + return shift; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/ScaledDataPoint.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/ScaledDataPoint.java new file mode 100644 index 0000000000..61f4102a30 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/ScaledDataPoint.java @@ -0,0 +1,46 @@ +package info.nightscout.androidaps.plugins.Overview.graphExtensions; + +import com.jjoe64.graphview.series.DataPointInterface; + +import java.io.Serializable; +import java.util.Date; + +/** + * Created by mike on 18.10.2017. + */ + +public class ScaledDataPoint implements DataPointInterface, Serializable { + private static final long serialVersionUID=1428263342645L; + + private double x; + private double y; + + private Scale scale; + + public ScaledDataPoint(double x, double y, Scale scale) { + this.x=x; + this.y=y; + this.scale = scale; + } + + public ScaledDataPoint(Date x, double y, Scale scale) { + this.x = x.getTime(); + this.y = y; + this.scale = scale; + } + + @Override + public double getX() { + return x; + } + + @Override + public double getY() { + return scale.transform(y); + } + + @Override + public String toString() { + return "["+x+"/"+y+"]"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/TimeAsXAxisLabelFormatter.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/TimeAsXAxisLabelFormatter.java index 881e472a1d..323751e4c8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/TimeAsXAxisLabelFormatter.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/TimeAsXAxisLabelFormatter.java @@ -15,7 +15,7 @@ public class TimeAsXAxisLabelFormatter extends DefaultLabelFormatter { protected final String mFormat; - public TimeAsXAxisLabelFormatter(Context context, String format) { + public TimeAsXAxisLabelFormatter(String format) { mFormat = format; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/events/EventNSProfileUpdateGUI.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/events/EventNSProfileUpdateGUI.java index 7bb5df792f..d24c59e511 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/events/EventNSProfileUpdateGUI.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/events/EventNSProfileUpdateGUI.java @@ -1,7 +1,9 @@ package info.nightscout.androidaps.plugins.ProfileNS.events; +import info.nightscout.androidaps.events.EventUpdateGui; + /** * Created by mike on 05.08.2016. */ -public class EventNSProfileUpdateGUI { +public class EventNSProfileUpdateGUI extends EventUpdateGui { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java index d48013b0e6..0c4a5beded 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java @@ -226,7 +226,7 @@ public class DanaRFragment extends SubscriberFragment { Long agoMsec = System.currentTimeMillis() - pump.lastBolusTime.getTime(); double agoHours = agoMsec / 60d / 60d / 1000d; if (agoHours < 6) // max 6h back - lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + MainApp.sResources.getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(DanaRPump.getInstance().lastBolusAmount) + " U"); + lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " " + DateUtil.sinceString(pump.lastBolusTime.getTime()) + " " + DecimalFormatter.to2Decimal(DanaRPump.getInstance().lastBolusAmount) + " U"); else lastBolusView.setText(""); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRBolusStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRBolusStart.java index 8217b51432..9e3af48fb2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRBolusStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRBolusStart.java @@ -1,7 +1,9 @@ package info.nightscout.androidaps.plugins.PumpDanaR.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 03.08.2016. */ -public class EventDanaRBolusStart { +public class EventDanaRBolusStart extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRNewStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRNewStatus.java index a04f27f2d6..55b0ab0998 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRNewStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRNewStatus.java @@ -1,7 +1,9 @@ package info.nightscout.androidaps.plugins.PumpDanaR.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 08.07.2016. */ -public class EventDanaRNewStatus { +public class EventDanaRNewStatus extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRSyncStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRSyncStatus.java index b64cf22748..4e3f28de9d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRSyncStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRSyncStatus.java @@ -1,9 +1,11 @@ package info.nightscout.androidaps.plugins.PumpDanaR.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 20.07.2016. */ -public class EventDanaRSyncStatus { +public class EventDanaRSyncStatus extends Event { public String message; public EventDanaRSyncStatus() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/events/EventVirtualPumpUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/events/EventVirtualPumpUpdateGui.java index 110e0f4a56..e035ea3aba 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/events/EventVirtualPumpUpdateGui.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/events/EventVirtualPumpUpdateGui.java @@ -1,7 +1,9 @@ package info.nightscout.androidaps.plugins.PumpVirtual.events; +import info.nightscout.androidaps.events.EventUpdateGui; + /** * Created by mike on 05.08.2016. */ -public class EventVirtualPumpUpdateGui { +public class EventVirtualPumpUpdateGui extends EventUpdateGui { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventNewSMS.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventNewSMS.java index 2b890fb59c..dfaebb3942 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventNewSMS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventNewSMS.java @@ -2,10 +2,12 @@ package info.nightscout.androidaps.plugins.SmsCommunicator.events; import android.os.Bundle; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 13.07.2016. */ -public class EventNewSMS { +public class EventNewSMS extends Event { public Bundle bundle; public EventNewSMS(Bundle bundle) { this.bundle = bundle; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventSmsCommunicatorUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventSmsCommunicatorUpdateGui.java index 7c1d480e72..02956a5d67 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventSmsCommunicatorUpdateGui.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventSmsCommunicatorUpdateGui.java @@ -1,7 +1,9 @@ package info.nightscout.androidaps.plugins.SmsCommunicator.events; +import info.nightscout.androidaps.events.EventUpdateGui; + /** * Created by mike on 05.08.2016. */ -public class EventSmsCommunicatorUpdateGui { +public class EventSmsCommunicatorUpdateGui extends EventUpdateGui { } diff --git a/app/src/main/java/info/nightscout/utils/DateUtil.java b/app/src/main/java/info/nightscout/utils/DateUtil.java index 1e399ddd58..d2f35e0c99 100644 --- a/app/src/main/java/info/nightscout/utils/DateUtil.java +++ b/app/src/main/java/info/nightscout/utils/DateUtil.java @@ -146,4 +146,20 @@ public class DateUtil { } -} \ No newline at end of file + public static String timeFrameString(long timeInMillis){ + long remainingTimeMinutes = timeInMillis/(1000*60); + long remainingTimeHours = remainingTimeMinutes/60; + remainingTimeMinutes = remainingTimeMinutes%60; + return "(" + ((remainingTimeHours >0)?(remainingTimeHours + "h "):"") + remainingTimeMinutes + "')"; + } + + public static String sinceString(long timestamp){ + return timeFrameString(System.currentTimeMillis()-timestamp); + } + + public static String untilString(long timestamp){ + return timeFrameString(timestamp- System.currentTimeMillis()); + } + + +} diff --git a/app/src/main/java/info/nightscout/utils/NSUpload.java b/app/src/main/java/info/nightscout/utils/NSUpload.java index 98ce8632ff..e11102198f 100644 --- a/app/src/main/java/info/nightscout/utils/NSUpload.java +++ b/app/src/main/java/info/nightscout/utils/NSUpload.java @@ -404,4 +404,23 @@ public class NSUpload { DbLogger.dbAdd(intent, data.toString()); } } + + public static void removeFoodFromNS(String _id) { + try { + Context context = MainApp.instance().getApplicationContext(); + Bundle bundle = new Bundle(); + bundle.putString("action", "dbRemove"); + bundle.putString("collection", "food"); + bundle.putString("_id", _id); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + DbLogger.dbRemove(intent, _id); + } catch (Exception e) { + log.error("Unhandled exception", e); + } + + } + } diff --git a/app/src/main/res/layout/food_fragment.xml b/app/src/main/res/layout/food_fragment.xml new file mode 100644 index 0000000000..7b42eff11f --- /dev/null +++ b/app/src/main/res/layout/food_fragment.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/food_item.xml b/app/src/main/res/layout/food_item.xml new file mode 100644 index 0000000000..d4efc403a3 --- /dev/null +++ b/app/src/main/res/layout/food_item.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 32063b67b5..33cb62e062 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -70,7 +70,7 @@ No pump available No change requested Request - Rate + Rate Duration Reason Glucose @@ -685,10 +685,10 @@ Pass the Overview Notifications through as wear confirmation messages. Enable broadcasts to other apps (like xDrip). Enable local Broadcasts. - ACTIVITY & FEEDBACK - CARBS & BOLUS - CGM & OPENAPS - PUMP + ACTIVITY & FEEDBACK + CARBS & BOLUS + CGM & OPENAPS + PUMP Basal value [U/h] Duration [min] insulin_oref_peak @@ -746,6 +746,13 @@ Controls from Watch Set Temp-Targets and enter Treatments from the watch. Connection timed out + Food + g + ]]> + kJ + En + Pr + Fat ]]> Waiting for bolus end. Remaining %d sec. Processing event