diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/GarminVo2MaxSampleProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/WorkoutVo2MaxSampleProvider.java
similarity index 74%
rename from app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/GarminVo2MaxSampleProvider.java
rename to app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/WorkoutVo2MaxSampleProvider.java
index 598553683..466274c89 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/GarminVo2MaxSampleProvider.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/WorkoutVo2MaxSampleProvider.java
@@ -14,7 +14,7 @@
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see . */
-package nodomain.freeyourgadget.gadgetbridge.devices.garmin;
+package nodomain.freeyourgadget.gadgetbridge.devices;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -26,6 +26,7 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@@ -33,8 +34,8 @@ import java.util.Objects;
import java.util.stream.Collectors;
import de.greenrobot.dao.query.QueryBuilder;
+import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
-import nodomain.freeyourgadget.gadgetbridge.devices.Vo2MaxSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummaryDao;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
@@ -42,15 +43,20 @@ import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries;
+import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryParser;
import nodomain.freeyourgadget.gadgetbridge.model.Vo2MaxSample;
-public class GarminVo2MaxSampleProvider implements Vo2MaxSampleProvider {
- private static final Logger LOG = LoggerFactory.getLogger(GarminVo2MaxSampleProvider.class);
+/**
+ * An implementation of {@link Vo2MaxSampleProvider} that extracts VO2 Max values from
+ * workouts, for devices that provide them as part of the workout data.
+ */
+public class WorkoutVo2MaxSampleProvider implements Vo2MaxSampleProvider {
+ private static final Logger LOG = LoggerFactory.getLogger(WorkoutVo2MaxSampleProvider.class);
private final GBDevice device;
private final DaoSession session;
- public GarminVo2MaxSampleProvider(final GBDevice device, final DaoSession session) {
+ public WorkoutVo2MaxSampleProvider(final GBDevice device, final DaoSession session) {
this.device = device;
this.session = session;
}
@@ -65,6 +71,8 @@ public class GarminVo2MaxSampleProvider implements Vo2MaxSampleProvider qb = summaryDao.queryBuilder();
qb.where(BaseActivitySummaryDao.Properties.DeviceId.eq(dbDevice.getId()))
.where(BaseActivitySummaryDao.Properties.StartTime.gt(new Date(timestampFrom)))
@@ -73,6 +81,7 @@ public class GarminVo2MaxSampleProvider implements Vo2MaxSampleProvider samples = qb.build().list();
summaryDao.detachAll();
+ fillSummaryData(coordinator, samples);
return samples.stream()
.map(GarminVo2maxSample::fromActivitySummary)
@@ -105,9 +114,10 @@ public class GarminVo2MaxSampleProvider implements Vo2MaxSampleProvider qb = summaryDao.queryBuilder();
- addWhereFilter(qb, type);
+ addWhereFilter(coordinator, qb, type);
if (until != 0) {
qb.where(BaseActivitySummaryDao.Properties.StartTime.le(new Date(until)));
@@ -119,35 +129,52 @@ public class GarminVo2MaxSampleProvider implements Vo2MaxSampleProvider samples = qb.build().list();
summaryDao.detachAll();
+ fillSummaryData(coordinator, samples);
return !samples.isEmpty() ? GarminVo2maxSample.fromActivitySummary(samples.get(0)) : null;
}
- private static void addWhereFilter(final QueryBuilder qb, final Vo2MaxSample.Type type) {
+ private static void addWhereFilter(final DeviceCoordinator coordinator,
+ final QueryBuilder qb,
+ final Vo2MaxSample.Type type) {
final List codes = new ArrayList<>();
- if (type == Vo2MaxSample.Type.ANY || type == Vo2MaxSample.Type.RUNNING) {
- codes.addAll(Arrays.asList(
- ActivityKind.INDOOR_RUNNING.getCode(),
- ActivityKind.OUTDOOR_RUNNING.getCode(),
- ActivityKind.CROSS_COUNTRY_RUNNING.getCode(),
- ActivityKind.RUNNING.getCode()
- ));
+ if (coordinator.supportsVO2MaxRunning()) {
+ if (type == Vo2MaxSample.Type.ANY || type == Vo2MaxSample.Type.RUNNING) {
+ codes.addAll(Arrays.asList(
+ ActivityKind.INDOOR_RUNNING.getCode(),
+ ActivityKind.OUTDOOR_RUNNING.getCode(),
+ ActivityKind.CROSS_COUNTRY_RUNNING.getCode(),
+ ActivityKind.RUNNING.getCode()
+ ));
+ }
}
- if (type == Vo2MaxSample.Type.ANY || type == Vo2MaxSample.Type.CYCLING) {
- codes.addAll(Arrays.asList(
- ActivityKind.CYCLING.getCode(),
- ActivityKind.INDOOR_CYCLING.getCode(),
- ActivityKind.HANDCYCLING.getCode(),
- ActivityKind.HANDCYCLING_INDOOR.getCode(),
- ActivityKind.MOTORCYCLING.getCode(),
- ActivityKind.OUTDOOR_CYCLING.getCode()
- ));
+ if (coordinator.supportsVO2MaxCycling()) {
+ if (type == Vo2MaxSample.Type.ANY || type == Vo2MaxSample.Type.CYCLING) {
+ codes.addAll(Arrays.asList(
+ ActivityKind.CYCLING.getCode(),
+ ActivityKind.INDOOR_CYCLING.getCode(),
+ ActivityKind.HANDCYCLING.getCode(),
+ ActivityKind.HANDCYCLING_INDOOR.getCode(),
+ ActivityKind.MOTORCYCLING.getCode(),
+ ActivityKind.OUTDOOR_CYCLING.getCode()
+ ));
+ }
}
qb.where(BaseActivitySummaryDao.Properties.ActivityKind.in(codes));
}
+ private void fillSummaryData(final DeviceCoordinator coordinator,
+ final Collection summaries) {
+ ActivitySummaryParser activitySummaryParser = coordinator.getActivitySummaryParser(device, GBApplication.getContext());
+ for (final BaseActivitySummary summary : summaries) {
+ if (summary.getSummaryData() == null) {
+ activitySummaryParser.parseBinaryData(summary, true);
+ }
+ }
+ }
+
@Nullable
@Override
public Vo2MaxSample getLatestSample() {
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/GarminCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/GarminCoordinator.java
index ff472bdae..e156c418e 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/GarminCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/GarminCoordinator.java
@@ -20,6 +20,7 @@ import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpec
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsScreen;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractBLEDeviceCoordinator;
+import nodomain.freeyourgadget.gadgetbridge.devices.WorkoutVo2MaxSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.TimeSampleProvider;
@@ -138,7 +139,7 @@ public abstract class GarminCoordinator extends AbstractBLEDeviceCoordinator {
@Override
public Vo2MaxSampleProvider extends Vo2MaxSample> getVo2MaxSampleProvider(final GBDevice device, final DaoSession session) {
- return new GarminVo2MaxSampleProvider(device, session);
+ return new WorkoutVo2MaxSampleProvider(device, session);
}
@Override
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/ZeppOsCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/ZeppOsCoordinator.java
index a76ef7a64..a8ae35d13 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/ZeppOsCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/ZeppOsCoordinator.java
@@ -43,6 +43,8 @@ import nodomain.freeyourgadget.gadgetbridge.capabilities.password.PasswordCapabi
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
+import nodomain.freeyourgadget.gadgetbridge.devices.Vo2MaxSampleProvider;
+import nodomain.freeyourgadget.gadgetbridge.devices.WorkoutVo2MaxSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiExtendedSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
@@ -58,6 +60,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.HuamiSpo2SampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.HuamiStressSampleDao;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryParser;
+import nodomain.freeyourgadget.gadgetbridge.model.Vo2MaxSample;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsFwInstallHandler;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
@@ -177,6 +180,16 @@ public abstract class ZeppOsCoordinator extends HuamiCoordinator {
return true;
}
+ @Override
+ public boolean supportsVO2Max() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsVO2MaxRunning() {
+ return true;
+ }
+
@Override
public boolean supportsHeartRateStats() {
return true;
@@ -301,6 +314,11 @@ public abstract class ZeppOsCoordinator extends HuamiCoordinator {
return new HuamiExtendedSampleProvider(device, session);
}
+ @Override
+ public Vo2MaxSampleProvider extends Vo2MaxSample> getVo2MaxSampleProvider(final GBDevice device, final DaoSession session) {
+ return new WorkoutVo2MaxSampleProvider(device, session);
+ }
+
@Override
public ActivitySummaryParser getActivitySummaryParser(final GBDevice device, final Context context) {
return new ZeppOsActivitySummaryParser();