1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-04 17:27:24 +01:00

Mi Band 8: Fix activity fetching

This commit is contained in:
José Rebelo 2023-10-17 21:44:27 +01:00
parent d66de2f94f
commit d35bcef406
4 changed files with 48 additions and 46 deletions

View File

@ -343,6 +343,12 @@ public abstract class XiaomiCoordinator extends AbstractBLEDeviceCoordinator {
settings.add(R.xml.devicesettings_header_other);
settings.add(R.xml.devicesettings_camera_remote);
//
// Developer
//
settings.add(R.xml.devicesettings_header_developer);
settings.add(R.xml.devicesettings_keep_activity_data_on_device);
return ArrayUtils.toPrimitive(settings.toArray(new Integer[0]));
}

View File

@ -22,7 +22,10 @@ import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.proto.xiaomi.XiaomiProto;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public final class XiaomiPreferences {
private XiaomiPreferences() {
@ -61,4 +64,9 @@ public final class XiaomiPreferences {
public static String getPrefPossibleValuesKey(final String key) {
return String.format(Locale.ROOT, "%s_possible_values", key);
}
public static boolean keepActivityDataOnDevice(final GBDevice gbDevice) {
final Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()));
return prefs.getBoolean("keep_activity_data_on_device", false);
}
}

View File

@ -33,6 +33,7 @@ import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.XiaomiPreferences;
import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.XiaomiSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.services.XiaomiHealthService;
import nodomain.freeyourgadget.gadgetbridge.util.CheckSums;
@ -43,9 +44,8 @@ public class XiaomiActivityFileFetcher {
private final XiaomiHealthService mHealthService;
private final Queue<List<XiaomiActivityFileId>> mFetchQueue = new LinkedList<>();
private ByteArrayOutputStream mBuffer = null;
private Set<XiaomiActivityFileId> pendingFiles = new HashSet<>();
private final Queue<XiaomiActivityFileId> mFetchQueue = new LinkedList<>();
private ByteArrayOutputStream mBuffer = new ByteArrayOutputStream();
private boolean isFetching = false;
public XiaomiActivityFileFetcher(final XiaomiHealthService healthService) {
@ -58,18 +58,11 @@ public class XiaomiActivityFileFetcher {
LOG.debug("Got activity chunk {}/{}", num, total);
if (num == 1) {
if (mBuffer == null) {
mBuffer = new ByteArrayOutputStream();
}
mBuffer.reset();
mBuffer.write(chunk, 4, chunk.length - 4);
}
if (num == total) {
final byte[] data = mBuffer.toByteArray();
mBuffer.reset();
mBuffer = null;
mBuffer = new ByteArrayOutputStream();
if (data.length < 13) {
LOG.warn("Activity data length of {} is too short", data.length);
@ -78,8 +71,15 @@ public class XiaomiActivityFileFetcher {
return;
}
if (!validChecksum(data)) {
LOG.warn("Invalid activity data checksum");
final int arrCrc32 = CheckSums.getCRC32(data, 0, data.length - 4);
final int expectedCrc32 = BLETypeConversions.toUint32(data, data.length - 4);
if (arrCrc32 != expectedCrc32) {
LOG.warn(
"Invalid activity data checksum: got {}, expected {}",
String.format("%08X", arrCrc32),
String.format("%08X", expectedCrc32)
);
// FIXME this may mess up the order.. maybe we should just abort
triggerNextFetch();
return;
@ -104,18 +104,21 @@ public class XiaomiActivityFileFetcher {
}
if (activityParser.parse(fileId, activityData)) {
if (!XiaomiPreferences.keepActivityDataOnDevice(mHealthService.getSupport().getDevice())) {
LOG.debug("Acking recorded data {}", fileId);
//mHealthService.ackRecordedData(fileId);
}
// FIXME only after receiving everything triggerNextFetch();
mHealthService.ackRecordedData(fileId);
}
}
public void fetch(final List<XiaomiActivityFileId> fileIds) {
mFetchQueue.add(fileIds);
triggerNextFetch();
}
}
public void fetch(final XiaomiActivityFileId fileId) {
mFetchQueue.add(fileId);
if (!isFetching) {
// Currently not fetching anything, fetch the next
isFetching = true;
final XiaomiSupport support = mHealthService.getSupport();
final Context context = support.getContext();
GB.updateTransferNotification(context.getString(R.string.busy_task_fetch_activity_data),"", true, 0, context);
@ -125,21 +128,18 @@ public class XiaomiActivityFileFetcher {
}
private void triggerNextFetch() {
final List<XiaomiActivityFileId> fileIds = mFetchQueue.poll();
final XiaomiActivityFileId fileId = mFetchQueue.poll();
if (fileIds == null || fileIds.isEmpty()) {
if (fileId == null) {
LOG.debug("Nothing more to fetch");
isFetching = false;
mHealthService.getSupport().getDevice().unsetBusyTask();
GB.updateTransferNotification(null, "", false, 100, mHealthService.getSupport().getContext());
return;
}
mHealthService.requestRecordedData(fileIds);
}
LOG.debug("Triggering next fetch for: {}", fileId);
public boolean validChecksum(final byte[] arr) {
final int arrCrc32 = CheckSums.getCRC32(arr, 0, arr.length - 4);
final int expectedCrc32 = BLETypeConversions.toUint32(arr, arr.length - 4);
return arrCrc32 == expectedCrc32;
mHealthService.requestRecordedData(fileId);
}
}

View File

@ -410,7 +410,7 @@ public class XiaomiHealthService extends AbstractXiaomiService {
}
public void onFetchRecordedData(final int dataTypes) {
LOG.debug("Fetch recorded data: {}", dataTypes);
LOG.debug("Fetch recorded data: {}", String.format("0x%08X", dataTypes));
fetchRecordedDataToday();
}
@ -439,19 +439,14 @@ public class XiaomiHealthService extends AbstractXiaomiService {
);
}
public void requestRecordedData(final List<XiaomiActivityFileId> fileIds) {
final ByteBuffer buf = ByteBuffer.allocate(7 * fileIds.size()).order(ByteOrder.LITTLE_ENDIAN);
for (final XiaomiActivityFileId fileId : fileIds) {
buf.put(fileId.toBytes());
}
public void requestRecordedData(final XiaomiActivityFileId fileId) {
getSupport().sendCommand(
"request recorded data",
XiaomiProto.Command.newBuilder()
.setType(COMMAND_TYPE)
.setSubtype(CMD_ACTIVITY_FETCH_REQUEST)
.setHealth(XiaomiProto.Health.newBuilder().setActivityRequestFileIds(
ByteString.copyFrom(buf.array())
ByteString.copyFrom(fileId.toBytes())
))
.build()
);
@ -476,26 +471,19 @@ public class XiaomiHealthService extends AbstractXiaomiService {
return;
}
LOG.debug("Got {} record IDs", recordIds.length / 7);
LOG.debug("Got {} activity file IDs", recordIds.length / 7);
final ByteBuffer buf = ByteBuffer.wrap(recordIds).order(ByteOrder.LITTLE_ENDIAN);
final List<XiaomiActivityFileId> fileIds = new ArrayList<>();
while (buf.position() < buf.limit()) {
final XiaomiActivityFileId fileId = XiaomiActivityFileId.from(buf);
LOG.debug("Got activity to fetch: {}", fileId);
fileIds.add(fileId);
}
if (!fileIds.isEmpty()) {
LOG.debug("Fetching {} files", fileIds.size());
activityFetcher.fetch(fileIds);
activityFetcher.fetch(fileId);
}
if (subtype == CMD_ACTIVITY_FETCH_TODAY) {
LOG.debug("Fetch recorded data from the past");
// FIXME fix scheduling fetchRecordedDataPast();
fetchRecordedDataPast();
}
}