mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-25 03:16:51 +01:00
Merge pull request #1181 from Dikay900/remove_invalid_hr_data
remove incorrect HR data <10 from the graphs
This commit is contained in:
commit
5e4ecd774b
@ -16,9 +16,14 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
package nodomain.freeyourgadget.gadgetbridge.activities;
|
package nodomain.freeyourgadget.gadgetbridge.activities;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||||
|
|
||||||
public class HeartRateUtils {
|
public class HeartRateUtils {
|
||||||
public static final int MAX_HEART_RATE_VALUE = 250;
|
public static final int MAX_HEART_RATE_VALUE = 250;
|
||||||
public static final int MIN_HEART_RATE_VALUE = 0;
|
public static final int MIN_HEART_RATE_VALUE = 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maxiumum gap between two hr measurements in which
|
* The maxiumum gap between two hr measurements in which
|
||||||
* we interpolate between the measurements. Otherwise, two
|
* we interpolate between the measurements. Otherwise, two
|
||||||
@ -28,7 +33,37 @@ public class HeartRateUtils {
|
|||||||
*/
|
*/
|
||||||
public static final int MAX_HR_MEASUREMENTS_GAP_MINUTES = 10;
|
public static final int MAX_HR_MEASUREMENTS_GAP_MINUTES = 10;
|
||||||
|
|
||||||
public static boolean isValidHeartRateValue(int value) {
|
private int maxHeartRateValue;
|
||||||
return value > HeartRateUtils.MIN_HEART_RATE_VALUE && value < HeartRateUtils.MAX_HEART_RATE_VALUE;
|
private int minHeartRateValue;
|
||||||
|
|
||||||
|
private static final HeartRateUtils instance = new HeartRateUtils();
|
||||||
|
|
||||||
|
public static HeartRateUtils getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton - to access this class use the static #getInstance()
|
||||||
|
*/
|
||||||
|
private HeartRateUtils() {
|
||||||
|
updateCachedHeartRatePreferences();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateCachedHeartRatePreferences(){
|
||||||
|
Prefs prefs = GBApplication.getPrefs();
|
||||||
|
maxHeartRateValue = prefs.getInt(GBPrefs.CHART_MAX_HEART_RATE, MAX_HEART_RATE_VALUE);
|
||||||
|
minHeartRateValue = prefs.getInt(GBPrefs.CHART_MIN_HEART_RATE, MIN_HEART_RATE_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxHeartRate(){
|
||||||
|
return maxHeartRateValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMinHeartRate(){
|
||||||
|
return minHeartRateValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValidHeartRateValue(int value) {
|
||||||
|
return value >= getMinHeartRate() && value <= getMaxHeartRate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,8 +70,6 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
|
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
|
||||||
|
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils.isValidHeartRateValue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A base class fragment to be used with ChartsActivity. The fragment can supply
|
* A base class fragment to be used with ChartsActivity. The fragment can supply
|
||||||
* a title to be displayed in the activity by returning non-null in #getTitle()
|
* a title to be displayed in the activity by returning non-null in #getTitle()
|
||||||
@ -443,6 +441,7 @@ public abstract class AbstractChartFragment extends AbstractGBFragment {
|
|||||||
List<Entry> heartrateEntries = hr ? new ArrayList<Entry>(numEntries) : null;
|
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...
|
||||||
int lastHrSampleIndex = -1;
|
int lastHrSampleIndex = -1;
|
||||||
|
HeartRateUtils heartRateUtilsInstance = HeartRateUtils.getInstance();
|
||||||
|
|
||||||
for (int i = 0; i < numEntries; i++) {
|
for (int i = 0; i < numEntries; i++) {
|
||||||
ActivitySample sample = samples.get(i);
|
ActivitySample sample = samples.get(i);
|
||||||
@ -512,7 +511,7 @@ public abstract class AbstractChartFragment extends AbstractGBFragment {
|
|||||||
}
|
}
|
||||||
activityEntries.add(createLineEntry(value, ts));
|
activityEntries.add(createLineEntry(value, ts));
|
||||||
}
|
}
|
||||||
if (hr && sample.getKind() != ActivityKind.TYPE_NOT_WORN && HeartRateUtils.isValidHeartRateValue(sample.getHeartRate())) {
|
if (hr && sample.getKind() != ActivityKind.TYPE_NOT_WORN && heartRateUtilsInstance.isValidHeartRateValue(sample.getHeartRate())) {
|
||||||
if (lastHrSampleIndex > -1 && ts - lastHrSampleIndex > 1800*HeartRateUtils.MAX_HR_MEASUREMENTS_GAP_MINUTES) {
|
if (lastHrSampleIndex > -1 && ts - lastHrSampleIndex > 1800*HeartRateUtils.MAX_HR_MEASUREMENTS_GAP_MINUTES) {
|
||||||
heartrateEntries.add(createLineEntry(0, lastHrSampleIndex + 1));
|
heartrateEntries.add(createLineEntry(0, lastHrSampleIndex + 1));
|
||||||
heartrateEntries.add(createLineEntry(0, ts - 1));
|
heartrateEntries.add(createLineEntry(0, ts - 1));
|
||||||
|
@ -104,8 +104,8 @@ public class ActivitySleepChartFragment extends AbstractChartFragment {
|
|||||||
yAxisRight.setDrawLabels(true);
|
yAxisRight.setDrawLabels(true);
|
||||||
yAxisRight.setDrawTopYLabelEntry(true);
|
yAxisRight.setDrawTopYLabelEntry(true);
|
||||||
yAxisRight.setTextColor(CHART_TEXT_COLOR);
|
yAxisRight.setTextColor(CHART_TEXT_COLOR);
|
||||||
yAxisRight.setAxisMaximum(HeartRateUtils.MAX_HEART_RATE_VALUE);
|
yAxisRight.setAxisMaximum(HeartRateUtils.getInstance().getMaxHeartRate());
|
||||||
yAxisRight.setAxisMinimum(HeartRateUtils.MIN_HEART_RATE_VALUE);
|
yAxisRight.setAxisMinimum(HeartRateUtils.getInstance().getMinHeartRate());
|
||||||
|
|
||||||
// refresh immediately instead of use refreshIfVisible(), for perceived performance
|
// refresh immediately instead of use refreshIfVisible(), for perceived performance
|
||||||
refresh();
|
refresh();
|
||||||
|
@ -168,7 +168,7 @@ public class LiveActivityFragment extends AbstractChartFragment {
|
|||||||
private void addSample(ActivitySample sample) {
|
private void addSample(ActivitySample sample) {
|
||||||
int heartRate = sample.getHeartRate();
|
int heartRate = sample.getHeartRate();
|
||||||
int timestamp = tsTranslation.shorten(sample.getTimestamp());
|
int timestamp = tsTranslation.shorten(sample.getTimestamp());
|
||||||
if (HeartRateUtils.isValidHeartRateValue(heartRate)) {
|
if (HeartRateUtils.getInstance().isValidHeartRateValue(heartRate)) {
|
||||||
setCurrentHeartRate(heartRate, timestamp);
|
setCurrentHeartRate(heartRate, timestamp);
|
||||||
}
|
}
|
||||||
int steps = sample.getSteps();
|
int steps = sample.getSteps();
|
||||||
@ -470,8 +470,8 @@ public class LiveActivityFragment extends AbstractChartFragment {
|
|||||||
yAxisRight.setDrawLabels(true);
|
yAxisRight.setDrawLabels(true);
|
||||||
yAxisRight.setDrawTopYLabelEntry(false);
|
yAxisRight.setDrawTopYLabelEntry(false);
|
||||||
yAxisRight.setTextColor(CHART_TEXT_COLOR);
|
yAxisRight.setTextColor(CHART_TEXT_COLOR);
|
||||||
yAxisRight.setAxisMaximum(HeartRateUtils.MAX_HEART_RATE_VALUE);
|
yAxisRight.setAxisMaximum(HeartRateUtils.getInstance().getMaxHeartRate());
|
||||||
yAxisRight.setAxisMinimum(HeartRateUtils.MIN_HEART_RATE_VALUE);
|
yAxisRight.setAxisMinimum(HeartRateUtils.getInstance().getMinHeartRate());
|
||||||
|
|
||||||
mHistorySet = new LineDataSet(new ArrayList<Entry>(), getString(R.string.live_activity_steps_history));
|
mHistorySet = new LineDataSet(new ArrayList<Entry>(), getString(R.string.live_activity_steps_history));
|
||||||
mHistorySet.setAxisDependency(YAxis.AxisDependency.LEFT);
|
mHistorySet.setAxisDependency(YAxis.AxisDependency.LEFT);
|
||||||
|
@ -233,8 +233,8 @@ public class SleepChartFragment extends AbstractChartFragment {
|
|||||||
yAxisRight.setDrawLabels(true);
|
yAxisRight.setDrawLabels(true);
|
||||||
yAxisRight.setDrawTopYLabelEntry(true);
|
yAxisRight.setDrawTopYLabelEntry(true);
|
||||||
yAxisRight.setTextColor(CHART_TEXT_COLOR);
|
yAxisRight.setTextColor(CHART_TEXT_COLOR);
|
||||||
yAxisRight.setAxisMaxValue(HeartRateUtils.MAX_HEART_RATE_VALUE);
|
yAxisRight.setAxisMaxValue(HeartRateUtils.getInstance().getMaxHeartRate());
|
||||||
yAxisRight.setAxisMinValue(HeartRateUtils.MIN_HEART_RATE_VALUE);
|
yAxisRight.setAxisMinValue(HeartRateUtils.getInstance().getMinHeartRate());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -151,7 +151,7 @@ public class GPXExporter implements ActivityTrackExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int hr = point.getHeartRate();
|
int hr = point.getHeartRate();
|
||||||
if (!HeartRateUtils.isValidHeartRateValue(hr)) {
|
if (!HeartRateUtils.getInstance().isValidHeartRateValue(hr)) {
|
||||||
if (!includeHeartRateOfNearestSample) {
|
if (!includeHeartRateOfNearestSample) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -162,7 +162,7 @@ public class GPXExporter implements ActivityTrackExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hr = closestPointItem.getHeartRate();
|
hr = closestPointItem.getHeartRate();
|
||||||
if (!HeartRateUtils.isValidHeartRateValue(hr)) {
|
if (!HeartRateUtils.getInstance().isValidHeartRateValue(hr)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,11 +177,12 @@ public class GPXExporter implements ActivityTrackExporter {
|
|||||||
|
|
||||||
private @Nullable ActivityPoint findClosestSensibleActivityPoint(Date time, List<ActivityPoint> trackPoints) {
|
private @Nullable ActivityPoint findClosestSensibleActivityPoint(Date time, List<ActivityPoint> trackPoints) {
|
||||||
ActivityPoint closestPointItem = null;
|
ActivityPoint closestPointItem = null;
|
||||||
|
HeartRateUtils heartRateUtilsInstance = HeartRateUtils.getInstance();
|
||||||
|
|
||||||
long lowestDifference = 60 * 2 * 1000; // minimum distance is 2min
|
long lowestDifference = 60 * 2 * 1000; // minimum distance is 2min
|
||||||
for (ActivityPoint pointItem : trackPoints) {
|
for (ActivityPoint pointItem : trackPoints) {
|
||||||
int hrItem = pointItem.getHeartRate();
|
int hrItem = pointItem.getHeartRate();
|
||||||
if (HeartRateUtils.isValidHeartRateValue(hrItem)) {
|
if (heartRateUtilsInstance.isValidHeartRateValue(hrItem)) {
|
||||||
Date timeItem = pointItem.getTime();
|
Date timeItem = pointItem.getTime();
|
||||||
if (timeItem.after(time) || timeItem.equals(time)) {
|
if (timeItem.after(time) || timeItem.equals(time)) {
|
||||||
break; // we assume that the given trackPoints are sorted in time ascending order (oldest first)
|
break; // we assume that the given trackPoints are sorted in time ascending order (oldest first)
|
||||||
|
@ -47,6 +47,7 @@ import java.util.UUID;
|
|||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.AlarmClockReceiver;
|
import nodomain.freeyourgadget.gadgetbridge.externalevents.AlarmClockReceiver;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.AlarmReceiver;
|
import nodomain.freeyourgadget.gadgetbridge.externalevents.AlarmReceiver;
|
||||||
@ -784,6 +785,9 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
|
|||||||
mDeviceSupport.setAutoReconnect(autoReconnect);
|
mDeviceSupport.setAutoReconnect(autoReconnect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (GBPrefs.CHART_MAX_HEART_RATE.equals(key) || GBPrefs.CHART_MIN_HEART_RATE.equals(key)) {
|
||||||
|
HeartRateUtils.getInstance().updateCachedHeartRatePreferences();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean hasPrefs() {
|
protected boolean hasPrefs() {
|
||||||
|
@ -38,6 +38,9 @@ public class GBPrefs {
|
|||||||
public static final String USER_NAME_DEFAULT = "gadgetbridge-user";
|
public static final String USER_NAME_DEFAULT = "gadgetbridge-user";
|
||||||
private static final String USER_BIRTHDAY = "";
|
private static final String USER_BIRTHDAY = "";
|
||||||
|
|
||||||
|
public static final String CHART_MAX_HEART_RATE = "chart_max_heart_rate";
|
||||||
|
public static final String CHART_MIN_HEART_RATE = "chart_min_heart_rate";
|
||||||
|
|
||||||
private final Prefs mPrefs;
|
private final Prefs mPrefs;
|
||||||
|
|
||||||
public GBPrefs(Prefs prefs) {
|
public GBPrefs(Prefs prefs) {
|
||||||
|
@ -469,6 +469,10 @@
|
|||||||
<string name="activity_prefs_height_cm">Height in cm</string>
|
<string name="activity_prefs_height_cm">Height in cm</string>
|
||||||
<string name="activity_prefs_weight_kg">Weight in kg</string>
|
<string name="activity_prefs_weight_kg">Weight in kg</string>
|
||||||
|
|
||||||
|
<string name="activity_prefs_charts">Chart settings</string>
|
||||||
|
<string name="activity_prefs_chart_max_heart_rate">Max heart rate</string>
|
||||||
|
<string name="activity_prefs_chart_min_heart_rate">Min heart rate</string>
|
||||||
|
|
||||||
<string name="authenticating">Authenticating</string>
|
<string name="authenticating">Authenticating</string>
|
||||||
<string name="authentication_required">Authentication required</string>
|
<string name="authentication_required">Authentication required</string>
|
||||||
|
|
||||||
|
@ -101,6 +101,24 @@
|
|||||||
android:maxLength="2"
|
android:maxLength="2"
|
||||||
android:title="@string/activity_prefs_sleep_duration" />
|
android:title="@string/activity_prefs_sleep_duration" />
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
<PreferenceScreen
|
||||||
|
android:key="pref_charts"
|
||||||
|
android:title="@string/activity_prefs_charts">
|
||||||
|
|
||||||
|
<EditTextPreference
|
||||||
|
android:inputType="number"
|
||||||
|
android:key="chart_max_heart_rate"
|
||||||
|
android:maxLength="3"
|
||||||
|
android:defaultValue="250"
|
||||||
|
android:title="@string/activity_prefs_chart_max_heart_rate" />
|
||||||
|
|
||||||
|
<EditTextPreference
|
||||||
|
android:inputType="number"
|
||||||
|
android:key="chart_min_heart_rate"
|
||||||
|
android:maxLength="3"
|
||||||
|
android:defaultValue="10"
|
||||||
|
android:title="@string/activity_prefs_chart_min_heart_rate" />
|
||||||
|
</PreferenceScreen>
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:layout="@layout/preference_checkbox"
|
android:layout="@layout/preference_checkbox"
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
|
Loading…
Reference in New Issue
Block a user