File Coverage

blib/lib/Device/Neurio.pm
Criterion Covered Total %
statement 46 307 14.9
branch 1 142 0.7
condition 0 33 0.0
subroutine 16 33 48.4
pod 1 16 6.2
total 64 531 12.0


line stmt bran cond sub pod time code
1             package Device::Neurio;
2              
3 1     1   606 use warnings;
  1         1  
  1         52  
4 1     1   4 use strict;
  1         1  
  1         25  
5 1     1   14 use 5.006_001;
  1         11  
  1         99  
6              
7             require Exporter;
8              
9             our @ISA = qw(Exporter);
10              
11             # Items to export into callers namespace by default. Note: do not export
12             # names by default without a very good reason. Use EXPORT_OK instead.
13             # Do not simply export all your public functions/methods/constants.
14              
15             # This allows declaration use Device::NeurioTools ':all';
16             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
17             # will save memory.
18              
19             our %EXPORT_TAGS = ( 'all' => [ qw(
20             new connect fetch_Samples_Recent_Live fetch_Samples_Last_Live fetch_Samples
21             fetch_Samples_Full fetch_Stats_Energy fetch_Appliances fetch_Appliances_Events_by_Appliance
22             fetch_Appliances_Events_by_Location fetch_Appliances_Specific fetch_Appliances_Stats
23             get_last_code get_last_exec_time get_last_reason
24             ) ] );
25              
26             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
27             our @EXPORT = qw( $EXPORT_TAGS{'all'});
28              
29             BEGIN
30             {
31 1 50   1   3019 if ($^O eq "MSWin32"){
32 1     1   755 use LWP::UserAgent;
  1         44365  
  1         33  
33 1     1   8 use Time::Local;
  1         1  
  1         76  
34 1     1   4 use JSON qw(decode_json encode_json);
  1         2  
  1         9  
35 1     1   765 use MIME::Base64 (qw(encode_base64));
  1         583  
  1         58  
36 1     1   490 use Time::HiRes qw/gettimeofday/;
  1         1220  
  1         4  
37 1     1   2268 use Data::Dumper;
  1         6235  
  1         87  
38             } else {
39 1     1   10 use LWP::UserAgent;
  1         2  
  1         66  
40 1     1   6 use Time::Local;
  1         1  
  1         53  
41 1     1   5 use JSON qw(decode_json encode_json);
  1         1  
  1         8  
42 1     1   166 use MIME::Base64 (qw(encode_base64));
  1         2  
  1         43  
43 1     1   3 use Time::HiRes qw/gettimeofday/;
  1         2  
  1         6  
44 1     1   80 use Data::Dumper;
  1         1  
  1         30  
45             }
46             }
47              
48              
49             =head1 NAME
50              
51             Device::Neurio - Methods for wrapping the Neurio API calls so that they are
52             accessible via Perl
53              
54             =head1 VERSION
55              
56             Version 0.15
57              
58             =cut
59              
60             our $VERSION = '0.15';
61              
62             #******************************************************************************
63             =head1 SYNOPSIS
64              
65             This module provides a Perl interface to a Neurio sensor via the following
66             methods:
67             - new
68             - connect
69             - fetch_Samples
70             - fetch_Samples_Full
71             - fetch_Samples_Last_Live
72             - fetch_Samples_Recent_Live
73             - fetch_Stats_Energy
74             - fetch_Appliances
75             - fetch_Appliances_Events
76             - fetch_Appliances_Specific
77             - fetch_Appliances_Stats
78              
79             Please note that in order to use the 'Samples' methods in this module you will
80             require three parameters (key, secret, sensor_id) as well as an Energy Aware
81             Neurio sensor installed in your house. In order to use the 'Appliances'
82             methods, you will also require another parameter (location_id). This information
83             can be obtained from the Neurio developpers website.
84              
85             The module is written entirely in Perl and was developped on Raspbian Linux.
86              
87             All date/time values are specified using ISO8601 format (yyyy-mm-ddThh:mm:ssZ)
88              
89             =head1 SAMPLE CODE
90              
91             use Device::Neurio;
92              
93             $my_Neurio = Device::Neurio->new($key,$secret,$sensor_id,$debug);
94              
95             $my_Neurio->connect();
96            
97             $data = $my_Neurio->fetch_Samples_Last_Live();
98             print $data->{'consumptionPower'}
99              
100             $data = $my_Neurio->fetch_Samples_Recent_Live("2014-06-18T19:20:21Z");
101             print $data->[0]->{'consumptionPower'}
102              
103             undef $my_Neurio;
104              
105              
106             =head2 EXPORT
107              
108             All by default.
109              
110              
111             =head1 SUBROUTINES/METHODS
112              
113             =head2 new - the constructor for a Neurio object
114              
115             Creates a new instance which will be able to fetch data from a unique Neurio
116             sensor. All three parameters are required and can be obtained from the
117             Neurio developpers website.
118              
119             my $Neurio = Device::Neurio->new($key, $secret, $sensor_id, $debug);
120              
121             This method accepts the following parameters:
122             - $key : unique key for the account - Required
123             - $secret : secret key for the account - Required
124             - $sensor_id : sensor ID connected to the account - Required
125             - $debug : turn on debug messages - Optional
126              
127             Returns a Neurio object if successful.
128             Returns 0 on failure
129            
130             =cut
131              
132             sub new {
133 0     0 1   my $class = shift;
134 0           my $self;
135            
136 0           $self->{'ua'} = LWP::UserAgent->new();
137 0           $self->{'key'} = shift;
138 0           $self->{'secret'} = shift;
139 0           $self->{'sensor_id'} = shift;
140 0           $self->{'debug'} = shift;
141 0           $self->{'base64'} = encode_base64($self->{'key'}.":".$self->{'secret'});
142 0           chomp($self->{'base64'});
143            
144 0 0         if (!defined $self->{'debug'}) {
145 0           $self->{'debug'} = 0;
146             }
147            
148 0 0 0       if ((!defined $self->{'key'}) || (!defined $self->{'secret'}) || (!defined $self->{'sensor_id'})) {
      0        
149 0 0         print "\nNeurio->new(): Key, Secret and Sensor_ID are REQUIRED parameters\n" if ($self->{'debug'});
150 0           $self->{'last_code'} = '0';
151 0           $self->{'last_reason'} = 'Neurio->new(): Key, Secret and Sensor_ID are REQUIRED parameters';
152 0           return 0;
153             }
154            
155             # $self->{'base_url'} = "https://api-staging.neur.io/v1";
156 0           $self->{'base_url'} = "https://api.neur.io/v1";
157 0           $self->{'Samples_Recent_Live_url'} = $self->{'base_url'}."/samples/live?sensorId=".$self->{'sensor_id'};
158 0           $self->{'Samples_Last_Live_url'} = $self->{'base_url'}."/samples/live/last?sensorId=".$self->{'sensor_id'};
159 0           $self->{'Samples_url'} = $self->{'base_url'}."/samples?sensorId=".$self->{'sensor_id'};
160 0           $self->{'Samples_Full_url'} = $self->{'base_url'}."/samples/full?sensorId=".$self->{'sensor_id'};
161 0           $self->{'Stats_Energy_url'} = $self->{'base_url'}."/samples/stats?sensorId=".$self->{'sensor_id'};
162 0           $self->{'Appliances_url'} = $self->{'base_url'}."/appliances";
163 0           $self->{'Appliances_Specific_url'} = $self->{'base_url'}."/appliances/";
164 0           $self->{'Appliances_Stats_url'} = $self->{'base_url'}."/appliances/stats";
165 0           $self->{'Appliances_Events_url'} = $self->{'base_url'}."/appliances/events";
166 0           $self->{'last_code'} = '';
167 0           $self->{'last_reason'} = '';
168 0           $self->{'last_exec_time'} = 0;
169            
170 0           bless $self, $class;
171            
172 0           return $self;
173             }
174              
175              
176             #******************************************************************************
177             =head2 connect - open a secure connection to the Neurio server
178              
179             Opens a secure connection via HTTPS to the Neurio server which provides
180             access to a set of API commands to access the sensor data.
181            
182             An optional location ID can be given. This is only required if calls
183             will be made to the 'Appliance' methods. Calls to the 'Samples'
184             methods do not require that a location ID be set. If a location_id is not
185             specified at connection, then it must be specified when using the 'Appliance'
186             methods.
187            
188             A location ID can be acquired from the Neurio developpers web site
189              
190             $Neurio->connect($location_id);
191            
192             This method accepts the following parameter:
193             - $location_id : unique location id - Optional
194            
195             Returns 1 on success
196             Returns 0 on failure
197            
198             =cut
199              
200             sub connect {
201 0     0 0   my ($self,$location_id) = @_;
202 0           my $access_token = '';
203            
204 0 0         if (defined $location_id) {
205 0           $self->{'location_id'} = $location_id;
206             } else {
207 0           $self->{'location_id'} = '';
208             }
209              
210             # Submit request for authentiaction token.
211 0           my $response = $self->{'ua'}->post('https://api-staging.neur.io/v1/oauth2/token',
212             { basic_authentication => $self->{'base64'},
213             Content_Type => 'application/x-www-form-urlencoded',
214             grant_type => 'client_credentials',
215             client_id => $self->{'key'},
216             client_secret => $self->{'secret'},
217             }
218             );
219            
220 0 0         if($response->is_success) {
221 0           my $return = $response->content;
222 0           $return =~ /\"access_token\":\"(.*)\"\,\"token_type\"/;
223 0           $self->{'access_token'} = $1;
224 0           return 1;
225             } else {
226 0 0         print "\nDevice::Neurio->connect(): Failed to connect.\n" if ($self->{'debug'});
227 0 0         print $response->content."\n\n" if ($self->{'debug'});
228 0           $self->{'last_code'} = '0';
229 0           $self->{'last_reason'} = 'Neurio->new(): Device::Neurio->connect(): Failed to connect';
230 0           return 0;
231             }
232             }
233              
234              
235             #******************************************************************************
236             =head2 fetch_Samples_Recent_Live - Fetch recent sensor samples
237              
238             Retrieves recent sensor readings from the Neurio server.
239             The values represent the sum of all phases.
240              
241             $Neurio->fetch_Samples_Recent_Live($last);
242            
243             This method accepts the following parameters:
244             $last - time of last sample received specified using ISO8601
245             format (yyyy-mm-ddThh:mm:ssZ) - Optional
246            
247             If no value is specified for $last, a default of 2 minutes is used.
248            
249             Returns an array of Perl data structures on success
250             $VAR1 = [
251             {
252             'generationEnergy' => 3716166644,
253             'timestamp' => '2014-06-24T11:08:00.000Z',
254             'consumptionEnergy' => 6762651207,
255             'generationPower' => 564,
256             'consumptionPower' => 821
257             },
258             ...
259             ]
260             Returns 0 on failure
261            
262             =cut
263              
264             sub fetch_Samples_Recent_Live {
265 0     0 0   my ($self,$last) = @_;
266 0           my $url;
267              
268             # if optional parameter is defined, add it
269 0 0         if (defined $last) {
270 0           $url = $self->{'Samples_Recent_Live_url'}."&last=$last";
271             } else {
272 0           $url = $self->{'Samples_Recent_Live_url'};
273             }
274 0           return $self->__process_get($url);
275             }
276              
277              
278             #******************************************************************************
279             =head2 fetch_Samples_Last_Live - Fetch the last live sensor sample
280              
281             Retrieves the last live sensor reading from the Neurio server.
282             The values represent the sum of all phases.
283              
284             $Neurio->fetch_Samples_Last_Live();
285              
286             This method accepts no parameters
287            
288             Returns a Perl data structure on success:
289             $VAR1 = {
290             'generationEnergy' => 3716027450,
291             'timestamp' => '2014-06-24T11:03:43.000Z',
292             'consumptionEnergy' => 6762445671,
293             'generationPower' => 542,
294             'consumptionPower' => 800
295             };
296             Returns 0 on failure
297            
298             =cut
299              
300             sub fetch_Samples_Last_Live {
301 0     0 0   my $self = shift;
302 0           my $url = $self->{'Samples_Last_Live_url'};
303 0           return $self->__process_get($url);
304             }
305              
306              
307             #******************************************************************************
308             =head2 fetch_Samples - Fetch sensor samples from the Neurio server
309              
310             Retrieves sensor readings within the parameters specified.
311             The values represent the sum of all phases.
312              
313             $Neurio->fetch_Samples($start,$granularity,$end,$frequency,$perPage,$page);
314              
315             This method accepts the following parameters:
316             - $start : yyyy-mm-ddThh:mm:ssZ - Required
317             specified using ISO8601 format
318             - $granularity : seconds|minutes|hours|days - Required
319             - $end : yyyy-mm-ddThh:mm:ssZ - Optional
320             specified using ISO8601 format
321             - $frequency : if the granularity is specified as 'minutes', then the
322             frequency must be a multiple of 5 - Optional
323             - $perPage : number of results per page - Optional
324             - $page : page number to return - Optional
325            
326             Returns an array of Perl data structures on success
327             $VAR1 = [
328             {
329             'generationEnergy' => 3568948578,
330             'timestamp' => '2014-06-21T19:00:00.000Z',
331             'consumptionEnergy' => 6487889194,
332             'generationPower' => 98,
333             'consumptionPower' => 240
334             },
335             ...
336             ]
337             Returns 0 on failure
338            
339             =cut
340              
341             sub fetch_Samples {
342 0     0 0   my ($self,$start,$granularity,$end,$frequency,$perPage,$page) = @_;
343            
344             # make sure $start and $granularity are defined
345 0 0 0       if ((!defined $start) || (!defined $granularity)) {
346 0 0         print "\nNeurio->fetch_Samples_Full(): \$start and \$granularity are required parameters\n\n" if ($self->{'debug'});
347 0           $self->{'last_code'} = '0';
348 0           $self->{'last_reason'} = 'Neurio->fetch_Samples_Full(): \$start and \$granularity are required parameters';
349 0           return 0;
350             }
351             # make sure that frequqncy is a multiple of 5 if $granularity is in minutes
352 0 0 0       if (($granularity eq 'minutes') and defined $frequency) {
353 0 0         if (eval($frequency%5) != 0) {
354 0 0         print "\nNeurio->fetch_Samples(): Only multiples of 5 are supported for \$frequency when \$granularity is in minutes\n\n" if ($self->{'debug'});
355 0           $self->{'last_code'} = '0';
356 0           $self->{'last_reason'} = 'Neurio->fetch_Samples(): Only multiples of 5 are supported for \$frequency when \$granularity is in minutes';
357 0           return 0;
358             }
359             }
360             # make sure $granularity is one of the correct values
361 0 0         if (!($granularity =~ /[seconds|minutes|hours|days]/)) {
362 0 0         print "\nNeurio->fetch_Samples_Full(): Only values of 'seconds, minutes, hours or days' are supported for \$granularity\n\n" if ($self->{'debug'});
363 0           $self->{'last_code'} = '0';
364 0           $self->{'last_reason'} = 'Neurio->fetch_Samples_Full(): Only values of "seconds, minutes, hours or days" are supported for \$granularity';
365 0           return 0;
366             }
367            
368 0           my $url = $self->{'Samples_url'}."&start=$start&granularity=$granularity";
369            
370             # if optional parameter is defined, add it
371 0 0         if (defined $end) {
372 0           $url = $url . "&end=$end";
373             }
374             # if optional parameter is defined, add it
375 0 0         if (defined $frequency) {
376 0           $url = $url . "&frequency=$frequency";
377             }
378             # if optional parameter is defined, add it
379 0 0         if (defined $perPage) {
380 0           $url = $url . "&perPage=$perPage";
381             }
382             # if optional parameter is defined, add it
383 0 0         if (defined $page) {
384 0           $url = $url . "&page=$page";
385             }
386            
387 0           return $self->__process_get($url);
388             }
389              
390              
391             #******************************************************************************
392             =head2 fetch_Samples_Full - Fetches full samples for all phases
393              
394             Retrieves full sensor readings including data for each individual phase within
395             the parameters specified.
396              
397             $Neurio->fetch_Samples_Full($start,$granularity,$end,$frequency,$perPage,$page);
398              
399             This method accepts the following parameters:
400             - $start : yyyy-mm-ddThh:mm:ssZ - Required
401             specified using ISO8601 format
402             - $granularity : seconds|minutes|hours|days - Required
403             - $end : yyyy-mm-ddThh:mm:ssZ - Optional
404             specified using ISO8601 format
405             - $frequency : an integer - Optional
406             - $perPage : number of results per page - Optional
407             - $page : page number to return - Optional
408            
409             Returns an array of Perl data structures on success
410             [
411             {
412             'timestamp' => '2014-06-16T19:20:21.000Z',
413             'channelSamples' => [
414             {
415             'voltage' => '123.19',
416             'power' => 129,
417             'name' => '1',
418             'energyExported' => 27,
419             'channelType' => 'phase_a',
420             'energyImported' => 2682910899,
421             'reactivePower' => 41
422             },
423             {
424             'voltage' => '123.94',
425             'power' => 199,
426             'name' => '2',
427             'energyExported' => 6,
428             'channelType' => 'phase_b',
429             'energyImported' => 3296564362,
430             'reactivePower' => -45
431             },
432             {
433             'voltage' => '123.57',
434             'power' => 327,
435             'name' => '3',
436             'energyExported' => 10,
437             'channelType' => 'consumption',
438             'energyImported' => 5979475235,
439             'reactivePower' => -4
440             }
441             ]
442             },
443             ...
444             ]
445             Returns 0 on failure
446            
447             =cut
448              
449             sub fetch_Samples_Full {
450 0     0 0   my ($self,$start,$granularity,$end,$frequency,$perPage,$page) = @_;
451            
452             # make sure $start and $granularity are defined
453 0 0 0       if ((!defined $start) || (!defined $granularity)) {
454 0 0         print "\nNeurio->fetch_Samples_Full(): \$start and \$granularity are required parameters\n\n" if ($self->{'debug'});
455 0           $self->{'last_code'} = '0';
456 0           $self->{'last_reason'} = 'Neurio->fetch_Samples_Full(): \$start and \$granularity are required parameters';
457 0           return 0;
458             }
459             # make sure $granularity is one of the correct values
460 0 0         if (!($granularity =~ /[seconds|minutes|hours|days]/)) {
461 0 0         print "\nNeurio->fetch_Samples_Full(): Found \$granularity of $granularity\nOnly values of 'seconds, minutes, hours or days' are supported for \$granularity\n\n" if ($self->{'debug'});
462 0           $self->{'last_code'} = '0';
463 0           $self->{'last_reason'} = 'Neurio->fetch_Samples_Full(): Only values of "seconds, minutes, hours or days" are supported for \$granularity';
464 0           return 0;
465             }
466            
467 0           my $url = $self->{'Samples_Full_url'}."&start=$start&granularity=$granularity";
468            
469             # if optional parameter is defined, add it
470 0 0         if (defined $end) {
471 0           $url = $url . "&end=$end";
472             }
473             # if optional parameter is defined, add it
474 0 0         if (defined $frequency) {
475 0           $url = $url . "&frequency=$frequency";
476             }
477             # if optional parameter is defined, add it
478 0 0         if (defined $perPage) {
479 0           $url = $url . "&perPage=$perPage";
480             }
481             # if optional parameter is defined, add it
482 0 0         if (defined $page) {
483 0           $url = $url . "&page=$page";
484             }
485            
486 0           return $self->__process_get($url);
487             }
488              
489              
490             #******************************************************************************
491             =head2 fetch_Stats_Energy - Fetches energy statistics
492              
493             Retrieves energy statistics within the parameters specified.
494             The values represent the sum of all phases.
495              
496             $Neurio->fetch_Stats_Energy($start,$granularity,$end,$frequency,$perPage,$page);
497              
498             This method accepts the following parameters:
499             - $start : yyyy-mm-ddThh:mm:ssZ - Required
500             specified using ISO8601 format
501             - $granularity : minutes|hours|days|months - Required
502             - $end : yyyy-mm-ddThh:mm:ssZ - Optional
503             specified using ISO8601 format
504             - $frequency : if the granularity is specified as 'minutes', then the
505             frequency must be a multiple of 5 - Optional
506             - $perPage : number of results per page - Optional
507             - $page : page number to return - Optional
508            
509             Returns a Perl data structure containing all the raw data
510             Returns 0 on failure
511            
512             =cut
513              
514             sub fetch_Stats_Energy {
515 0     0 0   my ($self,$start,$granularity,$end,$frequency,$perPage,$page) = @_;
516              
517             # make sure $start and $granularity are defined
518 0 0 0       if ((!defined $start) || (!defined $granularity)) {
519 0 0         print "\nNeurio->fetch_Stats_Energy(): \$start and \$granularity are required parameters\n\n" if ($self->{'debug'});
520 0           $self->{'last_code'} = '0';
521 0           $self->{'last_reason'} = 'Neurio->fetch_Stats_Energy(): \$start and \$granularity are required parameters';
522 0           return 0;
523             }
524             # make sure that frequqncy is a multiple of 5 if $granularity is in minutes
525 0 0 0       if (($granularity eq 'minutes') and defined $frequency) {
526 0 0         if (eval($frequency%5) != 0) {
527 0 0         print "\nNeurio->fetch_Stats_Energy(): Only multiples of 5 are supported for \$frequency when \$granularity is in minutes\n\n" if ($self->{'debug'});
528 0           $self->{'last_code'} = '0';
529 0           $self->{'last_reason'} = 'Neurio->fetch_Stats_Energy(): Only multiples of 5 are supported for \$frequency when \$granularity is in minutes';
530 0           return 0;
531             }
532             }
533             # make sure $granularity is one of the correct values
534 0 0         if (!($granularity ~~ ['minutes','hours','days','months'])) {
535 0 0         print "\nNeurio->fetch_Stats_Energy(): Only values of 'minutes, hours, days or months' are supported for \$granularity\n\n" if ($self->{'debug'});
536 0           $self->{'last_code'} = '0';
537 0           $self->{'last_reason'} = 'Neurio->fetch_Stats_Energy(): Only values of "minutes, hours, days or months" are supported for \$granularity';
538 0           return 0;
539             }
540            
541 0           my $url = $self->{'Stats_Energy_url'}."&start=$start&granularity=$granularity";
542            
543             # if optional parameter is defined, add it
544 0 0         if (defined $end) {
545 0           $url = $url . "&end=$end";
546             }
547             # if optional parameter is defined, add it
548 0 0         if (defined $frequency) {
549 0           $url = $url . "&frequency=$frequency";
550             }
551             # if optional parameter is defined, add it
552 0 0         if (defined $perPage) {
553 0           $url = $url . "&perPage=$perPage";
554             }
555             # if optional parameter is defined, add it
556 0 0         if (defined $page) {
557 0           $url = $url . "&page=$page";
558             }
559            
560 0           return $self->__process_get($url);
561             }
562              
563              
564             #******************************************************************************
565             =head2 fetch_Appliances - Fetch the appliances for a specific location
566              
567             Retrieves the appliances added for a specific location.
568            
569             The location_id is an optional parameter because it can be specified when
570             connecting. If it is specified below, then this will over-ride the location
571             ID set when connecting, but for this function call only.
572              
573             $Neurio->fetch_Appliances($location_id);
574              
575             This method accepts the following parameters:
576             - $location_id : id of a location - Optional
577            
578             Returns an array of Perl data structures on success
579             $VAR1 = [
580             {
581             'locationId' => 'xxxxxxxxxxxxxxx',
582             'name' => 'lighting_appliance',
583             'id' => 'yyyyyyyyyyyyyyyyy',
584             'label' => 'Range Light on Medium',
585             'tags' => []
586             },
587             {
588             'locationId' => 'xxxxxxxxxxxxxxx-3',
589             'name' => 'refrigerator',
590             'id' => 'zzzzzzzzzzzzzzzz',
591             'label' => '',
592             'tags' => []
593             },
594             ....
595             ]
596             Returns 0 on failure
597            
598             =cut
599              
600             sub fetch_Appliances {
601 0     0 0   my ($self,$location_id) = @_;
602            
603             # check if $location_id is defined
604 0 0         if (!defined $location_id) {
605 0 0         if (!defined $self->{'location_id'}) {
606 0 0         print "\nNeurio->fetch_Appliances(): \$location_id is a required parameter\n\n" if ($self->{'debug'});
607 0           $self->{'last_code'} = '0';
608 0           $self->{'last_reason'} = 'Neurio->fetch_Appliances(): \$location_id is a required parameters';
609 0           return 0;
610             } else {
611 0           $location_id = $self->{'location_id'};
612             }
613             }
614 0           my $url = $self->{'Appliances_url'}."?locationId=$location_id";
615              
616 0           return $self->__process_get($url);
617             }
618              
619              
620             #******************************************************************************
621             =head2 fetch_Appliances_Specific - Fetch information about a specific appliance
622              
623             Retrieves information about a specific appliance.
624            
625             The applicance_id parameter is determined by using the fetch_Appliance method
626             which returns a list of appliances with their IDs
627              
628             $Neurio->fetch_Appliances_Specific($appliance_id);
629              
630             This method accepts the following parameters:
631             - $appliance_id : id of the appliance - Required
632            
633             Returns a Perl data structure on success:
634             $VAR1 = {
635             'locationId' => 'xxxxxxxxxxxxx,
636             'name' => 'lighting_appliance',
637             'id' => 'yyyyyyyyyyyyyyy',
638             'label' => 'Range Light on Medium',
639             'tags' => []
640             };
641             Returns 0 on failure
642            
643             =cut
644              
645             sub fetch_Appliances_Specific {
646 0     0 0   my ($self,$appliance_id) = @_;
647            
648             # make sure $id is defined
649 0 0         if (!defined $appliance_id) {
650 0 0         print "\nNeurio->fetch_Appliances_Specific(): \$appliance_id is a required parameter\n\n" if ($self->{'debug'});
651 0           $self->{'last_code'} = '0';
652 0           $self->{'last_reason'} = 'Neurio->fetch_Appliances_Specific(): \$appliance_id is a required parameters';
653 0           return 0;
654             }
655              
656 0           my $url = $self->{'Appliances_Specific_url'}.$appliance_id;
657            
658 0           return $self->__process_get($url);
659             }
660              
661              
662             #******************************************************************************
663             =head2 fetch_Appliances_Stats - Fetch usage data for a given appliance
664              
665             Retrieves usage data for a specific appliance at a specific location.
666            
667             The applicance_id parameter is determined by using the fetch_Appliance method
668             which returns a list of appliances with their IDs
669              
670             $Neurio->fetch_Appliances_Stats($location_id,$appliance_id,$start,$granularity,$end,$frequency,$perPage,$page);
671              
672             This method accepts the following parameters:
673             - $location_Id : id of a location - Required
674             - $appliance_id : id of the appliance - Required
675             - $start : yyyy-mm-ddThh:mm:ssZ - Required
676             specified using ISO8601 format
677             - $granularity : seconds|minutes|hours|days - Required
678             - $end : yyyy-mm-ddThh:mm:ssZ - Required
679             specified using ISO8601 format
680             - $frequency : an integer - Required
681             - $perPage : number of results per page - Optional
682             - $page : page number to return - Optional
683            
684             Returns an array of Perl data structures on success
685             $VAR1 = [
686             {
687             'energy' => 152927,
688             'averagePower' => '110',
689             'timeOn' => 1398,
690             'guesses' => {},
691             'end' => '2014-09-05T14:00:00.000Z',
692             'lastEvent' => {
693             'energy' => 74124,
694             'averagePower' => '109',
695             'guesses' => {},
696             'end' => '2014-09-05T13:50:44.055Z',
697             'groupIds' => [
698             'aaaaaaaaaaaaaaaaa'
699             ],
700             'id' => '5EGh7o8eQJuIvsdA4qMkEw',
701             'appliance' => {
702             'locationId' => 'ccccccccccccccccc-3',
703             'name' => 'refrigerator',
704             'id' => 'bbbbbbbbbbbbbbbbb',
705             'label' => '',
706             'tags' => []
707             },
708             'start' => '2014-09-05T13:39:20.115Z'
709             },
710             'groupIds' => [
711             'aaaaaaaaaaaaaaaaa'
712             ],
713             'eventCount' => 2,
714             'usagePercentage' => '2.465231',
715             'id' => 'ddddddddddddddd',
716             'appliance' => {
717             'locationId' => 'ccccccccccccccccc-3',
718             'name' => 'refrigerator',
719             'id' => 'bbbbbbbbbbbbbbbbb',
720             'label' => '',
721             'tags' => []
722             },
723             'start' => '2014-09-05T13:00:00.000Z'
724             },
725             ......
726             ]
727             Returns 0 on failure
728            
729             =cut
730              
731             sub fetch_Appliances_Stats {
732 0     0 0   my ($self,$location_id,$appliance_id,$start,$granularity,$end,$frequency,$perPage,$page) = @_;
733            
734             # make sure $location_id is defined
735 0 0         if (!defined $location_id) {
736 0 0         print "\nNeurio->fetch_Appliances_Stats(): \$location_id is a required parameter\n\n" if ($self->{'debug'});
737 0           $self->{'last_code'} = '0';
738 0           $self->{'last_reason'} = 'Neurio->fetch_Appliances_Stats(): \$location_id is a required parameters';
739 0           return 0;
740             }
741             # make sure $appliance_id is defined
742 0 0         if (!defined $appliance_id) {
743 0 0         print "\nNeurio->fetch_Appliances_Stats(): \$appliance_id is a required parameter\n\n" if ($self->{'debug'});
744 0           $self->{'last_code'} = '0';
745 0           $self->{'last_reason'} = 'Neurio->fetch_Appliances_Stats(): \$appliance_id is a required parameters';
746 0           return 0;
747             }
748             # make sure $start, $granularity, $end and $frequqncy are defined
749 0 0 0       if ((!defined $start) || (!defined $granularity) || (!defined $end) || (!defined $frequency)) {
      0        
      0        
750 0 0         print "\nNeurio->fetch_Appliances_Stats(): \$start, \$granularity, \$end and \$frequency are required parameters\n\n" if ($self->{'debug'});
751 0           $self->{'last_code'} = '0';
752 0           $self->{'last_reason'} = 'Neurio->fetch_Appliances_Stats(): \$start, \$granularity, \$end and \$frequency are required parameters';
753 0           return 0;
754             }
755             # make sure $granularity is one of the correct values
756 0 0         if (!($granularity =~ /[seconds|minutes|hours|days]/)) {
757 0 0         print "\nNeurio->fetch_Appliances_Stats(): Found \$granularity of $granularity\nOnly values of 'seconds, minutes, hours or days' are supported for \$granularity\n\n" if ($self->{'debug'});
758 0           $self->{'last_code'} = '0';
759 0           $self->{'last_reason'} = 'Neurio->fetch_Appliances_Stats(): Only values of "seconds, minutes, hours or days" are supported for \$granularity';
760 0           return 0;
761             }
762            
763 0           my $url = $self->{'Appliances_Stats_url'}."?locationId=$location_id&appliance_id=$appliance_id&start=$start&granularity=$granularity&end=$end&frequency=$frequency";
764            
765             # if optional parameter is defined, add it
766 0 0         if (defined $perPage) {
767 0           $url = $url . "&perPage=$perPage";
768             }
769             # if optional parameter is defined, add it
770 0 0         if (defined $page) {
771 0           $url = $url . "&page=$page";
772             }
773            
774 0           return $self->__process_get($url);
775             }
776              
777              
778             #******************************************************************************
779             =head2 fetch_Appliances_Events_by_Location - Fetch events for a specific location
780              
781             Retrieves events for a specific location. An event is an interval when an
782             appliance was in use.
783            
784             The applicance_id parameter can be determined by using the fetch_Appliance method
785             which returns a list of appliances with their IDs.
786            
787             The function has the following 2 possibilities for parameters:
788              
789             $Neurio->fetch_Appliances_Events_by_Location($location_id, $start,$end,$perPage,$page);
790             $Neurio->fetch_Appliances_Events_by_Location($location_id, $since,$perPage,$page);
791              
792             This method accepts the following parameters:
793             - $location_Id : id of a location - Required
794             - $start : yyyy-mm-ddThh:mm:ssZ - Required
795             specified using ISO8601 format
796             - $end : yyyy-mm-ddThh:mm:ssZ - Required
797             specified using ISO8601 format
798             - $since : yyyy-mm-ddThh:mm:ssZ - Required
799             specified using ISO8601 format
800             - $perPage : number of results per page - Optional
801             - $page : page number to return - Optional
802            
803             Returns an array of Perl data structures on success
804             [
805             {
806             "id" : "1cRsH7KQTeONMzjSuRJ2aw",
807             "createdAt" : "2014-04-21T22:28:32Z",
808             "updatedAt" : "2014-04-21T22:45:32Z",
809             "appliance" : {
810             "id" : "2SMROBfiTA6huhV7Drrm1g",
811             "name" : "television",
812             "label" : "upstairs TV",
813             "tags" : ["bedroom_television", "42 inch LED"],
814             "locationId" : "0qX7nB-8Ry2bxIMTK0EmXw"
815             },
816             "start" : "2014-04-21T05:26:10.785Z",
817             "end" : "2014-04-21T05:36:00.547Z",
818             "guesses" : {"dryer1" : 0.78, "dishwasher_2014" : 0.12},
819             "energy" : 247896,
820             "averagePower" : 122,
821             "groupIds" : [ "2pMROafiTA6huhV7Drrm1g", "4SmROBfiTA6huhV7Drrm1h" ],
822             "cycleCount" : 5,
823             "isRunning" : false
824             },
825             ...
826             ]
827             Returns 0 on failure
828            
829             =cut
830              
831             sub fetch_Appliances_Events_by_Location {
832 0     0 0   my ($self,$location_id,$start,$end,$perPage,$page) = @_;
833 0           my ($url);
834            
835             # make sure $location_id is defined
836 0 0         if (!defined $location_id) {
837 0 0         print "\nNeurio->fetch_Appliances_Events_by_Location(): \$location_id is a required parameter\n\n" if ($self->{'debug'});
838 0           $self->{'last_code'} = '0';
839 0           $self->{'last_reason'} = 'Neurio->fetch_Appliances_Events_by_Location(): \$location_id is a required parameter';
840 0           return 0;
841             }
842             # make sure $start (or $since) is defined
843 0 0         if (!defined $start) {
844 0 0         print "\nNeurio->fetch_Appliances_Events_by_Location(): \$start is a required parameter\n\n" if ($self->{'debug'});
845 0           $self->{'last_code'} = '0';
846 0           $self->{'last_reason'} = 'Neurio->fetch_Appliances_Events_by_Location(): \$start is a required parameter';
847 0           return 0;
848             }
849            
850             # check if $end is in ISO8601 format. If it is, then it is $end. If not, then $since was specified
851 0 0         if (defined $end) {
852 0 0         if (defined eval{DateTime::Format::ISO8601->parse_datetime($end)}) {
  0            
853 0           $url = $self->{'Appliances_Events_url'}."?locationId=$location_id&start=$start&end=$end";
854             } else {
855 0           $perPage = $end;
856 0           $page = $perPage;
857 0           $url = $self->{'Appliances_Events_url'}."?locationId=$location_id&since=$start";
858             }
859             } else {
860 0           $url = $self->{'Appliances_Events_url'}."?locationId=$location_id&since=$start";
861             }
862            
863             # if optional parameter is defined, add it
864 0 0         if (defined $perPage) {
865 0           $url = $url . "&perPage=$perPage";
866             }
867             # if optional parameter is defined, add it
868 0 0         if (defined $page) {
869 0           $url = $url . "&page=$page";
870             }
871              
872 0           return $self->__process_get($url);
873             }
874              
875              
876             #******************************************************************************
877             =head2 fetch_Appliances_Events_by_Appliance - Fetch events for a specific appliance
878              
879             Retrieves events for a specific appliance. An event is an interval when an
880             appliance was in use.
881            
882             The applicance_id parameter can be determined by using the fetch_Appliance method
883             which returns a list of appliances with their IDs.
884            
885             $Neurio->fetch_Appliances_Events_by_Appliance($appliance_id,$start,$end,$perPage,$page);
886              
887             This method accepts the following parameters:
888             - $appliance_id : id of the appliance - Required
889             - $start : yyyy-mm-ddThh:mm:ssZ - Required
890             specified using ISO8601 format
891             - $end : yyyy-mm-ddThh:mm:ssZ - Required
892             specified using ISO8601 format
893             - $since : yyyy-mm-ddThh:mm:ssZ - Required
894             specified using ISO8601 format
895             - $perPage : number of results per page - Optional
896             - $page : page number to return - Optional
897            
898             Returns an array of Perl data structures on success
899             [
900             {
901             "id" : "1cRsH7KQTeONMzjSuRJ2aw",
902             "createdAt" : "2014-04-21T22:28:32Z",
903             "updatedAt" : "2014-04-21T22:45:32Z",
904             "appliance" : {
905             "id" : "2SMROBfiTA6huhV7Drrm1g",
906             "name" : "television",
907             "label" : "upstairs TV",
908             "tags" : ["bedroom_television", "42 inch LED"],
909             "locationId" : "0qX7nB-8Ry2bxIMTK0EmXw"
910             },
911             "start" : "2014-04-21T05:26:10.785Z",
912             "end" : "2014-04-21T05:36:00.547Z",
913             "guesses" : {"dryer1" : 0.78, "dishwasher_2014" : 0.12},
914             "energy" : 247896,
915             "averagePower" : 122,
916             "groupIds" : [ "2pMROafiTA6huhV7Drrm1g", "4SmROBfiTA6huhV7Drrm1h" ],
917             "cycleCount" : 5,
918             "isRunning" : false
919             },
920             ...
921             ]
922             Returns 0 on failure
923            
924             =cut
925              
926             sub fetch_Appliances_Events_by_Appliance {
927 0     0 0   my ($self,$appliance_id,$start,$end,$perPage,$page) = @_;
928            
929             # make sure $appliance_id is defined
930 0 0         if (!defined $appliance_id) {
931 0 0         print "\nNeurio->fetch_Appliances_Events_by_Appliance(): \$appliance_id is a required parameter\n\n" if ($self->{'debug'});
932 0           $self->{'last_code'} = '0';
933 0           $self->{'last_reason'} = 'Neurio->fetch_Appliances_Events_by_Appliance(): \$appliance_id is a required parameters';
934 0           return 0;
935             }
936             # make sure $start and $end are defined
937 0 0 0       if ((!defined $start) || (!defined $end)) {
938 0 0         print "\nNeurio->fetch_Appliances_Events_by_Appliance(): \$start and \$end are required parameters\n\n" if ($self->{'debug'});
939 0           $self->{'last_code'} = '0';
940 0           $self->{'last_reason'} = 'Neurio->fetch_Appliances_Events_by_Appliance(): \$start and \$end are required parameters';
941 0           return 0;
942             }
943              
944 0           my $url = $self->{'Appliances_Events_url'}."?applianceId=$appliance_id&start=$start&end=$end";
945            
946             # if optional parameter is defined, add it
947 0 0         if (defined $perPage) {
948 0           $url = $url . "&perPage=$perPage";
949             }
950             # if optional parameter is defined, add it
951 0 0         if (defined $page) {
952 0           $url = $url . "&page=$page";
953             }
954            
955 0           return $self->__process_get($url);
956             }
957              
958              
959             #******************************************************************************
960             =head2 dump_Object - shows the contents of the local Neurio object
961              
962             shows the contents of the local Neurio object in human readable form
963              
964             $Neurio->dump_Object();
965              
966             This method accepts no parameters
967            
968             Returns nothing
969            
970             =cut
971              
972             sub dump_Object {
973 0     0 0   my $self = shift;
974            
975 0           print "Key : ".substr($self->{'key'}, 0,120)."\n";
976 0           print "SecretKey : ".substr($self->{'secret'}, 0,120)."\n";
977 0           print "Sensor_ID : ".substr($self->{'sensor_id'}, 0,120)."\n";
978 0           print "Location_ID : ".substr($self->{'location_id'}, 0,120)."\n";
979 0           print "Access_token : ".substr($self->{'access_token'}, 0,120)."\n";
980 0           print "Base 64 : ".substr($self->{'base64'}, 0,120)."\n";
981 0           print "Base URL : ".substr($self->{'base_url'}, 0,120)."\n";
982 0           print "Samples_Recent_Live URL : ".substr($self->{'Samples_Recent_Live_url'}, 0,120)."\n";
983 0           print "Samples_Last_Live URL : ".substr($self->{'Samples_Last_Live_url'}, 0,120)."\n";
984 0           print "Samples URL : ".substr($self->{'Samples_url'}, 0,120)."\n";
985 0           print "Samples_Full URL : ".substr($self->{'Samples_Full_url'}, 0,120)."\n";
986 0           print "Stats_Energy URL : ".substr($self->{'Stats_Energy_url'}, 0,120)."\n";
987 0           print "Appliances URL : ".substr($self->{'Appliances_url'}, 0,120)."\n";
988 0           print "Appliances_Specific URL : ".substr($self->{'Appliances_Specific_url'}, 0,120)."\n";
989 0           print "Appliances_Stats URL : ".substr($self->{'Appliances_Stats_url'}, 0,120)."\n";
990 0           print "Appliances_Events URL : ".substr($self->{'Appliances_Events_url'}, 0,120)."\n";
991 0           print "debug : ".substr($self->{'debug'}, 0,120)."\n";
992 0           print "last_code : ".substr($self->{'last_code'}, 0,120)."\n";
993 0           print "last_reason : ".substr($self->{'last_reason'}, 0,120)."\n";
994 0           print "last_execution_time : ".substr($self->{'last_exec_time'}, 0,120)."\n";
995 0           print "\n";
996             }
997              
998              
999             #******************************************************************************
1000             =head2 get_last_reason - returns the text generated by the most recent fetch
1001              
1002             Returns the HTTP Header reason for the most recent fetch command
1003              
1004             $Neurio->get_last_reason();
1005              
1006             This method accepts no parameters
1007            
1008             Returns the textual reason
1009            
1010             =cut
1011              
1012             sub get_last_reason {
1013 0     0 0   my $self = shift;
1014 0           return $self->{'last_reason'};
1015             }
1016              
1017             #******************************************************************************
1018             =head2 get_last_code - returns the code generated by the most recent fetch
1019              
1020             Returns the HTTP Header code for the most recent fetch command
1021              
1022             $Neurio->get_last_code();
1023              
1024             This method accepts no parameters
1025            
1026             Returns the numeric code
1027            
1028             =cut
1029              
1030             sub get_last_code {
1031 0     0 0   my $self = shift;
1032 0           return $self->{'last_code'};
1033             }
1034              
1035             #******************************************************************************
1036             =head2 get_last_exec_time - returns the execution time for the last fetch
1037              
1038             Returns the number of milliseconds it took for the last fetch call
1039              
1040             $Neurio->get_last_exec_time();
1041              
1042             This method accepts no parameters
1043            
1044             Returns the number of milliseconds
1045            
1046             =cut
1047              
1048             sub get_last_exec_time {
1049 0     0 0   my $self = shift;
1050 0           return $self->{'last_exec_time'};
1051             }
1052              
1053             #******************************************************************************
1054             sub __process_get {
1055 0     0     my $self = shift;
1056 0           my $url = shift;
1057 0           my $time_before = gettimeofday;
1058 0           my $response = $self->{'ua'}->get($url,"Authorization"=>"Bearer ".$self->{'access_token'});
1059 0           my $time_after = gettimeofday;
1060              
1061 0           $self->{'last_exec_time'} = eval{($time_after-$time_before)*1000};
  0            
1062 0           $self->{'last_code'} = $response->code;
1063              
1064 0 0         if (($response->code) eq '200') {
1065 0           $self->{'last_reason'} = '';
1066             } else {
1067 0           $self->{'last_reason'} = $response->message;
1068             }
1069              
1070 0 0         if ($response->is_success) {
1071 0           return decode_json($response->content);
1072             } else {
1073 0 0         print "\n".(caller(1))[3]."(): Failed with return code ".$self->get_last_code()." - ".$self->get_last_reason()."\n" if ($self->{'debug'});
1074 0           return 0;
1075             }
1076             }
1077              
1078             #******************************************************************************
1079             =head1 AUTHOR
1080              
1081             Kedar Warriner, C
1082              
1083             =head1 BUGS
1084              
1085             Please report any bugs or feature requests to C
1086             or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Device-Neurio
1087             I will be notified, and then you'll automatically be notified of progress on
1088             your bug as I make changes.
1089              
1090             =head1 SUPPORT
1091              
1092             You can find documentation for this module with the perldoc command.
1093              
1094             perldoc Device::Neurio
1095              
1096             You can also look for information at:
1097              
1098             =over 5
1099              
1100             =item * RT: CPAN's request tracker
1101              
1102             L
1103              
1104             =item * AnnoCPAN: Annotated CPAN documentation
1105              
1106             L
1107              
1108             =item * CPAN Ratings
1109              
1110             L
1111              
1112             =item * Search CPAN
1113              
1114             L
1115              
1116             =back
1117              
1118             =head1 ACKNOWLEDGEMENTS
1119              
1120             Many thanks to:
1121             The guys at Energy Aware Technologies for creating the Neurio sensor and
1122             developping the API.
1123             Everyone involved with CPAN.
1124              
1125             =head1 LICENSE AND COPYRIGHT
1126              
1127             Copyright 2014 Kedar Warriner .
1128              
1129             This program is free software; you can redistribute it and/or modify it
1130             under the terms of either: the GNU General Public License as published
1131             by the Free Software Foundation; or the Artistic License.
1132              
1133             See http://dev.perl.org/licenses/ for more information.
1134              
1135             =cut
1136              
1137             #******************************************************************************
1138             1; # End of Device::Neurio - Return success to require/use statement
1139             #******************************************************************************
1140              
1141