mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-23 10:26:49 +01:00
Implement high res HR data
Specifically for: - The HR fragment - The sports activity graph Also adds support for Huawei high res HR, and high res SpO2.
This commit is contained in:
parent
1882ee947e
commit
82e3a86350
@ -152,6 +152,11 @@ public class ActivitySummariesChartFragment extends AbstractActivityChartFragmen
|
|||||||
return getAllSamples(db, device, tsFrom, tsTo);
|
return getAllSamples(db, device, tsFrom, tsTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<? extends ActivitySample> getSamplesHighRes(DBHandler db, GBDevice device, int tsFrom, int tsTo) {
|
||||||
|
return getAllSamplesHighRes(db, device, tsFrom, tsTo);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setupLegend(Chart<?> chart) {
|
protected void setupLegend(Chart<?> chart) {
|
||||||
List<LegendEntry> legendEntries = new ArrayList<>(5);
|
List<LegendEntry> legendEntries = new ArrayList<>(5);
|
||||||
@ -231,9 +236,12 @@ public class ActivitySummariesChartFragment extends AbstractActivityChartFragmen
|
|||||||
|
|
||||||
private DefaultChartsData<LineData> buildChartFromSamples(DBHandler handler) {
|
private DefaultChartsData<LineData> buildChartFromSamples(DBHandler handler) {
|
||||||
final List<? extends ActivitySample> samples = getAllSamples(handler, gbDevice, startTime, endTime);
|
final List<? extends ActivitySample> samples = getAllSamples(handler, gbDevice, startTime, endTime);
|
||||||
|
final List<? extends ActivitySample> highResSamples = getAllSamplesHighRes(handler, gbDevice, startTime, endTime);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (highResSamples == null)
|
||||||
return refresh(gbDevice, samples);
|
return refresh(gbDevice, samples);
|
||||||
|
return refresh(gbDevice, samples, highResSamples);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Unable to get charts data right now", e);
|
LOG.error("Unable to get charts data right now", e);
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import com.github.mikephil.charting.data.LineDataSet;
|
|||||||
import com.github.mikephil.charting.formatter.ValueFormatter;
|
import com.github.mikephil.charting.formatter.ValueFormatter;
|
||||||
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
|
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.NotImplementedException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -180,14 +181,28 @@ public abstract class AbstractActivityChartFragment<D extends ChartsData> extend
|
|||||||
return provider.getAllActivitySamples(tsFrom, tsTo);
|
return provider.getAllActivitySamples(tsFrom, tsTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected List<? extends ActivitySample> getAllSamplesHighRes(DBHandler db, GBDevice device, int tsFrom, int tsTo) {
|
||||||
|
SampleProvider<? extends ActivitySample> provider = getProvider(db, device);
|
||||||
|
// Only retrieve if the provider signals it has high res data, otherwise it is useless
|
||||||
|
if (provider.hasHighResData())
|
||||||
|
return provider.getAllActivitySamplesHighRes(tsFrom, tsTo);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
SampleProvider<? extends AbstractActivitySample> provider = getProvider(db, device);
|
SampleProvider<? extends AbstractActivitySample> provider = getProvider(db, device);
|
||||||
return provider.getActivitySamples(tsFrom, tsTo);
|
return provider.getActivitySamples(tsFrom, tsTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultChartsData<LineData> refresh(GBDevice gbDevice, List<? extends ActivitySample> samples) {
|
public DefaultChartsData<LineData> refresh(GBDevice gbDevice, List<? extends ActivitySample> samples) {
|
||||||
|
// If there is no high res samples, all the samples are high res samples
|
||||||
|
return refresh(gbDevice, samples, samples);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultChartsData<LineData> refresh(GBDevice gbDevice, List<? extends ActivitySample> samples, List<? extends ActivitySample> highResSamples) {
|
||||||
TimestampTranslation tsTranslation = new TimestampTranslation();
|
TimestampTranslation tsTranslation = new TimestampTranslation();
|
||||||
LOG.info("{}: number of samples: {}", getTitle(), samples.size());
|
LOG.info("{}: number of samples: {}", getTitle(), samples.size());
|
||||||
|
LOG.info("{}: number of high res samples: {}", getTitle(), highResSamples.size());
|
||||||
LineData lineData;
|
LineData lineData;
|
||||||
|
|
||||||
if (samples.isEmpty()) {
|
if (samples.isEmpty()) {
|
||||||
@ -257,8 +272,15 @@ public abstract class AbstractActivityChartFragment<D extends ChartsData> extend
|
|||||||
}
|
}
|
||||||
entries.get(index).add(createLineEntry(value, ts));
|
entries.get(index).add(createLineEntry(value, ts));
|
||||||
|
|
||||||
// heart rate line graph
|
last_type = type;
|
||||||
if (hr && type != ActivityKind.NOT_WORN && heartRateUtilsInstance.isValidHeartRateValue(sample.getHeartRate())) {
|
last_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currently only for HR
|
||||||
|
if (hr) {
|
||||||
|
for (ActivitySample sample : highResSamples) {
|
||||||
|
if (sample.getKind() != ActivityKind.NOT_WORN && heartRateUtilsInstance.isValidHeartRateValue(sample.getHeartRate())) {
|
||||||
|
int ts = tsTranslation.shorten(sample.getTimestamp());
|
||||||
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));
|
||||||
@ -266,8 +288,7 @@ public abstract class AbstractActivityChartFragment<D extends ChartsData> extend
|
|||||||
heartrateEntries.add(createLineEntry(sample.getHeartRate(), ts));
|
heartrateEntries.add(createLineEntry(sample.getHeartRate(), ts));
|
||||||
lastHrSampleIndex = ts;
|
lastHrSampleIndex = ts;
|
||||||
}
|
}
|
||||||
last_type = type;
|
}
|
||||||
last_value = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert Entry Lists to Datasets
|
// convert Entry Lists to Datasets
|
||||||
@ -364,15 +385,16 @@ public abstract class AbstractActivityChartFragment<D extends ChartsData> extend
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement this to supply the samples to be displayed.
|
* Implement this to supply the samples to be displayed.
|
||||||
*
|
|
||||||
* @param db
|
|
||||||
* @param device
|
|
||||||
* @param tsFrom
|
|
||||||
* @param tsTo
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
protected abstract List<? extends ActivitySample> getSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo);
|
protected abstract List<? extends ActivitySample> getSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement this to supply high resolution data
|
||||||
|
*/
|
||||||
|
protected List<? extends ActivitySample> getSamplesHighRes(DBHandler db, GBDevice device, int tsFrom, int tsTo) {
|
||||||
|
throw new NotImplementedException("High resolution samples have not been implemented for this chart.");
|
||||||
|
}
|
||||||
|
|
||||||
protected List<? extends ActivitySample> getSamples(DBHandler db, GBDevice device) {
|
protected List<? extends ActivitySample> getSamples(DBHandler db, GBDevice device) {
|
||||||
int tsStart = getTSStart();
|
int tsStart = getTSStart();
|
||||||
int tsEnd = getTSEnd();
|
int tsEnd = getTSEnd();
|
||||||
@ -388,6 +410,12 @@ public abstract class AbstractActivityChartFragment<D extends ChartsData> extend
|
|||||||
return samples;
|
return samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected List<? extends ActivitySample> getSamplesHighRes(DBHandler db, GBDevice device) {
|
||||||
|
int tsStart = getTSStart();
|
||||||
|
int tsEnd = getTSEnd();
|
||||||
|
return getSamplesHighRes(db, device, tsStart, tsEnd);
|
||||||
|
}
|
||||||
|
|
||||||
protected List<? extends ActivitySample> getSamplesofSleep(DBHandler db, GBDevice device) {
|
protected List<? extends ActivitySample> getSamplesofSleep(DBHandler db, GBDevice device) {
|
||||||
int SLEEP_HOUR_LIMIT = 12;
|
int SLEEP_HOUR_LIMIT = 12;
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ public class HeartRateDailyFragment extends AbstractChartFragment<HeartRateDaily
|
|||||||
|
|
||||||
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) {
|
||||||
SampleProvider<? extends ActivitySample> provider = device.getDeviceCoordinator().getSampleProvider(device, db.getDaoSession());
|
SampleProvider<? extends ActivitySample> provider = device.getDeviceCoordinator().getSampleProvider(device, db.getDaoSession());
|
||||||
return provider.getAllActivitySamples(tsFrom, tsTo);
|
return provider.getAllActivitySamplesHighRes(tsFrom, tsTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -76,6 +76,17 @@ public abstract class AbstractSampleProvider<T extends AbstractActivitySample> i
|
|||||||
return getGBActivitySamples(timestamp_from, timestamp_to);
|
return getGBActivitySamples(timestamp_from, timestamp_to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public List<T> getAllActivitySamplesHighRes(int timestamp_from, int timestamp_to) {
|
||||||
|
return getGBActivitySamplesHighRes(timestamp_from, timestamp_to);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasHighResData() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
@Deprecated // use getAllActivitySamples
|
@Deprecated // use getAllActivitySamples
|
||||||
@ -138,7 +149,7 @@ public abstract class AbstractSampleProvider<T extends AbstractActivitySample> i
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the activity samples between two timestamps. Exactly one every minute.
|
* Get the activity samples between two timestamps (inclusive). Exactly one every minute.
|
||||||
* @param timestamp_from Start timestamp
|
* @param timestamp_from Start timestamp
|
||||||
* @param timestamp_to End timestamp
|
* @param timestamp_to End timestamp
|
||||||
* @return Exactly one sample for every minute
|
* @return Exactly one sample for every minute
|
||||||
@ -162,6 +173,20 @@ public abstract class AbstractSampleProvider<T extends AbstractActivitySample> i
|
|||||||
return samples;
|
return samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the activity samples between two timestamps (inclusive).
|
||||||
|
* Differs from {@link #getGBActivitySamples(int, int)} in that it supplies as many samples as
|
||||||
|
* available.
|
||||||
|
* It assumes {@link #getGBActivitySamples(int, int)} returns the highest resolution data unless
|
||||||
|
* this is overwritten.
|
||||||
|
* @param timestamp_from Start timestamp
|
||||||
|
* @param timestamp_to End timestamp
|
||||||
|
* @return All the samples between start and end timestamp (inclusive)
|
||||||
|
*/
|
||||||
|
protected List<T> getGBActivitySamplesHighRes(int timestamp_from, int timestamp_to) {
|
||||||
|
return getGBActivitySamples(timestamp_from, timestamp_to);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detaches all samples of this type from the session. Changes to them may not be
|
* Detaches all samples of this type from the session. Changes to them may not be
|
||||||
* written back to the database.
|
* written back to the database.
|
||||||
|
@ -47,6 +47,7 @@ public interface SampleProvider<T extends AbstractActivitySample> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the list of all samples, of any type, within the given time span.
|
* Returns the list of all samples, of any type, within the given time span.
|
||||||
|
* This returns exactly one sample every minute.
|
||||||
* @param timestamp_from the start timestamp
|
* @param timestamp_from the start timestamp
|
||||||
* @param timestamp_to the end timestamp
|
* @param timestamp_to the end timestamp
|
||||||
* @return the list of samples of any type
|
* @return the list of samples of any type
|
||||||
@ -54,6 +55,19 @@ public interface SampleProvider<T extends AbstractActivitySample> {
|
|||||||
@NonNull
|
@NonNull
|
||||||
List<T> getAllActivitySamples(int timestamp_from, int timestamp_to);
|
List<T> getAllActivitySamples(int timestamp_from, int timestamp_to);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as {@link #getAllActivitySamples(int, int)}}, but returns as many samples as possible.
|
||||||
|
* Explicitly does not make a guarantee about how many samples there are per timeframe, which
|
||||||
|
* can also change over time.
|
||||||
|
*/
|
||||||
|
List<T> getAllActivitySamplesHighRes(int timestamp_from, int timestamp_to);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies that the sample provider has higher resolution data. Set to true if the sample
|
||||||
|
* provider can provide more than one sample a minute.
|
||||||
|
*/
|
||||||
|
boolean hasHighResData();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the list of all samples that represent user "activity", within
|
* Returns the list of all samples that represent user "activity", within
|
||||||
* the given time span. This excludes samples of type sleep, for example.
|
* the given time span. This excludes samples of type sleep, for example.
|
||||||
|
@ -21,6 +21,7 @@ import android.app.Activity;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes;
|
import androidx.annotation.DrawableRes;
|
||||||
@ -64,6 +65,16 @@ public class UnknownDeviceCoordinator extends AbstractDeviceCoordinator {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AbstractActivitySample> getAllActivitySamplesHighRes(int timestamp_from, int timestamp_to) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasHighResData() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<AbstractActivitySample> getActivitySamples(int timestamp_from, int timestamp_to) {
|
public List<AbstractActivitySample> getActivitySamples(int timestamp_from, int timestamp_to) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -305,12 +305,24 @@ public class HuaweiSampleProvider extends AbstractSampleProvider<HuaweiActivityS
|
|||||||
return processedSamples;
|
return processedSamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<HuaweiActivitySample> getGBActivitySamplesHighRes(int timestamp_from, int timestamp_to) {
|
||||||
|
List<HuaweiActivitySample> processedSamples = getRawOrderedActivitySamples(timestamp_from, timestamp_to);
|
||||||
|
addWorkoutSamples(processedSamples, timestamp_from, timestamp_to);
|
||||||
|
return processedSamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasHighResData() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private HuaweiActivitySample createDummySample(int timestamp) {
|
private HuaweiActivitySample createDummySample(int timestamp) {
|
||||||
HuaweiActivitySample activitySample = new HuaweiActivitySample(
|
HuaweiActivitySample activitySample = new HuaweiActivitySample(
|
||||||
timestamp,
|
timestamp,
|
||||||
-1,
|
-1,
|
||||||
-1,
|
-1,
|
||||||
0,
|
timestamp + 60, // Make sure the duration is 60
|
||||||
(byte) 0x00,
|
(byte) 0x00,
|
||||||
ActivitySample.NOT_MEASURED,
|
ActivitySample.NOT_MEASURED,
|
||||||
0,
|
0,
|
||||||
@ -438,7 +450,7 @@ public class HuaweiSampleProvider extends AbstractSampleProvider<HuaweiActivityS
|
|||||||
List<HuaweiWorkoutDataSample> workoutSamples = getRawOrderedWorkoutSamplesWithHeartRate(timestamp_from, timestamp_to);
|
List<HuaweiWorkoutDataSample> workoutSamples = getRawOrderedWorkoutSamplesWithHeartRate(timestamp_from, timestamp_to);
|
||||||
|
|
||||||
for (int i = 0; i < workoutSamples.size(); i++) {
|
for (int i = 0; i < workoutSamples.size(); i++) {
|
||||||
// Look ahead to see if this is still the same workout
|
// Look behind to see if this is still the same workout
|
||||||
boolean inWorkout = i != 0 && workoutSamples.get(i).getWorkoutId() == workoutSamples.get(i - 1).getWorkoutId();
|
boolean inWorkout = i != 0 && workoutSamples.get(i).getWorkoutId() == workoutSamples.get(i - 1).getWorkoutId();
|
||||||
|
|
||||||
// Skip the processed sample that are before this workout sample
|
// Skip the processed sample that are before this workout sample
|
||||||
@ -470,4 +482,53 @@ public class HuaweiSampleProvider extends AbstractSampleProvider<HuaweiActivityS
|
|||||||
processedSamples.get(currentIndex).setRawIntensity(0);
|
processedSamples.get(currentIndex).setRawIntensity(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addWorkoutSamples(List<HuaweiActivitySample> processedSamples, int timestamp_from, int timestamp_to) {
|
||||||
|
int currentIndex = 0;
|
||||||
|
List<HuaweiWorkoutDataSample> workoutSamples = getRawOrderedWorkoutSamplesWithHeartRate(timestamp_from, timestamp_to);
|
||||||
|
|
||||||
|
for (int i = 0; i < workoutSamples.size(); i++) {
|
||||||
|
// Look behind to see if this is still the same workout
|
||||||
|
boolean inWorkout = i != 0 && workoutSamples.get(i).getWorkoutId() == workoutSamples.get(i - 1).getWorkoutId();
|
||||||
|
|
||||||
|
// Skip the samples that are before this workout sample, and potentially clear the HR
|
||||||
|
// and intensity - see #4126 for the reasoning
|
||||||
|
while (currentIndex < processedSamples.size() && workoutSamples.get(i).getTimestamp() > processedSamples.get(currentIndex).getTimestamp()) {
|
||||||
|
if (inWorkout) {
|
||||||
|
processedSamples.get(currentIndex).setHeartRate(ActivitySample.NOT_MEASURED);
|
||||||
|
processedSamples.get(currentIndex).setRawIntensity(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentIndex += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < workoutSamples.size() - 1) {
|
||||||
|
processedSamples.add(currentIndex, convertWorkoutSampleToActivitySample(workoutSamples.get(i), workoutSamples.get(i + 1).getTimestamp()));
|
||||||
|
} else {
|
||||||
|
// For the last workout sample we assume it is over 5 seconds
|
||||||
|
processedSamples.add(currentIndex, convertWorkoutSampleToActivitySample(workoutSamples.get(i), workoutSamples.get(i).getTimestamp() + 5));
|
||||||
|
}
|
||||||
|
currentIndex += 1; // Prevent clearing the sample in the next loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private HuaweiActivitySample convertWorkoutSampleToActivitySample(HuaweiWorkoutDataSample workoutSample, int nextTimestamp) {
|
||||||
|
int hr = workoutSample.getHeartRate() & 0xFF;
|
||||||
|
HuaweiActivitySample newSample = new HuaweiActivitySample(
|
||||||
|
workoutSample.getTimestamp(),
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
nextTimestamp - 1, // Just to prevent overlap causing issues
|
||||||
|
(byte) 0x00,
|
||||||
|
ActivitySample.NOT_MEASURED,
|
||||||
|
ActivitySample.NOT_MEASURED,
|
||||||
|
ActivitySample.NOT_MEASURED,
|
||||||
|
ActivitySample.NOT_MEASURED,
|
||||||
|
ActivitySample.NOT_MEASURED,
|
||||||
|
ActivitySample.NOT_MEASURED,
|
||||||
|
hr
|
||||||
|
);
|
||||||
|
newSample.setProvider(this);
|
||||||
|
return newSample;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,8 @@ public class HuaweiSpo2SampleProvider extends AbstractTimeSampleProvider<HuaweiS
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public List<HuaweiSpo2Sample> getAllSamples(long timestampFrom, long timestampTo) {
|
public List<HuaweiSpo2Sample> getAllSamples(long timestampFrom, long timestampTo) {
|
||||||
List<HuaweiActivitySample> activitySamples = huaweiSampleProvider.getAllActivitySamples((int) (timestampFrom / 1000L), (int) (timestampTo / 1000L));
|
// Using high res data is fine for the SpO2 sample provider at the time of writing
|
||||||
|
List<HuaweiActivitySample> activitySamples = huaweiSampleProvider.getAllActivitySamplesHighRes((int) (timestampFrom / 1000L), (int) (timestampTo / 1000L));
|
||||||
List<HuaweiSpo2Sample> spo2Samples = new ArrayList<>(activitySamples.size());
|
List<HuaweiSpo2Sample> spo2Samples = new ArrayList<>(activitySamples.size());
|
||||||
for (HuaweiActivitySample sample : activitySamples) {
|
for (HuaweiActivitySample sample : activitySamples) {
|
||||||
if (sample.getSpo() == -1)
|
if (sample.getSpo() == -1)
|
||||||
|
Loading…
Reference in New Issue
Block a user