diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bc900d0b40..8d8c9baf08 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -20,7 +20,6 @@
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
- android:process=":mainProcess"
android:theme="@style/AppTheme">
@@ -30,12 +29,11 @@
-
+
+ android:exported="true">
diff --git a/app/src/main/java/info/nightscout/androidaps/MainActivity.java b/app/src/main/java/info/nightscout/androidaps/MainActivity.java
index ffd95db125..8788020c87 100644
--- a/app/src/main/java/info/nightscout/androidaps/MainActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/MainActivity.java
@@ -15,12 +15,15 @@ import org.slf4j.LoggerFactory;
import java.util.List;
import info.nightscout.androidaps.plugins.ProfileViewer.ProfileViewerFragment;
+import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment;
import info.nightscout.androidaps.tabs.*;
import info.nightscout.androidaps.plugins.Objectives.ObjectivesFragment;
import info.nightscout.androidaps.plugins.Test.TestFragment;
import info.nightscout.client.broadcasts.Intents;
-public class MainActivity extends AppCompatActivity implements ObjectivesFragment.OnFragmentInteractionListener {
+public class MainActivity extends AppCompatActivity
+ implements ObjectivesFragment.OnFragmentInteractionListener,
+ TreatmentsFragment.OnFragmentInteractionListener {
private static Logger log = LoggerFactory.getLogger(MainActivity.class);
private Toolbar toolbar;
@@ -36,6 +39,7 @@ public class MainActivity extends AppCompatActivity implements ObjectivesFragmen
// Register all tabs in app here
mAdapter = new TabPageAdapter(getSupportFragmentManager());
mAdapter.registerNewFragment("Test", TestFragment.newInstance());
+ mAdapter.registerNewFragment("Treatments", TreatmentsFragment.newInstance());
mAdapter.registerNewFragment("Profile", ProfileViewerFragment.newInstance());
mAdapter.registerNewFragment("Objectives", ObjectivesFragment.newInstance());
diff --git a/app/src/main/java/info/nightscout/androidaps/data/Iob.java b/app/src/main/java/info/nightscout/androidaps/data/Iob.java
new file mode 100644
index 0000000000..ee70699604
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/data/Iob.java
@@ -0,0 +1,15 @@
+package info.nightscout.androidaps.data;
+
+/**
+ * Created by mike on 05.06.2016.
+ */
+public class Iob {
+ public double iobContrib = 0d;
+ public double activityContrib = 0d;
+
+ public Iob plus(Iob iob) {
+ iobContrib += iob.iobContrib;
+ activityContrib += iob.activityContrib;
+ return this;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/db/Treatment.java b/app/src/main/java/info/nightscout/androidaps/db/Treatment.java
index ce60c2dc53..b09714ab62 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/Treatment.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/Treatment.java
@@ -16,8 +16,10 @@ import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.List;
+import info.nightscout.androidaps.data.Iob;
import info.nightscout.client.broadcasts.Intents;
import info.nightscout.androidaps.MainApp;
+import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.DateUtil;
@DatabaseTable(tableName = "Treatments")
@@ -53,40 +55,43 @@ public class Treatment {
this.insulin = t.insulin;
this.carbs = t.carbs;
}
-/*
- public Iob iobCalc(Date time, Double dia) {
- Double diaratio = 3.0 / dia;
- Double peak = 75d;
- Double end = 180d;
- //var sens = profile_data.sens;
- Iob results = new Iob();
+ public Iob iobCalc(Date time) {
- if (insulin != 0) {
- long bolusTime = created_at.getTime();
- Double minAgo = diaratio * (time.getTime() - bolusTime) / 1000 / 60;
- Double iobContrib = 0d;
- Double activityContrib = 0d;
+ Iob result = new Iob();
+ NSProfile profile = MainApp.getNSProfile();
- if (minAgo < peak) {
- Double x = (minAgo/5 + 1);
- iobContrib = insulin * (1 - 0.001852 * x * x + 0.001852 * x);
- //activityContrib=sens*treatment.insulin*(2/dia/60/peak)*minAgo;
- activityContrib = insulin * (2 / dia / 60 / peak) * minAgo;
- } else if (minAgo < end) {
- Double y = (minAgo-peak)/5;
- iobContrib = insulin * (0.001323 * y * y - .054233 * y + .55556);
- //activityContrib=sens*treatment.insulin*(2/dia/60-(minAgo-peak)*2/dia/60/(60*dia-peak));
- activityContrib = insulin * (2 / dia / 60 - (minAgo - peak) * 2 / dia / 60 / (60 * dia - peak));
- }
-
- results.iobContrib = iobContrib;
- results.activityContrib = activityContrib;
+ if (profile == null) {
+ return result;
}
- return results;
+ Double dia = profile.getDia();
+ Double sens = profile.getIsf(profile.secondsFromMidnight(time));
+
+ Double scaleFactor = 3.0 / dia;
+ Double peak = 75d;
+ Double end = 180d;
+
+ if (this.insulin != 0d) {
+ Long bolusTime = this.created_at.getTime();
+ Double minAgo = scaleFactor * (time.getTime() - bolusTime) / 1000d / 60d;
+
+ if (minAgo < peak) {
+ Double x1 = minAgo / 5 + 1;
+ result.iobContrib = this.insulin * (1 - 0.001852 * x1 * x1 + 0.001852 * x1);
+ // units: BG (mg/dL) = (BG/U) * U insulin * scalar
+ result.activityContrib = sens * this.insulin * (2 / dia / 60 / peak) * minAgo;
+
+ } else if (minAgo < end) {
+ Double x2 = (minAgo - 75) / 5;
+ result.iobContrib = this.insulin * (0.001323 * x2 * x2 - 0.054233 * x2 + 0.55556);
+ result.activityContrib = sens * this.insulin * (2 / dia / 60 - (minAgo - peak) * 2 / dia / 60 / (60 * dia - peak));
+ }
+ }
+ return result;
}
+/*
public Iob calcIobOpenAPS() {
IobCalc calc = new IobCalc(created_at,insulin,new Date());
calc.setBolusDiaTimesTwo();
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java b/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java
new file mode 100644
index 0000000000..2d6454406a
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java
@@ -0,0 +1,7 @@
+package info.nightscout.androidaps.events;
+
+/**
+ * Created by mike on 05.06.2016.
+ */
+public class EventNewBG {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileViewer/ProfileViewerFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileViewer/ProfileViewerFragment.java
index 4ff01f1de3..747733913e 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileViewer/ProfileViewerFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileViewer/ProfileViewerFragment.java
@@ -91,6 +91,4 @@ public class ProfileViewerFragment extends Fragment {
public void onStatusEvent(final EventNewBasalProfile ev) {
setContent();
}
-
-
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java
new file mode 100644
index 0000000000..23fbe175ad
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java
@@ -0,0 +1,237 @@
+package info.nightscout.androidaps.plugins.Treatments;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v7.widget.CardView;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.j256.ormlite.dao.Dao;
+import com.j256.ormlite.stmt.PreparedQuery;
+import com.j256.ormlite.stmt.QueryBuilder;
+import com.squareup.otto.Subscribe;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.SQLException;
+import java.text.DateFormat;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.Iob;
+import info.nightscout.androidaps.db.Treatment;
+import info.nightscout.androidaps.events.EventNewBG;
+import info.nightscout.androidaps.events.EventNewBasalProfile;
+import info.nightscout.androidaps.events.EventTreatmentChange;
+
+public class TreatmentsFragment extends Fragment {
+ private static Logger log = LoggerFactory.getLogger(TreatmentsFragment.class);
+
+ RecyclerView recyclerView;
+ LinearLayoutManager llm;
+
+ TextView iobTotal;
+ TextView activityTotal;
+
+ private static DecimalFormat formatNumber0decimalplaces = new DecimalFormat("0");
+ private static DecimalFormat formatNumber2decimalplaces = new DecimalFormat("0.00");
+ private static DecimalFormat formatNumber3decimalplaces = new DecimalFormat("0.000");
+
+ private OnFragmentInteractionListener mListener;
+
+ private List treatments;
+
+ private void initializeData() {
+ try {
+ Dao dao = MainApp.getDbHelper().getDaoTreatments();
+ QueryBuilder queryBuilder = dao.queryBuilder();
+ queryBuilder.orderBy("timeIndex", false);
+ queryBuilder.limit(30l);
+ PreparedQuery preparedQuery = queryBuilder.prepare();
+ treatments = dao.query(preparedQuery);
+ } catch (SQLException e) {
+ log.debug(e.getMessage(), e);
+ treatments = new ArrayList();
+ }
+ if (recyclerView != null) {
+ recyclerView.swapAdapter(new RecyclerViewAdapter(treatments), false);
+ //recyclerView.getAdapter().notifyDataSetChanged();
+ }
+ updateTotalIOB();
+ }
+
+ private void updateTotalIOB() {
+ Iob total = new Iob();
+ for (Integer pos = 0; pos < treatments.size(); pos++ ) {
+ Treatment t = treatments.get(pos);
+ total.plus(t.iobCalc(new Date()));
+ }
+ if (iobTotal != null)
+ iobTotal.setText(formatNumber2decimalplaces.format(total.iobContrib));
+ if (activityTotal != null)
+ activityTotal.setText(formatNumber3decimalplaces.format(total.activityContrib));
+ }
+
+ public static class RecyclerViewAdapter extends RecyclerView.Adapter {
+
+ List treatments;
+
+ RecyclerViewAdapter(List treatments) {
+ this.treatments = treatments;
+ }
+
+ @Override
+ public TreatmentsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
+ View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.treatments_item, viewGroup, false);
+ TreatmentsViewHolder treatmentsViewHolder = new TreatmentsViewHolder(v);
+ return treatmentsViewHolder;
+ }
+
+ @Override
+ public void onBindViewHolder(TreatmentsViewHolder holder, int position) {
+ // TODO: implement locales
+ DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, new Locale("cs", "CZ"));
+ holder.date.setText(df.format(treatments.get(position).created_at));
+ holder.insulin.setText(formatNumber2decimalplaces.format(treatments.get(position).insulin) + " U");
+ holder.carbs.setText(formatNumber0decimalplaces.format(treatments.get(position).carbs) + " g");
+ Iob iob = treatments.get(position).iobCalc(new Date());
+ holder.iob.setText(formatNumber2decimalplaces.format(iob.iobContrib) + " U");
+ holder.activity.setText(formatNumber3decimalplaces.format(iob.activityContrib) + " U");
+ }
+
+ @Override
+ public int getItemCount() {
+ return treatments.size();
+ }
+
+ @Override
+ public void onAttachedToRecyclerView(RecyclerView recyclerView) {
+ super.onAttachedToRecyclerView(recyclerView);
+ }
+
+ public static class TreatmentsViewHolder extends RecyclerView.ViewHolder {
+ CardView cv;
+ TextView date;
+ TextView insulin;
+ TextView carbs;
+ TextView iob;
+ TextView activity;
+
+ TreatmentsViewHolder(View itemView) {
+ super(itemView);
+ cv = (CardView) itemView.findViewById(R.id.treatments_cardview);
+ date = (TextView) itemView.findViewById(R.id.treatments_date);
+ insulin = (TextView) itemView.findViewById(R.id.treatments_insulin);
+ carbs = (TextView) itemView.findViewById(R.id.treatments_carbs);
+ iob = (TextView) itemView.findViewById(R.id.treatments_iob);
+ activity = (TextView) itemView.findViewById(R.id.treatments_activity);
+ }
+ }
+ }
+
+ public TreatmentsFragment() {
+ super();
+ initializeData();
+ }
+
+ public static TreatmentsFragment newInstance() {
+ TreatmentsFragment fragment = new TreatmentsFragment();
+ return fragment;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ registerBus();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.treatments_fragment, container, false);
+
+ recyclerView = (RecyclerView) view.findViewById(R.id.treatments_recyclerview);
+ recyclerView.setHasFixedSize(true);
+ llm = new LinearLayoutManager(view.getContext());
+ recyclerView.setLayoutManager(llm);
+
+ RecyclerViewAdapter adapter = new RecyclerViewAdapter(treatments);
+ recyclerView.setAdapter(adapter);
+
+ iobTotal = (TextView) view.findViewById(R.id.treatments_iobtotal);
+ activityTotal = (TextView) view.findViewById(R.id.treatments_iobactivitytotal);
+
+ return view;
+ }
+
+ /*
+ // TODO: Rename method, update argument and hook method into UI event
+ public void onButtonPressed(Uri uri) {
+ if (mListener != null) {
+ mListener.onFragmentInteraction(uri);
+ }
+ }
+ */
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ if (context instanceof OnFragmentInteractionListener) {
+ mListener = (OnFragmentInteractionListener) context;
+ } else {
+ throw new RuntimeException(context.toString()
+ + " must implement OnFragmentInteractionListener");
+ }
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ mListener = null;
+ }
+
+ private void registerBus() {
+ try {
+ MainApp.bus().unregister(this);
+ } catch (RuntimeException x) {
+ // Ignore
+ }
+ MainApp.bus().register(this);
+ }
+
+ @Subscribe
+ public void onStatusEvent(final EventTreatmentChange ev) {
+ initializeData();
+ }
+
+ @Subscribe
+ public void onStatusEvent(final EventNewBG ev) {
+ updateTotalIOB();
+ recyclerView.getAdapter().notifyDataSetChanged();
+ }
+
+ /**
+ * This interface must be implemented by activities that contain this
+ * fragment to allow an interaction in this fragment to be communicated
+ * to the activity and potentially other fragments contained in that
+ * activity.
+ *
+ * See the Android Training lesson Communicating with Other Fragments for more information.
+ */
+ public interface OnFragmentInteractionListener {
+ // TODO: Update argument type and name
+ void onFragmentInteraction(String param);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/client/data/NSProfile.java b/app/src/main/java/info/nightscout/client/data/NSProfile.java
index 30e0ba3594..9965d1db4e 100644
--- a/app/src/main/java/info/nightscout/client/data/NSProfile.java
+++ b/app/src/main/java/info/nightscout/client/data/NSProfile.java
@@ -6,6 +6,7 @@ import org.json.JSONObject;
import java.text.DecimalFormat;
import java.util.Calendar;
+import java.util.Date;
import java.util.TimeZone;
public class NSProfile {
@@ -279,4 +280,16 @@ public class NSProfile {
long passed = now - c.getTimeInMillis();
return (int) (passed / 1000);
}
+
+ public static int secondsFromMidnight(Date date) {
+ Calendar c = Calendar.getInstance();
+ long now = date.getTime();
+ c.setTime(date);
+ c.set(Calendar.HOUR_OF_DAY, 0);
+ c.set(Calendar.MINUTE, 0);
+ c.set(Calendar.SECOND, 0);
+ c.set(Calendar.MILLISECOND, 0);
+ long passed = now - c.getTimeInMillis();
+ return (int) (passed / 1000);
+ }
}
diff --git a/app/src/main/java/info/nightscout/client/receivers/NSClientDataReceiver.java b/app/src/main/java/info/nightscout/client/receivers/NSClientDataReceiver.java
index 3576e004cd..91756deffc 100644
--- a/app/src/main/java/info/nightscout/client/receivers/NSClientDataReceiver.java
+++ b/app/src/main/java/info/nightscout/client/receivers/NSClientDataReceiver.java
@@ -21,6 +21,7 @@ import java.sql.SQLException;
import java.util.Date;
import java.util.List;
+import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.client.broadcasts.Intents;
@@ -182,6 +183,7 @@ public class NSClientDataReceiver extends BroadcastReceiver {
removeTreatmentFromDb(_id);
}
}
+ MainApp.bus().post(new EventTreatmentChange());
} catch (JSONException e) {
e.printStackTrace();
@@ -189,6 +191,10 @@ public class NSClientDataReceiver extends BroadcastReceiver {
e1.printStackTrace();
}
}
+
+ if (intent.getAction().equals(Intents.ACTION_NEW_SGV)) {
+ MainApp.bus().post(new EventNewBG());
+ }
}
public void storeNSProfile() {
diff --git a/app/src/main/res/layout/treatments_fragment.xml b/app/src/main/res/layout/treatments_fragment.xml
new file mode 100644
index 0000000000..578e1b3900
--- /dev/null
+++ b/app/src/main/res/layout/treatments_fragment.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/treatments_item.xml b/app/src/main/res/layout/treatments_item.xml
new file mode 100644
index 0000000000..902990d0b1
--- /dev/null
+++ b/app/src/main/res/layout/treatments_item.xml
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 12b1f8b0ed..5e866eff2f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -34,5 +34,11 @@
Basal:
Target:
NO PROFILE SET
+ Insulin:
+ Carbs:
+ IOB:
+ Activity:
+ Toal IOB:
+ Total IOB activity: