diff --git a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java
index db389239d..a10a3c983 100644
--- a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java
+++ b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java
@@ -46,7 +46,7 @@ public class GBDaoGenerator {
public static void main(String[] args) throws Exception {
- final Schema schema = new Schema(78, MAIN_PACKAGE + ".entities");
+ final Schema schema = new Schema(79, MAIN_PACKAGE + ".entities");
Entity userAttributes = addUserAttributes(schema);
Entity user = addUserInfo(schema, userAttributes);
@@ -137,8 +137,8 @@ public class GBDaoGenerator {
addHuaweiActivitySample(schema, user, device);
Entity huaweiWorkoutSummary = addHuaweiWorkoutSummarySample(schema, user, device);
- addHuaweiWorkoutDataSample(schema, user, device, huaweiWorkoutSummary);
- addHuaweiWorkoutPaceSample(schema, user, device, huaweiWorkoutSummary);
+ addHuaweiWorkoutDataSample(schema, huaweiWorkoutSummary);
+ addHuaweiWorkoutPaceSample(schema, huaweiWorkoutSummary);
addCalendarSyncState(schema, device);
addAlarms(schema, user, device);
@@ -1307,10 +1307,12 @@ public class GBDaoGenerator {
workoutSummary.addByteArrayProperty("rawData");
+ workoutSummary.addStringProperty("gpxFileLocation");
+
return workoutSummary;
}
- private static Entity addHuaweiWorkoutDataSample(Schema schema, Entity user, Entity device, Entity summaryEntity) {
+ private static Entity addHuaweiWorkoutDataSample(Schema schema, Entity summaryEntity) {
Entity workoutDataSample = addEntity(schema, "HuaweiWorkoutDataSample");
workoutDataSample.setJavaDoc("Contains Huawei Workout data samples (multiple per workout)");
@@ -1345,7 +1347,7 @@ public class GBDaoGenerator {
return workoutDataSample;
}
- private static Entity addHuaweiWorkoutPaceSample(Schema schema, Entity user, Entity device, Entity summaryEntity) {
+ private static Entity addHuaweiWorkoutPaceSample(Schema schema, Entity summaryEntity) {
Entity workoutPaceSample = addEntity(schema, "HuaweiWorkoutPaceSample");
workoutPaceSample.setJavaDoc("Contains Huawei Workout pace data samples (one per workout)");
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_79.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_79.java
new file mode 100644
index 000000000..4663b6172
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_79.java
@@ -0,0 +1,38 @@
+/* Copyright (C) 2024 Martin.JM
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+package nodomain.freeyourgadget.gadgetbridge.database.schema;
+
+import android.database.sqlite.SQLiteDatabase;
+
+import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
+import nodomain.freeyourgadget.gadgetbridge.database.DBUpdateScript;
+import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySampleDao;
+
+public class GadgetbridgeUpdate_79 implements DBUpdateScript {
+ @Override
+ public void upgradeSchema(final SQLiteDatabase db) {
+ if (!DBHelper.existsColumn(HuaweiWorkoutSummarySampleDao.TABLENAME, HuaweiWorkoutSummarySampleDao.Properties.GpxFileLocation.columnName, db)) {
+ final String statement = "ALTER TABLE " + HuaweiWorkoutSummarySampleDao.TABLENAME + " ADD COLUMN \""
+ + HuaweiWorkoutSummarySampleDao.Properties.GpxFileLocation.columnName + "\" TEXT";
+ db.execSQL(statement);
+ }
+ }
+
+ @Override
+ public void downgradeSchema(final SQLiteDatabase db) {
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiBRCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiBRCoordinator.java
index e4a47808a..0ce47fc3d 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiBRCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiBRCoordinator.java
@@ -26,9 +26,7 @@ import androidx.annotation.NonNull;
import java.util.Collection;
import java.util.Collections;
-import java.util.List;
-import de.greenrobot.dao.query.QueryBuilder;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
@@ -38,13 +36,8 @@ import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.TimeSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
-import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummaryDao;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
-import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiActivitySampleDao;
-import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSampleDao;
-import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySample;
-import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySampleDao;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryParser;
import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample;
@@ -87,21 +80,7 @@ public abstract class HuaweiBRCoordinator extends AbstractBLClassicDeviceCoordin
@Override
protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException {
- long deviceId = device.getId();
- QueryBuilder> qb = session.getHuaweiActivitySampleDao().queryBuilder();
- qb.where(HuaweiActivitySampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
-
- QueryBuilder qb2 = session.getHuaweiWorkoutSummarySampleDao().queryBuilder();
- List workouts = qb2.where(HuaweiWorkoutSummarySampleDao.Properties.DeviceId.eq(deviceId)).build().list();
- for (HuaweiWorkoutSummarySample sample : workouts) {
- session.getHuaweiWorkoutDataSampleDao().queryBuilder().where(
- HuaweiWorkoutDataSampleDao.Properties.WorkoutId.eq(sample.getWorkoutId())
- ).buildDelete().executeDeleteWithoutDetachingEntities();
- }
-
- session.getHuaweiWorkoutSummarySampleDao().queryBuilder().where(HuaweiWorkoutSummarySampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
-
- session.getBaseActivitySummaryDao().queryBuilder().where(BaseActivitySummaryDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
+ huaweiCoordinator.deleteDevice(gbDevice, device, session);
}
@Override
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java
index d799c574c..401a074ce 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java
@@ -29,7 +29,9 @@ import java.util.TreeMap;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
+import de.greenrobot.dao.query.QueryBuilder;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
+import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.CameraActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.appmanager.AppManagerActivity;
@@ -40,11 +42,21 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.App;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Notifications;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Notifications.NotificationConstraintsType;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Watchface;
+import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummaryDao;
+import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
+import nodomain.freeyourgadget.gadgetbridge.entities.Device;
+import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiActivitySampleDao;
+import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSampleDao;
+import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSampleDao;
+import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySample;
+import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySampleDao;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.*;
+import androidx.annotation.NonNull;
+
public class HuaweiCoordinator {
Logger LOG = LoggerFactory.getLogger(HuaweiCoordinator.class);
@@ -56,6 +68,7 @@ public class HuaweiCoordinator {
ByteBuffer notificationConstraints = null;
private boolean supportsTruSleepNewSync = false;
+ private boolean supportsGpsNewSync = false;
private Watchface.WatchfaceDeviceParams watchfaceDeviceParams;
@@ -92,6 +105,28 @@ public class HuaweiCoordinator {
}
}
+ protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException {
+ long deviceId = device.getId();
+ QueryBuilder> qb = session.getHuaweiActivitySampleDao().queryBuilder();
+ qb.where(HuaweiActivitySampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
+
+ QueryBuilder qb2 = session.getHuaweiWorkoutSummarySampleDao().queryBuilder();
+ List workouts = qb2.where(HuaweiWorkoutSummarySampleDao.Properties.DeviceId.eq(deviceId)).build().list();
+ for (HuaweiWorkoutSummarySample sample : workouts) {
+ session.getHuaweiWorkoutDataSampleDao().queryBuilder().where(
+ HuaweiWorkoutDataSampleDao.Properties.WorkoutId.eq(sample.getWorkoutId())
+ ).buildDelete().executeDeleteWithoutDetachingEntities();
+
+ session.getHuaweiWorkoutPaceSampleDao().queryBuilder().where(
+ HuaweiWorkoutPaceSampleDao.Properties.WorkoutId.eq(sample.getWorkoutId())
+ ).buildDelete().executeDeleteWithoutDetachingEntities();
+ }
+
+ session.getHuaweiWorkoutSummarySampleDao().queryBuilder().where(HuaweiWorkoutSummarySampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
+
+ session.getBaseActivitySummaryDao().queryBuilder().where(BaseActivitySummaryDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
+ }
+
private SharedPreferences getCapabilitiesSharedPreferences() {
return GBApplication.getContext().getSharedPreferences("huawei_coordinator_capatilities" + parent.getDeviceType().name(), Context.MODE_PRIVATE);
}
@@ -694,4 +729,12 @@ public class HuaweiCoordinator {
public void setSupportsTruSleepNewSync(boolean supportsTruSleepNewSync) {
this.supportsTruSleepNewSync = supportsTruSleepNewSync;
}
+
+ public boolean isSupportsGpsNewSync() {
+ return supportsGpsNewSync;
+ }
+
+ public void setSupportsGpsNewSync(boolean supportsGpsNewSync) {
+ this.supportsGpsNewSync = supportsGpsNewSync;
+ }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiGpsParser.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiGpsParser.java
new file mode 100644
index 000000000..dc4a04d8d
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiGpsParser.java
@@ -0,0 +1,102 @@
+package nodomain.freeyourgadget.gadgetbridge.devices.huawei;
+
+import androidx.annotation.NonNull;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+
+public class HuaweiGpsParser {
+
+ public static class GpsPoint {
+ public int timestamp;
+ public double latitude;
+ public double longitude;
+ public boolean altitudeSupported;
+ public double altitude;
+
+ @NonNull
+ @Override
+ public String toString() {
+ return "GpsPoint{" +
+ "timestamp=" + timestamp +
+ ", longitude=" + longitude +
+ ", latitude=" + latitude +
+ ", altitudeSupported=" + altitudeSupported +
+ ", altitude=" + altitude +
+ '}';
+ }
+ }
+
+ public static GpsPoint[] parseHuaweiGps(byte[] data) {
+ ByteBuffer buffer = ByteBuffer.wrap(data);
+ buffer.order(ByteOrder.LITTLE_ENDIAN);
+
+ // Skip trim
+ buffer.position(0x20);
+
+ int timestamp;
+ double lon_start;
+ double lat_start;
+ boolean alt_support;
+ double alt_start;
+
+ byte fileType = buffer.get();
+ if ((fileType & 0x03) != 0x03) {
+ alt_support = false;
+ timestamp = buffer.getInt();
+ lon_start = buffer.getDouble();
+ lat_start = buffer.getDouble();
+ alt_start = 0;
+ buffer.position(62); // Skip past unknown fields/padding
+ } else {
+ alt_support = true;
+ timestamp = buffer.getInt();
+ lon_start = buffer.getDouble();
+ lat_start = buffer.getDouble();
+ alt_start = buffer.getDouble();
+ buffer.position(70); // Skip past unknown fields/padding
+ }
+
+ lat_start = lat_start * 0.017453292519943;
+ lon_start = lon_start * 0.017453292519943;
+
+ // Working values
+ int time = timestamp;
+ double lat = lat_start;
+ double lon = lon_start;
+ double alt = alt_start;
+
+ int data_size = 15;
+ if (alt_support)
+ data_size += 4;
+
+ ArrayList retv = new ArrayList<>(buffer.remaining() / data_size);
+ while (buffer.remaining() > data_size) {
+ short time_delta = buffer.getShort();
+ buffer.getShort(); // Unknown value
+ float lon_delta = buffer.getFloat();
+ float lat_delta = buffer.getFloat();
+ buffer.get(); buffer.get(); buffer.get(); // Unknown values
+
+ time = time + time_delta;
+ lat = lat + lat_delta;
+ lon = lon + lon_delta;
+
+ GpsPoint point = new GpsPoint();
+ point.timestamp = time;
+ point.latitude = (lat / 6383807.0d + lat_start) / 0.017453292519943d;
+ point.longitude = (lon / 6383807.0d / Math.cos(lat_start) + lon_start) / 0.017453292519943d;
+ point.altitudeSupported = alt_support;
+ if (alt_support) {
+ // TODO: not sure about this
+ float alt_delta = buffer.getFloat();
+ alt = alt + alt_delta;
+ point.altitude = alt;
+ }
+ retv.add(point);
+ }
+
+ return retv.toArray(new GpsPoint[0]);
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiLECoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiLECoordinator.java
index 16f35e377..7cbc50287 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiLECoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiLECoordinator.java
@@ -27,9 +27,7 @@ import androidx.annotation.NonNull;
import java.util.Collection;
import java.util.Collections;
-import java.util.List;
-import de.greenrobot.dao.query.QueryBuilder;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
@@ -39,13 +37,8 @@ import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.TimeSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
-import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummaryDao;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
-import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiActivitySampleDao;
-import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSampleDao;
-import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySample;
-import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySampleDao;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryParser;
import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample;
@@ -96,21 +89,7 @@ public abstract class HuaweiLECoordinator extends AbstractBLEDeviceCoordinator i
@Override
protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException {
- long deviceId = device.getId();
- QueryBuilder> qb = session.getHuaweiActivitySampleDao().queryBuilder();
- qb.where(HuaweiActivitySampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
-
- QueryBuilder qb2 = session.getHuaweiWorkoutSummarySampleDao().queryBuilder();
- List workouts = qb2.where(HuaweiWorkoutSummarySampleDao.Properties.DeviceId.eq(deviceId)).build().list();
- for (HuaweiWorkoutSummarySample sample : workouts) {
- session.getHuaweiWorkoutDataSampleDao().queryBuilder().where(
- HuaweiWorkoutDataSampleDao.Properties.WorkoutId.eq(sample.getWorkoutId())
- ).buildDelete().executeDeleteWithoutDetachingEntities();
- }
-
- session.getHuaweiWorkoutSummarySampleDao().queryBuilder().where(HuaweiWorkoutSummarySampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
-
- session.getBaseActivitySummaryDao().queryBuilder().where(BaseActivitySummaryDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
+ huaweiCoordinator.deleteDevice(gbDevice, device, session);
}
@Override
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/DeviceConfig.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/DeviceConfig.java
index def696cf8..6d43a9918 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/DeviceConfig.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/DeviceConfig.java
@@ -1515,6 +1515,7 @@ public class DeviceConfig {
public static class Response extends HuaweiPacket {
public boolean truSleepNewSync = false;
+ public boolean gpsNewSync = false;
public Response(ParamsProvider paramsProvider) {
super(paramsProvider);
@@ -1532,6 +1533,7 @@ public class DeviceConfig {
// Tag 2 -> File support
byte value = this.tlv.getByte(0x02);
truSleepNewSync = (value & 2) != 0;
+ gpsNewSync = (value & 8) != 0;
}
// Tag 3 -> SmartWatchVersion
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/FileDownloadService0A.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/FileDownloadService0A.java
index 482b9317d..e06db2695 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/FileDownloadService0A.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/FileDownloadService0A.java
@@ -31,6 +31,7 @@ public class FileDownloadService0A {
Type of files that can be downloaded through here:
- debug files
- sleep files
+ - gps files
- rrisqi file
*/
@@ -68,6 +69,26 @@ public class FileDownloadService0A {
}
}
+ public static class GpsFileRequest extends HuaweiPacket {
+ public GpsFileRequest(ParamsProvider paramsProvider, short workoutId) {
+ super(paramsProvider);
+
+ this.serviceId = FileDownloadService0A.id;
+ this.commandId = id;
+
+ this.tlv = new HuaweiTLV()
+ .put(0x02, (byte) 0x02)
+ .put(0x86, new HuaweiTLV()
+ .put(0x07, (byte) 0x01) // Might be type?
+ .put(0x88, new HuaweiTLV()
+ .put(0x09, workoutId)
+ )
+ );
+
+ this.complete = true;
+ }
+ }
+
public static class Response extends HuaweiPacket {
public String[] fileNames;
@@ -77,7 +98,11 @@ public class FileDownloadService0A {
@Override
public void parseTlv() throws ParseException {
- String possibleNames = this.tlv.getString(0x01);
+ String possibleNames;
+ if (this.tlv.contains(0x01))
+ possibleNames = this.tlv.getString(0x01);
+ else // For GPS, also has workoutId (0x09) and another tag (0x0e), not sure of the meaning
+ possibleNames = this.tlv.getObject(0x8b).getObject(0x8c).getString(0x0d);
fileNames = possibleNames.split(";");
}
}
@@ -87,13 +112,16 @@ public class FileDownloadService0A {
public static final int id = 0x02;
public static class Request extends HuaweiPacket {
- public Request(ParamsProvider paramsProvider) {
+ public Request(ParamsProvider paramsProvider, boolean truSleep) {
super(paramsProvider);
this.serviceId = FileDownloadService0A.id;
this.commandId = id;
- this.tlv = new HuaweiTLV().put(0x06, (byte) 1);
+ if (truSleep)
+ this.tlv = new HuaweiTLV().put(0x06, (byte) 0x01);
+ else
+ this.tlv = new HuaweiTLV().put(0x06, (byte) 0x02).put(0x07, (byte) 0x03);
this.complete = true;
}
@@ -151,7 +179,8 @@ public class FileDownloadService0A {
@Override
public void parseTlv() throws ParseException {
- this.fileLength = this.tlv.getInteger(0x02);
+ if (this.tlv.contains(0x02))
+ this.fileLength = this.tlv.getInteger(0x02);
if (this.tlv.contains(0x04))
this.transferType = this.tlv.getByte(0x04);
if (this.tlv.contains(0x05))
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/FileDownloadService2C.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/FileDownloadService2C.java
index 07f651444..bbbea5332 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/FileDownloadService2C.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/FileDownloadService2C.java
@@ -33,6 +33,7 @@ public class FileDownloadService2C {
public enum FileType {
SLEEP_STATE,
SLEEP_DATA,
+ GPS,
UNKNOWN; // Never use this as input
static byte fileTypeToByte(FileType fileType) {
@@ -41,6 +42,8 @@ public class FileDownloadService2C {
return (byte) 0x0e;
case SLEEP_DATA:
return (byte) 0x0f;
+ case GPS:
+ return (byte) 0x11;
default:
throw new RuntimeException();
}
@@ -52,6 +55,8 @@ public class FileDownloadService2C {
return FileType.SLEEP_STATE;
case 0x0f:
return FileType.SLEEP_DATA;
+ case 0x11:
+ return FileType.GPS;
default:
return FileType.UNKNOWN;
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiFileDownloadManager.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiFileDownloadManager.java
index da8716bb7..bdeb3f0c7 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiFileDownloadManager.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiFileDownloadManager.java
@@ -30,6 +30,7 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Locale;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileDownloadService0A;
@@ -102,48 +103,153 @@ public class HuaweiFileDownloadManager {
}
}
- /**
- * Only for internal use
- */
public enum FileType {
DEBUG,
SLEEP_STATE,
SLEEP_DATA,
+ GPS,
UNKNOWN // Never for input!
}
- /**
- * Only for internal use, though also used in exception
- */
+ public static class FileDownloadCallback {
+ public void downloadComplete(FileRequest fileRequest) { }
+
+ public void downloadException(HuaweiFileDownloadException e) {
+ if (e.fileRequest != null)
+ LOG.error("Error downloading file: {}{}", e.fileRequest.getFilename(), e.fileRequest.isNewSync() ? " (newsync)" : "", e);
+ else
+ LOG.error("Error in file download", e);
+ }
+ }
+
public static class FileRequest {
// Inputs
- public String filename;
- public FileType fileType;
- public boolean newSync;
+ private final String filename;
+ private final FileType fileType;
+ private final boolean newSync;
- // Sleep type only
- public int startTime;
- public int endTime;
+ FileDownloadCallback fileDownloadCallback = null;
+ // Sleep type only - for 2C GPS they are set to zero
+ private int startTime = 0;
+ private int endTime = 0;
+
+ // GPS type only
+ private short workoutId;
+ private Long databaseId;
+
+ private FileRequest(String filename, FileType fileType, boolean newSync, int startTime, int endTime, FileDownloadCallback fileDownloadCallback) {
+ this.filename = filename;
+ this.fileType = fileType;
+ this.newSync = newSync;
+ this.fileDownloadCallback = fileDownloadCallback;
+ this.startTime = startTime;
+ this.endTime = endTime;
+ }
+
+ public static FileRequest sleepStateFileRequest(boolean supportsTruSleepNewSync, int startTime, int endTime, FileDownloadCallback fileDownloadCallback) {
+ return new FileRequest("sleep_state.bin", FileType.SLEEP_STATE, supportsTruSleepNewSync, startTime, endTime, fileDownloadCallback);
+ }
+
+ public static FileRequest sleepDataFileRequest(boolean supportsTruSleepNewSync, int startTime, int endTime, FileDownloadCallback fileDownloadCallback) {
+ return new FileRequest("sleep_data.bin", FileType.SLEEP_DATA, supportsTruSleepNewSync, startTime, endTime, fileDownloadCallback);
+ }
+
+ private FileRequest(String filename, FileType fileType, boolean newSync, FileDownloadCallback fileDownloadCallback) {
+ this.filename = filename;
+ this.fileType = fileType;
+ this.newSync = newSync;
+ this.fileDownloadCallback = fileDownloadCallback;
+ }
+
+ public static FileRequest debugFileRequest(String filename, FileDownloadCallback fileDownloadCallback) {
+ return new FileRequest(filename, FileType.DEBUG, false, fileDownloadCallback);
+ }
+
+ private FileRequest(@Nullable String filename, FileType fileType, boolean newSync, short workoutId, Long databaseId, FileDownloadCallback fileDownloadCallback) {
+ this.filename = filename;
+ this.fileType = fileType;
+ this.newSync = newSync;
+ this.fileDownloadCallback = fileDownloadCallback;
+ this.workoutId = workoutId;
+ this.databaseId = databaseId;
+ }
+
+ public static FileRequest workoutGpsFileRequest(boolean newSync, short workoutId, Long databaseId, FileDownloadCallback fileDownloadCallback) {
+ if (newSync)
+ return new FileRequest(String.format(Locale.getDefault(), "%d_gps.bin", workoutId), FileType.GPS, true, workoutId, databaseId, fileDownloadCallback);
+ else
+ return new FileRequest(null, FileType.GPS, false, workoutId, databaseId, fileDownloadCallback);
+ }
// Retrieved
- public int fileSize;
- public int maxBlockSize;
- public int timeout; // TODO: unit?
- public ByteBuffer buffer;
+ private int fileSize;
+ private int maxBlockSize;
+ private int timeout; // TODO: unit?
+ private ByteBuffer buffer;
- public int startOfBlockOffset;
- public int currentBlockSize;
+ private int startOfBlockOffset;
+ private int currentBlockSize;
// Old sync only
- public String[] filenames;
- public byte lastPacketNumber;
+ private String[] filenames;
+ private byte lastPacketNumber;
// New sync only
- public byte fileId;
- public boolean noEncrypt;
+ private byte fileId;
+ private boolean noEncrypt;
+
+ public byte getFileId() {
+ return fileId;
+ }
+
+ public String getFilename() {
+ return filename;
+ }
+
+ public FileType getFileType() {
+ return fileType;
+ }
+
+ public byte[] getData() {
+ if (buffer == null)
+ return new byte[] {};
+ return buffer.array();
+ }
+
+ public int getCurrentOffset() {
+ return buffer.position();
+ }
+
+ public boolean isNewSync() {
+ return newSync;
+ }
+
+ public int getStartTime() {
+ return startTime;
+ }
+
+ public int getEndTime() {
+ return endTime;
+ }
+
+ public short getWorkoutId() {
+ return workoutId;
+ }
+
+ public Long getDatabaseId() {
+ return databaseId;
+ }
+
+ public int getCurrentBlockSize() {
+ return currentBlockSize;
+ }
+
+ public boolean isNoEncrypt() {
+ return noEncrypt;
+ }
}
/**
@@ -219,37 +325,25 @@ public class HuaweiFileDownloadManager {
private final ArrayList fileRequests;
private FileRequest currentFileRequest;
+ // If the GB interface needs to be updated at the end of the queue of downloads
+ private boolean needSync = false;
+
public HuaweiFileDownloadManager(HuaweiSupportProvider supportProvider) {
this.supportProvider = supportProvider;
handler = new Handler(Looper.getMainLooper());
isBusy = false;
fileRequests = new ArrayList<>();
timeout = () -> {
- this.supportProvider.downloadException(new HuaweiFileDownloadTimeoutException(currentFileRequest));
+ this.currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadTimeoutException(currentFileRequest));
reset();
};
}
- public void downloadDebug(String filename) {
- FileRequest request = new FileRequest();
- request.filename = filename;
- request.fileType = FileType.DEBUG;
- request.newSync = false;
+ public void addToQueue(FileRequest fileRequest, boolean needSync) {
synchronized (supportProvider) {
- fileRequests.add(request);
- }
- startDownload();
- }
-
- public void downloadSleep(boolean supportsTruSleepNewSync, String filename, int startTime, int endTime) {
- FileRequest request = new FileRequest();
- request.filename = filename;
- request.fileType = (filename.equals("sleep_state.bin"))?FileType.SLEEP_STATE: FileType.SLEEP_DATA;
- request.newSync = supportsTruSleepNewSync;
- request.startTime = startTime;
- request.endTime = endTime;
- synchronized (supportProvider) {
- fileRequests.add(request);
+ fileRequests.add(fileRequest);
+ if (needSync)
+ this.needSync = true;
}
startDownload();
}
@@ -275,7 +369,7 @@ public class HuaweiFileDownloadManager {
@Override
public void handleException(Request.ResponseParseException e) {
- supportProvider.downloadException(new HuaweiFileDownloadRequestException(null, this.getClass(), e));
+ currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadRequestException(null, this.getClass(), e));
}
});
}
@@ -285,11 +379,15 @@ public class HuaweiFileDownloadManager {
initFileDataReceiver(); // Make sure the fileDataReceiver is ready
synchronized (this.supportProvider) {
- if (this.isBusy)
+ if (this.isBusy) {
+ LOG.debug("A new download is started while a previous is in progress.");
return; // Already downloading, this file will come eventually
+ }
if (this.fileRequests.isEmpty()) {
// No more files to download
- supportProvider.downloadQueueEmpty();
+ supportProvider.downloadQueueEmpty(this.needSync);
+ // Don't need sync after this anymore
+ this.needSync = false;
return;
}
this.isBusy = true;
@@ -305,7 +403,7 @@ public class HuaweiFileDownloadManager {
GetFileDownloadInitRequest r = (GetFileDownloadInitRequest) request;
if (r.newSync) {
if (!currentFileRequest.filename.equals(r.filename)) {
- supportProvider.downloadException(new HuaweiFileDownloadFileMismatchException(
+ currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadFileMismatchException(
currentFileRequest,
r.filename
));
@@ -313,7 +411,7 @@ public class HuaweiFileDownloadManager {
return;
}
if (currentFileRequest.fileType != r.fileType) {
- supportProvider.downloadException(new HuaweiFileDownloadFileMismatchException(
+ currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadFileMismatchException(
currentFileRequest,
r.fileType
));
@@ -329,13 +427,39 @@ public class HuaweiFileDownloadManager {
}
getFileInfo();
} else {
- if (!arrayContains(r.filenames, currentFileRequest.filename)) {
- supportProvider.downloadException(new HuaweiFileDownloadFileMismatchException(
- currentFileRequest,
- r.filenames
- ));
- reset();
- return;
+ if (currentFileRequest.fileType == FileType.GPS) {
+ if (r.filenames.length == 0) {
+ reset();
+ return;
+ }
+ for (String filename : r.filenames) {
+ // We only download the gps file itself right now
+ if (!filename.contains("_gps.bin"))
+ continue;
+
+ // Add download request with the filename at the start of the queue
+ FileRequest fileRequest = new FileRequest(
+ filename,
+ FileType.GPS,
+ currentFileRequest.newSync,
+ currentFileRequest.workoutId,
+ currentFileRequest.databaseId,
+ currentFileRequest.fileDownloadCallback
+ );
+ synchronized (supportProvider) {
+ fileRequests.add(0, fileRequest);
+ }
+ }
+ currentFileRequest = fileRequests.remove(0); // Replace with the file to download
+ } else {
+ if (!arrayContains(r.filenames, currentFileRequest.filename)) {
+ currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadFileMismatchException(
+ currentFileRequest,
+ r.filenames
+ ));
+ reset();
+ return;
+ }
}
currentFileRequest.filenames = r.filenames;
getDownloadParameters();
@@ -344,13 +468,13 @@ public class HuaweiFileDownloadManager {
@Override
public void handleException(Request.ResponseParseException e) {
- supportProvider.downloadException(new HuaweiFileDownloadRequestException(currentFileRequest, this.getClass(), e));
+ currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadRequestException(currentFileRequest, this.getClass(), e));
}
});
try {
getFileDownloadInitRequest.doPerform();
} catch (IOException e) {
- supportProvider.downloadException(new HuaweiFileDownloadSendException(currentFileRequest, getFileDownloadInitRequest, e));
+ currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadSendException(currentFileRequest, getFileDownloadInitRequest, e));
reset();
}
}
@@ -359,7 +483,10 @@ public class HuaweiFileDownloadManager {
// Old sync only, can never be multiple at the same time
// Assuming currentRequest is the correct one the entire time
// Which may no longer be the case when we implement multi-download for new sync
- GetFileParametersRequest getFileParametersRequest = new GetFileParametersRequest(supportProvider);
+ GetFileParametersRequest getFileParametersRequest = new GetFileParametersRequest(supportProvider,
+ currentFileRequest.fileType == FileType.SLEEP_STATE ||
+ currentFileRequest.fileType == FileType.SLEEP_DATA
+ );
getFileParametersRequest.setFinalizeReq(new Request.RequestCallback() {
@Override
public void call() {
@@ -370,14 +497,14 @@ public class HuaweiFileDownloadManager {
@Override
public void handleException(Request.ResponseParseException e) {
- supportProvider.downloadException(new HuaweiFileDownloadRequestException(null, this.getClass(), e));
+ currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadRequestException(null, this.getClass(), e));
reset();
}
});
try {
getFileParametersRequest.doPerform();
} catch (IOException e) {
- supportProvider.downloadException(new HuaweiFileDownloadSendException(currentFileRequest, getFileParametersRequest, e));
+ currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadSendException(currentFileRequest, getFileParametersRequest, e));
reset();
}
}
@@ -390,7 +517,7 @@ public class HuaweiFileDownloadManager {
GetFileInfoRequest r = (GetFileInfoRequest) request;
if (r.newSync) {
if (currentFileRequest.fileId != r.fileId) {
- supportProvider.downloadException(new HuaweiFileDownloadFileMismatchException(currentFileRequest, r.fileId, true));
+ currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadFileMismatchException(currentFileRequest, r.fileId, true));
reset();
return;
}
@@ -412,21 +539,19 @@ public class HuaweiFileDownloadManager {
@Override
public void handleException(Request.ResponseParseException e) {
- supportProvider.downloadException(new HuaweiFileDownloadRequestException(null, this.getClass(), e));
+ currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadRequestException(null, this.getClass(), e));
reset();
}
});
try {
getFileInfoRequest.doPerform();
} catch (IOException e) {
- supportProvider.downloadException(new HuaweiFileDownloadSendException(currentFileRequest, getFileInfoRequest, e));
+ currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadSendException(currentFileRequest, getFileInfoRequest, e));
reset();
}
}
private void downloadNextFileBlock() {
- handler.removeCallbacks(this.timeout);
-
if (currentFileRequest.buffer == null) // New file
currentFileRequest.buffer = ByteBuffer.allocate(currentFileRequest.fileSize);
currentFileRequest.lastPacketNumber = -1; // Counts per block
@@ -439,6 +564,9 @@ public class HuaweiFileDownloadManager {
// Start listening for file data
this.supportProvider.addInProgressRequest(fileDataReceiver);
+ handler.removeCallbacks(this.timeout);
+ handler.postDelayed(HuaweiFileDownloadManager.this.timeout, currentFileRequest.timeout * 1000L);
+
GetFileBlockRequest getFileBlockRequest = new GetFileBlockRequest(supportProvider, currentFileRequest);
getFileBlockRequest.setFinalizeReq(new Request.RequestCallback() {
@Override
@@ -451,20 +579,20 @@ public class HuaweiFileDownloadManager {
try {
getFileBlockRequest.doPerform();
} catch (IOException e) {
- supportProvider.downloadException(new HuaweiFileDownloadSendException(currentFileRequest, getFileBlockRequest, e));
+ currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadSendException(currentFileRequest, getFileBlockRequest, e));
reset();
}
}
private void handleFileData(boolean newSync, byte number, byte[] data) {
if (newSync && currentFileRequest.fileId != number) {
- supportProvider.downloadException(new HuaweiFileDownloadFileMismatchException(currentFileRequest, number, true));
+ currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadFileMismatchException(currentFileRequest, number, true));
reset();
return;
}
if (!newSync) {
if (currentFileRequest.lastPacketNumber != number - 1) {
- supportProvider.downloadException(new HuaweiFileDownloadFileMismatchException(currentFileRequest, number, false));
+ currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadFileMismatchException(currentFileRequest, number, false));
reset();
return;
}
@@ -496,13 +624,12 @@ public class HuaweiFileDownloadManager {
try {
getFileDownloadCompleteRequest.doPerform();
} catch (IOException e) {
- supportProvider.downloadException(new HuaweiFileDownloadSendException(currentFileRequest, getFileDownloadCompleteRequest, e));
+ currentFileRequest.fileDownloadCallback.downloadException(new HuaweiFileDownloadSendException(currentFileRequest, getFileDownloadCompleteRequest, e));
reset();
}
// Handle file data
- if (currentFileRequest.buffer != null) // File size was zero
- supportProvider.downloadComplete(currentFileRequest.filename, currentFileRequest.buffer.array());
+ currentFileRequest.fileDownloadCallback.downloadComplete(currentFileRequest);
if (!this.currentFileRequest.newSync && !this.fileRequests.isEmpty() && !this.fileRequests.get(0).newSync) {
// Old sync can potentially take a shortcut
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java
index bb4b74aaf..1a5ea9839 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java
@@ -30,6 +30,7 @@ import androidx.annotation.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.File;
import java.nio.charset.StandardCharsets;
import java.io.IOException;
import java.util.ArrayList;
@@ -54,6 +55,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinatorSupplier;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinatorSupplier.HuaweiDeviceType;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCrypto;
+import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiGpsParser;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTruSleepParser;
@@ -71,6 +73,8 @@ import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSample;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySample;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySampleDao;
+import nodomain.freeyourgadget.gadgetbridge.export.ActivityTrackExporter;
+import nodomain.freeyourgadget.gadgetbridge.export.GPXExporter;
import nodomain.freeyourgadget.gadgetbridge.externalevents.gps.GBLocationProviderType;
import nodomain.freeyourgadget.gadgetbridge.externalevents.gps.GBLocationService;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
@@ -79,11 +83,14 @@ import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.User;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
+import nodomain.freeyourgadget.gadgetbridge.model.ActivityPoint;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
+import nodomain.freeyourgadget.gadgetbridge.model.ActivityTrack;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
import nodomain.freeyourgadget.gadgetbridge.model.Contact;
+import nodomain.freeyourgadget.gadgetbridge.model.GPSCoordinate;
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
@@ -166,6 +173,8 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetN
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FitnessData;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetWorkModeRequest;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
+import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
+import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.MediaManager;
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
@@ -173,6 +182,48 @@ import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
public class HuaweiSupportProvider {
private static final Logger LOG = LoggerFactory.getLogger(HuaweiSupportProvider.class);
+ private class SyncState {
+ private boolean activitySync = false;
+ private boolean workoutSync = false;
+ private int workoutGpsDownload = 0;
+
+ public void setActivitySync(boolean state) {
+ this.activitySync = state;
+ updateState();
+ }
+
+ public void setWorkoutSync(boolean state) {
+ this.workoutSync = state;
+ updateState();
+ }
+
+ public void startWorkoutGpsDownload() {
+ this.workoutGpsDownload += 1;
+ }
+
+ public void stopWorkoutGpsDownload() {
+ this.workoutGpsDownload -= 1;
+ updateState();
+ }
+
+ public void updateState() {
+ updateState(true);
+ }
+
+ public void updateState(boolean needSync) {
+ if (!activitySync && !workoutSync && workoutGpsDownload == 0) {
+ if (getDevice().isBusy()) {
+ getDevice().unsetBusyTask();
+ getDevice().sendDeviceUpdateIntent(context);
+ }
+ if (needSync)
+ GB.signalActivityDataFinish(getDevice());
+ }
+ }
+ }
+
+ private final SyncState syncState = new SyncState();
+
private final int initTimeout = 2000;
private HuaweiBRSupport brSupport;
@@ -1097,6 +1148,8 @@ public class HuaweiSupportProvider {
}
private void fetchActivityData() {
+ syncState.setActivitySync(true);
+
int sleepStart = 0;
int stepStart = 0;
final int end = (int) (System.currentTimeMillis() / 1000);
@@ -1144,13 +1197,13 @@ public class HuaweiSupportProvider {
@Override
public void call() {
if (!downloadTruSleepData(start, end))
- handleSyncFinished();
+ syncState.setActivitySync(false);
}
@Override
public void handleException(Request.ResponseParseException e) {
LOG.error("Fitness totals exception", e);
- handleSyncFinished();
+ syncState.setActivitySync(false);
}
});
@@ -1161,14 +1214,14 @@ public class HuaweiSupportProvider {
getFitnessTotalsRequest.doPerform();
} catch (IOException e) {
LOG.error("Exception on starting fitness totals request", e);
- handleSyncFinished();
+ syncState.setActivitySync(false);
}
}
@Override
public void handleException(Request.ResponseParseException e) {
LOG.error("Step data count exception", e);
- handleSyncFinished();
+ syncState.setActivitySync(false);
}
});
@@ -1179,14 +1232,14 @@ public class HuaweiSupportProvider {
getStepDataCountRequest.doPerform();
} catch (IOException e) {
LOG.error("Exception on starting step data count request", e);
- handleSyncFinished();
+ syncState.setActivitySync(false);
}
}
@Override
public void handleException(Request.ResponseParseException e) {
LOG.error("Sleep data count exception", e);
- handleSyncFinished();
+ syncState.setActivitySync(false);
}
});
@@ -1194,11 +1247,13 @@ public class HuaweiSupportProvider {
getSleepDataCountRequest.doPerform();
} catch (IOException e) {
LOG.error("Exception on starting sleep data count request", e);
- handleSyncFinished();
+ syncState.setActivitySync(false);
}
}
private void fetchWorkoutData() {
+ syncState.setWorkoutSync(true);
+
int start = 0;
int end = (int) (System.currentTimeMillis() / 1000);
@@ -1261,13 +1316,13 @@ public class HuaweiSupportProvider {
getWorkoutCountRequest.setFinalizeReq(new RequestCallback() {
@Override
public void call() {
- handleSyncFinished();
+ syncState.setWorkoutSync(false);
}
@Override
public void handleException(Request.ResponseParseException e) {
LOG.error("Workout parsing exception", e);
- handleSyncFinished();
+ syncState.setWorkoutSync(false);
}
});
@@ -1275,18 +1330,10 @@ public class HuaweiSupportProvider {
getWorkoutCountRequest.doPerform();
} catch (IOException e) {
LOG.error("Exception on starting workout count request", e);
- handleSyncFinished();
+ syncState.setWorkoutSync(false);
}
}
- private void handleSyncFinished() {
- if (gbDevice.isBusy()) {
- gbDevice.unsetBusyTask();
- gbDevice.sendDeviceUpdateIntent(context);
- }
- GB.signalActivityDataFinish(getDevice());
- }
-
public void onReset(int flags) {
try {
if(flags== GBDeviceProtocol.RESET_FLAGS_FACTORY_RESET) {
@@ -1559,7 +1606,8 @@ public class HuaweiSupportProvider {
packet.poolLength,
packet.laps,
packet.avgSwolf,
- raw
+ raw,
+ null
);
db.getDaoSession().getHuaweiWorkoutSummarySampleDao().insertOrReplace(summarySample);
@@ -2073,52 +2121,151 @@ public class HuaweiSupportProvider {
if (!getHuaweiCoordinator().supportsTruSleep())
return false;
- huaweiFileDownloadManager.downloadSleep(
+ huaweiFileDownloadManager.addToQueue(HuaweiFileDownloadManager.FileRequest.sleepStateFileRequest(
getHuaweiCoordinator().getSupportsTruSleepNewSync(),
- "sleep_state.bin", // new String[] {"sleep_state.bin"}, // Later also "sleep_data.bin", but we don't use it right now
start,
- end
- );
+ end,
+ new HuaweiFileDownloadManager.FileDownloadCallback() {
+ @Override
+ public void downloadComplete(HuaweiFileDownloadManager.FileRequest fileRequest) {
+ if (fileRequest.getData().length != 0) {
+ LOG.debug("Parsing sleep state file");
+ HuaweiTruSleepParser.TruSleepStatus[] results = HuaweiTruSleepParser.parseState(fileRequest.getData());
+ for (HuaweiTruSleepParser.TruSleepStatus status : results)
+ addSleepActivity(status.startTime, status.endTime, (byte) 0x06, (byte) 0x0a);
+ } else
+ LOG.debug("Sleep state file empty");
+ syncState.setActivitySync(false);
+ }
+
+ @Override
+ public void downloadException(HuaweiFileDownloadManager.HuaweiFileDownloadException e) {
+ super.downloadException(e);
+ syncState.setActivitySync(false);
+ }
+ }
+ ), true);
return true;
}
- /**
- * Called when a file download is complete
- * @param fileName Filename of the file
- * @param fileContents Contents of the file
- */
- public void downloadComplete(String fileName, byte[] fileContents) {
- LOG.debug("File download complete: {}: {}", fileName, GB.hexdump(fileContents));
+ public void downloadWorkoutGpsFiles(short workoutId, Long databaseId) {
+ syncState.startWorkoutGpsDownload();
- if (fileName.equals("sleep_state.bin")) {
- HuaweiTruSleepParser.TruSleepStatus[] results = HuaweiTruSleepParser.parseState(fileContents);
- for (HuaweiTruSleepParser.TruSleepStatus status : results)
- addSleepActivity(status.startTime, status.endTime, (byte) 0x06, (byte) 0x0a);
- // This should only be called once per sync - also if we start downloading more sleep data
- GB.signalActivityDataFinish(getDevice());
- // Unsetting busy is done at the end of all downloads
- } // "sleep_data.bin" later as well
+ huaweiFileDownloadManager.addToQueue(HuaweiFileDownloadManager.FileRequest.workoutGpsFileRequest(
+ getHuaweiCoordinator().isSupportsGpsNewSync(),
+ workoutId,
+ databaseId,
+ new HuaweiFileDownloadManager.FileDownloadCallback() {
+ @Override
+ public void downloadComplete(HuaweiFileDownloadManager.FileRequest fileRequest) {
+ syncState.stopWorkoutGpsDownload();
+
+ if (fileRequest.getData().length == 0) {
+ LOG.debug("GPS file empty");
+ return;
+ }
+
+ LOG.debug("Parsing GPS file");
+
+ HuaweiGpsParser.GpsPoint[] points = HuaweiGpsParser.parseHuaweiGps(fileRequest.getData());
+
+ LOG.debug("Received {} GPS points", points.length);
+
+ if (points.length == 0) {
+ LOG.debug("No GPS points returned");
+ return;
+ }
+
+ ActivityTrack track = new ActivityTrack();
+
+ track.setName("Workout " + fileRequest.getWorkoutId());
+ track.setBaseTime(DateTimeUtils.parseTimeStamp(points[0].timestamp));
+
+ try (DBHandler db = GBApplication.acquireDB()) {
+ track.setUser(DBHelper.getUser(db.getDaoSession()));
+ track.setDevice(DBHelper.getDevice(gbDevice, db.getDaoSession()));
+ } catch (Exception e) {
+ LOG.error("Cannot acquire DB, set user, or set device for Activity track, continuing anyway");
+ }
+
+ for (HuaweiGpsParser.GpsPoint point : points) {
+ GPSCoordinate coordinate;
+ if (point.altitudeSupported)
+ coordinate = new GPSCoordinate(point.longitude, point.latitude, point.altitude);
+ else
+ coordinate = new GPSCoordinate(point.longitude, point.latitude);
+
+ ActivityPoint activityPoint = new ActivityPoint();
+ activityPoint.setTime(DateTimeUtils.parseTimeStamp(point.timestamp));
+ activityPoint.setLocation(coordinate);
+
+ track.addTrackPoint(activityPoint);
+ }
+
+ String filename = FileUtils.makeValidFileName("workout_" + fileRequest.getWorkoutId() + "_" + points[0].timestamp + ".gpx");
+ File targetFile;
+ try {
+ targetFile = new File(
+ getDevice().getDeviceCoordinator().getWritableExportDirectory(getDevice()),
+ filename
+ );
+ } catch (IOException e) {
+ // TODO: Translatable string
+ GB.toast(context, "Could not open Workout GPS file to write to", Toast.LENGTH_SHORT, GB.ERROR, e);
+ LOG.error("Could not open Workout GPS file to write to", e);
+ return;
+ }
+
+ GPXExporter exporter = new GPXExporter();
+ exporter.setCreator(GBApplication.app().getNameAndVersion());
+ try {
+ exporter.performExport(track, targetFile);
+ } catch (IOException | ActivityTrackExporter.GPXTrackEmptyException e) {
+ // TODO: Translatable string
+ GB.toast(context, "Failed to export Workout GPX file", Toast.LENGTH_SHORT, GB.ERROR, e);
+ LOG.error("Failed to export Workout GPX file", e);
+ return;
+ }
+
+ Long databaseId = fileRequest.getDatabaseId();
+ if (databaseId == null) {
+ // TODO: Translatable string
+ GB.toast(context, "Cannot link GPX to workout", Toast.LENGTH_SHORT, GB.ERROR);
+ LOG.error("Cannot link GPX to workout");
+ return;
+ }
+
+ try (DBHandler db = GBApplication.acquireDB()) {
+ DaoSession daoSession = db.getDaoSession();
+ HuaweiWorkoutSummarySample sample = daoSession.getHuaweiWorkoutSummarySampleDao().load(databaseId);
+ sample.setGpxFileLocation(targetFile.getAbsolutePath());
+ sample.update();
+ } catch (Exception e) {
+ // TODO: Translatable string
+ GB.toast(context, "Failed to save Workout GPX file location", Toast.LENGTH_SHORT, GB.ERROR, e);
+ LOG.error("Failed to save Workout GPX file location", e);
+ return;
+ }
+
+ new HuaweiWorkoutGbParser(getDevice()).parseWorkout(databaseId);
+
+ LOG.debug("Completed workout GPS parsing and inserting");
+ }
+
+ @Override
+ public void downloadException(HuaweiFileDownloadManager.HuaweiFileDownloadException e) {
+ super.downloadException(e);
+ syncState.stopWorkoutGpsDownload();
+ }
+ }
+ ), true);
}
/**
* Called when there are no more files left to download
*/
- public void downloadQueueEmpty() {
- if (gbDevice.isBusy()) {
- gbDevice.unsetBusyTask();
- gbDevice.sendDeviceUpdateIntent(context);
- }
- }
-
- public void downloadException(HuaweiFileDownloadManager.HuaweiFileDownloadException e) {
- GB.toast("Error downloading file", Toast.LENGTH_SHORT, GB.ERROR, e);
- if (e.fileRequest != null)
- LOG.error("Error downloading file: {}{}", e.fileRequest.filename, e.fileRequest.newSync ? " (newsync)" : "", e);
- else
- LOG.error("Error in file download", e);
-
- // We also reset the sync state, just to get back to working as nicely as possible
- handleSyncFinished();
+ public void downloadQueueEmpty(boolean needSync) {
+ syncState.updateState(needSync);
}
public void onTestNewFunction() {
@@ -2126,17 +2273,27 @@ public class HuaweiSupportProvider {
gbDevice.setBusyTask("Downloading file...");
gbDevice.sendDeviceUpdateIntent(getContext());
- huaweiFileDownloadManager.downloadSleep(
+ huaweiFileDownloadManager.addToQueue(HuaweiFileDownloadManager.FileRequest.sleepStateFileRequest(
getHuaweiCoordinator().getSupportsTruSleepNewSync(),
- "sleep_state.bin",
0,
- (int) (System.currentTimeMillis() / 1000)
- );
- huaweiFileDownloadManager.downloadSleep(
+ (int) (System.currentTimeMillis() / 1000),
+ new HuaweiFileDownloadManager.FileDownloadCallback() {
+ @Override
+ public void downloadComplete(HuaweiFileDownloadManager.FileRequest fileRequest) {
+ // Handle file contents
+ }
+ }
+ ), true);
+ huaweiFileDownloadManager.addToQueue(HuaweiFileDownloadManager.FileRequest.sleepDataFileRequest(
getHuaweiCoordinator().getSupportsTruSleepNewSync(),
- "sleep_data.bin",
0,
- (int) (System.currentTimeMillis() / 1000)
- );
+ (int) (System.currentTimeMillis() / 1000),
+ new HuaweiFileDownloadManager.FileDownloadCallback() {
+ @Override
+ public void downloadComplete(HuaweiFileDownloadManager.FileRequest fileRequest) {
+ // Handle file contents
+ }
+ }
+ ), true);
}
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiWorkoutGbParser.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiWorkoutGbParser.java
index fa5ab5a19..8a9ac1cf9 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiWorkoutGbParser.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiWorkoutGbParser.java
@@ -304,6 +304,10 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
}
public void parseWorkout(Long workoutId) {
+ LOG.debug("Parsing workout ID {}", workoutId);
+ if (workoutId == null)
+ return;
+
try (DBHandler db = GBApplication.acquireDB()) {
final DaoSession session = db.getDaoSession();
final Device device = DBHelper.getDevice(gbDevice, session);
@@ -718,6 +722,11 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
if (baseSummary.getName() == null) {
baseSummary.setName("Workout " + summary.getWorkoutNumber());
}
+
+ if (baseSummary.getGpxTrack() == null) {
+ baseSummary.setGpxTrack(summary.getGpxFileLocation());
+ }
+
// start time never changes
baseSummary.setEndTime(new Date(summary.getEndTimestamp() * 1000L));
baseSummary.setActivityKind(type.getCode());
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileBlockRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileBlockRequest.java
index fcc4389bb..1a1beb3cc 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileBlockRequest.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileBlockRequest.java
@@ -29,7 +29,7 @@ public class GetFileBlockRequest extends Request {
public GetFileBlockRequest(HuaweiSupportProvider support, HuaweiFileDownloadManager.FileRequest request) {
super(support);
- if (request.newSync) {
+ if (request.isNewSync()) {
this.serviceId = FileDownloadService2C.id;
this.commandId = FileDownloadService2C.RequestBlock.id;
} else {
@@ -42,20 +42,20 @@ public class GetFileBlockRequest extends Request {
@Override
protected List createRequest() throws Request.RequestCreationException {
try {
- if (this.request.newSync)
+ if (this.request.isNewSync())
return new FileDownloadService2C.RequestBlock(
paramsProvider,
- this.request.fileId,
- this.request.buffer.position(),
- this.request.currentBlockSize,
- this.request.noEncrypt
+ this.request.getFileId(),
+ this.request.getCurrentOffset(),
+ this.request.getCurrentBlockSize(),
+ this.request.isNoEncrypt()
).serialize();
else
return new FileDownloadService0A.RequestBlock.Request(
paramsProvider,
- this.request.filename,
- this.request.buffer.position(),
- this.request.currentBlockSize
+ this.request.getFilename(),
+ this.request.getCurrentOffset(),
+ this.request.getCurrentBlockSize()
).serialize();
} catch (HuaweiPacket.CryptoException e) {
throw new Request.RequestCreationException(e);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileDownloadCompleteRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileDownloadCompleteRequest.java
index 425c14e70..a0168863b 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileDownloadCompleteRequest.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileDownloadCompleteRequest.java
@@ -30,7 +30,7 @@ public class GetFileDownloadCompleteRequest extends Request {
public GetFileDownloadCompleteRequest(HuaweiSupportProvider support, HuaweiFileDownloadManager.FileRequest request) {
super(support);
- if (request.newSync) {
+ if (request.isNewSync()) {
this.serviceId = FileDownloadService2C.id;
this.commandId = FileDownloadService2C.FileDownloadCompleteRequest.id;
} else {
@@ -43,8 +43,8 @@ public class GetFileDownloadCompleteRequest extends Request {
@Override
protected List createRequest() throws RequestCreationException {
try {
- if (request.newSync)
- return new FileDownloadService2C.FileDownloadCompleteRequest(paramsProvider, this.request.fileId).serialize();
+ if (request.isNewSync())
+ return new FileDownloadService2C.FileDownloadCompleteRequest(paramsProvider, this.request.getFileId()).serialize();
else
return new FileDownloadService0A.FileDownloadCompleteRequest(paramsProvider).serialize();
} catch (HuaweiPacket.CryptoException e) {
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileDownloadInitRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileDownloadInitRequest.java
index ebe80c53a..2e8951046 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileDownloadInitRequest.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileDownloadInitRequest.java
@@ -41,7 +41,7 @@ public class GetFileDownloadInitRequest extends Request {
public GetFileDownloadInitRequest(HuaweiSupportProvider support, HuaweiFileDownloadManager.FileRequest request) {
super(support);
- if (request.newSync) {
+ if (request.isNewSync()) {
this.serviceId = FileDownloadService2C.id;
this.commandId = FileDownloadService2C.FileDownloadInit.id;
} else {
@@ -57,6 +57,8 @@ public class GetFileDownloadInitRequest extends Request {
return FileDownloadService2C.FileType.SLEEP_STATE;
case SLEEP_DATA:
return FileDownloadService2C.FileType.SLEEP_DATA;
+ case GPS:
+ return FileDownloadService2C.FileType.GPS;
default:
return FileDownloadService2C.FileType.UNKNOWN;
}
@@ -68,6 +70,8 @@ public class GetFileDownloadInitRequest extends Request {
return HuaweiFileDownloadManager.FileType.SLEEP_STATE;
case SLEEP_DATA:
return HuaweiFileDownloadManager.FileType.SLEEP_DATA;
+ case GPS:
+ return HuaweiFileDownloadManager.FileType.GPS;
default:
return HuaweiFileDownloadManager.FileType.UNKNOWN;
}
@@ -76,16 +80,18 @@ public class GetFileDownloadInitRequest extends Request {
@Override
protected List createRequest() throws RequestCreationException {
try {
- if (this.request.newSync) {
- FileDownloadService2C.FileType type = convertFileTypeTo2C(request.fileType);
+ if (this.request.isNewSync()) {
+ FileDownloadService2C.FileType type = convertFileTypeTo2C(request.getFileType());
if (type == FileDownloadService2C.FileType.UNKNOWN)
- throw new RequestCreationException("Cannot convert type " + request.fileType);
- return new FileDownloadService2C.FileDownloadInit.Request(paramsProvider, request.filename, type, request.startTime, request.endTime).serialize();
+ throw new RequestCreationException("Cannot convert type " + request.getFileType());
+ return new FileDownloadService2C.FileDownloadInit.Request(paramsProvider, request.getFilename(), type, request.getStartTime(), request.getEndTime()).serialize();
} else {
- if (this.request.fileType == HuaweiFileDownloadManager.FileType.DEBUG)
+ if (this.request.getFileType() == HuaweiFileDownloadManager.FileType.DEBUG)
return new FileDownloadService0A.FileDownloadInit.DebugFilesRequest(paramsProvider).serialize();
- else if (this.request.fileType == HuaweiFileDownloadManager.FileType.SLEEP_STATE)
- return new FileDownloadService0A.FileDownloadInit.SleepFilesRequest(paramsProvider, request.startTime, request.endTime).serialize();
+ else if (this.request.getFileType() == HuaweiFileDownloadManager.FileType.SLEEP_STATE)
+ return new FileDownloadService0A.FileDownloadInit.SleepFilesRequest(paramsProvider, request.getStartTime(), request.getEndTime()).serialize();
+ else if (this.request.getFileType() == HuaweiFileDownloadManager.FileType.GPS)
+ return new FileDownloadService0A.FileDownloadInit.GpsFileRequest(paramsProvider, request.getWorkoutId()).serialize();
else
throw new RequestCreationException("Unknown file type");
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileInfoRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileInfoRequest.java
index 92965a356..b55d402a3 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileInfoRequest.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileInfoRequest.java
@@ -40,7 +40,7 @@ public class GetFileInfoRequest extends Request {
public GetFileInfoRequest(HuaweiSupportProvider support, HuaweiFileDownloadManager.FileRequest request) {
super(support);
- if (request.newSync) {
+ if (request.isNewSync()) {
this.serviceId = FileDownloadService2C.id;
this.commandId = FileDownloadService2C.FileInfo.id;
} else {
@@ -53,10 +53,10 @@ public class GetFileInfoRequest extends Request {
@Override
protected List createRequest() throws RequestCreationException {
try {
- if (this.request.newSync)
- return new FileDownloadService2C.FileInfo.Request(paramsProvider, this.request.fileId).serialize();
+ if (this.request.isNewSync())
+ return new FileDownloadService2C.FileInfo.Request(paramsProvider, this.request.getFileId()).serialize();
else
- return new FileDownloadService0A.FileInfo.Request(paramsProvider, this.request.filename).serialize();
+ return new FileDownloadService0A.FileInfo.Request(paramsProvider, this.request.getFilename()).serialize();
} catch (HuaweiPacket.CryptoException e) {
throw new RequestCreationException(e);
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileParametersRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileParametersRequest.java
index 8002aeb6f..0251c088d 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileParametersRequest.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetFileParametersRequest.java
@@ -24,19 +24,22 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupport
public class GetFileParametersRequest extends Request {
+ private final boolean truSleep;
+
private int maxBlockSize;
private int timeout;
- public GetFileParametersRequest(HuaweiSupportProvider support) {
+ public GetFileParametersRequest(HuaweiSupportProvider support, boolean truSleep) {
super(support);
this.serviceId = FileDownloadService0A.id;
this.commandId = FileDownloadService0A.FileParameters.id;
+ this.truSleep = truSleep;
}
@Override
protected List createRequest() throws RequestCreationException {
try {
- return new FileDownloadService0A.FileParameters.Request(paramsProvider).serialize();
+ return new FileDownloadService0A.FileParameters.Request(paramsProvider, truSleep).serialize();
} catch (HuaweiPacket.CryptoException e) {
throw new RequestCreationException(e);
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetSettingRelatedRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetSettingRelatedRequest.java
index 009d273df..e113548ac 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetSettingRelatedRequest.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetSettingRelatedRequest.java
@@ -56,5 +56,6 @@ public class GetSettingRelatedRequest extends Request {
LOG.debug("handle Setting Related");
supportProvider.getHuaweiCoordinator().setSupportsTruSleepNewSync(((DeviceConfig.SettingRelated.Response) receivedPacket).truSleepNewSync);
+ supportProvider.getHuaweiCoordinator().setSupportsGpsNewSync(((DeviceConfig.SettingRelated.Response) receivedPacket).gpsNewSync);
}
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetWorkoutDataRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetWorkoutDataRequest.java
index b339e42e0..c2e268c24 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetWorkoutDataRequest.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetWorkoutDataRequest.java
@@ -113,6 +113,7 @@ public class GetWorkoutDataRequest extends Request {
this.nextRequest(nextRequest);
} else {
new HuaweiWorkoutGbParser(getDevice()).parseWorkout(this.databaseId);
+ supportProvider.downloadWorkoutGpsFiles(this.workoutNumbers.workoutNumber, this.databaseId);
if (!remainder.isEmpty()) {
GetWorkoutTotalsRequest nextRequest = new GetWorkoutTotalsRequest(
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetWorkoutPaceRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetWorkoutPaceRequest.java
index 3145dcba0..babb367aa 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetWorkoutPaceRequest.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetWorkoutPaceRequest.java
@@ -90,6 +90,7 @@ public class GetWorkoutPaceRequest extends Request {
this.nextRequest(nextRequest);
} else {
new HuaweiWorkoutGbParser(getDevice()).parseWorkout(this.databaseId);
+ supportProvider.downloadWorkoutGpsFiles(this.workoutNumbers.workoutNumber, this.databaseId);
if (!remainder.isEmpty()) {
GetWorkoutTotalsRequest nextRequest = new GetWorkoutTotalsRequest(
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetWorkoutTotalsRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetWorkoutTotalsRequest.java
index 476873f10..c98551354 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetWorkoutTotalsRequest.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetWorkoutTotalsRequest.java
@@ -104,6 +104,7 @@ public class GetWorkoutTotalsRequest extends Request {
this.nextRequest(nextRequest);
} else {
new HuaweiWorkoutGbParser(getDevice()).parseWorkout(databaseId);
+ supportProvider.downloadWorkoutGpsFiles(this.workoutNumbers.workoutNumber, databaseId);
if (!remainder.isEmpty()) {
GetWorkoutTotalsRequest nextRequest = new GetWorkoutTotalsRequest(