fit_parser 0.0.8 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|