fit4ruby 3.2.0 → 3.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile.lock +30 -6
- data/fit4ruby.gemspec +4 -2
- data/lib/fit4ruby/Activity.rb +57 -9
- data/lib/fit4ruby/DeviceInfo.rb +37 -0
- data/lib/fit4ruby/FieldDescription.rb +7 -1
- data/lib/fit4ruby/FitDataRecord.rb +3 -3
- data/lib/fit4ruby/FitDefinitionField.rb +2 -2
- data/lib/fit4ruby/FitMessageRecord.rb +3 -3
- data/lib/fit4ruby/GlobalFitDictionaries.rb +278 -22
- data/lib/fit4ruby/GlobalFitMessage.rb +6 -1
- data/lib/fit4ruby/GlobalFitMessages.rb +213 -9
- data/lib/fit4ruby/Lap.rb +29 -3
- data/lib/fit4ruby/Length.rb +53 -0
- data/lib/fit4ruby/Record.rb +4 -4
- data/lib/fit4ruby/version.rb +1 -1
- data/spec/FitFile_spec.rb +59 -11
- metadata +36 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1867e2f6e32d331216b372024ba0607837bb5dc3baf7daad107b5a23d6465aa6
|
4
|
+
data.tar.gz: 25f0423ccf5e68259f48d02f35400fa2a723a9f7209613f77eca2631d056f2d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 05641db1523d5e8a9b8ab939d4b65def4e5a50ca6bbcae3fb1c727dc7d641cfeda6d7a5e892b38819b840b0a2222e0d775d20bf4f93ae4af6db2c79b4b6753b3
|
7
|
+
data.tar.gz: f4b7d619de81444329009c7a188f08bd4684524ecc1654a57b77df147a0e22730658d57247e30729f619a0ab2c6fbd6fce796908df05ff2d409a06a909656298
|
data/Gemfile.lock
CHANGED
@@ -1,15 +1,34 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
fit4ruby (
|
5
|
-
bindata (
|
4
|
+
fit4ruby (3.3.0)
|
5
|
+
bindata (= 2.3.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
bindata (2.
|
10
|
+
bindata (2.3.0)
|
11
|
+
coderay (1.1.2)
|
12
|
+
diff-lcs (1.3)
|
13
|
+
method_source (0.9.2)
|
14
|
+
pry (0.12.2)
|
15
|
+
coderay (~> 1.1.0)
|
16
|
+
method_source (~> 0.9.0)
|
11
17
|
rake (0.9.6)
|
12
|
-
|
18
|
+
rspec (3.8.0)
|
19
|
+
rspec-core (~> 3.8.0)
|
20
|
+
rspec-expectations (~> 3.8.0)
|
21
|
+
rspec-mocks (~> 3.8.0)
|
22
|
+
rspec-core (3.8.2)
|
23
|
+
rspec-support (~> 3.8.0)
|
24
|
+
rspec-expectations (3.8.4)
|
25
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
26
|
+
rspec-support (~> 3.8.0)
|
27
|
+
rspec-mocks (3.8.1)
|
28
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
29
|
+
rspec-support (~> 3.8.0)
|
30
|
+
rspec-support (3.8.2)
|
31
|
+
yard (0.9.20)
|
13
32
|
|
14
33
|
PLATFORMS
|
15
34
|
ruby
|
@@ -17,5 +36,10 @@ PLATFORMS
|
|
17
36
|
DEPENDENCIES
|
18
37
|
bundler (>= 1.6.4)
|
19
38
|
fit4ruby!
|
20
|
-
|
21
|
-
|
39
|
+
pry (>= 0.12)
|
40
|
+
rake (~> 12.0.0)
|
41
|
+
rspec (>= 3.8)
|
42
|
+
yard (~> 0.9.20)
|
43
|
+
|
44
|
+
BUNDLED WITH
|
45
|
+
2.0.2
|
data/fit4ruby.gemspec
CHANGED
@@ -25,7 +25,9 @@ EOT
|
|
25
25
|
spec.required_ruby_version = '>=2.0'
|
26
26
|
|
27
27
|
spec.add_dependency('bindata', '=2.3.0')
|
28
|
-
spec.add_development_dependency('yard', '~>0.9.
|
29
|
-
spec.add_development_dependency('rake', '~>0.
|
28
|
+
spec.add_development_dependency('yard', '~>0.9.20')
|
29
|
+
spec.add_development_dependency('rake', '~>12.0.0')
|
30
30
|
spec.add_development_dependency('bundler', '>=1.6.4')
|
31
|
+
spec.add_development_dependency('rspec', '>=3.8')
|
32
|
+
spec.add_development_dependency('pry', '>=0.12')
|
31
33
|
end
|
data/lib/fit4ruby/Activity.rb
CHANGED
@@ -24,6 +24,7 @@ require 'fit4ruby/UserProfile'
|
|
24
24
|
require 'fit4ruby/PhysiologicalMetrics'
|
25
25
|
require 'fit4ruby/Session'
|
26
26
|
require 'fit4ruby/Lap'
|
27
|
+
require 'fit4ruby/Length'
|
27
28
|
require 'fit4ruby/Record'
|
28
29
|
require 'fit4ruby/HRV'
|
29
30
|
require 'fit4ruby/HeartRateZones'
|
@@ -40,7 +41,7 @@ module Fit4Ruby
|
|
40
41
|
attr_accessor :file_id, :field_descriptions, :developer_data_ids, :epo_data,
|
41
42
|
:file_creator, :device_infos, :sensor_settings, :data_sources,
|
42
43
|
:user_data, :user_profiles, :physiological_metrics,
|
43
|
-
:sessions, :laps, :records, :hrv,
|
44
|
+
:sessions, :laps, :records, :lengths, :hrv,
|
44
45
|
:heart_rate_zones, :events, :personal_records
|
45
46
|
|
46
47
|
# Create a new Activity object.
|
@@ -65,15 +66,21 @@ module Fit4Ruby
|
|
65
66
|
@events = []
|
66
67
|
@sessions = []
|
67
68
|
@laps = []
|
69
|
+
@lengths = []
|
68
70
|
@records = []
|
69
71
|
@hrv = []
|
70
72
|
@heart_rate_zones = []
|
71
73
|
@personal_records = []
|
72
74
|
|
73
75
|
@cur_session_laps = []
|
76
|
+
|
74
77
|
@cur_lap_records = []
|
78
|
+
@cur_lap_lengths = []
|
79
|
+
|
80
|
+
@cur_length_records = []
|
75
81
|
|
76
82
|
@lap_counter = 1
|
83
|
+
@length_counter = 1
|
77
84
|
|
78
85
|
set_field_values(field_values)
|
79
86
|
end
|
@@ -141,11 +148,20 @@ module Fit4Ruby
|
|
141
148
|
|
142
149
|
# Laps must have a consecutively growing message index.
|
143
150
|
@laps.each.with_index do |lap, index|
|
144
|
-
lap.check(index)
|
151
|
+
lap.check(index, self)
|
145
152
|
# If we have heart rate zone records, there should be one for each
|
146
153
|
# lap
|
147
154
|
@heart_rate_zones[index].check(index) if @heart_rate_zones[index]
|
148
155
|
end
|
156
|
+
|
157
|
+
# Lengths must have a consecutively growing message index.
|
158
|
+
@lengths.each.with_index do |length, index|
|
159
|
+
length.check(index)
|
160
|
+
# If we have heart rate zone records, there should be one for each
|
161
|
+
# length
|
162
|
+
@heart_rate_zones[index].check(index) if @heart_rate_zones[index]
|
163
|
+
end
|
164
|
+
|
149
165
|
@sessions.each { |s| s.check(self) }
|
150
166
|
end
|
151
167
|
|
@@ -206,17 +222,22 @@ module Fit4Ruby
|
|
206
222
|
d
|
207
223
|
end
|
208
224
|
|
209
|
-
# Call this method to update the aggregated data fields stored in Lap
|
210
|
-
# Session objects.
|
225
|
+
# Call this method to update the aggregated data fields stored in Lap,
|
226
|
+
# Length, and Session objects.
|
211
227
|
def aggregate
|
212
228
|
@laps.each { |l| l.aggregate }
|
229
|
+
@lengths.each { |l| l.aggregate }
|
213
230
|
@sessions.each { |s| s.aggregate }
|
214
231
|
end
|
215
232
|
|
216
233
|
# Convenience method that averages the speed over all sessions.
|
217
234
|
def avg_speed
|
218
235
|
speed = 0.0
|
219
|
-
@sessions.each
|
236
|
+
@sessions.each do |s|
|
237
|
+
if (spd = s.avg_speed || s.enhanced_avg_speed)
|
238
|
+
speed += spd
|
239
|
+
end
|
240
|
+
end
|
220
241
|
speed / @sessions.length
|
221
242
|
end
|
222
243
|
|
@@ -292,8 +313,8 @@ module Fit4Ruby
|
|
292
313
|
@device_infos + @sensor_settings +
|
293
314
|
@data_sources + @user_profiles +
|
294
315
|
@physiological_metrics + @events +
|
295
|
-
@sessions + @laps + @records + @
|
296
|
-
@personal_records).sort.each do |s|
|
316
|
+
@sessions + @laps + @records + @lengths +
|
317
|
+
@heart_rate_zones + @personal_records).sort.each do |s|
|
297
318
|
s.write(io, id_mapper)
|
298
319
|
end
|
299
320
|
super
|
@@ -404,6 +425,16 @@ module Fit4Ruby
|
|
404
425
|
new_fit_data_record('lap', field_values)
|
405
426
|
end
|
406
427
|
|
428
|
+
# Add a new Length to the Activity. All previoulsy added Record objects are
|
429
|
+
# associated with this Length unless they have been associated with another
|
430
|
+
# Length before.
|
431
|
+
# @param field_values [Hash] A Hash that provides initial values for
|
432
|
+
# certain fields of the FitDataRecord.
|
433
|
+
# @return [Length]
|
434
|
+
def new_length(field_values = {})
|
435
|
+
new_fit_data_record('length', field_values)
|
436
|
+
end
|
437
|
+
|
407
438
|
# Add a new HeartRateZones record to the Activity.
|
408
439
|
# @param field_values [Heash] A Hash that provides initial values for
|
409
440
|
# certain fields of the FitDataRecord.
|
@@ -496,8 +527,12 @@ module Fit4Ruby
|
|
496
527
|
@cur_session_laps = []
|
497
528
|
when 'lap'
|
498
529
|
record = create_new_lap(field_values)
|
530
|
+
when 'length'
|
531
|
+
record = create_new_length(field_values)
|
499
532
|
when 'record'
|
500
|
-
|
533
|
+
record = Record.new(field_values)
|
534
|
+
@cur_lap_records << record
|
535
|
+
@cur_length_records << record
|
501
536
|
@records << record
|
502
537
|
when 'hrv'
|
503
538
|
@hrv << (record = HRV.new(field_values))
|
@@ -515,16 +550,29 @@ module Fit4Ruby
|
|
515
550
|
private
|
516
551
|
|
517
552
|
def create_new_lap(field_values)
|
518
|
-
lap = Lap.new(@cur_lap_records, @laps.last,
|
553
|
+
lap = Lap.new(@cur_lap_records, @laps.last,
|
554
|
+
field_values,
|
555
|
+
@length_counter, @cur_lap_lengths)
|
519
556
|
lap.message_index = @lap_counter - 1
|
520
557
|
@lap_counter += 1
|
521
558
|
@cur_session_laps << lap
|
522
559
|
@laps << lap
|
523
560
|
@cur_lap_records = []
|
561
|
+
@cur_lap_lengths = []
|
524
562
|
|
525
563
|
lap
|
526
564
|
end
|
527
565
|
|
566
|
+
def create_new_length(field_values)
|
567
|
+
length = Length.new(@cur_length_records, @lengths.last, field_values)
|
568
|
+
length.message_index = @length_counter - 1
|
569
|
+
@length_counter += 1
|
570
|
+
@cur_lap_lengths << length
|
571
|
+
@lengths << length
|
572
|
+
@cur_length_records = []
|
573
|
+
|
574
|
+
length
|
575
|
+
end
|
528
576
|
end
|
529
577
|
|
530
578
|
end
|
data/lib/fit4ruby/DeviceInfo.rb
CHANGED
@@ -32,6 +32,43 @@ module Fit4Ruby
|
|
32
32
|
@timestamp <=> fdr.timestamp
|
33
33
|
end
|
34
34
|
|
35
|
+
def numeric_manufacturer
|
36
|
+
if @manufacturer && @manufacturer.is_a?(String)
|
37
|
+
if @manufacturer[0..17] == 'Undocumented value'
|
38
|
+
return @manufacturer[18..-1].to_i
|
39
|
+
else
|
40
|
+
return GlobalFitDictionaries['manufacturer'].
|
41
|
+
value_by_name(@manufacturer)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
Log.fatal "Unexpected @manufacturer (#{@manufacturer}) value"
|
46
|
+
end
|
47
|
+
|
48
|
+
def numeric_product
|
49
|
+
# The numeric product ID must be an integer or nil. In case the
|
50
|
+
# dictionary did not contain an entry for the numeric ID in the fit file
|
51
|
+
# the @garmin_product or @product variables contain a String starting
|
52
|
+
# with 'Undocumented value ' followed by the ID.
|
53
|
+
if @garmin_product && @garmin_product.is_a?(String)
|
54
|
+
if @garmin_product[0..17] == 'Undocumented value'
|
55
|
+
return @garmin_product[18..-1].to_i
|
56
|
+
else
|
57
|
+
return GlobalFitDictionaries['garmin_product'].
|
58
|
+
value_by_name(@garmin_product)
|
59
|
+
end
|
60
|
+
elsif @product && @product.is_a?(String)
|
61
|
+
if @product[0..17] == 'Undocumented value'
|
62
|
+
return @product[18..-1].to_i
|
63
|
+
else
|
64
|
+
return GlobalFitDictionaries['product'].value_by_name(@product)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
Log.fatal "Unexpected @product (#{@product}) or " +
|
69
|
+
"@garmin_product (#{@garmin_product}) values"
|
70
|
+
end
|
71
|
+
|
35
72
|
def check(index)
|
36
73
|
unless @device_index
|
37
74
|
Log.fatal 'device info record must have a device_index'
|
@@ -47,6 +47,12 @@ module Fit4Ruby
|
|
47
47
|
Log.error "fit_base_type_id #{@fit_base_type_id} is too large"
|
48
48
|
return
|
49
49
|
end
|
50
|
+
|
51
|
+
name = "_#{@developer_data_index}_#{@field_name}"
|
52
|
+
# A fit file may include multiple definitions of the same field. We
|
53
|
+
# ignore all subsequent definitions.
|
54
|
+
return if msg.has_field?(name)
|
55
|
+
|
50
56
|
options = {}
|
51
57
|
options[:scale] = @scale if @scale
|
52
58
|
options[:offset] = @offset if @offset
|
@@ -54,7 +60,7 @@ module Fit4Ruby
|
|
54
60
|
options[:unit] = @units
|
55
61
|
msg.field(@field_definition_number,
|
56
62
|
FIT_TYPE_DEFS[@fit_base_type_id & 0x7F][1],
|
57
|
-
|
63
|
+
name, options)
|
58
64
|
end
|
59
65
|
|
60
66
|
end
|
@@ -21,7 +21,7 @@ module Fit4Ruby
|
|
21
21
|
|
22
22
|
RecordOrder = [ 'user_data', 'user_profile',
|
23
23
|
'device_info', 'data_sources', 'event',
|
24
|
-
'record', 'lap', 'session', 'heart_rate_zones',
|
24
|
+
'record', 'lap', 'length', 'session', 'heart_rate_zones',
|
25
25
|
'personal_records' ]
|
26
26
|
|
27
27
|
attr_reader :message
|
@@ -50,8 +50,8 @@ module Fit4Ruby
|
|
50
50
|
def set(name, value)
|
51
51
|
ivar_name = '@' + name
|
52
52
|
unless instance_variable_defined?(ivar_name)
|
53
|
-
Log.
|
54
|
-
|
53
|
+
Log.debug("Unknown FIT record field '#{name}' in global message " +
|
54
|
+
"#{@message.name} (#{@message.number}).")
|
55
55
|
return
|
56
56
|
end
|
57
57
|
instance_variable_set(ivar_name, value)
|
@@ -54,8 +54,8 @@ module Fit4Ruby
|
|
54
54
|
else
|
55
55
|
@name = "field#{field_definition_number.snapshot}"
|
56
56
|
@type = nil
|
57
|
-
Log.
|
58
|
-
|
57
|
+
Log.debug { "Unknown field number #{field_definition_number} " +
|
58
|
+
"in global message #{@global_message_number}" }
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
@@ -36,7 +36,7 @@ module Fit4Ruby
|
|
36
36
|
@name = @gfm.name
|
37
37
|
else
|
38
38
|
@name = "message#{@global_message_number}"
|
39
|
-
Log.
|
39
|
+
Log.debug { "Unknown global message number #{@global_message_number}" }
|
40
40
|
end
|
41
41
|
@message_record = produce(definition)
|
42
42
|
end
|
@@ -59,8 +59,8 @@ module Fit4Ruby
|
|
59
59
|
end
|
60
60
|
obj = entity.new_fit_data_record(@name)
|
61
61
|
|
62
|
-
# It's important to ensure that alternative fields processed after
|
63
|
-
# regular fields so that the decision field has already been
|
62
|
+
# It's important to ensure that alternative fields are processed after
|
63
|
+
# the regular fields so that the decision field has already been set.
|
64
64
|
sorted_fields = @definition.data_fields.sort do |f1, f2|
|
65
65
|
f1alt = is_alt_field?(f1)
|
66
66
|
f2alt = is_alt_field?(f2)
|
@@ -312,50 +312,306 @@ module Fit4Ruby
|
|
312
312
|
entry 144, 'uint64z'
|
313
313
|
|
314
314
|
dict 'garmin_product'
|
315
|
+
entry 1, 'hrm1'
|
316
|
+
entry 2, 'axh01'
|
317
|
+
entry 3, 'axb01'
|
318
|
+
entry 4, 'axb02'
|
319
|
+
entry 5, 'hrm2ss'
|
320
|
+
entry 6, 'dsi_alf02'
|
321
|
+
entry 7, 'hrm3ss'
|
315
322
|
entry 8, 'hrm_run_single_byte_product_id'
|
316
323
|
entry 9, 'bsm'
|
317
324
|
entry 10, 'bcm'
|
325
|
+
entry 11, 'axs01'
|
326
|
+
entry 12, 'hrm_tri_single_byte_product_id'
|
327
|
+
entry 13, 'hrm4_run_single_byte_product_id'
|
328
|
+
entry 14, 'fr225_single_byte_product_id'
|
329
|
+
entry 473, 'fr301_china'
|
330
|
+
entry 474, 'fr301_japan'
|
331
|
+
entry 475, 'fr301_korea'
|
332
|
+
entry 494, 'fr301_taiwan'
|
333
|
+
entry 717, 'fr405'
|
334
|
+
entry 782, 'fr50'
|
335
|
+
entry 987, 'fr405_japan'
|
336
|
+
entry 988, 'fr60'
|
337
|
+
entry 1011, 'dsi_alf01'
|
338
|
+
entry 1018, 'fr310xt'
|
339
|
+
entry 1036, 'edge500'
|
340
|
+
entry 1124, 'fr110'
|
341
|
+
entry 1169, 'edge800'
|
342
|
+
entry 1199, 'edge500_taiwan'
|
343
|
+
entry 1213, 'edge500_japan'
|
344
|
+
entry 1253, 'chirp'
|
345
|
+
entry 1274, 'fr110_japan'
|
346
|
+
entry 1325, 'edge200'
|
347
|
+
entry 1328, 'fr910xt'
|
348
|
+
entry 1333, 'edge800_taiwan'
|
349
|
+
entry 1334, 'edge800_japan'
|
350
|
+
entry 1341, 'alf04'
|
351
|
+
entry 1345, 'fr610'
|
352
|
+
entry 1360, 'fr210_japan'
|
353
|
+
entry 1380, 'vector_ss'
|
354
|
+
entry 1381, 'vector_cp'
|
355
|
+
entry 1386, 'edge800_china'
|
356
|
+
entry 1387, 'edge500_china'
|
357
|
+
entry 1405, 'approach_g10'
|
358
|
+
entry 1410, 'fr610_japan'
|
359
|
+
entry 1422, 'edge500_korea'
|
360
|
+
entry 1436, 'fr70'
|
361
|
+
entry 1446, 'fr310xt_4t'
|
362
|
+
entry 1461, 'amx'
|
363
|
+
entry 1482, 'fr10'
|
364
|
+
entry 1497, 'edge800_korea'
|
365
|
+
entry 1499, 'swim'
|
366
|
+
entry 1537, 'fr910xt_china'
|
318
367
|
entry 1551, 'fenix'
|
368
|
+
entry 1555, 'edge200_taiwan'
|
369
|
+
entry 1561, 'edge510'
|
370
|
+
entry 1567, 'edge810'
|
371
|
+
entry 1570, 'tempe'
|
372
|
+
entry 1600, 'fr910xt_japan'
|
319
373
|
# The Fenix3 is rumored to have a Mediatek MT3333 GPS chipset. Not sure if
|
320
374
|
# that would be a beter name.
|
321
375
|
entry 1620, 'fenix3_gps' # Just a guess
|
322
376
|
entry 1621, 'fenix5_gps' # Just a guess
|
323
377
|
entry 1623, 'fr620'
|
324
378
|
entry 1632, 'fr220'
|
379
|
+
entry 1664, 'fr910xt_korea'
|
380
|
+
entry 1688, 'fr10_japan'
|
325
381
|
# The FR620 is rumored to have a MediaTek MT3339 GPS chipset while the
|
326
382
|
# FR920XT is rumored to have a MT3333. Not sure why they have the same ID
|
327
383
|
# in the FIT file for the GPS device.
|
328
384
|
entry 1689, 'fr620_fr920xt_gps' # Just a guess
|
385
|
+
entry 1721, 'edge810_japan'
|
386
|
+
entry 1735, 'virb_elite'
|
387
|
+
entry 1736, 'edge_touring'
|
388
|
+
entry 1742, 'edge510_japan'
|
329
389
|
entry 1743, 'hrm_tri'
|
330
390
|
entry 1752, 'hrm_run'
|
331
391
|
entry 1765, 'fr920xt'
|
392
|
+
entry 1821, 'edge510_asia'
|
393
|
+
entry 1822, 'edge810_china'
|
394
|
+
entry 1823, 'edge810_taiwan'
|
395
|
+
entry 1836, 'edge1000'
|
396
|
+
entry 1837, 'vivo_fit'
|
397
|
+
entry 1853, 'virb_remote'
|
398
|
+
entry 1885, 'vivo_ki'
|
399
|
+
entry 1903, 'fr15'
|
400
|
+
entry 1907, 'vivo_active'
|
401
|
+
entry 1918, 'edge510_korea'
|
332
402
|
entry 1928, 'fr620_japan'
|
333
403
|
entry 1929, 'fr620_china'
|
334
404
|
entry 1930, 'fr220_japan'
|
335
405
|
entry 1931, 'fr220_china'
|
406
|
+
entry 1936, 'approach_s6'
|
407
|
+
entry 1956, 'vivo_smart'
|
336
408
|
entry 1967, 'fenix2'
|
337
409
|
entry 1988, 'epix'
|
338
410
|
entry 2050, 'fenix3'
|
411
|
+
entry 2052, 'edge1000_taiwan'
|
412
|
+
entry 2053, 'edge1000_japan'
|
413
|
+
entry 2061, 'fr15_japan'
|
414
|
+
entry 2067, 'edge520'
|
415
|
+
entry 2070, 'edge1000_china'
|
339
416
|
entry 2072, 'fr620_russia'
|
340
417
|
entry 2073, 'fr220_russia'
|
418
|
+
entry 2079, 'vector_s'
|
419
|
+
entry 2100, 'edge1000_korea'
|
341
420
|
entry 2130, 'fr920xt_taiwan'
|
342
421
|
entry 2131, 'fr920xt_china'
|
343
422
|
entry 2132, 'fr920xt_japan'
|
423
|
+
entry 2134, 'virbx'
|
424
|
+
entry 2135, 'vivo_smart_apac'
|
425
|
+
entry 2140, 'etrex_touch'
|
426
|
+
entry 2147, 'edge25'
|
427
|
+
entry 2148, 'fr25'
|
428
|
+
entry 2150, 'vivo_fit2'
|
429
|
+
entry 2153, 'fr225'
|
430
|
+
entry 2156, 'fr630'
|
431
|
+
entry 2157, 'fr230'
|
432
|
+
entry 2158, 'fr735xt'
|
433
|
+
entry 2160, 'vivo_active_apac'
|
434
|
+
entry 2161, 'vector_2'
|
435
|
+
entry 2162, 'vector_2s'
|
436
|
+
entry 2172, 'virbxe'
|
344
437
|
entry 2173, 'fr620_taiwan'
|
438
|
+
entry 2174, 'fr220_taiwan'
|
439
|
+
entry 2175, 'truswing'
|
345
440
|
entry 2188, 'fenix3_china'
|
346
441
|
entry 2189, 'fenix3_twn'
|
442
|
+
entry 2192, 'varia_headlight'
|
443
|
+
entry 2193, 'varia_taillight_old'
|
444
|
+
entry 2204, 'edge_explore_1000'
|
445
|
+
entry 2219, 'fr225_asia'
|
446
|
+
entry 2225, 'varia_radar_taillight'
|
447
|
+
entry 2226, 'varia_radar_display'
|
448
|
+
entry 2238, 'edge20'
|
449
|
+
entry 2260, 'edge520_asia'
|
450
|
+
entry 2261, 'edge520_japan'
|
451
|
+
entry 2262, 'd2_bravo'
|
452
|
+
entry 2266, 'approach_s20'
|
453
|
+
entry 2271, 'vivo_smart2'
|
454
|
+
entry 2274, 'edge1000_thai'
|
455
|
+
entry 2276, 'varia_remote'
|
456
|
+
entry 2288, 'edge25_asia'
|
457
|
+
entry 2289, 'edge25_jpn'
|
458
|
+
entry 2290, 'edge20_asia'
|
459
|
+
entry 2292, 'approach_x40'
|
460
|
+
entry 2293, 'fenix3_japan'
|
461
|
+
entry 2294, 'vivo_smart_emea'
|
462
|
+
entry 2310, 'fr630_asia'
|
463
|
+
entry 2311, 'fr630_jpn'
|
464
|
+
entry 2313, 'fr230_jpn'
|
347
465
|
entry 2327, 'hrm4_run'
|
466
|
+
entry 2332, 'epix_japan'
|
467
|
+
entry 2337, 'vivo_active_hr'
|
468
|
+
entry 2347, 'vivo_smart_gps_hr'
|
469
|
+
entry 2348, 'vivo_smart_hr'
|
470
|
+
entry 2361, 'vivo_smart_hr_asia'
|
471
|
+
entry 2362, 'vivo_smart_gps_hr_asia'
|
472
|
+
entry 2368, 'vivo_move'
|
473
|
+
entry 2379, 'varia_taillight'
|
474
|
+
entry 2397, 'fr235_japan'
|
475
|
+
entry 2398, 'varia_vision'
|
476
|
+
entry 2406, 'vivo_fit3'
|
477
|
+
entry 2407, 'fenix3_korea'
|
478
|
+
entry 2408, 'fenix3_sea'
|
348
479
|
entry 2413, 'fenix3_hr'
|
480
|
+
entry 2417, 'virb_ultra_30'
|
481
|
+
entry 2429, 'index_smart_scale'
|
349
482
|
entry 2431, 'fr235'
|
350
483
|
entry 2432, 'fenix3_chronos'
|
484
|
+
entry 2441, 'oregon7xx'
|
485
|
+
entry 2444, 'rino7xx'
|
486
|
+
entry 2457, 'epix_korea'
|
487
|
+
entry 2473, 'fenix3_hr_chn'
|
488
|
+
entry 2474, 'fenix3_hr_twn'
|
489
|
+
entry 2475, 'fenix3_hr_jpn'
|
490
|
+
entry 2476, 'fenix3_hr_sea'
|
491
|
+
entry 2477, 'fenix3_hr_kor'
|
492
|
+
entry 2496, 'nautix'
|
493
|
+
entry 2497, 'vivo_active_hr_apac'
|
494
|
+
entry 2512, 'oregon7xx_ww'
|
495
|
+
entry 2530, 'edge_820'
|
496
|
+
entry 2531, 'edge_explore_820'
|
497
|
+
entry 2533, 'fr735xt_apac'
|
498
|
+
entry 2534, 'fr735xt_japan'
|
351
499
|
entry 2544, 'fenix5s'
|
352
|
-
entry
|
500
|
+
entry 2547, 'd2_bravo_titanium'
|
501
|
+
entry 2567, 'varia_ut800'
|
353
502
|
entry 2593, 'running_dynamics_pod'
|
503
|
+
entry 2599, 'edge_820_china'
|
504
|
+
entry 2600, 'edge_820_japan'
|
505
|
+
entry 2604, 'fenix5x'
|
506
|
+
entry 2606, 'vivo_fit_jr'
|
507
|
+
entry 2622, 'vivo_smart3'
|
508
|
+
entry 2623, 'vivo_sport'
|
509
|
+
entry 2628, 'edge_820_taiwan'
|
510
|
+
entry 2629, 'edge_820_korea'
|
511
|
+
entry 2630, 'edge_820_sea'
|
512
|
+
entry 2650, 'fr35_hebrew'
|
513
|
+
entry 2656, 'approach_s60'
|
514
|
+
entry 2667, 'fr35_apac'
|
515
|
+
entry 2668, 'fr35_japan'
|
516
|
+
entry 2675, 'fenix3_chronos_asia'
|
517
|
+
entry 2687, 'virb_360'
|
354
518
|
entry 2691, 'fr935'
|
355
519
|
entry 2697, 'fenix5'
|
520
|
+
entry 2700, 'vivoactive3'
|
521
|
+
entry 2733, 'fr235_china_nfc'
|
522
|
+
entry 2769, 'foretrex_601_701'
|
523
|
+
entry 2772, 'vivo_move_hr'
|
524
|
+
entry 2713, 'edge_1030'
|
525
|
+
entry 2796, 'fenix5_asia'
|
526
|
+
entry 2797, 'fenix5s_asia'
|
527
|
+
entry 2798, 'fenix5x_asia'
|
528
|
+
entry 2806, 'approach_z80'
|
529
|
+
entry 2814, 'fr35_korea'
|
530
|
+
entry 2819, 'd2charlie'
|
531
|
+
entry 2831, 'vivo_smart3_apac'
|
532
|
+
entry 2832, 'vivo_sport_apac'
|
533
|
+
entry 2833, 'fr935_asia'
|
534
|
+
entry 2859, 'descent'
|
535
|
+
entry 2886, 'fr645'
|
536
|
+
entry 2888, 'fr645m'
|
537
|
+
entry 2891, 'fr30'
|
538
|
+
entry 2900, 'fenix5s_plus'
|
539
|
+
entry 2909, 'Edge_130'
|
540
|
+
entry 2924, 'edge_1030_asia'
|
541
|
+
entry 2927, 'vivosmart_4'
|
542
|
+
entry 2945, 'vivo_move_hr_asia'
|
356
543
|
entry 2957, 'fenix5_gps_galileo' # Just a guess
|
544
|
+
entry 2962, 'approach_x10'
|
545
|
+
entry 2977, 'fr30_asia'
|
546
|
+
entry 2988, 'vivoactive3m_w'
|
547
|
+
entry 3003, 'fr645_asia'
|
548
|
+
entry 3004, 'fr645m_asia'
|
549
|
+
entry 3011, 'edge_explore'
|
550
|
+
entry 3028, 'gpsmap66'
|
551
|
+
entry 3049, 'approach_s10'
|
552
|
+
entry 3066, 'vivoactive3m_l'
|
553
|
+
entry 3085, 'approach_g80'
|
554
|
+
entry 3092, 'edge_130_asia'
|
555
|
+
entry 3095, 'edge_1030_bontrager'
|
556
|
+
entry 3110, 'fenix5_plus'
|
357
557
|
entry 3111, 'fenix5x_plus'
|
558
|
+
entry 3112, 'edge_520_plus'
|
559
|
+
entry 3121, 'edge_530'
|
560
|
+
entry 3122, 'edge_830'
|
561
|
+
entry 3134, 'fenix5s_plus_apac'
|
562
|
+
entry 3135, 'fenix5x_plus_apac'
|
563
|
+
entry 3142, 'edge_520_plus_apac'
|
564
|
+
entry 3144, 'fr235l_asia'
|
565
|
+
entry 3145, 'fr245_asia'
|
566
|
+
entry 3163, 'vivo_active3m_apac'
|
567
|
+
entry 3218, 'vivo_smart4_asia'
|
568
|
+
entry 3224, 'vivoactive4_small'
|
569
|
+
entry 3225, 'vivoactive4_large'
|
570
|
+
entry 3226, 'venu'
|
571
|
+
entry 3246, 'marq_driver'
|
572
|
+
entry 3247, 'marq_aviator'
|
573
|
+
entry 3248, 'marq_captain'
|
574
|
+
entry 3249, 'marq_commander'
|
575
|
+
entry 3250, 'marq_expedition'
|
576
|
+
entry 3251, 'marq_athlete'
|
577
|
+
entry 3287, 'fenix6S_sport'
|
578
|
+
entry 3288, 'fenix6S'
|
579
|
+
entry 3289, 'fenix6_sport'
|
580
|
+
entry 3290, 'fenix6'
|
581
|
+
entry 3291, 'fenix6x'
|
582
|
+
entry 3299, 'hrm_dual'
|
583
|
+
entry 3308, 'vivo_move3_premium'
|
584
|
+
entry 3314, 'approach_s40'
|
585
|
+
entry 3321, 'fr245m_asia'
|
586
|
+
entry 3349, 'edge_530_apac'
|
587
|
+
entry 3350, 'edge_830_apac'
|
588
|
+
entry 3378, 'vivo_move3'
|
589
|
+
entry 3387, 'vivo_active4_small_asia'
|
590
|
+
entry 3388, 'vivo_active4_large_asia'
|
591
|
+
entry 3389, 'vivo_active4_oled_asia'
|
592
|
+
entry 3405, 'swim2'
|
593
|
+
entry 3420, 'marq_driver_asia'
|
594
|
+
entry 3421, 'marq_aviator_asia'
|
595
|
+
entry 3422, 'vivo_move3_asia'
|
596
|
+
entry 3446, 'vivo_active3t_chn'
|
597
|
+
entry 3448, 'marq_captain_asia'
|
598
|
+
entry 3449, 'marq_commander_asia'
|
599
|
+
entry 3450, 'marq_expedition_asia'
|
600
|
+
entry 3451, 'marq_athlete_asia'
|
601
|
+
entry 3469, 'fr45_asia'
|
602
|
+
entry 3473, 'vivoactive3_daimler'
|
603
|
+
entry 3512, 'fenix6s_sport_asia'
|
604
|
+
entry 3513, 'fenix6s_asia'
|
605
|
+
entry 3514, 'fenix6_sport_asia'
|
606
|
+
entry 3515, 'fenix6_asia'
|
607
|
+
entry 3516, 'fenix6x_asia'
|
608
|
+
entry 3624, 'marq_adventurer'
|
609
|
+
entry 3648, 'marq_adventurer_asia'
|
610
|
+
entry 3639, 'swim2_apac'
|
611
|
+
entry 3737, 'venu_daimler_asia'
|
612
|
+
entry 3740, 'venu_daimler'
|
358
613
|
entry 10007, 'sdm4'
|
614
|
+
entry 10014, 'edge_remote'
|
359
615
|
entry 20119, 'training_center'
|
360
616
|
entry 65532, 'android_antplus_plugin'
|
361
617
|
entry 65534, 'connect'
|
@@ -593,7 +849,7 @@ module Fit4Ruby
|
|
593
849
|
dict 'swim_stroke'
|
594
850
|
entry 0, 'freestyle'
|
595
851
|
entry 1, 'backstroke'
|
596
|
-
entry 2, '
|
852
|
+
entry 2, 'breaststroke'
|
597
853
|
entry 3, 'butterfly'
|
598
854
|
entry 4, 'drill'
|
599
855
|
entry 5, 'mixed'
|
@@ -627,39 +883,39 @@ module Fit4Ruby
|
|
627
883
|
entry 24, 'challenge'
|
628
884
|
entry 25, 'indoor_skiing'
|
629
885
|
entry 26, 'cardio_training'
|
630
|
-
entry 27, 'indoor_walking
|
631
|
-
entry 28, 'e_bike_fitness
|
886
|
+
entry 27, 'indoor_walking'
|
887
|
+
entry 28, 'e_bike_fitness'
|
632
888
|
entry 29, 'bmx'
|
633
|
-
entry 30, 'casual_walking
|
889
|
+
entry 30, 'casual_walking'
|
634
890
|
entry 31, 'speed_walking'
|
635
|
-
entry 32, 'bike_to_run_transition
|
636
|
-
entry 33, 'run_to_bike_transition
|
891
|
+
entry 32, 'bike_to_run_transition'
|
892
|
+
entry 33, 'run_to_bike_transition'
|
637
893
|
entry 34, 'swim_to_bike_transition'
|
638
894
|
entry 35, 'atv'
|
639
895
|
entry 36, 'motocross'
|
640
896
|
entry 37, 'backcountry'
|
641
|
-
entry 38, 'resort
|
642
|
-
entry 39, 'rc_drone
|
643
|
-
entry 40, 'wingsuit
|
644
|
-
entry 41, 'whitewater
|
645
|
-
entry 42, 'skate_skiing
|
646
|
-
entry 43, 'yoga
|
897
|
+
entry 38, 'resort'
|
898
|
+
entry 39, 'rc_drone'
|
899
|
+
entry 40, 'wingsuit'
|
900
|
+
entry 41, 'whitewater'
|
901
|
+
entry 42, 'skate_skiing'
|
902
|
+
entry 43, 'yoga'
|
647
903
|
entry 44, 'pilates'
|
648
|
-
entry 45, 'indoor_running
|
649
|
-
entry 46, 'gravel_cycling
|
904
|
+
entry 45, 'indoor_running'
|
905
|
+
entry 46, 'gravel_cycling'
|
650
906
|
entry 47, 'e_bike_mountain'
|
651
907
|
entry 48, 'commuting'
|
652
908
|
entry 49, 'mixed_surface'
|
653
|
-
entry 50, 'navigate
|
654
|
-
entry 51, 'track_me
|
909
|
+
entry 50, 'navigate'
|
910
|
+
entry 51, 'track_me'
|
655
911
|
entry 52, 'map'
|
656
912
|
entry 53, 'single_gas_diving'
|
657
|
-
entry 54, 'multi_gas_diving
|
658
|
-
entry 55, 'gauge_diving
|
659
|
-
entry 56, 'apnea_diving
|
913
|
+
entry 54, 'multi_gas_diving'
|
914
|
+
entry 55, 'gauge_diving'
|
915
|
+
entry 56, 'apnea_diving'
|
660
916
|
entry 57, 'apnea_hunting'
|
661
|
-
entry 58, 'virtual_activity
|
662
|
-
entry 59, 'obstacle
|
917
|
+
entry 58, 'virtual_activity'
|
918
|
+
entry 59, 'obstacle'
|
663
919
|
entry 254, 'all'
|
664
920
|
|
665
921
|
dict 'training_status'
|