Skip to content
Snippets Groups Projects
Commit 43423ddc authored by Lennart Goedhart's avatar Lennart Goedhart
Browse files

Merge branch 'develop' into pazaan/develop-basal-rates

* develop:
  Make app reading data directly again if triggered by use
  align restart of polling with last known event. It'll try to align with the last poll up to 2h (hardcoded). After that we assume that there is may be a sensor initialisation and restart polling immediately
  branch name can be added to VERSION_NAME
  change chart to GraphView
  change chart to GraphView
  fixing #95
parents 0e123b26 9600f5b4
No related branches found
No related tags found
No related merge requests found
......@@ -5,3 +5,4 @@ local.properties
.idea
bugfender.properties
/app/app.iml
gradle.properties
\ No newline at end of file
......@@ -27,7 +27,7 @@ apply plugin: 'realm-android'
def gitVersion() {
// current dir is <your proj>/app, so it's likely that all your git repo files are in the dir
// above.
ext.repo = Grgit.open(project.file('..'))
ext.repo = Grgit.open()
// should result in the same value as running
// git tag -l | wc -l or git tag -l | grep -c ".*" -
......@@ -36,14 +36,15 @@ def gitVersion() {
}
def gitCommitId() {
//def process = ['sh', '-c', 'git tag -l | grep -c ".*" -'].execute().text.trim()
//return process.toInteger() + 1
//return 42
// current dir is <your proj>/app, so it's likely that all your git repo files are in the dir
// above.
ext.repo = Grgit.open(project.file('..'))
ext.repo = Grgit.open()
return ext.repo.log().first().id.substring(0, 7) //+ " " + ext.repo.branch.current.name
}
return ext.repo.log().first().id.substring(0, 7)
def gitBranch() {
ext.repo = Grgit.open()
return ext.repo.branch.current.name
}
def getBugfenderApiKey() {
......@@ -66,7 +67,7 @@ android {
applicationId "info.nightscout.android"
minSdkVersion 14
targetSdkVersion 23
versionName project.properties['version'] + "/" + gitCommitId()
versionName project.properties['version'] + "/" + gitCommitId() // + " (" + gitBranch()+")"
versionCode gitVersion()
buildConfigField "String", "BUGFENDER_API_KEY", getBugfenderApiKey()
}
......@@ -154,8 +155,7 @@ dependencies {
compile 'com.mikepenz:google-material-typeface:2.2.0.1.original@aar'
compile 'uk.co.chrisjenx:calligraphy:2.2.0'
compile 'com.bugfender.sdk:android:0.6.2'
compile 'com.github.PhilJay:MPAndroidChart-Realm:v2.0.2@aar'
compile 'com.github.PhilJay:MPAndroidChart:v3.0.1'
compile 'com.jjoe64:graphview:4.2.1'
compile 'com.android.support:support-v4:23.4.0'
compile 'com.google.code.gson:gson:2.7'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
......
......@@ -80,11 +80,7 @@
<receiver android:name=".medtronic.service.MedtronicCnlAlarmReceiver" />
<receiver android:name=".upload.nightscout.NightscoutUploadReceiver" />
<receiver android:name=".xdrip_plus.XDripPlusUploadReceiver" /><!-- ATTENTION: This was auto-generated to add Google Play services to your project for
App Indexing. See https://g.co/AppIndexing/AndroidStudio for more information. -->
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<receiver android:name=".xdrip_plus.XDripPlusUploadReceiver" />
</application>
......
......@@ -12,6 +12,7 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.net.Uri;
......@@ -34,28 +35,19 @@ import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.TextView.BufferType;
import com.github.mikephil.charting.charts.ScatterChart;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.ScatterData;
import com.github.mikephil.charting.data.ScatterDataSet;
import com.github.mikephil.charting.data.realm.implementation.RealmScatterDataSet;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.formatter.IValueFormatter;
import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet;
import com.github.mikephil.charting.listener.ChartTouchListener;
import com.github.mikephil.charting.listener.OnChartGestureListener;
import com.github.mikephil.charting.renderer.ScatterChartRenderer;
import com.github.mikephil.charting.renderer.scatter.IShapeRenderer;
import com.github.mikephil.charting.utils.Transformer;
import com.github.mikephil.charting.utils.ViewPortHandler;
import android.widget.Toast;
import com.jjoe64.graphview.DefaultLabelFormatter;
import com.jjoe64.graphview.GraphView;
import com.jjoe64.graphview.Viewport;
import com.jjoe64.graphview.series.DataPoint;
import com.jjoe64.graphview.series.DataPointInterface;
import com.jjoe64.graphview.series.OnDataPointTapListener;
import com.jjoe64.graphview.series.PointsGraphSeries;
import com.jjoe64.graphview.series.Series;
import com.mikepenz.google_material_typeface_library.GoogleMaterial;
import com.mikepenz.materialdrawer.AccountHeaderBuilder;
import com.mikepenz.materialdrawer.Drawer;
......@@ -65,9 +57,8 @@ import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.text.NumberFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
......@@ -83,7 +74,6 @@ import info.nightscout.android.model.medtronicNg.PumpInfo;
import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
import info.nightscout.android.settings.SettingsActivity;
import info.nightscout.android.upload.nightscout.NightscoutUploadIntentService;
import io.realm.DynamicRealmObject;
import io.realm.Realm;
import io.realm.RealmChangeListener;
import io.realm.RealmResults;
......@@ -92,6 +82,7 @@ import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper;
public class MainActivity extends AppCompatActivity implements OnSharedPreferenceChangeListener, OnEulaAgreedTo {
private static final String TAG = MainActivity.class.getSimpleName();
public static final float MMOLXLFACTOR = 18.016f;
public static int batLevel = 0;
public static boolean reducePollOnPumpAway = false;
......@@ -99,12 +90,18 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
public static long lowBatteryPollInterval = MedtronicCnlIntentService.LOW_BATTERY_POLL_PERIOD_MS;
private static long activePumpMac;
private int chartZoom = 3;
private boolean hasZoomedChart = false;
private NumberFormat sgvFormatter;
private boolean mmolxl;
private boolean mmolxlDecimals;
boolean mEnableCgmService = true;
SharedPreferences prefs = null;
private PumpInfo mActivePump;
private TextView mTextViewLog; // This will eventually move to a status page.
private ScatterChart mChart;
private GraphView mChart;
private Intent mNightscoutUploadService;
private Handler mUiRefreshHandler = new Handler();
private Runnable mUiRefreshRunnable = new RefreshDisplayRunnable();
......@@ -112,17 +109,31 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
private StatusMessageReceiver statusMessageReceiver = new StatusMessageReceiver();
private MedtronicCnlAlarmReceiver medtronicCnlAlarmReceiver = new MedtronicCnlAlarmReceiver();
/**
* calculate the next poll timestamp based on last svg event
*
* @param pumpStatusData
* @return timestamp
*/
public static long getNextPoll(PumpStatusEvent pumpStatusData) {
long nextPoll = pumpStatusData.getEventDate().getTime() + pumpStatusData.getPumpTimeOffset()
+ MedtronicCnlIntentService.POLL_GRACE_PERIOD_MS;
long nextPoll = pumpStatusData.getEventDate().getTime() + pumpStatusData.getPumpTimeOffset(),
now = System.currentTimeMillis();
if (pumpStatusData.getBatteryPercentage() > 25) {
// poll every 5 min
nextPoll += MainActivity.pollInterval;
// align to next poll slot
if (nextPoll + 2 * 60 * 60 * 1000 < now) { // last event more than 2h old -> could be a calibration
nextPoll = System.currentTimeMillis() + 1000;
} else {
// if pump battery seems to be empty reduce polling to save battery (every 15 min)
//TODO add message & document it
nextPoll += MainActivity.lowBatteryPollInterval;
// align to poll interval
nextPoll += (((now - nextPoll) / MainActivity.pollInterval)) * MainActivity.pollInterval
+ MedtronicCnlIntentService.POLL_GRACE_PERIOD_MS;
if (pumpStatusData.getBatteryPercentage() > 25) {
// poll every 5 min
nextPoll += MainActivity.pollInterval;
} else {
// if pump battery seems to be empty reduce polling to save battery (every 15 min)
//TODO add message & document it
nextPoll += MainActivity.lowBatteryPollInterval;
}
}
return nextPoll;
......@@ -149,6 +160,18 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
MainActivity.pollInterval = Long.parseLong(prefs.getString("pollInterval", Long.toString(MedtronicCnlIntentService.POLL_PERIOD_MS)));
MainActivity.lowBatteryPollInterval = Long.parseLong(prefs.getString("lowBatPollInterval", Long.toString(MedtronicCnlIntentService.LOW_BATTERY_POLL_PERIOD_MS)));
MainActivity.reducePollOnPumpAway = prefs.getBoolean("doublePollOnPumpAway", false);
chartZoom = Integer.parseInt(prefs.getString("chartZoom", "3"));
mmolxl = prefs.getBoolean("mmolxl", false);
mmolxlDecimals = prefs.getBoolean("mmolDecimals", false);
if (mmolxl) {
if (mmolxlDecimals)
sgvFormatter = new DecimalFormat("0.00");
else
sgvFormatter = new DecimalFormat("0.0");
} else {
sgvFormatter = new DecimalFormat("0");
}
// Disable battery optimization to avoid missing values on 6.0+
// taken from https://github.com/NightscoutFoundation/xDrip/blob/master/app/src/main/java/com/eveningoutpost/dexdrip/Home.java#L277L298
......@@ -260,7 +283,8 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
stopCgmService();
finish();
} else if (drawerItem.equals(itemGetNow)) {
startCgmService();
// It was triggered by user so start reading of data now and not based on last poll.
startCgmService(0);
} else if (drawerItem.equals(itemClearLog)) {
clearLogText();
}
......@@ -271,118 +295,57 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
.build();
mTextViewLog = (TextView) findViewById(R.id.textview_log);
mChart = (ScatterChart) findViewById(R.id.chart);
mChart.setDescription(null); // Hide the description
mChart.setTouchEnabled(true);
mChart.setPinchZoom(true);
mChart.setHighlightPerDragEnabled(false);
mChart.setHighlightPerTapEnabled(false);
mChart.setOnChartGestureListener(new OnChartGestureListener() {
mChart = (GraphView) findViewById(R.id.chart);
@Override
public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {}
// disable scrolling at the moment
mChart.getViewport().setScalable(false);
mChart.getViewport().setScrollable(false);
mChart.getViewport().setXAxisBoundsManual(true);
final long now = System.currentTimeMillis(),
left = now - chartZoom * 60 * 60 * 1000;
@Override
public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {}
mChart.getViewport().setMaxX(now);
mChart.getViewport().setMinX(left);
mChart.getViewport().setOnXAxisBoundsChangedListener(new Viewport.OnXAxisBoundsChangedListener() {
@Override
public void onChartLongPressed(MotionEvent me) {
mChart.fitScreen();
public void onXAxisBoundsChanged(double minX, double maxX, Reason reason) {
double rightX = mChart.getSeries().get(0).getHighestValueX();
hasZoomedChart = (rightX != maxX || rightX - chartZoom * 60 * 60 * 1000 != minX);
}
@Override
public void onChartDoubleTapped(MotionEvent me) {}
@Override
public void onChartSingleTapped(MotionEvent me) {}
@Override
public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) {}
@Override
public void onChartScale(MotionEvent me, float scaleX, float scaleY) {}
@Override
public void onChartTranslate(MotionEvent me, float dX, float dY) {}
});
XAxis xAxis = mChart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setTextSize(10f);
xAxis.setTextColor(Color.WHITE);
xAxis.setDrawAxisLine(true);
xAxis.setDrawGridLines(true);
xAxis.setDrawLabels(true);
xAxis.setValueFormatter(new IAxisValueFormatter() {
private DateFormat mFormat = DateFormat.getTimeInstance(DateFormat.SHORT);
mChart.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
return mFormat.format(new Date((long) value));
public boolean onLongClick(View v) {
if (!mChart.getSeries().isEmpty() && !mChart.getSeries().get(0).isEmpty()) {
double rightX = mChart.getSeries().get(0).getHighestValueX();
mChart.getViewport().setMaxX(rightX);
mChart.getViewport().setMinX(rightX - chartZoom * 60 * 60 * 1000);
}
hasZoomedChart = false;
return true;
}
});
mChart.getGridLabelRenderer().setNumHorizontalLabels(6);
mChart.getGridLabelRenderer().setHumanRounding(false);
// left axis
mChart.getAxisLeft().setDrawLabels(false);
// right axis
YAxis yAxis = mChart.getAxisRight();
yAxis.setTextSize(10f);
yAxis.setTextColor(Color.WHITE);
mChart.getLegend().setEnabled(false); // Hide the legend
// TODO: remove if if "coloring bug" in MPAndroidChart is fixed
// see: https://github.com/PhilJay/MPAndroidChart/issues/2682
mChart.setRenderer(new ScatterChartRenderer(mChart, mChart.getAnimator(), mChart.getViewPortHandler()) {
float[] mPixelBuffer = new float[2];
mChart.getGridLabelRenderer().setLabelFormatter(new DefaultLabelFormatter() {
DateFormat mFormat = DateFormat.getTimeInstance(DateFormat.SHORT);
@Override
protected void drawDataSet(Canvas c, IScatterDataSet dataSet) {
ViewPortHandler viewPortHandler = mViewPortHandler;
Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
float phaseY = mAnimator.getPhaseY();
IShapeRenderer renderer = dataSet.getShapeRenderer();
if (renderer == null) {
Log.i("MISSING", "There's no IShapeRenderer specified for ScatterDataSet");
return;
}
int max = (int)(Math.min(
Math.ceil((float)dataSet.getEntryCount() * mAnimator.getPhaseX()),
(float)dataSet.getEntryCount()));
for (int i = 0; i < max; i++) {
Entry e = dataSet.getEntryForIndex(i);
mPixelBuffer[0] = e.getX();
mPixelBuffer[1] = e.getY() * phaseY;
trans.pointValuesToPixel(mPixelBuffer);
if (!viewPortHandler.isInBoundsRight(mPixelBuffer[0]))
break;
if (!viewPortHandler.isInBoundsLeft(mPixelBuffer[0])
|| !viewPortHandler.isInBoundsY(mPixelBuffer[1]))
continue;
mRenderPaint.setColor(dataSet.getColor(i));
renderer.renderShape(
c, dataSet, mViewPortHandler,
mPixelBuffer[0], mPixelBuffer[1],
mRenderPaint);
public String formatLabel(double value, boolean isValueX) {
if (isValueX) {
return mFormat.format(new Date((long) value));
} else {
if (mmolxl) {
return sgvFormatter.format(value / MMOLXLFACTOR);
} else {
return sgvFormatter.format(value);
}
}
}
});
}}
);
}
@Override
......@@ -462,7 +425,18 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
}
private void startCgmService() {
startCgmService(System.currentTimeMillis() + 1000);
startCgmServiceDelayed(0);
}
private void startCgmServiceDelayed(long delay) {
RealmResults<PumpStatusEvent> results = mRealm.where(PumpStatusEvent.class)
.findAllSorted("eventDate", Sort.DESCENDING);
if (results.size() > 0) {
startCgmService(getNextPoll(results.first()) + delay);
} else {
startCgmService(System.currentTimeMillis() + (delay==0?1000:delay));
}
}
private void startCgmService(long initialPoll) {
......@@ -543,7 +517,17 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
mEnableCgmService = true;
startCgmService();
}
} else if (key.equals("mmolxl")) {
} else if (key.equals("mmolxl") || key.equals("mmolDecimals")) {
mmolxl = sharedPreferences.getBoolean("mmolxl", false);
mmolxlDecimals = sharedPreferences.getBoolean("mmolDecimals", false);
if (mmolxl) {
if (mmolxlDecimals)
sgvFormatter = new DecimalFormat("0.00");
else
sgvFormatter = new DecimalFormat("0.0");
} else {
sgvFormatter = new DecimalFormat("0");
}
refreshDisplay();
} else if (key.equals("pollInterval")) {
MainActivity.pollInterval = Long.parseLong(sharedPreferences.getString("pollInterval",
......@@ -553,6 +537,10 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
Long.toString(MedtronicCnlIntentService.LOW_BATTERY_POLL_PERIOD_MS)));
} else if (key.equals("doublePollOnPumpAway")) {
MainActivity.reducePollOnPumpAway = sharedPreferences.getBoolean("doublePollOnPumpAway", false);
} else if (key.equals("chartZoom")) {
chartZoom = Integer.parseInt(sharedPreferences.getString("chartZoom", "3"));
hasZoomedChart = false;
refreshDisplay();
}
}
......@@ -737,7 +725,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
TextView textViewBg = (TextView) findViewById(R.id.textview_bg);
TextView textViewBgTime = (TextView) findViewById(R.id.textview_bg_time);
TextView textViewUnits = (TextView) findViewById(R.id.textview_units);
if (prefs.getBoolean("mmolxl", false)) {
if (mmolxl) {
textViewUnits.setText(R.string.text_unit_mmolxl);
} else {
textViewUnits.setText(R.string.text_unit_mgxdl);
......@@ -763,27 +751,17 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
if (pumpStatusData != null) {
String sgvString, units;
if (prefs.getBoolean("mmolxl", false)) {
DecimalFormat df;
if (prefs.getBoolean("mmolDecimals", false))
df = new DecimalFormat("0.00");
else
df = new DecimalFormat("0.0");
String sgvString;
if (mmolxl) {
float fBgValue = (float) pumpStatusData.getSgv();
sgvString = df.format(fBgValue / 18.016f);
units = "mmol/L";
sgvString = sgvFormatter.format(fBgValue / MMOLXLFACTOR);
Log.d(TAG, sgvString + " mmol/L");
} else {
sgvString = String.valueOf(pumpStatusData.getSgv());
units = "mg/dL";
Log.d(TAG, sgvString + " mg/dL");
}
textViewBg.setText(sgvString);
textViewUnits.setText(units);
textViewBgTime.setText(DateUtils.getRelativeTimeSpanString(pumpStatusData.getEventDate().getTime()));
textViewTrend.setText(Html.fromHtml(renderTrendHtml(pumpStatusData.getCgmTrend())));
textViewIOB.setText(String.format(Locale.getDefault(), "%.2f", pumpStatusData.getActiveInsulin()));
......@@ -825,77 +803,102 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
private void updateChart(RealmResults<PumpStatusEvent> results) {
int size = results.size();
if (size == 0) return;
if (size == 0) {
final long now = System.currentTimeMillis(),
left = now - chartZoom * 60 * 60 * 1000;
mChart.getViewport().setXAxisBoundsManual(true);
mChart.getViewport().setMaxX(now);
mChart.getViewport().setMinX(left);
mChart.getViewport().setYAxisBoundsManual(true);
if (mmolxl) {
mChart.getViewport().setMinY(80 / MMOLXLFACTOR);
mChart.getViewport().setMaxY(120 / MMOLXLFACTOR);
} else {
mChart.getViewport().setMinY(80);
mChart.getViewport().setMaxY(120);
}
mChart.postInvalidate();
return;
}
List<Entry> entries = new ArrayList<Entry>(size);
int[] colors = new int[size]; // getColor is called with (i/2)
DataPoint[] entries = new DataPoint[size];
final long left = System.currentTimeMillis() - chartZoom * 60 * 60 * 1000;
int pos = 0;
for (PumpStatusEvent pumpStatus: results) {
// turn your data into Entry objects
int sgv = pumpStatus.getSgv(),
pos = entries.size();
entries.add(new Entry(pumpStatus.getEventDate().getTime(), pumpStatus.getSgv()));
//TODO: need to be configurable
if (sgv < 80)
colors[pos] = Color.RED;
else if (sgv <= 180)
colors[pos] = Color.GREEN;
else if (sgv <= 260)
colors[pos] = Color.YELLOW;
else
colors[pos] = Color.RED;
int sgv = pumpStatus.getSgv();
if (mmolxl) {
entries[pos++] = new DataPoint(pumpStatus.getEventDate(), pumpStatus.getSgv() / MMOLXLFACTOR);
} else {
entries[pos++] = new DataPoint(pumpStatus.getEventDate(), pumpStatus.getSgv());
}
}
if (mChart.getData() == null) {
mChart.setMinimumHeight(200);
ScatterDataSet dataSet = new ScatterDataSet(entries, null);
if (mChart.getSeries().size() == 0) {
// long now = System.currentTimeMillis();
// entries = new DataPoint[1000];
// int j = 0;
// for(long i = now - 24*60*60*1000; i < now - 30*60*1000; i+= 5*60*1000) {
// entries[j++] = new DataPoint(i, (float) (Math.random()*200 + 89));
// }
// entries = Arrays.copyOfRange(entries, 0, j);
dataSet.setColors(colors); // disabled tue to a bug(??) in MPAndroid Chart
//dataSet.setColor(Color.LTGRAY);
dataSet.setValueTextColor(Color.WHITE);
dataSet.setScatterShape(ScatterChart.ScatterShape.CIRCLE);
dataSet.setScatterShapeSize(7.2f);
dataSet.setValueFormatter(new IValueFormatter() {
@Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
DecimalFormat df;
PointsGraphSeries sgvSerie = new PointsGraphSeries(entries);
// sgvSerie.setSize(3.6f);
// sgvSerie.setColor(Color.LTGRAY);
sgvSerie.setOnDataPointTapListener(new OnDataPointTapListener() {
DateFormat mFormat = DateFormat.getTimeInstance(DateFormat.MEDIUM);
if (prefs.getBoolean("mmolxl", false)) {
if (prefs.getBoolean("mmolDecimals", false))
df = new DecimalFormat("0.00");
else
df = new DecimalFormat("0.0");
@Override
public void onTap(Series series, DataPointInterface dataPoint) {
double sgv = dataPoint.getY();
return df.format(value / 18.016f);
StringBuilder sb = new StringBuilder(mFormat.format(new Date((long) dataPoint.getX())) + ": ");
if (mmolxl) {
sb.append(sgvFormatter.format(sgv / MMOLXLFACTOR));
} else {
return new DecimalFormat("0").format(value);
sb.append(sgvFormatter.format(sgv));
}
Toast.makeText(getBaseContext(), sb.toString(), Toast.LENGTH_SHORT).show();
}
});
ArrayList<IScatterDataSet> dataSets = new ArrayList<IScatterDataSet>();
dataSets.add(dataSet);
sgvSerie.setCustomShape(new PointsGraphSeries.CustomShape() {
@Override
public void draw(Canvas canvas, Paint paint, float x, float y, DataPointInterface dataPoint) {
double sgv = dataPoint.getY();
if (sgv < 80)
paint.setColor(Color.RED);
else if (sgv <= 180)
paint.setColor(Color.GREEN);
else if (sgv <= 260)
paint.setColor(Color.YELLOW);
else
paint.setColor(Color.RED);
canvas.drawCircle(x, y, 3.6f, paint);
}
});
ScatterData lineData = new ScatterData(dataSets);
mChart.setData(lineData);
mChart.getViewport().setYAxisBoundsManual(false);
mChart.addSeries(sgvSerie);
} else {
((ScatterDataSet)mChart.getScatterData().getDataSets().get(0)).setValues(entries);
((ScatterDataSet)mChart.getScatterData().getDataSets().get(0)).setColors(colors); // disabled tue to a bug(??) in MPAndroid Chart
if (entries.length > 0) {
((PointsGraphSeries) mChart.getSeries().get(0)).resetData(entries);
}
}
//TODO: make the display timespan configurable
//long now = System.currentTimeMillis();
//Log.d(TAG, "Graph limits: " + (new Date(now - 24 * 60 * 60 * 1000) + " - " + (new Date(now))));
//mChart.setVisibleXRangeMaximum(12);
//mChart.setVisibleXRangeMinimum(0);
//mChart.getXAxis().setAxisMaximum((now + 0*60*1000));
//mChart.getXAxis().setAxisMinimum(now - 35 * 60 * 1000);
//mChart.moveViewToX(now - 35*60*1000); // - 24 * 60 * 60 * 1000);
//mChart.invalidate();
mChart.postInvalidate();
// set vieport to latest SGV
long lastSGVTimestamp = (long) mChart.getSeries().get(0).getHighestValueX();
if (!hasZoomedChart) {
mChart.getViewport().setMaxX(lastSGVTimestamp);
mChart.getViewport().setMinX(lastSGVTimestamp - chartZoom * 60 * 60 * 1000);
}
}
}
......@@ -934,7 +937,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
if (hasUsbPermission()) {
// Give the USB a little time to warm up first
startCgmService(System.currentTimeMillis() + MedtronicCnlIntentService.USB_WARMUP_TIME_MS);
startCgmServiceDelayed(MedtronicCnlIntentService.USB_WARMUP_TIME_MS);
} else {
Log.d(TAG, "No permission for USB. Waiting.");
waitForUsbPermission();
......@@ -964,31 +967,4 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
}
}
private class PumsStatusDataSet extends RealmScatterDataSet<PumpStatusEvent> {
public PumsStatusDataSet(RealmResults<PumpStatusEvent> result, String yValuesField) {
super(result, yValuesField);
}
public PumsStatusDataSet(RealmResults<PumpStatusEvent> result, String xValuesField, String yValuesField) {
super(result, xValuesField, yValuesField);
}
public Entry buildEntryFromResultObject(PumpStatusEvent realmObject, float x) {
DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject);
float xFloat, yFloat;
if (mXValuesField == null) {
xFloat = x;
} else {
xFloat = dynamicObject.getDate(mXValuesField).getTime();
}
yFloat = dynamicObject.getInt(mYValuesField);
return new Entry(mXValuesField == null ? x : xFloat, yFloat);
}
}
}
......@@ -21,15 +21,14 @@ import java.util.Date;
import java.util.Locale;
import java.util.concurrent.TimeoutException;
import info.nightscout.android.BuildConfig;
import info.nightscout.android.R;
import info.nightscout.android.USB.UsbHidDriver;
import info.nightscout.android.medtronic.MainActivity;
import info.nightscout.android.medtronic.MedtronicCnlReader;
import info.nightscout.android.medtronic.exception.ChecksumException;
import info.nightscout.android.medtronic.exception.EncryptionException;
import info.nightscout.android.medtronic.message.MessageUtils;
import info.nightscout.android.medtronic.exception.UnexpectedMessageException;
import info.nightscout.android.medtronic.message.MessageUtils;
import info.nightscout.android.model.medtronicNg.ContourNextLinkInfo;
import info.nightscout.android.model.medtronicNg.PumpInfo;
import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
......@@ -38,8 +37,6 @@ import info.nightscout.android.xdrip_plus.XDripPlusUploadReceiver;
import io.realm.Realm;
import io.realm.RealmResults;
import static info.nightscout.android.medtronic.MainActivity.setActivePumpMac;
public class MedtronicCnlIntentService extends IntentService {
public final static int USB_VID = 0x1a79;
public final static int USB_PID = 0x6210;
......@@ -155,12 +152,7 @@ public class MedtronicCnlIntentService extends IntentService {
.findFirst();
if (info == null) {
// TODO - use realm.createObject()?
info = realm.createObject(ContourNextLinkInfo.class, cnlReader.getStickSerial());
//info = new ContourNextLinkInfo();
///info.setSerialNumber(cnlReader.getStickSerial());
//info = realm.copyToRealm(info);
}
cnlReader.getPumpSession().setStickSerial(info.getSerialNumber());
......@@ -204,7 +196,7 @@ public class MedtronicCnlIntentService extends IntentService {
// reduce polling interval to half until pump is available
MedtronicCnlAlarmManager.setAlarm(activePump.getLastQueryTS() +
(MainActivity.pollInterval + MedtronicCnlIntentService.POLL_GRACE_PERIOD_MS) / (MainActivity.reducePollOnPumpAway?2L:1L)
(MainActivity.pollInterval / (MainActivity.reducePollOnPumpAway?2L:1L))
);
} else {
setActivePumpMac(pumpMAC);
......
package info.nightscout.android.model.medtronicNg;
import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet;
import java.util.Date;
import io.realm.RealmObject;
......
......@@ -51,8 +51,7 @@ public class SettingsFragment extends PreferenceFragment implements OnSharedPref
*/
private void setMinBatPollIntervall(ListPreference pollIntervalPref, ListPreference lowBatPollIntervalPref) {
final String currentValue = lowBatPollIntervalPref.getValue();
final int pollIntervalPos = pollIntervalPref.findIndexOfValue(pollIntervalPref.getValue()),
lowBatPollIntervalPos = lowBatPollIntervalPref.findIndexOfValue(currentValue),
final int pollIntervalPos = (pollIntervalPref.findIndexOfValue(pollIntervalPref.getValue()) >= 0?pollIntervalPref.findIndexOfValue(pollIntervalPref.getValue()):0),
length = pollIntervalPref.getEntries().length;
CharSequence[] entries = new String[length - pollIntervalPos],
......
......@@ -119,11 +119,10 @@
</LinearLayout>
<com.github.mikephil.charting.charts.ScatterChart
android:id="@+id/chart"
<com.jjoe64.graphview.GraphView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="visible" />
android:layout_height="100dip"
android:id="@+id/chart" />
<ScrollView
android:id="@+id/scrollView"
......
......@@ -21,4 +21,20 @@
<item>3600000</item>
<!--item>0</item-->
</string-array>
<string-array name="chart_zoom">
<item>1 hour</item>
<item>3 hours</item>
<item>6 hours</item>
<item>12 hours</item>
<item>24 hours</item>
</string-array>
<string-array name="chart_zoom_hours">
<item>1</item>
<item>3</item>
<item>6</item>
<item>12</item>
<item>24</item>
</string-array>
</resources>
\ No newline at end of file
......@@ -57,4 +57,5 @@
<string name="no_registered_contour_next_link_devices">No registered Contour Next Link devices</string>
<string name="to_register_a_contour_next_link_you_must_first_plug_it_in_and_get_a_reading_from_the_pump">To register a Contour Next Link you must first plug it in, and get a reading from the pump.</string>
<string name="serial_number">Serial number</string>
<string name="preferences_chart_interval">Chart Zoom</string>
</resources>
......@@ -41,6 +41,15 @@
android:entries="@array/poll_interval"
android:entryValues="@array/poll_interval_millis"/>
</PreferenceCategory>
<PreferenceCategory android:title="Display">
<ListPreference
android:key="chartZoom"
android:defaultValue="3"
android:title="@string/preferences_chart_interval"
android:summary="%s"
android:entries="@array/chart_zoom"
android:entryValues="@array/chart_zoom_hours"/>
</PreferenceCategory>
<PreferenceCategory android:title="Sharing">
<CheckBoxPreference
android:disableDependentsState="false"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment