mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Xiaomi: Add ActivityTrackProvider
This commit is contained in:
+8
@@ -63,6 +63,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.XiaomiSleepTimeSampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryParser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityTrackProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.BodyEnergySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.HeartRateSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.PaiSample;
|
||||
@@ -74,6 +75,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.XiaomiUuids;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.XiaomiPreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.XiaomiSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.activity.XiaomiActivityTrackProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.activity.impl.WorkoutSummaryParser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
@@ -200,6 +202,12 @@ public abstract class XiaomiCoordinator extends AbstractBLEDeviceCoordinator {
|
||||
return new WorkoutSummaryParser();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ActivityTrackProvider getActivityTrackProvider(@NonNull final GBDevice device, @NonNull final Context context) {
|
||||
return new XiaomiActivityTrackProvider(device, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsFlashing(@NonNull GBDevice device) {
|
||||
return true;
|
||||
|
||||
+4
@@ -28,6 +28,7 @@ import org.slf4j.LoggerFactory;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -220,6 +221,9 @@ public class XiaomiActivityFileFetcher {
|
||||
protected void dumpBytesToExternalStorage(final XiaomiActivityFileId fileId, final byte[] bytes) {
|
||||
try {
|
||||
final File outputFile = getRawFile(mHealthService.getSupport().getDevice(), fileId);
|
||||
if (outputFile == null) {
|
||||
throw new IOException("Failed to get output file");
|
||||
}
|
||||
final File parentFile = outputFile.getParentFile();
|
||||
if (parentFile != null) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
|
||||
+1
-1
@@ -99,7 +99,7 @@ public class XiaomiActivityFileId implements Comparable<XiaomiActivityFileId> {
|
||||
}
|
||||
|
||||
public static XiaomiActivityFileId from(final byte[] bytes) {
|
||||
assert bytes.length == 7;
|
||||
assert bytes.length >= 7;
|
||||
|
||||
return from(ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN));
|
||||
}
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.activity;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityTrack;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityTrackProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.GpxActivityTrackProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.activity.impl.WorkoutGpsParser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
|
||||
@SuppressWarnings("ClassCanBeRecord")
|
||||
public class XiaomiActivityTrackProvider implements ActivityTrackProvider {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(XiaomiActivityTrackProvider.class);
|
||||
|
||||
private final GBDevice device;
|
||||
private final Context context;
|
||||
|
||||
public XiaomiActivityTrackProvider(final GBDevice device, final Context context) {
|
||||
this.device = device;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ActivityTrack getActivityTrack(@NonNull final BaseActivitySummary summary) {
|
||||
final File inputFile = FileUtils.tryFixPath(summary.getRawDetailsPath());
|
||||
if (inputFile == null) {
|
||||
LOG.warn("Raw file for details not found: {}", summary.getRawDetailsPath());
|
||||
return new GpxActivityTrackProvider().getActivityTrack(summary);
|
||||
}
|
||||
|
||||
LOG.debug("Loading raw details from {}", inputFile);
|
||||
|
||||
final byte[] detailsBytes;
|
||||
try {
|
||||
detailsBytes = FileUtils.readAll(inputFile);
|
||||
} catch (final IOException e) {
|
||||
LOG.error("Failed to read {}", inputFile, e);
|
||||
return new GpxActivityTrackProvider().getActivityTrack(summary);
|
||||
}
|
||||
|
||||
try {
|
||||
final WorkoutGpsParser workoutGpsParser = new WorkoutGpsParser();
|
||||
final XiaomiActivityFileId fileId = XiaomiActivityFileId.from(detailsBytes);
|
||||
return workoutGpsParser.getActivityTrack(fileId, detailsBytes);
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Failed to parse bytes from {}", inputFile, e);
|
||||
return new GpxActivityTrackProvider().getActivityTrack(summary);
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
-4
@@ -19,6 +19,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.activity.imp
|
||||
import android.content.Context;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -51,8 +53,8 @@ import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
public class WorkoutGpsParser extends XiaomiActivityParser {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(WorkoutGpsParser.class);
|
||||
|
||||
@Override
|
||||
public boolean parse(final Context context, final GBDevice gbDevice, final XiaomiActivityFileId fileId, final byte[] bytes) {
|
||||
@Nullable
|
||||
public ActivityTrack getActivityTrack(final XiaomiActivityFileId fileId, final byte[] bytes) {
|
||||
final int version = fileId.getVersion();
|
||||
final int headerSize;
|
||||
final int sampleSize;
|
||||
@@ -67,7 +69,7 @@ public class WorkoutGpsParser extends XiaomiActivityParser {
|
||||
break;
|
||||
default:
|
||||
LOG.warn("Unable to parse workout gps version {}", fileId.getVersion());
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
final ByteBuffer buf = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);
|
||||
@@ -118,7 +120,16 @@ public class WorkoutGpsParser extends XiaomiActivityParser {
|
||||
}
|
||||
}
|
||||
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
return activityTrack;
|
||||
}
|
||||
|
||||
public boolean parse(final Context context, final GBDevice gbDevice, final XiaomiActivityFileId fileId, final byte[] bytes) {
|
||||
final ActivityTrack activityTrack = getActivityTrack(fileId, bytes);
|
||||
if (activityTrack == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
final DaoSession session = dbHandler.getDaoSession();
|
||||
final Device device = DBHelper.getDevice(gbDevice, session);
|
||||
final User user = DBHelper.getUser(session);
|
||||
|
||||
+1
@@ -152,6 +152,7 @@ public class XiaomiSimpleActivityParser {
|
||||
}
|
||||
}
|
||||
|
||||
summaryData.setHasGps(summary.getRawDetailsPath() != null);
|
||||
summary.setSummaryData(summaryData.toString());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user