From 42420e676bd4078edf3607b002abb1c5b274d760 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Wed, 2 Sep 2015 23:49:06 +0200 Subject: [PATCH] More WIP: displays live activity data --- .../charts/LiveActivityFragment.java | 128 +++++++++++++++++- .../gadgetbridge/model/DeviceService.java | 1 + .../service/devices/miband/MiBandSupport.java | 3 +- .../res/layout/fragment_live_activity.xml | 7 + 4 files changed, 131 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java index d6610a84f..8b1cecc33 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java @@ -4,22 +4,30 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.graphics.Color; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.content.LocalBroadcastManager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Toast; import com.github.mikephil.charting.charts.BarLineChartBase; import com.github.mikephil.charting.charts.Chart; import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.ChartData; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.PieData; +import com.github.mikephil.charting.data.PieDataSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.text.NumberFormat; +import java.util.ArrayList; import java.util.List; import nodomain.freeyourgadget.gadgetbridge.GBApplication; @@ -28,12 +36,71 @@ import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; import nodomain.freeyourgadget.gadgetbridge.model.DeviceService; +import nodomain.freeyourgadget.gadgetbridge.util.GB; public class LiveActivityFragment extends AbstractChartFragment { private static final Logger LOG = LoggerFactory.getLogger(LiveActivityFragment.class); + private Entry totalStepsEntry; + private Entry stepsPerMinuteEntry; + private PieData mStepsPerMinuteData; + private PieData mTotalStepsData; + + private class Steps { + private int steps; + private long lastTimestamp; + private int currentStepsPerMinute; + + public int getStepsPerMinute() { + return currentStepsPerMinute; + } + + public int getTotalSteps() { + return steps; + } + + public void updateCurrentSteps(int newSteps, long timestamp) { + try { + if (steps == 0) { + steps = newSteps; + lastTimestamp = timestamp; + return; + } + + if (newSteps >= steps) { + int stepsDelta = newSteps - steps; + long timeDelta = timestamp - lastTimestamp; + currentStepsPerMinute = calculateStepsPerMinute(stepsDelta, timeDelta); + steps = newSteps; + lastTimestamp = timestamp; + } else { + // TODO: handle new day? + + } + } catch (Exception ex) { + GB.toast(LiveActivityFragment.this.getContext(), ex.getMessage(), Toast.LENGTH_SHORT, GB.ERROR, ex); + } + } + + private int calculateStepsPerMinute(int stepsDelta, long millis) { + if (stepsDelta == 0) { + return 0; // not walking or not enough data per mills? + } + if (millis <= 0) { + throw new IllegalArgumentException("delta in millis is <= 0 -- time change?"); + } + + long oneMinute = 60 * 1000; + float factor = oneMinute / millis; + return (int) (stepsDelta * factor); + } + } + private BarLineChartBase mStepsPerMinuteHistoryChart; private PieChart mStepsPerMinuteCurrentChart; + private PieChart mStepsTotalChart; + + private Steps mSteps = new Steps(); private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override @@ -42,31 +109,45 @@ public class LiveActivityFragment extends AbstractChartFragment { switch (action) { case DeviceService.ACTION_REALTIME_STEPS: int steps = intent.getIntExtra(DeviceService.EXTRA_REALTIME_STEPS, 0); - updateCurrentSteps(steps); + long timestamp = intent.getLongExtra(DeviceService.EXTRA_TIMESTAMP, System.currentTimeMillis()); + refreshCurrentSteps(steps, timestamp); break; } } }; - private void updateCurrentSteps(int steps) { - LOG.warn("STEPS: " + steps); - } + private void refreshCurrentSteps(int steps, long timestamp) { + mSteps.updateCurrentSteps(steps, timestamp); + totalStepsEntry.setVal(mSteps.getTotalSteps()); + mStepsTotalChart.setCenterText(NumberFormat.getNumberInstance().format(mSteps.getTotalSteps())); + stepsPerMinuteEntry.setVal(mSteps.getStepsPerMinute()); + mStepsPerMinuteCurrentChart.setCenterText(NumberFormat.getNumberInstance().format(mSteps.getStepsPerMinute())); + mTotalStepsData.notifyDataChanged(); + mStepsPerMinuteData.notifyDataChanged(); + + renderCharts(); + } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { IntentFilter filterLocal = new IntentFilter(); - filterLocal.addAction(DeviceService.ACTION_ENABLE_REALTIME_STEPS); + filterLocal.addAction(DeviceService.ACTION_REALTIME_STEPS); LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mReceiver, filterLocal); View rootView = inflater.inflate(R.layout.fragment_live_activity, container, false); mStepsPerMinuteHistoryChart = (BarLineChartBase) rootView.findViewById(R.id.livechart_steps_per_minute_history); mStepsPerMinuteCurrentChart = (PieChart) rootView.findViewById(R.id.livechart_steps_per_minute_current); + mStepsTotalChart = (PieChart) rootView.findViewById(R.id.livechart_steps_total); + + totalStepsEntry = new Entry(0, 0); + stepsPerMinuteEntry = new Entry(0, 0); setupHistoryChart(mStepsPerMinuteHistoryChart); - setupCurrentChart(mStepsPerMinuteCurrentChart); + mStepsPerMinuteData = setupCurrentChart(mStepsPerMinuteCurrentChart, stepsPerMinuteEntry); + mTotalStepsData = setupTotalStepsChart(mStepsTotalChart, totalStepsEntry); return rootView; } @@ -89,14 +170,46 @@ public class LiveActivityFragment extends AbstractChartFragment { super.onDestroyView(); } - private void setupCurrentChart(PieChart chart) { + private PieData setupCurrentChart(PieChart chart, Entry entry) { chart.setBackgroundColor(BACKGROUND_COLOR); chart.setDescriptionColor(DESCRIPTION_COLOR); chart.setDescription(""); chart.setNoDataTextDescription(""); chart.setNoDataText(""); + + PieData data = new PieData(); + List entries = new ArrayList<>(); + List colors = new ArrayList<>(); + + int value = 0; + chart.setCenterText(NumberFormat.getNumberInstance().format(value)); + entries.add(entry); + colors.add(akActivity.color); + //we don't want labels on the pie chart + data.addXValue(""); + +// entries.add(new Entry((20), 1)); +// colors.add(Color.GRAY); +// //we don't want labels on the pie chart +// data.addXValue(""); + + PieDataSet set = new PieDataSet(entries, ""); + set.setColors(colors); + data.setDataSet(set); + //this hides the values (numeric) added to the set. These would be shown aside the strings set with addXValue above + data.setDrawValues(false); + chart.setData(data); + + chart.getLegend().setEnabled(false); + + return data; } + private PieData setupTotalStepsChart(PieChart chart, Entry entry) { + return setupCurrentChart(chart, entry); // at the moment, these look the same + } + + private void setupHistoryChart(BarLineChartBase chart) { chart.setBackgroundColor(BACKGROUND_COLOR); chart.setDescriptionColor(DESCRIPTION_COLOR); @@ -139,6 +252,7 @@ public class LiveActivityFragment extends AbstractChartFragment { @Override protected void renderCharts() { mStepsPerMinuteCurrentChart.animateXY(50, 50); + mStepsTotalChart.animateXY(50, 50); mStepsPerMinuteHistoryChart.invalidate(); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java index 41b345d52..2833019b3 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java @@ -51,6 +51,7 @@ public interface DeviceService extends EventHandler { static final String EXTRA_PERFORM_PAIR = "perform_pair"; static final String EXTRA_ENABLE_REALTIME_STEPS = "enable_realtime_steps"; static final String EXTRA_REALTIME_STEPS = "realtime_steps"; + static final String EXTRA_TIMESTAMP = "timestamp"; void start(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java index 328e0d1ac..e01fc6509 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java @@ -665,7 +665,8 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { int steps = 0xff & value[0] | (0xff & value[1]) << 8; LOG.debug("realtime steps: " + steps); Intent intent = new Intent(DeviceService.ACTION_REALTIME_STEPS) - .putExtra(DeviceService.EXTRA_REALTIME_STEPS, steps); + .putExtra(DeviceService.EXTRA_REALTIME_STEPS, steps) + .putExtra(DeviceService.EXTRA_TIMESTAMP, System.currentTimeMillis()); LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent); } diff --git a/app/src/main/res/layout/fragment_live_activity.xml b/app/src/main/res/layout/fragment_live_activity.xml index 8d7b5a2f0..9129d81e0 100644 --- a/app/src/main/res/layout/fragment_live_activity.xml +++ b/app/src/main/res/layout/fragment_live_activity.xml @@ -17,4 +17,11 @@ android:layout_weight="20"> + + + \ No newline at end of file