1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-04 09:17:29 +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_header_other);
settings.add(R.xml.devicesettings_camera_remote); 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])); 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.Locale;
import java.util.TimeZone; 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.proto.xiaomi.XiaomiProto;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public final class XiaomiPreferences { public final class XiaomiPreferences {
private XiaomiPreferences() { private XiaomiPreferences() {
@ -61,4 +64,9 @@ public final class XiaomiPreferences {
public static String getPrefPossibleValuesKey(final String key) { public static String getPrefPossibleValuesKey(final String key) {
return String.format(Locale.ROOT, "%s_possible_values", 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.R;
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions; 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.XiaomiSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.services.XiaomiHealthService; import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.services.XiaomiHealthService;
import nodomain.freeyourgadget.gadgetbridge.util.CheckSums; import nodomain.freeyourgadget.gadgetbridge.util.CheckSums;
@ -43,9 +44,8 @@ public class XiaomiActivityFileFetcher {
private final XiaomiHealthService mHealthService; private final XiaomiHealthService mHealthService;
private final Queue<List<XiaomiActivityFileId>> mFetchQueue = new LinkedList<>(); private final Queue<XiaomiActivityFileId> mFetchQueue = new LinkedList<>();
private ByteArrayOutputStream mBuffer = null; private ByteArrayOutputStream mBuffer = new ByteArrayOutputStream();
private Set<XiaomiActivityFileId> pendingFiles = new HashSet<>();
private boolean isFetching = false; private boolean isFetching = false;
public XiaomiActivityFileFetcher(final XiaomiHealthService healthService) { public XiaomiActivityFileFetcher(final XiaomiHealthService healthService) {
@ -58,18 +58,11 @@ public class XiaomiActivityFileFetcher {
LOG.debug("Got activity chunk {}/{}", num, total); LOG.debug("Got activity chunk {}/{}", num, total);
if (num == 1) { mBuffer.write(chunk, 4, chunk.length - 4);
if (mBuffer == null) {
mBuffer = new ByteArrayOutputStream();
}
mBuffer.reset();
mBuffer.write(chunk, 4, chunk.length - 4);
}
if (num == total) { if (num == total) {
final byte[] data = mBuffer.toByteArray(); final byte[] data = mBuffer.toByteArray();
mBuffer.reset(); mBuffer = new ByteArrayOutputStream();
mBuffer = null;
if (data.length < 13) { if (data.length < 13) {
LOG.warn("Activity data length of {} is too short", data.length); LOG.warn("Activity data length of {} is too short", data.length);
@ -78,8 +71,15 @@ public class XiaomiActivityFileFetcher {
return; return;
} }
if (!validChecksum(data)) { final int arrCrc32 = CheckSums.getCRC32(data, 0, data.length - 4);
LOG.warn("Invalid activity data checksum"); 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 // FIXME this may mess up the order.. maybe we should just abort
triggerNextFetch(); triggerNextFetch();
return; return;
@ -104,18 +104,21 @@ public class XiaomiActivityFileFetcher {
} }
if (activityParser.parse(fileId, activityData)) { if (activityParser.parse(fileId, activityData)) {
LOG.debug("Acking recorded data {}", fileId); if (!XiaomiPreferences.keepActivityDataOnDevice(mHealthService.getSupport().getDevice())) {
//mHealthService.ackRecordedData(fileId); LOG.debug("Acking recorded data {}", fileId);
mHealthService.ackRecordedData(fileId);
}
} }
// FIXME only after receiving everything triggerNextFetch(); triggerNextFetch();
} }
} }
public void fetch(final List<XiaomiActivityFileId> fileIds) { public void fetch(final XiaomiActivityFileId fileId) {
mFetchQueue.add(fileIds); mFetchQueue.add(fileId);
if (!isFetching) { if (!isFetching) {
// Currently not fetching anything, fetch the next // Currently not fetching anything, fetch the next
isFetching = true;
final XiaomiSupport support = mHealthService.getSupport(); final XiaomiSupport support = mHealthService.getSupport();
final Context context = support.getContext(); final Context context = support.getContext();
GB.updateTransferNotification(context.getString(R.string.busy_task_fetch_activity_data),"", true, 0, context); GB.updateTransferNotification(context.getString(R.string.busy_task_fetch_activity_data),"", true, 0, context);
@ -125,21 +128,18 @@ public class XiaomiActivityFileFetcher {
} }
private void triggerNextFetch() { 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(); mHealthService.getSupport().getDevice().unsetBusyTask();
GB.updateTransferNotification(null, "", false, 100, mHealthService.getSupport().getContext()); GB.updateTransferNotification(null, "", false, 100, mHealthService.getSupport().getContext());
return; return;
} }
mHealthService.requestRecordedData(fileIds); LOG.debug("Triggering next fetch for: {}", fileId);
}
public boolean validChecksum(final byte[] arr) { mHealthService.requestRecordedData(fileId);
final int arrCrc32 = CheckSums.getCRC32(arr, 0, arr.length - 4);
final int expectedCrc32 = BLETypeConversions.toUint32(arr, arr.length - 4);
return arrCrc32 == expectedCrc32;
} }
} }

View File

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