mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2025-02-05 05:24:12 +01:00
Garmin/Zepp OS: Display resting HR
This commit is contained in:
parent
fb1d0a92cc
commit
bd3b7467a4
@ -12,7 +12,6 @@ import androidx.core.content.ContextCompat;
|
|||||||
|
|
||||||
import com.github.mikephil.charting.charts.Chart;
|
import com.github.mikephil.charting.charts.Chart;
|
||||||
import com.github.mikephil.charting.charts.LineChart;
|
import com.github.mikephil.charting.charts.LineChart;
|
||||||
import com.github.mikephil.charting.components.Legend;
|
|
||||||
import com.github.mikephil.charting.components.LegendEntry;
|
import com.github.mikephil.charting.components.LegendEntry;
|
||||||
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;
|
||||||
@ -23,6 +22,7 @@ import com.github.mikephil.charting.data.LineDataSet;
|
|||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -35,6 +35,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.HeartRateSample;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||||
|
|
||||||
public class HeartRateDailyFragment extends AbstractChartFragment<HeartRateDailyFragment.HeartRateData> {
|
public class HeartRateDailyFragment extends AbstractChartFragment<HeartRateDailyFragment.HeartRateData> {
|
||||||
@ -50,7 +51,6 @@ public class HeartRateDailyFragment extends AbstractChartFragment<HeartRateDaily
|
|||||||
private TextView hrAverage;
|
private TextView hrAverage;
|
||||||
private TextView hrMinimum;
|
private TextView hrMinimum;
|
||||||
private TextView hrMaximum;
|
private TextView hrMaximum;
|
||||||
private LinearLayout heartRateRestingWrapper;
|
|
||||||
private LineChart hrLineChart;
|
private LineChart hrLineChart;
|
||||||
|
|
||||||
|
|
||||||
@ -70,21 +70,22 @@ public class HeartRateDailyFragment extends AbstractChartFragment<HeartRateDaily
|
|||||||
hrAverage = rootView.findViewById(R.id.hr_average);
|
hrAverage = rootView.findViewById(R.id.hr_average);
|
||||||
hrMinimum = rootView.findViewById(R.id.hr_minimum);
|
hrMinimum = rootView.findViewById(R.id.hr_minimum);
|
||||||
hrMaximum = rootView.findViewById(R.id.hr_maximum);
|
hrMaximum = rootView.findViewById(R.id.hr_maximum);
|
||||||
heartRateRestingWrapper = rootView.findViewById(R.id.hr_resting_wrapper);
|
final LinearLayout heartRateRestingWrapper = rootView.findViewById(R.id.hr_resting_wrapper);
|
||||||
|
|
||||||
setupChart();
|
setupChart();
|
||||||
refresh();
|
refresh();
|
||||||
setupLegend(hrLineChart);
|
setupLegend(hrLineChart);
|
||||||
|
|
||||||
if (!supportHeartRateRestingMeasurement()) {
|
if (!supportsHeartRateRestingMeasurement()) {
|
||||||
heartRateRestingWrapper.setVisibility(View.GONE);
|
heartRateRestingWrapper.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rootView;
|
return rootView;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean supportHeartRateRestingMeasurement() {
|
public boolean supportsHeartRateRestingMeasurement() {
|
||||||
return false;
|
final GBDevice device = getChartsHost().getDevice();
|
||||||
|
return device.getDeviceCoordinator().supportsHeartRateRestingMeasurement(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<? extends AbstractActivitySample> getActivitySamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) {
|
protected List<? extends AbstractActivitySample> getActivitySamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) {
|
||||||
@ -124,7 +125,19 @@ public class HeartRateDailyFragment extends AbstractChartFragment<HeartRateDaily
|
|||||||
String formattedDate = new SimpleDateFormat("E, MMM dd").format(date);
|
String formattedDate = new SimpleDateFormat("E, MMM dd").format(date);
|
||||||
mDateView.setText(formattedDate);
|
mDateView.setText(formattedDate);
|
||||||
List<? extends ActivitySample> samples = getActivitySamples(db, device, startTs, endTs);
|
List<? extends ActivitySample> samples = getActivitySamples(db, device, startTs, endTs);
|
||||||
return new HeartRateData(samples);
|
|
||||||
|
int restingHeartRate = -1;
|
||||||
|
if (supportsHeartRateRestingMeasurement()) {
|
||||||
|
restingHeartRate = device.getDeviceCoordinator()
|
||||||
|
.getHeartRateRestingSampleProvider(device, db.getDaoSession())
|
||||||
|
.getAllSamples(startTs * 1000L, endTs * 1000L)
|
||||||
|
.stream()
|
||||||
|
.max(Comparator.comparingLong(HeartRateSample::getTimestamp))
|
||||||
|
.map(HeartRateSample::getHeartRate)
|
||||||
|
.orElse(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new HeartRateData(samples, restingHeartRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -186,7 +199,6 @@ public class HeartRateDailyFragment extends AbstractChartFragment<HeartRateDaily
|
|||||||
final List<Entry> lineEntries = new ArrayList<>();
|
final List<Entry> lineEntries = new ArrayList<>();
|
||||||
List<? extends ActivitySample> samples = data.samples;
|
List<? extends ActivitySample> samples = data.samples;
|
||||||
int average = 0;
|
int average = 0;
|
||||||
int resting = 0;
|
|
||||||
int minimum = 0;
|
int minimum = 0;
|
||||||
int maximum = 0;
|
int maximum = 0;
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
@ -233,7 +245,7 @@ public class HeartRateDailyFragment extends AbstractChartFragment<HeartRateDaily
|
|||||||
hrAverage.setText(average > 0 ? getString(R.string.bpm_value_unit, average) : "-");
|
hrAverage.setText(average > 0 ? getString(R.string.bpm_value_unit, average) : "-");
|
||||||
hrMinimum.setText(minimum > 0 ? getString(R.string.bpm_value_unit, minimum) : "-");
|
hrMinimum.setText(minimum > 0 ? getString(R.string.bpm_value_unit, minimum) : "-");
|
||||||
hrMaximum.setText(maximum > 0 ? getString(R.string.bpm_value_unit, maximum) : "-");
|
hrMaximum.setText(maximum > 0 ? getString(R.string.bpm_value_unit, maximum) : "-");
|
||||||
hrResting.setText(resting > 0 ? getString(R.string.bpm_value_unit, resting) : "-");
|
hrResting.setText(data.restingHeartRate > 0 ? getString(R.string.bpm_value_unit, data.restingHeartRate) : "-");
|
||||||
|
|
||||||
|
|
||||||
if (minimum > 0) {
|
if (minimum > 0) {
|
||||||
@ -251,9 +263,11 @@ public class HeartRateDailyFragment extends AbstractChartFragment<HeartRateDaily
|
|||||||
|
|
||||||
protected static class HeartRateData extends ChartsData {
|
protected static class HeartRateData extends ChartsData {
|
||||||
public List<? extends ActivitySample> samples;
|
public List<? extends ActivitySample> samples;
|
||||||
|
public int restingHeartRate;
|
||||||
|
|
||||||
protected HeartRateData(List<? extends ActivitySample> samples) {
|
protected HeartRateData(List<? extends ActivitySample> samples, int restingHeartRate) {
|
||||||
this.samples = samples;
|
this.samples = samples;
|
||||||
|
this.restingHeartRate = restingHeartRate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -643,6 +643,11 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsHeartRateRestingMeasurement(final GBDevice device) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportsManualHeartRateMeasurement(final GBDevice device) {
|
public boolean supportsManualHeartRateMeasurement(final GBDevice device) {
|
||||||
return supportsHeartRateMeasurement(device);
|
return supportsHeartRateMeasurement(device);
|
||||||
|
@ -462,6 +462,11 @@ public interface DeviceCoordinator {
|
|||||||
*/
|
*/
|
||||||
boolean supportsHeartRateMeasurement(GBDevice device);
|
boolean supportsHeartRateMeasurement(GBDevice device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given device supports resting heart rate measurements.
|
||||||
|
*/
|
||||||
|
boolean supportsHeartRateRestingMeasurement(GBDevice device);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the device supports triggering manual one-shot heart rate measurements.
|
* Returns true if the device supports triggering manual one-shot heart rate measurements.
|
||||||
*/
|
*/
|
||||||
|
@ -259,6 +259,11 @@ public abstract class GarminCoordinator extends AbstractBLEDeviceCoordinator {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsHeartRateRestingMeasurement(final GBDevice device) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportsRealtimeData() {
|
public boolean supportsRealtimeData() {
|
||||||
return true;
|
return true;
|
||||||
|
@ -120,6 +120,11 @@ public abstract class HuamiCoordinator extends AbstractBLEDeviceCoordinator {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsHeartRateRestingMeasurement(final GBDevice device) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getSupportedDeviceSpecificAuthenticationSettings() {
|
public int[] getSupportedDeviceSpecificAuthenticationSettings() {
|
||||||
return new int[]{R.xml.devicesettings_pairingkey};
|
return new int[]{R.xml.devicesettings_pairingkey};
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
android:id="@+id/hr_minimum"
|
android:id="@+id/hr_minimum"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="0"
|
android:text="@string/stats_empty_value"
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -65,7 +65,7 @@
|
|||||||
android:id="@+id/hr_maximum"
|
android:id="@+id/hr_maximum"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="0"
|
android:text="@string/stats_empty_value"
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -83,7 +83,7 @@
|
|||||||
android:id="@+id/hr_average"
|
android:id="@+id/hr_average"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="0"
|
android:text="@string/stats_empty_value"
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -107,7 +107,7 @@
|
|||||||
android:id="@+id/hr_resting"
|
android:id="@+id/hr_resting"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="0"
|
android:text="@string/stats_empty_value"
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
Loading…
Reference in New Issue
Block a user