garmin_connectr 0.0.1 → 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.
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 aroth
1
+ Copyright (c) 2009 Adam Roth
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.rdoc CHANGED
@@ -1,18 +1,7 @@
1
1
  = garmin_connectr
2
2
 
3
- Description goes here.
4
-
5
- == Note on Patches/Pull Requests
6
-
7
- * Fork the project.
8
- * Make your feature addition or bug fix.
9
- * Add tests for it. This is important so I don't break it in a
10
- future version unintentionally.
11
- * Commit, do not mess with rakefile, version, or history.
12
- (if you want to have your own version, that is fine but
13
- bump version in a commit by itself I can ignore when I pull)
14
- * Send me a pull request. Bonus points for topic branches.
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.
15
4
 
16
5
  == Copyright
17
6
 
18
- Copyright (c) 2009 aroth. See LICENSE for details.
7
+ Copyright (c) 2009 Adam Roth. See LICENSE for details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -0,0 +1,11 @@
1
+ require '../lib/garmin_connectr.rb'
2
+
3
+ activity_id = 20733252
4
+
5
+ gc = GarminConnectr.new
6
+ activity = gc.load( activity_id )
7
+
8
+ puts activity.name
9
+ puts " Activity : #{ activity.activity }"
10
+ puts " Distance : #{ activity.distance }"
11
+ puts " Start : #{ activity.start_time }\n\n"
@@ -0,0 +1,20 @@
1
+ require '../lib/garmin_connectr.rb'
2
+
3
+ username = 'garmin_connect_username'
4
+ password = 'garmin_connect_password'
5
+
6
+ opts = {
7
+ :preload => false, ## Automatically fetch additional activity data
8
+ :limit => 10 ## Limit to last 10 activites
9
+ }
10
+
11
+ gc = GarminConnectr.new
12
+ activities = gc.activities( username, password, opts )
13
+
14
+ activities.each do |activity|
15
+ puts "#{ activity.name } (#{ activity.activity_id })"
16
+ activity.load!
17
+ puts " Activity : #{ activity.activity }"
18
+ puts " Distance : #{ activity.distance }"
19
+ puts " Start : #{ activity.start_time }\n\n"
20
+ end
@@ -1,65 +1,101 @@
1
1
  require 'rubygems'
2
2
  require 'nokogiri'
3
3
  require 'open-uri'
4
+ require 'mechanize'
4
5
 
5
6
  class GarminConnectr
6
7
 
7
- attr_reader :name, :url, :device
8
- attr_reader :start_time, :start_time_str, :activity, :event, :time, :distance, :calories
8
+ attr_reader :activity_list
9
9
 
10
- def initialize( id )
11
- @id = id
12
- self.fetch
10
+ def initialize
11
+ @activity_list = []
13
12
  end
14
13
 
15
- def fetch
16
- @doc = Nokogiri::HTML(open("http://connect.garmin.com/activity/#{ @id }"))
14
+ ## Load a specific Garmin Connect activity. See GarminConnectActivity rdoc for more information.
15
+ def load( activity_id )
16
+ activity = GarminConnectActivity.new( activity_id )
17
+ activity.load!
18
+ end
19
+
20
+ ## Returns an array of GarminActivity objects.
21
+ ##
22
+ ## Options:
23
+ ## :preload [true/false] - Automatically fetch additional activity data for each activity returned (slower)
24
+ ## :limit - Limit the number of activites returned (default: 50)
25
+ def activities( username, password, opts={} )
26
+ @activity_list = []
27
+ limit = opts[:limit] || 50
17
28
 
18
- ## Name & URL
19
- @name = @doc.search('#activityName').inner_html
20
- @url = "http://connect.garmin.com/activity/#{ @id }"
21
- @device = @doc.search('.additionalInfoContent span').inner_html.gsub('Device: ','')
29
+ agent = WWW::Mechanize.new { |agent| agent.user_agent_alias = 'Mac Safari' }
30
+ page = agent.get('http://connect.garmin.com/signin')
31
+ form = page.form('login')
32
+ form.send('login:loginUsernameField', username)
33
+ form.send('login:password', password)
34
+ form.submit
22
35
 
23
- ## Start
24
- @start_time_str = @doc.search('#activityStartDate').children[0].to_s.gsub(/[\n]+/,'')
25
- @start_time = DateTime.parse( @start_time_str )
36
+ page = agent.get('http://connect.garmin.com/activities')
26
37
 
27
- ## Summary Fields
28
- @activity = @doc.search('#activityTypeValue').inner_html.gsub(/[\n]+/,'')
29
- @event = @doc.search('#eventTypeValue').inner_html.gsub(/[\n]+/,'')
30
- @time = @doc.css('#summaryTotalTime')[0].parent.children.search('.summaryField').inner_html
31
- @distance = @doc.css('#summaryDistance')[0].parent.children.search('.summaryField').inner_html
32
- @calories = @doc.css('#summaryCalories')[0].parent.children.search('.summaryField').inner_html
33
-
34
- ## Tabbed Fields
35
- fields = []
36
- fields << ['Avg Speed', 'Max Speed', 'Elevation Gain', 'Elevation Loss', 'Min Elevation', 'Max Elevation']
37
- fields << ['Avg HR', 'Max HR', 'Avg Bike Cadence', 'Max Bike Cadence', 'Avg Temperature', 'Min Temperature']
38
- fields << ['Max Temperature', 'Avg Pace', 'Best Pace']
39
- fields.flatten!
40
-
41
- fields.each do |field|
42
- name = field.downcase.gsub(' ','_')
43
- (class << self; self; end).class_eval do
44
- define_method name do
45
- self.send :tab_data, field
46
- end
47
- end
38
+ doc = Nokogiri::HTML( page.body )
39
+ activities = doc.search('.activityNameLink')
40
+ activities[0, limit].each do |act|
41
+ name = act.search('span').inner_html
42
+ act[:href].match(/\/([\d]+)$/)
43
+ aid = $1
44
+
45
+ activity = GarminConnectActivity.new( aid, name )
46
+ activity.load! if opts[:preload]
47
+ @activity_list << activity
48
48
  end
49
-
49
+ @activity_list
50
50
  end
51
51
 
52
- private
52
+ end
53
+
54
+ class GarminConnectActivity
55
+
56
+ attr_reader :activity_id, :loaded, :name, :url, :device, :start_time, :activity, :event, :time, :distance, :calories
57
+ attr_reader :avg_speed, :max_speed, :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
58
+
59
+ FIELDS = ['Avg Speed', 'Max Speed', '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']
53
60
 
54
- def tab_data( field_label )
55
- field_label += ":" unless field_label.match(/:$/)
56
- @doc.css('.label').to_a.delete_if { |e| e.inner_html != field_label }.first.parent.children.search('.field').inner_html rescue nil
61
+ def initialize( activity_id, name=nil )
62
+ @activity_id = activity_id
63
+ @name = name unless name.nil?
64
+ @loaded = false
65
+ @fields = ['name', 'url', 'device', 'start_time']
57
66
  end
58
67
 
59
- def create_method( name, value )
60
- class << self
61
- self.send( :define_method, name ){ "a" }
68
+ ## Fetch activity details. This will happen automatically if using GarminConnect#load. You will have
69
+ ## call load! explicity on the activities returned by GarminConnect#activities unless the :preload option is set to true.
70
+ def load!
71
+ @doc = Nokogiri::HTML(open("http://connect.garmin.com/activity/#{ @activity_id }"))
72
+ @name = @doc.search('#activityName').inner_html
73
+ @url = "http://connect.garmin.com/activity/#{ @activity_id }"
74
+ @device = @doc.search('.additionalInfoContent span').inner_html.gsub('Device: ','')
75
+ @start_time = @doc.search('#activityStartDate').children[0].to_s.gsub(/[\n]+/,'')
76
+ @loaded = true
77
+
78
+ # Summary Fields (TODO: clean up)
79
+ @activity = @doc.search('#activityTypeValue').inner_html.gsub(/[\n]+/,'').strip rescue nil
80
+ @event = @doc.search('#eventTypeValue').inner_html.gsub(/[\n]+/,'').strip rescue nil
81
+ @time = @doc.css('#summaryTotalTime')[0].parent.children.search('.summaryField').inner_html.strip rescue nil
82
+ @distance = @doc.css('#summaryDistance')[0].parent.children.search('.summaryField').inner_html.strip rescue nil
83
+ @calories = @doc.css('#summaryCalories')[0].parent.children.search('.summaryField').inner_html.strip rescue nil
84
+
85
+ # Tabbed Fields
86
+ FIELDS.each do |field|
87
+ name = field.downcase.gsub(' ','_')
88
+ self.instance_variable_set("@#{ name }", self.send( name ) )
62
89
  end
90
+
91
+ self
63
92
  end
93
+
94
+ private
64
95
 
96
+ def tab_data( field_label )
97
+ field_label += ":" unless field_label.match(/:$/)
98
+ @doc.css('.label').to_a.delete_if { |e| e.inner_html != field_label }.first.parent.children.search('.field').inner_html.strip rescue nil
99
+ end
100
+
65
101
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: garmin_connectr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - aroth
@@ -61,3 +61,5 @@ specification_version: 3
61
61
  summary: Simple ruby lib to fetch data from Garmin Connect
62
62
  test_files:
63
63
  - test/garmin_connectr_test.rb
64
+ - examples/activity.rb
65
+ - examples/activity_list.rb