Skip to content

Commit 335fa39

Browse files
committed
Break up parsing and writing to file, typehints, clarifying variable names
1 parent 192b636 commit 335fa39

1 file changed

Lines changed: 40 additions & 24 deletions

File tree

fit_to_csv.py

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
import glob
44
import os
55
from datetime import timezone
6+
from typing import Any
67
from zoneinfo import ZoneInfo
78

89
import fitparse
910

10-
allowed_fields = [
11+
FIELDS_ALLOWED = [
1112
"timestamp",
1213
"position_lat",
1314
"position_long",
@@ -21,43 +22,57 @@
2122
"cadence",
2223
"fractional_cadence",
2324
]
24-
required_fields = ["timestamp", "position_lat", "position_long"]
25+
FIELDS_REQUIRED = ["timestamp", "position_lat", "position_long"]
2526

2627
UTC = timezone.utc
2728
TZ = ZoneInfo("US/Central")
2829

2930

30-
def write_fitfile_to_csv(fitfile, output_path: str, tz: ZoneInfo = TZ):
31-
messages = fitfile.messages
31+
def write_to_csv(data: list[dict[str, Any]], output_path: str) -> None:
32+
# write to csv
33+
with open(output_path, "w") as f:
34+
writer = csv.writer(f)
35+
writer.writerow(FIELDS_ALLOWED)
36+
for entry in data:
37+
writer.writerow([str(entry.get(k, "")) for k in FIELDS_ALLOWED])
38+
print("wrote %s" % output_path)
39+
40+
41+
def collect_data(filepath: str, tz: ZoneInfo = TZ) -> list[dict[str, Any]]:
42+
# Parse the .fit file
43+
fitfile = fitparse.FitFile(
44+
filepath, data_processor=fitparse.StandardUnitsDataProcessor()
45+
)
46+
3247
data = []
48+
messages = fitfile.messages
49+
3350
for m in messages:
3451
skip = False
3552
if not hasattr(m, "fields"):
3653
continue
3754
fields = m.fields
38-
# check for important data types
55+
56+
# check for desired data and collect it
3957
mdata = {}
4058
for field in fields:
41-
if field.name in allowed_fields:
59+
if field.name in FIELDS_ALLOWED:
4260
if field.name == "timestamp":
43-
ts_value = field.value
44-
if ts_value.tzinfo is None:
45-
ts_value = ts_value.replace(tzinfo=UTC)
46-
mdata[field.name] = ts_value.astimezone(tz)
61+
timestamp_value = field.value
62+
if timestamp_value.tzinfo is None:
63+
timestamp_value = timestamp_value.replace(tzinfo=UTC)
64+
mdata[field.name] = timestamp_value.astimezone(tz)
4765
else:
4866
mdata[field.name] = field.value
49-
for rf in required_fields:
50-
if rf not in mdata:
67+
68+
for required_field in FIELDS_REQUIRED:
69+
if required_field not in mdata:
5170
skip = True
71+
5272
if not skip:
5373
data.append(mdata)
54-
# write to csv
55-
with open(output_path, "w") as f:
56-
writer = csv.writer(f)
57-
writer.writerow(allowed_fields)
58-
for entry in data:
59-
writer.writerow([str(entry.get(k, "")) for k in allowed_fields])
60-
print("wrote %s" % output_path)
74+
75+
return data
6176

6277

6378
def parse_args() -> argparse.Namespace:
@@ -86,19 +101,20 @@ def parse_args() -> argparse.Namespace:
86101
def main():
87102
args = parse_args()
88103

104+
# Identify .fit files
89105
fit_files = glob.glob(args.dir + "/*.fit")
106+
90107
for file in fit_files:
108+
# Use the same filename, just change extension to .csv
91109
base_filename = file.removesuffix(".fit")
92110
new_filename = base_filename + ".csv"
93111
if not args.overwrite and os.path.exists(new_filename):
94-
# print('%s already exists. skipping.' % new_filename)
95112
continue
96-
fitfile = fitparse.FitFile(
97-
file, data_processor=fitparse.StandardUnitsDataProcessor()
98-
)
99113

100114
print("converting %s" % file)
101-
write_fitfile_to_csv(fitfile, new_filename, tz=ZoneInfo(args.timezone))
115+
data = collect_data(file, tz=ZoneInfo(args.timezone))
116+
write_to_csv(data, new_filename)
117+
102118
print("finished conversions")
103119

104120

0 commit comments

Comments
 (0)