garmin-fit 0.0.2

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.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MDc2YmQ4NTI5MWE2NTAxZjdiZjM5Y2UzNDc3MGZiODc5YzUwNDYwNw==
5
+ data.tar.gz: !binary |-
6
+ ZjQ0MTJkNzI0ZGM3ZDlkNzY1NTA2ZTA3ZWY2YWZjNGRkNWRiMmE0Nw==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ YTM0NWYwMmVhNjdhNjI3NmEyZjk1OGNiZTdmZTdkODk3NzgxNWE4N2RkMDk4
10
+ NmQ3Y2UyZmM2NjRhY2YzZjIxZTA1ZTFjYzQ4MGRhNGJkM2U0ODM1ZmE1MThj
11
+ ZDc1NzkwMjllOTU5MTEwZGYxNzVhMTY2M2JmYWJlYWEzZDc0MWM=
12
+ data.tar.gz: !binary |-
13
+ ZDkxMzYxOWY2YzMxNGM1ZGJlNzk4YWI1Njc4NjIzNjBlYjFiMTcxYTE0YjE1
14
+ YTEzMjc0NDkxMmJiMDdhNDE3MjkzZTYzZDMwOTk0YzM1MGY4YTY3MWU5MWU3
15
+ ZjUyMGVmNjczMWVkMGVlZDM0YTI0ZjY2OTU2YzQ1N2Q0ZWU0Y2Q=
@@ -0,0 +1,20 @@
1
+ require 'bindata'
2
+ require 'active_support/core_ext/class'
3
+
4
+ require 'fit/file'
5
+ require 'fit/file/header'
6
+ require 'fit/file/record'
7
+ require 'fit/file/record_header'
8
+ require 'fit/file/definition'
9
+ require 'fit/file/data'
10
+ require 'fit/file/definitions'
11
+
12
+ require 'fit/version'
13
+
14
+ module Fit
15
+
16
+ def self.load_file(path)
17
+ File.read ::File.open(path)
18
+ end
19
+
20
+ end
@@ -0,0 +1,29 @@
1
+ module Fit
2
+ class File
3
+
4
+ def self.read(io)
5
+ new.read(io)
6
+ end
7
+
8
+ attr_reader :header, :records, :crc
9
+
10
+ def initialize
11
+ @records = []
12
+ end
13
+
14
+ def read(io)
15
+ @header = Header.read(io)
16
+
17
+ Record.clear_definitions!
18
+
19
+ while io.pos < @header.end_pos
20
+ @records << Record.read(io)
21
+ end
22
+
23
+ @crc = io.read(2)
24
+
25
+ self
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,36 @@
1
+ module Fit
2
+ class File
3
+ class Data < BinData::Record
4
+
5
+ class_attribute :global_message_number, :instance_writer => false
6
+
7
+ def self.generate(definition)
8
+ type = Definitions.get_name(definition.global_message_number.snapshot) ||
9
+ "data_record_#{definition.global_message_number.snapshot}"
10
+
11
+ Class.new(self) do
12
+ self.global_message_number = definition.global_message_number.snapshot
13
+
14
+ endian definition.endianness
15
+
16
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
17
+ def record_type
18
+ :#{type}
19
+ end
20
+ RUBY
21
+
22
+ definition.fields.each do |field|
23
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
24
+ #{field.type} :#{field.raw_name}
25
+
26
+ def #{field.name}
27
+ #{field.raw_name}.snapshot #{ "/ #{field.scale.inspect}.0" if field.scale }
28
+ end
29
+ RUBY
30
+ end
31
+ end
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,94 @@
1
+ module Fit
2
+ class File
3
+ class Definition < BinData::Record
4
+
5
+ class Field < BinData::Record
6
+ hide :reserved_bits
7
+
8
+ uint8 :field_definition_number
9
+ uint8 :field_size
10
+ bit1 :endian_ability
11
+ bit2 :reserved_bits
12
+ bit5 :base_type_number
13
+
14
+ def data
15
+ @data ||= Definitions.get_field(parent.parent.global_message_number.snapshot,
16
+ field_definition_number.snapshot) ||
17
+ { :name => "field_#{field_definition_number.snapshot}", :scale => nil }
18
+ end
19
+
20
+ def name
21
+ data[:name]
22
+ end
23
+
24
+ def raw_name
25
+ "raw_#{name}"
26
+ end
27
+
28
+ def scale
29
+ data[:scale]
30
+ end
31
+
32
+ def type
33
+ case base_type_number.snapshot
34
+ when 0 # enum
35
+ build_int_type 8, false
36
+ when 1
37
+ build_int_type 8, true
38
+ when 2
39
+ build_int_type 8, false
40
+ when 3
41
+ build_int_type 16, true
42
+ when 4
43
+ build_int_type 16, false
44
+ when 5
45
+ build_int_type 32, true
46
+ when 6
47
+ build_int_type 32, false
48
+ when 7
49
+ "stringz"
50
+ when 8
51
+ "float"
52
+ when 9
53
+ "double"
54
+ when 10 # uint8z
55
+ build_int_type 8, false
56
+ when 11 # uint16z
57
+ build_int_type 16, false
58
+ when 12 # uint32z
59
+ build_int_type 32, false
60
+ when 13 # array of bytes
61
+ build_int_type 8, false
62
+ else
63
+ raise "Can't map base_type_number #{base_type_number} to a data type"
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ def build_int_type(length, signed)
70
+ (signed ? '' : 'u') << 'int' << length.to_s
71
+ end
72
+ end
73
+
74
+ skip :length => 1
75
+ bit8 :architecture
76
+ choice :global_message_number, :selection => :architecture do
77
+ uint16le 0
78
+ uint16be 1
79
+ end
80
+ bit8 :field_count
81
+ array :fields, :type => Field, :initial_length => :field_count
82
+
83
+ def endianness
84
+ architecture.snapshot == 0 ? :little : :big
85
+ end
86
+
87
+ def record_type
88
+ :definition
89
+ end
90
+
91
+ end
92
+ end
93
+ end
94
+
@@ -0,0 +1,408 @@
1
+ module Fit
2
+ class File
3
+ module Definitions
4
+
5
+ @@fields = Hash.new{ |h,k| h[k]= {} }
6
+ @@names = Hash.new
7
+
8
+ class << self
9
+ def add_field(global_msg_num, field_def_num, name, options = {})
10
+ @@fields[global_msg_num][field_def_num] = options.merge(:name => name)
11
+ end
12
+
13
+ def get_field(global_msg_num, field_def_num)
14
+ @@fields[global_msg_num][field_def_num]
15
+ end
16
+
17
+ def add_name(global_msg_num, name)
18
+ @@names[global_msg_num] = name
19
+ end
20
+
21
+ def get_name(global_msg_num)
22
+ @@names[global_msg_num]
23
+ end
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+
30
+ # DATA
31
+ Fit::File::Definitions.add_name 0, "file_id"
32
+ Fit::File::Definitions.add_field 0, 0, "type", :type => 0, :scale => 1, :offset => 0
33
+ Fit::File::Definitions.add_field 0, 1, "manufacturer", :type => 4, :scale => 1, :offset => 0
34
+ Fit::File::Definitions.add_field 0, 2, "product", :type => 4, :scale => 1, :offset => 0
35
+ Fit::File::Definitions.add_field 0, 2, "garmin_product", :type => 4, :scale => 1, :offset => 0
36
+ Fit::File::Definitions.add_field 0, 3, "serial_number", :type => 12, :scale => 1, :offset => 0
37
+ Fit::File::Definitions.add_field 0, 4, "time_created", :type => 6, :scale => 1, :offset => 0
38
+ Fit::File::Definitions.add_field 0, 5, "number", :type => 4, :scale => 1, :offset => 0
39
+
40
+ Fit::File::Definitions.add_name 49, "file_creator"
41
+ Fit::File::Definitions.add_field 49, 0, "software_version", :type => 4, :scale => 1, :offset => 0
42
+ Fit::File::Definitions.add_field 49, 1, "hardware_version", :type => 2, :scale => 1, :offset => 0
43
+
44
+ Fit::File::Definitions.add_name 35, "software"
45
+ Fit::File::Definitions.add_field 35, 254, "message_index", :type => 4, :scale => 1, :offset => 0
46
+ Fit::File::Definitions.add_field 35, 3, "version", :type => 4, :scale => 100, :offset => 0
47
+ Fit::File::Definitions.add_field 35, 5, "part_number", :type => 7, :scale => 1, :offset => 0
48
+
49
+ Fit::File::Definitions.add_name 1, "capabilities"
50
+ Fit::File::Definitions.add_field 1, 0, "languages", :type => 10, :scale => 1, :offset => 0
51
+ Fit::File::Definitions.add_field 1, 1, "sports", :type => 10, :scale => 1, :offset => 0
52
+ Fit::File::Definitions.add_field 1, 21, "workouts_supported", :type => 12, :scale => 1, :offset => 0
53
+
54
+ Fit::File::Definitions.add_name 37, "file_capabilities"
55
+ Fit::File::Definitions.add_field 37, 254, "message_index", :type => 4, :scale => 1, :offset => 0
56
+ Fit::File::Definitions.add_field 37, 0, "type", :type => 0, :scale => 1, :offset => 0
57
+ Fit::File::Definitions.add_field 37, 1, "flags", :type => 10, :scale => 1, :offset => 0
58
+ Fit::File::Definitions.add_field 37, 2, "directory", :type => 7, :scale => 1, :offset => 0
59
+ Fit::File::Definitions.add_field 37, 3, "max_count", :type => 4, :scale => 1, :offset => 0
60
+ Fit::File::Definitions.add_field 37, 4, "max_size", :type => 6, :scale => 1, :offset => 0, :units => "bytes"
61
+
62
+ Fit::File::Definitions.add_name 38, "mesg_capabilities"
63
+ Fit::File::Definitions.add_field 38, 254, "message_index", :type => 4, :scale => 1, :offset => 0
64
+ Fit::File::Definitions.add_field 38, 0, "file", :type => 0, :scale => 1, :offset => 0
65
+ Fit::File::Definitions.add_field 38, 1, "mesg_num", :type => 4, :scale => 1, :offset => 0
66
+ Fit::File::Definitions.add_field 38, 2, "count_type", :type => 0, :scale => 1, :offset => 0
67
+ Fit::File::Definitions.add_field 38, 3, "count", :type => 4, :scale => 1, :offset => 0
68
+ Fit::File::Definitions.add_field 38, 3, "num_per_file", :type => 4, :scale => 1, :offset => 0
69
+ Fit::File::Definitions.add_field 38, 3, "max_per_file", :type => 4, :scale => 1, :offset => 0
70
+ Fit::File::Definitions.add_field 38, 3, "max_per_file_type", :type => 4, :scale => 1, :offset => 0
71
+
72
+ Fit::File::Definitions.add_name 39, "field_capabilities"
73
+ Fit::File::Definitions.add_field 39, 254, "message_index", :type => 4, :scale => 1, :offset => 0
74
+ Fit::File::Definitions.add_field 39, 0, "file", :type => 0, :scale => 1, :offset => 0
75
+ Fit::File::Definitions.add_field 39, 1, "mesg_num", :type => 4, :scale => 1, :offset => 0
76
+ Fit::File::Definitions.add_field 39, 2, "field_num", :type => 2, :scale => 1, :offset => 0
77
+ Fit::File::Definitions.add_field 39, 3, "count", :type => 4, :scale => 1, :offset => 0
78
+
79
+ Fit::File::Definitions.add_name 2, "device_settings"
80
+ Fit::File::Definitions.add_field 2, 1, "utc_offset", :type => 6, :scale => 1, :offset => 0
81
+
82
+ Fit::File::Definitions.add_name 3, "user_profile"
83
+ Fit::File::Definitions.add_field 3, 254, "message_index", :type => 4, :scale => 1, :offset => 0
84
+ Fit::File::Definitions.add_field 3, 0, "friendly_name", :type => 7, :scale => 1, :offset => 0
85
+ Fit::File::Definitions.add_field 3, 1, "gender", :type => 0, :scale => 1, :offset => 0
86
+ Fit::File::Definitions.add_field 3, 2, "age", :type => 2, :scale => 1, :offset => 0, :units => "years"
87
+ Fit::File::Definitions.add_field 3, 3, "height", :type => 2, :scale => 100, :offset => 0, :units => "m"
88
+ Fit::File::Definitions.add_field 3, 4, "weight", :type => 4, :scale => 10, :offset => 0, :units => "kg"
89
+ Fit::File::Definitions.add_field 3, 5, "language", :type => 0, :scale => 1, :offset => 0
90
+ Fit::File::Definitions.add_field 3, 6, "elev_setting", :type => 0, :scale => 1, :offset => 0
91
+ Fit::File::Definitions.add_field 3, 7, "weight_setting", :type => 0, :scale => 1, :offset => 0
92
+ Fit::File::Definitions.add_field 3, 8, "resting_heart_rate", :type => 2, :scale => 1, :offset => 0, :units => "bpm"
93
+ Fit::File::Definitions.add_field 3, 9, "default_max_running_heart_rate", :type => 2, :scale => 1, :offset => 0, :units => "bpm"
94
+ Fit::File::Definitions.add_field 3, 10, "default_max_biking_heart_rate", :type => 2, :scale => 1, :offset => 0, :units => "bpm"
95
+ Fit::File::Definitions.add_field 3, 11, "default_max_heart_rate", :type => 2, :scale => 1, :offset => 0, :units => "bpm"
96
+ Fit::File::Definitions.add_field 3, 12, "hr_setting", :type => 0, :scale => 1, :offset => 0
97
+ Fit::File::Definitions.add_field 3, 13, "speed_setting", :type => 0, :scale => 1, :offset => 0
98
+ Fit::File::Definitions.add_field 3, 14, "dist_setting", :type => 0, :scale => 1, :offset => 0
99
+ Fit::File::Definitions.add_field 3, 16, "power_setting", :type => 0, :scale => 1, :offset => 0
100
+ Fit::File::Definitions.add_field 3, 17, "activity_class", :type => 0, :scale => 1, :offset => 0
101
+ Fit::File::Definitions.add_field 3, 18, "position_setting", :type => 0, :scale => 1, :offset => 0
102
+ Fit::File::Definitions.add_field 3, 21, "temperature_setting", :type => 0, :scale => 1, :offset => 0
103
+ Fit::File::Definitions.add_field 3, 22, "local_id", :type => 4, :scale => 1, :offset => 0
104
+ Fit::File::Definitions.add_field 3, 23, "global_id", :type => 13, :scale => 1, :offset => 0
105
+
106
+ Fit::File::Definitions.add_name 4, "hrm_profile"
107
+ Fit::File::Definitions.add_field 4, 254, "message_index", :type => 4, :scale => 1, :offset => 0
108
+ Fit::File::Definitions.add_field 4, 0, "enabled", :type => 0, :scale => 1, :offset => 0
109
+ Fit::File::Definitions.add_field 4, 1, "hrm_ant_id", :type => 11, :scale => 1, :offset => 0
110
+
111
+ Fit::File::Definitions.add_name 5, "sdm_profile"
112
+ Fit::File::Definitions.add_field 5, 254, "message_index", :type => 4, :scale => 1, :offset => 0
113
+ Fit::File::Definitions.add_field 5, 0, "enabled", :type => 0, :scale => 1, :offset => 0
114
+ Fit::File::Definitions.add_field 5, 1, "sdm_ant_id", :type => 11, :scale => 1, :offset => 0
115
+ Fit::File::Definitions.add_field 5, 2, "sdm_cal_factor", :type => 4, :scale => 10, :offset => 0, :units => "%"
116
+ Fit::File::Definitions.add_field 5, 3, "odometer", :type => 6, :scale => 100, :offset => 0, :units => "m"
117
+ Fit::File::Definitions.add_field 5, 4, "speed_source", :type => 0, :scale => 1, :offset => 0
118
+
119
+ Fit::File::Definitions.add_name 6, "bike_profile"
120
+ Fit::File::Definitions.add_field 6, 254, "message_index", :type => 4, :scale => 1, :offset => 0
121
+ Fit::File::Definitions.add_field 6, 0, "name", :type => 7, :scale => 1, :offset => 0
122
+ Fit::File::Definitions.add_field 6, 1, "sport", :type => 0, :scale => 1, :offset => 0
123
+ Fit::File::Definitions.add_field 6, 2, "sub_sport", :type => 0, :scale => 1, :offset => 0
124
+ Fit::File::Definitions.add_field 6, 3, "odometer", :type => 6, :scale => 100, :offset => 0, :units => "m"
125
+ Fit::File::Definitions.add_field 6, 4, "bike_spd_ant_id", :type => 11, :scale => 1, :offset => 0
126
+ Fit::File::Definitions.add_field 6, 5, "bike_cad_ant_id", :type => 11, :scale => 1, :offset => 0
127
+ Fit::File::Definitions.add_field 6, 6, "bike_spdcad_ant_id", :type => 11, :scale => 1, :offset => 0
128
+ Fit::File::Definitions.add_field 6, 7, "bike_power_ant_id", :type => 11, :scale => 1, :offset => 0
129
+ Fit::File::Definitions.add_field 6, 8, "custom_wheelsize", :type => 4, :scale => 1000, :offset => 0, :units => "m"
130
+ Fit::File::Definitions.add_field 6, 9, "auto_wheelsize", :type => 4, :scale => 1000, :offset => 0, :units => "m"
131
+ Fit::File::Definitions.add_field 6, 10, "bike_weight", :type => 4, :scale => 10, :offset => 0, :units => "kg"
132
+ Fit::File::Definitions.add_field 6, 11, "power_cal_factor", :type => 4, :scale => 10, :offset => 0, :units => "%"
133
+ Fit::File::Definitions.add_field 6, 12, "auto_wheel_cal", :type => 0, :scale => 1, :offset => 0
134
+ Fit::File::Definitions.add_field 6, 13, "auto_power_zero", :type => 0, :scale => 1, :offset => 0
135
+ Fit::File::Definitions.add_field 6, 14, "id", :type => 2, :scale => 1, :offset => 0
136
+ Fit::File::Definitions.add_field 6, 15, "spd_enabled", :type => 0, :scale => 1, :offset => 0
137
+ Fit::File::Definitions.add_field 6, 16, "cad_enabled", :type => 0, :scale => 1, :offset => 0
138
+ Fit::File::Definitions.add_field 6, 17, "spdcad_enabled", :type => 0, :scale => 1, :offset => 0
139
+ Fit::File::Definitions.add_field 6, 18, "power_enabled", :type => 0, :scale => 1, :offset => 0
140
+
141
+ Fit::File::Definitions.add_name 7, "zones_target"
142
+ Fit::File::Definitions.add_field 7, 1, "max_heart_rate", :type => 2, :scale => 1, :offset => 0
143
+ Fit::File::Definitions.add_field 7, 2, "threshold_heart_rate", :type => 2, :scale => 1, :offset => 0
144
+ Fit::File::Definitions.add_field 7, 3, "functional_threshold_power", :type => 4, :scale => 1, :offset => 0
145
+ Fit::File::Definitions.add_field 7, 5, "hr_calc_type", :type => 0, :scale => 1, :offset => 0
146
+ Fit::File::Definitions.add_field 7, 7, "pwr_calc_type", :type => 0, :scale => 1, :offset => 0
147
+
148
+ Fit::File::Definitions.add_name 12, "sport"
149
+ Fit::File::Definitions.add_field 12, 0, "sport", :type => 0, :scale => 1, :offset => 0
150
+ Fit::File::Definitions.add_field 12, 1, "sub_sport", :type => 0, :scale => 1, :offset => 0
151
+ Fit::File::Definitions.add_field 12, 3, "name", :type => 7, :scale => 1, :offset => 0
152
+
153
+ Fit::File::Definitions.add_name 8, "hr_zone"
154
+ Fit::File::Definitions.add_field 8, 254, "message_index", :type => 4, :scale => 1, :offset => 0
155
+ Fit::File::Definitions.add_field 8, 1, "high_bpm", :type => 2, :scale => 1, :offset => 0, :units => "bpm"
156
+ Fit::File::Definitions.add_field 8, 2, "name", :type => 7, :scale => 1, :offset => 0
157
+
158
+ Fit::File::Definitions.add_name 9, "power_zone"
159
+ Fit::File::Definitions.add_field 9, 254, "message_index", :type => 4, :scale => 1, :offset => 0
160
+ Fit::File::Definitions.add_field 9, 1, "high_value", :type => 4, :scale => 1, :offset => 0, :units => "watts"
161
+ Fit::File::Definitions.add_field 9, 2, "name", :type => 7, :scale => 1, :offset => 0
162
+
163
+ Fit::File::Definitions.add_name 10, "met_zone"
164
+ Fit::File::Definitions.add_field 10, 254, "message_index", :type => 4, :scale => 1, :offset => 0
165
+ Fit::File::Definitions.add_field 10, 1, "high_bpm", :type => 2, :scale => 1, :offset => 0
166
+ Fit::File::Definitions.add_field 10, 2, "calories", :type => 4, :scale => 10, :offset => 0, :units => "kcal / min"
167
+ Fit::File::Definitions.add_field 10, 3, "fat_calories", :type => 2, :scale => 10, :offset => 0, :units => "kcal / min"
168
+
169
+ Fit::File::Definitions.add_name 15, "goal"
170
+ Fit::File::Definitions.add_field 15, 254, "message_index", :type => 4, :scale => 1, :offset => 0
171
+ Fit::File::Definitions.add_field 15, 0, "sport", :type => 0, :scale => 1, :offset => 0
172
+ Fit::File::Definitions.add_field 15, 1, "sub_sport", :type => 0, :scale => 1, :offset => 0
173
+ Fit::File::Definitions.add_field 15, 2, "start_date", :type => 6, :scale => 1, :offset => 0
174
+ Fit::File::Definitions.add_field 15, 3, "end_date", :type => 6, :scale => 1, :offset => 0
175
+ Fit::File::Definitions.add_field 15, 4, "type", :type => 0, :scale => 1, :offset => 0
176
+ Fit::File::Definitions.add_field 15, 5, "value", :type => 6, :scale => 1, :offset => 0
177
+ Fit::File::Definitions.add_field 15, 6, "repeat", :type => 0, :scale => 1, :offset => 0
178
+ Fit::File::Definitions.add_field 15, 7, "target_value", :type => 6, :scale => 1, :offset => 0
179
+ Fit::File::Definitions.add_field 15, 8, "recurrence", :type => 0, :scale => 1, :offset => 0
180
+ Fit::File::Definitions.add_field 15, 9, "recurrence_value", :type => 4, :scale => 1, :offset => 0
181
+ Fit::File::Definitions.add_field 15, 10, "enabled", :type => 0, :scale => 1, :offset => 0
182
+
183
+ Fit::File::Definitions.add_name 34, "activity"
184
+ Fit::File::Definitions.add_field 34, 253, "timestamp", :type => 6, :scale => 1, :offset => 0
185
+ Fit::File::Definitions.add_field 34, 0, "total_timer_time", :type => 6, :scale => 1000, :offset => 0, :units => "s"
186
+ Fit::File::Definitions.add_field 34, 1, "num_sessions", :type => 4, :scale => 1, :offset => 0
187
+ Fit::File::Definitions.add_field 34, 2, "type", :type => 0, :scale => 1, :offset => 0
188
+ Fit::File::Definitions.add_field 34, 3, "event", :type => 0, :scale => 1, :offset => 0
189
+ Fit::File::Definitions.add_field 34, 4, "event_type", :type => 0, :scale => 1, :offset => 0
190
+ Fit::File::Definitions.add_field 34, 5, "local_timestamp", :type => 6, :scale => 1, :offset => 0
191
+ Fit::File::Definitions.add_field 34, 6, "event_group", :type => 2, :scale => 1, :offset => 0
192
+
193
+ Fit::File::Definitions.add_name 18, "session"
194
+ Fit::File::Definitions.add_field 18, 254, "message_index", :type => 4, :scale => 1, :offset => 0
195
+ Fit::File::Definitions.add_field 18, 253, "timestamp", :type => 6, :scale => 1, :offset => 0, :units => "s"
196
+ Fit::File::Definitions.add_field 18, 0, "event", :type => 0, :scale => 1, :offset => 0
197
+ Fit::File::Definitions.add_field 18, 1, "event_type", :type => 0, :scale => 1, :offset => 0
198
+ Fit::File::Definitions.add_field 18, 2, "start_time", :type => 6, :scale => 1, :offset => 0
199
+ Fit::File::Definitions.add_field 18, 3, "start_position_lat", :type => 5, :scale => 1, :offset => 0, :units => "semicircles"
200
+ Fit::File::Definitions.add_field 18, 4, "start_position_long", :type => 5, :scale => 1, :offset => 0, :units => "semicircles"
201
+ Fit::File::Definitions.add_field 18, 5, "sport", :type => 0, :scale => 1, :offset => 0
202
+ Fit::File::Definitions.add_field 18, 6, "sub_sport", :type => 0, :scale => 1, :offset => 0
203
+ Fit::File::Definitions.add_field 18, 7, "total_elapsed_time", :type => 6, :scale => 1000, :offset => 0, :units => "s"
204
+ Fit::File::Definitions.add_field 18, 8, "total_timer_time", :type => 6, :scale => 1000, :offset => 0, :units => "s"
205
+ Fit::File::Definitions.add_field 18, 9, "total_distance", :type => 6, :scale => 100, :offset => 0, :units => "m"
206
+ Fit::File::Definitions.add_field 18, 10, "total_cycles", :type => 6, :scale => 1, :offset => 0, :units => "cycles"
207
+ Fit::File::Definitions.add_field 18, 10, "total_strides", :type => 6, :scale => 1, :offset => 0, :units => "strides"
208
+ Fit::File::Definitions.add_field 18, 11, "total_calories", :type => 4, :scale => 1, :offset => 0, :units => "kcal"
209
+ Fit::File::Definitions.add_field 18, 13, "total_fat_calories", :type => 4, :scale => 1, :offset => 0, :units => "kcal"
210
+ Fit::File::Definitions.add_field 18, 14, "avg_speed", :type => 4, :scale => 1000, :offset => 0, :units => "m/s"
211
+ Fit::File::Definitions.add_field 18, 15, "max_speed", :type => 4, :scale => 1000, :offset => 0, :units => "m/s"
212
+ Fit::File::Definitions.add_field 18, 16, "avg_heart_rate", :type => 2, :scale => 1, :offset => 0, :units => "bpm"
213
+ Fit::File::Definitions.add_field 18, 17, "max_heart_rate", :type => 2, :scale => 1, :offset => 0, :units => "bpm"
214
+ Fit::File::Definitions.add_field 18, 18, "avg_cadence", :type => 2, :scale => 1, :offset => 0, :units => "rpm"
215
+ Fit::File::Definitions.add_field 18, 18, "avg_running_cadence", :type => 2, :scale => 1, :offset => 0, :units => "strides/min"
216
+ Fit::File::Definitions.add_field 18, 19, "max_cadence", :type => 2, :scale => 1, :offset => 0, :units => "rpm"
217
+ Fit::File::Definitions.add_field 18, 19, "max_running_cadence", :type => 2, :scale => 1, :offset => 0, :units => "strides/min"
218
+ Fit::File::Definitions.add_field 18, 20, "avg_power", :type => 4, :scale => 1, :offset => 0, :units => "watts"
219
+ Fit::File::Definitions.add_field 18, 21, "max_power", :type => 4, :scale => 1, :offset => 0, :units => "watts"
220
+ Fit::File::Definitions.add_field 18, 22, "total_ascent", :type => 4, :scale => 1, :offset => 0, :units => "m"
221
+ Fit::File::Definitions.add_field 18, 23, "total_descent", :type => 4, :scale => 1, :offset => 0, :units => "m"
222
+ Fit::File::Definitions.add_field 18, 24, "total_training_effect", :type => 2, :scale => 10, :offset => 0
223
+ Fit::File::Definitions.add_field 18, 25, "first_lap_index", :type => 4, :scale => 1, :offset => 0
224
+ Fit::File::Definitions.add_field 18, 26, "num_laps", :type => 4, :scale => 1, :offset => 0
225
+ Fit::File::Definitions.add_field 18, 27, "event_group", :type => 2, :scale => 1, :offset => 0
226
+ Fit::File::Definitions.add_field 18, 28, "trigger", :type => 0, :scale => 1, :offset => 0
227
+ Fit::File::Definitions.add_field 18, 29, "nec_lat", :type => 5, :scale => 1, :offset => 0, :units => "semicircles"
228
+ Fit::File::Definitions.add_field 18, 30, "nec_long", :type => 5, :scale => 1, :offset => 0, :units => "semicircles"
229
+ Fit::File::Definitions.add_field 18, 31, "swc_lat", :type => 5, :scale => 1, :offset => 0, :units => "semicircles"
230
+ Fit::File::Definitions.add_field 18, 32, "swc_long", :type => 5, :scale => 1, :offset => 0, :units => "semicircles"
231
+
232
+ Fit::File::Definitions.add_name 19, "lap"
233
+ Fit::File::Definitions.add_field 19, 254, "message_index", :type => 4, :scale => 1, :offset => 0
234
+ Fit::File::Definitions.add_field 19, 253, "timestamp", :type => 6, :scale => 1, :offset => 0, :units => "s"
235
+ Fit::File::Definitions.add_field 19, 0, "event", :type => 0, :scale => 1, :offset => 0
236
+ Fit::File::Definitions.add_field 19, 1, "event_type", :type => 0, :scale => 1, :offset => 0
237
+ Fit::File::Definitions.add_field 19, 2, "start_time", :type => 6, :scale => 1, :offset => 0
238
+ Fit::File::Definitions.add_field 19, 3, "start_position_lat", :type => 5, :scale => 1, :offset => 0, :units => "semicircles"
239
+ Fit::File::Definitions.add_field 19, 4, "start_position_long", :type => 5, :scale => 1, :offset => 0, :units => "semicircles"
240
+ Fit::File::Definitions.add_field 19, 5, "end_position_lat", :type => 5, :scale => 1, :offset => 0, :units => "semicircles"
241
+ Fit::File::Definitions.add_field 19, 6, "end_position_long", :type => 5, :scale => 1, :offset => 0, :units => "semicircles"
242
+ Fit::File::Definitions.add_field 19, 7, "total_elapsed_time", :type => 6, :scale => 1000, :offset => 0, :units => "s"
243
+ Fit::File::Definitions.add_field 19, 8, "total_timer_time", :type => 6, :scale => 1000, :offset => 0, :units => "s"
244
+ Fit::File::Definitions.add_field 19, 9, "total_distance", :type => 6, :scale => 100, :offset => 0, :units => "m"
245
+ Fit::File::Definitions.add_field 19, 10, "total_cycles", :type => 6, :scale => 1, :offset => 0, :units => "cycles"
246
+ Fit::File::Definitions.add_field 19, 10, "total_strides", :type => 6, :scale => 1, :offset => 0, :units => "strides"
247
+ Fit::File::Definitions.add_field 19, 11, "total_calories", :type => 4, :scale => 1, :offset => 0, :units => "kcal"
248
+ Fit::File::Definitions.add_field 19, 12, "total_fat_calories", :type => 4, :scale => 1, :offset => 0, :units => "kcal"
249
+ Fit::File::Definitions.add_field 19, 13, "avg_speed", :type => 4, :scale => 1000, :offset => 0, :units => "m/s"
250
+ Fit::File::Definitions.add_field 19, 14, "max_speed", :type => 4, :scale => 1000, :offset => 0, :units => "m/s"
251
+ Fit::File::Definitions.add_field 19, 15, "avg_heart_rate", :type => 2, :scale => 1, :offset => 0, :units => "bpm"
252
+ Fit::File::Definitions.add_field 19, 16, "max_heart_rate", :type => 2, :scale => 1, :offset => 0, :units => "bpm"
253
+ Fit::File::Definitions.add_field 19, 17, "avg_cadence", :type => 2, :scale => 1, :offset => 0, :units => "rpm"
254
+ Fit::File::Definitions.add_field 19, 17, "avg_running_cadence", :type => 2, :scale => 1, :offset => 0, :units => "strides/min"
255
+ Fit::File::Definitions.add_field 19, 18, "max_cadence", :type => 2, :scale => 1, :offset => 0, :units => "rpm"
256
+ Fit::File::Definitions.add_field 19, 18, "max_running_cadence", :type => 2, :scale => 1, :offset => 0, :units => "strides/min"
257
+ Fit::File::Definitions.add_field 19, 19, "avg_power", :type => 4, :scale => 1, :offset => 0, :units => "watts"
258
+ Fit::File::Definitions.add_field 19, 20, "max_power", :type => 4, :scale => 1, :offset => 0, :units => "watts"
259
+ Fit::File::Definitions.add_field 19, 21, "total_ascent", :type => 4, :scale => 1, :offset => 0, :units => "m"
260
+ Fit::File::Definitions.add_field 19, 22, "total_descent", :type => 4, :scale => 1, :offset => 0, :units => "m"
261
+ Fit::File::Definitions.add_field 19, 23, "intensity", :type => 0, :scale => 1, :offset => 0
262
+ Fit::File::Definitions.add_field 19, 24, "lap_trigger", :type => 0, :scale => 1, :offset => 0
263
+ Fit::File::Definitions.add_field 19, 25, "sport", :type => 0, :scale => 1, :offset => 0
264
+ Fit::File::Definitions.add_field 19, 26, "event_group", :type => 2, :scale => 1, :offset => 0
265
+
266
+ Fit::File::Definitions.add_name 20, "record"
267
+ Fit::File::Definitions.add_field 20, 253, "timestamp", :type => 6, :scale => 1, :offset => 0, :units => "s"
268
+ Fit::File::Definitions.add_field 20, 0, "position_lat", :type => 5, :scale => 1, :offset => 0, :units => "semicircles"
269
+ Fit::File::Definitions.add_field 20, 1, "position_long", :type => 5, :scale => 1, :offset => 0, :units => "semicircles"
270
+ Fit::File::Definitions.add_field 20, 2, "altitude", :type => 4, :scale => 5, :offset => 500, :units => "m"
271
+ Fit::File::Definitions.add_field 20, 3, "heart_rate", :type => 2, :scale => 1, :offset => 0, :units => "bpm"
272
+ Fit::File::Definitions.add_field 20, 4, "cadence", :type => 2, :scale => 1, :offset => 0, :units => "rpm"
273
+ Fit::File::Definitions.add_field 20, 5, "distance", :type => 6, :scale => 100, :offset => 0, :units => "m"
274
+ Fit::File::Definitions.add_field 20, 6, "speed", :type => 4, :scale => 1000, :offset => 0, :units => "m/s"
275
+ Fit::File::Definitions.add_field 20, 7, "power", :type => 4, :scale => 1, :offset => 0, :units => "watts"
276
+ Fit::File::Definitions.add_field 20, 8, "compressed_speed_distance", :type => 13, :scale => 1, :offset => 0
277
+ Fit::File::Definitions.add_field 20, 9, "grade", :type => 3, :scale => 100, :offset => 0, :units => "%"
278
+ Fit::File::Definitions.add_field 20, 10, "resistance", :type => 2, :scale => 1, :offset => 0
279
+ Fit::File::Definitions.add_field 20, 11, "time_from_course", :type => 5, :scale => 1000, :offset => 0, :units => "s"
280
+ Fit::File::Definitions.add_field 20, 12, "cycle_length", :type => 2, :scale => 100, :offset => 0, :units => "m"
281
+ Fit::File::Definitions.add_field 20, 13, "temperature", :type => 1, :scale => 1, :offset => 0, :units => "C"
282
+
283
+ Fit::File::Definitions.add_name 21, "event"
284
+ Fit::File::Definitions.add_field 21, 253, "timestamp", :type => 6, :scale => 1, :offset => 0, :units => "s"
285
+ Fit::File::Definitions.add_field 21, 0, "event", :type => 0, :scale => 1, :offset => 0
286
+ Fit::File::Definitions.add_field 21, 1, "event_type", :type => 0, :scale => 1, :offset => 0
287
+ Fit::File::Definitions.add_field 21, 2, "data16", :type => 4, :scale => 1, :offset => 0
288
+ Fit::File::Definitions.add_field 21, 3, "data", :type => 6, :scale => 1, :offset => 0
289
+ Fit::File::Definitions.add_field 21, 3, "timer_trigger", :type => 6, :scale => 1, :offset => 0
290
+ Fit::File::Definitions.add_field 21, 3, "course_point_index", :type => 6, :scale => 1, :offset => 0
291
+ Fit::File::Definitions.add_field 21, 3, "battery_level", :type => 6, :scale => 1000, :offset => 0, :units => "V"
292
+ Fit::File::Definitions.add_field 21, 3, "virtual_partner_speed", :type => 6, :scale => 1000, :offset => 0, :units => "m/s"
293
+ Fit::File::Definitions.add_field 21, 3, "hr_high_alert", :type => 6, :scale => 1, :offset => 0, :units => "bpm"
294
+ Fit::File::Definitions.add_field 21, 3, "hr_low_alert", :type => 6, :scale => 1, :offset => 0, :units => "bpm"
295
+ Fit::File::Definitions.add_field 21, 3, "speed_high_alert", :type => 6, :scale => 1000, :offset => 0, :units => "m/s"
296
+ Fit::File::Definitions.add_field 21, 3, "speed_low_alert", :type => 6, :scale => 1000, :offset => 0, :units => "m/s"
297
+ Fit::File::Definitions.add_field 21, 3, "cad_high_alert", :type => 6, :scale => 1, :offset => 0, :units => "rpm"
298
+ Fit::File::Definitions.add_field 21, 3, "cad_low_alert", :type => 6, :scale => 1, :offset => 0, :units => "rpm"
299
+ Fit::File::Definitions.add_field 21, 3, "power_high_alert", :type => 6, :scale => 1, :offset => 0, :units => "watts"
300
+ Fit::File::Definitions.add_field 21, 3, "power_low_alert", :type => 6, :scale => 1, :offset => 0, :units => "watts"
301
+ Fit::File::Definitions.add_field 21, 3, "time_duration_alert", :type => 6, :scale => 1000, :offset => 0, :units => "s"
302
+ Fit::File::Definitions.add_field 21, 3, "distance_duration_alert", :type => 6, :scale => 100, :offset => 0, :units => "m"
303
+ Fit::File::Definitions.add_field 21, 3, "calorie_duration_alert", :type => 6, :scale => 1, :offset => 0, :units => "calories"
304
+ Fit::File::Definitions.add_field 21, 3, "fitness_equipment_state", :type => 6, :scale => 1, :offset => 0
305
+ Fit::File::Definitions.add_field 21, 4, "event_group", :type => 2, :scale => 1, :offset => 0
306
+
307
+ Fit::File::Definitions.add_name 23, "device_info"
308
+ Fit::File::Definitions.add_field 23, 253, "timestamp", :type => 6, :scale => 1, :offset => 0, :units => "s"
309
+ Fit::File::Definitions.add_field 23, 0, "device_index", :type => 2, :scale => 1, :offset => 0
310
+ Fit::File::Definitions.add_field 23, 1, "device_type", :type => 2, :scale => 1, :offset => 0
311
+ Fit::File::Definitions.add_field 23, 2, "manufacturer", :type => 4, :scale => 1, :offset => 0
312
+ Fit::File::Definitions.add_field 23, 3, "serial_number", :type => 12, :scale => 1, :offset => 0
313
+ Fit::File::Definitions.add_field 23, 4, "product", :type => 4, :scale => 1, :offset => 0
314
+ Fit::File::Definitions.add_field 23, 5, "software_version", :type => 4, :scale => 100, :offset => 0
315
+ Fit::File::Definitions.add_field 23, 6, "hardware_version", :type => 2, :scale => 1, :offset => 0
316
+ Fit::File::Definitions.add_field 23, 7, "cum_operating_time", :type => 6, :scale => 1, :offset => 0, :units => "s"
317
+ Fit::File::Definitions.add_field 23, 10, "battery_voltage", :type => 4, :scale => 256, :offset => 0, :units => "V"
318
+ Fit::File::Definitions.add_field 23, 11, "battery_status", :type => 2, :scale => 1, :offset => 0
319
+
320
+ Fit::File::Definitions.add_name 31, "course"
321
+ Fit::File::Definitions.add_field 31, 4, "sport", :type => 0, :scale => 1, :offset => 0
322
+ Fit::File::Definitions.add_field 31, 5, "name", :type => 7, :scale => 1, :offset => 0
323
+ Fit::File::Definitions.add_field 31, 6, "capabilities", :type => 12, :scale => 1, :offset => 0
324
+
325
+ Fit::File::Definitions.add_name 32, "course_point"
326
+ Fit::File::Definitions.add_field 32, 254, "message_index", :type => 4, :scale => 1, :offset => 0
327
+ Fit::File::Definitions.add_field 32, 1, "timestamp", :type => 6, :scale => 1, :offset => 0
328
+ Fit::File::Definitions.add_field 32, 2, "position_lat", :type => 5, :scale => 1, :offset => 0, :units => "semicircles"
329
+ Fit::File::Definitions.add_field 32, 3, "position_long", :type => 5, :scale => 1, :offset => 0, :units => "semicircles"
330
+ Fit::File::Definitions.add_field 32, 4, "distance", :type => 6, :scale => 100, :offset => 0, :units => "m"
331
+ Fit::File::Definitions.add_field 32, 5, "type", :type => 0, :scale => 1, :offset => 0
332
+ Fit::File::Definitions.add_field 32, 6, "name", :type => 7, :scale => 1, :offset => 0
333
+
334
+ Fit::File::Definitions.add_name 26, "workout"
335
+ Fit::File::Definitions.add_field 26, 4, "sport", :type => 0, :scale => 1, :offset => 0
336
+ Fit::File::Definitions.add_field 26, 5, "capabilities", :type => 12, :scale => 1, :offset => 0
337
+ Fit::File::Definitions.add_field 26, 6, "num_valid_steps", :type => 4, :scale => 1, :offset => 0
338
+ Fit::File::Definitions.add_field 26, 8, "wkt_name", :type => 7, :scale => 1, :offset => 0
339
+
340
+ Fit::File::Definitions.add_name 27, "workout_step"
341
+ Fit::File::Definitions.add_field 27, 254, "message_index", :type => 4, :scale => 1, :offset => 0
342
+ Fit::File::Definitions.add_field 27, 0, "wkt_step_name", :type => 7, :scale => 1, :offset => 0
343
+ Fit::File::Definitions.add_field 27, 1, "duration_type", :type => 0, :scale => 1, :offset => 0
344
+ Fit::File::Definitions.add_field 27, 2, "duration_value", :type => 6, :scale => 1, :offset => 0
345
+ Fit::File::Definitions.add_field 27, 2, "duration_time", :type => 6, :scale => 1000, :offset => 0, :units => "s"
346
+ Fit::File::Definitions.add_field 27, 2, "duration_distance", :type => 6, :scale => 100, :offset => 0, :units => "m"
347
+ Fit::File::Definitions.add_field 27, 2, "duration_hr", :type => 6, :scale => 1, :offset => 0, :units => "% or bpm"
348
+ Fit::File::Definitions.add_field 27, 2, "duration_calories", :type => 6, :scale => 1, :offset => 0, :units => "calories"
349
+ Fit::File::Definitions.add_field 27, 2, "duration_step", :type => 6, :scale => 1, :offset => 0
350
+ Fit::File::Definitions.add_field 27, 2, "duration_power", :type => 6, :scale => 1, :offset => 0, :units => "% or watts"
351
+ Fit::File::Definitions.add_field 27, 3, "target_type", :type => 0, :scale => 1, :offset => 0
352
+ Fit::File::Definitions.add_field 27, 4, "target_value", :type => 6, :scale => 1, :offset => 0
353
+ Fit::File::Definitions.add_field 27, 4, "target_hr_zone", :type => 6, :scale => 1, :offset => 0
354
+ Fit::File::Definitions.add_field 27, 4, "target_power_zone", :type => 6, :scale => 1, :offset => 0
355
+ Fit::File::Definitions.add_field 27, 4, "repeat_steps", :type => 6, :scale => 1, :offset => 0
356
+ Fit::File::Definitions.add_field 27, 4, "repeat_time", :type => 6, :scale => 1000, :offset => 0, :units => "s"
357
+ Fit::File::Definitions.add_field 27, 4, "repeat_distance", :type => 6, :scale => 100, :offset => 0, :units => "m"
358
+ Fit::File::Definitions.add_field 27, 4, "repeat_calories", :type => 6, :scale => 1, :offset => 0, :units => "calories"
359
+ Fit::File::Definitions.add_field 27, 4, "repeat_hr", :type => 6, :scale => 1, :offset => 0, :units => "% or bpm"
360
+ Fit::File::Definitions.add_field 27, 4, "repeat_power", :type => 6, :scale => 1, :offset => 0, :units => "% or watts"
361
+ Fit::File::Definitions.add_field 27, 5, "custom_target_value_low", :type => 6, :scale => 1, :offset => 0
362
+ Fit::File::Definitions.add_field 27, 5, "custom_target_speed_low", :type => 6, :scale => 1000, :offset => 0, :units => "m/s"
363
+ Fit::File::Definitions.add_field 27, 5, "custom_target_heart_rate_low", :type => 6, :scale => 1, :offset => 0, :units => "% or bpm"
364
+ Fit::File::Definitions.add_field 27, 5, "custom_target_cadence_low", :type => 6, :scale => 1, :offset => 0, :units => "rpm"
365
+ Fit::File::Definitions.add_field 27, 5, "custom_target_power_low", :type => 6, :scale => 1, :offset => 0, :units => "% or watts"
366
+ Fit::File::Definitions.add_field 27, 6, "custom_target_value_high", :type => 6, :scale => 1, :offset => 0
367
+ Fit::File::Definitions.add_field 27, 6, "custom_target_speed_high", :type => 6, :scale => 1000, :offset => 0, :units => "m/s"
368
+ Fit::File::Definitions.add_field 27, 6, "custom_target_heart_rate_high", :type => 6, :scale => 1, :offset => 0, :units => "% or bpm"
369
+ Fit::File::Definitions.add_field 27, 6, "custom_target_cadence_high", :type => 6, :scale => 1, :offset => 0, :units => "rpm"
370
+ Fit::File::Definitions.add_field 27, 6, "custom_target_power_high", :type => 6, :scale => 1, :offset => 0, :units => "% or watts"
371
+ Fit::File::Definitions.add_field 27, 7, "intensity", :type => 0, :scale => 1, :offset => 0
372
+
373
+ Fit::File::Definitions.add_name 33, "totals"
374
+ Fit::File::Definitions.add_field 33, 254, "message_index", :type => 4, :scale => 1, :offset => 0
375
+ Fit::File::Definitions.add_field 33, 253, "timestamp", :type => 6, :scale => 1, :offset => 0, :units => "s"
376
+ Fit::File::Definitions.add_field 33, 0, "timer_time", :type => 6, :scale => 1, :offset => 0, :units => "s"
377
+ Fit::File::Definitions.add_field 33, 1, "distance", :type => 6, :scale => 1, :offset => 0, :units => "m"
378
+ Fit::File::Definitions.add_field 33, 2, "calories", :type => 6, :scale => 1, :offset => 0, :units => "kcal"
379
+ Fit::File::Definitions.add_field 33, 3, "sport", :type => 0, :scale => 1, :offset => 0
380
+ Fit::File::Definitions.add_field 33, 4, "elapsed_time", :type => 6, :scale => 1, :offset => 0, :units => "s"
381
+
382
+ Fit::File::Definitions.add_name 30, "weight_scale"
383
+ Fit::File::Definitions.add_field 30, 253, "timestamp", :type => 6, :scale => 1, :offset => 0, :units => "s"
384
+ Fit::File::Definitions.add_field 30, 0, "weight", :type => 4, :scale => 100, :offset => 0, :units => "kg"
385
+ Fit::File::Definitions.add_field 30, 1, "percent_fat", :type => 4, :scale => 100, :offset => 0, :units => "%"
386
+ Fit::File::Definitions.add_field 30, 2, "percent_hydration", :type => 4, :scale => 100, :offset => 0, :units => "%"
387
+ Fit::File::Definitions.add_field 30, 3, "visceral_fat_mass", :type => 4, :scale => 100, :offset => 0, :units => "kg"
388
+ Fit::File::Definitions.add_field 30, 4, "bone_mass", :type => 4, :scale => 100, :offset => 0, :units => "kg"
389
+ Fit::File::Definitions.add_field 30, 5, "muscle_mass", :type => 4, :scale => 100, :offset => 0, :units => "kg"
390
+ Fit::File::Definitions.add_field 30, 7, "basal_met", :type => 4, :scale => 4, :offset => 0, :units => "kcal/day"
391
+ Fit::File::Definitions.add_field 30, 8, "physique_rating", :type => 2, :scale => 1, :offset => 0
392
+ Fit::File::Definitions.add_field 30, 9, "active_met", :type => 4, :scale => 4, :offset => 0, :units => "kcal/day"
393
+ Fit::File::Definitions.add_field 30, 10, "metabolic_age", :type => 2, :scale => 1, :offset => 0, :units => "years"
394
+ Fit::File::Definitions.add_field 30, 11, "visceral_fat_rating", :type => 2, :scale => 1, :offset => 0
395
+ Fit::File::Definitions.add_field 30, 12, "user_profile_index", :type => 4, :scale => 1, :offset => 0
396
+
397
+ Fit::File::Definitions.add_name 51, "blood_pressure"
398
+ Fit::File::Definitions.add_field 51, 253, "timestamp", :type => 6, :scale => 1, :offset => 0, :units => "s"
399
+ Fit::File::Definitions.add_field 51, 0, "systolic_pressure", :type => 4, :scale => 1, :offset => 0, :units => "mmHg"
400
+ Fit::File::Definitions.add_field 51, 1, "diastolic_pressure", :type => 4, :scale => 1, :offset => 0, :units => "mmHg"
401
+ Fit::File::Definitions.add_field 51, 2, "mean_arterial_pressure", :type => 4, :scale => 1, :offset => 0, :units => "mmHg"
402
+ Fit::File::Definitions.add_field 51, 3, "map_3_sample_mean", :type => 4, :scale => 1, :offset => 0, :units => "mmHg"
403
+ Fit::File::Definitions.add_field 51, 4, "map_morning_values", :type => 4, :scale => 1, :offset => 0, :units => "mmHg"
404
+ Fit::File::Definitions.add_field 51, 5, "map_evening_values", :type => 4, :scale => 1, :offset => 0, :units => "mmHg"
405
+ Fit::File::Definitions.add_field 51, 6, "heart_rate", :type => 2, :scale => 1, :offset => 0, :units => "bpm"
406
+ Fit::File::Definitions.add_field 51, 7, "heart_rate_type", :type => 0, :scale => 1, :offset => 0
407
+ Fit::File::Definitions.add_field 51, 8, "status", :type => 0, :scale => 1, :offset => 0
408
+ Fit::File::Definitions.add_field 51, 9, "user_profile_index", :type => 4, :scale => 1, :offset => 0
@@ -0,0 +1,17 @@
1
+ module Fit
2
+ class File
3
+ class Header < BinData::Record
4
+ endian :little
5
+
6
+ uint8 :header_size
7
+ uint8 :protocol_version
8
+ uint16 :profile_version
9
+ uint32 :data_size
10
+ string :data_type, :read_length => 4
11
+
12
+ def end_pos
13
+ header_size + data_size - 2
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,37 @@
1
+ module Fit
2
+ class File
3
+ class Record
4
+
5
+ @@definitions = {}
6
+ cattr_reader :definitions, instance_reader: false
7
+
8
+ def self.read(io)
9
+ new.read(io)
10
+ end
11
+
12
+ def self.clear_definitions!
13
+ @@definitions.clear
14
+ end
15
+
16
+ attr_reader :header, :content
17
+
18
+ def read(io)
19
+ @header = RecordHeader.read(io)
20
+
21
+ @content = case @header.message_type.snapshot
22
+ when 1
23
+ Definition.read(io).tap do |definition|
24
+ @@definitions[@header.local_message_type.snapshot] = Data.generate(definition)
25
+ end
26
+ when 0
27
+ definition = @@definitions[@header.local_message_type.snapshot]
28
+ # raise "No definition for local message type: #{@header} in #{@@definitions}" if definition.nil?
29
+ definition.read(io) unless definition.nil?
30
+ end
31
+
32
+ self
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,27 @@
1
+ module Fit
2
+ class File
3
+ class RecordHeader < BinData::Record
4
+ hide :reserved_bits
5
+
6
+ bit1 :header_type
7
+
8
+ bit1 :message_type, :onlyif => :normal?
9
+ bit2 :reserved_bits, :onlyif => :normal?
10
+
11
+ choice :local_message_type, :selection => :header_type do
12
+ bit4 0
13
+ bit2 1
14
+ end
15
+
16
+ bit5 :time_offset, :onlyif => :compressed_timestamp?
17
+
18
+ def normal?
19
+ header_type == 0
20
+ end
21
+
22
+ def compressed_timestamp?
23
+ header_type == 1
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module Fit
2
+ VERSION = '0.0.2'
3
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fit::File::Data do
4
+ describe ".generate" do
5
+ let(:definition) do
6
+ Fit::File::Definition.read example_file('record/message/definition')
7
+ end
8
+
9
+ subject { described_class.generate(definition) }
10
+
11
+ its(:ancestors) { should include(BinData::Record) }
12
+ its("new.record_type") { should eq(:file_id) }
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fit::File::Definition do
4
+ context "given a sample definition message" do
5
+ describe ".read" do
6
+ subject do
7
+ described_class.read example_file('record/message/definition')
8
+ end
9
+
10
+ its(:architecture) { should == 0 }
11
+ its(:global_message_number) { should == 0 }
12
+ its(:field_count) { should == 6 }
13
+ it { should have(subject.field_count).fields }
14
+
15
+ its(:record_type) { should == :definition }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fit::File::Definitions do
4
+ describe ".add_field" do
5
+ context "without additional options" do
6
+ it "adds field data" do
7
+ described_class.add_field(20,5, 'distance')
8
+
9
+ described_class.get_field(20,5).should be_a(Hash)
10
+ described_class.get_field(20,5).should eql({ :name => 'distance'})
11
+ end
12
+ end
13
+
14
+ context "with additional options" do
15
+ it "adds field data" do
16
+ described_class.add_field(20,5, 'distance', :scale => 100, :units => 'm')
17
+
18
+ described_class.get_field(20,5).should be_a(Hash)
19
+ described_class.get_field(20,5).should eql({ :name => 'distance', :scale => 100, :units => 'm'})
20
+ end
21
+ end
22
+ end
23
+
24
+ describe ".get_field" do
25
+ it "returns nil if no field exists" do
26
+ described_class.get_field(100,100).should be_nil
27
+ end
28
+ end
29
+
30
+ describe ".add_name" do
31
+ it "adds a name" do
32
+ described_class.add_name(20, 'record')
33
+ described_class.get_name(20).should eql('record')
34
+ end
35
+ end
36
+
37
+ describe ".get_name" do
38
+ it "returns nil if no name exists" do
39
+ described_class.get_name(100).should be_nil
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fit::File::Header do
4
+ context "given a sample FIT header" do
5
+ subject do
6
+ described_class.read example_file('file/header')
7
+ end
8
+
9
+ its(:header_size) { should == 12 }
10
+ its(:protocol_version) { should == 16 }
11
+ its(:profile_version) { should == 64 }
12
+ its(:data_size) { should == 36069 }
13
+ its(:data_type) { should == ".FIT" }
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fit::File::RecordHeader do
4
+ context "given a sample normal header" do
5
+ subject do
6
+ described_class.read example_file('record/normal_header')
7
+ end
8
+
9
+ its(:header_type) { should == 0 }
10
+ its(:message_type) { should == 1 }
11
+ its(:local_message_type) { should == 0 }
12
+
13
+ it { should be_normal }
14
+ it { should_not be_a_compressed_timestamp }
15
+ end
16
+
17
+ context "given a sample compressed timestamp header" do
18
+ # TODO
19
+ end
20
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fit::File::Record do
4
+ before { described_class.clear_definitions! }
5
+
6
+ describe ".read" do
7
+ subject { described_class.read(file) }
8
+
9
+ context "given a sample definition record" do
10
+ let(:file) { example_file('record/definition_record') }
11
+
12
+ its(:header) { should be_a(Fit::File::RecordHeader) }
13
+ its(:content) { should be_a(Fit::File::Definition) }
14
+ end
15
+
16
+ context "given a sample data record" do
17
+ let(:file) { nil }
18
+ end
19
+ end
20
+
21
+ describe ".clear_definitions" do
22
+ it "should clear the definitions class variable" do
23
+ described_class.read example_file('record/definition_record')
24
+ described_class.definitions.should_not be_empty
25
+ described_class.clear_definitions!
26
+ described_class.definitions.should be_empty
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fit::File do
4
+ it "should have a header"
5
+ it "should have records"
6
+ it "should have a CRC"
7
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fit do
4
+ describe "VERSION" do
5
+ subject{ Fit::VERSION }
6
+
7
+ it { should be_a(String) }
8
+ it { should match(/\d{1,2}\.\d{1,2}\.\d{1,2}/) }
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ require 'simplecov'
2
+ SimpleCov.add_filter '/spec/'
3
+ SimpleCov.start
4
+
5
+ SPEC_ROOT = File.dirname(__FILE__)
6
+
7
+ $LOAD_PATH.unshift SPEC_ROOT, File.join(SPEC_ROOT, '..', 'lib')
8
+
9
+ require 'rspec'
10
+ require 'fit'
11
+
12
+ def example_file(filename)
13
+ File.open File.join(SPEC_ROOT, 'support', 'examples', filename)
14
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: garmin-fit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Jeff Wallace
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-04-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bindata
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Published as a gem by adam.bird@gmail.com
42
+ email: jeff@tjwallace.ca
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - lib/fit/file/data.rb
48
+ - lib/fit/file/definition.rb
49
+ - lib/fit/file/definitions.rb
50
+ - lib/fit/file/header.rb
51
+ - lib/fit/file/record.rb
52
+ - lib/fit/file/record_header.rb
53
+ - lib/fit/file.rb
54
+ - lib/fit/version.rb
55
+ - lib/fit.rb
56
+ - spec/file/data_spec.rb
57
+ - spec/file/definition_spec.rb
58
+ - spec/file/definitions_spec.rb
59
+ - spec/file/header_spec.rb
60
+ - spec/file/record_header_spec.rb
61
+ - spec/file/record_spec.rb
62
+ - spec/file_spec.rb
63
+ - spec/fit_spec.rb
64
+ - spec/spec_helper.rb
65
+ - spec/support/examples/file/header
66
+ - spec/support/examples/record/definition_record
67
+ - spec/support/examples/record/message/definition
68
+ - spec/support/examples/record/normal_header
69
+ homepage: http://github.com/tjwallace/fit
70
+ licenses:
71
+ - LICENSE.txt
72
+ metadata: {}
73
+ post_install_message:
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubyforge_project:
89
+ rubygems_version: 2.0.3
90
+ signing_key:
91
+ specification_version: 4
92
+ summary: Utility for parsing Garmin FIT files
93
+ test_files:
94
+ - spec/file/data_spec.rb
95
+ - spec/file/definition_spec.rb
96
+ - spec/file/definitions_spec.rb
97
+ - spec/file/header_spec.rb
98
+ - spec/file/record_header_spec.rb
99
+ - spec/file/record_spec.rb
100
+ - spec/file_spec.rb
101
+ - spec/fit_spec.rb
102
+ - spec/spec_helper.rb
103
+ - spec/support/examples/file/header
104
+ - spec/support/examples/record/definition_record
105
+ - spec/support/examples/record/message/definition
106
+ - spec/support/examples/record/normal_header