RecordedWorkoutSyncer is only invoked for devices where supportsActivityTracks() is true,
and all such devices also support activity tracking — so the !supportsActivityTracking
guards were always false, making addHeartRateRecord and addStepsRecord unreachable.
HR and steps are already synced by HeartRateSyncer and StepsSyncer at activity level.
SleepSyncer was inserting the same sleep session in multiple slices when
the session spanned a slice boundary. The 1-day look-back caused the
session to be re-discovered in adjacent slices, and the overlap check
allowed it to be synced in each one.
Assign each session to the slice where its start time falls
([sliceStart, sliceEnd)). This ownership rule ensures each session is
synced exactly once regardless of how many slices it overlaps with.
Add a 12-hour look-forward to the DB query for SLEEP so that sessions
starting near the slice end are fetched with their full data, preventing
truncation at the slice boundary.
Fixes: https://codeberg.org/Freeyourgadget/Gadgetbridge/issues/5873
RecordedWorkoutSyncer was writing heart rate, steps, and calorie records
that overlap with the per-minute data already synced by HeartRateSyncer,
StepsSyncer, and ActiveCaloriesSyncer in the ACTIVITY data type sync.
The supportsActiveCalories guard from 8c575535b only covered
processDetailedWorkout but not processAggregateWorkout, which is the
code path hit when no track file is available. No guards existed for
heart rate or steps in either path.
Skip workout-level aggregate HR and steps when supportsActivityTracking
(covered by ACTIVITY sync), and skip workout-level calories when
supportsActiveCalories (covered by ActiveCaloriesSyncer). Per-second HR
from detailed workout track data is always synced as it is more granular
than the per-minute activity HR.
The sync state cursor was advancing to the slice end timestamp
unconditionally, even when no records were written. Late-arriving data
(sleep, workouts, VO2Max, etc.) that arrives after the cursor has
already advanced past it would be permanently skipped.
Each syncer now reports the latest timestamp of records actually
inserted into Health Connect. The sync cursor advances to
max(currentPersisted, latestRecordTimestamp) instead of
sliceEndTimestamp. If no records were written for a slice, the cursor
stays put. This handles all late-arriving data generically without
needing per-data-type special-casing.
# laxasfit support
With reference to issue #5640 here comes the initial implementation of the first supported laxasfit device:
- Q11 smartwatch
The used protocol is a derivate of the FitPro protocol, using
- different UUIDs
- different message ID's
- additional CRC
Protocol details are documented in the related issue #5640
Reviewed-on: https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/5774
Co-authored-by: Erwin Scheuch-Heilig <fr3ts0n@gmx.at>
Co-committed-by: Erwin Scheuch-Heilig <fr3ts0n@gmx.at>