Swift 适用的 Fit 文件解析 Actions Status

此代码提供了一个 Swift 包,用于解析 Garmin 设备和其他健身设备通常生成的 Fit 文件格式。

它使用了官方的 Fit SDK

您可以在 fit-sdk-swift 中查看一些在 iOS 和 macOS 上如何使用它的示例。

此包也完全集成到开源且已发布的 MacOS 和 iOS 应用 FitFileExplorer 和 ConnectStats 中。

开源应用 FitFileExplorer 使用了这个库,在处理包时,它对于探索 fit 文件的结构尤其有用。

如何安装

从 Xcode 项目中使用它相当简单,遵循标准的 添加 Swift 包 的方法。

如何使用

Fit 文件使用 let fitfile = FitFile(file: URL)let fitfile = FitFile(data : Data) 加载。

然后,您可以使用访问函数,例如 fitfile.messages(forMessageType: FitMessageType.session) 来获取 FitMessage 类型的对象。

类型 FitMessageType 代表消息类型(SDK 中的 mesg_num)。您可以使用类似 FitMessageType.recordFitMessageType.sessionFitMessageType.sport 等语法访问所有已知的消息。

函数 message.interpretedFields() 提供对消息字段的访问,它是一个键到 FitFieldValue 的字典。FitFieldValue 可以是日期、字符串、双精度值、带有单位的双精度值或 GPS 坐标。

这是一个完整的示例

if let fit = FitFile(file: path ) {
    var gps : [CLLocationCoordinate2D] = []
    var hr  : [Double] = []
    var ts  : [Date]   = []
    for message in fit.messages(forMessageType: .record) {
        if let one_gps = message.interpretedValue(key: "position"),
           let one_hr  = message.interpretedValue(key: "heart_rate"),
           let one_ts  = message.interpretedValue(key: "timestamp") {
            if case let FitValue.coordinate(coord) = one_gps {
                gps.append( coord )
            }
            if case let FitValue.time(date) = one_ts {
                ts.append( date )
            }
            if case let FitValue.valueUnit(d , _) = one_hr {
                hr.append( d )
            }
        }
    }
}

或者,如果更方便,您可以使用便捷的可选计算属性来获取值。

//...
 if let one_gps = message.interpretedField(key: "position")?.coordinate,
    let one_hr  = message.interpretedField(key: "heart_rate")?.valueUnit?.value,
    let one_ts  = message.interpretedField(key: "timestamp")?.time {
     gps.append( one_gps )
     ts.append( one_ts)
     hr.append( one_hr )
}
//...

方法

此代码构建在官方 SDK 中的示例 C 代码之上,并将其集成到 Swift 中,以生成一个包含由本机 Swift 字典组成的消息数组的本机对象。它增加了对开发者字段的支持以及 .generic 解析模式,用于处理配置文件中未预定义的任何消息和字段。

当使用 .fast 解析模式(来自 SDK C 示例)时,所有键和字段都是从示例 SDK 中 Profile.xlsx 定义的类型生成的。

有两种可用的解析方法,由 FitFile 构造函数中的 parsingType 参数确定。

所有需要的代码都通过运行 Python 脚本 fitsdkparser.py 自动生成,该脚本将 SDK 中的 Profile.xlsx 作为输入。

更新为新的 SDK

当有新的 SDK 可用时,下载后,您可以将新的 Profile.xlsx 复制到 python 目录中,并使用使用的版本编辑文件 fitsdkversion.txt

然后,您需要运行 fitsdkparser.py 脚本,该脚本将自动更新 Swift 代码以使用最新版本的 SDK。

为什么要实现这个库?

编写这个库的主要动机是为了 ConnectStats 用例提高 fit 文件的解析速度。

构建此库是为了替换 ConnectStats 和 FitFileExplorer 中使用的 SDK 中的原始 cpp 代码。由于 ConnectStats 现在从 Garmin 接收 FIT 文件,因此文件在接收时在手机上实时解析,因此性能对于用户体验非常重要。

cpp 解析最终非常缓慢,并且使得在 ConnectStats 或 FitFileExplorer 上解析 fit 文件非常缓慢。这种 C/Swift 方法要快得多。

您可以查看 该库与其他几个库的基准测试