rubyfit 0.0.8 → 0.0.9
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 +4 -4
- data/lib/rubyfit/message_constants.rb +83 -0
- data/lib/rubyfit/message_writer.rb +13 -31
- data/lib/rubyfit/type.rb +7 -0
- data/lib/rubyfit/version.rb +1 -1
- data/lib/rubyfit/writer.rb +58 -43
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 00b20b537878f333895f88bcd88bfa2aed26118a
|
4
|
+
data.tar.gz: 5638078b60c7fdbe1dd984e94225a4645959eb3e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5643d322008304a699877b16b8eac3dfdf8a08ce0a29bef8bf1eab7795ce6e64b4f99b7c2dd0720636d83e8e6d4e88ee36388e9a2182f7b80365134a7f53764e
|
7
|
+
data.tar.gz: 887e0f5f1d80504287437b935b16dc82c989e3b6a6709e0c54ecaff4a96c6f5e0e51c743c78e73be7e0f749fca7be646cf332cb257660814a668880be3c2febf
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module RubyFit::MessageConstants
|
2
|
+
COURSE_POINT_TYPE = {
|
3
|
+
invalid: 255,
|
4
|
+
generic: 0,
|
5
|
+
summit: 1,
|
6
|
+
valley: 2,
|
7
|
+
water: 3,
|
8
|
+
food: 4,
|
9
|
+
danger: 5,
|
10
|
+
left: 6,
|
11
|
+
right: 7,
|
12
|
+
straight: 8,
|
13
|
+
first_aid: 9,
|
14
|
+
fourth_category: 10,
|
15
|
+
third_category: 11,
|
16
|
+
second_category: 12,
|
17
|
+
first_category: 13,
|
18
|
+
hors_category: 14,
|
19
|
+
sprint: 15,
|
20
|
+
left_fork: 16,
|
21
|
+
right_fork: 17,
|
22
|
+
middle_fork: 18,
|
23
|
+
slight_left: 19,
|
24
|
+
sharp_left: 20,
|
25
|
+
slight_right: 21,
|
26
|
+
sharp_right: 22,
|
27
|
+
u_turn: 23,
|
28
|
+
segment_start: 24,
|
29
|
+
segment_end: 25
|
30
|
+
}.freeze
|
31
|
+
|
32
|
+
EVENT_TYPE = {
|
33
|
+
start: 0,
|
34
|
+
stop: 1,
|
35
|
+
consecutive_depreciated: 2,
|
36
|
+
marker: 3,
|
37
|
+
stop_all: 4,
|
38
|
+
begin_depreciated: 5,
|
39
|
+
end_depreciated: 6,
|
40
|
+
end_all_depreciated: 7,
|
41
|
+
stop_disable: 8,
|
42
|
+
stop_disable_all: 9,
|
43
|
+
}.freeze
|
44
|
+
|
45
|
+
EVENT = {
|
46
|
+
timer: 0, # Group 0. Start / stop_all
|
47
|
+
workout: 3, # start / stop
|
48
|
+
workout_step: 4, # Start at beginning of workout. Stop at end of each step.
|
49
|
+
power_down: 5, # stop_all group 0
|
50
|
+
power_up: 6, # stop_all group 0
|
51
|
+
off_course: 7, # start / stop group 0
|
52
|
+
session: 8, # Stop at end of each session.
|
53
|
+
lap: 9, # Stop at end of each lap.
|
54
|
+
course_point: 10, # marker
|
55
|
+
battery: 11, # marker
|
56
|
+
virtual_partner_pace: 12, # Group 1. Start at beginning of activity if VP enabled, when VP pace is changed during activity or VP enabled mid activity. stop_disable when VP disabled.
|
57
|
+
hr_high_alert: 13, # Group 0. Start / stop when in alert condition.
|
58
|
+
hr_low_alert: 14, # Group 0. Start / stop when in alert condition.
|
59
|
+
speed_high_alert: 15, # Group 0. Start / stop when in alert condition.
|
60
|
+
speed_low_alert: 16, # Group 0. Start / stop when in alert condition.
|
61
|
+
cad_high_alert: 17, # Group 0. Start / stop when in alert condition.
|
62
|
+
cad_low_alert: 18, # Group 0. Start / stop when in alert condition.
|
63
|
+
power_high_alert: 19, # Group 0. Start / stop when in alert condition.
|
64
|
+
power_low_alert: 20, # Group 0. Start / stop when in alert condition.
|
65
|
+
recovery_hr: 21, # marker
|
66
|
+
battery_low: 22, # marker
|
67
|
+
time_duration_alert: 23, # Group 1. Start if enabled mid activity (not required at start of activity). Stop when duration is reached. stop_disable if disabled.
|
68
|
+
distance_duration_alert: 24, # Group 1. Start if enabled mid activity (not required at start of activity). Stop when duration is reached. stop_disable if disabled.
|
69
|
+
calorie_duration_alert: 25, # Group 1. Start if enabled mid activity (not required at start of activity). Stop when duration is reached. stop_disable if disabled.
|
70
|
+
activity: 26, # Group 1.. Stop at end of activity.
|
71
|
+
fitness_equipment: 27, # marker
|
72
|
+
length: 28, # Stop at end of each length.
|
73
|
+
user_marker: 32, # marker
|
74
|
+
sport_point: 33, # marker
|
75
|
+
calibration: 36, # start/stop/marker
|
76
|
+
front_gear_change: 42, # marker
|
77
|
+
rear_gear_change: 43, # marker
|
78
|
+
rider_position_change: 44, # marker
|
79
|
+
elev_high_alert: 45, # Group 0. Start / stop when in alert condition.
|
80
|
+
elev_low_alert: 46, # Group 0. Start / stop when in alert condition.
|
81
|
+
comm_timeout: 47, # marker
|
82
|
+
}.freeze
|
83
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "rubyfit/type"
|
2
2
|
require "rubyfit/helpers"
|
3
|
+
require "rubyfit/message_constants"
|
3
4
|
|
4
5
|
class RubyFit::MessageWriter
|
5
6
|
extend RubyFit::Helpers
|
@@ -7,36 +8,6 @@ class RubyFit::MessageWriter
|
|
7
8
|
FIT_PROTOCOL_VERSION = 0x10 # major 1, minor 0
|
8
9
|
FIT_PROFILE_VERSION = 1 * 100 + 52 # major 1, minor 52
|
9
10
|
|
10
|
-
COURSE_POINT_TYPE = {
|
11
|
-
invalid: 255,
|
12
|
-
generic: 0,
|
13
|
-
summit: 1,
|
14
|
-
valley: 2,
|
15
|
-
water: 3,
|
16
|
-
food: 4,
|
17
|
-
danger: 5,
|
18
|
-
left: 6,
|
19
|
-
right: 7,
|
20
|
-
straight: 8,
|
21
|
-
first_aid: 9,
|
22
|
-
fourth_category: 10,
|
23
|
-
third_category: 11,
|
24
|
-
second_category: 12,
|
25
|
-
first_category: 13,
|
26
|
-
hors_category: 14,
|
27
|
-
sprint: 15,
|
28
|
-
left_fork: 16,
|
29
|
-
right_fork: 17,
|
30
|
-
middle_fork: 18,
|
31
|
-
slight_left: 19,
|
32
|
-
sharp_left: 20,
|
33
|
-
slight_right: 21,
|
34
|
-
sharp_right: 22,
|
35
|
-
u_turn: 23,
|
36
|
-
segment_start: 24,
|
37
|
-
segment_end: 25
|
38
|
-
}.freeze
|
39
|
-
|
40
11
|
MESSAGE_DEFINITIONS = {
|
41
12
|
file_id: {
|
42
13
|
id: 0,
|
@@ -59,6 +30,8 @@ class RubyFit::MessageWriter
|
|
59
30
|
fields: {
|
60
31
|
timestamp: { id: 253, type: RubyFit::Type.timestamp, required: true},
|
61
32
|
start_time: { id: 2, type: RubyFit::Type.timestamp, required: true},
|
33
|
+
total_elapsed_time: { id: 7, type: RubyFit::Type.duration, required: true },
|
34
|
+
total_timer_time: { id: 8, type: RubyFit::Type.duration, required: true },
|
62
35
|
start_y: { id: 3, type: RubyFit::Type.semicircles },
|
63
36
|
start_x: { id: 4, type: RubyFit::Type.semicircles },
|
64
37
|
end_y: { id: 5, type: RubyFit::Type.semicircles },
|
@@ -75,7 +48,7 @@ class RubyFit::MessageWriter
|
|
75
48
|
distance: { id: 4, type: RubyFit::Type.centimeters },
|
76
49
|
name: { id: 6, type: RubyFit::Type.string(16) },
|
77
50
|
message_index: { id: 254, type: RubyFit::Type.uint16 },
|
78
|
-
type: { id: 5, type: RubyFit::Type.enum, values: COURSE_POINT_TYPE, required: true }
|
51
|
+
type: { id: 5, type: RubyFit::Type.enum, values: RubyFit::MessageConstants::COURSE_POINT_TYPE, required: true }
|
79
52
|
},
|
80
53
|
},
|
81
54
|
record: {
|
@@ -87,6 +60,15 @@ class RubyFit::MessageWriter
|
|
87
60
|
distance: { id: 5, type: RubyFit::Type.centimeters },
|
88
61
|
elevation: { id: 2, type: RubyFit::Type.altitude },
|
89
62
|
}
|
63
|
+
},
|
64
|
+
event: {
|
65
|
+
id: 21,
|
66
|
+
fields: {
|
67
|
+
timestamp: { id: 253, type: RubyFit::Type.timestamp, required: true },
|
68
|
+
event: { id: 0, type: RubyFit::Type.enum, values: RubyFit::MessageConstants::EVENT, required: true },
|
69
|
+
event_type: { id: 1, type: RubyFit::Type.enum, values: RubyFit::MessageConstants::EVENT_TYPE, required: true },
|
70
|
+
event_group: { id: 4, type: RubyFit::Type.uint8 },
|
71
|
+
}
|
90
72
|
}
|
91
73
|
}
|
92
74
|
|
data/lib/rubyfit/type.rb
CHANGED
data/lib/rubyfit/version.rb
CHANGED
data/lib/rubyfit/writer.rb
CHANGED
@@ -1,57 +1,44 @@
|
|
1
1
|
require "rubyfit/message_writer"
|
2
2
|
|
3
3
|
class RubyFit::Writer
|
4
|
+
PRODUCT_ID = 65534 # Garmin Connect
|
5
|
+
|
4
6
|
def write(stream, opts = {})
|
5
7
|
raise "Can't start write mode from #{@state}" if @state
|
6
8
|
@state = :write
|
7
|
-
@local_nums =
|
9
|
+
@local_nums = {}
|
10
|
+
@last_local_num = -1
|
8
11
|
|
9
12
|
@stream = stream
|
10
13
|
|
11
|
-
%i(start_time
|
14
|
+
%i(start_time duration course_point_count track_point_count name
|
12
15
|
total_distance time_created start_x start_y end_x end_y).each do |key|
|
13
16
|
raise ArgumentError.new("Missing required option #{key}") unless opts[key]
|
14
17
|
end
|
15
18
|
|
16
19
|
start_time = opts[:start_time].to_i
|
17
|
-
|
20
|
+
duration = opts[:duration].to_i
|
18
21
|
|
19
22
|
@data_crc = 0
|
20
23
|
|
21
|
-
|
22
|
-
definition_sizes = %i(file_id course lap course_point record)
|
23
|
-
.map{|type| RubyFit::MessageWriter.definition_message_size(type) }
|
24
|
-
.reduce(&:+)
|
25
|
-
|
26
|
-
data_sizes = {
|
27
|
-
file_id: 1,
|
28
|
-
course: 1,
|
29
|
-
lap: 1,
|
30
|
-
course_point: opts[:course_point_count],
|
31
|
-
record: opts[:track_point_count]
|
32
|
-
}
|
33
|
-
.map{|type, count| RubyFit::MessageWriter.data_message_size(type) * count }
|
34
|
-
.reduce(&:+)
|
35
|
-
|
36
|
-
data_size = definition_sizes + data_sizes
|
24
|
+
data_size = calculate_data_size(opts[:course_point_count], opts[:track_point_count])
|
37
25
|
write_data(RubyFit::MessageWriter.file_header(data_size))
|
38
26
|
|
39
|
-
|
40
|
-
write_data_message(:file_id, {
|
27
|
+
write_message(:file_id, {
|
41
28
|
time_created: opts[:time_created],
|
42
29
|
type: 6, # Course file
|
43
30
|
manufacturer: 1, # Garmin
|
44
|
-
product:
|
31
|
+
product: PRODUCT_ID,
|
45
32
|
serial_number: 0,
|
46
33
|
})
|
47
34
|
|
48
|
-
|
49
|
-
write_data_message(:course, { name: opts[:name] })
|
35
|
+
write_message(:course, { name: opts[:name] })
|
50
36
|
|
51
|
-
|
52
|
-
write_data_message(:lap, {
|
37
|
+
write_message(:lap, {
|
53
38
|
start_time: start_time,
|
54
|
-
timestamp:
|
39
|
+
timestamp: start_time,
|
40
|
+
total_elapsed_time: duration,
|
41
|
+
total_timer_time: duration,
|
55
42
|
start_x: opts[:start_x],
|
56
43
|
start_y: opts[:start_y],
|
57
44
|
end_x: opts[:end_x],
|
@@ -59,8 +46,22 @@ class RubyFit::Writer
|
|
59
46
|
total_distance: opts[:total_distance]
|
60
47
|
})
|
61
48
|
|
49
|
+
write_message(:event, {
|
50
|
+
timestamp: start_time,
|
51
|
+
event: :timer,
|
52
|
+
event_type: :start,
|
53
|
+
event_group: 0
|
54
|
+
})
|
55
|
+
|
62
56
|
yield
|
63
57
|
|
58
|
+
write_message(:event, {
|
59
|
+
timestamp: start_time + duration,
|
60
|
+
event: :timer,
|
61
|
+
event_type: :stop_disable_all,
|
62
|
+
event_group: 0
|
63
|
+
})
|
64
|
+
|
64
65
|
write_data(RubyFit::MessageWriter.crc(@data_crc))
|
65
66
|
@state = nil
|
66
67
|
end
|
@@ -68,7 +69,6 @@ class RubyFit::Writer
|
|
68
69
|
def course_points
|
69
70
|
raise "Can only start course points mode inside 'write' block" if @state != :write
|
70
71
|
@state = :course_points
|
71
|
-
write_definition_message(:course_point)
|
72
72
|
yield
|
73
73
|
@state = :write
|
74
74
|
end
|
@@ -76,29 +76,32 @@ class RubyFit::Writer
|
|
76
76
|
def track_points
|
77
77
|
raise "Can only write track points inside 'write' block" if @state != :write
|
78
78
|
@state = :track_points
|
79
|
-
write_definition_message(:record)
|
80
79
|
yield
|
81
80
|
@state = :write
|
82
81
|
end
|
83
82
|
|
84
83
|
def course_point(values)
|
85
84
|
raise "Can only write course points inside 'course_points' block" if @state != :course_points
|
86
|
-
|
85
|
+
write_message(:course_point, values)
|
87
86
|
end
|
88
87
|
|
89
88
|
def track_point(values)
|
90
89
|
raise "Can only write track points inside 'track_points' block" if @state != :track_points
|
91
|
-
|
90
|
+
write_message(:record, values)
|
92
91
|
end
|
93
92
|
|
94
93
|
protected
|
95
|
-
|
96
|
-
def write_definition_message(type)
|
97
|
-
write_data(RubyFit::MessageWriter.definition_message(type, local_num(type)))
|
98
|
-
end
|
99
94
|
|
100
|
-
def
|
101
|
-
|
95
|
+
def write_message(type, values)
|
96
|
+
local_num = @local_nums[type]
|
97
|
+
unless local_num
|
98
|
+
@last_local_num += 1
|
99
|
+
local_num = @last_local_num
|
100
|
+
@local_nums[type] = local_num
|
101
|
+
write_data(RubyFit::MessageWriter.definition_message(type, local_num))
|
102
|
+
end
|
103
|
+
|
104
|
+
write_data(RubyFit::MessageWriter.data_message(type, local_num, values))
|
102
105
|
end
|
103
106
|
|
104
107
|
def write_data(data)
|
@@ -107,12 +110,24 @@ class RubyFit::Writer
|
|
107
110
|
@data_crc = RubyFit::CRC.update_crc(@data_crc, data)
|
108
111
|
end
|
109
112
|
|
110
|
-
def
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
113
|
+
def calculate_data_size(course_point_count, track_point_count)
|
114
|
+
record_counts = {
|
115
|
+
file_id: 1,
|
116
|
+
course: 1,
|
117
|
+
lap: 1,
|
118
|
+
event: 2,
|
119
|
+
course_point: course_point_count,
|
120
|
+
record: track_point_count,
|
121
|
+
}
|
122
|
+
|
123
|
+
data_sizes = record_counts.map do |type, count|
|
124
|
+
def_size = RubyFit::MessageWriter.definition_message_size(type)
|
125
|
+
data_size = RubyFit::MessageWriter.data_message_size(type) * count
|
126
|
+
result = def_size + data_size
|
127
|
+
puts "#{type}: #{result}"
|
128
|
+
result
|
115
129
|
end
|
116
|
-
|
130
|
+
|
131
|
+
data_sizes.reduce(&:+)
|
117
132
|
end
|
118
133
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubyfit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cullen King
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-02-
|
11
|
+
date: 2018-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -91,6 +91,7 @@ files:
|
|
91
91
|
- ext/rubyfit/rubyfit.c
|
92
92
|
- lib/rubyfit.rb
|
93
93
|
- lib/rubyfit/helpers.rb
|
94
|
+
- lib/rubyfit/message_constants.rb
|
94
95
|
- lib/rubyfit/message_writer.rb
|
95
96
|
- lib/rubyfit/type.rb
|
96
97
|
- lib/rubyfit/version.rb
|