From 17f59df59707c773f4f02f4ea05f7b06f36f3783 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Tue, 6 Jun 2017 08:21:11 +0200 Subject: [PATCH] gui tweaking, pump battery event --- .../androidaps/Services/DataService.java | 58 ++++++- .../androidaps/db/CareportalEvent.java | 148 +++++++++++++++++- .../androidaps/db/DatabaseHelper.java | 16 ++ .../androidaps/db/ExtendedBolus.java | 7 +- .../Careportal/CareportalFragment.java | 5 + .../Dialogs/NewNSTreatmentDialog.java | 17 +- .../plugins/NSClientInternal/data/NSMbg.java | 24 +++ .../services/NSClientService.java | 8 - .../plugins/Overview/Notification.java | 1 + .../plugins/Overview/OverviewFragment.java | 86 +++++----- .../PointsWithLabelGraphSeries.java | 121 ++++++++++++-- .../main/res/layout/careportal_fragment.xml | 11 ++ app/src/main/res/layout/overview_fragment.xml | 45 ++---- .../res/layout/overview_fragment_tablet.xml | 39 ++--- app/src/main/res/values/strings.xml | 1 + 15 files changed, 464 insertions(+), 123 deletions(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSMbg.java diff --git a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java index 82d94ef605..3c81d5c84c 100644 --- a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java +++ b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java @@ -22,6 +22,7 @@ import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.events.EventNewBasalProfile; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; +import info.nightscout.androidaps.plugins.NSClientInternal.data.NSMbg; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv; import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.plugins.Overview.Notification; @@ -434,7 +435,42 @@ public class DataService extends IntentService { } if (intent.getAction().equals(Intents.ACTION_NEW_MBG)) { - log.error("Not implemented yet"); // TODO implemeng MBGS + try { + if (bundles.containsKey("mbg")) { + String mbgstring = bundles.getString("mbg"); + JSONObject mbgJson = new JSONObject(mbgstring); + NSMbg nsMbg = new NSMbg(mbgJson); + CareportalEvent careportalEvent = new CareportalEvent(nsMbg); + if (careportalEvent.date < new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000l) { + if (Config.logIncommingData) + log.debug("Ignoring old MBG: " + careportalEvent.log()); + return; + } + MainApp.getDbHelper().createOrUpdate(careportalEvent); + if (Config.logIncommingData) + log.debug("Adding/Updating new MBG: " + careportalEvent.log()); + } + + if (bundles.containsKey("mbgs")) { + String sgvstring = bundles.getString("mbgs"); + JSONArray jsonArray = new JSONArray(sgvstring); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject mbgJson = jsonArray.getJSONObject(i); + NSMbg nsMbg = new NSMbg(mbgJson); + CareportalEvent careportalEvent = new CareportalEvent(nsMbg); + if (careportalEvent.date < new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000l) { + if (Config.logIncommingData) + log.debug("Ignoring old MBG: " + careportalEvent.log()); + return; + } + MainApp.getDbHelper().createOrUpdate(careportalEvent); + if (Config.logIncommingData) + log.debug("Adding/Updating new MBG: " + careportalEvent.log()); + } + } + } catch (Exception e) { + e.printStackTrace(); + } } } @@ -498,16 +534,36 @@ public class DataService extends IntentService { } public void handleAddChangeCareportalEventRecord(JSONObject trJson) throws JSONException { + if (trJson.has("insulin") && trJson.getDouble("insulin") > 0) + return; + if (trJson.has("carbs") && trJson.getDouble("carbs") > 0) + return; if (trJson.has("eventType") && ( trJson.getString("eventType").equals(CareportalEvent.SITECHANGE) || trJson.getString("eventType").equals(CareportalEvent.INSULINCHANGE) || trJson.getString("eventType").equals(CareportalEvent.SENSORCHANGE) || + trJson.getString("eventType").equals(CareportalEvent.BGCHECK) || + trJson.getString("eventType").equals(CareportalEvent.NOTE) || + trJson.getString("eventType").equals(CareportalEvent.NONE) || + trJson.getString("eventType").equals(CareportalEvent.ANNOUNCEMENT) || + trJson.getString("eventType").equals(CareportalEvent.QUESTION) || + trJson.getString("eventType").equals(CareportalEvent.EXERCISE) || + trJson.getString("eventType").equals(CareportalEvent.OPENAPSOFFLINE) || trJson.getString("eventType").equals(CareportalEvent.PUMPBATTERYCHANGE) )) { if (Config.logIncommingData) log.debug("Processing CareportalEvent record: " + trJson.toString()); MainApp.getDbHelper().createCareportalEventFromJsonIfNotExists(trJson); } + + if (trJson.getString("eventType").equals(CareportalEvent.ANNOUNCEMENT)) { + long date = trJson.getLong("mills"); + long now = new Date().getTime(); + if (date > now - 15 * 60 * 1000L && trJson.has("notes")) { + Notification announcement = new Notification(Notification.ANNOUNCEMENT, trJson.getString("notes"), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(announcement)); + } + } } public void handleAddChangeProfileSwitchRecord(JSONObject trJson) throws JSONException { diff --git a/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java index fd2b18c5c4..3d67abc597 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java +++ b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java @@ -1,8 +1,11 @@ package info.nightscout.androidaps.db; +import android.graphics.Color; + import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; +import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,12 +19,18 @@ import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; +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.plugins.NSClientInternal.data.NSMbg; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; import info.nightscout.utils.DateUtil; +import info.nightscout.utils.Translator; @DatabaseTable(tableName = DatabaseHelper.DATABASE_CAREPORTALEVENTS) -public class CareportalEvent { +public class CareportalEvent implements DataPointWithLabelInterface { private static Logger log = LoggerFactory.getLogger(CareportalEvent.class); @DatabaseField(id = true) @@ -52,10 +61,25 @@ public class CareportalEvent { public static final String INSULINCHANGE = "Insulin Change"; public static final String SENSORCHANGE = "Sensor Change"; public static final String PUMPBATTERYCHANGE = "Pump Battery Change"; + public static final String BGCHECK = "BG Check"; + public static final String ANNOUNCEMENT = "Announcement"; + public static final String NOTE = "Note"; + public static final String QUESTION = "Question"; + public static final String EXERCISE = "Exercise"; + public static final String OPENAPSOFFLINE = "OpenAPS Offline"; + public static final String NONE = ""; + + public static final String MBG = "Mbg"; // comming from entries public CareportalEvent() { } + public CareportalEvent(NSMbg mbg) { + date = mbg.date; + eventType = MBG; + json = mbg.json; + } + public long getMillisecondsFromStart() { return new Date().getTime() - date; } @@ -95,4 +119,126 @@ public class CareportalEvent { } return result; } + + // -------- DataPointWithLabelInterface ------- + + @Override + public double getX() { + return date; + } + + double yValue = 0; + + @Override + public double getY() { + Profile profile = MainApp.getConfigBuilder().getProfile(); + if (eventType.equals(MBG)) { + double mbg = 0d; + try { + JSONObject object = new JSONObject(json); + mbg = object.getDouble("mgdl"); + } catch (JSONException e) { + e.printStackTrace(); + } + if (profile != null) + return profile.fromMgdlToUnits(mbg, profile.getUnits()); + return 0d; + } + + double glucose = 0d; + String units = Constants.MGDL; + try { + JSONObject object = new JSONObject(json); + if (object.has("glucose")) { + glucose = object.getDouble("glucose"); + units = object.getString("units"); + } + } catch (JSONException e) { + e.printStackTrace(); + } + if (profile != null && glucose != 0d) { + double mmol = 0d; + double mgdl = 0; + if (units.equals(Constants.MGDL)) { + mgdl = glucose; + mmol = glucose * Constants.MGDL_TO_MMOLL; + } + if (units.equals(Constants.MMOL)) { + mmol = glucose; + mgdl = glucose * Constants.MMOLL_TO_MGDL; + } + return profile.toUnits(mgdl, mmol, profile.getUnits()); + } + + return yValue; + } + + @Override + public void setY(double y) { + yValue = y; + } + + @Override + public String getLabel() { + try { + JSONObject object = new JSONObject(json); + if (object.has("notes")) + return object.getString("notes"); + } catch (JSONException e) { + e.printStackTrace(); + } + return Translator.translate(eventType); + } + + @Override + public long getDuration() { + try { + JSONObject object = new JSONObject(json); + if (object.has("duration")) + return object.getInt("duration") * 60 * 1000L; + } catch (JSONException e) { + e.printStackTrace(); + } + return 0; + } + + @Override + public PointsWithLabelGraphSeries.Shape getShape() { + switch (eventType) { + case CareportalEvent.MBG: + return PointsWithLabelGraphSeries.Shape.MBG; + case CareportalEvent.BGCHECK: + return PointsWithLabelGraphSeries.Shape.BGCHECK; + case CareportalEvent.ANNOUNCEMENT: + return PointsWithLabelGraphSeries.Shape.ANNOUNCEMENT; + case CareportalEvent.OPENAPSOFFLINE: + return PointsWithLabelGraphSeries.Shape.OPENAPSOFFLINE; + case CareportalEvent.EXERCISE: + return PointsWithLabelGraphSeries.Shape.EXERCISE; + } + if (getDuration() > 0) + return PointsWithLabelGraphSeries.Shape.GENERALWITHDURATION; + return PointsWithLabelGraphSeries.Shape.GENERAL; + } + + @Override + public float getSize() { + boolean isTablet = MainApp.sResources.getBoolean(R.bool.isTablet); + return isTablet ? 12 : 10; + } + + @Override + public int getColor() { + if (eventType.equals(ANNOUNCEMENT)) + return 0xFFFF8C00; + if (eventType.equals(MBG)) + return Color.RED; + if (eventType.equals(BGCHECK)) + return Color.RED; + if (eventType.equals(EXERCISE)) + return Color.BLUE; + if (eventType.equals(OPENAPSOFFLINE)) + return Color.GRAY; + return Color.GRAY; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java index c6ffaae6b6..87b4050f6a 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java @@ -1266,6 +1266,22 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return null; } + public List getCareportalEventsFromTime(long mills, boolean ascending) { + try { + List careportalEvents; + QueryBuilder queryBuilder = getDaoCareportalEvents().queryBuilder(); + queryBuilder.orderBy("date", ascending); + Where where = queryBuilder.where(); + where.ge("date", mills); + PreparedQuery preparedQuery = queryBuilder.prepare(); + careportalEvents = getDaoCareportalEvents().query(preparedQuery); + return careportalEvents; + } catch (SQLException e) { + e.printStackTrace(); + } + return new ArrayList(); + } + public void deleteCareportalEventById(String _id) { try { QueryBuilder queryBuilder = null; diff --git a/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java b/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java index 585739b463..083ca76eeb 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java +++ b/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java @@ -201,6 +201,11 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface { + getRealDuration() + "/" + durationInMinutes + ") "; } + public String toStringTotal() { + return DecimalFormatter.to2Decimal(insulin) + "U ( " + + DecimalFormatter.to2Decimal(absoluteRate()) + " U/h )"; + } + // -------- DataPointWithLabelInterface -------- @Override public double getX() { @@ -223,7 +228,7 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface { @Override public String getLabel() { - return toStringMedium(); + return toStringTotal(); } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalFragment.java index 2eeb52785c..c016f5ec61 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalFragment.java @@ -49,6 +49,7 @@ public class CareportalFragment extends Fragment implements View.OnClickListener static final OptionsToShow sensorstart = new OptionsToShow(R.id.careportal_cgmsensorstart, R.string.careportal_cgmsensorstart, true, false, false, false, false, false, false, false, false, false); static final OptionsToShow sensorchange = new OptionsToShow(R.id.careportal_cgmsensorinsert, R.string.careportal_cgmsensorinsert, true, false, false, false, false, false, false, false, false, false); static final OptionsToShow insulinchange = new OptionsToShow(R.id.careportal_insulincartridgechange, R.string.careportal_insulincartridgechange, true, false, false, false, false, false, false, false, false, false); + static final OptionsToShow pumpbatterychange = new OptionsToShow(R.id.careportal_pumpbatterychange, R.string.careportal_pumpbatterychange, true, false, false, false, false, false, false, false, false, false); static final OptionsToShow tempbasalstart = new OptionsToShow(R.id.careportal_tempbasalstart, R.string.careportal_tempbasalstart, true, false, false, false, true, true, true, false, false, false); static final OptionsToShow tempbasalend = new OptionsToShow(R.id.careportal_tempbasalend, R.string.careportal_tempbasalend, true, false, false, false, false, false, false, false, false, false); static final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, true, false, false, true, false, false); @@ -69,6 +70,7 @@ public class CareportalFragment extends Fragment implements View.OnClickListener view.findViewById(R.id.careportal_carbscorrection).setOnClickListener(this); view.findViewById(R.id.careportal_exercise).setOnClickListener(this); view.findViewById(R.id.careportal_insulincartridgechange).setOnClickListener(this); + view.findViewById(R.id.careportal_pumpbatterychange).setOnClickListener(this); view.findViewById(R.id.careportal_mealbolus).setOnClickListener(this); view.findViewById(R.id.careportal_note).setOnClickListener(this); view.findViewById(R.id.careportal_profileswitch).setOnClickListener(this); @@ -124,6 +126,9 @@ public class CareportalFragment extends Fragment implements View.OnClickListener case R.id.careportal_insulincartridgechange: newDialog.setOptions(insulinchange); break; + case R.id.careportal_pumpbatterychange: + newDialog.setOptions(pumpbatterychange); + break; case R.id.careportal_mealbolus: newDialog.setOptions(mealbolus); break; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java index 29d6adeeee..23527e2a05 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java @@ -399,10 +399,10 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick data.put("created_at", DateUtil.toISOString(eventTime)); switch (options.eventType) { case R.id.careportal_bgcheck: - data.put("eventType", "BG Check"); + data.put("eventType", CareportalEvent.BGCHECK); break; case R.id.careportal_announcement: - data.put("eventType", "Announcement"); + data.put("eventType", CareportalEvent.ANNOUNCEMENT); data.put("isAnnouncement", true); break; case R.id.careportal_cgmsensorinsert: @@ -423,16 +423,19 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick data.put("eventType", "Carb Correction"); break; case R.id.careportal_exercise: - data.put("eventType", "Exercise"); + data.put("eventType", CareportalEvent.EXERCISE); break; case R.id.careportal_insulincartridgechange: data.put("eventType", CareportalEvent.INSULINCHANGE); break; + case R.id.careportal_pumpbatterychange: + data.put("eventType", CareportalEvent.PUMPBATTERYCHANGE); + break; case R.id.careportal_mealbolus: data.put("eventType", "Meal Bolus"); break; case R.id.careportal_note: - data.put("eventType", "Note"); + data.put("eventType", CareportalEvent.NOTE); break; case R.id.careportal_profileswitch: data.put("eventType", CareportalEvent.PROFILESWITCH); @@ -442,7 +445,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick data.put("eventType", CareportalEvent.SITECHANGE); break; case R.id.careportal_question: - data.put("eventType", "Question"); + data.put("eventType", CareportalEvent.QUESTION); break; case R.id.careportal_snackbolus: data.put("eventType", "Snack Bolus"); @@ -454,10 +457,10 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick data.put("eventType", CareportalEvent.TEMPBASAL); break; case R.id.careportal_openapsoffline: - data.put("eventType", "OpenAPS Offline"); + data.put("eventType", CareportalEvent.OPENAPSOFFLINE); break; case R.id.careportal_temporarytarget: - data.put("eventType", "Temporary Target"); + data.put("eventType", CareportalEvent.TEMPORARYTARGET); if (!reasonSpinner.getSelectedItem().toString().equals("")) data.put("reason", reasonSpinner.getSelectedItem().toString()); if (SafeParse.stringToDouble(low.getText().toString()) != 0d) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSMbg.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSMbg.java new file mode 100644 index 0000000000..79fa60c3bb --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSMbg.java @@ -0,0 +1,24 @@ +package info.nightscout.androidaps.plugins.NSClientInternal.data; + +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NSMbg { + private static Logger log = LoggerFactory.getLogger(NSMbg.class); + public long date; + public double mbg; + public String json; + + public NSMbg(JSONObject json) { + try { + date = json.getLong("mills"); + mbg = json.getDouble("mgdl"); + this.json = json.toString(); + } catch (JSONException e) { + e.printStackTrace(); + log.debug("Data: " + json.toString()); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/services/NSClientService.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/services/NSClientService.java index c2834dc077..d8e3b99c8d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/services/NSClientService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/services/NSClientService.java @@ -3,13 +3,11 @@ package info.nightscout.androidaps.plugins.NSClientInternal.services; import android.app.Service; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.PowerManager; -import android.preference.PreferenceManager; import com.google.common.base.Charsets; import com.google.common.hash.Hashing; @@ -310,10 +308,8 @@ public class NSClientService extends Service { "onDataUpdate"); wakeLock.acquire(); try { - SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); JSONObject data = (JSONObject) args[0]; - NSCal actualCal = new NSCal(); boolean broadcastProfile = false; try { // delta means only increment/changes are comming @@ -398,7 +394,6 @@ public class NSClientService extends Service { } else if (treatment.getAction().equals("update")) { updatedTreatments.put(jsonTreatment); } else if (treatment.getAction().equals("remove")) { - if (!isCurrent(treatment)) continue; removedTreatments.put(jsonTreatment); } } @@ -445,9 +440,6 @@ public class NSClientService extends Service { MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + cals.length() + " cals")); // Retreive actual calibration for (Integer index = 0; index < cals.length(); index++) { - if (index == 0) { - actualCal.set(cals.optJSONObject(index)); - } // remove from upload queue if Ack is failing UploadQueue.removeID(cals.optJSONObject(index)); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java index 572f8edae0..c9a80dbaef 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java @@ -29,6 +29,7 @@ public class Notification { public static final int IC_MISSING = 14; public static final int BASAL_MISSING = 15; public static final int TARGET_MISSING = 16; + public static final int ANNOUNCEMENT = 17; public int id; public Date date; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java index 8c3041ba26..756ca0c53d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java @@ -54,8 +54,6 @@ import java.util.Calendar; import java.util.Date; import java.util.Iterator; import java.util.List; -import java.util.Timer; -import java.util.TimerTask; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; @@ -78,6 +76,7 @@ import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.events.EventCareportalEventChange; import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventNewBG; @@ -323,14 +322,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } }); - Timer timeTimer = new Timer(); - timeTimer.schedule(new TimerTask() { - @Override - public void run() { - timeUpdate(); - } - }, 0, 30000); - return view; } @@ -787,6 +778,11 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, scheduleUpdateGUI("EventExtendedBolusChange"); } + @Subscribe + public void onStatusEvent(final EventCareportalEventChange ev) { + scheduleUpdateGUI("EventCareportalEventChange"); + } + @Subscribe public void onStatusEvent(final EventNewBG ev) { scheduleUpdateGUI("EventNewBG"); @@ -851,20 +847,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } } - private void timeUpdate() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - if (timeView != null) { //must not exists - timeView.setText(DateUtil.timeString(new Date())); - } - log.debug("Time updated"); - } - }); - } - public void scheduleUpdateGUI(final String from) { class UpdateRunnable implements Runnable { public void run() { @@ -888,7 +870,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, scheduledUpdate = worker.schedule(task, msec, TimeUnit.MILLISECONDS); } - private class updateGUIAsyncClass extends AsyncTask { + private class UpdateGUIAsyncTask extends AsyncTask { BgReading actualBG = DatabaseHelper.actualBg(); BgReading lastBG = DatabaseHelper.lastBg(); @@ -952,8 +934,15 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, @Override protected void onPreExecute() { - log.debug("updateGUIAsyncClass onPreExecute"); - updating.setVisibility(View.VISIBLE); + log.debug("UpdateGUIAsyncTask onPreExecute"); + if (getActivity() == null) + return; + + if (updating != null) + updating.setVisibility(View.VISIBLE); + if (timeView != null) { //must not exists + timeView.setText(DateUtil.timeString(new Date())); + } updateNotifications(); CareportalFragment.updateAge(getActivity(), sage, iage, cage, pbage); // open loop mode @@ -1129,8 +1118,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, highLine = Profile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units); } - timeUpdate(); - // **** BG value **** if (lastBG != null) { int color = MainApp.sResources.getColor(R.color.inrange); @@ -1236,14 +1223,14 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, iobGraph.getViewport().setXAxisBoundsManual(true); iobGraph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter(getActivity(), "HH")); iobGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space - bgGraph.onDataChanged(false, false); - iobGraph.onDataChanged(false, false); + bgGraph.onDataChanged(true, true); + iobGraph.onDataChanged(true, true); } @Override protected String doInBackground(String... params) { - log.debug("updateGUIAsyncClass starting background calculations from: " + params[0]); + log.debug("UpdateGUIAsyncTask doInBackground"); // IOB MainApp.getConfigBuilder().updateTotalIOBTreatments(); @@ -1470,6 +1457,29 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, filteredTreatments.add(t); } + // Extended bolus + if (!pump.isFakingTempsByExtendedBoluses()) { + List extendedBoluses = MainApp.getConfigBuilder().getExtendedBolusesFromHistory().getList(); + + for (int tx = 0; tx < extendedBoluses.size(); tx++) { + DataPointWithLabelInterface t = extendedBoluses.get(tx); + if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; + if (t.getDuration() == 0) continue; + t.setY(getNearestBg((long) t.getX(), bgReadingsArray)); + filteredTreatments.add(t); + } + } + + // Careportal + List careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, true); + + for (int tx = 0; tx < careportalEvents.size(); tx++) { + DataPointWithLabelInterface t = careportalEvents.get(tx); + if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; + t.setY(getNearestBg((long) t.getX(), bgReadingsArray)); + filteredTreatments.add(t); + } + DataPointWithLabelInterface[] treatmentsArray = new DataPointWithLabelInterface[filteredTreatments.size()]; treatmentsArray = filteredTreatments.toArray(treatmentsArray); if (treatmentsArray.length > 0) { @@ -1482,8 +1492,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, @Override protected void onPostExecute(String result) { - log.debug("updateGUIAsyncClass onPostExecute"); + log.debug("UpdateGUIAsyncTask onPostExecute"); // IOB + if (getActivity() == null) + return; String iobtext = getString(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U (" + getString(R.string.bolus) + ": " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U " + getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)"; @@ -1514,7 +1526,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, bgGraph.removeAllSeries(); // **** Area *** - bgGraph.addSeries(areaSeries); + if (areaSeries != null) + bgGraph.addSeries(areaSeries); // **** BG graph **** @@ -1576,12 +1589,13 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } }); - updating.setVisibility(View.GONE); + if (updating != null) + updating.setVisibility(View.GONE); } } public void updateGUIAsync(String from) { - new updateGUIAsyncClass().execute(from); + new UpdateGUIAsyncTask().execute(from); } @SuppressLint("SetTextI18n") diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/PointsWithLabelGraphSeries.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/PointsWithLabelGraphSeries.java index 9d633d13fa..071fdf41aa 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/PointsWithLabelGraphSeries.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/PointsWithLabelGraphSeries.java @@ -62,7 +62,14 @@ public class PointsWithLabelGraphSeries e RECTANGLE, BOLUS, EXTENDEDBOLUS, - PROFILE + PROFILE, + MBG, + BGCHECK, + ANNOUNCEMENT, + OPENAPSOFFLINE, + EXERCISE, + GENERAL, + GENERALWITHDURATION } /** @@ -177,19 +184,27 @@ public class PointsWithLabelGraphSeries e float endY = (float) (graphTop - y) + graphHeight; registerDataPoint(endX, endY, value); + float xpluslength = 0; + if (value.getDuration() > 0) { + xpluslength = endX + Math.min((float) (value.getDuration() * graphWidth / diffX), graphLeft + graphWidth); + } + // draw data point if (!overdraw) { if (value.getShape() == Shape.POINT) { + mPaint.setStrokeWidth(0); canvas.drawCircle(endX, endY, value.getSize(), mPaint); } else if (value.getShape() == Shape.RECTANGLE) { canvas.drawRect(endX-value.getSize(), endY-value.getSize(), endX+value.getSize(), endY+value.getSize(), mPaint); } else if (value.getShape() == Shape.TRIANGLE) { + mPaint.setStrokeWidth(0); Point[] points = new Point[3]; points[0] = new Point((int)endX, (int)(endY-value.getSize())); points[1] = new Point((int)(endX+value.getSize()), (int)(endY+value.getSize()*0.67)); points[2] = new Point((int)(endX-value.getSize()), (int)(endY+value.getSize()*0.67)); drawArrows(points, canvas, mPaint); } else if (value.getShape() == Shape.BOLUS) { + mPaint.setStrokeWidth(0); Point[] points = new Point[3]; points[0] = new Point((int)endX, (int)(endY-value.getSize())); points[1] = new Point((int)(endX+value.getSize()), (int)(endY+value.getSize()*0.67)); @@ -197,23 +212,21 @@ public class PointsWithLabelGraphSeries e mPaint.setStyle(Paint.Style.FILL_AND_STROKE); drawArrows(points, canvas, mPaint); if (value.getLabel() != null) { - float px = endX; - float py = endY - (int) (value.getSize()); - canvas.save(); - canvas.rotate(-45, px, py); + drawLabel45(endX, endY, value, canvas); + } + } else if (value.getShape() == Shape.EXTENDEDBOLUS) { + mPaint.setStrokeWidth(0); + if (value.getLabel() != null) { + Rect bounds = new Rect((int)endX, (int)endY + 3, (int) (xpluslength), (int) endY + 8); + mPaint.setStyle(Paint.Style.FILL_AND_STROKE); + canvas.drawRect(bounds, mPaint); mPaint.setTextSize((int) (value.getSize() * 2.5)); mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); mPaint.setFakeBoldText(true); - canvas.drawText(value.getLabel(), px + value.getSize(), py, mPaint); - canvas.restore(); + canvas.drawText(value.getLabel(), endX, endY, mPaint); } - } else if (value.getShape() == Shape.EXTENDEDBOLUS) { - Point[] points = new Point[3]; - points[0] = new Point((int)endX, (int)(endY-value.getSize())); - points[1] = new Point((int)(endX+value.getSize()), (int)(endY+value.getSize()*0.67)); - points[2] = new Point((int)(endX-value.getSize()), (int)(endY+value.getSize()*0.67)); - drawArrows(points, canvas, mPaint); } else if (value.getShape() == Shape.PROFILE) { + mPaint.setStrokeWidth(0); if (value.getLabel() != null) { mPaint.setTextSize((int) (value.getSize() * 3)); mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); @@ -228,6 +241,77 @@ public class PointsWithLabelGraphSeries e canvas.drawRect(px - 3, bounds.top + py - 3, bounds.right + px + 3, bounds.bottom + py + 3, mPaint); canvas.restore(); } + } else if (value.getShape() == Shape.MBG) { + mPaint.setStyle(Paint.Style.STROKE); + mPaint.setStrokeWidth(5); + float w = mPaint.getStrokeWidth(); + canvas.drawCircle(endX, endY, value.getSize(), mPaint); + } else if (value.getShape() == Shape.BGCHECK) { + mPaint.setStyle(Paint.Style.FILL_AND_STROKE); + mPaint.setStrokeWidth(0); + canvas.drawCircle(endX, endY, value.getSize(), mPaint); + if (value.getLabel() != null) { + drawLabel45(endX, endY, value, canvas); + } + } else if (value.getShape() == Shape.ANNOUNCEMENT) { + mPaint.setStyle(Paint.Style.FILL_AND_STROKE); + mPaint.setStrokeWidth(0); + canvas.drawCircle(endX, endY, value.getSize(), mPaint); + if (value.getLabel() != null) { + drawLabel45(endX, endY, value, canvas); + } + } else if (value.getShape() == Shape.GENERAL) { + mPaint.setStyle(Paint.Style.FILL_AND_STROKE); + mPaint.setStrokeWidth(0); + canvas.drawCircle(endX, endY, value.getSize(), mPaint); + if (value.getLabel() != null) { + drawLabel45(endX, endY, value, canvas); + } + } else if (value.getShape() == Shape.EXERCISE) { + mPaint.setStrokeWidth(0); + if (value.getLabel() != null) { + mPaint.setStrokeWidth(0); + mPaint.setTextSize((int) (value.getSize() * 3)); + mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + Rect bounds = new Rect(); + mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds); + mPaint.setStyle(Paint.Style.STROKE); + float px = endX; + float py = graphTop + 20; + canvas.drawText(value.getLabel(), px, py, mPaint); + mPaint.setStrokeWidth(5); + canvas.drawRect(px - 3, bounds.top + py - 3, xpluslength + 3, bounds.bottom + py + 3, mPaint); + } + } else if (value.getShape() == Shape.OPENAPSOFFLINE) { + mPaint.setStrokeWidth(0); + if (value.getLabel() != null) { + mPaint.setStrokeWidth(0); + mPaint.setTextSize((int) (value.getSize() * 3)); + mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + Rect bounds = new Rect(); + mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds); + mPaint.setStyle(Paint.Style.STROKE); + float px = endX; + float py = graphTop + 50; + canvas.drawText(value.getLabel(), px, py, mPaint); + mPaint.setStrokeWidth(5); + canvas.drawRect(px - 3, bounds.top + py - 3, xpluslength + 3, bounds.bottom + py + 3, mPaint); + } + } else if (value.getShape() == Shape.GENERALWITHDURATION) { + mPaint.setStrokeWidth(0); + if (value.getLabel() != null) { + mPaint.setStrokeWidth(0); + mPaint.setTextSize((int) (value.getSize() * 3)); + mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + Rect bounds = new Rect(); + mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds); + mPaint.setStyle(Paint.Style.STROKE); + float px = endX; + float py = graphTop + 80; + canvas.drawText(value.getLabel(), px, py, mPaint); + mPaint.setStrokeWidth(5); + canvas.drawRect(px - 3, bounds.top + py - 3, xpluslength + 3, bounds.bottom + py + 3, mPaint); + } } // set values above point } @@ -265,4 +349,15 @@ public class PointsWithLabelGraphSeries e canvas.restore(); } + void drawLabel45(float endX, float endY, E value, Canvas canvas) { + float px = endX; + float py = endY - value.getSize(); + canvas.save(); + canvas.rotate(-45, px, py); + mPaint.setTextSize((int) (value.getSize() * 2.5)); + mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + mPaint.setFakeBoldText(true); + canvas.drawText(value.getLabel(), px + value.getSize(), py, mPaint); + canvas.restore(); + } } diff --git a/app/src/main/res/layout/careportal_fragment.xml b/app/src/main/res/layout/careportal_fragment.xml index e538e9125c..d3b1488adc 100644 --- a/app/src/main/res/layout/careportal_fragment.xml +++ b/app/src/main/res/layout/careportal_fragment.xml @@ -236,6 +236,17 @@ app:layout_gravity="fill" app:layout_row="6" /> +