File Coverage

blib/lib/GPS/Garmin/Connect.pm
Criterion Covered Total %
statement 18 56 32.1
branch 0 8 0.0
condition n/a
subroutine 6 9 66.6
pod 3 3 100.0
total 27 76 35.5


line stmt bran cond sub pod time code
1             package GPS::Garmin::Connect;
2              
3 1     1   65783 use warnings;
  1         3  
  1         39  
4 1     1   6 use strict;
  1         2  
  1         36  
5              
6              
7 1     1   27269 use LWP::UserAgent;
  1         150618  
  1         39  
8 1     1   1312 use HTML::Form;
  1         50987  
  1         50  
9 1     1   1786 use JSON;
  1         39266  
  1         6  
10 1     1   1139 use Error;
  1         13085  
  1         7  
11              
12              
13             =head1 NAME
14              
15             GPS::Garmin::Connect - Allows simple fetching of
16             activities from http://connect.garmin.com
17              
18             =head1 VERSION
19              
20             Version 0.01
21              
22             =cut
23              
24             our $VERSION = '0.01';
25              
26              
27             =head1 SYNOPSIS
28              
29             This module is a simple helper to fetch and parse activities
30             from http://connect.garmin.com
31              
32              
33              
34             use GPS::Garmin::Connect;
35              
36             my $connect = GPS::Garmin::Connect->new();
37             my $json = $connect->fetchdata( $username, $password );
38              
39             my $activities = $connect->parse( $json );
40              
41             foreach my $activity (@$activities) {
42             print "My activity $activity->{activity} - HR: $activity->{heartrate}\n";
43             }
44              
45              
46             =head1 FUNCTIONS
47              
48             =head2 new
49              
50             =cut
51              
52             sub new {
53 0     0 1   my $self = shift;
54 0           return bless {
55             _loginurl => 'http://connect.garmin.com/signin',
56             }, $self;
57             }
58              
59             =head2 fetchdata
60              
61             $connect->fetchdata( $username, $password );
62              
63             Logins into connect.garmin.com and fetches all activities and returns
64             a JSON string which can be parsed using L.
65              
66             =cut
67              
68             sub fetchdata {
69 0     0 1   my ($pkg, $username, $password) = @_;
70 0           my $loginurl = $pkg->{_loginurl};
71 0           my $ua = LWP::UserAgent->new();
72 0           $ua->cookie_jar( { } );
73 0           push @{ $ua->requests_redirectable }, 'POST';
  0            
74              
75              
76              
77             # Fetch login form to get a session id ..
78 0           my $loginformreq = HTTP::Request->new(GET => $loginurl);
79 0           my $loginformres = $ua->request($loginformreq);
80              
81 0 0         throw Error::Simple('Error while requesting login form: ' . $loginformres->status_line)
82             unless $loginformres->is_success;
83            
84 0           my $loginform = HTML::Form->parse($loginformres->content, $loginurl);
85 0           $loginform->value( 'login:loginUsernameField' => $username );
86 0           $loginform->value( 'login:password' => $password );
87            
88             # Send login request ..
89 0           my $loginres = $ua->request($loginform->click);
90            
91 0 0         if ($loginres->is_success) {
92             # we successfully logged in (probably)
93             } else {
94 0           throw Error::Simple("Error while trying to log in: ".$loginres->status_line);
95             }
96              
97             # We can now retrieve our activity ...
98 0           my $req = HTTP::Request->new(GET => 'http://connect.garmin.com/proxy/activity-search-service-1.0/json/activities?_dc=1220170621856&start=0&limit=50');
99              
100 0           my $res = $ua->request($req);
101              
102 0 0         if ($res->is_success) {
103 0           return $res->content;
104             } else {
105 0           throw Error::Simple("error while requesting activities (".$res->status_line.")");
106             }
107             }
108              
109             =head2 parse
110              
111             method responsible for parsing the json data and returning a simplified array ref of hash refs:
112              
113             $VAR1 = [
114             {
115             'begindate' => '2009-02-17',
116             'distance' => 3156,
117             'name' => 'Untitled',
118             'heartrate' => 162,
119             'duration' => 1980,
120             'activity' => 'Untitled',
121             'activityid' => '2194739',
122             'id' => '2194739',
123             'type' => 'Uncategorized',
124             'begin' => 'Tue, Feb 17 \'09 08:27 AM'
125             },
126             {
127             'begindate' => '2009-02-17',
128             'distance' => 2200,
129             'name' => 'Untitled',
130             'heartrate' => 157,
131             'duration' => 1500,
132             'activity' => 'Untitled',
133             'activityid' => '2194738',
134             'id' => '2194738',
135             'type' => 'Uncategorized',
136             'begin' => 'Tue, Feb 17 \'09 08:02 AM'
137             },
138              
139              
140             =cut
141              
142             sub parse {
143 0     0 1   my ($pkg, $content) = @_;
144 0           my $json = JSON->new();
145              
146 0           my $results = $json->decode($content);
147              
148              
149 0           my $activities = $results->{results}->{activities};
150              
151              
152 0           my $simpleactivities = [];
153 0           foreach my $activity (@$activities) {
154 0           my $a = $activity->{activity};
155             # convert it to something more "userfriendly"
156 0           my $hr = undef;
157 0 0         if ($a->{weightedMeanHeartRate}) {
158 0           $hr = int($a->{weightedMeanHeartRate}->{value});
159             }
160 0           my $durstr = $a->{sumDuration}->{display};
161 0           my ($hrs, $min, $sec) = split(/:/,$durstr);
162 0           my $duration = (($hrs * 60) + $min) * 60 + $sec;
163 0           my $ac = { 'id' => $a->{activityId},
164             'activityid' => $a->{activityId},
165             'activity' => $a->{activityName}->{value},
166             'name' => $a->{activityName}->{value},
167             'type' => $a->{activityType}->{display},
168             'distance' => int($a->{sumDistance}->{value}*1000),#sprintf("%.2f",$a->{sumDistance}->{value}),
169             'duration' => $duration,
170             'begin' => $a->{beginTimestamp}->{display},
171             'begindate' => $a->{beginTimestamp}->{value},
172             'heartrate' => $hr,
173             };
174            
175 0           push(@$simpleactivities, $ac);
176             }
177 0           return $simpleactivities;
178             }
179              
180              
181              
182             =head1 AUTHOR
183              
184             Herbert Poul, C<< >>
185              
186             =head1 BUGS
187              
188             Please report any bugs or feature requests to C, or through
189             the web interface at L. I will be notified, and then you'll
190             automatically be notified of progress on your bug as I make changes.
191              
192              
193              
194              
195             =head1 SUPPORT
196              
197             You can find documentation for this module with the perldoc command.
198              
199             perldoc GPS::Garmin::Connect
200              
201              
202             You can also look for information at:
203              
204             =over 4
205              
206             =item * RT: CPAN's request tracker
207              
208             L
209              
210             =item * AnnoCPAN: Annotated CPAN documentation
211              
212             L
213              
214             =item * CPAN Ratings
215              
216             L
217              
218             =item * Search CPAN
219              
220             L
221              
222             =back
223              
224              
225             =head1 ACKNOWLEDGEMENTS
226              
227              
228             =head1 COPYRIGHT & LICENSE
229              
230             Copyright 2009 Herbert Poul, all rights reserved.
231              
232             This program is free software; you can redistribute it and/or modify it
233             under the same terms as Perl itself.
234              
235              
236             =cut
237              
238             1; # End of GPS::Garmin::Connect