fit4ruby 3.0.0 → 3.1.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
  SHA1:
3
- metadata.gz: b4ee014802983dc12f9d4204e29e1c80d33be729
4
- data.tar.gz: 7d52d887dea393412752a72974d189452ffea3e3
3
+ metadata.gz: d789b2e373decc4dfff48739b65a320c66da88fd
4
+ data.tar.gz: 1a40f4aac55b45f66cb082b6ffef4ca6e3c3ed9e
5
5
  SHA512:
6
- metadata.gz: 0d306e3ff6d58837943461a2508c6a81d05043b49eb186e352f273e11b341ffe6b0db92e500d764e327c37f38c5f3a5ec466a8bb8172599dd1df563a3b9a0075
7
- data.tar.gz: cb7692535f35056b613c8f9e3a334d9690400ec2f614c8e5676af0919cb8132b1a280caa7efcd3c6265044008def7deed8a6e706e4718aad1be57a96b12700f3
6
+ metadata.gz: 2ec0e96be6dd2d0cf44b03a5ac41197a693d4a4b8861063a55f7d37e98252656f380d8cb57bb4d77476d7f805fdab1668c598f5ec81208e7225102e151b12e8a
7
+ data.tar.gz: d92c14c4af7c98c043d3a675bb8eefa741fe30b18a05d4606358cd69a49c05b4564355b1c213dac9c9196d1b1c2f0bf5122bca7808652db310fccf1c59fe92f1
@@ -261,10 +261,10 @@ module Fit4Ruby
261
261
  @events.each do |e|
262
262
  return e.vo2max if e.event == 'vo2max'
263
263
  end
264
- # Then check the user_profile entries for a metmax entry. METmax * 3.5
264
+ # Then check the user_data entries for a metmax entry. METmax * 3.5
265
265
  # is same value as VO2max.
266
- @user_profiles.each do |u|
267
- return u.metmax * 3.5 if u.metmax
266
+ @user_data.each do |u|
267
+ return ((u.metmax * 1000.0) * 3.5) / 1024.0 if u.metmax
268
268
  end
269
269
 
270
270
  nil
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = CRC16.rb -- Fit4Ruby - FIT file processing library for Ruby
5
+ #
6
+ # Copyright (c) 2014, 2015, 2016, 2017, 2018
7
+ # by Chris Schlaeger <cs@taskjuggler.org>
8
+ #
9
+ # This program is free software; you can redistribute it and/or modify
10
+ # it under the terms of version 2 of the GNU General Public License as
11
+ # published by the Free Software Foundation.
12
+ #
13
+
14
+ module Fit4Ruby
15
+
16
+ module CRC16
17
+
18
+ def write_crc(io, start_pos, end_pos)
19
+ # Compute the checksum over the data section of the file and append it
20
+ # to the file. Ideally, we should compute the CRC from data in memory
21
+ # instead of the file data.
22
+ crc = compute_crc(io, start_pos, end_pos)
23
+ io.seek(end_pos)
24
+ BinData::Uint16le.new(crc).write(io)
25
+
26
+ crc
27
+ end
28
+
29
+ def compute_crc(io, start_pos, end_pos)
30
+ crc_table = [
31
+ 0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401,
32
+ 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400
33
+ ]
34
+
35
+ io.seek(start_pos)
36
+
37
+ crc = 0
38
+ while io.pos < end_pos
39
+ if io.eof?
40
+ raise IOError, "Premature end of file"
41
+ end
42
+
43
+ byte = io.readbyte
44
+
45
+ 0.upto(1) do |i|
46
+ tmp = crc_table[crc & 0xF]
47
+ crc = (crc >> 4) & 0x0FFF
48
+ crc = crc ^ tmp ^ crc_table[(byte >> (4 * i)) & 0xF]
49
+ end
50
+ end
51
+
52
+ crc
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+
@@ -3,7 +3,8 @@
3
3
  #
4
4
  # = FitFile.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, 2016, 2017, 2018
7
+ # by Chris Schlaeger <cs@taskjuggler.org>
7
8
  #
8
9
  # This program is free software; you can redistribute it and/or modify
9
10
  # it under the terms of version 2 of the GNU General Public License as
@@ -11,6 +12,7 @@
11
12
  #
12
13
 
13
14
  require 'fit4ruby/Log'
15
+ require 'fit4ruby/CRC16'
14
16
  require 'fit4ruby/FileNameCoder'
15
17
  require 'fit4ruby/FitHeader'
16
18
  require 'fit4ruby/FitFileEntity'
@@ -24,6 +26,8 @@ module Fit4Ruby
24
26
 
25
27
  class FitFile
26
28
 
29
+ include CRC16
30
+
27
31
  def initialize()
28
32
  @header = nil
29
33
  end
@@ -43,9 +47,14 @@ module Fit4Ruby
43
47
  offset = io.pos
44
48
 
45
49
  header = FitHeader.read(io)
46
- header.check
47
50
 
48
- check_crc(io, io.pos, offset + header.end_pos)
51
+ # If the header has a CRC the header is not included in the
52
+ # checksumed bytes. Otherwise it is included.
53
+ check_crc(io, header.has_crc? ? header.header_size : 0,
54
+ offset + header.end_pos)
55
+
56
+ # Rewind back to the beginning of the data right after the header.
57
+ io.seek(header.header_size)
49
58
 
50
59
  entity = FitFileEntity.new
51
60
  # This Array holds the raw data of the records that may be needed to
@@ -86,6 +95,7 @@ module Fit4Ruby
86
95
  # Create a header object, but don't yet write it into the file.
87
96
  header = FitHeader.new
88
97
  start_pos = header.header_size
98
+
89
99
  # Move the pointer behind the header section.
90
100
  io.seek(start_pos)
91
101
  id_mapper = FitMessageIdMapper.new
@@ -97,7 +107,6 @@ module Fit4Ruby
97
107
  # Complete the data of the header section and write it at the start of
98
108
  # the file.
99
109
  header.data_size = end_pos - start_pos
100
- header.crc = crc
101
110
  io.seek(0)
102
111
  header.write(io)
103
112
  ensure
@@ -113,47 +122,14 @@ module Fit4Ruby
113
122
  # Read the 2 CRC bytes from the end of the file
114
123
  io.seek(end_pos)
115
124
  crc_ref = io.readbyte.to_i | (io.readbyte.to_i << 8)
116
- io.seek(start_pos)
117
125
 
118
126
  unless crc == crc_ref
119
- Log.fatal "Checksum error in file '#{@file_name}'. " +
127
+ Log.error "Checksum error of segment #{start_pos} to #{end_pos} " +
128
+ "in file '#{@file_name}'. " +
120
129
  "Computed 0x#{"%04X" % crc} instead of 0x#{"%04X" % crc_ref}."
121
130
  end
122
131
  end
123
132
 
124
- def write_crc(io, start_pos, end_pos)
125
- # Compute the checksum over the data section of the file and append it
126
- # to the file. Ideally, we should compute the CRC from data in memory
127
- # instead of the file data.
128
- crc = compute_crc(io, start_pos, end_pos)
129
- io.seek(end_pos)
130
- BinData::Uint16le.new(crc).write(io)
131
-
132
- crc
133
- end
134
-
135
- def compute_crc(io, start_pos, end_pos)
136
- crc_table = [
137
- 0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401,
138
- 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400
139
- ]
140
-
141
- io.seek(start_pos)
142
-
143
- crc = 0
144
- while io.pos < end_pos
145
- byte = io.readbyte
146
-
147
- 0.upto(1) do |i|
148
- tmp = crc_table[crc & 0xF]
149
- crc = (crc >> 4) & 0x0FFF
150
- crc = crc ^ tmp ^ crc_table[(byte >> (4 * i)) & 0xF]
151
- end
152
- end
153
-
154
- crc
155
- end
156
-
157
133
  def dump_records(records)
158
134
  # For each message number we keep a count for how often we already had
159
135
  # this kind of message.
@@ -3,7 +3,8 @@
3
3
  #
4
4
  # = FitHeader.rb -- Fit4Ruby - FIT file processing library for Ruby
5
5
  #
6
- # Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org>
6
+ # Copyright (c) 2014, 2015, 2016, 2017, 2018
7
+ # by Chris Schlaeger <cs@taskjuggler.org>
7
8
  #
8
9
  # This program is free software; you can redistribute it and/or modify
9
10
  # it under the terms of version 2 of the GNU General Public License as
@@ -12,41 +13,60 @@
12
13
 
13
14
  require 'bindata'
14
15
  require 'fit4ruby/Log'
16
+ require 'fit4ruby/CRC16'
15
17
 
16
18
  module Fit4Ruby
17
19
 
18
20
  class FitHeader < BinData::Record
19
21
 
22
+ include CRC16
23
+
20
24
  endian :little
21
25
 
22
26
  uint8 :header_size, :initial_value => 14
23
- uint8 :protocol_version, :initial_value => 16
27
+ uint8 :protocol_version, :initial_value => 32
24
28
  uint16 :profile_version, :initial_value => 1012
25
29
  uint32 :data_size, :initial_value => 0
26
30
  string :data_type, :read_length => 4, :initial_value => '.FIT'
27
- uint16 :crc, :initial_value => 0
31
+ uint16 :crc, :initial_value => 0, :onlyif => :has_crc?
32
+
33
+ def read(io)
34
+ super
28
35
 
29
- def check
30
- unless header_size == 14
31
- Log.fatal "Unsupported header size #{header_size}"
36
+ unless header_size.snapshot == 12 || header_size.snapshot == 14
37
+ Log.fatal "Unsupported header size #{header_size.snapshot}"
32
38
  end
33
- unless data_type == '.FIT'
34
- Log.fatal "Unknown file type #{data_type}"
39
+ unless data_type.snapshot == '.FIT'
40
+ Log.fatal "Unknown file type #{data_type.snapshot}"
35
41
  end
42
+ if crc.snapshot != 0 &&
43
+ compute_crc(io, 0, header_size.snapshot - 2) != crc.snapshot
44
+ Log.fatal "CRC mismatch in header."
45
+ end
46
+ end
47
+
48
+ def write(io)
49
+ super
50
+
51
+ write_crc(io, 0, header_size.snapshot - 2)
36
52
  end
37
53
 
38
54
  def dump
39
55
  puts <<"EOT"
40
56
  Fit File Header
41
- Header Size: #{header_size}
42
- Protocol Version: #{protocol_version}
43
- Profile Version: #{profile_version}
44
- Data Size: #{data_size}
57
+ Header Size: #{header_size.snapshot}
58
+ Protocol Version: #{protocol_version.snapshot}
59
+ Profile Version: #{profile_version.snapshot}
60
+ Data Size: #{data_size.snapshot}
45
61
  EOT
46
62
  end
47
63
 
64
+ def has_crc?
65
+ header_size.snapshot == 14
66
+ end
67
+
48
68
  def end_pos
49
- header_size + data_size
69
+ header_size.snapshot + data_size.snapshot
50
70
  end
51
71
 
52
72
  end
@@ -304,6 +304,8 @@ module Fit4Ruby
304
304
 
305
305
  dict 'garmin_product'
306
306
  entry 8, 'hrm_run_single_byte_product_id'
307
+ entry 9, 'bsm'
308
+ entry 10, 'bcm'
307
309
  entry 1551, 'fenix'
308
310
  # The Fenix3 is rumored to have a Mediatek MT3333 GPS chipset. Not sure if
309
311
  # that would be a beter name.
@@ -470,7 +472,61 @@ module Fit4Ruby
470
472
  entry 85, 'woodway'
471
473
  entry 86, 'elite'
472
474
  entry 95, 'stryd'
475
+ entry 96, 'icg'
476
+ entry 97, 'MiPulse'
477
+ entry 98, 'bsx_athletics'
478
+ entry 99, 'look'
479
+ entry 100, 'campagnolo_srl'
480
+ entry 101, 'body_bike_smart'
481
+ entry 102, 'praxisworks'
482
+ entry 103, 'limits_technology'
483
+ entry 104, 'topaction_technology'
484
+ entry 105, 'cosinuss'
485
+ entry 106, 'fitcare'
486
+ entry 107, 'magene'
487
+ entry 108, 'giant_manufacturing_co'
488
+ entry 109, 'tigrasport'
489
+ entry 110, 'salutron'
490
+ entry 111, 'technogym'
491
+ entry 112, 'bryton_sensors'
492
+ entry 113, 'latitude_limited'
493
+ entry 114, 'soaring_technology'
494
+ entry 115, 'igpsport'
495
+ entry 116, 'thinkrider'
496
+ entry 117, 'gopher_sport'
497
+ entry 118, 'waterrower'
473
498
  entry 255, 'development'
499
+ entry 257, 'healthandlife'
500
+ entry 258, 'lezyne'
501
+ entry 259, 'scribe_labs'
502
+ entry 260, 'zwift'
503
+ entry 261, 'watteam'
504
+ entry 262, 'recon'
505
+ entry 263, 'favero_electronics'
506
+ entry 264, 'dynovelo'
507
+ entry 265, 'strava'
508
+ entry 266, 'precor'
509
+ entry 267, 'bryton'
510
+ entry 268, 'sram'
511
+ entry 269, 'navman'
512
+ entry 270, 'cobi'
513
+ entry 271, 'spivi'
514
+ entry 272, 'mio_magellan'
515
+ entry 273, 'evesports'
516
+ entry 274, 'sensitivus_gauge'
517
+ entry 275, 'podoon'
518
+ entry 276, 'life_time_fitness'
519
+ entry 277, 'falco_e_motors'
520
+ entry 278, 'minoura'
521
+ entry 279, 'cycliq'
522
+ entry 280, 'luxottica'
523
+ entry 281, 'trainer_road'
524
+ entry 282, 'the_sufferfest'
525
+ entry 283, 'fullspeedahead'
526
+ entry 284, 'virtualtraining'
527
+ entry 285, 'feedbacksports'
528
+ entry 286, 'omata'
529
+ entry 287, 'vdo'
474
530
  entry 5759, 'actigraphcorp'
475
531
 
476
532
  dict 'message_index'
@@ -560,6 +616,39 @@ module Fit4Ruby
560
616
  entry 24, 'challenge'
561
617
  entry 25, 'indoor_skiing'
562
618
  entry 26, 'cardio_training'
619
+ entry 27, 'indoor_walking '
620
+ entry 28, 'e_bike_fitness '
621
+ entry 29, 'bmx'
622
+ entry 30, 'casual_walking '
623
+ entry 31, 'speed_walking'
624
+ entry 32, 'bike_to_run_transition '
625
+ entry 33, 'run_to_bike_transition '
626
+ entry 34, 'swim_to_bike_transition'
627
+ entry 35, 'atv'
628
+ entry 36, 'motocross'
629
+ entry 37, 'backcountry'
630
+ entry 38, 'resort '
631
+ entry 39, 'rc_drone '
632
+ entry 40, 'wingsuit '
633
+ entry 41, 'whitewater '
634
+ entry 42, 'skate_skiing '
635
+ entry 43, 'yoga '
636
+ entry 44, 'pilates'
637
+ entry 45, 'indoor_running '
638
+ entry 46, 'gravel_cycling '
639
+ entry 47, 'e_bike_mountain'
640
+ entry 48, 'commuting'
641
+ entry 49, 'mixed_surface'
642
+ entry 50, 'navigate '
643
+ entry 51, 'track_me '
644
+ entry 52, 'map'
645
+ entry 53, 'single_gas_diving'
646
+ entry 54, 'multi_gas_diving '
647
+ entry 55, 'gauge_diving '
648
+ entry 56, 'apnea_diving '
649
+ entry 57, 'apnea_hunting'
650
+ entry 58, 'virtual_activity '
651
+ entry 59, 'obstacle '
563
652
  entry 254, 'all'
564
653
 
565
654
  end
@@ -100,6 +100,7 @@ module Fit4Ruby
100
100
  field 128, 'enum', 'undocumented_field_128'
101
101
  field 133, 'enum', 'undocumented_field_133'
102
102
  field 138, 'enum', 'undocumented_field_138'
103
+ field 144, 'enum', 'true_up_enabled'
103
104
 
104
105
  message 3, 'user_profile'
105
106
  field 0, 'string', 'friendly_name'
@@ -134,6 +135,7 @@ module Fit4Ruby
134
135
  field 41, 'uint32', 'undocumented_field_41'
135
136
  field 42, 'uint32', 'undocumented_field_42'
136
137
  field 43, 'enum', 'undocumented_field_43'
138
+ field 253, 'uint32', 'timestamp', :type => 'date_time'
137
139
 
138
140
  message 7, 'zones_target'
139
141
  field 1, 'uint8', 'max_heart_rate'
@@ -202,6 +204,8 @@ module Fit4Ruby
202
204
  field 55, 'enum', 'undocumented_field_55'
203
205
  field 57, 'enum', 'undocumented_field_57'
204
206
  field 60, 'enum', 'undocumented_field_60'
207
+ field 65, 'enum', 'undocumented_field_65'
208
+ field 66, 'enum', 'undocumented_field_66'
205
209
  field 254, 'uint16', 'message_index'
206
210
 
207
211
  message 18, 'session'
@@ -417,7 +421,11 @@ module Fit4Ruby
417
421
  field 5, 'uint32', 'distance', :scale => 100, :unit => 'm'
418
422
  field 6, 'uint16', 'speed', :scale => 1000, :unit => 'm/s'
419
423
  field 7, 'uint16', 'power', :unit => 'watts'
424
+ field 8, 'byte', 'compressed_speed_distance', :array => true
425
+ field 9, 'sint16', 'grade', :scale => 100, :unit => '%'
426
+ field 10, 'uint8', 'resistence'
420
427
  field 11, 'sint32', 'time_from_course', :scale => 1000, :unit => 's'
428
+ field 12, 'uint8', 'cycle_length', :scale => 100, :unit => 'm'
421
429
  field 13, 'sint8', 'temperature', :unit => 'C'
422
430
  field 14, 'uint32', 'undefined_field_14'
423
431
  field 15, 'uint32', 'undefined_field_15'
@@ -572,6 +580,7 @@ module Fit4Ruby
572
580
  field 4, 'enum', 'event_type', :dict => 'event_type'
573
581
  field 5, 'uint32', 'local_timestamp', :type => 'date_time'
574
582
  field 6, 'uint8', 'event_group'
583
+ field 7, 'uint8', 'undocumented_field_7'
575
584
  field 253, 'uint32', 'timestamp', :type => 'date_time'
576
585
 
577
586
  message 35, 'software'
@@ -581,6 +590,7 @@ module Fit4Ruby
581
590
  message 49, 'file_creator'
582
591
  field 0, 'uint16', 'software_version'
583
592
  field 1, 'uint8', 'hardware_version'
593
+ field 2, 'string', 'undocumented_field_2'
584
594
  field 254, 'uint16', 'message_index', :dict => 'message_index'
585
595
 
586
596
  message 55, 'monitoring'
@@ -744,6 +754,10 @@ module Fit4Ruby
744
754
  field 23, 'uint8', 'undocumented_field_23'
745
755
  field 24, 'sint32', 'undocumented_field_24'
746
756
  field 25, 'uint8', 'undocumented_field_25'
757
+ field 26, 'sint32', 'undocumented_field_26'
758
+ field 29, 'sint32', 'undocumented_field_29'
759
+ field 34, 'enum', 'undocumented_field_34'
760
+ field 35, 'uint32', 'undocumented_field_35'
747
761
  field 253, 'uint32', 'timestamp', :type => 'date_time'
748
762
 
749
763
  # Not part of the official ANT SDK doc. The message name is guessed and
@@ -812,6 +826,11 @@ module Fit4Ruby
812
826
  field 62, 'uint8', 'undocumented_field_62'
813
827
  field 254, 'uint16', 'message_index'
814
828
 
829
+ # Not part of the official ANT SDK doc.
830
+ message 188, 'undocumented_188'
831
+ field 0, 'enum', 'undocumented_field_0'
832
+ field 253, 'uint32', 'timestamp', :type => 'date_time'
833
+
815
834
  message 206, 'field_description'
816
835
  field 0, 'uint8', 'developer_data_index'
817
836
  field 1, 'uint8', 'field_definition_number'
@@ -857,11 +876,10 @@ module Fit4Ruby
857
876
  field 15, 'uint16', 'undocumented_field_15'
858
877
  field 253, 'uint32', 'timestamp', :type => 'date_time'
859
878
 
860
- # Not part of the official ANT SDK doc.
861
- message 227, 'stress'
862
- field 0, 'sint16', 'undocumented_0'
863
- field 1, 'uint32', 'undocumented_1'
864
- field 2, 'sint8', 'level'
879
+ message 227, 'stress_level'
880
+ field 0, 'sint16', 'stress_level_value'
881
+ field 1, 'uint32', 'stress_level_time', :type => 'date_time'
882
+ field 2, 'sint8', 'undocumented_field_2'
865
883
 
866
884
  message 1024, 'undocumented_1024'
867
885
  field 0, 'enum', 'undocumented_field_0'
@@ -1,4 +1,4 @@
1
1
  module Fit4Ruby
2
2
  # The version number of the library.
3
- VERSION = '3.0.0'
3
+ VERSION = '3.1.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.0.0
4
+ version: 3.1.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: 2018-03-04 00:00:00.000000000 Z
11
+ date: 2018-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bindata
@@ -84,6 +84,7 @@ files:
84
84
  - fit4ruby.gemspec
85
85
  - lib/fit4ruby.rb
86
86
  - lib/fit4ruby/Activity.rb
87
+ - lib/fit4ruby/CRC16.rb
87
88
  - lib/fit4ruby/Converters.rb
88
89
  - lib/fit4ruby/DataSources.rb
89
90
  - lib/fit4ruby/DeveloperDataId.rb