fit4ruby 3.7.0 → 3.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/fit4ruby.gemspec +2 -2
- data/lib/fit4ruby/Activity.rb +118 -55
- data/lib/fit4ruby/BDFieldNameTranslator.rb +36 -0
- data/lib/fit4ruby/FDR_DevField_Extension.rb +81 -0
- data/lib/fit4ruby/FieldDescription.rb +22 -10
- data/lib/fit4ruby/FileId.rb +2 -1
- data/lib/fit4ruby/FitDataRecord.rb +84 -31
- data/lib/fit4ruby/FitDefinition.rb +11 -4
- data/lib/fit4ruby/FitDefinitionField.rb +4 -4
- data/lib/fit4ruby/FitDefinitionFieldBase.rb +15 -6
- data/lib/fit4ruby/FitDeveloperDataFieldDefinition.rb +1 -1
- data/lib/fit4ruby/FitFile.rb +2 -0
- data/lib/fit4ruby/FitMessageRecord.rb +23 -18
- data/lib/fit4ruby/FitRecord.rb +2 -1
- data/lib/fit4ruby/FitTypeDefs.rb +2 -2
- data/lib/fit4ruby/GlobalFitDictionaries.rb +197 -2
- data/lib/fit4ruby/GlobalFitMessage.rb +79 -14
- data/lib/fit4ruby/GlobalFitMessages.rb +52 -6
- data/lib/fit4ruby/Lap.rb +10 -1
- data/lib/fit4ruby/Record.rb +11 -2
- data/lib/fit4ruby/Workout.rb +31 -0
- data/lib/fit4ruby/WorkoutStep.rb +32 -0
- data/lib/fit4ruby/version.rb +1 -1
- data/spec/FitFile_spec.rb +198 -100
- metadata +16 -13
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
# = GlobalFitDictionaries.rb -- Fit4Ruby - FIT file processing library for Ruby
|
5
5
|
#
|
6
|
-
# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org>
|
6
|
+
# Copyright (c) 2014, 2021 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
|
@@ -23,7 +23,50 @@ module Fit4Ruby
|
|
23
23
|
entry 3, 'transition'
|
24
24
|
entry 4, 'fitness_equipment'
|
25
25
|
entry 5, 'swimming'
|
26
|
-
entry 6, '
|
26
|
+
entry 6, 'basketball'
|
27
|
+
entry 7, 'soccer'
|
28
|
+
entry 8, 'tennis'
|
29
|
+
entry 9, 'american_football'
|
30
|
+
entry 10, 'training'
|
31
|
+
entry 11, 'walking'
|
32
|
+
entry 12, 'cross_country_skiing'
|
33
|
+
entry 13, 'alpine_skiing'
|
34
|
+
entry 14, 'snowboarding'
|
35
|
+
entry 15, 'rowing'
|
36
|
+
entry 16, 'mountaineering'
|
37
|
+
entry 17, 'hiking'
|
38
|
+
entry 18, 'multisport'
|
39
|
+
entry 19, 'paddling'
|
40
|
+
entry 20, 'flying'
|
41
|
+
entry 21, 'e_biking'
|
42
|
+
entry 22, 'motorcycling'
|
43
|
+
entry 23, 'boating'
|
44
|
+
entry 24, 'driving'
|
45
|
+
entry 25, 'golf'
|
46
|
+
entry 26, 'hang_gliding'
|
47
|
+
entry 27, 'horseback_riding'
|
48
|
+
entry 28, 'hunting'
|
49
|
+
entry 29, 'fishing'
|
50
|
+
entry 30, 'inline_skating'
|
51
|
+
entry 31, 'rock_climbing'
|
52
|
+
entry 32, 'sailing'
|
53
|
+
entry 33, 'ice_skating'
|
54
|
+
entry 34, 'sky_diving'
|
55
|
+
entry 35, 'snowshoeing'
|
56
|
+
entry 36, 'snowmobiling'
|
57
|
+
entry 37, 'stand_up_paddleboarding'
|
58
|
+
entry 38, 'surfing'
|
59
|
+
entry 39, 'wakeboarding'
|
60
|
+
entry 40, 'water_skiing'
|
61
|
+
entry 41, 'kayaking'
|
62
|
+
entry 42, 'rafting'
|
63
|
+
entry 43, 'windsurfing'
|
64
|
+
entry 44, 'kitesurfing'
|
65
|
+
entry 45, 'tactical'
|
66
|
+
entry 46, 'jumpmaster'
|
67
|
+
entry 47, 'boxing'
|
68
|
+
entry 48, 'floor_climbing'
|
69
|
+
entry 53, 'diving'
|
27
70
|
entry 254, 'all'
|
28
71
|
|
29
72
|
dict 'activity_level'
|
@@ -51,6 +94,52 @@ module Fit4Ruby
|
|
51
94
|
entry 16, 'stair_climbing'
|
52
95
|
entry 17, 'lap_swimming'
|
53
96
|
entry 18, 'open_water'
|
97
|
+
entry 19, 'flexibility_training'
|
98
|
+
entry 20, 'strength_training'
|
99
|
+
entry 21, 'warm_up'
|
100
|
+
entry 22, 'match'
|
101
|
+
entry 23, 'exercise'
|
102
|
+
entry 24, 'challenge'
|
103
|
+
entry 25, 'indoor_skiing'
|
104
|
+
entry 26, 'cardio_training'
|
105
|
+
entry 27, 'indoor_walking'
|
106
|
+
entry 28, 'e_bike_fitness'
|
107
|
+
entry 29, 'bmx'
|
108
|
+
entry 30, 'casual_walking'
|
109
|
+
entry 31, 'speed_walking'
|
110
|
+
entry 32, 'bike_to_run_transition'
|
111
|
+
entry 33, 'run_to_bike_transition'
|
112
|
+
entry 34, 'swim_to_bike_transition'
|
113
|
+
entry 35, 'atv'
|
114
|
+
entry 36, 'motocross'
|
115
|
+
entry 37, 'backcountry'
|
116
|
+
entry 38, 'resort'
|
117
|
+
entry 39, 'rc_drone'
|
118
|
+
entry 40, 'wingsuit'
|
119
|
+
entry 41, 'whitewater'
|
120
|
+
entry 42, 'skate_skiing'
|
121
|
+
entry 43, 'yoga'
|
122
|
+
entry 44, 'pilates'
|
123
|
+
entry 45, 'indoor_running'
|
124
|
+
entry 46, 'gravel_cycling'
|
125
|
+
entry 47, 'e_bike_mountain'
|
126
|
+
entry 48, 'commuting'
|
127
|
+
entry 49, 'mixed_surface'
|
128
|
+
entry 50, 'navigate'
|
129
|
+
entry 51, 'track_me'
|
130
|
+
entry 52, 'map'
|
131
|
+
entry 53, 'single_gas_diving'
|
132
|
+
entry 54, 'multi_gas_diving'
|
133
|
+
entry 55, 'gauge_diving'
|
134
|
+
entry 56, 'apnea_diving'
|
135
|
+
entry 57, 'apnea_hunting'
|
136
|
+
entry 58, 'virtual_activity'
|
137
|
+
entry 59, 'obstacle'
|
138
|
+
entry 62, 'breathing'
|
139
|
+
entry 65, 'sail_race'
|
140
|
+
entry 67, 'ultra'
|
141
|
+
entry 68, 'indoor_climbing'
|
142
|
+
entry 69, 'bouldering'
|
54
143
|
entry 254, 'all'
|
55
144
|
|
56
145
|
dict 'ant_network'
|
@@ -625,6 +714,9 @@ module Fit4Ruby
|
|
625
714
|
entry 1, 'rest'
|
626
715
|
entry 2, 'warmup'
|
627
716
|
entry 3, 'cooldown'
|
717
|
+
entry 4, 'recovery'
|
718
|
+
entry 5, 'interval'
|
719
|
+
entry 6, 'other'
|
628
720
|
|
629
721
|
dict 'hr_zone_calc'
|
630
722
|
entry 0, 'custom'
|
@@ -844,6 +936,36 @@ module Fit4Ruby
|
|
844
936
|
entry 17, 'hiking'
|
845
937
|
entry 18, 'multisport'
|
846
938
|
entry 19, 'paddling'
|
939
|
+
entry 20, 'flying'
|
940
|
+
entry 21, 'e_biking'
|
941
|
+
entry 22, 'motorcycling'
|
942
|
+
entry 23, 'boating'
|
943
|
+
entry 24, 'driving'
|
944
|
+
entry 25, 'golf'
|
945
|
+
entry 26, 'hang_gliding'
|
946
|
+
entry 27, 'horseback_riding'
|
947
|
+
entry 28, 'hunting'
|
948
|
+
entry 29, 'fishing'
|
949
|
+
entry 30, 'inline_skating'
|
950
|
+
entry 31, 'rock_climbing'
|
951
|
+
entry 32, 'sailing'
|
952
|
+
entry 33, 'ice_skating'
|
953
|
+
entry 34, 'sky_diving'
|
954
|
+
entry 35, 'snowshoeing'
|
955
|
+
entry 36, 'snowmobiling'
|
956
|
+
entry 37, 'stand_up_paddleboarding'
|
957
|
+
entry 38, 'surfing'
|
958
|
+
entry 39, 'wakeboarding'
|
959
|
+
entry 40, 'water_skiing'
|
960
|
+
entry 41, 'kayaking'
|
961
|
+
entry 42, 'rafting'
|
962
|
+
entry 43, 'windsurfing'
|
963
|
+
entry 44, 'kitesurfing'
|
964
|
+
entry 45, 'tactical'
|
965
|
+
entry 46, 'jumpmaster'
|
966
|
+
entry 47, 'boxing'
|
967
|
+
entry 48, 'floor_climbing'
|
968
|
+
entry 53, 'diving'
|
847
969
|
entry 254, 'all'
|
848
970
|
|
849
971
|
dict 'swim_stroke'
|
@@ -934,6 +1056,79 @@ module Fit4Ruby
|
|
934
1056
|
entry 2, 'maintaining'
|
935
1057
|
entry 3, 'up'
|
936
1058
|
|
1059
|
+
dict 'wkt_step_duration'
|
1060
|
+
entry 0, 'time'
|
1061
|
+
entry 1, 'distance'
|
1062
|
+
entry 2, 'hr_less_than'
|
1063
|
+
entry 3, 'hr_greater_than'
|
1064
|
+
entry 4, 'calories'
|
1065
|
+
entry 5, 'open'
|
1066
|
+
entry 6, 'repeat_until_steps_cmplt'
|
1067
|
+
entry 7, 'repeat_until_time'
|
1068
|
+
entry 8, 'repeat_until_distance'
|
1069
|
+
entry 9, 'repeat_until_calories'
|
1070
|
+
entry 10, 'repeat_until_hr_less_than'
|
1071
|
+
entry 11, 'repeat_until_hr_greater_than'
|
1072
|
+
entry 12, 'repeat_until_power_less_than'
|
1073
|
+
entry 13, 'repeat_until_power_greater_than'
|
1074
|
+
entry 14, 'power_less_than'
|
1075
|
+
entry 15, 'power_greater_than'
|
1076
|
+
entry 16, 'training_peaks_tss'
|
1077
|
+
entry 17, 'repeat_until_power_last_lap_less_than'
|
1078
|
+
entry 18, 'repeat_until_max_power_last_lap_less_than'
|
1079
|
+
entry 19, 'power_3s_less_than'
|
1080
|
+
entry 20, 'power_10s_less_than'
|
1081
|
+
entry 21, 'power_30s_less_than'
|
1082
|
+
entry 22, 'power_3s_greater_than'
|
1083
|
+
entry 23, 'power_10s_greater_than'
|
1084
|
+
entry 24, 'power_30s_greater_than'
|
1085
|
+
entry 25, 'power_lap_less_than'
|
1086
|
+
entry 26, 'power_lap_greater_than'
|
1087
|
+
entry 27, 'repeat_until_training_peaks_tss'
|
1088
|
+
entry 28, 'repetition_time'
|
1089
|
+
entry 29, 'reps'
|
1090
|
+
entry 31, 'time_only'
|
1091
|
+
|
1092
|
+
dict 'wkt_step_target'
|
1093
|
+
entry 0, 'speed'
|
1094
|
+
entry 1, 'heart_rate'
|
1095
|
+
entry 2, 'open'
|
1096
|
+
entry 3, 'cadence'
|
1097
|
+
entry 4, 'power'
|
1098
|
+
entry 5, 'grade'
|
1099
|
+
entry 6, 'resistance'
|
1100
|
+
entry 7, 'power_3s'
|
1101
|
+
entry 8, 'power_10s'
|
1102
|
+
entry 9, 'power_30s'
|
1103
|
+
entry 10, 'power_lap'
|
1104
|
+
entry 11, 'swim_stroke'
|
1105
|
+
entry 12, 'speed_lap'
|
1106
|
+
entry 13, 'heart_rate_lap'
|
1107
|
+
|
1108
|
+
dict 'workout_capabilities'
|
1109
|
+
entry 0x1, 'interval'
|
1110
|
+
entry 0x2, 'custom'
|
1111
|
+
entry 0x4, 'fitness_equipment'
|
1112
|
+
entry 0x8, 'firstbeat'
|
1113
|
+
entry 0x10, 'new_leaf'
|
1114
|
+
entry 0x20, 'tcx'
|
1115
|
+
entry 0x80, 'speed'
|
1116
|
+
entry 0x100, 'heart_rate'
|
1117
|
+
entry 0x200, 'distance'
|
1118
|
+
entry 0x400, 'cadence'
|
1119
|
+
entry 0x800, 'power'
|
1120
|
+
entry 0x1000, 'grade'
|
1121
|
+
entry 0x2000, 'resistance'
|
1122
|
+
entry 0x4000, 'protected'
|
1123
|
+
|
1124
|
+
dict 'workout_equipment'
|
1125
|
+
entry 0, 'none'
|
1126
|
+
entry 1, 'swim_fins'
|
1127
|
+
entry 2, 'swim_kickboard'
|
1128
|
+
entry 3, 'swim_paddles'
|
1129
|
+
entry 4, 'swim_pull_buoy'
|
1130
|
+
entry 5, 'swim_snorkel'
|
1131
|
+
|
937
1132
|
end
|
938
1133
|
|
939
1134
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
# = GlobalFitMessage.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, 2020 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
|
@@ -21,7 +21,8 @@ module Fit4Ruby
|
|
21
21
|
# the data fields of the message.
|
22
22
|
class GlobalFitMessage
|
23
23
|
|
24
|
-
attr_reader :name, :number, :fields_by_name, :fields_by_number
|
24
|
+
attr_reader :name, :number, :fields_by_name, :fields_by_number,
|
25
|
+
:field_values_by_name
|
25
26
|
|
26
27
|
# The Field objects describe the name, type and optional attributes of a
|
27
28
|
# FitMessage definition field. It also provides methods to convert field
|
@@ -38,8 +39,21 @@ module Fit4Ruby
|
|
38
39
|
@opts = opts
|
39
40
|
end
|
40
41
|
|
42
|
+
def is_undefined?(value)
|
43
|
+
value == FitDefinitionFieldBase.undefined_value(@type)
|
44
|
+
end
|
45
|
+
|
46
|
+
def is_string?
|
47
|
+
@type == 'string'
|
48
|
+
end
|
49
|
+
|
50
|
+
def is_array?
|
51
|
+
@opts[:array] == true
|
52
|
+
end
|
53
|
+
|
41
54
|
def to_machine(value)
|
42
|
-
return nil if value.nil?
|
55
|
+
return nil if value.nil? ||
|
56
|
+
value == FitDefinitionFieldBase.undefined_value(@type)
|
43
57
|
|
44
58
|
if @opts.include?(:dict) &&
|
45
59
|
(dict = GlobalFitDictionaries[@opts[:dict]])
|
@@ -51,6 +65,13 @@ module Fit4Ruby
|
|
51
65
|
value *= 180.0 / 2147483648
|
52
66
|
when 'date_time'
|
53
67
|
value = fit_time_to_time(value)
|
68
|
+
when 'float'
|
69
|
+
if value >= 4294967295.0
|
70
|
+
return nil
|
71
|
+
end
|
72
|
+
end
|
73
|
+
if value.is_a?(Float) && value >= 4294967295.0
|
74
|
+
return nil
|
54
75
|
end
|
55
76
|
value /= @opts[:scale].to_f if @opts[:scale]
|
56
77
|
value -= @opts[:offset] if @opts[:offset]
|
@@ -133,7 +154,7 @@ module Fit4Ruby
|
|
133
154
|
value
|
134
155
|
end
|
135
156
|
|
136
|
-
def to_s(value)
|
157
|
+
def to_s(value = nil)
|
137
158
|
return "[no value]" if value.nil?
|
138
159
|
|
139
160
|
human_readable = to_human(value)
|
@@ -167,7 +188,7 @@ module Fit4Ruby
|
|
167
188
|
|
168
189
|
def field(ref_value, type, name, opts = {})
|
169
190
|
field = Field.new(type, name, opts)
|
170
|
-
if ref_value.respond_to?(
|
191
|
+
if ref_value.respond_to?(:each)
|
171
192
|
ref_value.each do |rv|
|
172
193
|
@fields[rv] = field
|
173
194
|
end
|
@@ -180,13 +201,13 @@ module Fit4Ruby
|
|
180
201
|
# Select the alternative field based on the actual field values of the
|
181
202
|
# FitMessageRecord.
|
182
203
|
def select(field_values_by_name)
|
183
|
-
unless (
|
204
|
+
unless (value_of_referenced_field = field_values_by_name[@ref_field])
|
184
205
|
Log.fatal "The selection field #{@ref_field} for the alternative " +
|
185
206
|
"field is undefined in global message #{@message.name}: " +
|
186
207
|
field_values_by_name.inspect
|
187
208
|
end
|
188
209
|
@fields.each do |ref_value, field|
|
189
|
-
return field if ref_value ==
|
210
|
+
return field if ref_value == value_of_referenced_field
|
190
211
|
end
|
191
212
|
return @fields[:default] if @fields[:default]
|
192
213
|
|
@@ -199,7 +220,7 @@ module Fit4Ruby
|
|
199
220
|
# Create a new GlobalFitMessage definition.
|
200
221
|
# @param name [String] name of the FIT message
|
201
222
|
# @param number [Fixnum] global message number
|
202
|
-
def initialize(name, number)
|
223
|
+
def initialize(name, number, field_values_by_name = {})
|
203
224
|
@name = name
|
204
225
|
@number = number
|
205
226
|
# Field names must be unique. A name always matches a single Field.
|
@@ -207,13 +228,57 @@ module Fit4Ruby
|
|
207
228
|
# Field numbers are not unique. A group of alternative fields shares the
|
208
229
|
# same number and is stored as an AltField. Otherwise as Field.
|
209
230
|
@fields_by_number = {}
|
231
|
+
# To generate the proper definition message we need to know the length
|
232
|
+
# of String and Array fields. This is only needed when writing FIT
|
233
|
+
# files.
|
234
|
+
@field_values_by_name = field_values_by_name
|
210
235
|
end
|
211
236
|
|
212
237
|
# Two GlobalFitMessage objects are considered equal if they have the same
|
213
|
-
# number, name and list of named fields.
|
238
|
+
# number, name and list of named fields. In case they have String or Array
|
239
|
+
# values, they must have identical size.
|
214
240
|
def ==(m)
|
215
|
-
@number == m.number && @name == m.name &&
|
216
|
-
|
241
|
+
unless @number == m.number && @name == m.name &&
|
242
|
+
@fields_by_name.keys.sort == m.fields_by_name.keys.sort
|
243
|
+
return false
|
244
|
+
end
|
245
|
+
|
246
|
+
unless @field_values_by_name.size == m.field_values_by_name.size
|
247
|
+
return false
|
248
|
+
end
|
249
|
+
|
250
|
+
unless @field_values_by_name.empty?
|
251
|
+
@field_values_by_name.keys.each do |name|
|
252
|
+
a = @field_values_by_name[name]
|
253
|
+
b = m.field_values_by_name[name]
|
254
|
+
if a.class != b.class
|
255
|
+
return false
|
256
|
+
end
|
257
|
+
if a.is_a?(String)
|
258
|
+
if a.bytes.length != b.bytes.length
|
259
|
+
return false
|
260
|
+
end
|
261
|
+
elsif a.is_a?(Array)
|
262
|
+
if a.length != b.length
|
263
|
+
return false
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
true
|
270
|
+
end
|
271
|
+
|
272
|
+
def each_field(field_values)
|
273
|
+
@fields_by_number.each do |number, field|
|
274
|
+
if field.is_a?(AltField)
|
275
|
+
# For alternative fields, we need to look at the value of the
|
276
|
+
# selector field and pick the corresponding Field.
|
277
|
+
field = field.select(field_values)
|
278
|
+
end
|
279
|
+
|
280
|
+
yield(number, field)
|
281
|
+
end
|
217
282
|
end
|
218
283
|
|
219
284
|
# Define a new Field for this message definition.
|
@@ -255,7 +320,7 @@ module Fit4Ruby
|
|
255
320
|
end
|
256
321
|
|
257
322
|
def construct(field_values_by_name)
|
258
|
-
gfm = GlobalFitMessage.new(@name, @number)
|
323
|
+
gfm = GlobalFitMessage.new(@name, @number, field_values_by_name)
|
259
324
|
|
260
325
|
@fields_by_number.each do |number, field|
|
261
326
|
if field.is_a?(AltField)
|
@@ -269,7 +334,7 @@ module Fit4Ruby
|
|
269
334
|
gfm
|
270
335
|
end
|
271
336
|
|
272
|
-
def write(io, local_message_type
|
337
|
+
def write(io, local_message_type)
|
273
338
|
header = FitRecordHeader.new
|
274
339
|
header.normal = 0
|
275
340
|
header.message_type = 1
|
@@ -278,7 +343,7 @@ module Fit4Ruby
|
|
278
343
|
|
279
344
|
definition = FitDefinition.new
|
280
345
|
definition.global_message_number = @number
|
281
|
-
definition.setup(
|
346
|
+
definition.setup(self, @field_values_by_name)
|
282
347
|
definition.write(io)
|
283
348
|
end
|
284
349
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
# = GlobalFitMessages.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, 2020, 2021 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
|
@@ -461,19 +461,23 @@ module Fit4Ruby
|
|
461
461
|
field 169, 'uint16', 'undocumented_field_169'
|
462
462
|
field 170, 'uint16', 'undocumented_field_170'
|
463
463
|
field 177, 'uint16', 'undocumented_field_177'
|
464
|
-
field 178, 'uint16', '
|
464
|
+
field 178, 'uint16', 'est_sweat_loss', :unit => 'ml' # guessed
|
465
465
|
field 179, 'uint16', 'undocumented_field_179'
|
466
466
|
field 180, 'uint16', 'undocumented_field_180'
|
467
|
-
field 181, 'float32', '
|
468
|
-
field
|
467
|
+
field 181, 'float32', 'total_grit', :unit => 'kGrit'
|
468
|
+
field 182, 'float32', 'total_flow', :unit => 'Flow'
|
469
|
+
field 183, 'uint16', 'jump_count'
|
469
470
|
field 184, 'enum', 'undocumented_field_184'
|
470
471
|
field 185, 'uint8', 'undocumented_field_185'
|
471
|
-
field
|
472
|
+
field 186, 'float32', 'avg_grit', :unit => 'kGrit'
|
473
|
+
field 187, 'float32', 'avg_flow', :unit => 'Flow'
|
472
474
|
field 188, 'enum', 'undocumented_field_188'
|
473
475
|
field 189, 'uint16', 'undocumented_field_189'
|
474
476
|
field 190, 'uint16', 'undocumented_field_190'
|
475
477
|
field 194, 'uint8', 'undocumented_field_194'
|
476
478
|
field 195, 'uint8', 'undocumented_field_195'
|
479
|
+
field 199, 'uint8', 'total_fractional_ascent', :scale => 100, :unit => 'm'
|
480
|
+
field 200, 'uint8', 'total_fractional_descent', :scale => 100, :unit => 'm'
|
477
481
|
field 253, 'uint32', 'timestamp', :type => 'date_time'
|
478
482
|
field 254, 'uint16', 'message_index'
|
479
483
|
|
@@ -745,6 +749,48 @@ module Fit4Ruby
|
|
745
749
|
# counter.
|
746
750
|
field 2, 'byte', 'undocumented_field_2', :array => true
|
747
751
|
|
752
|
+
message 26, 'workout'
|
753
|
+
field 4, 'enum', 'sport', :dict => 'sport'
|
754
|
+
field 5, 'uint32z', 'capabilities', :dict => 'workout_capabilities'
|
755
|
+
field 6, 'uint16', 'num_valid_step'
|
756
|
+
field 8, 'string', 'wkt_name'
|
757
|
+
field 11, 'enum', 'sub_sport', :dict => 'sub_sport'
|
758
|
+
field 14, 'uint16', 'pool_length', :scale => 100, :unit => 'm'
|
759
|
+
field 15, 'enum', 'pool_length_unit'
|
760
|
+
|
761
|
+
message 27, 'workout_step'
|
762
|
+
field 0, 'string', 'wkt_step_name'
|
763
|
+
field 1, 'enum', 'duration_type', :dict => 'wkt_step_duration'
|
764
|
+
alt_field 2, 'duration_type' do
|
765
|
+
field :default, 'uint32', 'duration_value'
|
766
|
+
field 'distance', 'uint32', 'duration_distance', :scale => 100, :unit => 'm'
|
767
|
+
field 'time', 'uint32', 'duration_time', :scale => 1000, :unit => 's'
|
768
|
+
field 'repeat_until_steps_cmplt', 'uint32', 'duration_reps'
|
769
|
+
end
|
770
|
+
field 3, 'enum', 'target_type', :dict => 'wkt_step_target'
|
771
|
+
alt_field 4, 'target_type' do
|
772
|
+
field :default, 'uint32', 'target_value'
|
773
|
+
field 'speed', 'uint32', 'target_speed_zone'
|
774
|
+
field 'cadence', 'uint32', 'target_cadence_zone'
|
775
|
+
field 'power', 'uint32', 'target_power_zone'
|
776
|
+
end
|
777
|
+
alt_field 5, 'target_type' do
|
778
|
+
field :default, 'uint32', 'custom_target_value_low'
|
779
|
+
field 'speed', 'uint32', 'custom_target_speed_low', :scale => 1000, :unit => 'm/s'
|
780
|
+
end
|
781
|
+
alt_field 6, 'target_type' do
|
782
|
+
field :default, 'uint32', 'custom_target_value_high'
|
783
|
+
field 'speed', 'uint32', 'custom_target_speed_high', :scale => 1000, :unit => 'm/s'
|
784
|
+
end
|
785
|
+
field 7, 'enum', 'intensity', :dict => 'intensity'
|
786
|
+
field 8, 'string', 'notes'
|
787
|
+
field 9, 'enum', 'equipment', :dict => 'workout_equipment'
|
788
|
+
field 10, 'uint16', 'exercise_category'
|
789
|
+
field 11, 'uint16', 'exercise_name'
|
790
|
+
field 12, 'uint16', 'exercise_weight', :scale => 100, :unit => 'kg'
|
791
|
+
field 13, 'uint16', 'weight_display_unit'
|
792
|
+
field 254, 'uint16', 'message_index'
|
793
|
+
|
748
794
|
# Message 29 is just a guess. It's not officially documented.
|
749
795
|
# Found in LCTNS.FIT on Fenix 3
|
750
796
|
message 29, 'location'
|
@@ -1017,7 +1063,7 @@ module Fit4Ruby
|
|
1017
1063
|
field 18, 'uint8z', 'undocumented_field_18'
|
1018
1064
|
field 19, 'uint8z', 'undocumented_field_19'
|
1019
1065
|
field 20, 'uint8z', 'undocumented_field_20'
|
1020
|
-
field 21, 'uint16', '
|
1066
|
+
field 21, 'uint16', 'wheel_size', :unit => 'mm'
|
1021
1067
|
field 25, 'uint16', 'undocumented_field_25'
|
1022
1068
|
field 26, 'uint16', 'undocumented_field_26'
|
1023
1069
|
field 27, 'uint8', 'undocumented_field_27'
|
data/lib/fit4ruby/Lap.rb
CHANGED
@@ -12,24 +12,30 @@
|
|
12
12
|
|
13
13
|
require 'fit4ruby/FitDataRecord'
|
14
14
|
require 'fit4ruby/RecordAggregator'
|
15
|
+
require 'fit4ruby/FDR_DevField_Extension'
|
15
16
|
|
16
17
|
module Fit4Ruby
|
17
18
|
|
18
19
|
class Lap < FitDataRecord
|
19
20
|
|
20
21
|
include RecordAggregator
|
22
|
+
include FDR_DevField_Extension
|
21
23
|
|
22
24
|
attr_reader :records, :lengths
|
23
25
|
|
24
26
|
# Create a new Lap object.
|
27
|
+
# @param top_level_record [FitDataRecord] Top level record that is Lap
|
28
|
+
# belongs to.
|
25
29
|
# @param records [Array of Records] Records to associate with the Lap.
|
26
30
|
# @param lengths [Array of Lengths] Lengths to associate with the Lap.
|
27
31
|
# @param first_length_index [Fixnum] Index of the first Length in this Lap.
|
28
32
|
# @param previous_lap [Lap] Previous Lap on same Session.
|
29
33
|
# @param field_values [Hash] Hash that provides initial values for certain
|
30
34
|
# fields.
|
31
|
-
def initialize(records, previous_lap, field_values,
|
35
|
+
def initialize(top_level_record, records, previous_lap, field_values,
|
36
|
+
first_length_index, lengths)
|
32
37
|
super('lap')
|
38
|
+
@top_level_record = top_level_record
|
33
39
|
@lengths = lengths
|
34
40
|
@meta_field_units['avg_stride_length'] = 'm'
|
35
41
|
@records = records
|
@@ -51,6 +57,9 @@ module Fit4Ruby
|
|
51
57
|
@total_elapsed_time = records.last.timestamp - @start_time
|
52
58
|
end
|
53
59
|
|
60
|
+
# Create instance variables for developer fields
|
61
|
+
create_dev_field_instance_variables
|
62
|
+
|
54
63
|
set_field_values(field_values)
|
55
64
|
end
|
56
65
|
|
data/lib/fit4ruby/Record.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
# = Record.rb -- Fit4Ruby - FIT file processing library for Ruby
|
5
5
|
#
|
6
|
-
# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org>
|
6
|
+
# Copyright (c) 2014, 2020 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
|
@@ -11,6 +11,7 @@
|
|
11
11
|
#
|
12
12
|
|
13
13
|
require 'fit4ruby/FitDataRecord'
|
14
|
+
require 'fit4ruby/FDR_DevField_Extension'
|
14
15
|
|
15
16
|
module Fit4Ruby
|
16
17
|
|
@@ -18,13 +19,21 @@ module Fit4Ruby
|
|
18
19
|
# of primary measurements that are associated with a certain timestamp.
|
19
20
|
class Record < FitDataRecord
|
20
21
|
|
22
|
+
include FDR_DevField_Extension
|
23
|
+
|
21
24
|
# Create a new Record object.
|
25
|
+
# @param fit_entity The FitEntity this record belongs to
|
22
26
|
# @param field_values [Hash] Hash that provides initial values for certain
|
23
27
|
# fields.
|
24
|
-
def initialize(field_values = {})
|
28
|
+
def initialize(top_level_record, field_values = {})
|
25
29
|
super('record')
|
30
|
+
@top_level_record = top_level_record
|
26
31
|
@meta_field_units['pace'] = 'min/km'
|
27
32
|
@meta_field_units['run_cadence'] = 'spm'
|
33
|
+
|
34
|
+
# Create instance variables for developer fields
|
35
|
+
create_dev_field_instance_variables
|
36
|
+
|
28
37
|
set_field_values(field_values)
|
29
38
|
end
|
30
39
|
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# = Workout.rb -- Fit4Ruby - FIT file processing library for Ruby
|
5
|
+
#
|
6
|
+
# Copyright (c) 2021 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
|
+
class Workout < FitDataRecord
|
18
|
+
|
19
|
+
def initialize(field_values = {})
|
20
|
+
super('workout')
|
21
|
+
set_field_values(field_values)
|
22
|
+
end
|
23
|
+
|
24
|
+
def check(index)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# = WorkoutStep.rb -- Fit4Ruby - FIT file processing library for Ruby
|
5
|
+
#
|
6
|
+
# Copyright (c) 2021 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
|
+
class WorkoutStep < FitDataRecord
|
18
|
+
|
19
|
+
def initialize(field_values = {})
|
20
|
+
super('workout_step')
|
21
|
+
set_field_values(field_values)
|
22
|
+
end
|
23
|
+
|
24
|
+
def check(index)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
|
data/lib/fit4ruby/version.rb
CHANGED