fit4ruby 3.7.0 → 3.10.0

Sign up to get free protection for your applications and to get access to all the features.
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: