Merge branch 'dev2' into queue

This commit is contained in:
Milos Kozak 2017-11-20 17:34:03 +01:00
commit d8d8b150b6
75 changed files with 1562 additions and 576 deletions

View file

@ -149,6 +149,7 @@ dependencies {
compile('com.github.tony19:logback-android-classic:1.1.1-6') { compile('com.github.tony19:logback-android-classic:1.1.1-6') {
exclude group: 'com.google.android', module: 'android' exclude group: 'com.google.android', module: 'android'
} }
compile 'org.apache.commons:commons-lang3:3.6'
compile 'org.slf4j:slf4j-api:1.7.12' compile 'org.slf4j:slf4j-api:1.7.12'
compile 'com.jjoe64:graphview:4.0.1' compile 'com.jjoe64:graphview:4.0.1'
compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.1.1' compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.1.1'

View file

@ -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<String, Set<String>> 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: <unknown>");
}
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<String>());
event2Receiver.get(key).add(receiverMethod);
} catch (ReflectiveOperationException e) {
log.debug(" receiver: <unknown>");
}
if (everyMinute < System.currentTimeMillis()) {
log.debug("***************** Event -> receiver pairings seen so far ****************");
for (Map.Entry<String, Set<String>> 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);
}
}

View file

@ -34,6 +34,7 @@ public class Config {
public static final boolean logPumpActions = true; public static final boolean logPumpActions = true;
public static final boolean logCongigBuilderActions = true; public static final boolean logCongigBuilderActions = true;
public static final boolean logAutosensData = false; public static final boolean logAutosensData = false;
public static final boolean logEvents = false;
// DanaR specific // DanaR specific
public static final boolean logDanaBTComm = true; public static final boolean logDanaBTComm = true;

View file

@ -13,6 +13,7 @@ import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
import com.j256.ormlite.android.apptools.OpenHelperManager; import com.j256.ormlite.android.apptools.OpenHelperManager;
import com.squareup.otto.Bus; import com.squareup.otto.Bus;
import com.squareup.otto.LoggingBus;
import com.squareup.otto.ThreadEnforcer; import com.squareup.otto.ThreadEnforcer;
import org.slf4j.Logger; 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.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin; 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.InsulinFastactingPlugin;
import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingProlongedPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingProlongedPlugin;
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin;
@ -103,7 +105,8 @@ public class MainApp extends Application {
log.info("Version: " + BuildConfig.VERSION_NAME); log.info("Version: " + BuildConfig.VERSION_NAME);
log.info("BuildVersion: " + BuildConfig.BUILDVERSION); log.info("BuildVersion: " + BuildConfig.BUILDVERSION);
sBus = new Bus(ThreadEnforcer.ANY); sBus = Config.logEvents ? new LoggingBus(ThreadEnforcer.ANY) : new Bus(ThreadEnforcer.ANY);
sInstance = this; sInstance = this;
sResources = getResources(); sResources = getResources();
@ -149,6 +152,7 @@ public class MainApp extends Application {
if (!Config.NSCLIENT) if (!Config.NSCLIENT)
pluginsList.add(SourceGlimpPlugin.getPlugin()); pluginsList.add(SourceGlimpPlugin.getPlugin());
if (Config.SMSCOMMUNICATORENABLED) pluginsList.add(SmsCommunicatorPlugin.getPlugin()); if (Config.SMSCOMMUNICATORENABLED) pluginsList.add(SmsCommunicatorPlugin.getPlugin());
pluginsList.add(FoodPlugin.getPlugin());
pluginsList.add(WearPlugin.initPlugin(this)); pluginsList.add(WearPlugin.initPlugin(this));
pluginsList.add(StatuslinePlugin.initPlugin(this)); pluginsList.add(StatuslinePlugin.initPlugin(this));
@ -165,14 +169,12 @@ public class MainApp extends Application {
else else
Answers.getInstance().logCustom(new CustomEvent("AppStart")); Answers.getInstance().logCustom(new CustomEvent("AppStart"));
startKeepAliveService();
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
SystemClock.sleep(5000); SystemClock.sleep(5000);
ConfigBuilderPlugin.getCommandQueue().readStatus("Initialization", null); ConfigBuilderPlugin.getCommandQueue().readStatus("Initialization", null);
startKeepAliveService();
} }
}).start(); }).start();
@ -183,6 +185,9 @@ public class MainApp extends Application {
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_TREATMENT)); 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_CHANGED_TREATMENT));
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_REMOVED_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_SGV));
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_PROFILE)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_PROFILE));
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_STATUS)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_STATUS));
@ -203,12 +208,6 @@ public class MainApp extends Application {
private void startKeepAliveService() { private void startKeepAliveService() {
if (keepAliveReceiver == null) { if (keepAliveReceiver == null) {
keepAliveReceiver = new KeepAliveReceiver(); 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); keepAliveReceiver.setAlarm(this);
} }
} }

View file

@ -1,6 +1,5 @@
package info.nightscout.androidaps; package info.nightscout.androidaps;
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.preference.EditTextPreference; import android.preference.EditTextPreference;
@ -23,7 +22,6 @@ import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin; import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin; import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.BluetoothDevicePreference;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
@ -46,7 +44,9 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
myPreferenceFragment = new MyPreferenceFragment(); myPreferenceFragment = new MyPreferenceFragment();
myPreferenceFragment.setCaller(getIntent()); Bundle args = new Bundle();
args.putInt("id", getIntent().getIntExtra("id", -1));
myPreferenceFragment.setArguments(args);
getFragmentManager().beginTransaction().replace(android.R.id.content, myPreferenceFragment).commit(); getFragmentManager().beginTransaction().replace(android.R.id.content, myPreferenceFragment).commit();
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this); PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
} }
@ -70,7 +70,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
} }
private static void updatePrefSummary(Preference pref) { private static void updatePrefSummary(Preference pref) {
if (pref instanceof ListPreference || pref instanceof BluetoothDevicePreference) { if (pref instanceof ListPreference) {
ListPreference listPref = (ListPreference) pref; ListPreference listPref = (ListPreference) pref;
pref.setSummary(listPref.getEntry()); pref.setSummary(listPref.getEntry());
} }
@ -83,14 +83,10 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
} else if (editTextPref.getText() != null && !editTextPref.getText().equals("")) { } else if (editTextPref.getText() != null && !editTextPref.getText().equals("")) {
((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage()); ((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage());
pref.setSummary(editTextPref.getText()); pref.setSummary(editTextPref.getText());
} else if (pref.getKey().contains("smscommunicator_allowednumbers") && TextUtils.isEmpty(editTextPref.getText().toString().trim())) { } else if (pref.getKey().contains("smscommunicator_allowednumbers") && TextUtils.isEmpty(editTextPref.getText().trim())) {
pref.setSummary(MainApp.sResources.getString(R.string.smscommunicator_allowednumbers_summary)); pref.setSummary(MainApp.sResources.getString(R.string.smscommunicator_allowednumbers_summary));
} }
} }
if (pref instanceof MultiSelectListPreference) {
EditTextPreference editTextPref = (EditTextPreference) pref;
pref.setSummary(editTextPref.getText());
}
} }
public static void initSummary(Preference p) { public static void initSummary(Preference p) {
@ -105,10 +101,12 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
} }
public static class MyPreferenceFragment extends PreferenceFragment { public static class MyPreferenceFragment extends PreferenceFragment {
Intent caller; private Integer id;
public void setCaller(Intent i) { @Override
caller = i; public void setArguments(Bundle args) {
super.setArguments(args);
id = args.getInt("id");
} }
void addPreferencesFromResourceIfEnabled(PluginBase p, int type) { void addPreferencesFromResourceIfEnabled(PluginBase p, int type) {
@ -120,7 +118,9 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
public void onCreate(final Bundle savedInstanceState) { public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Integer id = caller.getIntExtra("id", -1); if (savedInstanceState != null && savedInstanceState.containsKey("id")) {
id = savedInstanceState.getInt("id");
}
if (id != -1) { if (id != -1) {
addPreferencesFromResource(id); addPreferencesFromResource(id);
@ -184,6 +184,12 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
initSummary(getPreferenceScreen()); initSummary(getPreferenceScreen());
} }
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("id", id);
}
public Preference getPreference(String key) { public Preference getPreference(String key) {
return findPreference(key); return findPreference(key);
} }

View file

@ -116,6 +116,9 @@ public class DataService extends IntentService {
Intents.ACTION_REMOVED_TREATMENT.equals(action) || Intents.ACTION_REMOVED_TREATMENT.equals(action) ||
Intents.ACTION_NEW_STATUS.equals(action) || Intents.ACTION_NEW_STATUS.equals(action) ||
Intents.ACTION_NEW_DEVICESTATUS.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_CAL.equals(action) ||
Intents.ACTION_NEW_MBG.equals(action)) Intents.ACTION_NEW_MBG.equals(action))
) { ) {
@ -413,6 +416,56 @@ public class DataService extends IntentService {
log.error("Unhandled exception", e); 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) { private void handleRemovedRecordFromNS(String _id) {

View file

@ -87,6 +87,8 @@ public class FoodHelper {
log.debug("FOOD: Updating record by _id: " + old.toString()); log.debug("FOOD: Updating record by _id: " + old.toString());
scheduleFoodChange(); scheduleFoodChange();
return true; return true;
} else {
return false;
} }
} }
} }

View file

@ -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);
}
}

View file

@ -3,5 +3,5 @@ package info.nightscout.androidaps.events;
/** /**
* Created by mike on 07.07.2016. * Created by mike on 07.07.2016.
*/ */
public class EventAppExit { public class EventAppExit extends Event {
} }

View file

@ -4,7 +4,7 @@ package info.nightscout.androidaps.events;
* Created by adrian on 07/02/17. * Created by adrian on 07/02/17.
*/ */
public class EventBolusRequested { public class EventBolusRequested extends Event {
private double amount; private double amount;
public EventBolusRequested (double amount){ public EventBolusRequested (double amount){

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* Created by mike on 25.05.2017. * Created by mike on 25.05.2017.
*/ */
public class EventCareportalEventChange { public class EventCareportalEventChange extends Event {
} }

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* Created by mike on 17.02.2017. * Created by mike on 17.02.2017.
*/ */
public class EventConfigBuilderChange { public class EventConfigBuilderChange extends Event {
} }

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* Created by mike on 15.05.2017. * Created by mike on 15.05.2017.
*/ */
public class EventExtendedBolusChange { public class EventExtendedBolusChange extends Event {
} }

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* Created by mike on 20.09.2017. * Created by mike on 20.09.2017.
*/ */
public class EventFoodDatabaseChanged { public class EventFoodDatabaseChanged extends Event {
} }

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* Created by mike on 13.12.2016. * Created by mike on 13.12.2016.
*/ */
public class EventInitializationChanged { public class EventInitializationChanged extends Event {
} }

View file

@ -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 {
}

View file

@ -3,5 +3,5 @@ package info.nightscout.androidaps.events;
/** /**
* Created by mike on 05.06.2016. * Created by mike on 05.06.2016.
*/ */
public class EventNewBG { public class EventNewBG extends EventLoop {
} }

View file

@ -3,5 +3,5 @@ package info.nightscout.androidaps.events;
/** /**
* Created by mike on 04.06.2016. * Created by mike on 04.06.2016.
*/ */
public class EventNewBasalProfile { public class EventNewBasalProfile extends Event {
} }

View file

@ -5,7 +5,7 @@ import info.nightscout.androidaps.MainApp;
/** /**
* Created by mike on 19.06.2016. * Created by mike on 19.06.2016.
*/ */
public class EventPreferenceChange { public class EventPreferenceChange extends Event {
public String changedKey; public String changedKey;
public EventPreferenceChange(String key) { public EventPreferenceChange(String key) {
changedKey = key; changedKey = key;

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* Created by mike on 02.06.2017. * Created by mike on 02.06.2017.
*/ */
public class EventProfileSwitchChange { public class EventProfileSwitchChange extends Event {
} }

View file

@ -7,7 +7,7 @@ import info.nightscout.androidaps.R;
* Created by mike on 19.02.2017. * 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 CONNECTING = 0;
public static final int CONNECTED = 1; public static final int CONNECTED = 1;
public static final int PERFORMING = 2; public static final int PERFORMING = 2;

View file

@ -3,5 +3,5 @@ package info.nightscout.androidaps.events;
/** /**
* Created by mike on 13.06.2016. * Created by mike on 13.06.2016.
*/ */
public class EventRefreshGui { public class EventRefreshGui extends Event {
} }

View file

@ -4,7 +4,7 @@ package info.nightscout.androidaps.events;
* Created by mike on 16.06.2017. * Created by mike on 16.06.2017.
*/ */
public class EventRefreshOverview { public class EventRefreshOverview extends Event {
public String from; public String from;
public EventRefreshOverview(String from) { public EventRefreshOverview(String from) {

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* Created by mike on 12.06.2017. * Created by mike on 12.06.2017.
*/ */
public class EventReloadProfileSwitchData { public class EventReloadProfileSwitchData extends Event {
} }

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* Created by mike on 29.05.2017. * Created by mike on 29.05.2017.
*/ */
public class EventReloadTempBasalData { public class EventReloadTempBasalData extends Event {
} }

View file

@ -4,7 +4,7 @@ package info.nightscout.androidaps.events;
* Created by mike on 29.05.2017. * Created by mike on 29.05.2017.
*/ */
public class EventReloadTreatmentData { public class EventReloadTreatmentData extends Event {
public Object next; public Object next;
public EventReloadTreatmentData(Object next) { public EventReloadTreatmentData(Object next) {

View file

@ -3,5 +3,5 @@ package info.nightscout.androidaps.events;
/** /**
* Created by mike on 05.06.2016. * Created by mike on 05.06.2016.
*/ */
public class EventTempBasalChange { public class EventTempBasalChange extends EventLoop {
} }

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* Created by mike on 13.01.2017. * Created by mike on 13.01.2017.
*/ */
public class EventTempTargetChange { public class EventTempTargetChange extends Event {
} }

View file

@ -3,5 +3,5 @@ package info.nightscout.androidaps.events;
/** /**
* Created by mike on 04.06.2016. * Created by mike on 04.06.2016.
*/ */
public class EventTreatmentChange { public class EventTreatmentChange extends EventLoop {
} }

View file

@ -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 {
}

View file

@ -138,6 +138,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
if (options==null) return null;
getDialog().setTitle(getString(options.eventName)); getDialog().setTitle(getString(options.eventName));
setStyle(DialogFragment.STYLE_NORMAL, getTheme()); setStyle(DialogFragment.STYLE_NORMAL, getTheme());
View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false); View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false);

View file

@ -453,9 +453,13 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
@Override @Override
public boolean isThisProfileSet(Profile profile) { public boolean isThisProfileSet(Profile profile) {
if (activePump != null) if (activePump != null) {
return activePump.isThisProfileSet(profile); boolean result = activePump.isThisProfileSet(profile);
else return true; if (result == false) {
log.debug("Current profile: " + getProfile().getData().toString());
log.debug("New profile: " + profile.getData().toString());
}
} else return true;
} }
@Override @Override
@ -582,7 +586,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
if (Config.logCongigBuilderActions) if (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: " + request.toString()); log.debug("applyAPSRequest: " + request.toString());
if ((request.rate == 0 && request.duration == 0) || Math.abs(request.rate - getBaseBasalRate()) < 0.05) { if ((request.rate == 0 && request.duration == 0) || Math.abs(request.rate - getBaseBasalRate()) < getPumpDescription().basalStep) {
if (isTempBasalInProgress()) { if (isTempBasalInProgress()) {
if (Config.logCongigBuilderActions) if (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: cancelTempBasal()"); log.debug("applyAPSRequest: cancelTempBasal()");

View file

@ -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<Food> unfiltered;
List<Food> filtered;
ArrayList<CharSequence> categories;
ArrayList<CharSequence> 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<CharSequence> 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<CharSequence> 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<RecyclerViewAdapter.FoodsViewHolder> {
List<Food> foodList;
RecyclerViewAdapter(List<Food> 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;
}
}
}
}
}

View file

@ -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;
}
}

View file

@ -1,8 +1,10 @@
package info.nightscout.androidaps.plugins.IobCobCalculator.events; package info.nightscout.androidaps.plugins.IobCobCalculator.events;
import info.nightscout.androidaps.events.EventLoop;
/** /**
* Created by mike on 30.04.2017. * Created by mike on 30.04.2017.
*/ */
public class EventAutosensCalculationFinished { public class EventAutosensCalculationFinished extends EventLoop {
} }

View file

@ -1,10 +1,12 @@
package info.nightscout.androidaps.plugins.IobCobCalculator.events; package info.nightscout.androidaps.plugins.IobCobCalculator.events;
import info.nightscout.androidaps.events.Event;
/** /**
* Created by mike on 26.04.2017. * Created by mike on 26.04.2017.
*/ */
public class EventNewHistoryData { public class EventNewHistoryData extends Event {
public long time = 0; public long time = 0;
public EventNewHistoryData(long time) { public EventNewHistoryData(long time) {

View file

@ -1,9 +1,11 @@
package info.nightscout.androidaps.plugins.Loop.events; package info.nightscout.androidaps.plugins.Loop.events;
import info.nightscout.androidaps.events.EventUpdateGui;
/** /**
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
*/ */
public class EventLoopSetLastRunGui { public class EventLoopSetLastRunGui extends EventUpdateGui {
public String text = null; public String text = null;
public EventLoopSetLastRunGui(String text) { public EventLoopSetLastRunGui(String text) {

View file

@ -1,7 +1,9 @@
package info.nightscout.androidaps.plugins.Loop.events; package info.nightscout.androidaps.plugins.Loop.events;
import info.nightscout.androidaps.events.EventUpdateGui;
/** /**
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
*/ */
public class EventLoopUpdateGui { public class EventLoopUpdateGui extends EventUpdateGui {
} }

View file

@ -1,7 +1,9 @@
package info.nightscout.androidaps.plugins.Loop.events; package info.nightscout.androidaps.plugins.Loop.events;
import info.nightscout.androidaps.events.Event;
/** /**
* Created by mike on 07.08.2016. * Created by mike on 07.08.2016.
*/ */
public class EventNewOpenLoopNotification { public class EventNewOpenLoopNotification extends Event {
} }

View file

@ -7,14 +7,14 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp; 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.events.EventNSClientRestart;
import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService;
import io.socket.client.Ack; import io.socket.client.Ack;
/** /**
* Created by mike on 29.12.2015. * 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); private static Logger log = LoggerFactory.getLogger(NSAddAck.class);
public String _id = null; public String _id = null;
public String nsClientID = null; public String nsClientID = null;

View file

@ -3,13 +3,14 @@ package info.nightscout.androidaps.plugins.NSClientInternal.acks;
import org.json.JSONObject; import org.json.JSONObject;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog;
import io.socket.client.Ack; import io.socket.client.Ack;
/** /**
* Created by mike on 02.01.2016. * 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 read = false;
public boolean write = false; public boolean write = false;
public boolean write_treatment = false; public boolean write_treatment = false;

View file

@ -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();
}
}
}

View file

@ -6,12 +6,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.events.Event;
import io.socket.client.Ack; import io.socket.client.Ack;
/** /**
* Created by mike on 21.02.2016. * 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); private static Logger log = LoggerFactory.getLogger(NSUpdateAck.class);
public boolean result = false; public boolean result = false;
public String _id = null; public String _id = null;

View file

@ -336,7 +336,9 @@ public class NSDeviceStatus {
try { try {
long clock = 0L; long clock = 0L;
if (object.has("created_at")) if (object.has("mills"))
clock = object.getLong("mills");
else if (object.has("created_at"))
clock = DateUtil.fromISODateString(object.getString("created_at")).getTime(); clock = DateUtil.fromISODateString(object.getString("created_at")).getTime();
String device = getDevice(); String device = getDevice();
Integer battery = null; Integer battery = null;

View file

@ -1,19 +1,15 @@
package info.nightscout.androidaps.plugins.NSClientInternal.events; 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.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import info.nightscout.androidaps.events.Event;
/** /**
* Created by mike on 15.02.2017. * Created by mike on 15.02.2017.
*/ */
public class EventNSClientNewLog { public class EventNSClientNewLog extends Event {
public Date date = new Date(); public Date date = new Date();
public String action; public String action;
public String logText; public String logText;

View file

@ -1,8 +1,10 @@
package info.nightscout.androidaps.plugins.NSClientInternal.events; package info.nightscout.androidaps.plugins.NSClientInternal.events;
import info.nightscout.androidaps.events.Event;
/** /**
* Created by mike on 15.02.2017. * Created by mike on 15.02.2017.
*/ */
public class EventNSClientRestart { public class EventNSClientRestart extends Event {
} }

View file

@ -1,9 +1,11 @@
package info.nightscout.androidaps.plugins.NSClientInternal.events; package info.nightscout.androidaps.plugins.NSClientInternal.events;
import info.nightscout.androidaps.events.Event;
/** /**
* Created by mike on 02.01.2016. * Created by mike on 02.01.2016.
*/ */
public class EventNSClientStatus { public class EventNSClientStatus extends Event {
public String status = ""; public String status = "";
public EventNSClientStatus(String status) { public EventNSClientStatus(String status) {

View file

@ -1,8 +1,10 @@
package info.nightscout.androidaps.plugins.NSClientInternal.events; package info.nightscout.androidaps.plugins.NSClientInternal.events;
import info.nightscout.androidaps.events.EventUpdateGui;
/** /**
* Created by mike on 17.02.2017. * Created by mike on 17.02.2017.
*/ */
public class EventNSClientUpdateGUI { public class EventNSClientUpdateGUI extends EventUpdateGui {
} }

View file

@ -1,7 +1,9 @@
package info.nightscout.androidaps.plugins.OpenAPSMA.events; package info.nightscout.androidaps.plugins.OpenAPSMA.events;
import info.nightscout.androidaps.events.EventUpdateGui;
/** /**
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
*/ */
public class EventOpenAPSUpdateGui { public class EventOpenAPSUpdateGui extends EventUpdateGui {
} }

View file

@ -1,9 +1,11 @@
package info.nightscout.androidaps.plugins.OpenAPSMA.events; package info.nightscout.androidaps.plugins.OpenAPSMA.events;
import info.nightscout.androidaps.events.EventUpdateGui;
/** /**
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
*/ */
public class EventOpenAPSUpdateResultGui { public class EventOpenAPSUpdateResultGui extends EventUpdateGui {
public String text = null; public String text = null;
public EventOpenAPSUpdateResultGui(String text) { public EventOpenAPSUpdateResultGui(String text) {

View file

@ -37,9 +37,7 @@ import com.crashlytics.android.Crashlytics;
import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
import com.jjoe64.graphview.GraphView; import com.jjoe64.graphview.GraphView;
import com.jjoe64.graphview.LabelFormatter;
import com.jjoe64.graphview.ValueDependentColor; import com.jjoe64.graphview.ValueDependentColor;
import com.jjoe64.graphview.Viewport;
import com.jjoe64.graphview.series.BarGraphSeries; import com.jjoe64.graphview.series.BarGraphSeries;
import com.jjoe64.graphview.series.DataPoint; import com.jjoe64.graphview.series.DataPoint;
import com.jjoe64.graphview.series.LineGraphSeries; import com.jjoe64.graphview.series.LineGraphSeries;
@ -55,7 +53,6 @@ import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.Executors; 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.CareportalEvent;
import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventCareportalEventChange; import info.nightscout.androidaps.events.EventCareportalEventChange;
import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventExtendedBolusChange;
import info.nightscout.androidaps.events.EventInitializationChanged; 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.ConstraintsObjectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; 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.IobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification; import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
@ -114,11 +108,8 @@ import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog;
import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog; import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock; import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.AreaGraphSeries; import info.nightscout.androidaps.plugins.Overview.graphData.GraphData;
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.FixedLineGraphSeries;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter; import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter;
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin; import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
import info.nightscout.androidaps.plugins.Treatments.fragments.ProfileViewerDialog; import info.nightscout.androidaps.plugins.Treatments.fragments.ProfileViewerDialog;
@ -129,7 +120,6 @@ import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.NSUpload; import info.nightscout.utils.NSUpload;
import info.nightscout.utils.OKDialog; import info.nightscout.utils.OKDialog;
import info.nightscout.utils.Profiler; import info.nightscout.utils.Profiler;
import info.nightscout.utils.Round;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
import info.nightscout.utils.ToastUtils; import info.nightscout.utils.ToastUtils;
@ -928,8 +918,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
return; return;
} }
Double lowLine = SP.getDouble("low_mark", 0d); double lowLine = SP.getDouble("low_mark", 0d);
Double highLine = SP.getDouble("high_mark", 0d); double highLine = SP.getDouble("high_mark", 0d);
//Start with updating the BG as it is unaffected by loop. //Start with updating the BG as it is unaffected by loop.
// **** BG value **** // **** BG value ****
@ -996,7 +986,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
tempTargetView.setTextColor(Color.BLACK); tempTargetView.setTextColor(Color.BLACK);
tempTargetView.setBackgroundColor(MainApp.sResources.getColor(R.color.tempTargetBackground)); tempTargetView.setBackgroundColor(MainApp.sResources.getColor(R.color.tempTargetBackground));
tempTargetView.setVisibility(View.VISIBLE); 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 { } else {
tempTargetView.setTextColor(Color.WHITE); tempTargetView.setTextColor(Color.WHITE);
tempTargetView.setBackgroundColor(MainApp.sResources.getColor(R.color.tempTargetDisabledBackground)); tempTargetView.setBackgroundColor(MainApp.sResources.getColor(R.color.tempTargetDisabledBackground));
@ -1240,7 +1230,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
} }
// ****** GRAPH ******* // ****** GRAPH *******
//log.debug("updateGUI checkpoint 1");
// allign to hours // allign to hours
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance();
@ -1269,464 +1258,82 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
endTime = toTime; endTime = toTime;
} }
LineGraphSeries<DataPoint> basalsLineSeries = null;
LineGraphSeries<DataPoint> absoluteBasalsLineSeries = null;
LineGraphSeries<DataPoint> baseBasalsSeries = null;
LineGraphSeries<DataPoint> tempBasalsSeries = null;
AreaGraphSeries<DoubleDataPoint> areaSeries;
LineGraphSeries<DataPoint> seriesNow, seriesNow2;
// **** TEMP BASALS graph ****
Double maxBasalValueFound = 0d;
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) {
List<DataPoint> baseBasalArray = new ArrayList<>();
List<DataPoint> tempBasalArray = new ArrayList<>();
List<DataPoint> basalLineArray = new ArrayList<>();
List<DataPoint> 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) { // 2nd graph
basalLineArray.add(new DataPoint(time, lastLineBasal)); // remove old data
basalLineArray.add(new DataPoint(time, baseBasalValue)); iobGraph.getSeries().clear();
}
if (absoluteLineValue != lastAbsoluteLineBasal) {
absoluteBasalLineArray.add(new DataPoint(time, lastAbsoluteLineBasal));
absoluteBasalLineArray.add(new DataPoint(time, basal));
}
lastAbsoluteLineBasal = absoluteLineValue; GraphData secondGraphData = new GraphData();
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));
DataPoint[] baseBasal = new DataPoint[baseBasalArray.size()]; boolean useIobForScale = false;
baseBasal = baseBasalArray.toArray(baseBasal); boolean useCobForScale = false;
baseBasalsSeries = new LineGraphSeries<>(baseBasal); boolean useDevForScale = false;
baseBasalsSeries.setDrawBackground(true); boolean useRatioForScale = false;
baseBasalsSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.basebasal));
baseBasalsSeries.setThickness(0);
DataPoint[] tempBasal = new DataPoint[tempBasalArray.size()]; if (showIobView.isChecked()) {
tempBasal = tempBasalArray.toArray(tempBasal); useIobForScale = true;
tempBasalsSeries = new LineGraphSeries<>(tempBasal); } else if (showCobView.isChecked()) {
tempBasalsSeries.setDrawBackground(true); useCobForScale = true;
tempBasalsSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.tempbasal)); } else if (showDeviationsView.isChecked()) {
tempBasalsSeries.setThickness(0); useDevForScale = true;
} else if (showRatiosView.isChecked()) {
DataPoint[] basalLine = new DataPoint[basalLineArray.size()]; useRatioForScale = true;
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);
} }
//log.debug("updateGUI checkpoint 2"); if (showIobView.isChecked())
secondGraphData.addIob(iobGraph, fromTime, now, useIobForScale, 1d);
// **** IOB COB DEV graph **** if (showCobView.isChecked())
class DeviationDataPoint extends DataPoint { secondGraphData.addCob(iobGraph, fromTime, now, useCobForScale, useCobForScale ? 1d : 0.5d);
public int color; if (showDeviationsView.isChecked())
secondGraphData.addDeviations(iobGraph, fromTime, now, useDevForScale, 1d);
public DeviationDataPoint(double x, double y, int color) { if (showRatiosView.isChecked())
super(x, y); secondGraphData.addRatio(iobGraph, fromTime, now, useRatioForScale, 1d);
this.color = color;
}
}
FixedLineGraphSeries<DataPoint> iobSeries;
FixedLineGraphSeries<DataPoint> cobSeries;
BarGraphSeries<DeviationDataPoint> devSeries;
LineGraphSeries<DataPoint> ratioSeries;
Double maxIobValueFound = 0d;
Double maxCobValueFound = 0d;
Double maxDevValueFound = 0d;
Double maxRatioValueFound = 0d;
if (showIobView.isChecked() || showCobView.isChecked() || showDeviationsView.isChecked() || showRatiosView.isChecked()) { if (showIobView.isChecked() || showCobView.isChecked() || showDeviationsView.isChecked() || showRatiosView.isChecked()) {
//Date start = new Date();
List<DataPoint> iobArray = new ArrayList<>();
List<DataPoint> cobArray = new ArrayList<>();
List<DeviationDataPoint> devArray = new ArrayList<>();
List<DataPoint> 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<DataPoint> 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<DeviationDataPoint> 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<DataPoint> 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<DeviationDataPoint>() {
@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); iobGraph.setVisibility(View.VISIBLE);
} else { } else {
iobGraph.setVisibility(View.GONE); iobGraph.setVisibility(View.GONE);
} }
//log.debug("updateGUI checkpoint 3");
// remove old data from graph // remove old data from graph
bgGraph.getSecondScale().getSeries().clear();
bgGraph.getSeries().clear(); bgGraph.getSeries().clear();
//log.debug("updateGUI checkpoint 4");
// **** Area **** GraphData graphData = new GraphData();
DoubleDataPoint[] areaDataPoints = new DoubleDataPoint[]{
new DoubleDataPoint(fromTime, lowLine, highLine), // **** In range Area ****
new DoubleDataPoint(endTime, lowLine, highLine) graphData.addInRangeArea(bgGraph, fromTime, endTime, lowLine, highLine);
};
areaSeries = new AreaGraphSeries<>(areaDataPoints); // **** BG ****
addSeriesWithoutInvalidate(areaSeries, bgGraph); if (showPrediction)
areaSeries.setColor(0); graphData.addBgReadings(bgGraph, fromTime, toTime, lowLine, highLine, (DetermineBasalResultAMA) finalLastRun.constraintsProcessed);
areaSeries.setDrawBackground(true); else
areaSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.inrangebackground)); graphData.addBgReadings(bgGraph, fromTime, toTime, lowLine, highLine, null);
// set manual x bounds to have nice steps // set manual x bounds to have nice steps
bgGraph.getViewport().setMaxX(endTime); graphData.formatAxis(bgGraph, fromTime, endTime);
bgGraph.getViewport().setMinX(fromTime); secondGraphData.formatAxis(iobGraph, fromTime, endTime);
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
//log.debug("updateGUI checkpoint 5");
// **** BG graph ****
List<BgReading> bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true);
List<DataPointWithLabelInterface> bgListArray = new ArrayList<>();
if (bgReadingsArray.size() == 0) {
return;
}
Iterator<BgReading> 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<BgReading> 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 // Treatments
List<DataPointWithLabelInterface> filteredTreatments = new ArrayList<>(); graphData.addTreatments(bgGraph, fromTime, endTime);
List<Treatment> treatments = MainApp.getConfigBuilder().getTreatmentsFromHistory(); // add basal data
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<ProfileSwitch> 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<ExtendedBolus> 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<CareportalEvent> 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
if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) { if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) {
bgGraph.getSecondScale().setMinY(0); graphData.addBasals(bgGraph, fromTime, now, lowLine / graphData.maxY / 1.2d);
bgGraph.getSecondScale().setMaxY(maxBgValue / lowLine * maxBasalValueFound * 1.2d);
bgGraph.getSecondScale().addSeries(baseBasalsSeries);
bgGraph.getSecondScale().addSeries(tempBasalsSeries);
bgGraph.getSecondScale().addSeries(basalsLineSeries);
bgGraph.getSecondScale().addSeries(absoluteBasalsLineSeries);
} }
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 **** // **** NOW line ****
DataPoint[] nowPoints = new DataPoint[]{ graphData.addNowLine(bgGraph, now);
new DataPoint(now, 0), secondGraphData.addNowLine(iobGraph, now);
new DataPoint(now, maxBgValue)
}; // finaly enforce drawing of graphs
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);
bgGraph.onDataChanged(false, false); bgGraph.onDataChanged(false, false);
iobGraph.onDataChanged(false, false); iobGraph.onDataChanged(false, false);
Profiler.log(log, from, updateGUIStart); Profiler.log(log, from, updateGUIStart);
} }
public double getNearestBg(long date, List<BgReading> 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 //Notifications
static class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.NotificationsViewHolder> { static class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.NotificationsViewHolder> {

View file

@ -1,12 +1,13 @@
package info.nightscout.androidaps.plugins.Overview.events; package info.nightscout.androidaps.plugins.Overview.events;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.events.Event;
/** /**
* Created by adrian on 20/02/17. * Created by adrian on 20/02/17.
*/ */
public class EventDismissBolusprogressIfRunning { public class EventDismissBolusprogressIfRunning extends Event {
public final PumpEnactResult result; public final PumpEnactResult result;
public EventDismissBolusprogressIfRunning(PumpEnactResult result) { public EventDismissBolusprogressIfRunning(PumpEnactResult result) {

View file

@ -1,10 +1,12 @@
package info.nightscout.androidaps.plugins.Overview.events; package info.nightscout.androidaps.plugins.Overview.events;
import info.nightscout.androidaps.events.Event;
/** /**
* Created by mike on 03.12.2016. * Created by mike on 03.12.2016.
*/ */
public class EventDismissNotification { public class EventDismissNotification extends Event {
public int id; public int id;
public EventDismissNotification(int did) { public EventDismissNotification(int did) {

View file

@ -1,12 +1,13 @@
package info.nightscout.androidaps.plugins.Overview.events; package info.nightscout.androidaps.plugins.Overview.events;
import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.Notification;
/** /**
* Created by mike on 03.12.2016. * Created by mike on 03.12.2016.
*/ */
public class EventNewNotification { public class EventNewNotification extends Event {
public Notification notification; public Notification notification;
public EventNewNotification(Notification n) { public EventNewNotification(Notification n) {

View file

@ -4,8 +4,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.db.Treatment; 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); private static Logger log = LoggerFactory.getLogger(EventOverviewBolusProgress.class);
public String status = ""; public String status = "";
public Treatment t = null; public Treatment t = null;

View file

@ -1,8 +1,10 @@
package info.nightscout.androidaps.plugins.Overview.events; package info.nightscout.androidaps.plugins.Overview.events;
import info.nightscout.androidaps.events.Event;
/** /**
* Created by mike on 20.10.2016. * Created by mike on 20.10.2016.
*/ */
public class EventQuickWizardChange { public class EventQuickWizardChange extends Event {
} }

View file

@ -1,10 +1,12 @@
package info.nightscout.androidaps.plugins.Overview.events; package info.nightscout.androidaps.plugins.Overview.events;
import info.nightscout.androidaps.events.Event;
/** /**
* Created by mike on 02.07.2017. * Created by mike on 02.07.2017.
*/ */
public class EventSetWakeLock { public class EventSetWakeLock extends Event {
public boolean lock = false; public boolean lock = false;
public EventSetWakeLock(boolean val) { public EventSetWakeLock(boolean val) {

View file

@ -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<BgReading> 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<DataPointWithLabelInterface> bgListArray = new ArrayList<>();
if (bgReadingsArray.size() == 0) {
return;
}
Iterator<BgReading> it = bgReadingsArray.iterator();
while (it.hasNext()) {
BgReading bg = it.next();
if (bg.value > maxBgValue) maxBgValue = bg.value;
bgListArray.add(bg);
}
if (amaResult != null) {
List<BgReading> 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<DoubleDataPoint> 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<ScaledDataPoint> basalsLineSeries;
LineGraphSeries<ScaledDataPoint> absoluteBasalsLineSeries;
LineGraphSeries<ScaledDataPoint> baseBasalsSeries;
LineGraphSeries<ScaledDataPoint> tempBasalsSeries;
double maxBasalValueFound = 0d;
Scale basalScale = new Scale();
List<ScaledDataPoint> baseBasalArray = new ArrayList<>();
List<ScaledDataPoint> tempBasalArray = new ArrayList<>();
List<ScaledDataPoint> basalLineArray = new ArrayList<>();
List<ScaledDataPoint> 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<DataPointWithLabelInterface> filteredTreatments = new ArrayList<>();
List<Treatment> 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<ProfileSwitch> 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<ExtendedBolus> 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<CareportalEvent> 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<ScaledDataPoint> iobSeries;
List<ScaledDataPoint> 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<ScaledDataPoint> cobSeries;
List<ScaledDataPoint> 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<DeviationDataPoint> devSeries;
List<DeviationDataPoint> 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<DeviationDataPoint>() {
@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<DataPoint> ratioSeries;
List<DataPoint> 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<DataPoint> 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);
}
}
}

View file

@ -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;
}
}

View file

@ -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+"]";
}
}

View file

@ -15,7 +15,7 @@ public class TimeAsXAxisLabelFormatter extends DefaultLabelFormatter {
protected final String mFormat; protected final String mFormat;
public TimeAsXAxisLabelFormatter(Context context, String format) { public TimeAsXAxisLabelFormatter(String format) {
mFormat = format; mFormat = format;
} }

View file

@ -1,7 +1,9 @@
package info.nightscout.androidaps.plugins.ProfileNS.events; package info.nightscout.androidaps.plugins.ProfileNS.events;
import info.nightscout.androidaps.events.EventUpdateGui;
/** /**
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
*/ */
public class EventNSProfileUpdateGUI { public class EventNSProfileUpdateGUI extends EventUpdateGui {
} }

View file

@ -223,7 +223,7 @@ public class DanaRFragment extends SubscriberFragment {
Long agoMsec = System.currentTimeMillis() - pump.lastBolusTime.getTime(); Long agoMsec = System.currentTimeMillis() - pump.lastBolusTime.getTime();
double agoHours = agoMsec / 60d / 60d / 1000d; double agoHours = agoMsec / 60d / 60d / 1000d;
if (agoHours < 6) // max 6h back 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(""); else lastBolusView.setText("");
} }

View file

@ -1,7 +1,9 @@
package info.nightscout.androidaps.plugins.PumpDanaR.events; package info.nightscout.androidaps.plugins.PumpDanaR.events;
import info.nightscout.androidaps.events.Event;
/** /**
* Created by mike on 03.08.2016. * Created by mike on 03.08.2016.
*/ */
public class EventDanaRBolusStart { public class EventDanaRBolusStart extends Event {
} }

View file

@ -1,7 +1,9 @@
package info.nightscout.androidaps.plugins.PumpDanaR.events; package info.nightscout.androidaps.plugins.PumpDanaR.events;
import info.nightscout.androidaps.events.Event;
/** /**
* Created by mike on 08.07.2016. * Created by mike on 08.07.2016.
*/ */
public class EventDanaRNewStatus { public class EventDanaRNewStatus extends Event {
} }

View file

@ -1,9 +1,11 @@
package info.nightscout.androidaps.plugins.PumpDanaR.events; package info.nightscout.androidaps.plugins.PumpDanaR.events;
import info.nightscout.androidaps.events.Event;
/** /**
* Created by mike on 20.07.2016. * Created by mike on 20.07.2016.
*/ */
public class EventDanaRSyncStatus { public class EventDanaRSyncStatus extends Event {
public String message; public String message;
public EventDanaRSyncStatus() { public EventDanaRSyncStatus() {

View file

@ -1,7 +1,9 @@
package info.nightscout.androidaps.plugins.PumpVirtual.events; package info.nightscout.androidaps.plugins.PumpVirtual.events;
import info.nightscout.androidaps.events.EventUpdateGui;
/** /**
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
*/ */
public class EventVirtualPumpUpdateGui { public class EventVirtualPumpUpdateGui extends EventUpdateGui {
} }

View file

@ -2,10 +2,12 @@ package info.nightscout.androidaps.plugins.SmsCommunicator.events;
import android.os.Bundle; import android.os.Bundle;
import info.nightscout.androidaps.events.Event;
/** /**
* Created by mike on 13.07.2016. * Created by mike on 13.07.2016.
*/ */
public class EventNewSMS { public class EventNewSMS extends Event {
public Bundle bundle; public Bundle bundle;
public EventNewSMS(Bundle bundle) { public EventNewSMS(Bundle bundle) {
this.bundle = bundle; this.bundle = bundle;

View file

@ -1,7 +1,9 @@
package info.nightscout.androidaps.plugins.SmsCommunicator.events; package info.nightscout.androidaps.plugins.SmsCommunicator.events;
import info.nightscout.androidaps.events.EventUpdateGui;
/** /**
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
*/ */
public class EventSmsCommunicatorUpdateGui { public class EventSmsCommunicatorUpdateGui extends EventUpdateGui {
} }

View file

@ -27,8 +27,8 @@ public class DateUtil {
/** /**
* The date format in iso. * The date format in iso.
*/ */
private static String FORMAT_DATE_ISO = "yyyy-MM-dd'T'HH:mm:ss'Z'"; private static String FORMAT_DATE_ISO = "yyyy-MM-dd'T'HH:mm:ssZ";
private static String FORMAT_DATE_ISO_MSEC = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; private static String FORMAT_DATE_ISO_MSEC = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
/** /**
* Takes in an ISO date string of the following format: * Takes in an ISO date string of the following format:
@ -146,4 +146,20 @@ public class DateUtil {
} }
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());
}
} }

View file

@ -404,4 +404,23 @@ public class NSUpload {
DbLogger.dbAdd(intent, data.toString()); 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);
}
}
} }

View file

@ -0,0 +1,90 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsExtendedBolusesFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/foodSearchImage"
android:layout_width="wrap_content"
android:paddingLeft="5dp"
android:paddingRight="5dp"
app:srcCompat="@android:drawable/ic_menu_search"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/food_filter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:inputType="text"
android:text="" />
<ImageView
android:id="@+id/food_clearfilter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="5dp"
android:paddingRight="5dp"
app:srcCompat="@android:drawable/ic_menu_close_clear_cancel" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Category" />
<Spinner
android:id="@+id/food_category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right"
android:minWidth="100dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Subcategory" />
<Spinner
android:id="@+id/food_subcategory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right"
android:minWidth="100dp" />
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/food_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
</FrameLayout>

View file

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/food_cardview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
card_view:cardBackgroundColor="@color/cardColorBackground"
card_view:cardCornerRadius="6dp"
card_view:cardUseCompatPadding="true"
card_view:contentPadding="6dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:id="@+id/food_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="textMultiLine|textNoSuggestions"
android:text="Name"
android:textStyle="bold" />
<TextView
android:id="@+id/food_portion"
android:layout_width="60dp"
android:layout_height="wrap_content"
android:gravity="end"
android:text="Portion" />
<TextView
android:id="@+id/food_carbs"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:gravity="end"
android:text="Carbs" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="end"
android:orientation="horizontal">
<TextView
android:id="@+id/food_fat"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:gravity="end"
android:text="Fat" />
<TextView
android:id="@+id/food_protein"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:gravity="end"
android:text="Protein" />
<TextView
android:id="@+id/food_energy"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:gravity="end"
android:text="Energy" />
<TextView
android:id="@+id/ns_sign"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="30dp"
android:text="NS"
android:textAlignment="viewEnd"
android:textColor="@color/colorSetTempButton" />
<TextView
android:id="@+id/food_remove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingEnd="5dp"
android:paddingStart="10dp"
android:text="@string/overview_quickwizard_item_remove_button"
android:textAlignment="viewEnd"
android:textColor="@android:color/holo_orange_light" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>

View file

@ -70,7 +70,7 @@
<string name="openapsma_nopump">No pump available</string> <string name="openapsma_nopump">No pump available</string>
<string name="nochangerequested">No change requested</string> <string name="nochangerequested">No change requested</string>
<string name="openapsma_request_label">Request</string> <string name="openapsma_request_label">Request</string>
<string name="rate">Rate</string> <string name="rate">Rate</string>
<string name="duration">Duration</string> <string name="duration">Duration</string>
<string name="reason">Reason</string> <string name="reason">Reason</string>
<string name="glucose">Glucose</string> <string name="glucose">Glucose</string>
@ -685,10 +685,10 @@
<string name="wear_overviewnotifications_summary">Pass the Overview Notifications through as wear confirmation messages.</string> <string name="wear_overviewnotifications_summary">Pass the Overview Notifications through as wear confirmation messages.</string>
<string name="ns_localbroadcasts">Enable broadcasts to other apps (like xDrip).</string> <string name="ns_localbroadcasts">Enable broadcasts to other apps (like xDrip).</string>
<string name="ns_localbroadcasts_title">Enable local Broadcasts.</string> <string name="ns_localbroadcasts_title">Enable local Broadcasts.</string>
<string name="careportal_activity_label">ACTIVITY &amp; FEEDBACK</string> <string name="careportal_activity_label">ACTIVITY &amp; FEEDBACK</string>
<string name="careportal_carbsandbolus_label">CARBS &amp; BOLUS</string> <string name="careportal_carbsandbolus_label">CARBS &amp; BOLUS</string>
<string name="careportal_cgm_label">CGM &amp; OPENAPS</string> <string name="careportal_cgm_label">CGM &amp; OPENAPS</string>
<string name="careportal_pump_label">PUMP</string> <string name="careportal_pump_label">PUMP</string>
<string name="overview_newtempbasal_basalabsolute">Basal value [U/h]</string> <string name="overview_newtempbasal_basalabsolute">Basal value [U/h]</string>
<string name="careportal_newnstreatment_duration_min_label">Duration [min]</string> <string name="careportal_newnstreatment_duration_min_label">Duration [min]</string>
<string name="key_insulin_oref_peak" translatable="false">insulin_oref_peak</string> <string name="key_insulin_oref_peak" translatable="false">insulin_oref_peak</string>
@ -746,6 +746,13 @@
<string name="wearcontrol_title">Controls from Watch</string> <string name="wearcontrol_title">Controls from Watch</string>
<string name="wearcontrol_summary">Set Temp-Targets and enter Treatments from the watch.</string> <string name="wearcontrol_summary">Set Temp-Targets and enter Treatments from the watch.</string>
<string name="connectiontimedout">Connection timed out</string> <string name="connectiontimedout">Connection timed out</string>
<string name="food">Food</string>
<string name="shortgramm">g</string>
<string name="none"><![CDATA[<none>]]></string>
<string name="shortkilojoul">kJ</string>
<string name="shortenergy">En</string>
<string name="shortprotein">Pr</string>
<string name="shortfat">Fat</string>
<string name="active"><![CDATA[<Active>]]></string> <string name="active"><![CDATA[<Active>]]></string>
<string name="waitingforestimatedbolusend" formatted="false">Waiting for bolus end. Remaining %d sec.</string> <string name="waitingforestimatedbolusend" formatted="false">Waiting for bolus end. Remaining %d sec.</string>
<string name="processinghistory">Processing event</string> <string name="processinghistory">Processing event</string>

View file

@ -0,0 +1,25 @@
package info.nightscout.utils;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Created by mike on 20.11.2017.
*/
public class DateUtilTest {
public DateUtilTest() {
super();
}
@Test
public void fromISODateStringTest() throws Exception {
assertEquals( 1511124634417L, DateUtil.fromISODateString("2017-11-19T22:50:34.417+0200").getTime());
assertEquals( 1511124634000L, DateUtil.fromISODateString("2017-11-19T22:50:34+0200").getTime());
}
}