从码表 FIT 文件到跨端工具:FitTool 的开发过程
从码表 FIT 文件到跨端工具:FitTool 的开发过程
最近把一个折腾了挺久的小工具开源了——FitTool。它做的事情很单纯:读取 Garmin / 码表导出的 .fit 活动文件,把心率、速度、功率等曲线画出来,再按时间截一段,导出成仍然合法的 FIT(以及 CSV / JSON)。
仓库地址:https://gitee.com/daizhizhou/fit-tool
这篇文章不打算写成「功能清单」,而是顺着开发过程,把踩过的坑和几次路线切换记下来。
为什么要做它
码表骑完一趟,.fit 文件里往往混着热身、等红灯、收工慢骑。想只留中间一段高质量数据时,常见做法是:
- 丢到第三方网页工具里裁,但数据要上传,也不好批量改;
- 用 Garmin 官方 JAR(
FitCSVTool等)命令行处理,能用,但对日常「打开 → 看图 → 拖一下 → 导出」太重; - 手机里想快速截一段,更缺顺手的本地工具。
所以目标很明确:本地、可视化、可截取、导出仍是合法 FIT,并尽量覆盖 Windows 和 Android。
第一版:Python + CustomTkinter
最早落地在 Python:
- 解析用官方 garmin-fit-sdk;
- GUI 用 CustomTkinter;
- 需要 CSV / 修复时,再调官方 fit-sdk-tools 里的 JAR。
这条路验证了核心链路是否跑得通:
- 解码 Activity / Record / Lap / Session;
- 画曲线并选时间窗;
- 截取后重算汇总再写回 FIT。
作为原型很快,但打包体积、启动速度、以及 Windows 上「装个小工具却要拖一整套 Python 环境」的体验一般。于是有了第二站。
第二版:WPF + .NET 8
Windows 正式版改成了 WPF:
- 解析:
Garmin.FIT.Sdk(与官方生态对齐); - 图表:OxyPlot;
- 发布:依赖框架版大约 1.6 MB,也可以打自包含单文件。
这一阶段主要在打磨「用起来像个正经桌面软件」:
- 滚动条、下拉框等控件在深色/浅色主题下的可读性;
- 图表操作区按钮布局;
- 统一按 UTC+8 显示时间(FIT 内部多是 UTC,直接展示很容易「晚了八小时」);
- 厂商 / 产品号映射成可读设备名(否则摘要里全是数字 ID);
- 导出格式对齐:FIT / CSV / JSON,而不只是一个二进制片段。
截取逻辑的关键点不在「删几条 Record」,而在:Lap、Session、Activity 的汇总字段要跟着时间窗重算,否则下游软件打开会显示时长、距离对不上。
Android:同一能力搬到手机
Android 侧用官方 Java SDK com.garmin:fit,能力对齐 PC:打开、摘要、曲线、截取、导出。
移动端额外折腾了不少「看起来很小、用起来很烦」的问题:
多语言与主题
默认中文,并补了 English / Русский / Español / 日本語 / 한국어 / Français / Italiano。主题支持自动(按本地时间切换浅/深)、浅色、深色。
输入法遮挡
时间范围输入框在键盘弹出时经常被盖住。最终靠 adjustResize + WindowInsets 处理,让 NestedScrollView 能把焦点滚到可见区域。
图表手势
手机上不能只靠桌面那套鼠标拖拽。ChartView 补了双指缩放、平移、轴交互和取点,才比较接近「在车上随手看一眼」的预期。
时间与设备名
与 PC 一样:展示用 UTC+8;厂商/产品枚举通过映射表翻成可读名称,避免摘要页一堆冷冰冰的 ID。
Debug APK 大约 6MB,仓库根目录有 FitTool-android-debug.apk,也可以在 android/ 用 Android Studio / Gradle 自行构建。
导出:不只是「另存为」
早期导出一度走过弯路(例如先落成中间二进制再转换)。后来两端都收束到明确格式:
| 格式 | 用途 |
|---|---|
| FIT | 继续给码表 / Garmin Connect / 分析软件用 |
| CSV | 表格、脚本、快速核对字段 |
| JSON | 调试结构、对接其它工具 |
PC 侧需要时仍可借助官方 FitCSVTool.jar、ActivityRepairTool.jar;Android 侧在应用内完成同源能力的导出路径。原则是:用户选什么格式,就得到什么格式,中间过程尽量不可见。
开源与协作方式
代码放在 Gitee 公开仓库:daizhizhou/fit-tool。README 里写了 Windows(WPF / Python)和 Android 的运行、构建方式。
开发过程本身也很「工具化」:需求从真实使用里冒出来(时区、设备名、键盘遮挡、图表缩放……),改一点、跑一遍、再推一版。没有追求大而全的训练平台,只把「读 FIT → 看懂 → 裁一段 → 还能用」这条链走稳。
现阶段能做什么、不做什么
能做的:
- 打开常见 Activity FIT;
- 看摘要与多指标曲线;
- 按时间截取并导出合法 FIT / CSV / JSON;
- Windows 与 Android 两端覆盖日常场景。
刻意没做的:
- 不做账号体系、不做云同步;
- 不做完整训练计划 / 社交;
- 不对所有冷门 Message 类型做可视化(优先保障裁剪后的文件仍可用)。
一点体会
- 官方 SDK 值得跟:FIT 细节多,自己「猜结构」迟早翻车;跟 Garmin 官方 SDK / Tools 走,导出兼容性会好很多。
- 原型语言 ≠ 交付语言:Python 适合把业务跑通;Windows 上最终体验更吃原生 UI 与体积。
- 跨端不是复制粘贴:同一业务在手机上会变成 IME、手势、主题、多语言问题——这些往往比解析本身更耗时间。
- 时间与单位是隐藏大坑:UTC 与本地时区、厂商产品号与显示名,不处理就会让「明明解析对了」的工具看起来很假。
如果你也有码表 FIT 要本地裁剪,欢迎去仓库试试看;有问题或想法,直接在 Gitee 提 Issue 就行。
FitTool · 本地 FIT 查看与截取 · Gitee

浙公网安备 33010602011771号