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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 247b4e5fd81ffc3c5e12bc1d3235196126fdb8cc
4
- data.tar.gz: b493e5b073e63d977ed28edc3600dac73519d0b6
2
+ SHA256:
3
+ metadata.gz: 1867e2f6e32d331216b372024ba0607837bb5dc3baf7daad107b5a23d6465aa6
4
+ data.tar.gz: 25f0423ccf5e68259f48d02f35400fa2a723a9f7209613f77eca2631d056f2d0
5
5
  SHA512:
6
- metadata.gz: 88b2fe75bdf8a1bfb4a6f3d4892db4253f942a3a251118fc054f4671f9f3927960552fe9005334da6f884e95990babae029071edbf287740efaff2450748824b
7
- data.tar.gz: f8aa4152a1d37f682d0ca526045d10a19628ba79bad41eebbf3b3e3e963fcb971fc82d38fef8756b2bfa50eaefd3eea80388c849cb1bc0bf34aa79d64754e7eb
6
+ metadata.gz: 05641db1523d5e8a9b8ab939d4b65def4e5a50ca6bbcae3fb1c727dc7d641cfeda6d7a5e892b38819b840b0a2222e0d775d20bf4f93ae4af6db2c79b4b6753b3
7
+ data.tar.gz: f4b7d619de81444329009c7a188f08bd4684524ecc1654a57b77df147a0e22730658d57247e30729f619a0ab2c6fbd6fce796908df05ff2d409a06a909656298
@@ -1,15 +1,34 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fit4ruby (0.0.1)
5
- bindata (>= 2.0.0)
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.1.0)
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
- yard (0.8.7.4)
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
- rake
21
- yard
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
@@ -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.12')
29
- spec.add_development_dependency('rake', '~>0.9.6')
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
@@ -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 and
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 { |s| speed += s.avg_speed }
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 + @heart_rate_zones +
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
- @cur_lap_records << (record = Record.new(field_values))
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, field_values)
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
@@ -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
- "_#{@developer_data_index}_#{@field_name}", options)
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.warn("Unknown FIT record field '#{name}' in global message " +
54
- "#{@message.name} (#{@message.number}).")
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.warn { "Unknown field number #{field_definition_number} " +
58
- "in global message #{@global_message_number}" }
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.warn { "Unknown global message number #{@global_message_number}" }
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 the
63
- # regular fields so that the decision field has already been already set.
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 2604, 'fenix5x'
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, 'breaststrike'
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'