fit4ruby 3.1.0 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/fit4ruby/Activity.rb +1 -1
- data/lib/fit4ruby/FieldDescription.rb +4 -2
- data/lib/fit4ruby/FitDeveloperDataFieldDefinition.rb +39 -5
- data/lib/fit4ruby/FitFileEntity.rb +4 -0
- data/lib/fit4ruby/FitMessageRecord.rb +34 -1
- data/lib/fit4ruby/GlobalFitDictionaries.rb +27 -0
- data/lib/fit4ruby/GlobalFitMessages.rb +178 -20
- data/lib/fit4ruby/Metrics.rb +78 -0
- data/lib/fit4ruby/TrainingStatus.rb +46 -0
- data/lib/fit4ruby/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 247b4e5fd81ffc3c5e12bc1d3235196126fdb8cc
|
4
|
+
data.tar.gz: b493e5b073e63d977ed28edc3600dac73519d0b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 88b2fe75bdf8a1bfb4a6f3d4892db4253f942a3a251118fc054f4671f9f3927960552fe9005334da6f884e95990babae029071edbf287740efaff2450748824b
|
7
|
+
data.tar.gz: f8aa4152a1d37f682d0ca526045d10a19628ba79bad41eebbf3b3e3e963fcb971fc82d38fef8756b2bfa50eaefd3eea80388c849cb1bc0bf34aa79d64754e7eb
|
data/lib/fit4ruby/Activity.rb
CHANGED
@@ -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
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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', '
|
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 =>
|
310
|
-
field 137, 'uint8', '
|
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
|
407
|
-
field
|
408
|
-
field
|
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 =>
|
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', '
|
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', '
|
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', '
|
726
|
-
field 1, 'uint8', '
|
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', '
|
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, '
|
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', '
|
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
|
+
|
data/lib/fit4ruby/version.rb
CHANGED
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.
|
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:
|
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
|