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.
data/spec/FitFile_spec.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # = FitFile_spec.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
@@ -12,115 +12,147 @@
12
12
 
13
13
  $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
14
 
15
+ #require "super_diff/rspec"
15
16
  require 'fit4ruby'
16
17
 
17
18
  ENV['TZ'] = 'UTC'
18
19
 
19
20
  describe Fit4Ruby do
21
+ before(:each) do
22
+ File.delete(fit_file) if File.exist?(fit_file)
23
+ expect(File.exist?(fit_file)).to be false
24
+ end
25
+
26
+ after(:each) { File.delete(fit_file) }
27
+
20
28
  let(:fit_file) { 'test.fit' }
21
- let(:timestamp) { Time.now }
22
- let(:activity) do
23
- ts = timestamp
24
- a = Fit4Ruby::Activity.new
25
- a.total_timer_time = 30 * 60.0
26
- a.new_user_data({ :age => 33, :height => 1.78, :weight => 73.0,
27
- :gender => 'male', :activity_class => 4.0,
28
- :max_hr => 178 })
29
-
30
- a.new_event({ :event => 'timer', :event_type => 'start_time' })
31
- a.new_device_info({ :timestamp => ts,
32
- :device_index => 0, :manufacturer => 'garmin',
33
- :garmin_product => 'fenix3',
34
- :serial_number => 123456789 })
35
- a.new_device_info({ :timestamp => ts,
36
- :device_index => 1, :manufacturer => 'garmin',
37
- :garmin_product => 'fenix3_gps'})
38
- a.new_device_info({ :timestamp => ts,
39
- :device_index => 2, :manufacturer => 'garmin',
40
- :garmin_product => 'hrm_run',
41
- :battery_status => 'ok' })
42
- a.new_device_info({ :timestamp => ts,
43
- :device_index => 3, :manufacturer => 'garmin',
44
- :garmin_product => 'sdm4',
45
- :battery_status => 'ok' })
46
- a.new_data_sources({ :timestamp => ts, :distance => 1,
47
- :speed => 1, :cadence => 3, :elevation => 1,
48
- :heart_rate => 2 })
49
- laps = 0
50
- 0.upto(a.total_timer_time / 60) do |mins|
51
- ts += 60
52
- a.new_record({
53
- :timestamp => ts,
54
- :position_lat => 51.5512 - mins * 0.0008,
55
- :position_long => 11.647 + mins * 0.002,
56
- :distance => 200.0 * mins,
57
- :altitude => (100 + mins * 0.5).to_i,
58
- :speed => 3.1,
59
- :vertical_oscillation => 9 + mins * 0.02,
60
- :stance_time => 235.0 * mins * 0.01,
61
- :stance_time_percent => 32.0,
62
- :heart_rate => 140 + mins,
63
- :cadence => 75,
64
- :activity_type => 'running',
65
- :fractional_cadence => (mins % 2) / 2.0
66
- })
29
+ # Round the timestamp to seconds. This is what the file format can store. A
30
+ # higher resolution would create errors during comparions.
31
+ let(:timestamp) { Time.at(Time.now.to_i) }
32
+ let(:user_data) do
33
+ {
34
+ :age => 33, :height => 1.78, :weight => 73.0,
35
+ :gender => 'male', :activity_class => 4.0,
36
+ :max_hr => 178
37
+ }
38
+ end
39
+ let(:user_profile) do
40
+ {
41
+ :friendly_name => 'Fast Runner',
42
+ :gender => 'male',
43
+ :age => 33,
44
+ :height => 1.78,
45
+ :weight => 73.0,
46
+ :resting_heart_rate => 43
47
+ }
48
+ end
49
+ def device_info_fenix3(ts)
50
+ {
51
+ :timestamp => ts,
52
+ :device_index => 0, :manufacturer => 'garmin',
53
+ :garmin_product => 'fenix3',
54
+ :serial_number => 123456789
55
+ }
56
+ end
57
+ def device_info_fenix3_gps(ts)
58
+ {
59
+ :timestamp => ts,
60
+ :device_index => 1, :manufacturer => 'garmin',
61
+ :garmin_product => 'fenix3_gps'
62
+ }
63
+ end
64
+ def device_info_hrm_run(ts, bs = 'ok')
65
+ {
66
+ :timestamp => ts,
67
+ :device_index => 2, :manufacturer => 'garmin',
68
+ :garmin_product => 'hrm_run',
69
+ :battery_status => bs
70
+ }
71
+ end
72
+ def device_info_sdm4(ts)
73
+ {
74
+ :timestamp => timestamp,
75
+ :device_index => 3, :manufacturer => 'garmin',
76
+ :garmin_product => 'sdm4',
77
+ :battery_status => 'ok'
78
+ }
79
+ end
80
+
81
+ context 'running activity' do
82
+ let(:activity) do
83
+ ts = timestamp
84
+ a = Fit4Ruby::Activity.new
85
+ a.total_timer_time = 30 * 60.0
86
+ a.new_user_data(user_data)
87
+ a.new_user_profile(user_profile)
88
+
89
+ a.new_event({ :event => 'timer', :event_type => 'start_time' })
90
+ a.new_device_info(device_info_fenix3(ts))
91
+ a.new_device_info(device_info_fenix3_gps(ts))
92
+ a.new_device_info(device_info_hrm_run(ts))
93
+ a.new_device_info(device_info_sdm4(ts))
94
+ a.new_data_sources({ :timestamp => ts, :distance => 1,
95
+ :speed => 1, :cadence => 3, :elevation => 1,
96
+ :heart_rate => 2 })
97
+ laps = 0
98
+ 0.upto(a.total_timer_time / 60) do |mins|
99
+ ts += 60
100
+ a.new_record({
101
+ :timestamp => ts,
102
+ :position_lat => 51.5512 - mins * 0.0008,
103
+ :position_long => 11.647 + mins * 0.002,
104
+ :distance => 200.0 * mins,
105
+ :altitude => (100 + mins * 0.5).to_i,
106
+ :speed => 3.1,
107
+ :vertical_oscillation => 9 + mins * 0.02,
108
+ :stance_time => 235.0 * mins * 0.01,
109
+ :stance_time_percent => 32.0,
110
+ :heart_rate => 140 + mins,
111
+ :cadence => 75,
112
+ :activity_type => 'running',
113
+ :fractional_cadence => (mins % 2) / 2.0
114
+ })
67
115
 
68
- if mins > 0 && mins % 5 == 0
69
- a.new_lap({ :timestamp => ts, :sport => 'running',
70
- :message_index => laps, :total_cycles => 195 })
71
- laps += 1
116
+ if mins > 0 && mins % 5 == 0
117
+ a.new_lap({ :timestamp => ts, :sport => 'running',
118
+ :message_index => laps, :total_cycles => 195 })
119
+ laps += 1
120
+ end
72
121
  end
73
- end
74
- a.new_session({ :timestamp => ts, :sport => 'running' })
75
- a.new_event({ :timestamp => ts, :event => 'recovery_time',
76
- :event_type => 'marker',
77
- :recovery_time => 2160 })
78
- a.new_event({ :timestamp => ts, :event => 'vo2max',
79
- :event_type => 'marker', :vo2max => 52 })
80
- a.new_event({ :timestamp => ts, :event => 'timer',
81
- :event_type => 'stop_all' })
82
- ts += 1
83
- a.new_device_info({ :timestamp => ts,
84
- :device_index => 0, :manufacturer => 'garmin',
85
- :garmin_product => 'fenix3',
86
- :serial_number => 123456789 })
87
- a.new_device_info({ :timestamp => ts,
88
- :device_index => 1, :manufacturer => 'garmin',
89
- :garmin_product => 'fenix3_gps'})
90
- a.new_device_info({ :timestamp => ts,
91
- :device_index => 2, :manufacturer => 'garmin',
92
- :garmin_product => 'hrm_run',
93
- :battery_status => 'low' })
94
- a.new_device_info({ :timestamp => ts,
95
- :device_index => 3, :manufacturer => 'garmin',
96
- :garmin_product => 'sdm4',
97
- :battery_status => 'ok' })
98
- ts += 120
99
- a.new_event({ :timestamp => ts, :event => 'recovery_hr',
100
- :event_type => 'marker', :recovery_hr => 132 })
101
-
102
- a.aggregate
103
- a
104
- end
122
+ a.new_session({ :timestamp => ts, :sport => 'running' })
123
+ a.new_event({ :timestamp => ts, :event => 'recovery_time',
124
+ :event_type => 'marker',
125
+ :recovery_time => 2160 })
126
+ a.new_event({ :timestamp => ts, :event => 'vo2max',
127
+ :event_type => 'marker', :vo2max => 52 })
128
+ a.new_event({ :timestamp => ts, :event => 'timer',
129
+ :event_type => 'stop_all' })
130
+ ts += 1
131
+ a.new_device_info(device_info_fenix3(ts))
132
+ a.new_device_info(device_info_fenix3_gps(ts))
133
+ a.new_device_info(device_info_hrm_run(ts, 'low'))
134
+ a.new_device_info(device_info_sdm4(ts))
135
+ ts += 120
136
+ a.new_event({ :timestamp => ts, :event => 'recovery_hr',
137
+ :event_type => 'marker', :recovery_hr => 132 })
105
138
 
106
- before do
107
- File.delete(fit_file) if File.exist?(fit_file)
108
- expect(File.exist?(fit_file)).to be false
109
- end
139
+ a.aggregate
140
+ a
141
+ end
110
142
 
111
- after { File.delete(fit_file) }
143
+ it 'should write an Activity FIT file and read it back' do
144
+ Fit4Ruby.write(fit_file, activity)
145
+ expect(File.exist?(fit_file)).to be true
112
146
 
113
- it 'should write an Activity FIT file and read it back' do
114
- Fit4Ruby.write(fit_file, activity)
115
- expect(File.exist?(fit_file)).to be true
147
+ b = Fit4Ruby.read(fit_file)
148
+ expect(b.laps.count).to eq 6
149
+ expect(b.lengths.count).to eq 0
150
+ expect(b.export).to eq(activity.export)
151
+ end
116
152
 
117
- b = Fit4Ruby.read(fit_file)
118
- expect(b.laps.count).to eq 6
119
- expect(b.lengths.count).to eq 0
120
- expect(b.inspect).to eq(activity.inspect)
121
153
  end
122
154
 
123
- context 'activity with Lengths' do
155
+ context 'swimming activity' do
124
156
  let(:activity) do
125
157
  ts = timestamp
126
158
  laps = 0
@@ -128,9 +160,7 @@ describe Fit4Ruby do
128
160
  a = Fit4Ruby::Activity.new
129
161
 
130
162
  a.total_timer_time = 30 * 60.0
131
- a.new_device_info({ :timestamp => ts,
132
- :device_index => 0, :manufacturer => 'garmin',
133
- :serial_number => 123456789 })
163
+ a.new_device_info(device_info_fenix3(ts))
134
164
 
135
165
  0.upto(a.total_timer_time / 60) do |mins|
136
166
  ts += 60
@@ -144,6 +174,7 @@ describe Fit4Ruby do
144
174
  lengths += 1
145
175
  end
146
176
  end
177
+ a.aggregate
147
178
  a
148
179
  end
149
180
 
@@ -156,9 +187,76 @@ describe Fit4Ruby do
156
187
  expect(b.lengths.count).to eq 6
157
188
  expect(b.laps.select { |l| l.sport == 'swimming' }.count).to eq 6
158
189
  expect(b.lengths.select { |l| l.total_strokes == 45 }.count).to eq 6
159
- expect(b.inspect).to eq(activity.inspect)
190
+ expect(b.export).to eq(activity.export)
191
+ end
192
+
193
+ end
194
+
195
+ context 'activity with developer fields' do
196
+ let(:activity) do
197
+ ts = timestamp
198
+ laps = 0
199
+ lengths = 0
200
+ a = Fit4Ruby::Activity.new
201
+
202
+ a.total_timer_time = 30 * 60.0
203
+ a.new_device_info(device_info_fenix3(ts))
204
+ a.new_developer_data_id({
205
+ application_id: [ 24, 251, 44, 240, 26, 75, 67, 13,
206
+ 173, 102, 152, 140, 132, 116, 33, 244 ],
207
+ application_version: 77
208
+ })
209
+ a.new_field_description({
210
+ developer_data_index: 0,
211
+ field_definition_number: 0,
212
+ fit_base_type_id: 132,
213
+ field_name: 'Power',
214
+ units: 'Watts',
215
+ native_mesg_num: 20,
216
+ native_field_num: 7
217
+ })
218
+ a.new_data_sources({ :timestamp => ts, :distance => 1,
219
+ :speed => 1, :cadence => 3, :elevation => 1,
220
+ :heart_rate => 2 })
221
+ laps = 0
222
+ 0.upto(a.total_timer_time / 60) do |mins|
223
+ ts += 60
224
+ a.new_record({
225
+ :timestamp => ts,
226
+ :position_lat => 51.5512 - mins * 0.0008,
227
+ :position_long => 11.647 + mins * 0.002,
228
+ :distance => 200.0 * mins,
229
+ :altitude => (100 + mins * 0.5).to_i,
230
+ :speed => 3.1,
231
+ :vertical_oscillation => 9 + mins * 0.02,
232
+ :stance_time => 235.0 * mins * 0.01,
233
+ :stance_time_percent => 32.0,
234
+ :heart_rate => 140 + mins,
235
+ :cadence => 75,
236
+ :activity_type => 'running',
237
+ :fractional_cadence => (mins % 2) / 2.0,
238
+ :Power_18FB2CF01A4B430DAD66988C847421F4 => 240
239
+ })
240
+
241
+ if mins > 0 && mins % 5 == 0
242
+ a.new_lap({ :timestamp => ts, :sport => 'running',
243
+ :message_index => laps, :total_cycles => 195 })
244
+ laps += 1
245
+ end
246
+ end
247
+ a.aggregate
248
+ a
160
249
  end
161
250
 
251
+ it 'should write an Activity FIT file and read it back' do
252
+ Fit4Ruby.write(fit_file, activity)
253
+ expect(File.exist?(fit_file)).to be true
254
+
255
+ # This currently does not work as the saving of developer fields is not
256
+ # yet implemented.
257
+ #b = Fit4Ruby.read(fit_file)
258
+ #expect(b.export).to eq(activity.export)
259
+ end
162
260
  end
163
261
 
164
262
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fit4ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.7.0
4
+ version: 3.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Schlaeger
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-01 00:00:00.000000000 Z
11
+ date: 2022-08-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bindata
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '='
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 2.3.0
19
+ version: 2.4.8
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '='
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 2.3.0
26
+ version: 2.4.8
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: yard
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 12.0.0
47
+ version: 13.0.3
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 12.0.0
54
+ version: 13.0.3
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -112,6 +112,7 @@ files:
112
112
  - fit4ruby.gemspec
113
113
  - lib/fit4ruby.rb
114
114
  - lib/fit4ruby/Activity.rb
115
+ - lib/fit4ruby/BDFieldNameTranslator.rb
115
116
  - lib/fit4ruby/CRC16.rb
116
117
  - lib/fit4ruby/Converters.rb
117
118
  - lib/fit4ruby/DataSources.rb
@@ -120,6 +121,7 @@ files:
120
121
  - lib/fit4ruby/DumpedField.rb
121
122
  - lib/fit4ruby/EPO_Data.rb
122
123
  - lib/fit4ruby/Event.rb
124
+ - lib/fit4ruby/FDR_DevField_Extension.rb
123
125
  - lib/fit4ruby/FieldDescription.rb
124
126
  - lib/fit4ruby/FileCreator.rb
125
127
  - lib/fit4ruby/FileId.rb
@@ -162,6 +164,8 @@ files:
162
164
  - lib/fit4ruby/TrainingStatus.rb
163
165
  - lib/fit4ruby/UserData.rb
164
166
  - lib/fit4ruby/UserProfile.rb
167
+ - lib/fit4ruby/Workout.rb
168
+ - lib/fit4ruby/WorkoutStep.rb
165
169
  - lib/fit4ruby/version.rb
166
170
  - spec/FileNameCoder_spec.rb
167
171
  - spec/FitFile_spec.rb
@@ -174,7 +178,7 @@ homepage: https://github.com/scrapper/fit4ruby
174
178
  licenses:
175
179
  - GNU GPL version 2
176
180
  metadata: {}
177
- post_install_message:
181
+ post_install_message:
178
182
  rdoc_options: []
179
183
  require_paths:
180
184
  - lib
@@ -189,9 +193,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
189
193
  - !ruby/object:Gem::Version
190
194
  version: '0'
191
195
  requirements: []
192
- rubyforge_project:
193
- rubygems_version: 2.7.6.2
194
- signing_key:
196
+ rubygems_version: 3.2.32
197
+ signing_key:
195
198
  specification_version: 4
196
199
  summary: Library to read and write GARMIN FIT files.
197
200
  test_files: