mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-28 12:56:49 +01:00
Some work in progress for heart rate graphs #178
Currently we get the heart rate when synchronizing activity data (i.e. not live) and we write it to the activity database so that we can show a nice graph. The value is currently always 0 though, because we can't enable recording hr, yet.
This commit is contained in:
parent
df741e9571
commit
0ef738067d
@ -12,9 +12,14 @@ import android.view.View;
|
|||||||
|
|
||||||
import com.github.mikephil.charting.charts.BarLineChartBase;
|
import com.github.mikephil.charting.charts.BarLineChartBase;
|
||||||
import com.github.mikephil.charting.charts.Chart;
|
import com.github.mikephil.charting.charts.Chart;
|
||||||
|
import com.github.mikephil.charting.charts.CombinedChart;
|
||||||
import com.github.mikephil.charting.data.BarData;
|
import com.github.mikephil.charting.data.BarData;
|
||||||
import com.github.mikephil.charting.data.BarDataSet;
|
import com.github.mikephil.charting.data.BarDataSet;
|
||||||
import com.github.mikephil.charting.data.BarEntry;
|
import com.github.mikephil.charting.data.BarEntry;
|
||||||
|
import com.github.mikephil.charting.data.CombinedData;
|
||||||
|
import com.github.mikephil.charting.data.Entry;
|
||||||
|
import com.github.mikephil.charting.data.LineData;
|
||||||
|
import com.github.mikephil.charting.data.LineDataSet;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -23,6 +28,7 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -72,12 +78,16 @@ public abstract class AbstractChartFragment extends AbstractGBFragment {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
private boolean mChartDirty = true;
|
private boolean mChartDirty = true;
|
||||||
|
private boolean supportsHeartrateChart = false;
|
||||||
|
|
||||||
public boolean isChartDirty() {
|
public boolean isChartDirty() {
|
||||||
return mChartDirty;
|
return mChartDirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract String getTitle();
|
public abstract String getTitle();
|
||||||
|
public boolean supportsHeartrate() {
|
||||||
|
return supportsHeartrateChart;
|
||||||
|
}
|
||||||
|
|
||||||
protected static final class ActivityConfig {
|
protected static final class ActivityConfig {
|
||||||
public final int type;
|
public final int type;
|
||||||
@ -101,6 +111,7 @@ public abstract class AbstractChartFragment extends AbstractGBFragment {
|
|||||||
protected int DESCRIPTION_COLOR;
|
protected int DESCRIPTION_COLOR;
|
||||||
protected int CHART_TEXT_COLOR;
|
protected int CHART_TEXT_COLOR;
|
||||||
protected int LEGEND_TEXT_COLOR;
|
protected int LEGEND_TEXT_COLOR;
|
||||||
|
protected int HEARTRATE_COLOR;
|
||||||
protected int AK_ACTIVITY_COLOR;
|
protected int AK_ACTIVITY_COLOR;
|
||||||
protected int AK_DEEP_SLEEP_COLOR;
|
protected int AK_DEEP_SLEEP_COLOR;
|
||||||
protected int AK_LIGHT_SLEEP_COLOR;
|
protected int AK_LIGHT_SLEEP_COLOR;
|
||||||
@ -134,6 +145,7 @@ public abstract class AbstractChartFragment extends AbstractGBFragment {
|
|||||||
DESCRIPTION_COLOR = getResources().getColor(R.color.primarytext);
|
DESCRIPTION_COLOR = getResources().getColor(R.color.primarytext);
|
||||||
CHART_TEXT_COLOR = getResources().getColor(R.color.secondarytext);
|
CHART_TEXT_COLOR = getResources().getColor(R.color.secondarytext);
|
||||||
LEGEND_TEXT_COLOR = getResources().getColor(R.color.primarytext);
|
LEGEND_TEXT_COLOR = getResources().getColor(R.color.primarytext);
|
||||||
|
HEARTRATE_COLOR = getResources().getColor(R.color.chart_heartrate);
|
||||||
AK_ACTIVITY_COLOR = getResources().getColor(R.color.chart_activity_light);
|
AK_ACTIVITY_COLOR = getResources().getColor(R.color.chart_activity_light);
|
||||||
AK_DEEP_SLEEP_COLOR = getResources().getColor(R.color.chart_light_sleep_light);
|
AK_DEEP_SLEEP_COLOR = getResources().getColor(R.color.chart_light_sleep_light);
|
||||||
AK_LIGHT_SLEEP_COLOR = getResources().getColor(R.color.chart_deep_sleep_light);
|
AK_LIGHT_SLEEP_COLOR = getResources().getColor(R.color.chart_deep_sleep_light);
|
||||||
@ -389,6 +401,8 @@ public abstract class AbstractChartFragment extends AbstractGBFragment {
|
|||||||
int numEntries = samples.size();
|
int numEntries = samples.size();
|
||||||
List<String> xLabels = new ArrayList<>(numEntries);
|
List<String> xLabels = new ArrayList<>(numEntries);
|
||||||
List<BarEntry> activityEntries = new ArrayList<>(numEntries);
|
List<BarEntry> activityEntries = new ArrayList<>(numEntries);
|
||||||
|
boolean hr = supportsHeartrate();
|
||||||
|
List<Entry> heartrateEntries = hr ? new ArrayList<Entry>(numEntries) : null;
|
||||||
List<Integer> colors = new ArrayList<>(numEntries); // this is kinda inefficient...
|
List<Integer> colors = new ArrayList<>(numEntries); // this is kinda inefficient...
|
||||||
|
|
||||||
for (int i = 0; i < numEntries; i++) {
|
for (int i = 0; i < numEntries; i++) {
|
||||||
@ -431,6 +445,9 @@ public abstract class AbstractChartFragment extends AbstractGBFragment {
|
|||||||
colors.add(akActivity.color);
|
colors.add(akActivity.color);
|
||||||
}
|
}
|
||||||
activityEntries.add(createBarEntry(value, i));
|
activityEntries.add(createBarEntry(value, i));
|
||||||
|
if (hr) {
|
||||||
|
heartrateEntries.add(createLineEntry(sample.getCustomShortValue(), i));
|
||||||
|
}
|
||||||
|
|
||||||
String xLabel = "";
|
String xLabel = "";
|
||||||
if (annotate) {
|
if (annotate) {
|
||||||
@ -463,13 +480,19 @@ public abstract class AbstractChartFragment extends AbstractGBFragment {
|
|||||||
chart.getXAxis().setValues(xLabels);
|
chart.getXAxis().setValues(xLabels);
|
||||||
|
|
||||||
BarDataSet activitySet = createActivitySet(activityEntries, colors, "Activity");
|
BarDataSet activitySet = createActivitySet(activityEntries, colors, "Activity");
|
||||||
|
|
||||||
ArrayList<BarDataSet> dataSets = new ArrayList<>();
|
|
||||||
dataSets.add(activitySet);
|
|
||||||
|
|
||||||
// create a data object with the datasets
|
// create a data object with the datasets
|
||||||
BarData data = new BarData(xLabels, dataSets);
|
CombinedData combinedData = new CombinedData(xLabels);
|
||||||
data.setGroupSpace(0);
|
List<BarDataSet> list = new ArrayList<>();
|
||||||
|
list.add(activitySet);
|
||||||
|
BarData barData = new BarData(xLabels, list);
|
||||||
|
barData.setGroupSpace(0);
|
||||||
|
combinedData.setData(barData);
|
||||||
|
|
||||||
|
if (hr) {
|
||||||
|
LineDataSet heartrateSet = createHeartrateSet(heartrateEntries, "Heart Rate");
|
||||||
|
LineData lineData = new LineData(xLabels, heartrateSet);
|
||||||
|
combinedData.setData(lineData);
|
||||||
|
}
|
||||||
|
|
||||||
chart.setDescription("");
|
chart.setDescription("");
|
||||||
// chart.setDescription(getString(R.string.sleep_activity_date_range, dateStringFrom, dateStringTo));
|
// chart.setDescription(getString(R.string.sleep_activity_date_range, dateStringFrom, dateStringTo));
|
||||||
@ -477,7 +500,7 @@ public abstract class AbstractChartFragment extends AbstractGBFragment {
|
|||||||
|
|
||||||
setupLegend(chart);
|
setupLegend(chart);
|
||||||
|
|
||||||
chart.setData(data);
|
chart.setData(combinedData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,6 +521,10 @@ public abstract class AbstractChartFragment extends AbstractGBFragment {
|
|||||||
return new BarEntry(value, index);
|
return new BarEntry(value, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Entry createLineEntry(float value, int index) {
|
||||||
|
return new Entry(value, index);
|
||||||
|
}
|
||||||
|
|
||||||
protected BarDataSet createActivitySet(List<BarEntry> values, List<Integer> colors, String label) {
|
protected BarDataSet createActivitySet(List<BarEntry> values, List<Integer> colors, String label) {
|
||||||
BarDataSet set1 = new BarDataSet(values, label);
|
BarDataSet set1 = new BarDataSet(values, label);
|
||||||
set1.setColors(colors);
|
set1.setColors(colors);
|
||||||
@ -515,6 +542,24 @@ public abstract class AbstractChartFragment extends AbstractGBFragment {
|
|||||||
return set1;
|
return set1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected LineDataSet createHeartrateSet(List<Entry> values, String label) {
|
||||||
|
LineDataSet set1 = new LineDataSet(values, label);
|
||||||
|
set1.setColor(HEARTRATE_COLOR);
|
||||||
|
// set1.setColors(colors);
|
||||||
|
// set1.setDrawCubic(true);
|
||||||
|
// set1.setCubicIntensity(0.2f);
|
||||||
|
// //set1.setDrawFilled(true);
|
||||||
|
// set1.setDrawCircles(false);
|
||||||
|
// set1.setLineWidth(2f);
|
||||||
|
// set1.setCircleSize(5f);
|
||||||
|
// set1.setFillColor(ColorTemplate.getHoloBlue());
|
||||||
|
set1.setDrawValues(false);
|
||||||
|
// set1.setHighLightColor(Color.rgb(128, 0, 255));
|
||||||
|
// set1.setColor(Color.rgb(89, 178, 44));
|
||||||
|
set1.setValueTextColor(CHART_TEXT_COLOR);
|
||||||
|
return set1;
|
||||||
|
}
|
||||||
|
|
||||||
protected BarDataSet createDeepSleepSet(List<BarEntry> values, String label) {
|
protected BarDataSet createDeepSleepSet(List<BarEntry> values, String label) {
|
||||||
BarDataSet set1 = new BarDataSet(values, label);
|
BarDataSet set1 = new BarDataSet(values, label);
|
||||||
// set1.setDrawCubic(true);
|
// set1.setDrawCubic(true);
|
||||||
|
@ -78,7 +78,7 @@ public class ActivitySleepChartFragment extends AbstractChartFragment {
|
|||||||
|
|
||||||
YAxis yAxisRight = mChart.getAxisRight();
|
YAxis yAxisRight = mChart.getAxisRight();
|
||||||
yAxisRight.setDrawGridLines(false);
|
yAxisRight.setDrawGridLines(false);
|
||||||
yAxisRight.setEnabled(false);
|
yAxisRight.setEnabled(supportsHeartrate());
|
||||||
yAxisRight.setDrawLabels(false);
|
yAxisRight.setDrawLabels(false);
|
||||||
yAxisRight.setDrawTopYLabelEntry(false);
|
yAxisRight.setDrawTopYLabelEntry(false);
|
||||||
yAxisRight.setTextColor(CHART_TEXT_COLOR);
|
yAxisRight.setTextColor(CHART_TEXT_COLOR);
|
||||||
|
@ -10,6 +10,7 @@ import android.view.ViewGroup;
|
|||||||
import com.github.mikephil.charting.animation.Easing;
|
import com.github.mikephil.charting.animation.Easing;
|
||||||
import com.github.mikephil.charting.charts.BarLineChartBase;
|
import com.github.mikephil.charting.charts.BarLineChartBase;
|
||||||
import com.github.mikephil.charting.charts.Chart;
|
import com.github.mikephil.charting.charts.Chart;
|
||||||
|
import com.github.mikephil.charting.charts.CombinedChart;
|
||||||
import com.github.mikephil.charting.charts.PieChart;
|
import com.github.mikephil.charting.charts.PieChart;
|
||||||
import com.github.mikephil.charting.components.XAxis;
|
import com.github.mikephil.charting.components.XAxis;
|
||||||
import com.github.mikephil.charting.components.YAxis;
|
import com.github.mikephil.charting.components.YAxis;
|
||||||
@ -39,7 +40,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
|||||||
public class SleepChartFragment extends AbstractChartFragment {
|
public class SleepChartFragment extends AbstractChartFragment {
|
||||||
protected static final Logger LOG = LoggerFactory.getLogger(ActivitySleepChartFragment.class);
|
protected static final Logger LOG = LoggerFactory.getLogger(ActivitySleepChartFragment.class);
|
||||||
|
|
||||||
private BarLineChartBase mActivityChart;
|
private CombinedChart mActivityChart;
|
||||||
private PieChart mSleepAmountChart;
|
private PieChart mSleepAmountChart;
|
||||||
|
|
||||||
private int mSmartAlarmFrom = -1;
|
private int mSmartAlarmFrom = -1;
|
||||||
@ -99,7 +100,7 @@ public class SleepChartFragment extends AbstractChartFragment {
|
|||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View rootView = inflater.inflate(R.layout.fragment_sleepchart, container, false);
|
View rootView = inflater.inflate(R.layout.fragment_sleepchart, container, false);
|
||||||
|
|
||||||
mActivityChart = (BarLineChartBase) rootView.findViewById(R.id.sleepchart);
|
mActivityChart = (CombinedChart) rootView.findViewById(R.id.sleepchart);
|
||||||
mSleepAmountChart = (PieChart) rootView.findViewById(R.id.sleepchart_pie_light_deep);
|
mSleepAmountChart = (PieChart) rootView.findViewById(R.id.sleepchart_pie_light_deep);
|
||||||
|
|
||||||
setupActivityChart();
|
setupActivityChart();
|
||||||
|
@ -27,13 +27,14 @@ import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_PROV
|
|||||||
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_STEPS;
|
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_STEPS;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_TIMESTAMP;
|
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_TIMESTAMP;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_TYPE;
|
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_TYPE;
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_CUSTOM_SHORT;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.TABLE_GBACTIVITYSAMPLES;
|
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.TABLE_GBACTIVITYSAMPLES;
|
||||||
|
|
||||||
public class ActivityDatabaseHandler extends SQLiteOpenHelper implements DBHandler {
|
public class ActivityDatabaseHandler extends SQLiteOpenHelper implements DBHandler {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ActivityDatabaseHandler.class);
|
private static final Logger LOG = LoggerFactory.getLogger(ActivityDatabaseHandler.class);
|
||||||
|
|
||||||
private static final int DATABASE_VERSION = 5;
|
private static final int DATABASE_VERSION = 6;
|
||||||
|
|
||||||
public ActivityDatabaseHandler(Context context) {
|
public ActivityDatabaseHandler(Context context) {
|
||||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||||
@ -101,6 +102,7 @@ public class ActivityDatabaseHandler extends SQLiteOpenHelper implements DBHandl
|
|||||||
values.put(KEY_PROVIDER, sample.getProvider().getID());
|
values.put(KEY_PROVIDER, sample.getProvider().getID());
|
||||||
values.put(KEY_INTENSITY, sample.getRawIntensity());
|
values.put(KEY_INTENSITY, sample.getRawIntensity());
|
||||||
values.put(KEY_STEPS, sample.getSteps());
|
values.put(KEY_STEPS, sample.getSteps());
|
||||||
|
values.put(KEY_CUSTOM_SHORT, sample.getCustomShortValue());
|
||||||
values.put(KEY_TYPE, sample.getRawKind());
|
values.put(KEY_TYPE, sample.getRawKind());
|
||||||
|
|
||||||
db.insert(TABLE_GBACTIVITYSAMPLES, null, values);
|
db.insert(TABLE_GBACTIVITYSAMPLES, null, values);
|
||||||
@ -117,7 +119,7 @@ public class ActivityDatabaseHandler extends SQLiteOpenHelper implements DBHandl
|
|||||||
* @param kind the raw activity kind of the sample
|
* @param kind the raw activity kind of the sample
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void addGBActivitySample(int timestamp, byte provider, short intensity, short steps, byte kind) {
|
public void addGBActivitySample(int timestamp, byte provider, short intensity, short steps, byte kind, short customShortValue) {
|
||||||
if (intensity < 0) {
|
if (intensity < 0) {
|
||||||
LOG.error("negative intensity received, ignoring");
|
LOG.error("negative intensity received, ignoring");
|
||||||
intensity = 0;
|
intensity = 0;
|
||||||
@ -127,6 +129,11 @@ public class ActivityDatabaseHandler extends SQLiteOpenHelper implements DBHandl
|
|||||||
steps = 0;
|
steps = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (customShortValue < 0) {
|
||||||
|
LOG.error("negative short value received, ignoring");
|
||||||
|
customShortValue = 0;
|
||||||
|
}
|
||||||
|
|
||||||
try (SQLiteDatabase db = this.getWritableDatabase()) {
|
try (SQLiteDatabase db = this.getWritableDatabase()) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(KEY_TIMESTAMP, timestamp);
|
values.put(KEY_TIMESTAMP, timestamp);
|
||||||
@ -134,6 +141,7 @@ public class ActivityDatabaseHandler extends SQLiteOpenHelper implements DBHandl
|
|||||||
values.put(KEY_INTENSITY, intensity);
|
values.put(KEY_INTENSITY, intensity);
|
||||||
values.put(KEY_STEPS, steps);
|
values.put(KEY_STEPS, steps);
|
||||||
values.put(KEY_TYPE, kind);
|
values.put(KEY_TYPE, kind);
|
||||||
|
values.put(KEY_CUSTOM_SHORT, customShortValue);
|
||||||
|
|
||||||
db.insert(TABLE_GBACTIVITYSAMPLES, null, values);
|
db.insert(TABLE_GBACTIVITYSAMPLES, null, values);
|
||||||
}
|
}
|
||||||
@ -144,8 +152,8 @@ public class ActivityDatabaseHandler extends SQLiteOpenHelper implements DBHandl
|
|||||||
try (SQLiteDatabase db = this.getWritableDatabase()) {
|
try (SQLiteDatabase db = this.getWritableDatabase()) {
|
||||||
|
|
||||||
String sql = "INSERT INTO " + TABLE_GBACTIVITYSAMPLES + " (" + KEY_TIMESTAMP + "," +
|
String sql = "INSERT INTO " + TABLE_GBACTIVITYSAMPLES + " (" + KEY_TIMESTAMP + "," +
|
||||||
KEY_PROVIDER + "," + KEY_INTENSITY + "," + KEY_STEPS + "," + KEY_TYPE + ")" +
|
KEY_PROVIDER + "," + KEY_INTENSITY + "," + KEY_STEPS + "," + KEY_TYPE + "," + KEY_CUSTOM_SHORT + ")" +
|
||||||
" VALUES (?,?,?,?,?);";
|
" VALUES (?,?,?,?,?,?);";
|
||||||
SQLiteStatement statement = db.compileStatement(sql);
|
SQLiteStatement statement = db.compileStatement(sql);
|
||||||
db.beginTransaction();
|
db.beginTransaction();
|
||||||
|
|
||||||
@ -156,6 +164,7 @@ public class ActivityDatabaseHandler extends SQLiteOpenHelper implements DBHandl
|
|||||||
statement.bindLong(3, activitySample.getRawIntensity());
|
statement.bindLong(3, activitySample.getRawIntensity());
|
||||||
statement.bindLong(4, activitySample.getSteps());
|
statement.bindLong(4, activitySample.getSteps());
|
||||||
statement.bindLong(5, activitySample.getRawKind());
|
statement.bindLong(5, activitySample.getRawKind());
|
||||||
|
statement.bindLong(6, activitySample.getCustomShortValue());
|
||||||
statement.execute();
|
statement.execute();
|
||||||
}
|
}
|
||||||
db.setTransactionSuccessful();
|
db.setTransactionSuccessful();
|
||||||
@ -216,7 +225,8 @@ public class ActivityDatabaseHandler extends SQLiteOpenHelper implements DBHandl
|
|||||||
cursor.getInt(cursor.getColumnIndex(KEY_TIMESTAMP)),
|
cursor.getInt(cursor.getColumnIndex(KEY_TIMESTAMP)),
|
||||||
cursor.getShort(cursor.getColumnIndex(KEY_INTENSITY)),
|
cursor.getShort(cursor.getColumnIndex(KEY_INTENSITY)),
|
||||||
cursor.getShort(cursor.getColumnIndex(KEY_STEPS)),
|
cursor.getShort(cursor.getColumnIndex(KEY_STEPS)),
|
||||||
(byte) cursor.getShort(cursor.getColumnIndex(KEY_TYPE)));
|
(byte) cursor.getShort(cursor.getColumnIndex(KEY_TYPE)),
|
||||||
|
cursor.getShort(cursor.getColumnIndex(KEY_CUSTOM_SHORT)));
|
||||||
samples.add(sample);
|
samples.add(sample);
|
||||||
} while (cursor.moveToNext());
|
} while (cursor.moveToNext());
|
||||||
}
|
}
|
||||||
|
@ -10,5 +10,6 @@ public class DBConstants {
|
|||||||
public static final String KEY_PROVIDER = "provider";
|
public static final String KEY_PROVIDER = "provider";
|
||||||
public static final String KEY_INTENSITY = "intensity";
|
public static final String KEY_INTENSITY = "intensity";
|
||||||
public static final String KEY_STEPS = "steps";
|
public static final String KEY_STEPS = "steps";
|
||||||
|
public static final String KEY_CUSTOM_SHORT = "customShort";
|
||||||
public static final String KEY_TYPE = "type";
|
public static final String KEY_TYPE = "type";
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ public interface DBHandler {
|
|||||||
|
|
||||||
List<ActivitySample> getSleepSamples(int tsFrom, int tsTo, SampleProvider provider);
|
List<ActivitySample> getSleepSamples(int tsFrom, int tsTo, SampleProvider provider);
|
||||||
|
|
||||||
void addGBActivitySample(int timestamp, byte provider, short intensity, short steps, byte kind);
|
void addGBActivitySample(int timestamp, byte provider, short intensity, short steps, byte kind, short heartrate);
|
||||||
|
|
||||||
void addGBActivitySamples(ActivitySample[] activitySamples);
|
void addGBActivitySamples(ActivitySample[] activitySamples);
|
||||||
|
|
||||||
|
@ -5,27 +5,25 @@ import android.database.sqlite.SQLiteDatabase;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.database.DBUpdateScript;
|
import nodomain.freeyourgadget.gadgetbridge.database.DBUpdateScript;
|
||||||
|
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_CUSTOM_SHORT;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_PROVIDER;
|
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_PROVIDER;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_STEPS;
|
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_STEPS;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_TIMESTAMP;
|
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_TIMESTAMP;
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.TABLE_GBACTIVITYSAMPLES;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.TABLE_STEPS_PER_DAY;
|
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.TABLE_STEPS_PER_DAY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a table "STEPS_PER_DAY".
|
* Adds a column "customShort" to the table "GBActivitySamples"
|
||||||
*/
|
*/
|
||||||
public class ActivityDBUpdate_6 implements DBUpdateScript {
|
public class ActivityDBUpdate_6 implements DBUpdateScript {
|
||||||
@Override
|
@Override
|
||||||
public void upgradeSchema(SQLiteDatabase db) {
|
public void upgradeSchema(SQLiteDatabase db) {
|
||||||
String CREATE_STEPS_PER_DAY_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_STEPS_PER_DAY + " ("
|
String ADD_COLUMN_CUSTOM_SHORT = "ALTER TABLE " + TABLE_GBACTIVITYSAMPLES + " ADD COLUMN "
|
||||||
+ KEY_TIMESTAMP + " INT,"
|
+ KEY_CUSTOM_SHORT + " INT;";
|
||||||
+ KEY_PROVIDER + " TINYINT,"
|
db.execSQL(ADD_COLUMN_CUSTOM_SHORT);
|
||||||
+ KEY_STEPS + " MEDIUMINT,"
|
|
||||||
+ " PRIMARY KEY (" + KEY_TIMESTAMP + "," + KEY_PROVIDER + ") ON CONFLICT REPLACE)" + DBHelper.getWithoutRowId();
|
|
||||||
db.execSQL(CREATE_STEPS_PER_DAY_TABLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void downgradeSchema(SQLiteDatabase db) {
|
public void downgradeSchema(SQLiteDatabase db) {
|
||||||
DBHelper.dropTable(TABLE_STEPS_PER_DAY, db);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.database.schema;
|
||||||
|
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.database.DBUpdateScript;
|
||||||
|
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_PROVIDER;
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_STEPS;
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_TIMESTAMP;
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.TABLE_STEPS_PER_DAY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a table "STEPS_PER_DAY".
|
||||||
|
*/
|
||||||
|
public class ActivityDBUpdate_X implements DBUpdateScript {
|
||||||
|
@Override
|
||||||
|
public void upgradeSchema(SQLiteDatabase db) {
|
||||||
|
String CREATE_STEPS_PER_DAY_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_STEPS_PER_DAY + " ("
|
||||||
|
+ KEY_TIMESTAMP + " INT,"
|
||||||
|
+ KEY_PROVIDER + " TINYINT,"
|
||||||
|
+ KEY_STEPS + " MEDIUMINT,"
|
||||||
|
+ " PRIMARY KEY (" + KEY_TIMESTAMP + "," + KEY_PROVIDER + ") ON CONFLICT REPLACE)" + DBHelper.getWithoutRowId();
|
||||||
|
db.execSQL(CREATE_STEPS_PER_DAY_TABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void downgradeSchema(SQLiteDatabase db) {
|
||||||
|
DBHelper.dropTable(TABLE_STEPS_PER_DAY, db);
|
||||||
|
}
|
||||||
|
}
|
@ -9,19 +9,19 @@ public class GBActivitySample implements ActivitySample {
|
|||||||
private final SampleProvider provider;
|
private final SampleProvider provider;
|
||||||
private final short intensity;
|
private final short intensity;
|
||||||
private final short steps;
|
private final short steps;
|
||||||
private final short heartrate;
|
|
||||||
private final byte type;
|
private final byte type;
|
||||||
|
private final short customShortValue;
|
||||||
|
|
||||||
public GBActivitySample(SampleProvider provider, int timestamp, short intensity, short steps, byte type) {
|
public GBActivitySample(SampleProvider provider, int timestamp, short intensity, short steps, byte type) {
|
||||||
this(provider, timestamp, intensity, steps, (short) 0, type);
|
this(provider, timestamp, intensity, steps, type, (short) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GBActivitySample(SampleProvider provider, int timestamp, short intensity, short steps, short heartrate, byte type) {
|
public GBActivitySample(SampleProvider provider, int timestamp, short intensity, short steps, byte type, short customShortValue) {
|
||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
this.intensity = intensity;
|
this.intensity = intensity;
|
||||||
this.steps = steps;
|
this.steps = steps;
|
||||||
this.heartrate = heartrate;
|
this.customShortValue = customShortValue;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
@ -36,8 +36,8 @@ public class GBActivitySample implements ActivitySample {
|
|||||||
if (timestamp < 0) {
|
if (timestamp < 0) {
|
||||||
throw new IllegalArgumentException("timestamp must be >= 0");
|
throw new IllegalArgumentException("timestamp must be >= 0");
|
||||||
}
|
}
|
||||||
if (heartrate < 0) {
|
if (customShortValue < 0) {
|
||||||
throw new IllegalArgumentException("heartrate must be >= 0");
|
throw new IllegalArgumentException("customShortValue must be >= 0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,8 +77,8 @@ public class GBActivitySample implements ActivitySample {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public short getHeartRate() {
|
public short getCustomShortValue() {
|
||||||
return heartrate;
|
return customShortValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -87,7 +87,7 @@ public class GBActivitySample implements ActivitySample {
|
|||||||
"timestamp=" + DateTimeUtils.formatDateTime(DateTimeUtils.parseTimeStamp(timestamp)) +
|
"timestamp=" + DateTimeUtils.formatDateTime(DateTimeUtils.parseTimeStamp(timestamp)) +
|
||||||
", intensity=" + getIntensity() +
|
", intensity=" + getIntensity() +
|
||||||
", steps=" + getSteps() +
|
", steps=" + getSteps() +
|
||||||
", heartrate=" + getHeartRate() +
|
", customShortValue=" + getCustomShortValue() +
|
||||||
", type=" + getKind() +
|
", type=" + getKind() +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
@ -42,5 +42,5 @@ public interface ActivitySample {
|
|||||||
*/
|
*/
|
||||||
short getSteps();
|
short getSteps();
|
||||||
|
|
||||||
short getHeartRate();
|
short getCustomShortValue();
|
||||||
}
|
}
|
||||||
|
@ -305,7 +305,7 @@ public class FetchActivityOperation extends AbstractMiBandOperation {
|
|||||||
}
|
}
|
||||||
int bpm = getBytesPerMinuteOfActivityData();
|
int bpm = getBytesPerMinuteOfActivityData();
|
||||||
LOG.debug("flushing activity data samples: " + activityStruct.activityDataHolderProgress / bpm);
|
LOG.debug("flushing activity data samples: " + activityStruct.activityDataHolderProgress / bpm);
|
||||||
byte category, intensity, steps, heartrate;
|
byte category, intensity, steps, heartrate = 0;
|
||||||
|
|
||||||
DBHandler dbHandler = null;
|
DBHandler dbHandler = null;
|
||||||
try {
|
try {
|
||||||
@ -334,7 +334,8 @@ public class FetchActivityOperation extends AbstractMiBandOperation {
|
|||||||
timestampInSeconds,
|
timestampInSeconds,
|
||||||
(short) (intensity & 0xff),
|
(short) (intensity & 0xff),
|
||||||
(short) (steps & 0xff),
|
(short) (steps & 0xff),
|
||||||
category);
|
category,
|
||||||
|
(short) (heartrate & 0xff));
|
||||||
|
|
||||||
// next minute
|
// next minute
|
||||||
minutes++;
|
minutes++;
|
||||||
|
@ -55,7 +55,7 @@ public class AppMessageHandlerGBPebble extends AppMessageHandler {
|
|||||||
byte type = (byte) ((sample & 0xe000) >>> 13);
|
byte type = (byte) ((sample & 0xe000) >>> 13);
|
||||||
byte intensity = (byte) ((sample & 0x1f80) >>> 7);
|
byte intensity = (byte) ((sample & 0x1f80) >>> 7);
|
||||||
byte steps = (byte) (sample & 0x007f);
|
byte steps = (byte) (sample & 0x007f);
|
||||||
db.addGBActivitySample(timestamp + offset_seconds, SampleProvider.PROVIDER_PEBBLE_GADGETBRIDGE, (short) (intensity & 0xff), (short) (steps & 0xff), type);
|
db.addGBActivitySample(timestamp + offset_seconds, SampleProvider.PROVIDER_PEBBLE_GADGETBRIDGE, (short) (intensity & 0xff), (short) (steps & 0xff), type, (short)0);
|
||||||
offset_seconds += 60;
|
offset_seconds += 60;
|
||||||
}
|
}
|
||||||
} catch (GBException e) {
|
} catch (GBException e) {
|
||||||
|
@ -93,7 +93,7 @@ public class AppMessageHandlerMorpheuz extends AppMessageHandler {
|
|||||||
DBHandler db = null;
|
DBHandler db = null;
|
||||||
try {
|
try {
|
||||||
db = GBApplication.acquireDB();
|
db = GBApplication.acquireDB();
|
||||||
db.addGBActivitySample(recording_base_timestamp + index * 600, SampleProvider.PROVIDER_PEBBLE_MORPHEUZ, intensity, (byte) 0, type);
|
db.addGBActivitySample(recording_base_timestamp + index * 600, SampleProvider.PROVIDER_PEBBLE_MORPHEUZ, intensity, (byte) 0, type, (short)0);
|
||||||
} catch (GBException e) {
|
} catch (GBException e) {
|
||||||
LOG.error("Error acquiring database", e);
|
LOG.error("Error acquiring database", e);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
android:layout_weight="40">
|
android:layout_weight="40">
|
||||||
</com.github.mikephil.charting.charts.PieChart>
|
</com.github.mikephil.charting.charts.PieChart>
|
||||||
|
|
||||||
<com.github.mikephil.charting.charts.BarChart
|
<com.github.mikephil.charting.charts.CombinedChart
|
||||||
android:id="@+id/sleepchart"
|
android:id="@+id/sleepchart"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity$PlaceholderFragment">
|
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity$PlaceholderFragment">
|
||||||
|
|
||||||
<com.github.mikephil.charting.charts.BarChart
|
<com.github.mikephil.charting.charts.CombinedChart
|
||||||
android:id="@+id/activitysleepchart"
|
android:id="@+id/activitysleepchart"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
android:layout_weight="20">
|
android:layout_weight="20">
|
||||||
</com.github.mikephil.charting.charts.PieChart>
|
</com.github.mikephil.charting.charts.PieChart>
|
||||||
|
|
||||||
<com.github.mikephil.charting.charts.BarChart
|
<com.github.mikephil.charting.charts.CombinedChart
|
||||||
android:id="@+id/sleepchart"
|
android:id="@+id/sleepchart"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
<color name="secondarytext" type="color">#ff808080</color>
|
<color name="secondarytext" type="color">#ff808080</color>
|
||||||
<color name="divider" type="color">#1f000000</color>
|
<color name="divider" type="color">#1f000000</color>
|
||||||
|
|
||||||
|
<color name="chart_heartrate" type="color">#b40000</color>
|
||||||
<color name="chart_deep_sleep_light" type="color">#0071b7</color>
|
<color name="chart_deep_sleep_light" type="color">#0071b7</color>
|
||||||
<color name="chart_deep_sleep_dark" type="color">#4c5aff</color>
|
<color name="chart_deep_sleep_dark" type="color">#4c5aff</color>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user