feat(train): a workout out as GPX, TCX or FIT (ADR 0030, D49)

11b: Export on a workout's page hands it to the share sheet as GPX (with
a track only; heart rate and cadence in Garmin's TrackPointExtension),
TCX (laps, heart rate, cadence, watts, a row's distance) or FIT (file
ID, records, timer events at the pauses, laps with their intensities,
session, activity), all from the same points: the precise fixes while
moving, else the rower's frames, else the heart rates; a plan's steps
are the laps. The FIT writer is our own (protocol 1.0, CRC-16/ARC),
tested by a reader written from the specification.

Not tried yet with Strava, intervals.icu or Garmin Connect.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-29 14:37:48 +01:00
commit 128ba1f6c8
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -1137,6 +1137,23 @@ Strava. What was found, 27 Oct:
for every activity until switched on (`announce.json`, `AnnounceStore`, never
synced). Not tried on a phone yet: how it sounds over music, eSpeak's and
RHVoice's reading of the German sentences.
- Built: 11b. *Export* on a workout's page (where the device hands files on) offers
GPX (only with a track), TCX and FIT, and hands the file to the share sheet (saved
where the person chooses on the desktop), named `halkyon-train-` and when it
started in UTC. Each is written from the same points (`workout_export.dart`): the
precise fixes while moving as the saved distance counts them, else the rower's
frames, else the heart rates; with the heart rate of the last 5 s and the cadence
of the window the point falls in, on foot in strides (half the steps, as Garmin's
devices write a run's cadence), a row's strokes, its watts; a plan's steps are the
laps (recovery *Resting* in TCX, FIT's intensities for warm-up and cool-down), else
one lap. GPX has a segment each piece between pauses; TCX writes the schema's order;
FIT (`fit_encoder.dart`, protocol 1.0, little-endian, profile 21.00, CRC-16/ARC) the
file ID as a development manufacturer's, the timer's start, stops and starts at
the pauses, a record each point (semicircles, centimetres), a lap each, the session
(a row as rowing indoors) and the activity. Tested by reading the files back: the
XML parsed, the FIT by a reader written from the specification in the tests
(`test/support/fit_reader.dart`), not by Garmin's SDK. Not tried yet: an upload to
Strava, intervals.icu or Garmin Connect.
## Consequences