garmin_connectr 0.0.5 → 0.0.6
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.
- data/README.rdoc +17 -9
- data/VERSION +1 -1
- data/examples/activity.rb +5 -6
- data/examples/activity_list.rb +6 -8
- data/features/activity.feature +109 -0
- data/features/activity_list.feature +6 -0
- data/features/step_definitions/activity_list_steps.rb +12 -0
- data/features/step_definitions/activity_steps.rb +17 -0
- data/features/support/env.rb +1 -0
- data/garmin_connectr.gemspec +8 -3
- data/lib/garmin_connectr.rb +110 -96
- metadata +17 -5
data/README.rdoc
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
GarminConnectr is a simple Ruby library for accessing data from Garmin Connect. As of 12/2009, Garmin's own Connect API has yet to be released. Until then, this screen scraping lib does the job.
|
4
4
|
|
5
|
+
CHANGELOG:
|
6
|
+
0.6: The Garmin Connect interface has been updated. I have rewritten most of garmin_connectr and added several cucumber tests. The API has changed. Please see the example usage below.
|
7
|
+
|
5
8
|
Install:
|
6
9
|
|
7
10
|
gem install garmin_connectr
|
@@ -12,23 +15,28 @@ Usage:
|
|
12
15
|
gc = GarminConnectr.new
|
13
16
|
|
14
17
|
# Load a specific activity
|
15
|
-
activity = gc.
|
18
|
+
activity = gc.load_activity( :id => ACTIVITY_ID )
|
16
19
|
puts "#{ g.activity } / #{ g.name } / #{ g.time } / #{ g.distance }"
|
17
20
|
|
21
|
+
puts "Available fields for this activity: #{ g.fields.join(',') }"
|
22
|
+
|
23
|
+
puts "Splits for this activity:"
|
24
|
+
g.activity.splits.each do |split|
|
25
|
+
puts "#{ split.split } / #{ split.distance } / #{ split.time }"
|
26
|
+
end
|
27
|
+
|
28
|
+
puts "Split summary:"
|
29
|
+
puts "#{ activity.split_summary.time }"
|
30
|
+
|
18
31
|
# Load a list of my activities
|
19
|
-
list = gc.
|
32
|
+
list = gc.load_activities( :username => garmin_connect_username,
|
33
|
+
:password => garmin_connect_password )
|
20
34
|
list.each do |activity|
|
21
|
-
activity.load!
|
22
35
|
puts "#{ activity.name } / #{ activity.start_time }"
|
23
36
|
end
|
24
37
|
|
25
|
-
# Review activity split/lap data
|
26
|
-
activity.splits.each do |split|
|
27
|
-
puts "#{ split['split'] }: Distance: #{ split['distance'] }"
|
28
|
-
end
|
29
|
-
|
30
38
|
See examples/*
|
31
39
|
|
32
40
|
== Copyright
|
33
41
|
|
34
|
-
Copyright (c)
|
42
|
+
Copyright (c) 2010 Adam Roth. See LICENSE for details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.6
|
data/examples/activity.rb
CHANGED
@@ -3,15 +3,14 @@ require '../lib/garmin_connectr.rb'
|
|
3
3
|
activity_id = 21450277
|
4
4
|
|
5
5
|
gc = GarminConnectr.new
|
6
|
-
activity = gc.
|
6
|
+
activity = gc.load_activity( :id => activity_id )
|
7
7
|
|
8
8
|
puts activity.name
|
9
|
-
puts " Activity : #{ activity.
|
9
|
+
puts " Activity : #{ activity.activity_type }"
|
10
10
|
puts " Distance : #{ activity.distance }"
|
11
|
-
puts " Start : #{ activity.
|
12
|
-
puts "
|
13
|
-
puts " Splits : #{ activity.splits.count }"
|
11
|
+
puts " Start : #{ activity.timestamp }"
|
12
|
+
puts " Splits : #{ activity.split_count }"
|
14
13
|
|
15
14
|
activity.splits.each do |split|
|
16
|
-
puts "\t#{ split
|
15
|
+
puts "\t#{ split.split } : Distance = #{ split.distance }"
|
17
16
|
end
|
data/examples/activity_list.rb
CHANGED
@@ -3,18 +3,16 @@ require '../lib/garmin_connectr.rb'
|
|
3
3
|
username = 'garmin_connect_username'
|
4
4
|
password = 'garmin_connect_password'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
:limit => 10 ## Limit to last 10 activites
|
9
|
-
}
|
6
|
+
username = 'adamjroth'
|
7
|
+
password = 'xcxcxc98'
|
10
8
|
|
11
9
|
gc = GarminConnectr.new
|
12
|
-
activities = gc.
|
10
|
+
activities = gc.load_activity_list( :username => username, :password => password )
|
13
11
|
|
14
12
|
activities.each do |activity|
|
15
|
-
puts "#{ activity.name }
|
13
|
+
puts "#{ activity.name }"
|
16
14
|
activity.load!
|
17
|
-
puts " Activity : #{ activity.
|
15
|
+
puts " Activity : #{ activity.activity_type }"
|
18
16
|
puts " Distance : #{ activity.distance }"
|
19
|
-
puts " Start : #{ activity.
|
17
|
+
puts " Start : #{ activity.timestamp }\n\n"
|
20
18
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
Scenario: Load Activity
|
2
|
+
Given I have loaded activity 30051790
|
3
|
+
Then the name should be "MTB - Mesh RDL "
|
4
|
+
And the activity_type should be "Mountain Biking"
|
5
|
+
And the event_type should be "Training"
|
6
|
+
And the timestamp should be "Wed, Apr 14, 2010 1:46 PM"
|
7
|
+
And the time should be "00:55:15"
|
8
|
+
And the distance should be "5.26 mi"
|
9
|
+
And the elevation_gain should be "610 ft"
|
10
|
+
And the calories should be "433 C"
|
11
|
+
And the avg_temperature should be "74.4 °F"
|
12
|
+
And the moving_time should be "00:35:39"
|
13
|
+
And the elapsed_time should be "00:55:15"
|
14
|
+
And the avg_speed should be "5.7 mph"
|
15
|
+
And the avg_moving_speed should be "8.9 mph"
|
16
|
+
And the max_speed should be "27.1 mph"
|
17
|
+
And the avg_pace should be "10:30 min/mi"
|
18
|
+
And the avg_moving_pace should be "06:46 min/mi"
|
19
|
+
And the best_pace should be "02:12 min/mi"
|
20
|
+
And the elevation_loss should be "615 ft"
|
21
|
+
And the min_elevation should be "334 ft"
|
22
|
+
And the max_elevation should be "886 ft"
|
23
|
+
And the avg_hr_bpm should be "132 bpm"
|
24
|
+
And the max_hr_bpm should be "172 bpm"
|
25
|
+
And the avg_hr_pom should be "67 % of Max"
|
26
|
+
And the max_hr_pom should be "87 % of Max"
|
27
|
+
And the avg_hr_hrzones should be "1.0 z"
|
28
|
+
And the max_hr_hrzones should be "3.9 z"
|
29
|
+
And the avg_bike_cadence should be "84 rpm"
|
30
|
+
And the max_bike_cadence should be "166 rpm"
|
31
|
+
And the avg_temperature should be "74.4 °F"
|
32
|
+
And the min_temperature should be "73.4 °F"
|
33
|
+
And the max_temperature should be "78.8 °F"
|
34
|
+
And the split_count should be "3"
|
35
|
+
|
36
|
+
Scenario: Load Activity with Splits
|
37
|
+
Given I have loaded activity 30051790
|
38
|
+
Then the split_count should be "3"
|
39
|
+
|
40
|
+
And the time for split 1 should be "00:08:51"
|
41
|
+
And the time for split 2 should be "00:26:16"
|
42
|
+
And the time for split 3 should be "00:20:07"
|
43
|
+
|
44
|
+
And the moving_time for split 1 should be "00:05:42"
|
45
|
+
And the moving_time for split 2 should be "00:16:18"
|
46
|
+
And the moving_time for split 3 should be "00:13:39"
|
47
|
+
|
48
|
+
And the distance for split 1 should be "1.55"
|
49
|
+
And the distance for split 2 should be "1.85"
|
50
|
+
And the distance for split 3 should be "1.87"
|
51
|
+
|
52
|
+
And the elevation_gain for split 1 should be "44"
|
53
|
+
And the elevation_gain for split 2 should be "483"
|
54
|
+
And the elevation_gain for split 3 should be "82"
|
55
|
+
|
56
|
+
And the elevation_loss for split 1 should be "368"
|
57
|
+
And the elevation_loss for split 2 should be "0"
|
58
|
+
And the elevation_loss for split 3 should be "247"
|
59
|
+
|
60
|
+
And the avg_speed for split 1 should be "10.5"
|
61
|
+
And the avg_speed for split 2 should be "4.2"
|
62
|
+
And the avg_speed for split 3 should be "5.6"
|
63
|
+
|
64
|
+
And the avg_moving_speed for split 1 should be "16.3"
|
65
|
+
And the avg_moving_speed for split 2 should be "6.8"
|
66
|
+
And the avg_moving_speed for split 3 should be "8.2"
|
67
|
+
|
68
|
+
And the max_speed for split 1 should be "27.1"
|
69
|
+
And the max_speed for split 2 should be "13.2"
|
70
|
+
And the max_speed for split 3 should be "25.8"
|
71
|
+
|
72
|
+
And the avg_hr for split 1 should be "111"
|
73
|
+
And the avg_hr for split 2 should be "141"
|
74
|
+
And the avg_hr for split 3 should be "131"
|
75
|
+
|
76
|
+
And the max_hr for split 1 should be "135"
|
77
|
+
And the max_hr for split 2 should be "172"
|
78
|
+
And the max_hr for split 3 should be "166"
|
79
|
+
|
80
|
+
And the avg_bike_cadence for split 1 should be "92"
|
81
|
+
And the avg_bike_cadence for split 2 should be "82"
|
82
|
+
And the avg_bike_cadence for split 3 should be "84"
|
83
|
+
|
84
|
+
And the max_bike_cadence for split 1 should be "146"
|
85
|
+
And the max_bike_cadence for split 2 should be "146"
|
86
|
+
And the max_bike_cadence for split 3 should be "166"
|
87
|
+
|
88
|
+
And the calories for split 1 should be "15"
|
89
|
+
And the calories for split 2 should be "266"
|
90
|
+
And the calories for split 3 should be "152"
|
91
|
+
|
92
|
+
And the avg_temp for split 1 should be "75.6"
|
93
|
+
And the avg_temp for split 2 should be "74.7"
|
94
|
+
And the avg_temp for split 3 should be "73.4"
|
95
|
+
|
96
|
+
And the time for split summary should be "00:55:15"
|
97
|
+
And the moving_time for split summary should be "00:35:39"
|
98
|
+
And the distance for split summary should be "5.26"
|
99
|
+
And the elevation_gain for split summary should be "610"
|
100
|
+
And the elevation_loss for split summary should be "615"
|
101
|
+
And the avg_speed for split summary should be "5.7"
|
102
|
+
And the avg_moving_speed for split summary should be "8.9"
|
103
|
+
And the max_speed for split summary should be "27.1"
|
104
|
+
And the avg_hr for split summary should be "132"
|
105
|
+
And the max_hr for split summary should be "172"
|
106
|
+
And the avg_bike_cadence for split summary should be "84"
|
107
|
+
And the max_bike_cadence for split summary should be "166"
|
108
|
+
And the calories for split summary should be "433"
|
109
|
+
And the avg_temp for split summary should be "74.4"
|
@@ -0,0 +1,6 @@
|
|
1
|
+
Scenario: Load Activity List
|
2
|
+
Given I have loaded the activity list for username USERNAME with password PASSWORD
|
3
|
+
Then the activity list should contain some activities
|
4
|
+
And the first activity should have a name
|
5
|
+
And the first activity should have a distance
|
6
|
+
And the first activity should have a activity_type
|
@@ -0,0 +1,12 @@
|
|
1
|
+
Given /^I have loaded the activity list for username ([\w]+) with password ([\w]+)$/ do |username, password|
|
2
|
+
@gc = GarminConnectr.new
|
3
|
+
@activities = @gc.load_activity_list( :username => username, :password => password )
|
4
|
+
end
|
5
|
+
|
6
|
+
Then /^the activity list should contain some activities$/ do
|
7
|
+
@activities.size.should_not == 0
|
8
|
+
end
|
9
|
+
|
10
|
+
Then /^the first activity should have a ([\w]+)$/ do |field|
|
11
|
+
@activities.first.send( field.to_sym ).should_not == nil
|
12
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Given /^I have loaded activity 30051790$/ do
|
2
|
+
@gc = GarminConnectr.new
|
3
|
+
@activity = @gc.load_activity( :id => 30051790 )
|
4
|
+
end
|
5
|
+
|
6
|
+
Then /^the ([\w_]+) should be "([^"]*)"$/ do |field, value|
|
7
|
+
value = value.to_i if field.to_s.match(/count/i)
|
8
|
+
@activity.send( field ).should == value
|
9
|
+
end
|
10
|
+
|
11
|
+
Then /^the ([\w_]+) for split ([\d\w]+) should be "([^\"]*)"$/ do |field, split, value|
|
12
|
+
if split == 'summary'
|
13
|
+
@activity.split_summary.send( field ).should == value
|
14
|
+
else
|
15
|
+
@activity.splits[ split.to_i - 1 ].send( field ).should == value
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'lib/garmin_connectr.rb'
|
data/garmin_connectr.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{garmin_connectr}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["aroth"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-04-17}
|
13
13
|
s.description = %q{GarminConnectr is a simple Ruby library for accessing data from Garmin Connect.}
|
14
14
|
s.email = %q{adamjroth@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -25,6 +25,11 @@ Gem::Specification.new do |s|
|
|
25
25
|
"VERSION",
|
26
26
|
"examples/activity.rb",
|
27
27
|
"examples/activity_list.rb",
|
28
|
+
"features/activity.feature",
|
29
|
+
"features/activity_list.feature",
|
30
|
+
"features/step_definitions/activity_list_steps.rb",
|
31
|
+
"features/step_definitions/activity_steps.rb",
|
32
|
+
"features/support/env.rb",
|
28
33
|
"garmin_connectr.gemspec",
|
29
34
|
"lib/garmin_connectr.rb",
|
30
35
|
"test/garmin_connectr_test.rb"
|
@@ -32,7 +37,7 @@ Gem::Specification.new do |s|
|
|
32
37
|
s.homepage = %q{http://github.com/aroth/garmin_connectr}
|
33
38
|
s.rdoc_options = ["--charset=UTF-8"]
|
34
39
|
s.require_paths = ["lib"]
|
35
|
-
s.rubygems_version = %q{1.3.
|
40
|
+
s.rubygems_version = %q{1.3.6}
|
36
41
|
s.summary = %q{GarminConnectr is a simple Ruby library for accessing data from Garmin Connect.}
|
37
42
|
s.test_files = [
|
38
43
|
"test/garmin_connectr_test.rb",
|
data/lib/garmin_connectr.rb
CHANGED
@@ -1,32 +1,28 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'nokogiri'
|
3
3
|
require 'open-uri'
|
4
|
-
require 'mechanize'
|
5
4
|
require 'fastercsv'
|
5
|
+
require 'simple-rss'
|
6
|
+
require 'mechanize'
|
6
7
|
|
7
8
|
class GarminConnectr
|
8
9
|
|
9
|
-
attr_reader :activity_list
|
10
|
-
|
11
10
|
def initialize
|
12
|
-
@activity_list = []
|
13
11
|
end
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
activity =
|
13
|
+
def load_activity( opts )
|
14
|
+
id = opts[:id]
|
15
|
+
activity = GarminConnectrActivity.new( :id => id )
|
18
16
|
activity.load!
|
19
17
|
end
|
20
18
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
## :preload [true/false] - Automatically fetch additional activity data for each activity returned (slower)
|
25
|
-
## :limit - Limit the number of activites returned (default: 50)
|
26
|
-
def activities( username, password, opts={} )
|
27
|
-
@activity_list = []
|
19
|
+
def load_activity_list( opts )
|
20
|
+
username = opts[:username]
|
21
|
+
password = opts[:password]
|
28
22
|
limit = opts[:limit] || 50
|
29
23
|
|
24
|
+
activity_list = []
|
25
|
+
|
30
26
|
agent = WWW::Mechanize.new { |agent| agent.user_agent_alias = 'Mac Safari' }
|
31
27
|
page = agent.get('http://connect.garmin.com/signin')
|
32
28
|
form = page.form('login')
|
@@ -42,112 +38,130 @@ class GarminConnectr
|
|
42
38
|
name = act.search('span').inner_html
|
43
39
|
act[:href].match(/\/([\d]+)$/)
|
44
40
|
aid = $1
|
45
|
-
|
46
|
-
|
47
|
-
activity.load! if opts[:preload]
|
48
|
-
@activity_list << activity
|
41
|
+
activity = GarminConnectrActivity.new( :id => aid, :name => name )
|
42
|
+
activity_list << activity
|
49
43
|
end
|
50
|
-
|
44
|
+
activity_list
|
51
45
|
end
|
52
46
|
|
53
47
|
end
|
54
48
|
|
55
|
-
class
|
49
|
+
class GarminConnectrActivity
|
50
|
+
attr_accessor :id, :data, :splits, :split_summary, :loaded
|
56
51
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
FIELDS = ['Avg Speed', 'Max Speed', 'Avg Power', 'Max Power', 'Elevation Gain', 'Elevation Loss', 'Min Elevation', 'Max Elevation', 'Avg HR', 'Max HR', 'Avg Bike Cadence', 'Max Bike Cadence', 'Avg Temperature', 'Min Temperature', 'Max Temperature', 'Avg Pace', 'Best Pace']
|
61
|
-
|
62
|
-
def initialize( activity_id, name=nil )
|
63
|
-
@activity_id = activity_id
|
64
|
-
@name = name unless name.nil?
|
65
|
-
@loaded = false
|
66
|
-
@fields = ['name', 'url', 'device', 'start_time']
|
52
|
+
def initialize( opts )
|
53
|
+
@id = opts[:id]
|
67
54
|
@splits = []
|
68
|
-
@
|
55
|
+
@data = {}
|
56
|
+
@data[:name] = opts[:name]
|
57
|
+
@loaded = false
|
69
58
|
end
|
70
|
-
|
71
|
-
## Fetch activity details. This will happen automatically if using GarminConnect#load. You will have
|
72
|
-
## call load! explicity on the activities returned by GarminConnect#activities unless the :preload option is set to true.
|
59
|
+
|
73
60
|
def load!
|
74
|
-
|
75
|
-
|
76
|
-
@url = "http://connect.garmin.com/activity/#{ @activity_id }"
|
77
|
-
@device = @doc.search('.additionalInfoContent span').inner_html.gsub('Device: ','')
|
78
|
-
@start_time = @doc.search('#activityStartDate').children[0].to_s.gsub(/[\n]+/,'')
|
79
|
-
@loaded = true
|
80
|
-
|
81
|
-
# Summary Fields (TODO: clean up)
|
82
|
-
@activity = @doc.search('#activityTypeValue').inner_html.gsub(/[\n]+/,'').strip rescue nil
|
83
|
-
@event = @doc.search('#eventTypeValue').inner_html.gsub(/[\n]+/,'').strip rescue nil
|
84
|
-
@time = @doc.css('#summaryTotalTime')[0].parent.children.search('.summaryField').inner_html.strip rescue nil
|
85
|
-
@distance = @doc.css('#summaryDistance')[0].parent.children.search('.summaryField').inner_html.strip rescue nil
|
86
|
-
@calories = @doc.css('#summaryCalories')[0].parent.children.search('.summaryField').inner_html.strip rescue nil
|
87
|
-
|
88
|
-
# Tabbed Fields
|
89
|
-
FIELDS.each do |field|
|
90
|
-
name = field.downcase.gsub(' ','_')
|
91
|
-
self.instance_variable_set("@#{ name }", self.send( :tab_data, field ) )
|
92
|
-
end
|
93
|
-
|
94
|
-
# Splits - parse CSV
|
95
|
-
@doc = open("http://connect.garmin.com/csvExporter/#{ @activity_id }.csv")
|
96
|
-
@splits = []
|
97
|
-
@split_summary = {}
|
61
|
+
url = "http://connect.garmin.com/activity/#{ @id }"
|
62
|
+
doc = Nokogiri::HTML(open(url))
|
98
63
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
64
|
+
# HR cell name manipulation
|
65
|
+
['bpm', 'pom', 'hrZones'].each do |hr|
|
66
|
+
doc.css("##{ hr }Summary td").each do |e|
|
67
|
+
e.inner_html = "Max HR #{ hr.upcase }:" if e.inner_html =~ /Max HR/i
|
68
|
+
e.inner_html = "Avg HR #{ hr.upcase }:" if e.inner_html =~ /Avg HR/i
|
69
|
+
end
|
103
70
|
end
|
104
|
-
|
105
|
-
@
|
106
|
-
|
107
|
-
|
108
|
-
|
71
|
+
|
72
|
+
@scrape = {
|
73
|
+
:details => {
|
74
|
+
:name => doc.css('#activityName').inner_html,
|
75
|
+
:activity_type => doc.css('#activityTypeValue').inner_html.gsub(/[\n\t]+/,''),
|
76
|
+
:event_type => doc.css('#eventTypeValue').inner_html.gsub(/[\n\t]+/,''),
|
77
|
+
:timestamp => doc.css('#timestamp').inner_html.gsub(/[\n\t]+/,''),
|
78
|
+
:embed => doc.css('.detailsEmbedCode').attr('value').value
|
79
|
+
},
|
80
|
+
:summaries => {
|
81
|
+
:overall => { :css => '#detailsOverallBox' },
|
82
|
+
:timing => { :css => '#detailsTimingBox' },
|
83
|
+
:elevation => { :css => '#detailsElevationBox' },
|
84
|
+
:heart_rate => { :css => '#detailsHeartRateBox' },
|
85
|
+
:cadence => { :css => '#detailsCadenceBox' },
|
86
|
+
:temperature => { :css => '#detailsTemperatureBox' },
|
87
|
+
:power => { :css => '#detailsPowerBox' }
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
@scrape[:details][:split_count] = doc.css('.detailsLapsNumber')[0].inner_html.to_i rescue 0
|
92
|
+
|
93
|
+
@scrape[:details].each { |k,v| @data[k] = v }
|
94
|
+
@scrape[:summaries].each do |k,v|
|
95
|
+
doc.css("#{ v[:css] } td").each do |e|
|
96
|
+
if e.inner_html =~ /:[ ]?$/
|
97
|
+
key = e.inner_html.downcase.gsub(/ $/,'').gsub(/:/,'').gsub(' ','_').to_sym
|
98
|
+
@data[key] = e.next.next.inner_html.strip
|
99
|
+
end
|
109
100
|
end
|
110
|
-
@splits << split
|
111
101
|
end
|
112
|
-
|
113
|
-
|
114
|
-
|
102
|
+
|
103
|
+
## Splits
|
104
|
+
if self.split_count > 0
|
105
|
+
load_splits!
|
115
106
|
end
|
116
|
-
|
107
|
+
|
108
|
+
@loaded = true
|
117
109
|
self
|
118
110
|
end
|
119
111
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
## distance
|
125
|
-
## elevation_gain
|
126
|
-
## elevation_loss
|
127
|
-
## avg_speed
|
128
|
-
## max_speed
|
129
|
-
## avg_hr
|
130
|
-
## max_hr
|
131
|
-
## avg_bike_cadence
|
132
|
-
## max_bike_cadence
|
133
|
-
## calories
|
134
|
-
## avg_temp
|
135
|
-
## max_power
|
136
|
-
## avg_power
|
112
|
+
def fields
|
113
|
+
@data.keys
|
114
|
+
end
|
115
|
+
|
137
116
|
def splits
|
117
|
+
self.load! unless @loaded
|
138
118
|
@splits
|
139
119
|
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def load_splits!
|
124
|
+
doc = open("http://connect.garmin.com/csvExporter/#{ @id }.csv")
|
125
|
+
|
126
|
+
keys = []
|
127
|
+
csv = FasterCSV.parse( doc.read )
|
128
|
+
csv[0].each do |key|
|
129
|
+
keys.push key.downcase.gsub(' ','_') if key.is_a?(String)
|
130
|
+
end
|
131
|
+
|
132
|
+
csv[1, csv.length-1].each_with_index do |row, index|
|
133
|
+
split = GarminConnectrActivitySplit.new
|
134
|
+
keys.each_with_index do |key, key_index|
|
135
|
+
split.data[ key.to_sym ] = row[ key_index ].strip
|
136
|
+
end
|
137
|
+
index < csv.length - 2 ? @splits << split : @split_summary = split
|
138
|
+
end
|
139
|
+
end
|
140
140
|
|
141
|
-
|
142
|
-
|
143
|
-
@
|
141
|
+
def method_missing(name)
|
142
|
+
self.load! if !@data[name.to_sym] and !@loaded # lazy loading
|
143
|
+
@data[name.to_sym]
|
144
144
|
end
|
145
145
|
|
146
|
+
end
|
147
|
+
|
148
|
+
class GarminConnectrActivitySplit
|
149
|
+
|
150
|
+
attr_reader :index, :data
|
151
|
+
|
152
|
+
def initialize( opts={} )
|
153
|
+
@index = opts[:index]
|
154
|
+
@data = {}
|
155
|
+
end
|
156
|
+
|
157
|
+
def fields
|
158
|
+
@data.keys
|
159
|
+
end
|
160
|
+
|
146
161
|
private
|
147
162
|
|
148
|
-
def
|
149
|
-
|
150
|
-
@doc.css('.label').to_a.delete_if { |e| e.inner_html != label }.first.parent.children.search('.field').inner_html.strip rescue nil
|
163
|
+
def method_missing(name)
|
164
|
+
@data[name.to_sym]
|
151
165
|
end
|
152
|
-
|
166
|
+
|
153
167
|
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: garmin_connectr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 6
|
9
|
+
version: 0.0.6
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- aroth
|
@@ -9,7 +14,7 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-
|
17
|
+
date: 2010-04-17 00:00:00 -04:00
|
13
18
|
default_executable:
|
14
19
|
dependencies: []
|
15
20
|
|
@@ -31,6 +36,11 @@ files:
|
|
31
36
|
- VERSION
|
32
37
|
- examples/activity.rb
|
33
38
|
- examples/activity_list.rb
|
39
|
+
- features/activity.feature
|
40
|
+
- features/activity_list.feature
|
41
|
+
- features/step_definitions/activity_list_steps.rb
|
42
|
+
- features/step_definitions/activity_steps.rb
|
43
|
+
- features/support/env.rb
|
34
44
|
- garmin_connectr.gemspec
|
35
45
|
- lib/garmin_connectr.rb
|
36
46
|
- test/garmin_connectr_test.rb
|
@@ -47,18 +57,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
47
57
|
requirements:
|
48
58
|
- - ">="
|
49
59
|
- !ruby/object:Gem::Version
|
60
|
+
segments:
|
61
|
+
- 0
|
50
62
|
version: "0"
|
51
|
-
version:
|
52
63
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
64
|
requirements:
|
54
65
|
- - ">="
|
55
66
|
- !ruby/object:Gem::Version
|
67
|
+
segments:
|
68
|
+
- 0
|
56
69
|
version: "0"
|
57
|
-
version:
|
58
70
|
requirements: []
|
59
71
|
|
60
72
|
rubyforge_project:
|
61
|
-
rubygems_version: 1.3.
|
73
|
+
rubygems_version: 1.3.6
|
62
74
|
signing_key:
|
63
75
|
specification_version: 3
|
64
76
|
summary: GarminConnectr is a simple Ruby library for accessing data from Garmin Connect.
|