fit-parser 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +27 -0
  7. data/Rakefile +2 -0
  8. data/fit.gemspec +30 -0
  9. data/lib/fit.rb +23 -0
  10. data/lib/fit/file.rb +29 -0
  11. data/lib/fit/file/data.rb +99 -0
  12. data/lib/fit/file/definition.rb +120 -0
  13. data/lib/fit/file/definitions.rb +705 -0
  14. data/lib/fit/file/header.rb +18 -0
  15. data/lib/fit/file/record.rb +37 -0
  16. data/lib/fit/file/record_header.rb +27 -0
  17. data/lib/fit/file/type.rb +41 -0
  18. data/lib/fit/file/types.rb +954 -0
  19. data/lib/fit/version.rb +3 -0
  20. data/spec/file/data_spec.rb +111 -0
  21. data/spec/file/definition_spec.rb +26 -0
  22. data/spec/file/definitions_spec.rb +81 -0
  23. data/spec/file/header_spec.rb +28 -0
  24. data/spec/file/record_header_spec.rb +20 -0
  25. data/spec/file/record_spec.rb +56 -0
  26. data/spec/file/type_spec.rb +99 -0
  27. data/spec/file/types_spec.rb +100 -0
  28. data/spec/file_spec.rb +21 -0
  29. data/spec/fit_spec.rb +10 -0
  30. data/spec/spec_helper.rb +19 -0
  31. data/spec/support/examples/file/full_file_with_wrong_crc.fit +0 -0
  32. data/spec/support/examples/file/header +0 -0
  33. data/spec/support/examples/file/header_14b.fit +0 -0
  34. data/spec/support/examples/record/data_record_2.fit +0 -0
  35. data/spec/support/examples/record/data_record_2bis.fit +0 -0
  36. data/spec/support/examples/record/definition_record +0 -0
  37. data/spec/support/examples/record/definition_record_2.fit +0 -0
  38. data/spec/support/examples/record/message/data_dynamic_fields.fit +0 -0
  39. data/spec/support/examples/record/message/data_field_array.fit +0 -0
  40. data/spec/support/examples/record/message/data_file_capabilities_activities.fit +0 -0
  41. data/spec/support/examples/record/message/data_file_capabilities_settings.fit +0 -0
  42. data/spec/support/examples/record/message/definition +0 -0
  43. data/spec/support/examples/record/message/definition_dynamic_fields.fit +0 -0
  44. data/spec/support/examples/record/message/definition_field_array.fit +0 -0
  45. data/spec/support/examples/record/message/definition_file_capabilities.fit +0 -0
  46. data/spec/support/examples/record/normal_header +1 -0
  47. metadata +228 -0
@@ -0,0 +1,18 @@
1
+ module Fit
2
+ class File
3
+ class Header < BinData::Record
4
+ endian :little
5
+
6
+ uint8 :header_size, :check_value => lambda { value >= 12 }
7
+ uint8 :protocol_version
8
+ uint16 :profile_version
9
+ uint32 :data_size
10
+ string :data_type, :read_length => 4
11
+ uint16 :crc, :onlyif => lambda { header_size == 14 }
12
+
13
+ def end_pos
14
+ header_size + data_size - 2
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,37 @@
1
+ module Fit
2
+ class File
3
+ class Record
4
+
5
+ @@definitions = {}
6
+ mattr_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.local_message_type}" if definition.nil?
29
+ definition.read(io)
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,41 @@
1
+ module Fit
2
+ class File
3
+ class Type
4
+
5
+ @@types = {}
6
+
7
+ def self.get_type(name)
8
+ return @@types[name] if @@types.has_key? name
9
+ type = Types.get_type_definition name
10
+ @@types[name] = type ? new(type) : nil
11
+ end
12
+
13
+ def initialize(type)
14
+ @type = type
15
+ end
16
+
17
+ def value(val)
18
+ return nil unless is_valid(val)
19
+ if @type.has_key? :method
20
+ Types.send(@type[:method], val, @type[:values], @type[:parameters])
21
+ else
22
+ values = @type[:values]
23
+ value = values[val] if values
24
+ return value unless value.nil?
25
+ val
26
+ end
27
+ end
28
+
29
+ private
30
+ def is_valid(val)
31
+ if @type.has_key? :invalid
32
+ invalid_value = @type[:invalid]
33
+ else
34
+ invalid_value = Types.get_type_definition(@type[:basic_type])[:invalid]
35
+ end
36
+ return false if val == invalid_value
37
+ true
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,954 @@
1
+ module Fit
2
+ class File
3
+ module Types
4
+
5
+ @@types = {}
6
+
7
+ class << self
8
+ def add_type(name, type, option = {})
9
+ @@types[name] = option.merge({:basic_type => type})
10
+ end
11
+
12
+ def get_type_definition(name)
13
+ return @@types[name] if @@types.has_key? name
14
+ nil
15
+ end
16
+
17
+ def date_time_value(time, values, parameters)
18
+ val = values.invert
19
+ if time < val['min']
20
+ time.to_s
21
+ else
22
+ res= parameters[:utc] ? Time.utc(1989,12,31) + time : Time.local(1989,12,31) + time
23
+ res.to_s
24
+ end
25
+ end
26
+
27
+ def message_index_value(msg_index, values, parameters = nil)
28
+ val = values.invert
29
+ msg_index & val['mask']
30
+ end
31
+
32
+ def bitfield_value(bitfield, values, parameters = nil)
33
+ res = ''
34
+ values.each do |key, val|
35
+ if key & bitfield != 0
36
+ res << '/' unless res.empty?
37
+ res << val
38
+ end
39
+ end
40
+ res
41
+ end
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+
48
+ # basic types
49
+ Fit::File::Types.add_type :enum, nil, :invalid => 0xFF
50
+ Fit::File::Types.add_type :sint8, nil, :invalid => 0x7F
51
+ Fit::File::Types.add_type :uint8, nil, :invalid => 0xFF
52
+ Fit::File::Types.add_type :sint16, nil, :invalid => 0x7FFF
53
+ Fit::File::Types.add_type :uint16, nil, :invalid => 0xFFFF
54
+ Fit::File::Types.add_type :sint32, nil, :invalid => 0x7FFFFFFF
55
+ Fit::File::Types.add_type :uint32, nil, :invalid => 0xFFFFFFFF
56
+ Fit::File::Types.add_type :string, nil, :invalid => 0x00
57
+ Fit::File::Types.add_type :float32, nil, :invalid => 0xFFFFFFFF
58
+ Fit::File::Types.add_type :float64, nil, :invalid => 0xFFFFFFFFFFFFFFFF
59
+ Fit::File::Types.add_type :uint8z, nil, :invalid => 0x00
60
+ Fit::File::Types.add_type :uint16z, nil, :invalid => 0x0000
61
+ Fit::File::Types.add_type :uint32z, nil, :invalid => 0x00000000
62
+ Fit::File::Types.add_type :byte, nil, :invalid => 0xFF
63
+
64
+ # derived types
65
+ Fit::File::Types.add_type :file, :enum, :values => {
66
+ 1 => 'device',
67
+ 2 => 'settings',
68
+ 3 => 'sport',
69
+ 4 => 'activity',
70
+ 5 => 'workout',
71
+ 6 => 'course',
72
+ 7 => 'schedules',
73
+ 9 => 'weight',
74
+ 10 => 'totals',
75
+ 11 => 'goals',
76
+ 14 => 'blood_pressure',
77
+ 15 => 'monitoring_a',
78
+ 20 => 'activity_summary',
79
+ 28 => 'monitoring_daily',
80
+ 32 => 'monitoring_b' }
81
+ Fit::File::Types.add_type :mesg_num, :uint16, :values => {
82
+ 0 => 'file_id',
83
+ 1 => 'capabilities',
84
+ 2 => 'device_settings',
85
+ 3 => 'user_profile',
86
+ 4 => 'hrm_profile',
87
+ 5 => 'sdm_profile',
88
+ 6 => 'bike_profile',
89
+ 7 => 'zones_target',
90
+ 8 => 'hr_zone',
91
+ 9 => 'power_zone',
92
+ 10 => 'met_zone',
93
+ 12 => 'sport',
94
+ 15 => 'goal',
95
+ 18 => 'session',
96
+ 19 => 'lap',
97
+ 20 => 'record',
98
+ 21 => 'event',
99
+ 23 => 'device_info',
100
+ 26 => 'workout',
101
+ 27 => 'workout_step',
102
+ 28 => 'schedule',
103
+ 30 => 'weight_scale',
104
+ 31 => 'course',
105
+ 32 => 'course_point',
106
+ 33 => 'totals',
107
+ 34 => 'activity',
108
+ 35 => 'software',
109
+ 37 => 'file_capabilities',
110
+ 38 => 'mesg_capabilities',
111
+ 39 => 'field_capabilities',
112
+ 49 => 'file_creator',
113
+ 51 => 'blood_pressure',
114
+ 53 => 'speed_zone',
115
+ 55 => 'monitoring',
116
+ 72 => 'training_file',
117
+ 78 => 'hrv',
118
+ 101 => 'length',
119
+ 103 => 'monitoring_info',
120
+ 105 => 'pad',
121
+ 106 => 'slave_device',
122
+ 131 => 'cadence_zone',
123
+ 145 => 'memo_glob',
124
+ 65280 => 'mfg_range_min',
125
+ 65534 => 'mfg_range_max' }
126
+ Fit::File::Types.add_type :checksum, :uint8, :values => {
127
+ 0 => 'clear',
128
+ 1 => 'ok' }
129
+ Fit::File::Types.add_type :file_flags, :uint8z, :values => {
130
+ 0x02 => 'read',
131
+ 0x04 => 'write',
132
+ 0x08 => 'erase' }, :method => :bitfield_value
133
+ Fit::File::Types.add_type :mesg_count, :enum, :values => {
134
+ 0 => 'num_per_file',
135
+ 1 => 'max_per_file',
136
+ 2 => 'max_per_file_type' }
137
+ Fit::File::Types.add_type :date_time, :uint32, :values => {
138
+ 268435456 => 'min' }, :method => :date_time_value, :parameters => {:utc => true}
139
+ Fit::File::Types.add_type :local_date_time, :uint32, :values => {
140
+ 268435456 => 'min' }, :method => :date_time_value, :parameters => {:utc => false}
141
+ Fit::File::Types.add_type :message_index, :uint16, :values => {
142
+ 32768 => 'selected',
143
+ 26872 => 'reserved',
144
+ 4095 => 'mask' }, :method => :message_index_value
145
+ Fit::File::Types.add_type :device_index, :uint8, :values => {
146
+ 0 => 'creator' }
147
+ Fit::File::Types.add_type :gender, :enum, :values => {
148
+ 0 => 'female',
149
+ 1 => 'male' }
150
+ Fit::File::Types.add_type :language, :enum, :values => {
151
+ 0 => 'english',
152
+ 1 => 'french',
153
+ 2 => 'italian',
154
+ 3 => 'german',
155
+ 4 => 'spanish',
156
+ 5 => 'croatian',
157
+ 6 => 'czech',
158
+ 7 => 'danish',
159
+ 8 => 'dutch',
160
+ 9 => 'finnish',
161
+ 10 => 'greek',
162
+ 11 => 'hungarian',
163
+ 12 => 'norwegian',
164
+ 13 => 'polish',
165
+ 14 => 'portuguese',
166
+ 15 => 'slovakian',
167
+ 16 => 'slovenian',
168
+ 17 => 'swedish',
169
+ 18 => 'russian',
170
+ 19 => 'turkish',
171
+ 20 => 'latvian',
172
+ 21 => 'ukrainian',
173
+ 22 => 'arabic',
174
+ 23 => 'farsi',
175
+ 24 => 'bulgarian',
176
+ 25 => 'romanian',
177
+ 254 => 'custom' }
178
+ Fit::File::Types.add_type :time_zone, :enum, :values => {
179
+ 0 => 'almaty',
180
+ 1 => 'bangkok',
181
+ 2 => 'bombay',
182
+ 3 => 'brasilia',
183
+ 4 => 'cairo',
184
+ 5 => 'cape_verde_is',
185
+ 6 => 'darwin',
186
+ 7 => 'eniwetok',
187
+ 8 => 'fiji',
188
+ 9 => 'hong_kong',
189
+ 10 => 'islamabad',
190
+ 11 => 'kabul',
191
+ 12 => 'magadan',
192
+ 13 => 'mid_atlantic',
193
+ 14 => 'moscow',
194
+ 15 => 'muscat',
195
+ 16 => 'newfoundland',
196
+ 17 => 'samoa',
197
+ 18 => 'sydney',
198
+ 19 => 'tehran',
199
+ 20 => 'tokyo',
200
+ 21 => 'us_alaska',
201
+ 22 => 'us_atlantic',
202
+ 23 => 'us_central',
203
+ 24 => 'us_eastern',
204
+ 25 => 'us_hawaii',
205
+ 26 => 'us_mountain',
206
+ 27 => 'us_pacific',
207
+ 28 => 'other',
208
+ 29 => 'auckland',
209
+ 30 => 'kathmandu',
210
+ 31 => 'europe_western_wet',
211
+ 32 => 'europe_central_cet',
212
+ 33 => 'europe_eastern_eet',
213
+ 34 => 'jakarta',
214
+ 35 => 'perth',
215
+ 36 => 'adelaide',
216
+ 37 => 'brisbane',
217
+ 38 => 'tasmania',
218
+ 39 => 'iceland',
219
+ 40 => 'amsterdam',
220
+ 41 => 'athens',
221
+ 42 => 'barcelona',
222
+ 43 => 'berlin',
223
+ 44 => 'brussels',
224
+ 45 => 'budapest',
225
+ 46 => 'copenhagen',
226
+ 47 => 'dublin',
227
+ 48 => 'helsinki',
228
+ 49 => 'lisbon',
229
+ 50 => 'london',
230
+ 51 => 'madrid',
231
+ 52 => 'munich',
232
+ 53 => 'oslo',
233
+ 54 => 'paris',
234
+ 55 => 'prague',
235
+ 56 => 'reykjavik',
236
+ 57 => 'rome',
237
+ 58 => 'stockholm',
238
+ 59 => 'vienna',
239
+ 60 => 'warsaw',
240
+ 61 => 'zurich',
241
+ 62 => 'quebec',
242
+ 63 => 'ontario',
243
+ 64 => 'manitoba',
244
+ 65 => 'saskatchewan',
245
+ 66 => 'alberta',
246
+ 67 => 'british_columbia',
247
+ 68 => 'boise',
248
+ 69 => 'boston',
249
+ 70 => 'chicago',
250
+ 71 => 'dallas',
251
+ 72 => 'denver',
252
+ 73 => 'kansas_city',
253
+ 74 => 'las_vegas',
254
+ 75 => 'los_angeles',
255
+ 76 => 'miami',
256
+ 77 => 'minneapolis',
257
+ 78 => 'new_york',
258
+ 79 => 'new_orleans',
259
+ 80 => 'phoenix',
260
+ 81 => 'santa_fe',
261
+ 82 => 'seattle',
262
+ 83 => 'washington_dc',
263
+ 84 => 'us_arizona',
264
+ 85 => 'chita',
265
+ 86 => 'ekaterinburg',
266
+ 87 => 'irkutsk',
267
+ 88 => 'kaliningrad',
268
+ 89 => 'krasnoyarsk',
269
+ 90 => 'novosibirsk',
270
+ 91 => 'petropavlovsk_kamchatskiy',
271
+ 92 => 'samara',
272
+ 93 => 'vladivostok',
273
+ 94 => 'mexico_central',
274
+ 95 => 'mexico_mountain',
275
+ 96 => 'mexico_pacific',
276
+ 97 => 'cape_town',
277
+ 98 => 'winkhoek',
278
+ 99 => 'lagos',
279
+ 100 => 'riyahd',
280
+ 101 => 'venezuela',
281
+ 102 => 'australia_lh',
282
+ 103 => 'santiago',
283
+ 253 => 'manual',
284
+ 254 => 'automatic' }
285
+ Fit::File::Types.add_type :display_measure, :enum, :values => {
286
+ 0 => 'metric',
287
+ 1 => 'statute' }
288
+ Fit::File::Types.add_type :display_heart, :enum, :values => {
289
+ 0 => 'bpm',
290
+ 1 => 'max',
291
+ 2 => 'reserve' }
292
+ Fit::File::Types.add_type :display_power, :enum, :values => {
293
+ 0 => 'watts',
294
+ 1 => 'percent_ftp' }
295
+ Fit::File::Types.add_type :display_position, :enum, :values => {
296
+ 0 => 'degree',
297
+ 1 => 'degree_minute',
298
+ 2 => 'degree_minute_second',
299
+ 3 => 'austrian_grid',
300
+ 4 => 'british_grid',
301
+ 5 => 'dutch_grid',
302
+ 6 => 'hungarian_grid',
303
+ 7 => 'finnish_grid',
304
+ 8 => 'german_grid',
305
+ 9 => 'icelandic_grid',
306
+ 10 => 'indonesian_equatorial',
307
+ 11 => 'indonesian_irian',
308
+ 12 => 'indonesian_southern',
309
+ 13 => 'india_zone_0',
310
+ 14 => 'india_zone_IA',
311
+ 15 => 'india_zone_IB',
312
+ 16 => 'india_zone_IIA',
313
+ 17 => 'india_zone_IIB',
314
+ 18 => 'india_zone_IIIA',
315
+ 19 => 'india_zone_IIIB',
316
+ 20 => 'india_zone_IVA',
317
+ 21 => 'india_zone_IVB',
318
+ 22 => 'irish_transverse',
319
+ 23 => 'irish_grid',
320
+ 24 => 'loran',
321
+ 25 => 'maidenhead_grid',
322
+ 26 => 'mgrs_grid',
323
+ 27 => 'new_zealand_grid',
324
+ 28 => 'new_zealand_transverse',
325
+ 29 => 'qatar_grid',
326
+ 30 => 'modified_swedish_grid',
327
+ 31 => 'swedish_grid',
328
+ 32 => 'south_african_grid',
329
+ 33 => 'swiss_grid',
330
+ 34 => 'taiwan_grid',
331
+ 35 => 'united_states_grid',
332
+ 36 => 'utm_ups_grid',
333
+ 37 => 'west_malayan',
334
+ 38 => 'borneo_rso',
335
+ 39 => 'estonian_grid',
336
+ 40 => 'latvian_grid',
337
+ 41 => 'swedish_ref_99_grid' }
338
+ Fit::File::Types.add_type :sport, :enum, :values => {
339
+ 0 => 'generic',
340
+ 1 => 'running',
341
+ 2 => 'cycling',
342
+ 3 => 'transition',
343
+ 4 => 'fitness_equipment',
344
+ 5 => 'swimming',
345
+ 6 => 'basketball',
346
+ 7 => 'soccer',
347
+ 8 => 'tennis',
348
+ 9 => 'american_football',
349
+ 10 => 'training',
350
+ 11 => 'walking',
351
+ 12 => 'cross_country_skiing',
352
+ 13 => 'alpine_skiing',
353
+ 14 => 'snowboarding',
354
+ 15 => 'rowing',
355
+ 16 => 'mountaineering',
356
+ 17 => 'hiking',
357
+ 18 => 'multisport',
358
+ 19 => 'paddling',
359
+ 254 => 'all' }
360
+ Fit::File::Types.add_type :sport_bits_0, :uint8z, :values => {
361
+ 1 => 'generic',
362
+ 2 => 'running',
363
+ 4 => 'cycling',
364
+ 8 => 'transition',
365
+ 16 => 'fitness_equipment',
366
+ 32 => 'swimming',
367
+ 64 => 'basketball',
368
+ 128 => 'soccer' }
369
+ Fit::File::Types.add_type :sport_bits_1, :uint8z, :values => {
370
+ 1 => 'tennis',
371
+ 2 => 'american_football',
372
+ 4 => 'training',
373
+ 8 => 'walking',
374
+ 16 => 'cross_country_skiing',
375
+ 32 => 'alpine_skiing',
376
+ 64 => 'snowboarding',
377
+ 128 => 'rowing' }
378
+ Fit::File::Types.add_type :sport_bits_2, :uint8z, :values => {
379
+ 1 => 'mountaineering',
380
+ 2 => 'hiking',
381
+ 4 => 'multisport',
382
+ 8 => 'paddling' }
383
+ Fit::File::Types.add_type :sub_sport, :enum, :values => {
384
+ 0 => 'generic',
385
+ 1 => 'treadmill',
386
+ 2 => 'street',
387
+ 3 => 'trail',
388
+ 4 => 'track',
389
+ 5 => 'spin',
390
+ 6 => 'indoor_cycling',
391
+ 7 => 'road',
392
+ 8 => 'mountain',
393
+ 9 => 'downhill',
394
+ 10 => 'recumbent',
395
+ 11 => 'cyclocross',
396
+ 12 => 'hand_cycling',
397
+ 13 => 'track_cycling',
398
+ 14 => 'indoor_rowing',
399
+ 15 => 'elliptical',
400
+ 16 => 'stair_climbing',
401
+ 17 => 'lap_swimming',
402
+ 18 => 'open_water',
403
+ 19 => 'flexibility_training',
404
+ 20 => 'strength_training',
405
+ 21 => 'warm_up',
406
+ 22 => 'match',
407
+ 23 => 'exercise',
408
+ 24 => 'challenge',
409
+ 25 => 'indoor_skiing',
410
+ 26 => 'cardio_training',
411
+ 254 => 'all' }
412
+ Fit::File::Types.add_type :activity, :enum, :values => {
413
+ 0 => 'manual',
414
+ 1 => 'auto_multi_sport' }
415
+ Fit::File::Types.add_type :intensity, :enum, :values => {
416
+ 0 => 'active',
417
+ 1 => 'rest',
418
+ 2 => 'warmup',
419
+ 3 => 'cooldown' }
420
+ Fit::File::Types.add_type :session_trigger, :enum, :values => {
421
+ 0 => 'activity_end',
422
+ 1 => 'manual',
423
+ 2 => 'auto_multi_sport',
424
+ 3 => 'fitness_equipment' }
425
+ Fit::File::Types.add_type :autolap_trigger, :enum, :values => {
426
+ 0 => 'time',
427
+ 1 => 'distance',
428
+ 2 => 'position_start',
429
+ 3 => 'position_lap',
430
+ 4 => 'position_waypoint',
431
+ 5 => 'position_marked',
432
+ 6 => 'off' }
433
+ Fit::File::Types.add_type :lap_trigger, :enum, :values => {
434
+ 0 => 'manual',
435
+ 1 => 'time',
436
+ 2 => 'distance',
437
+ 3 => 'position_start',
438
+ 4 => 'position_lap',
439
+ 5 => 'position_waypoint',
440
+ 6 => 'position_marked',
441
+ 7 => 'session_end',
442
+ 8 => 'fitness_equipment' }
443
+ Fit::File::Types.add_type :event, :enum, :values => {
444
+ 0 => 'timer',
445
+ 3 => 'workout',
446
+ 4 => 'workout_step',
447
+ 5 => 'power_down',
448
+ 6 => 'power_up',
449
+ 7 => 'off_course',
450
+ 8 => 'session',
451
+ 9 => 'lap',
452
+ 10 => 'course_point',
453
+ 11 => 'battery',
454
+ 12 => 'virtual_partner_pace',
455
+ 13 => 'hr_high_alert',
456
+ 14 => 'hr_low_alert',
457
+ 15 => 'speed_high_alert',
458
+ 16 => 'speed_low_alert',
459
+ 17 => 'cad_high_alert',
460
+ 18 => 'cad_low_alert',
461
+ 19 => 'power_high_alert',
462
+ 20 => 'power_low_alert',
463
+ 21 => 'recovery_hr',
464
+ 22 => 'battery_low',
465
+ 23 => 'time_duration_alert',
466
+ 24 => 'distance_duration_alert',
467
+ 25 => 'calorie_duration_alert',
468
+ 26 => 'activity',
469
+ 27 => 'fitness_equipment',
470
+ 28 => 'length',
471
+ 32 => 'user_marker',
472
+ 33 => 'sport_point',
473
+ 36 => 'calibration',
474
+ 42 => 'front_gear_change',
475
+ 43 => 'rear_gear_change',
476
+ 45 => 'elev_high_alert',
477
+ 46 => 'elev_low_alert' }
478
+ Fit::File::Types.add_type :event_type, :enum, :values => {
479
+ 0 => 'start',
480
+ 1 => 'stop',
481
+ 2 => 'consecutive_depreciated',
482
+ 3 => 'marker',
483
+ 4 => 'stop_all',
484
+ 5 => 'begin_depreciated',
485
+ 6 => 'end_depreciated',
486
+ 7 => 'end_all_depreciated',
487
+ 8 => 'stop_disable',
488
+ 9 => 'stop_disable_all' }
489
+ Fit::File::Types.add_type :timer_trigger, :enum, :values => {
490
+ 0 => 'manual',
491
+ 1 => 'auto',
492
+ 2 => 'fitness_equipment' }
493
+ Fit::File::Types.add_type :fitness_equipment_state, :enum, :values => {
494
+ 0 => 'ready',
495
+ 1 => 'in_use',
496
+ 2 => 'paused',
497
+ 3 => 'unknown' }
498
+ Fit::File::Types.add_type :activity_class, :enum, :values => {
499
+ 127 => 'level',
500
+ 100 => 'level_max',
501
+ 128 => 'athlete' }
502
+ Fit::File::Types.add_type :hr_zone_calc, :enum, :values => {
503
+ 0 => 'custom',
504
+ 1 => 'percent_max_hr',
505
+ 2 => 'percent_hrr' }
506
+ Fit::File::Types.add_type :pwr_zone_calc, :enum, :values => {
507
+ 0 => 'custom',
508
+ 1 => 'percent_ftp' }
509
+ Fit::File::Types.add_type :wkt_step_duration, :enum, :values => {
510
+ 0 => 'time',
511
+ 1 => 'distance',
512
+ 2 => 'hr_less_than',
513
+ 3 => 'hr_greater_than',
514
+ 4 => 'calories',
515
+ 5 => 'open',
516
+ 6 => 'repeat_until_steps_cmplt',
517
+ 7 => 'repeat_until_time',
518
+ 8 => 'repeat_until_distance',
519
+ 9 => 'repeat_until_calories',
520
+ 10 => 'repeat_until_hr_less_than',
521
+ 11 => 'repeat_until_hr_greater_than',
522
+ 12 => 'repeat_until_power_less_than',
523
+ 13 => 'repeat_until_power_greater_than',
524
+ 14 => 'power_less_than',
525
+ 15 => 'power_greater_than',
526
+ 28 => 'repetition_time' }
527
+ Fit::File::Types.add_type :wkt_step_target, :enum, :values => {
528
+ 0 => 'speed',
529
+ 1 => 'heart_rate',
530
+ 2 => 'open',
531
+ 3 => 'cadence',
532
+ 4 => 'power',
533
+ 5 => 'grade',
534
+ 6 => 'resistance' }
535
+ Fit::File::Types.add_type :goal, :enum, :values => {
536
+ 0 => 'time',
537
+ 1 => 'distance',
538
+ 2 => 'calories',
539
+ 3 => 'frequency',
540
+ 4 => 'steps' }
541
+ Fit::File::Types.add_type :goal_recurrence, :enum, :values => {
542
+ 0 => 'off',
543
+ 1 => 'daily',
544
+ 2 => 'weekly',
545
+ 3 => 'monthly',
546
+ 4 => 'yearly',
547
+ 5 => 'custom' }
548
+ Fit::File::Types.add_type :schedule, :enum, :values => {
549
+ 0 => 'workout',
550
+ 1 => 'course' }
551
+ Fit::File::Types.add_type :course_point, :enum, :values => {
552
+ 0 => 'generic',
553
+ 1 => 'summit',
554
+ 2 => 'valley',
555
+ 3 => 'water',
556
+ 4 => 'food',
557
+ 5 => 'danger',
558
+ 6 => 'left',
559
+ 7 => 'right',
560
+ 8 => 'straight',
561
+ 9 => 'first_aid',
562
+ 10 => 'fourth_category',
563
+ 11 => 'third_category',
564
+ 12 => 'second_category',
565
+ 13 => 'first_category',
566
+ 14 => 'hors_category',
567
+ 15 => 'sprint',
568
+ 16 => 'left_fork',
569
+ 17 => 'right_fork',
570
+ 18 => 'middle_fork',
571
+ 19 => 'slight_left',
572
+ 20 => 'sharp_left',
573
+ 21 => 'slight_right',
574
+ 22 => 'sharp_right',
575
+ 23 => 'u_turn' }
576
+ Fit::File::Types.add_type :manufacturer, :uint16, :values => {
577
+ 1 => 'garmin',
578
+ 2 => 'garmin_fr405_antfs',
579
+ 3 => 'zephyr',
580
+ 4 => 'dayton',
581
+ 5 => 'idt',
582
+ 6 => 'srm',
583
+ 7 => 'quarq',
584
+ 8 => 'ibike',
585
+ 9 => 'saris',
586
+ 10 => 'spark_hk',
587
+ 11 => 'tanita',
588
+ 12 => 'echowell',
589
+ 13 => 'dynastream_oem',
590
+ 14 => 'nautilus',
591
+ 15 => 'dynastream',
592
+ 16 => 'timex',
593
+ 17 => 'metrigear',
594
+ 18 => 'xelic',
595
+ 19 => 'beurer',
596
+ 20 => 'cardiosport',
597
+ 21 => 'a_and_d',
598
+ 22 => 'hmm',
599
+ 23 => 'suunto',
600
+ 24 => 'thita_elektronik',
601
+ 25 => 'gpulse',
602
+ 26 => 'clean_mobile',
603
+ 27 => 'pedal_brain',
604
+ 28 => 'peaksware',
605
+ 29 => 'saxonar',
606
+ 30 => 'lemond_fitness',
607
+ 31 => 'dexcom',
608
+ 32 => 'wahoo_fitness',
609
+ 33 => 'octane_fitness',
610
+ 34 => 'archinoetics',
611
+ 35 => 'the_hurt_box',
612
+ 36 => 'citizen_systems',
613
+ 37 => 'magellan',
614
+ 38 => 'osynce',
615
+ 39 => 'holux',
616
+ 40 => 'concept2',
617
+ 42 => 'one_giant_leap',
618
+ 43 => 'ace_sensor',
619
+ 44 => 'brim_brothers',
620
+ 45 => 'xplova',
621
+ 46 => 'perception_digital',
622
+ 47 => 'bf1systems',
623
+ 48 => 'pioneer',
624
+ 49 => 'spantec',
625
+ 50 => 'metalogics',
626
+ 51 => '4iiiis',
627
+ 52 => 'seiko_epson',
628
+ 53 => 'seiko_epson_oem',
629
+ 54 => 'ifor_powell',
630
+ 55 => 'maxwell_guider',
631
+ 56 => 'star_trac',
632
+ 57 => 'breakaway',
633
+ 58 => 'alatech_technology_ltd',
634
+ 59 => 'mio_technology_europe',
635
+ 60 => 'rotor',
636
+ 61 => 'geonaute',
637
+ 62 => 'id_bike',
638
+ 63 => 'specialized',
639
+ 64 => 'wtek',
640
+ 65 => 'physical_enterprises',
641
+ 66 => 'north_pole_engineering',
642
+ 67 => 'bkool',
643
+ 68 => 'cateye',
644
+ 69 => 'stages_cycling',
645
+ 70 => 'sigmasport',
646
+ 71 => 'tomtom',
647
+ 72 => 'peripedal',
648
+ 73 => 'wattbike',
649
+ 76 => 'moxy',
650
+ 77 => 'ciclosport',
651
+ 78 => 'powerbahn',
652
+ 79 => 'acorn_projects_aps',
653
+ 80 => 'lifebeam',
654
+ 81 => 'bontrager',
655
+ 82 => 'wellgo',
656
+ 83 => 'scosche',
657
+ 84 => 'magura',
658
+ 85 => 'woodway',
659
+ 86 => 'elite',
660
+ 87 => 'nielsen_kellerman',
661
+ 88 => 'dk_city',
662
+ 89 => 'tacx',
663
+ 90 => 'direction_technology',
664
+ 91 => 'magtonic',
665
+ 92 => '1partcarbon',
666
+ 93 => 'inside_ride_technologies',
667
+ 255 => 'development',
668
+ 257 => 'healthandlife',
669
+ 258 => 'lezyne',
670
+ 259 => 'scribe_labs',
671
+ 5759 => 'actigraphcorp' }
672
+ Fit::File::Types.add_type :garmin_product, :uint16, :values => {
673
+ 1 => 'hrm1',
674
+ 2 => 'axh01',
675
+ 3 => 'axb01',
676
+ 4 => 'axb02',
677
+ 5 => 'hrm2ss',
678
+ 6 => 'dsi_alf02',
679
+ 7 => 'hrm3ss',
680
+ 8 => 'hrm_run_single_byte_product_id',
681
+ 9 => 'bsm',
682
+ 10 => 'bcm',
683
+ 473 => 'fr301_china',
684
+ 474 => 'fr301_japan',
685
+ 475 => 'fr301_korea',
686
+ 494 => 'fr301_taiwan',
687
+ 717 => 'fr405',
688
+ 782 => 'fr50',
689
+ 987 => 'fr405_japan',
690
+ 988 => 'fr60',
691
+ 1011 => 'dsi_alf01',
692
+ 1018 => 'fr310xt',
693
+ 1036 => 'edge500',
694
+ 1124 => 'fr110',
695
+ 1169 => 'edge800',
696
+ 1199 => 'edge500_taiwan',
697
+ 1213 => 'edge500_japan',
698
+ 1253 => 'chirp',
699
+ 1274 => 'fr110_japan',
700
+ 1325 => 'edge200',
701
+ 1328 => 'fr910xt',
702
+ 1333 => 'edge800_taiwan',
703
+ 1334 => 'edge800_japan',
704
+ 1341 => 'alf04',
705
+ 1345 => 'fr610',
706
+ 1360 => 'fr210_japan',
707
+ 1380 => 'vector_ss',
708
+ 1381 => 'vector_cp',
709
+ 1386 => 'edge800_china',
710
+ 1387 => 'edge500_china',
711
+ 1410 => 'fr610_japan',
712
+ 1422 => 'edge500_korea',
713
+ 1436 => 'fr70',
714
+ 1446 => 'fr310xt_4t',
715
+ 1461 => 'amx',
716
+ 1482 => 'fr10',
717
+ 1497 => 'edge800_korea',
718
+ 1499 => 'swim',
719
+ 1537 => 'fr910xt_china',
720
+ 1551 => 'fenix',
721
+ 1555 => 'edge200_taiwan',
722
+ 1561 => 'edge510',
723
+ 1567 => 'edge810',
724
+ 1570 => 'tempe',
725
+ 1600 => 'fr910xt_japan',
726
+ 1623 => 'fr620',
727
+ 1632 => 'fr220',
728
+ 1664 => 'fr910xt_korea',
729
+ 1688 => 'fr10_japan',
730
+ 1721 => 'edge810_japan',
731
+ 1735 => 'virb_elite',
732
+ 1736 => 'edge_touring',
733
+ 1742 => 'edge510_japan',
734
+ 1752 => 'hrm_run',
735
+ 1821 => 'edge510_asia',
736
+ 1822 => 'edge810_china',
737
+ 1823 => 'edge810_taiwan',
738
+ 1836 => 'edge1000',
739
+ 1837 => 'vivo_fit',
740
+ 1853 => 'virb_remote',
741
+ 1885 => 'vivo_ki',
742
+ 1903 => 'fr15',
743
+ 1918 => 'edge510_korea',
744
+ 1928 => 'fr620_japan',
745
+ 1929 => 'fr620_china',
746
+ 1930 => 'fr220_japan',
747
+ 1931 => 'fr220_china',
748
+ 1967 => 'fenix2',
749
+ 10007 => 'sdm4',
750
+ 10014 => 'edge_remote',
751
+ 20119 => 'training_center',
752
+ 65532 => 'android_antplus_plugin',
753
+ 65534 => 'connect' }
754
+ Fit::File::Types.add_type :antplus_device_type, :uint8, :values => {
755
+ 1 => 'antfs',
756
+ 11 => 'bike_power',
757
+ 12 => 'environment_sensor_legacy',
758
+ 15 => 'multi_sport_speed_distance',
759
+ 16 => 'control',
760
+ 17 => 'fitness_equipment',
761
+ 18 => 'blood_pressure',
762
+ 19 => 'geocache_node',
763
+ 20 => 'light_electric_vehicle',
764
+ 25 => 'env_sensor',
765
+ 26 => 'racquet',
766
+ 119 => 'weight_scale',
767
+ 120 => 'heart_rate',
768
+ 121 => 'bike_speed_cadence',
769
+ 122 => 'bike_cadence',
770
+ 123 => 'bike_speed',
771
+ 124 => 'stride_speed_distance' }
772
+ Fit::File::Types.add_type :ant_network, :enum, :values => {
773
+ 0 => 'public',
774
+ 1 => 'antplus',
775
+ 2 => 'antfs',
776
+ 3 => 'private' }
777
+ Fit::File::Types.add_type :workout_capabilities, :uint32z, :values => {
778
+ 0x00000001 => 'interval',
779
+ 0x00000002 => 'custom',
780
+ 0x00000004 => 'fitness_equipment',
781
+ 0x00000008 => 'firstbeat',
782
+ 0x00000010 => 'new_leaf',
783
+ 0x00000020 => 'tcx',
784
+ 0x00000080 => 'speed',
785
+ 0x00000100 => 'heart_rate',
786
+ 0x00000200 => 'distance',
787
+ 0x00000400 => 'cadence',
788
+ 0x00000800 => 'power',
789
+ 0x00001000 => 'grade',
790
+ 0x00002000 => 'resistance',
791
+ 0x00004000 => 'protected' }, :method => :bitfield_value
792
+ Fit::File::Types.add_type :battery_status, :uint8, :values => {
793
+ 1 => 'new',
794
+ 2 => 'good',
795
+ 3 => 'ok',
796
+ 4 => 'low',
797
+ 5 => 'critical' }
798
+ Fit::File::Types.add_type :hr_type, :enum, :values => {
799
+ 0 => 'normal',
800
+ 1 => 'irregular' }
801
+ Fit::File::Types.add_type :course_capabilities, :uint32z, :values => {
802
+ 0x00000001 => 'processed',
803
+ 0x00000002 => 'valid',
804
+ 0x00000004 => 'time',
805
+ 0x00000008 => 'distance',
806
+ 0x00000010 => 'position',
807
+ 0x00000020 => 'heart_rate',
808
+ 0x00000040 => 'power',
809
+ 0x00000080 => 'cadence',
810
+ 0x00000100 => 'training',
811
+ 0x00000200 => 'navigation' }, :method => :bitfield_value
812
+ Fit::File::Types.add_type :weight, :uint16, :values => {
813
+ 65534 => 'calculating' }
814
+ Fit::File::Types.add_type :workout_hr, :uint32, :values => {
815
+ 100 => 'bpm_offset' }
816
+ Fit::File::Types.add_type :workout_power, :uint32, :values => {
817
+ 1000 => 'watts_offset' }
818
+ Fit::File::Types.add_type :bp_status, :enum, :values => {
819
+ 0 => 'no_error',
820
+ 1 => 'error_incomplete_data',
821
+ 2 => 'error_no_measurement',
822
+ 3 => 'error_data_out_of_range',
823
+ 4 => 'error_irregular_heart_rate' }
824
+ Fit::File::Types.add_type :user_local_id, :uint16, :values => {
825
+ 0 => 'local_min',
826
+ 15 => 'local_max',
827
+ 16 => 'stationary_min',
828
+ 255 => 'stationary_max',
829
+ 256 => 'portable_min',
830
+ 65534 => 'portable_max' }
831
+ Fit::File::Types.add_type :swim_stroke, :enum, :values => {
832
+ 0 => 'freestyle',
833
+ 1 => 'backstroke',
834
+ 2 => 'breaststroke',
835
+ 3 => 'butterfly',
836
+ 4 => 'drill',
837
+ 5 => 'mixed',
838
+ 6 => 'im' }
839
+ Fit::File::Types.add_type :activity_type, :enum, :values => {
840
+ 0 => 'generic',
841
+ 1 => 'running',
842
+ 2 => 'cycling',
843
+ 3 => 'transition',
844
+ 4 => 'fitness_equipment',
845
+ 5 => 'swimming',
846
+ 6 => 'walking',
847
+ 254 => 'all' }
848
+ Fit::File::Types.add_type :activity_subtype, :enum, :values => {
849
+ 0 => 'generic',
850
+ 1 => 'treadmill',
851
+ 2 => 'street',
852
+ 3 => 'trail',
853
+ 4 => 'track',
854
+ 5 => 'spin',
855
+ 6 => 'indoor_cycling',
856
+ 7 => 'road',
857
+ 8 => 'mountain',
858
+ 9 => 'downhill',
859
+ 10 => 'recumbent',
860
+ 11 => 'cyclocross',
861
+ 12 => 'hand_cycling',
862
+ 13 => 'track_cycling',
863
+ 14 => 'indoor_rowing',
864
+ 15 => 'elliptical',
865
+ 16 => 'stair_climbing',
866
+ 17 => 'lap_swimming',
867
+ 18 => 'open_water',
868
+ 254 => 'all' }
869
+ Fit::File::Types.add_type :activity_level, :enum, :values => {
870
+ 0 => 'low',
871
+ 1 => 'medium',
872
+ 2 => 'high' }
873
+ Fit::File::Types.add_type :left_right_balance, :uint8, :values => {
874
+ 127 => 'mask',
875
+ 128 => 'right' }
876
+ Fit::File::Types.add_type :left_right_balance_100, :uint16, :values => {
877
+ 16383 => 'mask',
878
+ 32768 => 'right' }
879
+ Fit::File::Types.add_type :length_type, :enum, :values => {
880
+ 0 => 'idle',
881
+ 1 => 'active' }
882
+ Fit::File::Types.add_type :connectivity_capabilities, :uint32z, :values => {
883
+ 1 => 'bluetooth',
884
+ 2 => 'bluetooth_le',
885
+ 4 => 'ant',
886
+ 8 => 'activity_upload',
887
+ 16 => 'course_download',
888
+ 32 => 'workout_download',
889
+ 64 => 'live_track',
890
+ 128 => 'weather_conditions',
891
+ 256 => 'weather_alerts',
892
+ 512 => 'gps_ephemeris_download',
893
+ 1024 => 'explicit_archive',
894
+ 2048 => 'setup_incomplete',
895
+ 4096 => 'continue_sync_after_software_update',
896
+ 8192 => 'connect_iq_app_download' }
897
+ Fit::File::Types.add_type :stroke_type, :enum, :values => {
898
+ 0 => 'no_event',
899
+ 1 => 'other',
900
+ 2 => 'serve',
901
+ 3 => 'forehand',
902
+ 4 => 'backhand',
903
+ 5 => 'smash' }
904
+ Fit::File::Types.add_type :body_location, :enum, :values => {
905
+ 0 => 'left_leg',
906
+ 1 => 'left_calf',
907
+ 2 => 'left_shin',
908
+ 3 => 'left_hamstring',
909
+ 4 => 'left_quad',
910
+ 5 => 'left_glute',
911
+ 6 => 'right_leg',
912
+ 7 => 'right_calf',
913
+ 8 => 'right_shin',
914
+ 9 => 'right_hamstring',
915
+ 10 => 'right_quad',
916
+ 11 => 'right_glute',
917
+ 12 => 'torso_back',
918
+ 13 => 'left_lower_back',
919
+ 14 => 'left_upper_back',
920
+ 15 => 'right_lower_back',
921
+ 16 => 'right_upper_back',
922
+ 17 => 'torso_front',
923
+ 18 => 'left_abdomen',
924
+ 19 => 'left_chest',
925
+ 20 => 'right_abdomen',
926
+ 21 => 'right_chest',
927
+ 22 => 'left_arm',
928
+ 23 => 'left_shoulder',
929
+ 24 => 'left_bicep',
930
+ 25 => 'left_tricep',
931
+ 26 => 'left_brachioradialis',
932
+ 27 => 'left_forearm_extensors',
933
+ 28 => 'right_arm',
934
+ 29 => 'right_shoulder',
935
+ 30 => 'right_bicep',
936
+ 31 => 'right_tricep',
937
+ 32 => 'right_brachioradialis',
938
+ 33 => 'right_forearm_extensors',
939
+ 34 => 'neck',
940
+ 35 => 'throat' }
941
+ Fit::File::Types.add_type :source_type, :enum, :values => {
942
+ 0 => 'ant',
943
+ 1 => 'antplus',
944
+ 2 => 'bluetooth',
945
+ 3 => 'bluetooth_low_energy',
946
+ 4 => 'wifi',
947
+ 5 => 'local' }
948
+
949
+ # the type below is assigned to some fileds, but
950
+ # it is not defined in terms of values and basic type in FIT SDK as
951
+ # of 2015-01-29
952
+ Fit::File::Types.add_type :bool, :uint8, :values => {
953
+ 0 => false,
954
+ 1 => true }