fit_parser 0.0.8 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/bindata/dsl_field_validator.rb +28 -0
- data/lib/fit_parser/file/data.rb +54 -2
- data/lib/fit_parser/file/definition.rb +103 -0
- data/lib/fit_parser/file/definitions.rb +95 -1
- data/lib/fit_parser/file/record.rb +8 -3
- data/lib/fit_parser/file/record_header.rb +2 -1
- data/lib/fit_parser/file/types.rb +651 -9
- data/lib/fit_parser/file.rb +7 -1
- data/lib/fit_parser/version.rb +1 -1
- data/lib/fit_parser.rb +1 -0
- data/spec/file/data_spec.rb +4 -3
- data/spec/file/record_spec.rb +5 -5
- data/spec/fit_parser_spec.rb +26 -0
- data/spec/support/examples/1375670253.fit +0 -0
- data/spec/support/examples/1379311720.fit +0 -0
- data/spec/support/examples/1426768070-2.fit +0 -0
- data/spec/support/examples/6AUI5200.FIT +0 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c5a9b2aa672b5b76113b211fe1cb1f9ee699abd2
|
4
|
+
data.tar.gz: 71dc6534e61ca9a129f05f508973c4cbc78880da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ebd8c2da5930fc9bbd21d3110c6575f2e4e18fdbe030b548ee589d02a5073872bb736770fb460c1ad5f56507f4e76c879f44f71d639362f88816f2b57a38250
|
7
|
+
data.tar.gz: e51a26600a8bbefab0550e85a8507fa31224cdc78b2c0b58770313e7235f15e3d3df3917ad37aad9ff2744056d6060e459b1406fc588ca3b599546d11aea1557
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Override DSLFieldValidator#ensure_valid_name from bindata/lib/dsl.rb
|
2
|
+
# gem bindata
|
3
|
+
# because we should not raise error on duplicate name
|
4
|
+
module BinData
|
5
|
+
module DSLMixin
|
6
|
+
class DSLFieldValidator
|
7
|
+
def ensure_valid_name(name)
|
8
|
+
if name and not option?(:fieldnames_are_values)
|
9
|
+
if malformed_name?(name)
|
10
|
+
raise NameError.new("", name), "field '#{name}' is an illegal fieldname"
|
11
|
+
end
|
12
|
+
|
13
|
+
if duplicate_name?(name)
|
14
|
+
# raise SyntaxError, "duplicate field '#{name}'"
|
15
|
+
end
|
16
|
+
|
17
|
+
if name_shadows_method?(name)
|
18
|
+
raise NameError.new("", name), "field '#{name}' shadows an existing method"
|
19
|
+
end
|
20
|
+
|
21
|
+
if name_is_reserved?(name)
|
22
|
+
raise NameError.new("", name), "field '#{name}' is a reserved name"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/fit_parser/file/data.rb
CHANGED
@@ -2,13 +2,15 @@ module FitParser
|
|
2
2
|
class File
|
3
3
|
class Data < BinData::Record
|
4
4
|
class_attribute :global_message_number, instance_writer: false
|
5
|
+
class_attribute :dev_definitions, instance_writer: false
|
5
6
|
|
6
|
-
def self.generate(definition)
|
7
|
+
def self.generate(definition, dev_definitions = nil)
|
7
8
|
msg_num = definition.global_message_number.snapshot
|
8
9
|
type = Definitions.get_name(msg_num) || "data_record_#{msg_num}"
|
9
10
|
|
10
11
|
Class.new(self) do
|
11
12
|
self.global_message_number = msg_num
|
13
|
+
self.dev_definitions = dev_definitions
|
12
14
|
|
13
15
|
endian definition.endianness
|
14
16
|
|
@@ -36,7 +38,57 @@ module FitParser
|
|
36
38
|
code << "def #{field.name}\n"
|
37
39
|
|
38
40
|
if field.scale && field.scale != 1
|
39
|
-
|
41
|
+
scale = field.scale
|
42
|
+
if scale.is_a?(Integer)
|
43
|
+
code << "scale = #{scale.inspect}.0\n"
|
44
|
+
else
|
45
|
+
code << "scale = #{scale.inspect}\n"
|
46
|
+
end
|
47
|
+
else
|
48
|
+
code << "scale = nil\n"
|
49
|
+
end
|
50
|
+
|
51
|
+
if field.dyn_data
|
52
|
+
code << "dyn = #{field.dyn_data}\n"
|
53
|
+
else
|
54
|
+
code << "dyn = nil\n"
|
55
|
+
end
|
56
|
+
code << <<-RUBY
|
57
|
+
get_value #{field.raw_name}.snapshot, '#{field.real_type}', scale, dyn
|
58
|
+
end
|
59
|
+
RUBY
|
60
|
+
|
61
|
+
class_eval code, __FILE__, __LINE__ + 1
|
62
|
+
end
|
63
|
+
|
64
|
+
definition.dev_fields_arr.each do |field|
|
65
|
+
data = dev_definitions[field[:developer_data_index].to_s][field[:field_number].to_s]
|
66
|
+
field.base_type_number = data[:raw_field_2]
|
67
|
+
field.name = data[:raw_field_3].downcase.gsub(' ', '_')
|
68
|
+
field.scale = data[:raw_field_6] && data[:raw_field_6] != 255 ? data[:raw_field_6] : nil
|
69
|
+
code = ''
|
70
|
+
|
71
|
+
# in case the field size is a multiple of the field length, we must build an array
|
72
|
+
if field.type != 'string' && field.field_size > field.length
|
73
|
+
code << "array :#{field.raw_name}, :type => :#{field.type}, :initial_length => #{field.field_size/field.length}\n"
|
74
|
+
else
|
75
|
+
# string are not null terminated when they have exactly the lenght of the field
|
76
|
+
code << "#{field.type} :#{field.raw_name}"
|
77
|
+
if field.type == 'string'
|
78
|
+
code << ", :read_length => #{field.field_size}, :trim_padding => true"
|
79
|
+
end
|
80
|
+
code << "\n"
|
81
|
+
end
|
82
|
+
|
83
|
+
code << "def #{field.name}\n"
|
84
|
+
|
85
|
+
if field.scale && field.scale != 1
|
86
|
+
scale = field.scale
|
87
|
+
if scale.is_a?(Integer)
|
88
|
+
code << "scale = #{scale.inspect}.0\n"
|
89
|
+
else
|
90
|
+
code << "scale = #{scale.inspect}\n"
|
91
|
+
end
|
40
92
|
else
|
41
93
|
code << "scale = nil\n"
|
42
94
|
end
|
@@ -1,6 +1,82 @@
|
|
1
1
|
module FitParser
|
2
2
|
class File
|
3
3
|
class Definition < BinData::Record
|
4
|
+
class DevField < BinData::Record
|
5
|
+
uint8 :field_number
|
6
|
+
uint8 :field_size
|
7
|
+
uint8 :developer_data_index
|
8
|
+
|
9
|
+
attr_accessor :base_type_number, :name, :scale
|
10
|
+
|
11
|
+
def raw_name
|
12
|
+
"raw_#{name}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def dyn_data
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def type
|
20
|
+
case base_type_number
|
21
|
+
when 0 # enum
|
22
|
+
build_int_type 8, false
|
23
|
+
when 1 # sint8
|
24
|
+
build_int_type 8, true
|
25
|
+
when 2 # uint8
|
26
|
+
build_int_type 8, false
|
27
|
+
when 131 # sint16
|
28
|
+
build_int_type 16, true
|
29
|
+
when 132 # uint16
|
30
|
+
build_int_type 16, false
|
31
|
+
when 133 # sint32
|
32
|
+
build_int_type 32, true
|
33
|
+
when 134 # uint32
|
34
|
+
build_int_type 32, false
|
35
|
+
when 7 # string
|
36
|
+
# some cases found where string has the max field length
|
37
|
+
# and is therefore not null terminated
|
38
|
+
@length = 1
|
39
|
+
'string'
|
40
|
+
when 136 # float32
|
41
|
+
@length = 4
|
42
|
+
'float'
|
43
|
+
when 137 # float64
|
44
|
+
@length = 8
|
45
|
+
'double'
|
46
|
+
when 10 # uint8z
|
47
|
+
build_int_type 8, false
|
48
|
+
when 139 # uint16z
|
49
|
+
build_int_type 16, false
|
50
|
+
when 140 # uint32z
|
51
|
+
build_int_type 32, false
|
52
|
+
when 13 # array of bytes
|
53
|
+
build_int_type 8, false
|
54
|
+
when 142 # sint64
|
55
|
+
build_int_type 64, true
|
56
|
+
when 143 # uint64
|
57
|
+
build_int_type 64, false
|
58
|
+
when 144 # uint64z
|
59
|
+
build_int_type 64, false
|
60
|
+
else
|
61
|
+
fail "Can't map base_type_number #{base_type_number} to a data type"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
alias :real_type :type
|
65
|
+
|
66
|
+
# return the length in byte of the given type
|
67
|
+
def length
|
68
|
+
@length
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def build_int_type(length, signed)
|
74
|
+
# @length is in byte not in bits, so divide by 8
|
75
|
+
@length = length / 8
|
76
|
+
(signed ? '' : 'u') << 'int' << length.to_s
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
4
80
|
class Field < BinData::Record
|
5
81
|
hide :reserved_bits
|
6
82
|
|
@@ -72,6 +148,12 @@ module FitParser
|
|
72
148
|
build_int_type 32, false
|
73
149
|
when 13 # array of bytes
|
74
150
|
build_int_type 8, false
|
151
|
+
when 14 # sint64
|
152
|
+
build_int_type 64, true
|
153
|
+
when 15 # uint64
|
154
|
+
build_int_type 64, false
|
155
|
+
when 16 # uint64z
|
156
|
+
build_int_type 64, false
|
75
157
|
else
|
76
158
|
fail "Can't map base_type_number #{base_type_number} to a data type"
|
77
159
|
end
|
@@ -104,6 +186,21 @@ module FitParser
|
|
104
186
|
end
|
105
187
|
bit8 :field_count
|
106
188
|
array :fields_arr, type: Field, initial_length: :field_count
|
189
|
+
bit8 :dev_field_count, :onlyif => :dev_data_flag?
|
190
|
+
array :dev_fields_arr, type: DevField, initial_length: :dev_field_count, :onlyif => :dev_data_flag?
|
191
|
+
|
192
|
+
def self.attributes
|
193
|
+
@attributes ||= Hash.new { |h, k| h[k] = {} }
|
194
|
+
end
|
195
|
+
|
196
|
+
def self.attributes=(val)
|
197
|
+
@attributes = val
|
198
|
+
end
|
199
|
+
|
200
|
+
def self.read(io, attrs = {})
|
201
|
+
self.attributes = attrs
|
202
|
+
super(io)
|
203
|
+
end
|
107
204
|
|
108
205
|
def endianness
|
109
206
|
architecture.snapshot == 0 ? :little : :big
|
@@ -112,6 +209,12 @@ module FitParser
|
|
112
209
|
def record_type
|
113
210
|
:definition
|
114
211
|
end
|
212
|
+
|
213
|
+
def dev_data_flag?
|
214
|
+
dev_data_flag = Definition.attributes[:dev_data_flag]
|
215
|
+
return true if dev_data_flag && dev_data_flag == 1
|
216
|
+
false
|
217
|
+
end
|
115
218
|
end
|
116
219
|
end
|
117
220
|
end
|
@@ -70,6 +70,7 @@ FitParser::File::Definitions.add_field(0, 2, 'garmin_product', type: :garmin_pro
|
|
70
70
|
FitParser::File::Definitions.add_field(0, 3, 'serial_number', type: :uint32z)
|
71
71
|
FitParser::File::Definitions.add_field(0, 4, 'time_created', type: :date_time)
|
72
72
|
FitParser::File::Definitions.add_field(0, 5, 'number', type: :uint16)
|
73
|
+
FitParser::File::Definitions.add_field(0, 8, 'product_number', type: :string)
|
73
74
|
|
74
75
|
FitParser::File::Definitions.add_name(49, 'file_creator')
|
75
76
|
FitParser::File::Definitions.add_field(49, 0, 'software_version', type: :uint16)
|
@@ -119,7 +120,26 @@ FitParser::File::Definitions.add_field 39, 3, 'count', type: :uint16
|
|
119
120
|
FitParser::File::Definitions.add_name 2, 'device_settings'
|
120
121
|
FitParser::File::Definitions.add_field 2, 0, 'active_time_zone', type: :uint8, scale: 1
|
121
122
|
FitParser::File::Definitions.add_field 2, 1, 'utc_offset', type: :uint32
|
123
|
+
FitParser::File::Definitions.add_field 2, 2, 'time_offset', type: :uint32
|
124
|
+
FitParser::File::Definitions.add_field 2, 4, 'time_mode', type: :type_mode
|
122
125
|
FitParser::File::Definitions.add_field 2, 5, 'time_zone_offset', type: :sint8, scale: 4, unit: 'hr'
|
126
|
+
FitParser::File::Definitions.add_field 2, 12, 'backlight_mode', type: :backlight_mode
|
127
|
+
FitParser::File::Definitions.add_field 2, 36, 'activity_tracker_enabled', type: :bool
|
128
|
+
FitParser::File::Definitions.add_field 2, 39, 'clock_time', type: :date_time
|
129
|
+
FitParser::File::Definitions.add_field 2, 40, 'pages_enabled', type: :uint16
|
130
|
+
FitParser::File::Definitions.add_field 2, 46, 'move_alert_enabled', type: :bool
|
131
|
+
FitParser::File::Definitions.add_field 2, 47, 'date_mode', type: :date_mode
|
132
|
+
FitParser::File::Definitions.add_field 2, 55, 'display_orientation', type: :display_orientation
|
133
|
+
FitParser::File::Definitions.add_field 2, 56, 'mounting_side', type: :side
|
134
|
+
FitParser::File::Definitions.add_field 2, 57, 'default_page', type: :uint16
|
135
|
+
FitParser::File::Definitions.add_field 2, 58, 'autosync_min_steps', type: :uint16
|
136
|
+
FitParser::File::Definitions.add_field 2, 59, 'autosync_min_time', type: :uint16
|
137
|
+
FitParser::File::Definitions.add_field 2, 80, 'lactate_threshold_autodetect_enabled', type: :bool
|
138
|
+
FitParser::File::Definitions.add_field 2, 86, 'ble_auto_upload_enabled', type: :bool
|
139
|
+
FitParser::File::Definitions.add_field 2, 89, 'auto_sync_frequency', type: :auto_sync_frequency
|
140
|
+
FitParser::File::Definitions.add_field 2, 90, 'auto_activity_detect', type: :auto_activity_detect
|
141
|
+
FitParser::File::Definitions.add_field 2, 94, 'number_of_screens', type: :uint8
|
142
|
+
FitParser::File::Definitions.add_field 2, 95, 'smart_notification_display_orientation', type: :display_orientation
|
123
143
|
|
124
144
|
FitParser::File::Definitions.add_name 3, 'user_profile'
|
125
145
|
FitParser::File::Definitions.add_field 3, 254, 'message_index', type: :message_index
|
@@ -145,6 +165,8 @@ FitParser::File::Definitions.add_field 3, 21, 'temperature_setting', type: :disp
|
|
145
165
|
FitParser::File::Definitions.add_field 3, 22, 'local_id', type: :user_local_id
|
146
166
|
FitParser::File::Definitions.add_field 3, 23, 'global_id', type: :byte
|
147
167
|
FitParser::File::Definitions.add_field 3, 30, 'height_setting', type: :display_measure
|
168
|
+
FitParser::File::Definitions.add_field 3, 31, 'user_running_step_length', type: :uint16, scale: 1000, unit: 'm'
|
169
|
+
FitParser::File::Definitions.add_field 3, 32, 'user_walking_step_length', type: :uint16, scale: 1000, unit: 'm'
|
148
170
|
|
149
171
|
FitParser::File::Definitions.add_name 4, 'hrm_profile'
|
150
172
|
FitParser::File::Definitions.add_field 4, 254, 'message_index', type: :message_index, scale: 1
|
@@ -195,6 +217,7 @@ FitParser::File::Definitions.add_field 6, 38, 'front_gear_num', type: :uint8z
|
|
195
217
|
FitParser::File::Definitions.add_field 6, 39, 'front_gear', type: :uint8z
|
196
218
|
FitParser::File::Definitions.add_field 6, 40, 'rear_gear_num', type: :uint8z
|
197
219
|
FitParser::File::Definitions.add_field 6, 41, 'rear_gear', type: :uint8z
|
220
|
+
FitParser::File::Definitions.add_field 6, 44, 'shimano_di2_enabled', type: :bool
|
198
221
|
|
199
222
|
FitParser::File::Definitions.add_name 7, 'zones_target'
|
200
223
|
FitParser::File::Definitions.add_field 7, 1, 'max_heart_rate', type: :uint8, scale: 1
|
@@ -247,6 +270,7 @@ FitParser::File::Definitions.add_field 15, 7, 'target_value', type: :uint32, sca
|
|
247
270
|
FitParser::File::Definitions.add_field 15, 8, 'recurrence', type: :goal_recurrence, scale: 1
|
248
271
|
FitParser::File::Definitions.add_field 15, 9, 'recurrence_value', type: :uint16, scale: 1
|
249
272
|
FitParser::File::Definitions.add_field 15, 10, 'enabled', type: :bool, scale: 1
|
273
|
+
FitParser::File::Definitions.add_field 15, 11, 'source', type: :goal_source
|
250
274
|
|
251
275
|
FitParser::File::Definitions.add_name 34, 'activity'
|
252
276
|
FitParser::File::Definitions.add_field 34, 253, 'timestamp', type: :date_time
|
@@ -354,6 +378,31 @@ FitParser::File::Definitions.add_field 18, 102, 'avg_right_torque_effectiveness'
|
|
354
378
|
FitParser::File::Definitions.add_field 18, 103, 'avg_left_pedal_smoothness', type: :uint8, scale: 2, unit: 'percent'
|
355
379
|
FitParser::File::Definitions.add_field 18, 104, 'avg_right_pedal_smoothness', type: :uint8, scale: 2, unit: 'percent'
|
356
380
|
FitParser::File::Definitions.add_field 18, 105, 'avg_combined_pedal_smoothness', type: :uint8, scale: 2, unit: 'percent'
|
381
|
+
FitParser::File::Definitions.add_field 18, 111, 'sport_index', type: :uint8
|
382
|
+
FitParser::File::Definitions.add_field 18, 112, 'time_standing', type: :uint32, scale: 1000, units: 's'
|
383
|
+
FitParser::File::Definitions.add_field 18, 113, 'stand_count', type: :uint16
|
384
|
+
FitParser::File::Definitions.add_field 18, 114, 'avg_left_pco', type: :sint8, units: 'mm'
|
385
|
+
FitParser::File::Definitions.add_field 18, 115, 'avg_right_pco', type: :sint8, units: 'mm'
|
386
|
+
FitParser::File::Definitions.add_field 18, 116, 'avg_left_power_phase', type: :uint8, scale: 0.7111111, units: 'degrees'
|
387
|
+
FitParser::File::Definitions.add_field 18, 117, 'avg_left_power_phase_peak', type: :uint8, scale: 0.7111111, units: 'degrees'
|
388
|
+
FitParser::File::Definitions.add_field 18, 118, 'avg_right_power_phase', type: :uint8, scale: 0.7111111, units: 'degrees'
|
389
|
+
FitParser::File::Definitions.add_field 18, 119, 'avg_right_power_phase_peak', type: :uint8, scale: 0.7111111, units: 'degrees'
|
390
|
+
FitParser::File::Definitions.add_field 18, 120, 'avg_power_position', type: :uint16, units: 'watts'
|
391
|
+
FitParser::File::Definitions.add_field 18, 121, 'max_power_position', type: :uint16, units: 'watts'
|
392
|
+
FitParser::File::Definitions.add_field 18, 122, 'avg_cadence_position', type: :uint8, units: 'rpm'
|
393
|
+
FitParser::File::Definitions.add_field 18, 123, 'max_cadence_position', type: :uint8, units: 'rpm'
|
394
|
+
FitParser::File::Definitions.add_field 18, 124, 'enhanced_avg_speed', type: :uint32, scale: 1000, units: 'm/s'
|
395
|
+
FitParser::File::Definitions.add_field 18, 125, 'enhanced_max_speed', type: :uint32, scale: 1000, units: 'm/s'
|
396
|
+
FitParser::File::Definitions.add_field 18, 126, 'enhanced_avg_altitude', type: :uint32, scale: 5, offset: 500, units: 'm'
|
397
|
+
FitParser::File::Definitions.add_field 18, 127, 'enhanced_min_altitude', type: :uint32, scale: 5, offset: 500, units: 'm'
|
398
|
+
FitParser::File::Definitions.add_field 18, 128, 'enhanced_max_altitude', type: :uint32, scale: 5, offset: 500, units: 'm'
|
399
|
+
FitParser::File::Definitions.add_field 18, 129, 'avg_lev_motor_power', type: :uint16, units: 'watts'
|
400
|
+
FitParser::File::Definitions.add_field 18, 130, 'max_lev_motor_power', type: :uint16, units: 'watts'
|
401
|
+
FitParser::File::Definitions.add_field 18, 131, 'lev_battery_consumption', type: :uint8, scale: 2, units: 'percent'
|
402
|
+
FitParser::File::Definitions.add_field 18, 132, 'avg_vertical_ratio', type: :uint16, scale: 100, units: 'percent'
|
403
|
+
FitParser::File::Definitions.add_field 18, 133, 'avg_stance_time_balance', type: :uint16, scale: 100, units: 'percent'
|
404
|
+
FitParser::File::Definitions.add_field 18, 134, 'avg_step_length', type: :uint16, scale: 10, units: 'mm'
|
405
|
+
FitParser::File::Definitions.add_field 18, 137, 'total_anaerobic_training_effect', type: :uint8, scale: 10
|
357
406
|
|
358
407
|
FitParser::File::Definitions.add_name 19, 'lap'
|
359
408
|
FitParser::File::Definitions.add_field 19, 254, 'message_index', type: :message_index, scale: 1
|
@@ -441,6 +490,29 @@ FitParser::File::Definitions.add_field 19, 92, 'avg_right_torque_effectiveness',
|
|
441
490
|
FitParser::File::Definitions.add_field 19, 93, 'avg_left_pedal_smoothness', type: :uint8, scale: 2, unit: 'percent'
|
442
491
|
FitParser::File::Definitions.add_field 19, 94, 'avg_right_pedal_smoothness', type: :uint8, scale: 2, unit: 'percent'
|
443
492
|
FitParser::File::Definitions.add_field 19, 95, 'avg_combined_pedal_smoothness', type: :uint8, scale: 2, unit: 'percent'
|
493
|
+
FitParser::File::Definitions.add_field 19, 98, 'time_standing', type: :uint32, scale: 1000, unit: 's'
|
494
|
+
FitParser::File::Definitions.add_field 19, 99, 'stand_count', type: :uint16
|
495
|
+
FitParser::File::Definitions.add_field 19, 100, 'avg_left_pco', type: :sint8, unit: 'mm'
|
496
|
+
FitParser::File::Definitions.add_field 19, 101, 'avg_right_pco', type: :sint8, unit: 's'
|
497
|
+
FitParser::File::Definitions.add_field 19, 102, 'avg_left_power_phase', type: :uint8, scale: 0.7111111, unit: 'degrees'
|
498
|
+
FitParser::File::Definitions.add_field 19, 103, 'avg_left_power_phase_peak', type: :uint8, scale: 0.7111111, unit: 'degrees'
|
499
|
+
FitParser::File::Definitions.add_field 19, 104, 'avg_right_power_phase', type: :uint8, scale: 0.7111111, unit: 'degrees'
|
500
|
+
FitParser::File::Definitions.add_field 19, 105, 'avg_right_power_phase_peak', type: :uint8, scale: 0.7111111, unit: 'degrees'
|
501
|
+
FitParser::File::Definitions.add_field 19, 106, 'avg_power_position', type: :uint16, unit: 'watts'
|
502
|
+
FitParser::File::Definitions.add_field 19, 107, 'max_power_position', type: :uint16, unit: 'watts'
|
503
|
+
FitParser::File::Definitions.add_field 19, 108, 'avg_cadence_position', type: :uint8, unit: 'rpm'
|
504
|
+
FitParser::File::Definitions.add_field 19, 109, 'max_cadence_position', type: :uint8, unit: 'rpm'
|
505
|
+
FitParser::File::Definitions.add_field 19, 110, 'enhanced_avg_speed', type: :uint32, scale: 1000, unit: 'm/s'
|
506
|
+
FitParser::File::Definitions.add_field 19, 111, 'enhanced_max_speed', type: :uint32, scale: 1000, unit: 'm/s'
|
507
|
+
FitParser::File::Definitions.add_field 19, 112, 'enhanced_avg_altitude', type: :uint32, scale: 5, offset: 500, unit: 'm'
|
508
|
+
FitParser::File::Definitions.add_field 19, 113, 'enhanced_min_altitude', type: :uint32, scale: 5, offset: 500, unit: 'm'
|
509
|
+
FitParser::File::Definitions.add_field 19, 114, 'enhanced_max_altitude', type: :uint32, scale: 5, offset: 500, unit: 'm'
|
510
|
+
FitParser::File::Definitions.add_field 19, 115, 'avg_lev_motor_power', type: :uint16, unit: 'watts'
|
511
|
+
FitParser::File::Definitions.add_field 19, 116, 'max_lev_motor_power', type: :uint16, unit: 'watts'
|
512
|
+
FitParser::File::Definitions.add_field 19, 117, 'lev_battery_consumption', type: :uint8, scale: 2, unit: 'percent'
|
513
|
+
FitParser::File::Definitions.add_field 19, 118, 'avg_vertical_ratio', type: :uint16, scale: 100, unit: 'percent'
|
514
|
+
FitParser::File::Definitions.add_field 19, 119, 'avg_stance_time_balance', type: :uint16, scale: 100, unit: 'percent'
|
515
|
+
FitParser::File::Definitions.add_field 19, 120, 'avg_step_length', type: :uint16, scale: 10, unit: 'mm'
|
444
516
|
|
445
517
|
FitParser::File::Definitions.add_name 101, 'length'
|
446
518
|
FitParser::File::Definitions.add_field 101, 254, 'message_index', type: :message_index, scale: 1
|
@@ -509,6 +581,19 @@ FitParser::File::Definitions.add_field 20, 57, 'saturated_hemoglobin_percent', t
|
|
509
581
|
FitParser::File::Definitions.add_field 20, 58, 'saturated_hemoglobin_percent_min', type: :uint16, scale: 10, unit: '%'
|
510
582
|
FitParser::File::Definitions.add_field 20, 59, 'saturated_hemoglobin_percent_max', type: :uint16, scale: 10, unit: '%'
|
511
583
|
FitParser::File::Definitions.add_field 20, 62, 'device_index', type: :device_index
|
584
|
+
FitParser::File::Definitions.add_field 20, 67, 'left_pco', type: :sint8, unit: 'mm'
|
585
|
+
FitParser::File::Definitions.add_field 20, 68, 'right_pco', type: :sint8, unit: 'mm'
|
586
|
+
FitParser::File::Definitions.add_field 20, 69, 'left_power_phase', type: :uint8, scale: 0.7111111, unit: 'degrees'
|
587
|
+
FitParser::File::Definitions.add_field 20, 70, 'left_power_phase_peak', type: :uint8, scale: 0.7111111, unit: 'degrees'
|
588
|
+
FitParser::File::Definitions.add_field 20, 71, 'right_power_phase', type: :uint8, scale: 0.7111111, unit: 'degrees'
|
589
|
+
FitParser::File::Definitions.add_field 20, 72, 'right_power_phase_peak', type: :uint8, scale: 0.7111111, unit: 'degrees'
|
590
|
+
FitParser::File::Definitions.add_field 20, 73, 'enhanced_speed', type: :uint32, scale: 1000, unit: 'm/s'
|
591
|
+
FitParser::File::Definitions.add_field 20, 78, 'enhanced_altitude', type: :uint32, scale: 5, offset: 500, unit: 'm'
|
592
|
+
FitParser::File::Definitions.add_field 20, 81, 'battery_soc', type: :uint8, scale: 2, unit: 'percent'
|
593
|
+
FitParser::File::Definitions.add_field 20, 82, 'motor_power', type: :uint16, unit: 'watts'
|
594
|
+
FitParser::File::Definitions.add_field 20, 83, 'vertical_ratio', type: :uint16, scale: 100, unit: 'percent'
|
595
|
+
FitParser::File::Definitions.add_field 20, 84, 'stance_time_balance', type: :uint16, scale: 100, unit: 'percent'
|
596
|
+
FitParser::File::Definitions.add_field 20, 85, 'step_length', type: :uint16, scale: 10, unit: 'mm'
|
512
597
|
|
513
598
|
FitParser::File::Definitions.add_name 21, 'event'
|
514
599
|
FitParser::File::Definitions.add_field 21, 253, 'timestamp', type: :date_time, unit: 's'
|
@@ -541,6 +626,7 @@ FitParser::File::Definitions.add_field 21, 9, 'front_gear_num', type: :uint8z
|
|
541
626
|
FitParser::File::Definitions.add_field 21, 10, 'front_gear', type: :uint8z
|
542
627
|
FitParser::File::Definitions.add_field 21, 11, 'rear_gear_num', type: :uint8z
|
543
628
|
FitParser::File::Definitions.add_field 21, 12, 'rear_gear', type: :uint8z
|
629
|
+
FitParser::File::Definitions.add_field 21, 13, 'device_index'
|
544
630
|
|
545
631
|
FitParser::File::Definitions.add_name 23, 'device_info'
|
546
632
|
FitParser::File::Definitions.add_field 23, 253, 'timestamp', type: :date_time, scale: 1, unit: 's'
|
@@ -562,6 +648,7 @@ FitParser::File::Definitions.add_field 23, 20, 'ant_transmission_type', type: :u
|
|
562
648
|
FitParser::File::Definitions.add_field 23, 21, 'ant_device_number', type: :uint16z
|
563
649
|
FitParser::File::Definitions.add_field 23, 22, 'ant_network', type: :ant_network
|
564
650
|
FitParser::File::Definitions.add_field 23, 25, 'source_type', type: :source_type
|
651
|
+
FitParser::File::Definitions.add_field 23, 27, 'product_name', type: :string
|
565
652
|
|
566
653
|
FitParser::File::Definitions.add_name 72, 'training_file'
|
567
654
|
FitParser::File::Definitions.add_field 72, 253, 'timestamp', type: :date_time
|
@@ -579,6 +666,7 @@ FitParser::File::Definitions.add_name 31, 'course'
|
|
579
666
|
FitParser::File::Definitions.add_field 31, 4, 'sport', type: :sport
|
580
667
|
FitParser::File::Definitions.add_field 31, 5, 'name', type: :string
|
581
668
|
FitParser::File::Definitions.add_field 31, 6, 'capabilities', type: :course_capabilities
|
669
|
+
FitParser::File::Definitions.add_field 31, 7, 'sub_sport', type: :sub_sport
|
582
670
|
|
583
671
|
FitParser::File::Definitions.add_name 32, 'course_point'
|
584
672
|
FitParser::File::Definitions.add_field 32, 254, 'message_index', type: :message_index
|
@@ -588,6 +676,7 @@ FitParser::File::Definitions.add_field 32, 3, 'position_long', type: :sint32, sc
|
|
588
676
|
FitParser::File::Definitions.add_field 32, 4, 'distance', type: :uint32, scale: 100, unit: 'm'
|
589
677
|
FitParser::File::Definitions.add_field 32, 5, 'type', type: :course_point, scale: 1
|
590
678
|
FitParser::File::Definitions.add_field 32, 6, 'name', type: :string
|
679
|
+
FitParser::File::Definitions.add_field 32, 8, 'favorite', type: :bool
|
591
680
|
|
592
681
|
FitParser::File::Definitions.add_name 26, 'workout'
|
593
682
|
FitParser::File::Definitions.add_field 26, 4, 'sport', type: :sport, scale: 1
|
@@ -648,6 +737,7 @@ FitParser::File::Definitions.add_field 33, 3, 'sport', type: :sport
|
|
648
737
|
FitParser::File::Definitions.add_field 33, 4, 'elapsed_time', type: :uint32, unit: 's'
|
649
738
|
FitParser::File::Definitions.add_field 33, 5, 'sessions', type: :uint16
|
650
739
|
FitParser::File::Definitions.add_field 33, 6, 'active_time', type: :uint32, unit: 's'
|
740
|
+
FitParser::File::Definitions.add_field 33, 9, 'sport_index', type: :uint8
|
651
741
|
|
652
742
|
FitParser::File::Definitions.add_name 30, 'weight_scale'
|
653
743
|
FitParser::File::Definitions.add_field 30, 253, 'timestamp', type: :date_time, scale: 1, unit: 's'
|
@@ -712,7 +802,11 @@ FitParser::File::Definitions.add_field 55, 26, 'timestamp_16', type: :uint16, un
|
|
712
802
|
FitParser::File::Definitions.add_field 55, 27, 'heart_rate', type: :uint8, unit: 'bpm'
|
713
803
|
FitParser::File::Definitions.add_field 55, 28, 'intensity', type: :uint8, scale: 10
|
714
804
|
FitParser::File::Definitions.add_field 55, 29, 'duration_min', type: :uint16, unit: 'min'
|
715
|
-
FitParser::File::Definitions.add_field
|
805
|
+
FitParser::File::Definitions.add_field 55, 30, 'duration', type: :uint32, unit: 's'
|
806
|
+
FitParser::File::Definitions.add_field 55, 31, 'ascent', type: :uint32, scale: 1000, unit: 'm'
|
807
|
+
FitParser::File::Definitions.add_field 55, 32, 'descent', type: :uint32, scale: 1000, unit: 'm'
|
808
|
+
FitParser::File::Definitions.add_field 55, 33, 'moderate_activity_minutes', type: :uint16, unit: 'minutes'
|
809
|
+
FitParser::File::Definitions.add_field 55, 34, 'vigorous_activity_minutes', type: :uint16, unit: 'minutes'
|
716
810
|
|
717
811
|
FitParser::File::Definitions.add_name(145, 'memo_glob')
|
718
812
|
FitParser::File::Definitions.add_field(145, 250, 'part_index', type: :uint32)
|
@@ -3,8 +3,9 @@ module FitParser
|
|
3
3
|
class Record
|
4
4
|
attr_reader :header, :content, :definitions
|
5
5
|
|
6
|
-
def initialize(definitions)
|
6
|
+
def initialize(definitions, dev_definitions)
|
7
7
|
@definitions = definitions
|
8
|
+
@dev_definitions = dev_definitions
|
8
9
|
end
|
9
10
|
|
10
11
|
def read(io)
|
@@ -12,8 +13,12 @@ module FitParser
|
|
12
13
|
|
13
14
|
@content = case @header.message_type.snapshot
|
14
15
|
when 1
|
15
|
-
Definition.read(io).tap do |definition|
|
16
|
-
@
|
16
|
+
Definition.read(io, { dev_data_flag: @header.dev_data_flag }).tap do |definition|
|
17
|
+
if @header.dev_data_flag == 1
|
18
|
+
@definitions[@header.local_message_type.snapshot] = Data.generate(definition, @dev_definitions)
|
19
|
+
else
|
20
|
+
@definitions[@header.local_message_type.snapshot] = Data.generate(definition)
|
21
|
+
end
|
17
22
|
end
|
18
23
|
when 0
|
19
24
|
definition = @definitions[@header.local_message_type.snapshot]
|
@@ -6,7 +6,8 @@ module FitParser
|
|
6
6
|
bit1 :header_type
|
7
7
|
|
8
8
|
bit1 :message_type, :onlyif => :normal?
|
9
|
-
|
9
|
+
bit1 :dev_data_flag, :onlyif => :normal?
|
10
|
+
bit1 :reserved_bits, :onlyif => :normal?
|
10
11
|
|
11
12
|
choice :local_message_type, :selection => :header_type do
|
12
13
|
bit4 0
|