garmin-fit 0.0.2

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