garmin-fit 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|