fit4ruby 3.1.0 → 3.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d789b2e373decc4dfff48739b65a320c66da88fd
4
- data.tar.gz: 1a40f4aac55b45f66cb082b6ffef4ca6e3c3ed9e
3
+ metadata.gz: 247b4e5fd81ffc3c5e12bc1d3235196126fdb8cc
4
+ data.tar.gz: b493e5b073e63d977ed28edc3600dac73519d0b6
5
5
  SHA512:
6
- metadata.gz: 2ec0e96be6dd2d0cf44b03a5ac41197a693d4a4b8861063a55f7d37e98252656f380d8cb57bb4d77476d7f805fdab1668c598f5ec81208e7225102e151b12e8a
7
- data.tar.gz: d92c14c4af7c98c043d3a675bb8eefa741fe30b18a05d4606358cd69a49c05b4564355b1c213dac9c9196d1b1c2f0bf5122bca7808652db310fccf1c59fe92f1
6
+ metadata.gz: 88b2fe75bdf8a1bfb4a6f3d4892db4253f942a3a251118fc054f4671f9f3927960552fe9005334da6f884e95990babae029071edbf287740efaff2450748824b
7
+ data.tar.gz: f8aa4152a1d37f682d0ca526045d10a19628ba79bad41eebbf3b3e3e963fcb971fc82d38fef8756b2bfa50eaefd3eea80388c849cb1bc0bf34aa79d64754e7eb
@@ -264,7 +264,7 @@ module Fit4Ruby
264
264
  # Then check the user_data entries for a metmax entry. METmax * 3.5
265
265
  # is same value as VO2max.
266
266
  @user_data.each do |u|
267
- return ((u.metmax * 1000.0) * 3.5) / 1024.0 if u.metmax
267
+ return u.metmax * 3.5 if u.metmax
268
268
  end
269
269
 
270
270
  nil
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # = FieldDescription.rb -- Fit4Ruby - FIT file processing library for Ruby
5
5
  #
6
- # Copyright (c) 2017, 2018 by Chris Schlaeger <cs@taskjuggler.org>
6
+ # Copyright (c) 2017, 2018, 2019 by Chris Schlaeger <cs@taskjuggler.org>
7
7
  #
8
8
  # This program is free software; you can redistribute it and/or modify
9
9
  # it under the terms of version 2 of the GNU General Public License as
@@ -32,17 +32,20 @@ module Fit4Ruby
32
32
  unless (gfm = GlobalFitMessages[@native_mesg_num])
33
33
  Log.error "Developer field description references unknown global " +
34
34
  "message number #{@native_mesg_num}"
35
+ return
35
36
  end
36
37
 
37
38
  if @developer_data_index >=
38
39
  fit_entity.top_level_record.developer_data_ids.size
39
40
  Log.error "Developer data index #{@developer_data_index} is too large"
41
+ return
40
42
  end
41
43
 
42
44
  msg = messages[@native_mesg_num] ||
43
45
  messages.message(@native_mesg_num, gfm.name)
44
46
  unless (@fit_base_type_id & 0x7F) < FIT_TYPE_DEFS.size
45
47
  Log.error "fit_base_type_id #{@fit_base_type_id} is too large"
48
+ return
46
49
  end
47
50
  options = {}
48
51
  options[:scale] = @scale if @scale
@@ -58,4 +61,3 @@ module Fit4Ruby
58
61
 
59
62
  end
60
63
 
61
-
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # = FitDeveloperDataFieldDefinition.rb -- Fit4Ruby - FIT file processing library for Ruby
5
5
  #
6
- # Copyright (c) 2017, 2018 by Chris Schlaeger <cs@taskjuggler.org>
6
+ # Copyright (c) 2017, 2018, 2019 by Chris Schlaeger <cs@taskjuggler.org>
7
7
  #
8
8
  # This program is free software; you can redistribute it and/or modify
9
9
  # it under the terms of version 2 of the GNU General Public License as
@@ -41,22 +41,56 @@ module Fit4Ruby
41
41
  size_in_bytes
42
42
  end
43
43
 
44
- private
44
+ def undefined_value
45
+ FIT_TYPE_DEFS[checked_base_type_number][2]
46
+ end
45
47
 
46
48
  def find_field_definition
49
+ return @field_definition if @field_definition
50
+
47
51
  tlr = parent.parent.fit_entity.top_level_record
48
- field = tlr.field_descriptions.find do |fd|
52
+ @field_definition = tlr.field_descriptions.find do |fd|
49
53
  fd.field_definition_number == field_number.snapshot &&
50
54
  fd.developer_data_index == developer_data_index.snapshot
51
55
  end
52
- unless field
56
+ unless @field_definition
53
57
  Log.error "Unknown developer field #{field_number.snapshot} " +
54
58
  "for developer #{developer_data_index.snapshot}"
59
+ return nil
55
60
  end
56
61
 
57
- field
62
+ @field_definition
63
+ end
64
+
65
+ def to_s(value)
66
+ return '' if value.nil?
67
+
68
+ if (field_definition = find_field_definition)
69
+ "#{value} #{find_field_definition.units}"
70
+ else
71
+ if value.kind_of?(Array)
72
+ s = '[ '
73
+ value.each do |v|
74
+ v /= @field_def.scale.to_f if @field_def.scale
75
+ v -= @fielid_def.offset if @field_def.offset
76
+ s << to_s(v) + ' '
77
+ end
78
+ s + ']'
79
+
80
+ return s
81
+ else
82
+ field_number = field_definition_number.snapshot
83
+
84
+ value /= @field_def.scale.to_f if @field_def.scale
85
+ value -= @fielid_def.offset if @field_def.offset
86
+
87
+ return value.to_s
88
+ end
89
+ end
58
90
  end
59
91
 
92
+ private
93
+
60
94
  def checked_base_type_number
61
95
  field = find_field_definition
62
96
  base_type_number = field.fit_base_type_id & 0x7F
@@ -13,6 +13,7 @@
13
13
  require 'fit4ruby/Activity'
14
14
  require 'fit4ruby/Monitoring_B'
15
15
  require 'fit4ruby/GlobalFitMessage'
16
+ require 'fit4ruby/Metrics'
16
17
 
17
18
  module Fit4Ruby
18
19
 
@@ -49,6 +50,9 @@ module Fit4Ruby
49
50
  when 32, 'monitoring_b'
50
51
  @top_level_record = Monitoring_B.new
51
52
  @type = 'monitoring_b'
53
+ when 44, 'metrics'
54
+ @top_level_record = Metrics.new
55
+ @type = 'metrics'
52
56
  else
53
57
  Log.error "Unsupported FIT file type #{type}"
54
58
  return nil
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # = FitMessageRecord.rb -- Fit4Ruby - FIT file processing library for Ruby
5
5
  #
6
- # Copyright (c) 2014, 2015 by Chris Schlaeger <cs@taskjuggler.org>
6
+ # Copyright (c) 2014, 2015, 2018, 2019 by Chris Schlaeger <cs@taskjuggler.org>
7
7
  #
8
8
  # This program is free software; you can redistribute it and/or modify
9
9
  # it under the terms of version 2 of the GNU General Public License as
@@ -98,6 +98,39 @@ module Fit4Ruby
98
98
  end
99
99
  end
100
100
 
101
+ @definition.developer_fields.each do |field|
102
+ # Find the corresponding field description for the given developer and
103
+ # field number.
104
+ field_number = field.field_number.snapshot
105
+
106
+ unless (field_description = field.find_field_definition)
107
+ Log.error "There is no field definition for developer " +
108
+ "#{field.developer_data_index} field #{field_number}"
109
+ next
110
+ end
111
+
112
+ field_name = field_description.field_name
113
+ units = field_description.units
114
+ type = field.type
115
+ native_message_number = field_description.native_mesg_num
116
+ native_field_number = field_description.native_field_num
117
+
118
+ value = @message_record[field.name].snapshot
119
+ value = nil if value == field.undefined_value
120
+
121
+ if filter && fields_dump &&
122
+ (filter.field_names.nil? ||
123
+ filter.field_names.include?(field_name)) &&
124
+ !(((value.respond_to?('count') &&
125
+ (value.count(field.undefined_value) == value.length)) ||
126
+ value == field.undefined_value) && filter.ignore_undef)
127
+ fields_dump << DumpedField.new(
128
+ native_message_number,
129
+ 256 * (1 + field.developer_data_index) + field_number,
130
+ field_name, type, field.to_s(value))
131
+ end
132
+ end
133
+
101
134
  if @name == 'field_description'
102
135
  obj.create_global_definition(fit_entity)
103
136
  end
@@ -75,6 +75,10 @@ module Fit4Ruby
75
75
  entry 4, 'low'
76
76
  entry 5, 'critical'
77
77
 
78
+ dict 'date_mode'
79
+ entry 0, 'day_month'
80
+ entry 1, 'month_day'
81
+
78
82
  dict 'body_location'
79
83
  entry 0, 'left_leg'
80
84
  entry 1, 'left_calf'
@@ -245,6 +249,7 @@ module Fit4Ruby
245
249
  entry 45, 'elev_high_alert'
246
250
  entry 46, 'elev_low_alert'
247
251
  entry 47, 'comm_timeout'
252
+ entry 48, 'functional_threshold_power' # guess (in Watt)
248
253
  entry 49, 'lactate_threshold_heart_rate' # guess (in BPM)
249
254
  entry 50, 'lactate_threshold_speed' # guess (in m/s)
250
255
 
@@ -276,6 +281,10 @@ module Fit4Ruby
276
281
  entry 20, 'activity_summary'
277
282
  entry 28, 'monitoring_daily'
278
283
  entry 32, 'monitoring_b'
284
+ entry 34, 'segment'
285
+ entry 35, 'segment_list'
286
+ entry 40, 'exd_configuration'
287
+ entry 44, 'metrics'
279
288
 
280
289
  dict 'fitness_equipment_state'
281
290
  entry 0, 'ready'
@@ -344,6 +353,8 @@ module Fit4Ruby
344
353
  entry 2593, 'running_dynamics_pod'
345
354
  entry 2691, 'fr935'
346
355
  entry 2697, 'fenix5'
356
+ entry 2957, 'fenix5_gps_galileo' # Just a guess
357
+ entry 3111, 'fenix5x_plus'
347
358
  entry 10007, 'sdm4'
348
359
  entry 20119, 'training_center'
349
360
  entry 65532, 'android_antplus_plugin'
@@ -651,6 +662,22 @@ module Fit4Ruby
651
662
  entry 59, 'obstacle '
652
663
  entry 254, 'all'
653
664
 
665
+ dict 'training_status'
666
+ entry 0, 'overreaching'
667
+ entry 1, 'detraining'
668
+ entry 2, 'unproductive'
669
+ entry 3, 'recovery'
670
+ entry 4, 'maintaining'
671
+ entry 5, 'productive'
672
+ entry 6, 'peaking'
673
+ entry 7, 'productive'
674
+
675
+ dict 'training_status_trend'
676
+ entry 0, 'undefined'
677
+ entry 1, 'down'
678
+ entry 2, 'maintaining'
679
+ entry 3, 'up'
680
+
654
681
  end
655
682
 
656
683
  end
@@ -44,8 +44,12 @@ module Fit4Ruby
44
44
  field 14, 'uint8', 'undocumented_field_14'
45
45
  field 15, 'uint8', 'undocumented_field_15'
46
46
  field 22, 'enum', 'undocumented_field_22'
47
+ field 23, 'enum', 'undocumented_field_23'
48
+ field 25, 'enum', 'undocumented_field_25'
47
49
  field 26, 'enum', 'undocumented_field_26'
48
50
  field 28, 'enum', 'undocumented_field_28'
51
+ field 30, 'enum', 'undocumented_field_30'
52
+ field 31, 'enum', 'undocumented_field_31'
49
53
  field 34, 'enum', 'undocumented_field_34'
50
54
  field 35, 'enum', 'undocumented_field_35'
51
55
  field 36, 'enum', 'activity_tracker_enabled'
@@ -56,6 +60,7 @@ module Fit4Ruby
56
60
  field 44, 'enum', 'undocumented_field_44'
57
61
  field 45, 'enum', 'undocumented_field_45'
58
62
  field 46, 'enum', 'move_alert_enabled'
63
+ field 47, 'enum', 'date_mode'
59
64
  field 48, 'enum', 'undocumented_field_48'
60
65
  field 49, 'uint16', 'undocumented_field_49'
61
66
  field 51, 'enum', 'undocumented_field_51'
@@ -75,6 +80,8 @@ module Fit4Ruby
75
80
  field 68, 'enum', 'undocumented_field_68'
76
81
  field 69, 'enum', 'undocumented_field_69'
77
82
  field 75, 'enum', 'undocumented_field_75'
83
+ field 76, 'enum', 'undocumented_field_76'
84
+ field 77, 'enum', 'undocumented_field_77'
78
85
  field 80, 'enum', 'lactate_threshold_autodetect_enabled'
79
86
  field 81, 'enum', 'undocumented_field_81'
80
87
  field 82, 'enum', 'undocumented_field_82'
@@ -84,6 +91,7 @@ module Fit4Ruby
84
91
  field 87, 'enum', 'undocumented_field_87'
85
92
  field 90, 'uint32', 'auto_activity_detect'
86
93
  field 94, 'uint8', 'number_of_screens'
94
+ field 96, 'enum', 'undocumented_field_96'
87
95
  field 97, 'uint8z', 'undocumented_field_97'
88
96
  field 101, 'enum', 'undocumented_field_101'
89
97
  field 104, 'enum', 'undocumented_field_104'
@@ -93,14 +101,27 @@ module Fit4Ruby
93
101
  field 110, 'enum', 'undocumented_field_110'
94
102
  field 111, 'enum', 'undocumented_field_111'
95
103
  field 112, 'enum', 'undocumented_field_112'
104
+ field 116, 'enum', 'undocumented_field_116'
105
+ field 117, 'enum', 'undocumented_field_117'
96
106
  field 124, 'uint8', 'undocumented_field_124'
97
107
  field 125, 'uint8', 'undocumented_field_125'
98
108
  field 126, 'enum', 'undocumented_field_126'
99
109
  field 127, 'enum', 'undocumented_field_127'
100
110
  field 128, 'enum', 'undocumented_field_128'
111
+ field 129, 'enum', 'undocumented_field_129'
112
+ field 130, 'enum', 'undocumented_field_130'
113
+ field 131, 'enum', 'undocumented_field_131'
114
+ field 132, 'enum', 'undocumented_field_132'
101
115
  field 133, 'enum', 'undocumented_field_133'
116
+ field 137, 'enum', 'undocumented_field_137'
102
117
  field 138, 'enum', 'undocumented_field_138'
118
+ field 139, 'enum', 'undocumented_field_139'
119
+ field 141, 'uint8', 'undocumented_field_141'
120
+ field 142, 'uint8', 'undocumented_field_142'
121
+ field 143, 'uint8', 'undocumented_field_143'
103
122
  field 144, 'enum', 'true_up_enabled'
123
+ field 148, 'enum', 'undocumented_field_148'
124
+ field 149, 'enum', 'undocumented_field_149'
104
125
 
105
126
  message 3, 'user_profile'
106
127
  field 0, 'string', 'friendly_name'
@@ -124,7 +145,7 @@ module Fit4Ruby
124
145
  field 30, 'enum', 'height_setting', :dict => 'display_measure'
125
146
  field 31, 'uint16', 'user_running_step_length'
126
147
  field 32, 'uint16', 'user_walking_step_length'
127
- field 33, 'uint16', 'undocumented_field_33'
148
+ field 33, 'uint16', 'undocumented_field_33' # varies between 800 to 1600, seems VO2max related
128
149
  field 34, 'uint16', 'undocumented_field_34'
129
150
  field 35, 'uint32', 'undocumented_field_35'
130
151
  field 36, 'uint8', 'undocumented_field_36'
@@ -132,11 +153,54 @@ module Fit4Ruby
132
153
  field 38, 'uint16', 'undocumented_field_38'
133
154
  field 39, 'float32', 'undocumented_field_39'
134
155
  field 40, 'float32', 'undocumented_field_40'
135
- field 41, 'uint32', 'undocumented_field_41'
156
+ field 41, 'uint32', 'time_last_lthr_update', :type => 'date_time'
136
157
  field 42, 'uint32', 'undocumented_field_42'
137
158
  field 43, 'enum', 'undocumented_field_43'
159
+ field 47, 'enum', 'undocumented_field_47'
138
160
  field 253, 'uint32', 'timestamp', :type => 'date_time'
139
161
 
162
+ message 5, 'sdm_profile'
163
+ field 0, 'bool', 'enabled'
164
+ field 1, 'uint16z', 'sdm_ant_id'
165
+ field 2, 'uint16', 'sdm_cal_factor', :scale => 10, :unit => '%'
166
+ field 3, 'uint32', 'odometer', :scale => 100, :unit => 'm'
167
+ field 4, 'bool', 'speed_source'
168
+ field 5, 'uint8z', 'sdm_ant_id_trans_type'
169
+ field 7, 'uint8', 'odometer_rollover'
170
+
171
+ message 6, 'bike_profile'
172
+ field 0, 'string', 'name'
173
+ field 1, 'sport', 'sport'
174
+ field 2, 'sub_sport', 'sub_sport'
175
+ field 3, 'uint32', 'odometer', :scale => 100, :unit => 'm'
176
+ field 4, 'uint16z', 'bike_spd_ant_id'
177
+ field 5, 'uint16z', 'bike_cad_ant_id'
178
+ field 6, 'uint16z', 'bike_spdcad_ant_id'
179
+ field 7, 'uint16z', 'bike_power_ant_id'
180
+ field 8, 'uint16', 'custom_wheelsize', :scale => 1000, :unit => 'm'
181
+ field 9, 'uint16', 'auto_wheelsize', :scale => 1000, :unit => 'm'
182
+ field 10, 'uint16', 'bike_weight', :scale => 10, :unit => 'kg'
183
+ field 11, 'uint16', 'power_cal_factor', :scale => 10, :unit => '%'
184
+ field 12, 'bool', 'auto_wheel_cal'
185
+ field 13, 'bool', 'auto_power_zero'
186
+ field 14, 'uint8', 'id'
187
+ field 15, 'bool', 'spd_enabled'
188
+ field 16, 'bool', 'cad_enabled'
189
+ field 17, 'bool', 'spdcad_enabled'
190
+ field 18, 'bool', 'power_enabled'
191
+ field 19, 'uint8', 'crank_length', :scale => 2, :offset => -110, :unit => 'mm'
192
+ field 20, 'bool', 'enabled'
193
+ field 21, 'uint8z', 'bike_spd_ant_id_trans_type'
194
+ field 22, 'uint8z', 'bike_cad_ant_id_trans_type'
195
+ field 23, 'uint8z', 'bike_spdcad_ant_id_trans_type'
196
+ field 24, 'uint8z', 'bike_power_ant_id_trans_type'
197
+ field 37, 'uint8', 'odometer_rollover'
198
+ field 38, 'uint8z', 'front_gear_num', :array => true
199
+ field 39, 'uint8z', 'front_gear'
200
+ field 40, 'uint8z', 'rear_gear_num', :array => true
201
+ field 41, 'uint8z', 'rear_gear'
202
+ field 44, 'bool', 'shimano_di2_enabled'
203
+
140
204
  message 7, 'zones_target'
141
205
  field 1, 'uint8', 'max_heart_rate'
142
206
  field 2, 'uint8', 'threshold_heart_rate'
@@ -157,10 +221,13 @@ module Fit4Ruby
157
221
  field 4, 'uint16', 'undocumented_field_4'
158
222
  field 5, 'enum', 'undocumented_field_5'
159
223
  field 6, 'enum', 'undocumented_field_6'
224
+ field 9, 'uint8', 'undocumented_field_9'
160
225
  field 10, 'uint8', 'undocumented_field_10', :array => true
161
226
  field 11, 'enum', 'undocumented_field_11'
162
- field 12, 'uint8', 'undocumented_field_12'
227
+ field 12, 'uint8', 'undocumented_field_12', :array => true
163
228
  field 13, 'enum', 'undocumented_field_13'
229
+ field 15, 'enum', 'undocumented_field_15'
230
+ field 19, 'enum', 'undocumented_field_19', :array => true
164
231
 
165
232
  # Not part of the official ANT SDK doc.
166
233
  message 13, 'undocumented_13'
@@ -198,14 +265,23 @@ module Fit4Ruby
198
265
  field 40, 'enum', 'undocumented_field_40'
199
266
  field 41, 'sint32', 'undocumented_field_41'
200
267
  field 42, 'uint8', 'undocumented_field_42'
268
+ field 43, 'enum', 'undocumented_field_43'
269
+ field 44, 'enum', 'undocumented_field_44'
270
+ field 45, 'enum', 'undocumented_field_45'
201
271
  field 46, 'enum', 'undocumented_field_46'
272
+ field 47, 'enum', 'undocumented_field_47'
273
+ field 48, 'enum', 'undocumented_field_48'
202
274
  field 53, 'enum', 'undocumented_field_53'
203
275
  field 54, 'uint32', 'undocumented_field_54'
204
276
  field 55, 'enum', 'undocumented_field_55'
205
277
  field 57, 'enum', 'undocumented_field_57'
206
278
  field 60, 'enum', 'undocumented_field_60'
279
+ field 62, 'enum', 'undocumented_field_62'
280
+ field 63, 'enum', 'undocumented_field_63'
281
+ field 64, 'uint16', 'undocumented_field_64'
207
282
  field 65, 'enum', 'undocumented_field_65'
208
283
  field 66, 'enum', 'undocumented_field_66'
284
+ field 76, 'enum', 'undocumented_field_76'
209
285
  field 254, 'uint16', 'message_index'
210
286
 
211
287
  message 18, 'session'
@@ -304,10 +380,15 @@ module Fit4Ruby
304
380
  field 121, 'uint16', 'max_power_position', :array => true, :unit => 'watts'
305
381
  field 122, 'uint8', 'avg_cadence_position', :array => true, :unit => 'rpm'
306
382
  field 123, 'uint8', 'max_cadence_position', :array => true, :unit => 'rpm'
383
+ field 124, 'uint32', 'enhanced_avg_speed', :scale => 1000, :unit => 'm/s'
384
+ field 125, 'uint32', 'enhanced_max_speed', :scale => 1000, :unit => 'm/s'
385
+ field 126, 'uint32', 'enhanced_avg_altitude', :scale => 5, :offset => 500, :unit => 'm'
386
+ field 127, 'uint32', 'enhanced_min_altitude', :scale => 5, :offset => 500, :unit => 'm'
387
+ field 128, 'uint32', 'enhanced_max_altitude', :scale => 5, :offset => 500, :unit => 'm'
307
388
  field 132, 'uint16', 'avg_vertical_ratio', :scale => 100, :unit => '%'
308
389
  field 133, 'uint16', 'avg_stance_time_balance', :scale => 100, :unit => '%'
309
- field 134, 'uint16', 'avg_step_length', :scale => 100, :unit => 'mm'
310
- field 137, 'uint8', 'g_effect', :scale => 10
390
+ field 134, 'uint16', 'avg_step_length', :scale => 10, :unit => 'mm'
391
+ field 137, 'uint8', 'total_anaerobic_training_effect', :scale => 10
311
392
  field 138, 'uint8', 'undocumented_field_138'
312
393
  field 150, 'sint8', 'min_temperature', :unit => 'C' # guessed
313
394
  field 151, 'uint16', 'undocumented_field_151'
@@ -316,6 +397,7 @@ module Fit4Ruby
316
397
  field 158, 'uint16', 'undocumented_field_158'
317
398
  field 153, 'enum', 'undocumented_field_153'
318
399
  field 154, 'enum', 'undocumented_field_154'
400
+ field 184, 'enum', 'undocumented_field_184'
319
401
  field 253, 'uint32', 'timestamp', :type => 'date_time'
320
402
  field 254, 'uint16', 'message_index'
321
403
 
@@ -403,9 +485,14 @@ module Fit4Ruby
403
485
  field 107, 'uint16', 'max_power_position', :array => true, :unit => 'watts'
404
486
  field 108, 'uint8', 'avg_cadence_position', :array => true, :unit => 'rpm'
405
487
  field 109, 'uint8', 'max_cadence_position', :array => true, :unit => 'rpm'
406
- field 118, 'uint16', 'vertical_ratio', :scale => 100, :unit => '%' # guessed
407
- field 119, 'uint16', 'avg_gct_balance', :scale => 100, :unit => '%' # guessed
408
- field 120, 'uint16', 'avg_stride_length', :scale => 10000, :unit => 'm' # guessed
488
+ field 110, 'uint32', 'enhanced_avg_speed', :scale => 1000, :unit => 'm/s'
489
+ field 111, 'uint32', 'enhanced_max_speed', :scale => 1000, :unit => 'm/s'
490
+ field 112, 'uint32', 'enhanced_avg_altitude', :scale => 5, :offset => 500, :unit => 'm'
491
+ field 113, 'uint32', 'enhanced_min_altitude', :scale => 5, :offset => 500, :unit => 'm'
492
+ field 114, 'uint32', 'enhanced_max_altitude', :scale => 5, :offset => 500, :unit => 'm'
493
+ field 118, 'uint16', 'avg_vertical_ratio', :scale => 100, :unit => '%'
494
+ field 119, 'uint16', 'avg_stance_time_balance', :scale => 100, :unit => '%'
495
+ field 120, 'uint16', 'avg_step_length', :scale => 10000, :unit => 'm'
409
496
  field 124, 'sint8', 'min_temperature', :unit => 'C' # guessed
410
497
  field 125, 'uint16', 'undocumented_field_125'
411
498
  field 126, 'uint16', 'undocumented_field_126'
@@ -488,6 +575,7 @@ module Fit4Ruby
488
575
  field 'recovery_time', 'uint32', 'recovery_time', :unit => 'min'
489
576
  field 'recovery_info', 'uint32', 'recovery_info', :unit => 'min'
490
577
  field 'vo2max', 'uint32', 'vo2max'
578
+ field 'functional_threshold_power', 'uint32', 'functional_threshold_power', :unit => 'W'
491
579
  field 'lactate_threshold_heart_rate', 'uint32', 'lactate_threshold_heart_rate', :unit => 'bpm'
492
580
  field 'lactate_threshold_speed', 'uint32', 'lactate_threshold_speed', :scale => 1000, :unit => 'm/s'
493
581
  end
@@ -495,6 +583,8 @@ module Fit4Ruby
495
583
  field 14, 'enum', 'undocumented_field_14'
496
584
  field 15, 'uint32', 'undocumented_field_15'
497
585
  field 16, 'enum', 'undocumented_field_16'
586
+ field 19, 'uint8', 'undocumented_field_19'
587
+ field 20, 'uint8', 'undocumented_field_20'
498
588
  field 253, 'uint32', 'timestamp', :type => 'date_time'
499
589
 
500
590
  # Possibly which device is used as metering source.
@@ -642,7 +732,7 @@ module Fit4Ruby
642
732
 
643
733
  # Not part of the official ANT SDK doc
644
734
  message 79, 'user_data'
645
- field 0, 'uint16', 'metmax', :scale => 1000, :unit => 'MET' # VO2max / 3.5
735
+ field 0, 'uint16', 'metmax', :scale => 1024, :unit => 'MET' # VO2max / 3.5
646
736
  field 1, 'uint8', 'age', :unit => 'years'
647
737
  field 2, 'uint8', 'height', :scale => 100, :unit => 'm'
648
738
  field 3, 'uint16', 'weight', :scale => 10, :unit => 'kg'
@@ -652,9 +742,9 @@ module Fit4Ruby
652
742
  field 7, 'sint8', 'undocumented_field_7' # seems to be always 1
653
743
  field 8, 'uint16', 'recovery_time', :scale => 60, :unit => 'hours'
654
744
  field 9, 'uint16', 'undocumented_field_9' # maybe activity measurement
655
- field 10, 'uint8', 'undocumented_field_10'
745
+ field 10, 'uint8', 'avg_resting_heart_rate', :unit => 'bpm'
656
746
  field 11, 'uint16', 'running_lactate_threshold_heart_rate', :unit => 'bpm'
657
- field 12, 'uint16', 'undocumented_field_12'
747
+ field 12, 'uint16', 'functional_threshold_power', :unit => 'W'
658
748
  field 13, 'uint16', 'undocumented_field_13'
659
749
  field 14, 'uint8', 'undocumented_field_14'
660
750
  field 15, 'uint8', 'undocumented_field_15'
@@ -722,18 +812,18 @@ module Fit4Ruby
722
812
  # All known fields so far seem to be physiological values. We'll use the
723
813
  # name physiological_metrics for now.
724
814
  message 140, 'physiological_metrics'
725
- field 0, 'uint8', 'max_heart_rate', :unit => 'bpm'
726
- field 1, 'uint8', 'undocumented_field_1'
815
+ field 0, 'uint8', 'min_heart_rate', :unit => 'bpm'
816
+ field 1, 'uint8', 'max_heart_rate', :unit => 'bpm'
727
817
  field 2, 'sint32', 'undocumented_field_2'
728
818
  field 3, 'sint32', 'undocumented_field_3'
729
819
  field 4, 'uint8', 'aerobic_training_effect', :scale => 10
730
820
  field 5, 'sint32', 'undocumented_field_5'
731
821
  field 6, 'sint32', 'undocumented_field_6'
732
- field 7, 'sint32', 'undocumented_field_7'
822
+ field 7, 'sint32', 'metmax', :scale => 65536, :unit => 'MET'
733
823
  # Field 8 used to be uint8 but recent devices use sint8. We model this
734
824
  # with an alt_field. The switch field is randomly picked as we have no
735
825
  # details why the type has been changed.
736
- alt_field 8, 'undocumented_field_1' do
826
+ alt_field 8, 'max_heart_rate' do
737
827
  field :default, 'sint8', 'undocumented_field_8s'
738
828
  field 255, 'uint8', 'undocumented_field_8u'
739
829
  end
@@ -755,9 +845,10 @@ module Fit4Ruby
755
845
  field 24, 'sint32', 'undocumented_field_24'
756
846
  field 25, 'uint8', 'undocumented_field_25'
757
847
  field 26, 'sint32', 'undocumented_field_26'
758
- field 29, 'sint32', 'undocumented_field_29'
848
+ field 29, 'sint32', 'metmax_running', :scale => 65536, :unit => 'MET'
759
849
  field 34, 'enum', 'undocumented_field_34'
760
850
  field 35, 'uint32', 'undocumented_field_35'
851
+ field 36, 'uint32', 'undocumented_field_36'
761
852
  field 253, 'uint32', 'timestamp', :type => 'date_time'
762
853
 
763
854
  # Not part of the official ANT SDK doc. The message name is guessed and
@@ -824,6 +915,9 @@ module Fit4Ruby
824
915
  field 58, 'enum', 'undocumented_field_58'
825
916
  field 59, 'uint8', 'undocumented_field_59'
826
917
  field 62, 'uint8', 'undocumented_field_62'
918
+ field 63, 'enum', 'undocumented_field_63'
919
+ field 64, 'uint32', 'undocumented_field_64'
920
+ field 65, 'uint32', 'undocumented_field_65'
827
921
  field 254, 'uint16', 'message_index'
828
922
 
829
923
  # Not part of the official ANT SDK doc.
@@ -881,6 +975,74 @@ module Fit4Ruby
881
975
  field 1, 'uint32', 'stress_level_time', :type => 'date_time'
882
976
  field 2, 'sint8', 'undocumented_field_2'
883
977
 
978
+ # Not part of the official ANT SDK doc.
979
+ message 229, 'undocumented_229'
980
+ field 0, 'uint32', 'time', :type => 'date_time'
981
+ field 1, 'sint32', 'metmax', :scale => 65536, :unit => 'MET'
982
+ field 2, 'uint16', 'vo2max', :scale => 10, :unit => 'ml/kg/min'
983
+ field 3, 'sint8', 'undocumented_field_3'
984
+ field 4, 'sint8', 'undocumented_field_4'
985
+ field 5, 'enum', 'undocumented_field_5'
986
+ field 6, 'enum', 'undocumented_field_6'
987
+ field 7, 'enum', 'undocumented_field_7'
988
+ field 8, 'enum', 'undocumented_field_8'
989
+ field 9, 'enum', 'undocumented_field_9'
990
+
991
+ # Not part of the official ANT SDK doc.
992
+ message 232, 'training_status'
993
+ field 0, 'enum', 'undocumented_0'
994
+ field 1, 'enum', 'undocumented_1'
995
+ field 2, 'enum', 'current_status', :dict => 'training_status'
996
+ field 3, 'enum', 'fitness', :dict => 'training_status_trend'
997
+ field 4, 'enum', 'load', :dict => 'training_status_trend'
998
+ field 5, 'uint16', 'training_load'
999
+ field 6, 'uint16', 'low_training_load'
1000
+ field 7, 'uint16', 'high_training_load'
1001
+ field 8, 'uint16', 'max_training_load'
1002
+ field 253, 'uint32', 'timestamp', :type => 'date_time'
1003
+
1004
+ # Not part of the official ANT SDK doc.
1005
+ message 233, 'undocumented_233'
1006
+ field 2, 'byte', 'undocumented_field_2'
1007
+
1008
+ # Not part of the official ANT SDK doc.
1009
+ message 241, 'metrics'
1010
+ field 0, 'uint32', 'localtime', :type => 'date_time'
1011
+ field 253, 'uint32', 'timestamp', :type => 'date_time'
1012
+
1013
+ # Not part of the official ANT SDK doc.
1014
+ message 243, 'media_player_info'
1015
+ field 0, 'uint32', 'undocumented_field_0'
1016
+ field 1, 'uint16', 'undocumented_field_1'
1017
+ field 2, 'string', 'track_1'
1018
+ field 3, 'string', 'track_2'
1019
+ field 4, 'string', 'track_3'
1020
+ field 5, 'uint16', 'undocumented_field_5'
1021
+ field 6, 'uint16', 'undocumented_field_6'
1022
+
1023
+ # Not part of the official ANT SDK doc.
1024
+ message 244, 'undocumented_244'
1025
+ field 0, 'uint32', 'undocumented_field_0'
1026
+ field 1, 'enum', 'undocumented_field_1'
1027
+ field 2, 'uint16', 'undocumented_field_2'
1028
+
1029
+ # Not part of the official ANT SDK doc.
1030
+ message 269, 'undocumented_269'
1031
+ field 0, 'uint8', 'undocumented_field_0'
1032
+ field 1, 'uint8', 'undocumented_field_1'
1033
+ field 253, 'uint32', 'timestamp', :type => 'date_time'
1034
+
1035
+ # Not part of the official ANT SDK doc.
1036
+ message 279, 'undocumented_279'
1037
+ field 0, 'uint32', 'undocumented_field_0'
1038
+ field 253, 'uint32', 'timestamp', :type => 'date_time'
1039
+
1040
+ # Not part of the official ANT SDK doc.
1041
+ message 284, 'training_load'
1042
+ field 0, 'uint16', 'load'
1043
+ field 1, 'uint32', 'timestamp', :type => 'date_time'
1044
+
1045
+ # Not part of the official ANT SDK doc.
884
1046
  message 1024, 'undocumented_1024'
885
1047
  field 0, 'enum', 'undocumented_field_0'
886
1048
  field 2, 'enum', 'undocumented_field_2'
@@ -890,10 +1052,6 @@ module Fit4Ruby
890
1052
  field 247, 'enum', 'undocumented_field_247'
891
1053
  field 255, 'enum', 'undocumented_field_255'
892
1054
 
893
- # Not part of the official ANT SDK doc.
894
- message 233, 'undocumented_233'
895
- field 2, 'byte', 'undocumented_field_2'
896
-
897
1055
  end
898
1056
 
899
1057
  end
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = Metrics.rb -- Fit4Ruby - FIT file processing library for Ruby
5
+ #
6
+ # Copyright (c) 2018 by Chris Schlaeger <cs@taskjuggler.org>
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of version 2 of the GNU General Public License as
10
+ # published by the Free Software Foundation.
11
+ #
12
+
13
+ require 'fit4ruby/FitDataRecord'
14
+ require 'fit4ruby/FileId'
15
+ require 'fit4ruby/FileCreator'
16
+ require 'fit4ruby/DeviceInfo'
17
+ require 'fit4ruby/TrainingStatus'
18
+
19
+ module Fit4Ruby
20
+
21
+ # The Metrics object is a FIT file class. It's a top-level object that
22
+ # holds all references to other FIT records that are part of the FIT file.
23
+ # Each of the objects it references are direct equivalents of the message
24
+ # record structures used in the FIT file.
25
+ #
26
+ # This is not part of the officially documented FIT API. Names may change in
27
+ # the future if the real Garmin names get known.
28
+ class Metrics < FitDataRecord
29
+
30
+ attr_accessor :field_descriptions, :file_id, :file_creator, :device_infos
31
+
32
+ # Create a new Metrics object.
33
+ # @param field_values [Hash] A Hash that provides initial values for
34
+ # certain fields of the FitDataRecord.
35
+ def initialize(field_values = {})
36
+ super('metrics')
37
+
38
+ @field_descriptions = []
39
+
40
+ @file_id = FileId.new
41
+ @device_infos = []
42
+ @file_creator = nil
43
+ @training_statuses = []
44
+ end
45
+
46
+ # Perform some basic logical checks on the object and all references sub
47
+ # objects. Any errors will be reported via the Log object.
48
+ def check
49
+ end
50
+
51
+ # Create a new FitDataRecord.
52
+ # @param record_type [String] Type that identifies the FitDataRecord
53
+ # derived class to create.
54
+ # @param field_values [Hash] A Hash that provides initial values for
55
+ # certain fields of the FitDataRecord.
56
+ # @return FitDataRecord
57
+ def new_fit_data_record(record_type, field_values = {})
58
+ case record_type
59
+ when 'file_id'
60
+ @file_id = (record = FileId.new(field_values))
61
+ when 'file_creator'
62
+ @software = (record = FileCreator.new(field_values))
63
+ when 'device_info'
64
+ @device_infos << (record = DeviceInfo.new(field_values))
65
+ when 'training_status'
66
+ @training_statuses << (record = TrainingStatus.new(field_values))
67
+ else
68
+ record = nil
69
+ end
70
+
71
+ record
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+
78
+
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = TrainingStatus.rb -- Fit4Ruby - FIT file processing library for Ruby
5
+ #
6
+ # Copyright (c) 2018 by Chris Schlaeger <cs@taskjuggler.org>
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of version 2 of the GNU General Public License as
10
+ # published by the Free Software Foundation.
11
+ #
12
+
13
+ require 'fit4ruby/FitDataRecord'
14
+
15
+ module Fit4Ruby
16
+
17
+ # This class corresponds to the training_status message.
18
+ #
19
+ # This is not part of the officially documented FIT API. Names may change in
20
+ # the future if the real Garmin names get known.
21
+ class TrainingStatus < FitDataRecord
22
+
23
+ def initialize(field_values = {})
24
+ super('training_status')
25
+ set_field_values(field_values)
26
+ end
27
+
28
+ # Ensure that FitDataRecords have a deterministic sequence. Device infos
29
+ # are sorted by device_index.
30
+ def <=>(fdr)
31
+ @timestamp == fdr.timestamp ?
32
+ @message.name == fdr.message.name ?
33
+ @device_index <=> fdr.device_index :
34
+ RecordOrder.index(@message.name) <=>
35
+ RecordOrder.index(fdr.message.name) :
36
+ @timestamp <=> fdr.timestamp
37
+ end
38
+
39
+ def check(index)
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+
46
+
@@ -1,4 +1,4 @@
1
1
  module Fit4Ruby
2
2
  # The version number of the library.
3
- VERSION = '3.1.0'
3
+ VERSION = '3.2.0'
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fit4ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Schlaeger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-17 00:00:00.000000000 Z
11
+ date: 2019-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bindata
@@ -119,6 +119,7 @@ files:
119
119
  - lib/fit4ruby/HeartRateZones.rb
120
120
  - lib/fit4ruby/Lap.rb
121
121
  - lib/fit4ruby/Log.rb
122
+ - lib/fit4ruby/Metrics.rb
122
123
  - lib/fit4ruby/Monitoring.rb
123
124
  - lib/fit4ruby/MonitoringInfo.rb
124
125
  - lib/fit4ruby/Monitoring_B.rb
@@ -129,6 +130,7 @@ files:
129
130
  - lib/fit4ruby/SensorSettings.rb
130
131
  - lib/fit4ruby/Session.rb
131
132
  - lib/fit4ruby/Software.rb
133
+ - lib/fit4ruby/TrainingStatus.rb
132
134
  - lib/fit4ruby/UserData.rb
133
135
  - lib/fit4ruby/UserProfile.rb
134
136
  - lib/fit4ruby/version.rb