diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/Workout.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/Workout.java index 01f9797ee..9ad41749d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/Workout.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/Workout.java @@ -19,6 +19,7 @@ package nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.List; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket; @@ -91,6 +92,9 @@ public class Workout { } this.workoutNumbers.add(workoutNumber); } + + // Has to be sorted for the timestamp-based sync start that we use in the HuaweiSupportProvider + this.workoutNumbers.sort(Comparator.comparingInt(o -> o.workoutNumber)); } } } 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 9e79c0a87..1be2099b6 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 @@ -197,32 +197,75 @@ public class HuaweiSupportProvider { // TODO: Potentially use translatable messages for the toast messages private class SyncState { + private final List syncQueue = new ArrayList<>(2); + private boolean activitySync = false; private boolean p2pSync = false; private boolean workoutSync = false; private int workoutGpsDownload = 0; + public void addActivitySyncToQueue() { + if (syncQueue.contains(RecordedDataTypes.TYPE_ACTIVITY)) + LOG.info("Activity type sync already queued, ignoring"); + else + syncQueue.add(RecordedDataTypes.TYPE_ACTIVITY); + } + + public void addWorkoutSyncToQueue() { + if (syncQueue.contains(RecordedDataTypes.TYPE_GPS_TRACKS)) + LOG.info("Workout type sync already queued, ignoring"); + else + syncQueue.add(RecordedDataTypes.TYPE_GPS_TRACKS); + } + + public int getCurrentSyncType() { + if (syncQueue.isEmpty()) + return -1; + return syncQueue.get(0); + } + public void setActivitySync(boolean state) { + LOG.debug("Set activity sync state to {}", state); this.activitySync = state; + if (!state && !this.p2pSync) { + this.syncQueue.remove((Integer) RecordedDataTypes.TYPE_ACTIVITY); + HuaweiSupportProvider.this.fetchRecodedDataFromQueue(); + } updateState(); } public void setP2pSync(boolean state) { + LOG.debug("Set p2p sync state to {}", state); this.p2pSync = state; + if (!state && !this.activitySync) { + this.syncQueue.remove((Integer) RecordedDataTypes.TYPE_ACTIVITY); + HuaweiSupportProvider.this.fetchRecodedDataFromQueue(); + } updateState(); } public void setWorkoutSync(boolean state) { + LOG.debug("Set workout sync state to {}", state); this.workoutSync = state; + if (!state && this.workoutGpsDownload == 0) { + this.syncQueue.remove((Integer) RecordedDataTypes.TYPE_GPS_TRACKS); + HuaweiSupportProvider.this.fetchRecodedDataFromQueue(); + } updateState(); } public void startWorkoutGpsDownload() { this.workoutGpsDownload += 1; + LOG.debug("Add GPS download: {}", this.workoutGpsDownload); } public void stopWorkoutGpsDownload() { this.workoutGpsDownload -= 1; + LOG.debug("Subtract GPS download: {}", this.workoutGpsDownload); + if (this.workoutGpsDownload == 0 && !this.workoutSync) { + this.syncQueue.remove((Integer) RecordedDataTypes.TYPE_GPS_TRACKS); + HuaweiSupportProvider.this.fetchRecodedDataFromQueue(); + } updateState(); } @@ -1163,23 +1206,31 @@ public class HuaweiSupportProvider { } public void onFetchRecordedData(int dataTypes) { - if (gbDevice.isBusy()) { + for (int i = 1; i > -1; i <<= 1) { + if ((dataTypes & i) != 0) { + switch (i) { + case RecordedDataTypes.TYPE_ACTIVITY: + this.syncState.addActivitySyncToQueue(); + break; + case RecordedDataTypes.TYPE_GPS_TRACKS: + this.syncState.addWorkoutSyncToQueue(); + break; + // Ignore the following because we know/they are included in the others + case RecordedDataTypes.TYPE_SPO2: + case RecordedDataTypes.TYPE_STRESS: + case RecordedDataTypes.TYPE_HEART_RATE: + case RecordedDataTypes.TYPE_PAI: + case RecordedDataTypes.TYPE_SLEEP_RESPIRATORY_RATE: + break; + default: + LOG.warn("Recorded data type {} not implemented yet.", i); + } + } + } + if (gbDevice.isBusy()) LOG.warn("Device is already busy with {}, so won't fetch data now.", gbDevice.getBusyTask()); - // TODO: better way of letting user know? - GB.toast("Device is already busy with " + gbDevice.getBusyTask() + ", so won't fetch data now.", Toast.LENGTH_LONG, 0); - return; - } - - // TODO: Add support for retrieving multiple activity types with one call - maybe with a queue? - - if ((dataTypes & RecordedDataTypes.TYPE_ACTIVITY) != 0) { - fetchActivityData(); - } else if (dataTypes == RecordedDataTypes.TYPE_GPS_TRACKS) { - fetchWorkoutData(); - } else { - LOG.warn("Recorded data type {} not implemented yet.", dataTypes); - GB.toast("Recoded data type " + dataTypes + " not implemented yet", Toast.LENGTH_SHORT, GB.WARN); - } + else + fetchRecodedDataFromQueue(); // Get the battery level as well getBatteryLevel(); @@ -1189,6 +1240,18 @@ public class HuaweiSupportProvider { getAlarms(); } + private void fetchRecodedDataFromQueue() { + int dataType = this.syncState.getCurrentSyncType(); + if (dataType == -1) + return; // Empty queue + + if (dataType == RecordedDataTypes.TYPE_ACTIVITY) { + fetchActivityData(); + } else if (dataType == RecordedDataTypes.TYPE_GPS_TRACKS) { + fetchWorkoutData(); + } + } + private void fetchActivityData() { syncState.setActivitySync(true); fetchActivityDataP2P(); @@ -1296,9 +1359,9 @@ public class HuaweiSupportProvider { } private void fetchActivityDataP2P() { - syncState.setP2pSync(true); HuaweiP2PDataDictionarySyncService P2PSyncService = HuaweiP2PDataDictionarySyncService.getRegisteredInstance(huaweiP2PManager); if (P2PSyncService != null && getHuaweiCoordinator().supportsTemperature()) { + syncState.setP2pSync(true); P2PSyncService.sendSyncRequest(400012, new HuaweiP2PDataDictionarySyncService.DictionarySyncCallback() { @Override public void onComplete(boolean complete) { @@ -2355,7 +2418,7 @@ public class HuaweiSupportProvider { new HuaweiFileDownloadManager.FileDownloadCallback() { @Override public void downloadComplete(HuaweiFileDownloadManager.FileRequest fileRequest) { - syncState.stopWorkoutGpsDownload(); + syncState.stopWorkoutGpsDownload(); // TODO: delay until the file is actually parsed... extraCallbackAction.run(); if (fileRequest.getData().length == 0) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetWorkoutCountRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetWorkoutCountRequest.java index 994b8a299..02398b537 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetWorkoutCountRequest.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetWorkoutCountRequest.java @@ -83,6 +83,8 @@ public class GetWorkoutCountRequest extends Request { ); nextRequest.setFinalizeReq(this.finalizeReq); this.nextRequest(nextRequest); + } else { + this.supportProvider.endOfWorkoutSync(); } } }