File Coverage

blib/lib/WWW/OPG.pm
Criterion Covered Total %
statement 32 54 59.2
branch 10 28 35.7
condition 0 3 0.0
subroutine 9 9 100.0
pod 4 4 100.0
total 55 98 56.1


line stmt bran cond sub pod time code
1             # WWW::OPG
2             # Perl interface to Ontario Power Generation's site
3             #
4             # $Id: OPG.pm 11016 2010-01-16 06:11:43Z FREQUENCY@cpan.org $
5              
6             package WWW::OPG;
7              
8 4     4   103470 use strict;
  4         10  
  4         135  
9 4     4   20 use warnings;
  4         8  
  4         98  
10 4     4   23 use Carp ();
  4         6  
  4         67  
11              
12 4     4   18707 use LWP::UserAgent;
  4         326009  
  4         160  
13 4     4   9074 use DateTime;
  4         1016267  
  4         3558  
14              
15             =head1 NAME
16              
17             WWW::OPG - Perl interface to Ontario Power Generation's site
18              
19             =head1 VERSION
20              
21             Version 1.005 ($Id: OPG.pm 11016 2010-01-16 06:11:43Z FREQUENCY@cpan.org $)
22              
23             =cut
24              
25             our $VERSION = '1.005';
26             $VERSION = eval $VERSION;
27              
28             =head1 SYNOPSIS
29              
30             use WWW::OPG;
31              
32             my $opg = WWW::OPG->new();
33             eval {
34             $opg->poll();
35             };
36             print "Currently generating ", $opg->power, "MW of electricity\n";
37              
38             =head1 DESCRIPTION
39              
40             This module provides a Perl interface to information published on Ontario
41             Power Generation's web site at L. This module provides
42             very quick and low-bandwidth queries using the special machine-readable file
43             proffered by OPG; see L.
44              
45             =head1 COMPATIBILITY
46              
47             This module was tested under Perl 5.10.1, using Debian Linux. However, because
48             it's Pure Perl and doesn't do anything too obscure, it should be compatible
49             with any version of Perl that supports its prerequisite modules.
50              
51             If you encounter any problems on a different version or architecture, please
52             contact the maintainer.
53              
54             =head1 METHODS
55              
56             =head2 new
57              
58             WWW::OPG->new( \%params )
59              
60             Initialize a C object, setting up the user agent and preparing
61             for a transaction. Note that you can pass a L object or a
62             subclass thereof, which can include your proxy or UserAgent settings.
63              
64             Example code:
65              
66             my $opg = WWW::OPG->new();
67             # or, with some parameters:
68             my $opg = WWW::OPG->new({
69             useragent => LWP::UserAgent->new()
70             });
71              
72             This method will return an appropriate B object or throw an
73             exception on error.
74              
75             =cut
76              
77             sub new {
78 3     3 1 1544 my ($class, $params) = @_;
79              
80 3 100       220 Carp::croak('You must call this as a class method') if ref($class);
81              
82 2         8 my $self = {
83             };
84              
85 2 50       11 if (exists $params->{useragent}) {
86 0         0 $self->{useragent} = $params->{useragent};
87             }
88             else {
89 2         28 my $ua = LWP::UserAgent->new;
90 2         23636 $ua->agent(__PACKAGE__ . '/' . $VERSION . ' ' . $ua->_agent);
91 2         216 $self->{useragent} = $ua;
92             }
93              
94 2         11 bless($self, $class);
95 2         14 return $self;
96             }
97              
98             =head2 poll
99              
100             $opg->poll()
101              
102             Update data in the C object, C<$obj>, by connecting to the OPG
103             site and scraping data. The data can then be extracted using the other
104             methods available in this class.
105              
106             Example code:
107              
108             $opg->poll();
109              
110             This method will return a true value if an update has been performed, a
111             false value if the data is unchanged since the last update, or throw an
112             exception on error.
113              
114             =cut
115              
116             sub poll {
117 1     1 1 468 my ($self) = @_;
118              
119 1 50       125 Carp::croak('You must call this method as an object') unless ref($self);
120              
121 0         0 my $ua = $self->{useragent};
122 0         0 my $r = $ua->get('http://www.opg.com/megafile.txt');
123              
124 0 0       0 Carp::croak('Error reading response: ' . $r->status_line)
125             unless $r->is_success;
126              
127 0         0 my ($power, $date) = split(chr(13) . chr(10), $r->content);
128              
129 0 0       0 if ($power =~ m{^\s*([0-9]+),?([0-9]+)$})
130             {
131 0         0 $self->{power} = $1 . $2;
132              
133 0 0       0 if ($date =~ m{^(\d+)/(\d+)/(\d+) (\d+):(\d+):(\d+) (AM|PM)})
134             {
135 0         0 my $hour = $4;
136             # 12:00 noon and midnight are a special case
137 0 0       0 if ($hour == 12) {
    0          
138             # 12am is midnight
139 0 0       0 if ($7 eq 'AM') {
140 0         0 $hour = 0;
141             }
142             }
143             elsif ($7 eq 'PM') {
144 0         0 $hour += 12;
145             }
146              
147 0         0 my $dt = DateTime->new(
148             month => $1,
149             day => $2,
150             year => $3,
151             hour => $hour, # derived from $4
152             minute => $5,
153             second => $6,
154             time_zone => 'America/Toronto',
155             );
156              
157 0 0 0     0 if (!exists $self->{updated} || $self->{updated} != $dt)
158             {
159 0         0 $self->{updated} = $dt;
160 0         0 return 1;
161             }
162 0         0 return 0;
163             }
164             }
165              
166 0         0 die 'Error parsing response, perhaps the format has changed?';
167 0         0 return;
168             }
169              
170             =head2 power
171              
172             $opg->power()
173              
174             Returns the amount of power being generated by Ontario Power Generation
175             (OPG) plants, in MegaWatts (MW).
176              
177             Example code:
178              
179             $opg->poll();
180             print "Currently generating ", $opg->power, " MW for Ontario\n";
181              
182             Note that this value may be undefined if the server has not yet been polled,
183             or if there was a failure polling.
184              
185             =cut
186              
187             sub power {
188 2     2 1 1634 my ($self) = @_;
189              
190 2 100       128 Carp::croak('You must call this method as an object') unless ref($self);
191              
192 1 50       19 return unless exists $self->{power};
193 0         0 return $self->{power};
194             }
195              
196             =head2 last_updated
197              
198             $opg->last_updated()
199              
200             Returns the date and time that the data was last updated (as defined by the
201             remote OPG web server), given as a L object.
202              
203             Example code:
204              
205             $opg->poll();
206             print "Last updated ", $opg->last_updated, "\n";
207              
208             =cut
209              
210             sub last_updated {
211 2     2 1 302 my ($self) = @_;
212              
213 2 100       118 Carp::croak('You must call this method as an object') unless ref($self);
214              
215 1 50       9 return unless exists $self->{updated};
216 0           return $self->{updated};
217             }
218              
219             =head1 AUTHOR
220              
221             Jonathan Yu Ejawnsy@cpan.orgE
222              
223             =head2 CONTRIBUTORS
224              
225             Your name here ;-)
226              
227             =head1 ACKNOWLEDGEMENTS
228              
229             =over
230              
231             =item *
232              
233             Thanks to the kind folks at OPG and in particular someone I know only as
234             "Rose" Ewebmaster@opg.comE for providing me with an API in the form
235             of a small text file which provides the same data as that scraped from the
236             web page itself. This cuts down significantly on bandwidth costs and the
237             time it takes to check the data.
238              
239             =back
240              
241             =head1 SUPPORT
242              
243             You can find documentation for this module with the perldoc command.
244              
245             perldoc WWW::OPG
246              
247             You can also look for information at:
248              
249             =over
250              
251             =item * AnnoCPAN: Annotated CPAN documentation
252              
253             L
254              
255             =item * CPAN Ratings
256              
257             L
258              
259             =item * Search CPAN
260              
261             L
262              
263             =item * CPAN Request Tracker
264              
265             L
266              
267             =item * CPAN Testing Service (Kwalitee Tests)
268              
269             L
270              
271             =item * CPAN Testers Platform Compatibility Matrix
272              
273             L
274              
275             =back
276              
277             =head1 REPOSITORY
278              
279             You can access the most recent development version of this module at:
280              
281             L
282              
283             If you are a CPAN developer and would like to make modifications to the code
284             base, please contact Adam Kennedy Eadamk@cpan.orgE, the repository
285             administrator. I only ask that you contact me first to discuss the changes you
286             wish to make to the distribution.
287              
288             =head1 FEEDBACK
289              
290             Please send relevant comments, rotten tomatoes and suggestions directly to the
291             maintainer noted above.
292              
293             If you have a bug report or feature request, please file them on the CPAN
294             Request Tracker at L. If you are able to submit your bug
295             report in the form of failing unit tests, you are B encouraged to do
296             so.
297              
298             =head1 SEE ALSO
299              
300             L, the Ontario Power Generation web site.
301              
302             =head1 CAVEATS
303              
304             =head2 KNOWN BUGS
305              
306             There are no known bugs as of this release.
307              
308             =head2 LIMITATIONS
309              
310             =over
311              
312             =item *
313              
314             The only data currently easily available from the Ontario Power Generation
315             web site is the data for power currently being generated for the province
316             of Ontario, in MegaWatts (MW). This data seems to be updated every five
317             minutes.
318              
319             =back
320              
321             =head1 QUALITY ASSURANCE METRICS
322              
323             =head2 TEST COVERAGE
324              
325             File stmt bran cond sub pod total
326             ----------------------- ------ ------ ------ ------ ------ ------
327             lib/WWW/OPG.pm 92.9 71.4 66.7 100.0 100.0 87.1
328              
329             =head1 LICENSE
330              
331             In a perfect world, I could just say that this package and all of the code
332             it contains is Public Domain. It's a bit more complicated than that; you'll
333             have to read the included F file to get the full details.
334              
335             =head1 DISCLAIMER OF WARRANTY
336              
337             The software is provided "AS IS", without warranty of any kind, express or
338             implied, including but not limited to the warranties of merchantability,
339             fitness for a particular purpose and noninfringement. In no event shall the
340             authors or copyright holders be liable for any claim, damages or other
341             liability, whether in an action of contract, tort or otherwise, arising from,
342             out of or in connection with the software or the use or other dealings in
343             the software.
344              
345             =cut
346              
347             1;