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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0ce4c1fb626d5bb6a55bb391a1e7866d3ebd1731
4
- data.tar.gz: 1c3c23c7559acfd7a53b60e89444770fc08768e7
3
+ metadata.gz: c5a9b2aa672b5b76113b211fe1cb1f9ee699abd2
4
+ data.tar.gz: 71dc6534e61ca9a129f05f508973c4cbc78880da
5
5
  SHA512:
6
- metadata.gz: 66c26eab5d161cd18e02d9d47732614ba61ee84a681df341e6837440deb13fb758c3d7485d202f3bd5da901b4f9946934a010f0f1c4f3752a46d3cdb3e30d7c8
7
- data.tar.gz: dd7968418eed7a3cc97c5aeea89ded49b45ea72f7f066e9e669003529c9d958eb63299fe30a7858dac9aa238d5f0476e41c7b60b6e3632030180d1e2a5b75b0e
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
@@ -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
- code << "scale = #{field.scale.inspect}.0\n"
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(55, 30, 'duration', type: :uint32, unit: 's')
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
- @definitions[@header.local_message_type.snapshot] = Data.generate(definition)
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
- bit2 :reserved_bits, :onlyif => :normal?
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