fit4ruby 3.9.0 → 3.11.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
  SHA256:
3
- metadata.gz: 1f0a74c755c07cbbcfd9b17b9efeb16a62696fd9076c9ece178e00e51b3ce075
4
- data.tar.gz: 81ee48cea068828a6ad08c5f4f274270ec96179159e585ecc9068eccbf1be3a4
3
+ metadata.gz: 550fffeb71313287a1a1037974608c23b738da5a34c6aaca39374fea562b7426
4
+ data.tar.gz: 923417ab9520777208f4bd830696d7012c68b8ad2e7d39572749bad42301d560
5
5
  SHA512:
6
- metadata.gz: 0f140497b1f269075e912da5988238db3a279ef5baf20e4ce29f3b960307c3b87a4ada116283f17f5965a7e0e25e9b3e5bcdce7306b14ae49cb16d837692b239
7
- data.tar.gz: 829a3ff7cee37f26218915d8370a0dd44fe6c24152c634f073fb0d25a543c3e50783188fe81f6d5cbbb00af42974eba1aed51f59ee25a108718773b7a65f8ad8
6
+ metadata.gz: 990ce2d227826d09a114e55652bbc4287dc1b8c2e1a4a534a6ade8bbcc2baed3a321a4508ca6b880a6af745c007f58a60649b0f32bf75a6782f0e7df1498f26d
7
+ data.tar.gz: 3e6fe4df5bda73caa364937a13b1e4a764a65a55723026260f381d9a108441a030dc8ec8ff2876e7ece8527575571933164f8c23eae485e8f1ea09c479fe6924
data/README.md CHANGED
@@ -10,7 +10,7 @@ me comments and patches. It was developed to form the back-end of
10
10
 
11
11
  ## Supported Devices
12
12
 
13
- Tested devices: Garmin FR620
13
+ Tested devices: Garmin FR620, Fenix 3, Fenix 5, Fenix 5X, Fenix 6X
14
14
 
15
15
  Other Garmin devices that generate FIT files may work as well. Since I
16
16
  don't have any other devices, I can't add support for them.
data/fit4ruby.gemspec CHANGED
@@ -22,7 +22,7 @@ EOT
22
22
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
23
23
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
24
24
  spec.require_paths = ["lib"]
25
- spec.required_ruby_version = '>=2.0'
25
+ spec.required_ruby_version = '>=2.3'
26
26
 
27
27
  spec.add_dependency('bindata', '~>2.4.8')
28
28
  spec.add_development_dependency('yard', '~>0.9.20')
@@ -30,6 +30,8 @@ require 'fit4ruby/HRV'
30
30
  require 'fit4ruby/HeartRateZones'
31
31
  require 'fit4ruby/Event'
32
32
  require 'fit4ruby/PersonalRecords'
33
+ require 'fit4ruby/Workout'
34
+ require 'fit4ruby/WorkoutStep'
33
35
 
34
36
  module Fit4Ruby
35
37
 
@@ -54,6 +56,8 @@ module Fit4Ruby
54
56
  :epo_data,
55
57
  :user_profiles,
56
58
  :user_data,
59
+ :workouts,
60
+ :workout_steps,
57
61
  :sensor_settings,
58
62
  :developer_data_ids,
59
63
  :field_descriptions,
@@ -184,7 +188,7 @@ module Fit4Ruby
184
188
  # sessions.
185
189
  def total_distance
186
190
  d = 0.0
187
- @sessions.each { |s| d += s.total_distance }
191
+ @sessions.each { |s| d += (s.total_distance || 0) }
188
192
  d
189
193
  end
190
194
 
@@ -311,11 +315,21 @@ module Fit4Ruby
311
315
  @sessions[0].sport
312
316
  end
313
317
 
318
+ # Sets the sport type of this activity.
319
+ def sport=(sport)
320
+ @sessions[0].sport = sport
321
+ end
322
+
314
323
  # Returns the sport subtype of this activity.
315
324
  def sub_sport
316
325
  @sessions[0].sub_sport
317
326
  end
318
327
 
328
+ # Sets the sport subtype of this activity.
329
+ def sub_sport=(sub_sport)
330
+ @sessions[0].sub_sport = sub_sport
331
+ end
332
+
319
333
  # Write the Activity data to a file.
320
334
  # @param io [IO] File reference
321
335
  # @param id_mapper [FitMessageIdMapper] Maps global FIT record types to
@@ -405,6 +419,22 @@ module Fit4Ruby
405
419
  new_fit_data_record('user_profile', field_values)
406
420
  end
407
421
 
422
+ # Add a new Workout to the Activity.
423
+ # @param field_values [Hash] A Hash that provides initial values for
424
+ # certain fields of the FitDataRecord.
425
+ # @return [UserProfile]
426
+ def new_workout(field_values = {})
427
+ new_fit_data_record('workout', field_values)
428
+ end
429
+
430
+ # Add a new WorkoutSet to the Activity.
431
+ # @param field_values [Hash] A Hash that provides initial values for
432
+ # certain fields of the FitDataRecord.
433
+ # @return [UserProfile]
434
+ def new_workout_set(field_values = {})
435
+ new_fit_data_record('workout_set', field_values)
436
+ end
437
+
408
438
  # Add a new PhysiologicalMetrics to the Activity.
409
439
  # @param field_values [Hash] A Hash that provides initial values for
410
440
  # certain fields of the FitDataRecord.
@@ -522,6 +552,10 @@ module Fit4Ruby
522
552
  @data_sources << (record = DataSources.new(field_values))
523
553
  when 'user_data'
524
554
  @user_data << (record = UserData.new(field_values))
555
+ when 'workout'
556
+ @workouts << (record = Workout.new(field_values))
557
+ when 'workout_step'
558
+ @workout_steps << (record = WorkoutStep.new(field_values))
525
559
  when 'user_profile'
526
560
  @user_profiles << (record = UserProfile.new(field_values))
527
561
  when 'physiological_metrics'
@@ -615,4 +649,3 @@ module Fit4Ruby
615
649
  end
616
650
 
617
651
  end
618
-
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env ruby -w
2
- # encoding: UTF-8
3
2
  #
4
3
  # = Converters.rb -- Fit4Ruby - FIT file processing library for Ruby
5
4
  #
@@ -9,34 +8,47 @@
9
8
  # it under the terms of version 2 of the GNU General Public License as
10
9
  # published by the Free Software Foundation.
11
10
  #
11
+ # frozen_string_literal: true
12
12
 
13
13
  module Fit4Ruby
14
-
15
14
  module Converters
15
+ FACTORS = {
16
+ 'm' => { 'km' => 0.001, 'in' => 39.3701, 'ft' => 3.28084,
17
+ 'mi' => 0.000621371 },
18
+ 'mm' => { 'cm' => 0.1, 'in' => 0.0393701 },
19
+ 'm/s' => { 'km/h' => 3.6, 'mph' => 2.23694 },
20
+ 'min/km' => { 'min/mi' => 1.60934 },
21
+ 'kg' => { 'lbs' => 2.20462262 },
22
+ 'C' => { 'F' => 9.0 / 5.0 }
23
+ }.freeze
24
+ OFFSETS = {
25
+ 'C' => { 'F' => 32 }
26
+ }.freeze
16
27
 
17
28
  def conversion_factor(from_unit, to_unit)
18
- factors = {
19
- 'm' => { 'km' => 0.001, 'in' => 39.3701, 'ft' => 3.28084,
20
- 'mi' => 0.000621371 },
21
- 'mm' => { 'cm' => 0.1, 'in' => 0.0393701 },
22
- 'm/s' => { 'km/h' => 3.6, 'mph' => 2.23694 },
23
- 'min/km' => { 'min/mi' => 1.60934 },
24
- 'kg' => { 'lbs' => 0.453592 }
25
- }
26
29
  return 1.0 if from_unit == to_unit
27
- unless factors.include?(from_unit)
28
- Log.fatal "No conversion factors defined for unit " +
30
+
31
+ unless FACTORS.include?(from_unit)
32
+ Log.fatal 'No conversion factors defined for unit ' \
29
33
  "'#{from_unit}' to '#{to_unit}'"
30
34
  end
31
35
 
32
- factor = factors[from_unit][to_unit]
36
+ factor = FACTORS[from_unit][to_unit]
33
37
  if factor.nil?
34
- Log.fatal "No conversion factor from '#{from_unit}' to '#{to_unit}' " +
35
- "defined."
38
+ Log.fatal "No conversion factor from '#{from_unit}' to '#{to_unit}' " \
39
+ 'defined.'
36
40
  end
41
+
37
42
  factor
38
43
  end
39
44
 
45
+ def conversion_offset(from_unit, to_unit)
46
+ return 0.0 if from_unit == to_unit || !OFFSETS.include?(from_unit) ||
47
+ !OFFSETS[from_unit].include?(to_unit)
48
+
49
+ OFFSETS[from_unit][to_unit]
50
+ end
51
+
40
52
  def speedToPace(speed, distance = 1000.0)
41
53
  if speed && speed > 0.01
42
54
  # We only show 2 fractional digits, so make sure we round accordingly
@@ -89,4 +101,3 @@ module Fit4Ruby
89
101
  end
90
102
 
91
103
  end
92
-
@@ -1,30 +1,28 @@
1
1
  #!/usr/bin/env ruby -w
2
- # encoding: UTF-8
3
2
  #
4
3
  # = FitDataRecord.rb -- Fit4Ruby - FIT file processing library for Ruby
5
4
  #
6
- # Copyright (c) 2014, 2015, 2020 by Chris Schlaeger <cs@taskjuggler.org>
5
+ # Copyright (c) 2014, 2015, 2020, 2021 by Chris Schlaeger <cs@taskjuggler.org>
7
6
  #
8
7
  # This program is free software; you can redistribute it and/or modify
9
8
  # it under the terms of version 2 of the GNU General Public License as
10
9
  # published by the Free Software Foundation.
11
10
  #
11
+ # frozen_string_literal: true
12
12
 
13
13
  require 'fit4ruby/FitMessageIdMapper'
14
- require 'fit4ruby/GlobalFitMessages.rb'
14
+ require 'fit4ruby/GlobalFitMessages'
15
15
  require 'fit4ruby/BDFieldNameTranslator'
16
16
 
17
17
  module Fit4Ruby
18
-
19
18
  class FitDataRecord
20
-
21
19
  include Converters
22
20
  include BDFieldNameTranslator
23
21
 
24
- RecordOrder = [ 'user_data', 'user_profile',
25
- 'device_info', 'data_sources', 'event',
26
- 'record', 'lap', 'length', 'session', 'heart_rate_zones',
27
- 'personal_records' ]
22
+ RecordOrder = ['user_data', 'user_profile', 'workout', 'workout_set',
23
+ 'device_info', 'data_sources', 'event',
24
+ 'record', 'lap', 'length', 'session', 'heart_rate_zones',
25
+ 'personal_records']
28
26
 
29
27
  attr_reader :message, :timestamp
30
28
 
@@ -33,7 +31,7 @@ module Fit4Ruby
33
31
 
34
32
  # Create instance variables that correspond to every field of the
35
33
  # corresponding FIT data record.
36
- @message.fields_by_name.each do |name, field|
34
+ @message.fields_by_name.each do |name, _|
37
35
  create_instance_variable(name)
38
36
  end
39
37
 
@@ -51,9 +49,9 @@ module Fit4Ruby
51
49
  end
52
50
 
53
51
  def set(name, value)
54
- ivar_name = '@' + name
52
+ ivar_name = "@#{name}"
55
53
  unless instance_variable_defined?(ivar_name)
56
- Log.debug("Unknown FIT record field '#{name}' in global message " +
54
+ Log.debug("Unknown FIT record field '#{name}' in global message " \
57
55
  "#{@message.name} (#{@message.number}).")
58
56
  return
59
57
  end
@@ -62,7 +60,7 @@ module Fit4Ruby
62
60
 
63
61
  def get(name)
64
62
  # This is a request for a native FIT field.
65
- ivar_name = '@' + name
63
+ ivar_name = "@#{name}"
66
64
  return nil unless instance_variable_defined?(ivar_name)
67
65
 
68
66
  instance_variable_get(ivar_name)
@@ -82,17 +80,17 @@ module Fit4Ruby
82
80
  end
83
81
  end
84
82
 
85
- value * conversion_factor(unit, to_unit)
83
+ conversion_offset(unit, to_unit) + value * conversion_factor(unit, to_unit)
86
84
  end
87
85
 
88
- def ==(fdr)
89
- @message.each_field(field_values_as_hash) do |number, field|
90
- ivar_name = '@' + field.name
86
+ def ==(other)
87
+ @message.each_field(field_values_as_hash) do |_, field|
88
+ ivar_name = "@#{field.name}"
91
89
  # Comparison of values is done in the fit file format as the accuracy
92
90
  # of native formats is better and could lead to wrong results if a
93
91
  # value hasn't been read back from a fit file yet.
94
92
  v1 = field.native_to_fit(instance_variable_get(ivar_name))
95
- v2 = field.native_to_fit(fdr.instance_variable_get(ivar_name))
93
+ v2 = field.native_to_fit(other.instance_variable_get(ivar_name))
96
94
 
97
95
  return false unless v1 == v2
98
96
  end
@@ -100,16 +98,15 @@ module Fit4Ruby
100
98
  true
101
99
  end
102
100
 
103
- def <=>(fdr)
104
- @timestamp == fdr.timestamp ?
101
+ def <=>(other)
102
+ @timestamp == other.timestamp ?
105
103
  RecordOrder.index(@message.name) <=>
106
- RecordOrder.index(fdr.message.name) :
107
- @timestamp <=> fdr.timestamp
104
+ RecordOrder.index(other.message.name) :
105
+ @timestamp <=> other.timestamp
108
106
  end
109
107
 
110
108
  def write(io, id_mapper)
111
- global_fit_message = @message.construct(
112
- field_values = field_values_as_hash)
109
+ global_fit_message = @message.construct(field_values = field_values_as_hash)
113
110
 
114
111
  # Map the global message number to the current local message number.
115
112
  unless (local_message_number = id_mapper.get_local(global_fit_message))
@@ -134,10 +131,10 @@ module Fit4Ruby
134
131
 
135
132
  # Fill the BinData::Struct object with the values from the corresponding
136
133
  # instance variables.
137
- global_fit_message.each_field(field_values) do |number, field|
134
+ global_fit_message.each_field(field_values) do |_, field|
138
135
  bin_data_type = FitDefinitionFieldBase.fit_type_to_bin_data(field.type)
139
136
  field_name = to_bd_field_name(field.name)
140
- field_def = [ bin_data_type, field_name ]
137
+ field_def = [bin_data_type, field_name]
141
138
 
142
139
  iv = "@#{field.name}"
143
140
  if instance_variable_defined?(iv) &&
@@ -147,7 +144,7 @@ module Fit4Ruby
147
144
  # If we don't have a corresponding variable or the variable is nil
148
145
  # we write the 'undefined' value instead.
149
146
  value = FitDefinitionFieldBase.undefined_value(field.type)
150
- values[field.name] = field.opts[:array] ? [ value ] :
147
+ values[field.name] = field.opts[:array] ? [value] :
151
148
  field.type == 'string' ? '' : value
152
149
  end
153
150
 
@@ -157,17 +154,17 @@ module Fit4Ruby
157
154
  values[field.name] += "\0"
158
155
  elsif field.opts[:array]
159
156
  # For Arrays we use a BinData::Array to write them.
160
- field_def = [ :array, field_name,
161
- { :type => bin_data_type,
162
- :initial_length => values[field.name].size } ]
157
+ field_def = [:array, field_name,
158
+ { type: bin_data_type,
159
+ initial_length: values[field.name].size }]
163
160
  end
164
161
  fields << field_def
165
162
  end
166
- bd = BinData::Struct.new(:endian => :little, :fields => fields)
163
+ bd = BinData::Struct.new(endian: :little, fields: fields)
167
164
 
168
165
  # Fill the BinData::Struct object with the values from the corresponding
169
166
  # instance variables.
170
- global_fit_message.each_field(field_values) do |number, field|
167
+ global_fit_message.each_field(field_values) do |_, field|
171
168
  bd[to_bd_field_name(field.name)] = values[field.name]
172
169
  end
173
170
 
@@ -183,13 +180,13 @@ module Fit4Ruby
183
180
  }
184
181
 
185
182
  @message.each_field(field_values_as_hash) do |number, field|
186
- ivar_name = '@' + field.name
183
+ ivar_name = "@#{field.name}"
187
184
  fit_value = field.native_to_fit(instance_variable_get(ivar_name))
188
185
  unless field.is_undefined?(fit_value)
189
186
  fld = {
190
187
  'number' => number,
191
188
  'value' => field.fit_to_native(fit_value),
192
- #'human' => field.to_human(fit_value),
189
+ # 'human' => field.to_human(fit_value),
193
190
  'type' => field.type
194
191
  }
195
192
  fld['unit'] = field.opts[:unit] if field.opts[:unit]
@@ -214,7 +211,7 @@ module Fit4Ruby
214
211
  # set of fields. It does not contain any AltField objects.
215
212
  field_values = {}
216
213
  @message.fields_by_name.each_key do |name|
217
- field_values[name] = instance_variable_get('@' + name)
214
+ field_values[name] = instance_variable_get("@#{name}")
218
215
  end
219
216
 
220
217
  field_values
@@ -223,12 +220,9 @@ module Fit4Ruby
223
220
  def create_instance_variable(name)
224
221
  # Create a new instance variable for 'name'. We initialize it with a
225
222
  # provided default value or nil.
226
- instance_variable_set('@' + name, nil)
223
+ instance_variable_set("@#{name}", nil)
227
224
  # And create an accessor method for it as well.
228
225
  self.class.__send__(:attr_accessor, name)
229
226
  end
230
-
231
227
  end
232
-
233
228
  end
234
-
@@ -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
@@ -16,6 +16,10 @@ module Fit4Ruby
16
16
 
17
17
  GlobalFitDictionaries = GlobalFitDictList.new do
18
18
 
19
+ dict 'activity'
20
+ entry 0, 'manual'
21
+ entry 1, 'auto_multi_sport'
22
+
19
23
  dict 'activity_type'
20
24
  entry 0, 'generic'
21
25
  entry 1, 'running'
@@ -23,50 +27,8 @@ module Fit4Ruby
23
27
  entry 3, 'transition'
24
28
  entry 4, 'fitness_equipment'
25
29
  entry 5, 'swimming'
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'
30
+ entry 6, 'walking'
31
+ entry 8, 'sedentary'
70
32
  entry 254, 'all'
71
33
 
72
34
  dict 'activity_level'
@@ -714,6 +676,9 @@ module Fit4Ruby
714
676
  entry 1, 'rest'
715
677
  entry 2, 'warmup'
716
678
  entry 3, 'cooldown'
679
+ entry 4, 'recovery'
680
+ entry 5, 'interval'
681
+ entry 6, 'other'
717
682
 
718
683
  dict 'hr_zone_calc'
719
684
  entry 0, 'custom'
@@ -933,6 +898,36 @@ module Fit4Ruby
933
898
  entry 17, 'hiking'
934
899
  entry 18, 'multisport'
935
900
  entry 19, 'paddling'
901
+ entry 20, 'flying'
902
+ entry 21, 'e_biking'
903
+ entry 22, 'motorcycling'
904
+ entry 23, 'boating'
905
+ entry 24, 'driving'
906
+ entry 25, 'golf'
907
+ entry 26, 'hang_gliding'
908
+ entry 27, 'horseback_riding'
909
+ entry 28, 'hunting'
910
+ entry 29, 'fishing'
911
+ entry 30, 'inline_skating'
912
+ entry 31, 'rock_climbing'
913
+ entry 32, 'sailing'
914
+ entry 33, 'ice_skating'
915
+ entry 34, 'sky_diving'
916
+ entry 35, 'snowshoeing'
917
+ entry 36, 'snowmobiling'
918
+ entry 37, 'stand_up_paddleboarding'
919
+ entry 38, 'surfing'
920
+ entry 39, 'wakeboarding'
921
+ entry 40, 'water_skiing'
922
+ entry 41, 'kayaking'
923
+ entry 42, 'rafting'
924
+ entry 43, 'windsurfing'
925
+ entry 44, 'kitesurfing'
926
+ entry 45, 'tactical'
927
+ entry 46, 'jumpmaster'
928
+ entry 47, 'boxing'
929
+ entry 48, 'floor_climbing'
930
+ entry 53, 'diving'
936
931
  entry 254, 'all'
937
932
 
938
933
  dict 'swim_stroke'
@@ -1023,6 +1018,79 @@ module Fit4Ruby
1023
1018
  entry 2, 'maintaining'
1024
1019
  entry 3, 'up'
1025
1020
 
1021
+ dict 'wkt_step_duration'
1022
+ entry 0, 'time'
1023
+ entry 1, 'distance'
1024
+ entry 2, 'hr_less_than'
1025
+ entry 3, 'hr_greater_than'
1026
+ entry 4, 'calories'
1027
+ entry 5, 'open'
1028
+ entry 6, 'repeat_until_steps_cmplt'
1029
+ entry 7, 'repeat_until_time'
1030
+ entry 8, 'repeat_until_distance'
1031
+ entry 9, 'repeat_until_calories'
1032
+ entry 10, 'repeat_until_hr_less_than'
1033
+ entry 11, 'repeat_until_hr_greater_than'
1034
+ entry 12, 'repeat_until_power_less_than'
1035
+ entry 13, 'repeat_until_power_greater_than'
1036
+ entry 14, 'power_less_than'
1037
+ entry 15, 'power_greater_than'
1038
+ entry 16, 'training_peaks_tss'
1039
+ entry 17, 'repeat_until_power_last_lap_less_than'
1040
+ entry 18, 'repeat_until_max_power_last_lap_less_than'
1041
+ entry 19, 'power_3s_less_than'
1042
+ entry 20, 'power_10s_less_than'
1043
+ entry 21, 'power_30s_less_than'
1044
+ entry 22, 'power_3s_greater_than'
1045
+ entry 23, 'power_10s_greater_than'
1046
+ entry 24, 'power_30s_greater_than'
1047
+ entry 25, 'power_lap_less_than'
1048
+ entry 26, 'power_lap_greater_than'
1049
+ entry 27, 'repeat_until_training_peaks_tss'
1050
+ entry 28, 'repetition_time'
1051
+ entry 29, 'reps'
1052
+ entry 31, 'time_only'
1053
+
1054
+ dict 'wkt_step_target'
1055
+ entry 0, 'speed'
1056
+ entry 1, 'heart_rate'
1057
+ entry 2, 'open'
1058
+ entry 3, 'cadence'
1059
+ entry 4, 'power'
1060
+ entry 5, 'grade'
1061
+ entry 6, 'resistance'
1062
+ entry 7, 'power_3s'
1063
+ entry 8, 'power_10s'
1064
+ entry 9, 'power_30s'
1065
+ entry 10, 'power_lap'
1066
+ entry 11, 'swim_stroke'
1067
+ entry 12, 'speed_lap'
1068
+ entry 13, 'heart_rate_lap'
1069
+
1070
+ dict 'workout_capabilities'
1071
+ entry 0x1, 'interval'
1072
+ entry 0x2, 'custom'
1073
+ entry 0x4, 'fitness_equipment'
1074
+ entry 0x8, 'firstbeat'
1075
+ entry 0x10, 'new_leaf'
1076
+ entry 0x20, 'tcx'
1077
+ entry 0x80, 'speed'
1078
+ entry 0x100, 'heart_rate'
1079
+ entry 0x200, 'distance'
1080
+ entry 0x400, 'cadence'
1081
+ entry 0x800, 'power'
1082
+ entry 0x1000, 'grade'
1083
+ entry 0x2000, 'resistance'
1084
+ entry 0x4000, 'protected'
1085
+
1086
+ dict 'workout_equipment'
1087
+ entry 0, 'none'
1088
+ entry 1, 'swim_fins'
1089
+ entry 2, 'swim_kickboard'
1090
+ entry 3, 'swim_paddles'
1091
+ entry 4, 'swim_pull_buoy'
1092
+ entry 5, 'swim_snorkel'
1093
+
1026
1094
  end
1027
1095
 
1028
1096
  end
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # = GlobalFitMessages.rb -- Fit4Ruby - FIT file processing library for Ruby
5
5
  #
6
- # Copyright (c) 2014, 2015, 2020 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', 'undocumented_field_178'
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', 'undocumented_field_181'
468
- field 183, 'uint16', 'undocumented_field_183'
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 187, 'float32', 'undocumented_field_187'
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
 
@@ -638,7 +642,7 @@ module Fit4Ruby
638
642
  field 83, 'uint16', 'vertical_ratio', :scale => 100, :unit => '%' # guessed
639
643
  field 84, 'uint16', 'gct_balance', :scale => 100, :unit => '%' # guessed
640
644
  field 85, 'uint16', 'stride_length', :scale => 10000, :unit => 'm' # guessed
641
- field 87, 'uint16', 'undefined_value_87' # first seen on F3 FW6.80
645
+ field 87, 'uint16', 'stroke_distance', :scale => 100, :unit => 'm'
642
646
  field 88, 'uint16', 'undefined_value_88' # first seen on F3HR FW3.60
643
647
  field 90, 'sint8', 'performance_condition' # guessed
644
648
  field 100, 'sint32', 'undocumented_field_100'
@@ -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'
@@ -771,7 +817,7 @@ module Fit4Ruby
771
817
  message 34, 'activity'
772
818
  field 0, 'uint32', 'total_timer_time', :type => 'duration', :scale => 1000
773
819
  field 1, 'uint16', 'num_sessions'
774
- field 2, 'enum', 'type', :dict => 'activity_type'
820
+ field 2, 'enum', 'type', :dict => 'activity'
775
821
  field 3, 'enum', 'event', :dict => 'event'
776
822
  field 4, 'enum', 'event_type', :dict => 'event_type'
777
823
  field 5, 'uint32', 'local_timestamp', :type => 'date_time'
@@ -1069,14 +1115,19 @@ module Fit4Ruby
1069
1115
  field 73, 'uint16z', 'undocumented_field_73'
1070
1116
  field 254, 'uint16', 'message_index'
1071
1117
 
1072
- # Not part of the official ANT SDK doc.
1073
- message 160, 'undocumented_160'
1074
- field 3, 'uint32', 'undocumented_field_3'
1075
- field 4, 'uint32', 'undocumented_field_4'
1118
+ message 160, 'gps_metadata'
1119
+ field 0, 'uint16', 'timestamp_ms'
1120
+ field 1, 'sint32', 'position_lat'
1121
+ field 2, 'sint32', 'position_long'
1122
+ field 3, 'uint32', 'enhanced_altitude', :scale => 5, :offset => 500, :unit => 'm'
1123
+ field 4, 'uint32', 'enhanced_speed', :unit => 'm/s', :scale => 1000
1124
+ field 5, 'uint16', 'heading', :unit => 'degrees', :scale => 100
1125
+ field 6, 'uint32', 'utc_timestamp', :type => 'date_time'
1126
+ field 7, 'sint16', 'velocity', :array => true, :scale => 100, :unit => 'm/s'
1127
+ field 253, 'uint32', 'timestamp', :type => 'date_time'
1076
1128
 
1077
- # Not part of the official ANT SDK doc.
1078
- message 188, 'undocumented_188'
1079
- field 0, 'enum', 'undocumented_field_0'
1129
+ message 188, 'ohr_settings'
1130
+ field 0, 'enum', 'switch'
1080
1131
  field 253, 'uint32', 'timestamp', :type => 'date_time'
1081
1132
 
1082
1133
  message 206, 'field_description'
@@ -1217,6 +1268,24 @@ module Fit4Ruby
1217
1268
  field 252, 'uint8', 'undocumented_field_252'
1218
1269
  field 253, 'uint32', 'timestamp', :type => 'date_time'
1219
1270
 
1271
+ # Not part of the official ANT SDK doc.
1272
+ message 312, 'undocumented_312'
1273
+ field 0, 'enum', 'undocumented_field_0'
1274
+ field 9, 'uint32', 'interval_start', :type => 'date_time'
1275
+ field 15, 'uint8', 'min_heart_rate', :unit => 'bpm'
1276
+ field 16, 'uint8', 'max_heart_rate', :unit => 'bpm'
1277
+ field 21, 'sint32', 'position_lat', :type => 'coordinate'
1278
+ field 22, 'sint32', 'position_long', :type => 'coordinate'
1279
+ field 27, 'uint32', 'interval_end', :type => 'date_time'
1280
+ field 32, 'sint8', 'avg_temperature', :unit => 'C'
1281
+ field 33, 'sint8', 'max_temperature', :unit => 'C'
1282
+ field 34, 'sint8', 'min_temperature', :unit => 'C'
1283
+ field 37, 'uint16', 'undocumented_field_37'
1284
+ field 38, 'uint16', 'undocumented_field_38'
1285
+ field 39, 'uint16', 'undocumented_field_39'
1286
+ field 253, 'uint32', 'timestamp', :type => 'date_time'
1287
+ field 254, 'uint16', 'message_index'
1288
+
1220
1289
  # Not part of the official ANT SDK doc.
1221
1290
  message 325, 'undocumented_325'
1222
1291
  field 0, 'uint8', 'undocumented_field_0'
@@ -1259,4 +1328,3 @@ module Fit4Ruby
1259
1328
  end
1260
1329
 
1261
1330
  end
1262
-
@@ -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
+
@@ -1,4 +1,4 @@
1
1
  module Fit4Ruby
2
2
  # The version number of the library.
3
- VERSION = '3.9.0'
3
+ VERSION = '3.11.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.9.0
4
+ version: 3.11.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: 2021-11-17 00:00:00.000000000 Z
11
+ date: 2023-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bindata
@@ -164,6 +164,8 @@ files:
164
164
  - lib/fit4ruby/TrainingStatus.rb
165
165
  - lib/fit4ruby/UserData.rb
166
166
  - lib/fit4ruby/UserProfile.rb
167
+ - lib/fit4ruby/Workout.rb
168
+ - lib/fit4ruby/WorkoutStep.rb
167
169
  - lib/fit4ruby/version.rb
168
170
  - spec/FileNameCoder_spec.rb
169
171
  - spec/FitFile_spec.rb
@@ -184,14 +186,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
184
186
  requirements:
185
187
  - - ">="
186
188
  - !ruby/object:Gem::Version
187
- version: '2.0'
189
+ version: '2.3'
188
190
  required_rubygems_version: !ruby/object:Gem::Requirement
189
191
  requirements:
190
192
  - - ">="
191
193
  - !ruby/object:Gem::Version
192
194
  version: '0'
193
195
  requirements: []
194
- rubygems_version: 3.2.22
196
+ rubygems_version: 3.4.10
195
197
  signing_key:
196
198
  specification_version: 4
197
199
  summary: Library to read and write GARMIN FIT files.