Skip to content

Commit

Permalink
fix crash when int too large for FIT_ENUM by using truncatingIfNecessary
Browse files Browse the repository at this point in the history
Easier access function for FitValue
Ability to annotate file with python function that generated each line
  • Loading branch information
roznet committed Feb 23, 2021
1 parent e93bdf6 commit f880f4f
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 160 deletions.
22 changes: 10 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ if let fit = FitFile(file: path ) {
var hr : [Double] = []
var ts : [Date] = []
for message in fit.messages(forMessageType: .record) {
if let one_gps = message.interpretedField(key: "position")?.fitValue,
let one_hr = message.interpretedField(key: "heart_rate")?.fitValue,
let one_ts = message.interpretedField(key: "timestamp")?.fitValue {
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 )
}
Expand Down Expand Up @@ -67,30 +67,28 @@ Alternatively you can use the convenience optional computed property to get the
```




## Approach

This code builds upon the example c code from the official SDK and integrate it into swift to generate a native object with an array of messages made of native swift dictionaries. It also adds support for developer fields.
This code builds upon the example c code from the official SDK and integrate it into swift to generate a native object with an array of messages made of native swift dictionaries. It adds support for developer fields and a `.generic` parsing mode to process any message and field not predefined in the profile.

All the keys and fields are generated from the types defined in `Profile.xlsx` from the example SDK.
When using the `.fast` parsing mode (from the sdk c example), all the keys and fields are generated from the types defined in `Profile.xlsx` from the example SDK.

There are two available approaches to parsing, determined by the `parsingType` argument in the `FitFile` constructor:

- `.fast` this method will only parse the fields defined as an example in the `Profile.xlsx` and therefore in `fit_example.h` from the sdk. This approach is the fastest as it relies on pre-defined static parsing of the fields.
- `.fast` this method will only parse the fields defined as an example in the `Profile.xlsx` and therefore matching those in `fit_example.h` from the sdk. This approach is the fastest as it relies on pre-defined static parsing of the fields.
- `.generic` this method will blindly convert all the messages found in the files, interpreting as much as possible from the information in `Profile.xlsx` as possible, but also building information from unkonwn messages and types. This approach is a bit slower as tries to interpret each fields dynamically.

All the required code is auto generated by running a python script `fitgenparser.py` that takes as input the `Profile.xlsx` from the sdk.
All the required code is auto generated by running a python script `fitsdkparser.py` that takes as input the `Profile.xlsx` from the sdk.

## Update for a new SDK

When a new SDK is available, after download, copy the new Profile.xlsx.
When a new SDK is available, after download, you can copy the new `Profile.xlsx`.

You need to then run the `fitgenparser.py` script that will automatically update the swift code for the latest version of the sdk
You need to then run the `fitsdkparser.py` script that will automatically update the swift code for the latest version of the sdk

## Why implement this Library?

The main purpose of this library was speed of parsing the fit file for the ConnectStats use case.
The main motivation to write this library was speed of parsing the fit file for the ConnectStats use case.

This library was built to replace the original cpp code from the SDK used in ConnectStats and FitFileExplorer. As ConnectStats now [receives the FIT files](https://github.com/roznet/connectstats_server) from Garmin, the files are parsed live on the phone as they are received and performance was therefore important for the user experience.

Expand Down
12 changes: 9 additions & 3 deletions Sources/FitFileParser/FitMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,18 +95,24 @@ public class FitMessage : Codable {
return rv
}

/// Returns the best swift interpretation for a specific the field in the message as a FitFieldValue
public func interpretedField(key:FitFieldKey) -> FitFieldValue? {
let interp = self.interpretedFields()

return interp[key]
}


/// Returns the best swift interpretation for a specific the field in the message as a FitValue
public func interpretedValue(key:FitFieldKey) -> FitValue? {
let interp = self.interpretedFields()
return interp[key]?.fitValue
}

/// Clear all cached value when memory need to be reclaimed. All value will then be recalculated if needed
public func purgeCache() {
self.cacheInterpretation = [:]
}

/// Returns the best swift interpreation of each of the field in the message
/// Returns the best swift interpretation of each of the field in the message
/// Some of the interpration is generic or a function of knowledge on the field, for example times or coordinates
/// the returned FitFieldValue
/// - Returns: Array of keys to FitFieldValue
Expand Down
Loading

0 comments on commit f880f4f

Please sign in to comment.