From 6a397b91194adc8c43a4b5f55bab78bd93d39132 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Rebelo?= Date: Sun, 2 Feb 2025 15:54:20 +0000 Subject: [PATCH] Zepp OS: Fix activity details parsing getting stuck --- .../fetch/FetchSportsDetailsOperation.java | 22 +++++++++++----- .../zeppos/ZeppOsActivityDetailsParser.java | 25 +++++++++++++------ 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/fetch/FetchSportsDetailsOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/fetch/FetchSportsDetailsOperation.java index f4663ffde..b8c1d7477 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/fetch/FetchSportsDetailsOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/fetch/FetchSportsDetailsOperation.java @@ -95,6 +95,20 @@ public class FetchSportsDetailsOperation extends AbstractFetchOperation { ((HuamiActivityDetailsParser) detailsParser).setSkipCounterByte(false); // is already stripped } + // Start by persisting the raw bytes right away - they can always be re-processed later if needed + try { + final String rawBytesPath = saveRawBytes(); + if (rawBytesPath != null) { + try (DBHandler dbHandler = GBApplication.acquireDB()) { + summary.setRawDetailsPath(rawBytesPath); + dbHandler.getDaoSession().getBaseActivitySummaryDao().update(summary); + } + } + } catch (final Exception e) { + GB.toast(getContext(), "Error saving raw bytes: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e); + return false; + } + try { final ActivityTrack track = detailsParser.parse(buffer.toByteArray()); final ActivityTrackExporter exporter = new GPXExporter(); @@ -123,8 +137,6 @@ public class FetchSportsDetailsOperation extends AbstractFetchOperation { break; } - final String rawBytesPath = saveRawBytes(); - final String fileName = FileUtils.makeValidFileName("gadgetbridge-" + trackType.toLowerCase() + "-" + DateTimeUtils.formatIso8601(summary.getStartTime()) + ".gpx"); final File targetFile = new File(FileUtils.getExternalFilesDir(), fileName); @@ -139,14 +151,12 @@ public class FetchSportsDetailsOperation extends AbstractFetchOperation { if (exportGpxSuccess) { summary.setGpxTrack(targetFile.getAbsolutePath()); } - if (rawBytesPath != null) { - summary.setRawDetailsPath(rawBytesPath); - } dbHandler.getDaoSession().getBaseActivitySummaryDao().update(summary); } } catch (final Exception e) { GB.toast(getContext(), "Error saving activity details: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e); - return false; + // #4549 - we do not return false here, since this might cause the same activity to be fetched over and over again + // the raw details are persisted above, we can always re-process if needed } // Always increment the sync timestamp on success, even if we did not get data diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/zeppos/ZeppOsActivityDetailsParser.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/zeppos/ZeppOsActivityDetailsParser.java index c40ccc0f0..20efe5873 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/zeppos/ZeppOsActivityDetailsParser.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/zeppos/ZeppOsActivityDetailsParser.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2022-2024 José Rebelo +/* Copyright (C) 2022-2025 José Rebelo This file is part of Gadgetbridge. @@ -77,13 +77,24 @@ public class ZeppOsActivityDetailsParser extends AbstractHuamiActivityDetailsPar // Keep track of unknown type codes so we can print them without spamming the logs final Map unknownTypeCodes = new HashMap<>(); - + while (buf.position() < buf.limit()) { - final byte typeCode = buf.get(); - final byte length = buf.get(); + byte typeCode = buf.get(); + // FIXME: This is probably not right, but type 31 makes the parser get out of sync otherwise + if (typeCode == 31) { + typeCode = buf.get(); + } + byte lengthByte = buf.get(); + if (lengthByte == -127) { + lengthByte = buf.get(); + } + final int length = lengthByte & 0xff; final int initialPosition = buf.position(); final Type type = Type.fromCode(typeCode); + + //trace("Read typeCode={}, type={}, length={}, initialPosition={}", typeCode, type, length, initialPosition); + if (type == null) { if (!unknownTypeCodes.containsKey(typeCode)) { unknownTypeCodes.put(typeCode, 0); @@ -181,7 +192,7 @@ public class ZeppOsActivityDetailsParser extends AbstractHuamiActivityDetailsPar consumeTimestampOffset(buf); final short longitudeDelta = buf.getShort(); final short latitudeDelta = buf.getShort(); - buf.getShort(); // ? seems to always be 2 + final short two = buf.getShort(); // ? seems to always be 2 this.longitude += longitudeDelta; this.latitude += latitudeDelta; @@ -194,7 +205,7 @@ public class ZeppOsActivityDetailsParser extends AbstractHuamiActivityDetailsPar addNewGpsCoordinates(); - //trace("Consumed GPS delta: {} {}", longitudeDelta, latitudeDelta); + //trace("Consumed GPS delta: {} {} {}", longitudeDelta, latitudeDelta, two); } private void consumeStatus(final ByteBuffer buf) { @@ -236,7 +247,7 @@ public class ZeppOsActivityDetailsParser extends AbstractHuamiActivityDetailsPar // TODO integrate into gpx - //trace("Consumed speed: cadence={}, stride={}, ?={}", cadence, stride, ); + //trace("Consumed speed: cadence={}, stride={}, pace={}", cadence, stride, pace); } private void consumeAltitude(final ByteBuffer buf) {