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:
parent
d66de2f94f
commit
d35bcef406
@ -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]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user