Skip to content

Latest commit

 

History

History
91 lines (66 loc) · 3.3 KB

README.md

File metadata and controls

91 lines (66 loc) · 3.3 KB

rowing-data (Python)

Python sample

A draft Python implementation of the Rowing Data Standard.

This package implements Draft v0.1, which is not ratified. Field IDs, scales and units may still change. Do not treat this library as a stable contract for shipping products.

Scope

Implements Draft v0.1 §4 native FIT fields, §5.1 core metrics (IDs 0–9 and 19), and Session RecordingStrategy (ID 10), under application UUID 89e86158-6d47-5c98-9d46-7d29437f27b9. Producers write protocol version 1 in DeveloperDataId.application_version. A file that omits it is still read.

Stroke rate is native cadence256 (scale 256) plus cadence, rounded to the nearest integer. This library does not write developer field StrokeRate (93) or native fractional_cadence.

RecordingStrategy includes TimeSampled (3). StrokeState (ID 96) is written only for that strategy: 0 Unknown, 1 Waiting, 2 Drive, 3 Dwell, 4 Recovery.

Force is AverageDriveForce (6) and PeakDriveForce (7), in newtons. Fields 4 and 5 are not part of this sample.

SlipThreshold (94) and WashThreshold (95) are optional session fields, in newtons, written when set.

Not implemented (later work, or blocked on draft defects):

  • Oarlock summary fields 11–18
  • Dual-oarlock 200–211
  • In-stroke axis metadata 90–92, curve arrays, curve summaries, .instroke.json

WorkoutState (ID 9) uses the FIT intensity values: 0 Active, 1 Rest, 2 Warmup, 3 Cooldown, 4 Recovery, 5 Interval, 6 Other. An unknown value is read as Other. When a lap's intensity disagrees with a record, the lap wins. Every lap written here sets native intensity. A session with no laps is written as one active lap. RowingSession.moving_time_s() sums timer time over every lap except Rest, and validate warns about rowing data inside a rest lap (light rowing is Recovery).

Heart rate is the native heart_rate field. When no sensor is connected, omit it rather than write 0. cycle_length16 is the distance the boat travels in one stroke cycle, not cumulative distance and not handle travel (DriveLength).

Pre-v1.2 files: DriveLength used scale 100 / metres. This reader decodes with v0.1 units (mm) and records a field_scale warning. It does not silently convert old files into millimetres.

Developer fields are interpreted only when they use the standard application UUID.

Install

From the repository root:

pip install -e "./python[dev]"

Use Python 3.11 or later.

Example

from pathlib import Path
from rowing_data import STANDARD_VERSION, read_fit, validate, write_fit

assert STANDARD_VERSION == "0.1"
session = read_fit("workout.fit")
write_fit(session, Path("copy.fit"))
issues = validate(session)  # includes warnings captured during read_fit

Development

cd python
pytest
ruff check src tests

CI runs exactly these two commands on Python 3.11, 3.12 and 3.13 (.github/workflows/python.yml), and only when something under python/ changes. The interop test against the rowingdata golden FIT file skips on CI, since that file is not in this repository.