Migrate from fitdecode¶
fitdecode is a clean frame-oriented reader, and its frame model maps almost one-to-one onto chiptime's lower layers — then chiptime's semantic layer covers the interpretation code you'd otherwise write on top.
API mapping¶
| fitdecode | chiptime |
|---|---|
FitReader("a.fit") + iterate frames |
chiptime.iter_frames("a.fit") (wire) or iter_messages (decoded) |
frame.frame_type == FIT_FRAME_DATA |
messages from iter_messages are the data frames |
frame.name == "record" |
msg.name == "record" |
frame.get_value("hr", fallback=None) |
msg.get("hr") (absent → None) |
frame.get_field("hr").units |
msg.fields["hr"].units |
FitReader(..., check_crc=CrcCheck.WARN) |
default lenient (CRC triaged + reported) |
except FitHeaderError / FitEOFError: |
result.errors / result.ok; strict mode raises coded errors |
| your session/stream assembly code | result.activity.sessions[*] — already assembled, tested |
Before / after¶
fitdecode
import fitdecode
power = []
with fitdecode.FitReader("ride.fit") as fit:
for frame in fit:
if frame.frame_type == fitdecode.FIT_FRAME_DATA and frame.name == "record":
v = frame.get_value("power", fallback=None)
if v is not None:
power.append(v)
chiptime
import chiptime
result = chiptime.parse("ride.fit")
power = result.activity.sessions[0].records.stream("power")
# power.values: 0 W is coasting (real), None is dropout (absent) — kept distinct
What you can delete after migrating¶
- Wrapper detection (gzip/zip) — chiptime unwraps and records it in
source.unwrapped. - Sentinel guards — invalid values are
Nonebefore you ever see them. - Session/lap/stream assembly, timer math, gap handling — the semantic layer
ships them, with the edge cases (compressed timestamps,
timestamp_16rollover, HR expansion) already handled.