Skip to content

Commit 044afad

Browse files
committed
Add FitFileEncoder for writing FIT files
1 parent 0b1dc79 commit 044afad

10 files changed

+950
-72
lines changed

fitparse/base.py

+8-26
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
1-
import io
21
import os
32
import struct
43

5-
# Python 2 compat
6-
try:
7-
num_types = (int, float, long)
8-
str = basestring
9-
except NameError:
10-
num_types = (int, float)
11-
124
from fitparse.processors import FitFileDataProcessor
135
from fitparse.profile import FIELD_TYPE_TIMESTAMP, MESSAGE_TYPES
146
from fitparse.records import (
@@ -94,6 +86,7 @@ def _parse_file_header(self):
9486

9587
# Initialize data
9688
self._accumulators = {}
89+
self.data_size = 0
9790
self._bytes_left = -1
9891
self._complete = False
9992
self._compressed_ts_accumulator = 0
@@ -106,7 +99,7 @@ def _parse_file_header(self):
10699
raise FitHeaderError("Invalid .FIT File Header")
107100

108101
# Larger fields are explicitly little endian from SDK
109-
header_size, protocol_ver_enc, profile_ver_enc, data_size = self._read_struct('2BHI4x', data=header_data)
102+
header_size, protocol_ver_enc, profile_ver_enc, self.data_size = self._read_struct('2BHI4x', data=header_data)
110103

111104
# Decode the same way the SDK does
112105
self.protocol_version = float("%d.%d" % (protocol_ver_enc >> 4, protocol_ver_enc & ((1 << 4) - 1)))
@@ -127,7 +120,7 @@ def _parse_file_header(self):
127120
self._read(extra_header_size - 2)
128121

129122
# After we've consumed the header, set the bytes left to be read
130-
self._bytes_left = data_size
123+
self._bytes_left = self.data_size
131124

132125
def _parse_message(self):
133126
# When done, calculate the CRC and return None
@@ -239,7 +232,7 @@ def _parse_definition_message(self, header):
239232
def _parse_raw_values_from_data_message(self, def_mesg):
240233
# Go through mesg's field defs and read them
241234
raw_values = []
242-
for field_def in def_mesg.field_defs + def_mesg.dev_field_defs:
235+
for field_def in def_mesg.all_field_defs():
243236
base_type = field_def.base_type
244237
is_byte = base_type.name == 'byte'
245238
# Struct to read n base types (field def size / base type size)
@@ -280,18 +273,6 @@ def _resolve_subfield(field, def_mesg, raw_values):
280273
return sub_field, field
281274
return field, None
282275

283-
def _apply_scale_offset(self, field, raw_value):
284-
# Apply numeric transformations (scale+offset)
285-
if isinstance(raw_value, tuple):
286-
# Contains multiple values, apply transformations to all of them
287-
return tuple(self._apply_scale_offset(field, x) for x in raw_value)
288-
elif isinstance(raw_value, num_types):
289-
if field.scale:
290-
raw_value = float(raw_value) / field.scale
291-
if field.offset:
292-
raw_value = raw_value - field.offset
293-
return raw_value
294-
295276
@staticmethod
296277
def _apply_compressed_accumulation(raw_value, accumulation, num_bits):
297278
max_value = (1 << num_bits)
@@ -314,7 +295,7 @@ def _parse_data_message(self, header):
314295

315296
# TODO: Maybe refactor this and make it simpler (or at least broken
316297
# up into sub-functions)
317-
for field_def, raw_value in zip(def_mesg.field_defs + def_mesg.dev_field_defs, raw_values):
298+
for field_def, raw_value in zip(def_mesg.all_field_defs(), raw_values):
318299
field, parent_field = field_def.field, None
319300
if field:
320301
field, parent_field = self._resolve_subfield(field, def_mesg, raw_values)
@@ -335,7 +316,7 @@ def _parse_data_message(self, header):
335316

336317
# Apply scale and offset from component, not from the dynamic field
337318
# as they may differ
338-
cmp_raw_value = self._apply_scale_offset(component, cmp_raw_value)
319+
cmp_raw_value = component.apply_scale_offset(cmp_raw_value)
339320

340321
# Extract the component's dynamic field from def_mesg
341322
cmp_field = def_mesg.mesg_type.fields[component.def_num]
@@ -357,7 +338,8 @@ def _parse_data_message(self, header):
357338

358339
# TODO: Do we care about a base_type and a resolved field mismatch?
359340
# My hunch is we don't
360-
value = self._apply_scale_offset(field, field.render(raw_value))
341+
value = field.render(raw_value)
342+
value = field.apply_scale_offset(value)
361343
else:
362344
value = raw_value
363345

0 commit comments

Comments
 (0)