garmin-fit 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/lib/fit.rb +20 -0
- data/lib/fit/file.rb +29 -0
- data/lib/fit/file/data.rb +36 -0
- data/lib/fit/file/definition.rb +94 -0
- data/lib/fit/file/definitions.rb +408 -0
- data/lib/fit/file/header.rb +17 -0
- data/lib/fit/file/record.rb +37 -0
- data/lib/fit/file/record_header.rb +27 -0
- data/lib/fit/version.rb +3 -0
- data/spec/file/data_spec.rb +14 -0
- data/spec/file/definition_spec.rb +18 -0
- data/spec/file/definitions_spec.rb +42 -0
- data/spec/file/header_spec.rb +15 -0
- data/spec/file/record_header_spec.rb +20 -0
- data/spec/file/record_spec.rb +29 -0
- data/spec/file_spec.rb +7 -0
- data/spec/fit_spec.rb +10 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/examples/file/header +0 -0
- data/spec/support/examples/record/definition_record +0 -0
- data/spec/support/examples/record/message/definition +0 -0
- data/spec/support/examples/record/normal_header +1 -0
- metadata +106 -0
checksums.yaml
ADDED
@@ -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=
|
data/lib/fit.rb
ADDED
@@ -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
|
data/lib/fit/file.rb
ADDED
@@ -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
|
data/lib/fit/version.rb
ADDED
@@ -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
|
data/spec/file_spec.rb
ADDED
data/spec/fit_spec.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -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
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
@
|
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
|