File Coverage

blib/lib/Device/Neurio.pm
Criterion Covered Total %
statement 51 508 10.0
branch 1 184 0.5
condition 0 6 0.0
subroutine 18 54 33.3
pod 1 30 3.3
total 71 782 9.0


line stmt bran cond sub pod time code
1             package Device::Neurio;
2              
3 1     1   922 use warnings;
  1         2  
  1         33  
4 1     1   4 use strict;
  1         2  
  1         17  
5 1     1   22 use 5.006_001;
  1         10  
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_Appliance 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   7531 if ($^O eq "MSWin32"){
  0            
32 1     1   6085150 use LWP::UserAgent;
  1         1899541  
  1         73  
33 1     1   14 use HTTP::Request;
  1         2  
  1         38  
34 1     1   6 use Time::Local;
  1         3  
  1         116  
35 1     1   7 use JSON qw(decode_json encode_json);
  1         3  
  1         14  
36 1     1   1214 use MIME::Base64 (qw(encode_base64));
  1         1052  
  1         91  
37 1     1   975 use Time::HiRes (qw/gettimeofday/);
  1         1759  
  1         5  
38 1     1   1489 use Data::Dumper;
  1         10493  
  1         132  
39 0           } else {
40 1     1   11 use LWP::UserAgent;
  1         3  
  1         38  
41 1     1   7 use HTTP::Request;
  1         3  
  1         35  
42 1     1   8 use Time::Local;
  1         2  
  1         81  
43 1     1   9 use JSON qw(decode_json encode_json);
  1         3  
  1         16  
44 1     1   201 use MIME::Base64 (qw(encode_base64));
  1         3  
  1         210  
45 1     1   12 use Time::HiRes (qw/gettimeofday/);
  1         4  
  1         37  
46 1     1   186 use Data::Dumper;
  1         3  
  1         70  
47             }
48             }
49              
50              
51             =head1 NAME
52              
53             Device::Neurio - Methods for wrapping the Neurio API calls so that they are
54             accessible via Perl
55              
56             =head1 VERSION
57              
58             Version 0.16
59              
60             =cut
61              
62             our $VERSION = '0.16';
63              
64             ###################################################################################################
65             =head1 SYNOPSIS
66              
67             This module provides a Perl interface to a Neurio sensor via the following
68             methods:
69             - new
70             - connect
71             - fetch_Samples
72             - fetch_Samples_Full
73             - fetch_Samples_Last_Live
74             - fetch_Samples_Recent_Live
75             - fetch_Stats_Energy
76             - fetch_Appliances
77             - fetch_Appliances_Events
78             - fetch_Appliance
79             - fetch_Appliances_Stats
80              
81             Please note that in order to use the 'Samples' methods in this module you will
82             require three parameters (key, secret, sensor_id) as well as an Energy Aware
83             Neurio sensor installed in your house. In order to use the 'Appliances'
84             methods, you will also require another parameter (location_id). This information
85             can be obtained from the Neurio developpers website.
86              
87             The module is written entirely in Perl and was developped on Raspbian Linux.
88              
89             All date/time values are specified using ISO8601 format (yyyy-mm-ddThh:mm:ssZ)
90              
91             =head1 SAMPLE CODE
92              
93             use Device::Neurio;
94              
95             $my_Neurio = Device::Neurio->new($key,$secret,$sensor_id);
96              
97             $my_Neurio->connect($location_id);
98            
99             $data = $my_Neurio->fetch_Samples_Last_Live();
100             print $data->{'consumptionPower'}
101              
102             $data = $my_Neurio->fetch_Samples_Recent_Live("2014-06-18T19:20:21Z");
103             print $data->[0]->{'consumptionPower'}
104              
105             undef $my_Neurio;
106              
107              
108             =head2 EXPORT
109              
110             All by default.
111              
112              
113             =head1 SUBROUTINES/METHODS
114              
115             =head2 new - the constructor for a Neurio object
116              
117             Creates a new instance which will be able to fetch data from a unique Neurio
118             sensor. All three parameters are required and can be obtained from the
119             Neurio developpers website.
120              
121             my $Neurio = Device::Neurio->new($key, $secret, $sensor_id, $debug);
122              
123             This method accepts the following parameters:
124             - $key : unique key for the account - Required
125             - $secret : secret key for the account - Required
126             - $sensor_id : sensor ID connected to the account - Required
127             - $debug : turn on debug messages - Optional
128              
129             Returns a Neurio object if successful.
130             Returns 0 on failure
131            
132             =cut
133              
134             sub new {
135 0     0 1   my $class = shift;
136 0           my $self;
137            
138 0           $self->{'ua'} = LWP::UserAgent->new();
139 0           $self->{'key'} = shift;
140 0           $self->{'secret'} = shift;
141 0           $self->{'sensor_id'} = shift;
142 0           $self->{'debug'} = 0;
143              
144 0 0 0       if ((!defined $self->{'key'}) || (!defined $self->{'secret'}) || (!defined $self->{'sensor_id'})) {
      0        
145 0           print "\nNeurio->new(): Key, Secret and Sensor_ID are REQUIRED parameters\n";
146 0           $self->{'last_code'} = '0';
147 0           $self->{'last_reason'} = 'Neurio->new(): Key, Secret and Sensor_ID are REQUIRED parameters';
148 0           return 0;
149             }
150            
151 0           $self->{'base64'} = encode_base64($self->{'key'}.":".$self->{'secret'});
152 0           chomp($self->{'base64'});
153            
154 0 0         if (!defined $self->{'debug'}) {
155 0           $self->{'debug'} = 0;
156             }
157            
158 0           $self->{'base_url'} = "https://api-staging.neur.io/v1";
159             # $self->{'base_url'} = "https://api.neur.io/v1";
160 0           $self->{'Samples_Recent_Live_url'} = $self->{'base_url'}."/samples/live?sensorId=".$self->{'sensor_id'};
161 0           $self->{'Samples_Last_Live_url'} = $self->{'base_url'}."/samples/live/last?sensorId=".$self->{'sensor_id'};
162 0           $self->{'Samples_url'} = $self->{'base_url'}."/samples?sensorId=".$self->{'sensor_id'};
163 0           $self->{'Samples_Full_url'} = $self->{'base_url'}."/samples/full?sensorId=".$self->{'sensor_id'};
164 0           $self->{'Stats_Energy_url'} = $self->{'base_url'}."/samples/stats?sensorId=".$self->{'sensor_id'};
165 0           $self->{'Appliances_url'} = $self->{'base_url'}."/appliances";
166 0           $self->{'Appliances_Specs_url'} = $self->{'base_url'}."/appliances/specs";
167 0           $self->{'Appliances_Stats_url'} = $self->{'base_url'}."/appliances/stats";
168 0           $self->{'Appliances_Status_url'} = $self->{'base_url'}."/appliances/status";
169 0           $self->{'Appliances_Events_url'} = $self->{'base_url'}."/appliances/events";
170 0           $self->{'Users_url'} = $self->{'base_url'}."/users";
171 0           $self->{'Location_url'} = $self->{'base_url'}."/locations";
172 0           $self->{'Cycles_url'} = $self->{'base_url'}."/cycles";
173 0           $self->{'Cycles_Full_url'} = $self->{'base_url'}."/cycles/full";
174 0           $self->{'Cycles_Groups_url'} = $self->{'base_url'}."/cycles/groups";
175 0           $self->{'Edges_url'} = $self->{'base_url'}."/edges?sensorId=".$self->{'sensor_id'};
176 0           $self->{'Sensors_url'} = $self->{'base_url'}."/sensors";
177 0           $self->{'Analytics_url'} = $self->{'base_url'}."/analytics/results";
178 0           $self->{'last_code'} = '';
179 0           $self->{'last_reason'} = '';
180 0           $self->{'last_exec_time'} = 0;
181 0           $self->{'rateLimitRemaining'} = 0;
182 0           $self->{'rateLimitReset'} = 0;
183 0           $self->{'rateLimitLimit'} = 0;
184 0           $self->{'contentLength'} = 0;
185            
186 0           bless $self, $class;
187            
188 0           return $self;
189             }
190              
191              
192              
193              
194             #*****************************************************************
195              
196             =head2 DESTROY - the destructor for a Neurio object
197              
198             Destroys a previously created Neuri object.
199            
200             =cut
201             sub DESTROY {
202 0     0     my $self = shift;
203            
204 0           print"\nDestroying ".ref($self), "...\n\n";
205              
206 0           undef $self->{'ua'};
207 0           undef $self->{'key'};
208 0           undef $self->{'secret'};
209 0           undef $self->{'sensor_id'};
210 0           undef $self->{'debug'};
211 0           undef $self->{'base64'};
212 0           undef $self->{'base_url'};
213 0           undef $self->{'Samples_Recent_Live_url'};
214 0           undef $self->{'Samples_Last_Live_url'};
215 0           undef $self->{'Samples_url'};
216 0           undef $self->{'Samples_Full_url'};
217 0           undef $self->{'Stats_Energy_url'};
218 0           undef $self->{'Appliances_url'};
219 0           undef $self->{'Appliances_Specs_url'};
220 0           undef $self->{'Appliances_Stats_url'};
221 0           undef $self->{'Appliances_Status_url'};
222 0           undef $self->{'Appliances_Events_url'};
223 0           undef $self->{'Users_url'};
224 0           undef $self->{'Cycles_url'};
225 0           undef $self->{'Cycles_Full_url'};
226 0           undef $self->{'Cycles_Groups_url'};
227 0           undef $self->{'Edges_url'};
228 0           undef $self->{'Sensors_url'};
229 0           undef $self->{'Analytics_url'};
230 0           undef $self->{'last_code'};
231 0           undef $self->{'last_reason'};
232 0           undef $self->{'last_exec_time'};
233 0           undef $self->{'rateLimitRemaining'};
234 0           undef $self->{'rateLimitReset'};
235 0           undef $self->{'rateLimitLimit'};
236 0           undef $self->{'contentLength'};
237            
238             }
239              
240             ###################################################################################################
241             =head2 connect - open a secure connection to the Neurio server
242              
243             Opens a secure connection via HTTPS to the Neurio server which provides
244             access to a set of API commands to access the sensor data.
245            
246             An optional location ID can be given. This is only required if calls
247             will be made to the 'Appliance' methods. Calls to the 'Samples'
248             methods do not require that a location ID be set. If a location_id is not
249             specified at connection, then it must be specified when using the 'Appliance'
250             methods.
251            
252             A location ID can be acquired from the Neurio developpers web site
253              
254             $Neurio->connect($location_id);
255            
256             This method accepts the following parameter:
257             - $location_id : unique location id - Optional
258            
259             Returns 1 on success
260             Returns 0 on failure
261            
262             =cut
263              
264             sub connect {
265 0     0 0   my ($self,$location_id) = @_;
266 0           my $access_token = '';
267            
268 0 0         if (defined $location_id) {
269 0           $self->{'location_id'} = $location_id;
270             } else {
271 0           $self->{'location_id'} = '';
272             }
273              
274             # Submit request for authentiaction token.
275             my $response = $self->{'ua'}->post($self->{'base_url'}.'/oauth2/token',
276             { basic_authentication => $self->{'base64'},
277             Content_Type => 'application/x-www-form-urlencoded',
278             grant_type => 'client_credentials',
279             client_id => $self->{'key'},
280 0           client_secret => $self->{'secret'},
281             }
282             );
283            
284 0 0         if($response->is_success) {
285 0           my $return = $response->content;
286 0           $return =~ /\"access_token\":\"(.*)\"\,\"token_type\"/;
287 0           $self->{'access_token'} = $1;
288 0           return 1;
289             } else {
290 0           $self->printLOG("\nDevice::Neurio->connect(): Failed to connect.\n");
291 0 0         if ($self->{'debug'}) {$self->printLOG($response->content."\n\n");}
  0            
292 0           $self->{'last_code'} = '0';
293 0           $self->{'last_reason'} = 'Neurio->new(): Device::Neurio->connect(): Failed to connect';
294 0           return 0;
295             }
296             }
297              
298             ###################################################################################################
299             =head2 debug - Configure debug settings for a Neurio object
300              
301             Enables debug printouts and an optional file handle can be supplied
302             where printouts will be re-directed.
303              
304             $my_Neurio = Device::Neurio->new($key,$secret,$sensor_id);
305              
306             $my_Neurio->connect($location_id);
307             $my_Neurio->debug($debug,$fileHandle);
308              
309             This method accepts at least one of the following parameters:
310             - $debug : turn on debug messages - Optional
311             - $fileHandle : filehandle for logging debug messages - Optional
312              
313             Returns nothing.
314            
315             =cut
316             sub debug {
317 0     0 0   my ($self,$debug,$fileHandle) = @_;
318            
319 0 0         if (defined $debug) {
320 0           $self->{'debug'} = $debug;
321             }
322            
323 0 0         if (defined $fileHandle) {
324 0           $self->{'$fileHandle'} = $fileHandle;
325             }
326             }
327              
328             ###################################################################################################
329             =head2 fetch_Samples_Recent_Live - Fetch recent sensor samples
330              
331             Get recent samples, one sample per second for up to the last 2 minutes.
332             The values represent the sum of all phases.
333              
334             $Neurio->fetch_Samples_Recent_Live($last);
335            
336             This method accepts the following parameters:
337             $last - time of last sample received specified using ISO8601
338             format (yyyy-mm-ddThh:mm:ssZ) - Optional
339            
340             If no value is specified for $last, a default of 2 minutes is used.
341            
342             Returns an array of Perl data structures on success
343             [
344             {
345             'generationEnergy' => 3716166644,
346             'timestamp' => '2014-06-24T11:08:00.000Z',
347             'consumptionEnergy' => 6762651207,
348             'generationPower' => 564,
349             'consumptionPower' => 821
350             },
351             ...
352             ]
353             Returns 0 on failure
354            
355             =cut
356              
357             sub fetch_Samples_Recent_Live {
358 0     0 0   my ($self,$last) = @_;
359 0           my $url = $self->{'Samples_Recent_Live_url'};;
360              
361             # if optional parameter is defined, add it
362 0 0         if (defined $last) {
363 0           $url = $self->{'Samples_Recent_Live_url'}."&last=$last";
364             }
365              
366 0           return $self->__process_get($url);
367             }
368              
369              
370             ###################################################################################################
371             =head2 fetch_Samples_Last_Live - Fetch the last live sensor sample
372              
373             Get the last sample recorded by the sensor.
374             The values represent the sum of all phases.
375              
376             $Neurio->fetch_Samples_Last_Live();
377              
378             This method accepts no parameters
379            
380             Returns a Perl data structure on success:
381             {
382             'generationEnergy' => 3716027450,
383             'timestamp' => '2014-06-24T11:03:43.000Z',
384             'consumptionEnergy' => 6762445671,
385             'generationPower' => 542,
386             'consumptionPower' => 800
387             };
388             Returns 0 on failure
389            
390             =cut
391              
392             sub fetch_Samples_Last_Live {
393 0     0 0   my $self = shift;
394 0           my $url = $self->{'Samples_Last_Live_url'};
395 0           return $self->__process_get($url);
396             }
397              
398              
399             ###################################################################################################
400             =head2 fetch_Samples - Fetch sensor samples from the Neurio server
401              
402             Get samples for a specified time interval.
403             The values represent the sum of all phases.
404              
405             $Neurio->fetch_Samples($start,$granularity,$end,$frequency,$perPage,$page);
406              
407             This method accepts the following parameters:
408             - $start : yyyy-mm-ddThh:mm:ssZ - Required
409             specified using ISO8601 format
410             - $granularity : seconds|minutes|hours|days - Required
411             - $end : yyyy-mm-ddThh:mm:ssZ - Optional
412             specified using ISO8601 format
413             - $frequency : if the granularity is specified as 'minutes', then the
414             frequency must be a multiple of 5 - Optional
415             - $perPage : number of results per page - Optional
416             - $page : page number to return - Optional
417            
418             Returns an array of Perl data structures on success
419             [
420             {
421             'generationEnergy' => 3568948578,
422             'timestamp' => '2014-06-21T19:00:00.000Z',
423             'consumptionEnergy' => 6487889194,
424             'generationPower' => 98,
425             'consumptionPower' => 240
426             },
427             ...
428             ]
429             Returns 0 on failure
430            
431             =cut
432              
433             sub fetch_Samples {
434 0     0 0   my ($self,$start,$granularity,$end,$frequency,$perPage,$page) = @_;
435            
436 0           my $url = $self->{'Samples_url'};
437            
438             # if REQUIRED parameters are defined, add them
439 0 0         if (defined $start) {
440 0           $url = $url . "&start=$start";
441             }
442 0 0         if (defined $granularity) {
443 0           $url = $url . "&granularity=$granularity";
444             }
445            
446             # if optional parameters are defined, add them
447 0 0         if (defined $end) {
448 0           $url = $url . "&end=$end";
449             }
450 0 0         if (defined $frequency) {
451 0           $url = $url . "&frequency=$frequency";
452             }
453 0 0         if (defined $perPage) {
454 0           $url = $url . "&perPage=$perPage";
455             }
456 0 0         if (defined $page) {
457 0           $url = $url . "&page=$page";
458             }
459            
460 0           return $self->__process_get($url);
461             }
462              
463              
464             ###################################################################################################
465             =head2 fetch_Samples_Full - Fetches full samples for all phases
466              
467             Get full samples for a specified time interval. Sample data will include
468             information broken down by channel.
469              
470             $Neurio->fetch_Samples_Full($start,$granularity,$end,$frequency,$perPage,$page);
471              
472             This method accepts the following parameters:
473             - $start : yyyy-mm-ddThh:mm:ssZ - Required
474             specified using ISO8601 format
475             - $granularity : seconds|minutes|hours|days - Required
476             - $end : yyyy-mm-ddThh:mm:ssZ - Optional
477             specified using ISO8601 format
478             - $frequency : an integer - Optional
479             - $perPage : number of results per page - Optional
480             - $page : page number to return - Optional
481            
482             Returns an array of Perl data structures on success
483             [
484             {
485             'timestamp' => '2014-06-16T19:20:21.000Z',
486             'channelSamples' => [
487             {
488             'voltage' => '123.19',
489             'power' => 129,
490             'name' => '1',
491             'energyExported' => 27,
492             'channelType' => 'phase_a',
493             'energyImported' => 2682910899,
494             'reactivePower' => 41
495             },
496             {
497             'voltage' => '123.94',
498             'power' => 199,
499             'name' => '2',
500             'energyExported' => 6,
501             'channelType' => 'phase_b',
502             'energyImported' => 3296564362,
503             'reactivePower' => -45
504             },
505             {
506             'voltage' => '123.57',
507             'power' => 327,
508             'name' => '3',
509             'energyExported' => 10,
510             'channelType' => 'consumption',
511             'energyImported' => 5979475235,
512             'reactivePower' => -4
513             }
514             ]
515             },
516             ...
517             ]
518             Returns 0 on failure
519            
520             =cut
521              
522             sub fetch_Samples_Full {
523 0     0 0   my ($self,$start,$granularity,$end,$frequency,$perPage,$page) = @_;
524            
525 0           my $url = $self->{'Samples_Full_url'};
526            
527             # if REQUIRED parameters are defined, add them
528 0 0         if (defined $start) {
529 0           $url = $url . "&start=$start";
530             }
531 0 0         if (defined $granularity) {
532 0           $url = $url . "&granularity=$granularity";
533             }
534              
535             # if optional parameters are defined, add them
536 0 0         if (defined $end) {
537 0           $url = $url . "&end=$end";
538             }
539 0 0         if (defined $frequency) {
540 0           $url = $url . "&frequency=$frequency";
541             }
542 0 0         if (defined $perPage) {
543 0           $url = $url . "&perPage=$perPage";
544             }
545 0 0         if (defined $page) {
546 0           $url = $url . "&page=$page";
547             }
548            
549 0           return $self->__process_get($url);
550             }
551              
552              
553             ###################################################################################################
554             =head2 fetch_Stats_Energy - Fetches energy statistics
555              
556             Get brief stats for energy consumed in a given time interval.
557             The values represent the sum of all phases.
558              
559             To convert the energy returned into kWh, divide it by 3600000
560              
561             $Neurio->fetch_Stats_Energy($start,$granularity,$frequency,$end);
562              
563             This method accepts the following parameters:
564             - $start : yyyy-mm-ddThh:mm:ssZ - Required
565             specified using ISO8601 format
566             - $granularity : minutes|hours|days|months - Required
567             - $frequency : if the granularity is specified as 'minutes', then the
568             frequency must be a multiple of 5 - Required
569             - $end : yyyy-mm-ddThh:mm:ssZ - Optional
570             specified using ISO8601 format
571            
572             Returns a Perl data structure containing all the raw data
573             Returns 0 on failure
574            
575             =cut
576              
577             sub fetch_Stats_Energy {
578 0     0 0   my ($self,$start,$granularity,$frequency,$end) = @_;
579              
580 0           my $url = $self->{'Stats_Energy_url'};
581              
582             # if REQUIRED parameter are defined, add them
583 0 0         if (defined $start) {
584 0           $url = $url . "&start=$start";
585             }
586            
587             # if optional parameter is defined, add it
588 0 0         if (defined $frequency) {
589 0           $url = $url . "&frequency=$frequency";
590             }
591 0 0         if (defined $granularity) {
592 0           $url = $url . "&granularity=$granularity";
593             }
594 0 0         if (defined $end) {
595 0           $url = $url . "&end=$end";
596             }
597            
598 0           return $self->__process_get($url);
599             }
600              
601              
602              
603              
604             ###################################################################################################
605             =head2 fetch_Appliances - Fetch the appliances for a specific location
606              
607             Get the appliances added for a specified location.
608            
609             The location_id is an optional parameter because it can be specified when
610             connecting. If it is specified below, then this will over-ride the location
611             ID set when connecting, but for this function call only.
612              
613             $Neurio->fetch_Appliances($location_id);
614              
615             This method accepts the following parameters:
616             - $location_id : id of a location - Optional
617            
618             Returns an array of Perl data structures on success
619             [
620             {
621             'locationId' => 'xxxxxxxxxxxxxxx',
622             'name' => 'lighting_appliance',
623             'id' => 'yyyyyyyyyyyyyyyyy',
624             'label' => 'Range Light on Medium',
625             'tags' => []
626             },
627             {
628             'locationId' => 'xxxxxxxxxxxxxxx-3',
629             'name' => 'refrigerator',
630             'id' => 'zzzzzzzzzzzzzzzz',
631             'label' => '',
632             'tags' => []
633             },
634             ....
635             ]
636             Returns 0 on failure
637            
638             =cut
639              
640             sub fetch_Appliances {
641 0     0 0   my ($self,$location_id) = @_;
642              
643 0           my $url = $self->{'Appliances_url'}."?";
644              
645             # if REQUIRED parameter is defined, add it
646 0 0         if (defined $location_id) {
647 0           $url = $url . "locationId=$location_id";
648             } else {
649 0           $url = $url . "locationId=".$self->{'location_id'};
650             }
651              
652 0           return $self->__process_get($url);
653             }
654              
655              
656             ###################################################################################################
657             =head2 fetch_Appliance - Fetch information about a specific appliance
658              
659             Get the information for a given appliance.
660            
661             The applicance_id parameter is determined by using the fetch_Appliance method
662             which returns a list of appliances with their IDs
663              
664             $Neurio->fetch_Appliance($appliance_id);
665              
666             This method accepts the following parameters:
667             - $appliance_id : id of the appliance - Required
668            
669             Returns a Perl data structure on success:
670             {
671             'locationId' => 'xxxxxxxxxxxxx,
672             'name' => 'lighting_appliance',
673             'id' => 'yyyyyyyyyyyyyyy',
674             'label' => 'Range Light on Medium',
675             'tags' => []
676             };
677             Returns 0 on failure
678            
679             =cut
680              
681             sub fetch_Appliance {
682 0     0 0   my ($self,$appliance_id) = @_;
683            
684 0           my $url = $self->{'Appliances_url'}."/";
685              
686             # if REQUIRED parameter are defined, add them
687 0 0         if (defined $appliance_id) {
688 0           $url = $url . $appliance_id;
689             }
690            
691 0           return $self->__process_get($url);
692             }
693              
694              
695             ###################################################################################################
696             =head2 fetch_Appliances_Specs - Fetch specs about all appliances
697              
698             Get all supported appliance types that Neurio can detect, along with their
699             specifications.
700            
701             $Neurio->fetch_Appliances_Specs();
702              
703             This method accepts no parameters:
704            
705             Returns a Perl data structure on success:
706             {
707             'locationId' => 'xxxxxxxxxxxxx,
708             'name' => 'lighting_appliance',
709             'id' => 'yyyyyyyyyyyyyyy',
710             'label' => 'Range Light on Medium',
711             'tags' => []
712             };
713             Returns 0 on failure
714            
715             =cut
716              
717             sub fetch_Appliances_Specs {
718 0     0 0   my $self = shift;
719 0           my $url = $self->{'Appliances_Specs_url'};
720            
721 0           return $self->__process_get($url);
722             }
723              
724              
725             ###################################################################################################
726             =head2 fetch_Appliances_Status - Fetch specs about all appliances
727              
728             Query the appliance statuses for a specified location.
729            
730             $Neurio->fetch_Appliances_Status($location_id);
731              
732             This method accepts the following parameters:
733             - $location_Id : id of a location - Required
734            
735             Returns a Perl data structure on success:
736             [
737             {
738             "appliance" : {
739             "id" : "2SMROBfiTA6huhV7Drrm1g",
740             "name" : "television",
741             "label" : "upstairs TV",
742             "tags" : ["bedroom_television", "42 inch LED"],
743             "locationId" : "0qX7nB-8Ry2bxIMTK0EmXw",
744             "createdAt": "2014-10-16T18:21:11.038Z",
745             "updatedAt": "2014-10-16T18:47:09.566Z",
746             },
747             "isTrained": true,
748             "lastUsed": "2014-10-31T15:08:01.310Z"
749             },
750             ...
751             ]
752             Returns 0 on failure
753            
754             =cut
755              
756             sub fetch_Appliances_Status {
757 0     0 0   my ($self,$location_id) = @_;
758 0           my $url = $self->{'Appliances_Status_url'}."?locationId=$location_id";
759            
760 0           return $self->__process_get($url);
761             }
762              
763              
764             ###################################################################################################
765             =head2 fetch_Appliances_Stats_by_Location - Fetch appliance stats for a given location
766              
767             Get appliance usage data for a given location.
768            
769             $Neurio->fetch_Appliances_Stats_by_location($location_id,$start,$granularity,$end,$minPower,$perPage,$page);
770              
771             This method accepts the following parameters:
772             - $location_Id : id of a location - Required
773             - $start : yyyy-mm-ddThh:mm:ssZ - Required
774             specified using ISO8601 format
775             - $granularity : seconds|minutes|hours|days - Required
776             - $end : yyyy-mm-ddThh:mm:ssZ - Required
777             specified using ISO8601 format
778             - $minPower : minimum power - Optional
779             - $perPage : number of results per page - Optional
780             - $page : page number to return - Optional
781            
782             Returns an array of Perl data structures on success
783             [
784             {
785             "appliance": {
786             "label": "",
787             "name": "dryer",
788             "locationId": "0qX7nB-8Ry2bxIMTK0EmXw",
789             "tags": [],
790             "createdAt": "2015-01-04T23:42:54.009Z",
791             "updatedAt": "2015-01-30T19:19:10.278Z",
792             "id": "4SmROBfiTA6huhV7Drrm1h"
793             },
794             "averagePower": 5162.4,
795             "eventCount": 5,
796             "lastEvent": {
797             "appliance": {
798             "label": "",
799             "name": "dryer",
800             "locationId": "0qX7nB-8Ry2bxIMTK0EmXw",
801             "tags": [],
802             "createdAt": "2015-01-04T23:42:54.009Z",
803             "updatedAt": "2015-01-30T19:19:10.278Z",
804             "id": "4SmROBfiTA6huhV7Drrm1h"
805             },
806             "status": "complete",
807             "start": "2015-02-04T22:24:41.816Z",
808             "end": "2015-02-04T22:31:06.792Z",
809             "energy": 1308604,
810             "averagePower": 5155,
811             "guesses": {
812             "air_conditioner": 0.5,
813             "dryer": 0.5
814             },
815             "groupIds": ["2pMROafiTA6huhV7Drrm1g"],
816             "lastCycle": {
817             "groupId": "cd0r-kOrRvWFbIuuUnL5GQ",
818             "start": "2015-02-04T22:29:25.798Z",
819             "end": "2015-02-04T22:31:06.792Z",
820             "energy": 482612,
821             "averagePower": 5182,
822             "createdAt": "2015-02-04T22:29:38.701Z",
823             "updatedAt": "2015-02-04T23:28:08.014Z",
824             "significant": true,
825             "sensorId": "0x0000C47F510179FE",
826             "id": "Xj_L10ryTgSdX8euqj_fHw"
827             },
828             "cycleCount": 2,
829             "isConfirmed": true,
830             "id": "-yvnL0vgTN2DUx2dVv4uTw"
831             },
832             "timeOn": 687944,
833             "energy": 14443276,
834             "usagePercentage": 16.34809,
835             "guesses": {},
836             "start": "2015-02-04T03:37:51.566Z",
837             "end": "2015-02-11T23:41:06.554Z",
838             "groupIds": ["2pMROafiTA6huhV7Drrm1g"],
839             "id": "Y8StKV6nStaXaguxnmNKtg"
840             },
841             ...
842             ]
843             Returns 0 on failure
844            
845             =cut
846              
847             sub fetch_Appliances_Stats_by_Location {
848 0     0 0   my ($self,$location_id,$start,$granularity,$end,$minPower,$perPage,$page) = @_;
849            
850 0           my $url = $self->{'Appliances_Stats_url'}."?";
851            
852             # if REQUIRED parameter are defined, add them
853 0 0         if (defined $location_id) {
854 0           $url = $url . "locationId=$location_id";
855             }
856 0 0         if (defined $start) {
857 0           $url = $url . "&start=$start";
858             }
859 0 0         if (defined $end) {
860 0           $url = $url . "&end=$end";
861             }
862 0 0         if (defined $granularity) {
863 0           $url = $url . "&granularity=$granularity";
864             }
865            
866             # if optional parameters are defined, add them
867 0 0         if (defined $minPower) {
868 0           $url = $url . "&minPower=$minPower";
869             }
870 0 0         if (defined $perPage) {
871 0           $url = $url . "&perPage=$perPage";
872             }
873 0 0         if (defined $page) {
874 0           $url = $url . "&page=$page";
875             }
876            
877 0           return $self->__process_get($url);
878             }
879              
880              
881             ###################################################################################################
882             =head2 fetch_Appliances_Stats_by_Appliance - Fetch usage data for a given appliance
883              
884             Get appliance usage data for a given appliance.
885            
886             $Neurio->fetch_Appliances_Stats_by_Appliance($appliance_id,$start,$granularity,$end,$minPower,$perPage,$page);
887              
888             This method accepts the following parameters:
889             - $appliance_id : id of the appliance - Required
890             - $start : yyyy-mm-ddThh:mm:ssZ - Required
891             specified using ISO8601 format
892             - $granularity : days, weeks, or months - Required
893             - $end : yyyy-mm-ddThh:mm:ssZ - Required
894             specified using ISO8601 format
895             - $minPower : minimum Power - Optional
896             - $perPage : number of results per page - Optional
897             - $page : page number to return - Optional
898            
899             Returns an array of Perl data structures on success
900             [
901             {
902             "appliance": {
903             "label": "",
904             "name": "dryer",
905             "locationId": "0qX7nB-8Ry2bxIMTK0EmXw",
906             "tags": [],
907             "createdAt": "2015-01-04T23:42:54.009Z",
908             "updatedAt": "2015-01-30T19:19:10.278Z",
909             "id": "4SmROBfiTA6huhV7Drrm1h"
910             },
911             "averagePower": 5162.4,
912             "eventCount": 5,
913             "lastEvent": {
914             "appliance": {
915             "label": "",
916             "name": "dryer",
917             "locationId": "0qX7nB-8Ry2bxIMTK0EmXw",
918             "tags": [],
919             "createdAt": "2015-01-04T23:42:54.009Z",
920             "updatedAt": "2015-01-30T19:19:10.278Z",
921             "id": "4SmROBfiTA6huhV7Drrm1h"
922             },
923             "status": "complete",
924             "start": "2015-02-04T22:24:41.816Z",
925             "end": "2015-02-04T22:31:06.792Z",
926             "energy": 1308604,
927             "averagePower": 5155,
928             "guesses": {
929             "air_conditioner": 0.5,
930             "dryer": 0.5
931             },
932             "groupIds": ["2pMROafiTA6huhV7Drrm1g"],
933             "lastCycle": {
934             "groupId": "cd0r-kOrRvWFbIuuUnL5GQ",
935             "start": "2015-02-04T22:29:25.798Z",
936             "end": "2015-02-04T22:31:06.792Z",
937             "energy": 482612,
938             "averagePower": 5182,
939             "createdAt": "2015-02-04T22:29:38.701Z",
940             "updatedAt": "2015-02-04T23:28:08.014Z",
941             "significant": true,
942             "sensorId": "0x0000C47F510179FE",
943             "id": "Xj_L10ryTgSdX8euqj_fHw"
944             },
945             "cycleCount": 2,
946             "isConfirmed": true,
947             "id": "-yvnL0vgTN2DUx2dVv4uTw"
948             },
949             "timeOn": 687944,
950             "energy": 14443276,
951             "usagePercentage": 16.34809,
952             "guesses": {},
953             "start": "2015-02-04T03:37:51.566Z",
954             "end": "2015-02-11T23:41:06.554Z",
955             "groupIds": ["2pMROafiTA6huhV7Drrm1g"],
956             "id": "Y8StKV6nStaXaguxnmNKtg"
957             },
958             ...
959             ]
960             Returns 0 on failure
961            
962             =cut
963              
964             sub fetch_Appliances_Stats_by_Appliance {
965 0     0 0   my ($self,$appliance_id,$start,$granularity,$end,$minPower,$perPage,$page) = @_;
966              
967 0           my $url = $self->{'Appliances_Stats_url'}."?";
968              
969             # if REQUIRED parameter are defined, add them
970 0 0         if (defined $appliance_id) {
971 0           $url = $url . "applianceId=$appliance_id";
972             }
973 0 0         if (defined $start) {
974 0           $url = $url . "&start=$start";
975             }
976 0 0         if (defined $end) {
977 0           $url = $url . "&end=$end";
978             }
979 0 0         if (defined $granularity) {
980 0           $url = $url . "&granularity=$granularity";
981             }
982            
983             # if optional parameters are defined, add them
984 0 0         if (defined $minPower) {
985 0           $url = $url . "&minPower=$minPower";
986             }
987 0 0         if (defined $perPage) {
988 0           $url = $url . "&perPage=$perPage";
989             }
990 0 0         if (defined $page) {
991 0           $url = $url . "&page=$page";
992             }
993            
994 0           return $self->__process_get($url);
995             }
996              
997              
998             ###################################################################################################
999             =head2 fetch_Appliances_Events_by_Location - Fetch events for a specific location
1000              
1001             Get appliance events by location Id.
1002             An event is an interval when an appliance was in use.
1003            
1004             An applicance_id can be requested by using the NeurioTools::get_appliance_ID
1005             method which returns an appliance ID for a given string name.
1006            
1007              
1008             $Neurio->fetch_Appliances_Events_by_Location($location_id, $start,$end,$perPage,$page);
1009              
1010             This method accepts the following parameters:
1011             - $location_Id : id of a location - Required
1012             - $start : yyyy-mm-ddThh:mm:ssZ - Required
1013             specified using ISO8601 format
1014             - $end : yyyy-mm-ddThh:mm:ssZ - Required
1015             specified using ISO8601 format
1016             - $minpower : Minimum power consumption - Optional
1017             - $perPage : number of results per page - Optional
1018             - $page : page number to return - Optional
1019            
1020             Returns an array of Perl data structures on success
1021             [
1022             {
1023             "id" : "1cRsH7KQTeONMzjSuRJ2aw",
1024             "createdAt" : "2014-04-21T22:28:32Z",
1025             "updatedAt" : "2014-04-21T22:45:32Z",
1026             "appliance" : {
1027             "id" : "2SMROBfiTA6huhV7Drrm1g",
1028             "name" : "television",
1029             "label" : "upstairs TV",
1030             "tags" : ["bedroom_television", "42 inch LED"],
1031             "locationId" : "0qX7nB-8Ry2bxIMTK0EmXw"
1032             },
1033             "start" : "2014-04-21T05:26:10.785Z",
1034             "end" : "2014-04-21T05:36:00.547Z",
1035             "guesses" : {"dryer1" : 0.78, "dishwasher_2014" : 0.12},
1036             "energy" : 247896,
1037             "averagePower" : 122,
1038             "groupIds" : [ "2pMROafiTA6huhV7Drrm1g", "4SmROBfiTA6huhV7Drrm1h" ],
1039             "cycleCount" : 5,
1040             "isRunning" : false
1041             },
1042             ...
1043             ]
1044             Returns 0 on failure
1045            
1046             =cut
1047              
1048             sub fetch_Appliances_Events_by_Location {
1049 0     0 0   my ($self,$location_id,$start,$end,$minPower,$perPage,$page) = @_;
1050            
1051 0           my $url = $self->{'Appliances_Events_url'}."?";
1052            
1053             # if REQUIRED parameter are defined, add them
1054 0 0         if (defined $location_id) {
1055 0           $url = $url . "locationId=$location_id";
1056             }
1057            
1058 0 0         if (defined $start) {
1059 0           $url = $url . "&start=$start";
1060             }
1061 0 0         if (defined $end) {
1062 0           $url = $url . "&end=$end";
1063             }
1064            
1065             # if optional parameters are defined, add them
1066 0 0         if (defined $minPower) {
1067 0           $url = $url . "&minPower=$minPower";
1068             }
1069 0 0         if (defined $perPage) {
1070 0           $url = $url . "&perPage=$perPage";
1071             }
1072 0 0         if (defined $page) {
1073 0           $url = $url . "&page=$page";
1074             }
1075              
1076 0           return $self->__process_get($url);
1077             }
1078              
1079              
1080             ###################################################################################################
1081             =head2 fetch_Appliances_Events_by_Appliance - Fetch events for a specific appliance
1082              
1083             Get appliance events by appliance Id.
1084             An event is an interval when an appliance was in use.
1085            
1086             An applicance_id can be requested by using the NeurioTools::get_appliance_ID
1087             method which returns an appliance ID for a given string name.
1088            
1089             $Neurio->fetch_Appliances_Events_by_Appliance($appliance_id,$start,$end,$perPage,$page);
1090              
1091             This method accepts the following parameters:
1092             - $appliance_id : id of the appliance - Required
1093             - $start : yyyy-mm-ddThh:mm:ssZ - Required
1094             specified using ISO8601 format
1095             - $end : yyyy-mm-ddThh:mm:ssZ - Required
1096             specified using ISO8601 format
1097             - $minpower : Minimum power consumption - Optional
1098             - $perPage : number of results per page - Optional
1099             - $page : page number to return - Optional
1100            
1101             Returns an array of Perl data structures on success
1102             [
1103             {
1104             "id" : "1cRsH7KQTeONMzjSuRJ2aw",
1105             "appliance" : {
1106             "id" : "2SMROBfiTA6huhV7Drrm1g",
1107             "name" : "television",
1108             "label" : "upstairs TV",
1109             "tags" : ["bedroom_television", "42 inch LED"],
1110             "locationId" : "0qX7nB-8Ry2bxIMTK0EmXw"
1111             },
1112             "start" : "2014-04-21T05:26:10.785Z",
1113             "end" : "2014-04-21T05:36:00.547Z",
1114             "guesses" : {"dryer1" : 0.78, "dishwasher_2014" : 0.12},
1115             "energy" : 247896,
1116             "averagePower" : 122,
1117             "groupIds" : [ "2pMROafiTA6huhV7Drrm1g", "4SmROBfiTA6huhV7Drrm1h" ],
1118             "lastCycle": {
1119             "groupId" : "4SmROBfiTA6huhV7Drrm1h",
1120             "start" : "2014-04-21T05:29:00.547Z",
1121             "end" : "2014-04-21T05:36:00.147Z",
1122             "energy" : 41846,
1123             "averagePower" : 122,
1124             "createdAt" : "2014-04-21T05:29:02.547Z",
1125             "updatedAt" : "2014-04-21T05:36:05.147Z",
1126             "sensorId" : "0x0013A00000000000",
1127             "id" : "ALJGM7voQpux5fujXtM2Qw"
1128             },
1129             "cycleCount" : 5,
1130             "status" : "complete",
1131             "isConfirmed" : false,
1132             "precedingEventId": "1cRsH7KQTeONMzjSuRJ2er"
1133             },
1134             ...
1135             ]
1136              
1137             Returns 0 on failure
1138            
1139             =cut
1140              
1141             sub fetch_Appliances_Events_by_Appliance {
1142 0     0 0   my ($self,$appliance_id,$start,$end,$minPower,$perPage,$page) = @_;
1143              
1144 0           my $url = $self->{'Appliances_Events_url'}."?";
1145              
1146             # if REQUIRED parameter are defined, add them
1147 0 0         if (defined $appliance_id) {
1148 0           $url = $url . "applianceId=$appliance_id";
1149             }
1150 0 0         if (defined $start) {
1151 0           $url = $url . "&start=$start";
1152             }
1153 0 0         if (defined $end) {
1154 0           $url = $url . "&end=$end";
1155             }
1156            
1157             # if optional parameters are defined, add them
1158 0 0         if (defined $minPower) {
1159 0           $url = $url . "&minPower=$minPower";
1160             }
1161 0 0         if (defined $perPage) {
1162 0           $url = $url . "&perPage=$perPage";
1163             }
1164 0 0         if (defined $page) {
1165 0           $url = $url . "&page=$page";
1166             }
1167            
1168 0           return $self->__process_get($url);
1169             }
1170              
1171              
1172             ###################################################################################################
1173             =head2 fetch_Appliances_Events_Recent - Fetch events after a spceific time
1174              
1175             Get appliance events created or updated after a specific time.
1176             An event is an interval when an appliance was in use.
1177            
1178             This method accepts the following parameters:
1179             - $location_Id : id of a location - Required
1180             - $since : yyyy-mm-ddThh:mm:ssZ - Required
1181             specified using ISO8601 format
1182             - $minPower : minimum average power - Optional
1183             - $perPage : number of results per page - Optional
1184             - $page : page number to return - Optional
1185            
1186             Returns an array of Perl data structures on success
1187             [
1188             {
1189             "id" : "1cRsH7KQTeONMzjSuRJ2aw",
1190             "appliance" : {
1191             "id" : "2SMROBfiTA6huhV7Drrm1g",
1192             "name" : "television",
1193             "label" : "upstairs TV",
1194             "tags" : ["bedroom_television", "42 inch LED"],
1195             "locationId" : "0qX7nB-8Ry2bxIMTK0EmXw"
1196             },
1197             "start" : "2014-04-21T05:26:10.785Z",
1198             "end" : "2014-04-21T05:36:00.547Z",
1199             "guesses" : {"dryer1" : 0.78, "dishwasher_2014" : 0.12},
1200             "energy" : 247896,
1201             "averagePower" : 122,
1202             "groupIds" : [ "2pMROafiTA6huhV7Drrm1g", "4SmROBfiTA6huhV7Drrm1h" ],
1203             "lastCycle": {
1204             "groupId" : "4SmROBfiTA6huhV7Drrm1h",
1205             "start" : "2014-04-21T05:29:00.547Z",
1206             "end" : "2014-04-21T05:36:00.147Z",
1207             "energy" : 41846,
1208             "averagePower" : 122,
1209             "createdAt" : "2014-04-21T05:29:02.547Z",
1210             "updatedAt" : "2014-04-21T05:36:05.147Z",
1211             "sensorId" : "0x0013A00000000000",
1212             "id" : "ALJGM7voQpux5fujXtM2Qw"
1213             },
1214             "cycleCount" : 5,
1215             "status" : "complete",
1216             "isConfirmed" : false,
1217             "precedingEventId": "1cRsH7KQTeONMzjSuRJ2er"
1218             },
1219             ...
1220             ]
1221             Returns 0 on failure
1222            
1223             =cut
1224              
1225             sub fetch_Appliances_Events_Recent {
1226 0     0 0   my ($self,$location_Id,$since,$minPower,$perPage,$page) = @_;
1227              
1228 0           my $url = $self->{'Appliances_Events_url'}."?";
1229              
1230             # if REQUIRED parameter are defined, add them
1231 0 0         if (defined $location_Id) {
1232 0           $url = $url . "locationId=$location_Id";
1233             }
1234 0 0         if (defined $since) {
1235 0           $url = $url . "&since=$since";
1236             }
1237            
1238             # if optional parameters are defined, add them
1239 0 0         if (defined $minPower) {
1240 0           $url = $url . "&minPower=$minPower";
1241             }
1242 0 0         if (defined $perPage) {
1243 0           $url = $url . "&perPage=$perPage";
1244             }
1245 0 0         if (defined $page) {
1246 0           $url = $url . "&page=$page";
1247             }
1248              
1249 0           return $self->__process_get($url);
1250             }
1251              
1252              
1253             ###################################################################################################
1254             =head2 fetch_Location - Fetch information for a location
1255              
1256             Retrieves information about a particular location.
1257            
1258             $Neurio->fetch_Location($location_id);
1259              
1260             This method accepts the following parameters:
1261             - $location_id : id of a location - Required
1262            
1263             Returns a Perl data structure on success
1264             {
1265             "name": "bob location",
1266             "timezone": "America/Vancouver",
1267             "sensors":
1268             [
1269             {
1270             "sensorId": "0x0000000000000001",
1271             "installCode": "5555",
1272             "sensorType": "neurio",
1273             "locationId": "222ROBfiTA6huhV7Drrrmg",
1274             "channels":
1275             [
1276             {
1277             "sensorId": "0x0000000000000001",
1278             "channel": 1,
1279             "channelType": "phase_a",
1280             "start": "2014-07-21T20:40:39.523Z",
1281             "id": "2221OBfiTA6huhV7Drrrmg"
1282             },
1283             ...
1284             ],
1285             "startTime": "2014-10-01T22:05:17.747Z",
1286             "id": "0x0000000000000001"
1287             },
1288             ...
1289             ],
1290             "energyRate": 0.1,
1291             "createdAt": "2014-10-01T22:05:22.406Z",
1292             "id": "2SMROBfiTA6huhV7Drrrmg"
1293             }
1294             Returns 0 on failure
1295            
1296             =cut
1297              
1298             sub fetch_Location {
1299 0     0 0   my ($self,$location_id) = @_;
1300            
1301             # make sure $location_id is defined
1302 0 0         if (!defined $location_id) {
1303 0           $self->printLOG("\nNeurio->fetch_Location(): \$location_id is a required parameter\n\n");
1304 0           $self->{'last_code'} = '0';
1305 0           $self->{'last_reason'} = 'Neurio->fetch_Location(): \$location_id is a required parameter';
1306 0           return 0;
1307             }
1308 0           my $url = $self->{'Location_url'}."/$location_id";
1309 0           return $self->__process_get($url);
1310             }
1311              
1312              
1313             ###################################################################################################
1314             =head2 fetch_UserLocation - Fetch information for a user's location
1315              
1316             Retrieves information about a location for a particular user.
1317            
1318             $Neurio->fetch_UserLocation($user_id);
1319              
1320             This method accepts the following parameters:
1321             - $user_id : id of a user - Required
1322            
1323             Returns a Perl data structure on success
1324             [
1325             {
1326             "name": "John",
1327             "timezone": "America/Vancouver",
1328             "sensors":
1329             [
1330             {
1331             "sensorId": "0x0000000000000001",
1332             "installCode": "5555",
1333             "sensorType": "neurio",
1334             "locationId": "222ROBfiTA6huhV7Drrrmg",
1335             "channels":
1336             [
1337             {
1338             "sensorId": "0x0000000000000001",
1339             "channel": 1,
1340             "channelType": "phase_a",
1341             "start": "2014-07-21T20:40:39.523Z",
1342             "id": "2221OBfiTA6huhV7Drrrmg"
1343             },
1344             ...
1345             ],
1346             "startTime": "2014-10-01T22:05:17.747Z",
1347             "id": "0x0000000000000001"
1348             },
1349             ...
1350             ],
1351             "energyRate": 0.1,
1352             "createdAt": "2014-10-01T22:05:22.406Z",
1353             "id": "2SMROBfiTA6huhV7Drrrmg"
1354             },
1355             ...
1356             ]
1357             Returns 0 on failure
1358            
1359             =cut
1360              
1361             sub fetch_UserLocation {
1362 0     0 0   my ($self,$user_id) = @_;
1363            
1364             # make sure $user_id is defined
1365 0 0         if (!defined $user_id) {
1366 0           $self->printLOG("\nNeurio->fetch_UserLocation(): \$user_id is a required parameter\n\n");
1367 0           $self->{'last_code'} = '0';
1368 0           $self->{'last_reason'} = 'Neurio->fetch_UserLocation(): \$user_id is a required parameter';
1369 0           return 0;
1370             }
1371 0           my $url = $self->{'Location_url'}."/?$user_id";
1372 0           return $self->__process_get($url);
1373             }
1374              
1375              
1376              
1377              
1378             ###################################################################################################
1379             =head2 fetch_User - Fetch information about a particular user
1380              
1381             Retrieves information about a particular user.
1382            
1383             $Neurio->fetch_User($user_id);
1384              
1385             This method accepts the following parameters:
1386             - $user_id : id of a user - Required
1387            
1388             Returns a Perl data structure on success
1389             {
1390             "id": 123,
1391             "name" : "Bruce Bane",
1392             "email" : "bruce@bane.com",
1393             "status" : "active",
1394             "createdAt" : "2014-04-21T22:28:32Z",
1395             "updatedAt" : "2014-04-21T22:45:32Z",
1396             "locations" : [
1397             {
1398             "id" : "2SMROBfiTA6huhV7Drrm1g",
1399             "name" : "my home",
1400             "timezone" "America/Vancouver",
1401             "sensors" : [
1402             {
1403             "id" : "0qX7nB-8Ry2bxIMTK0EmXw",
1404             "name" : "sensor 1",
1405             "type" : "powerblaster",
1406             "channels" : [
1407             {
1408             "channel" : 1
1409             "channelType" : "phase_a"
1410             },
1411             ...
1412             ]
1413             },
1414             ...
1415             ]
1416             },
1417             ...
1418             ]
1419             }
1420             Returns 0 on failure
1421            
1422             =cut
1423              
1424             sub fetch_User {
1425 0     0 0   my ($self,$user_id) = @_;
1426            
1427             # make sure $user_id is defined
1428 0 0         if (!defined $user_id) {
1429 0           $self->printLOG("\nNeurio->fetch_User(): \$user_id is a required parameter\n\n");
1430 0           $self->{'last_code'} = '0';
1431 0           $self->{'last_reason'} = 'Neurio->fetch_User(): \$user_id is a required parameter';
1432 0           return 0;
1433             }
1434 0           my $url = $self->{'Users_url'}."/$user_id";
1435 0           return $self->__process_get($url);
1436             }
1437              
1438              
1439             ###################################################################################################
1440             =head2 fetch_User_Current - Fetch information about the current user
1441              
1442             Retrieves information about the current user.
1443            
1444             $Neurio->fetch_User_Current();
1445              
1446             This method accepts no parameters:
1447            
1448             Returns a Perl data structure on success
1449             {
1450             "id": 123,
1451             "name" : "Bruce Bane",
1452             "email" : "bruce@bane.com",
1453             "status" : "active",
1454             "createdAt" : "2014-04-21T22:28:32Z",
1455             "updatedAt" : "2014-04-21T22:45:32Z",
1456             "locations" : [
1457             {
1458             "id" : "2SMROBfiTA6huhV7Drrm1g",
1459             "name" : "my home",
1460             "timezone" "America/Vancouver",
1461             "sensors" : [
1462             {
1463             "id" : "0qX7nB-8Ry2bxIMTK0EmXw",
1464             "name" : "sensor 1",
1465             "type" : "powerblaster",
1466             "channels" : [
1467             {
1468             "channel" : 1
1469             "channelType" : "phase_a"
1470             },
1471             ...
1472             ]
1473             },
1474             ...
1475             ]
1476             },
1477             ...
1478             ]
1479             }
1480             Returns 0 on failure
1481            
1482             =cut
1483              
1484             sub fetch_User_Current {
1485 0     0 0   my ($self) = @_;
1486            
1487 0           my $url = $self->{'Users_url'}."/current";
1488 0           return $self->__process_get($url);
1489             }
1490              
1491              
1492              
1493              
1494              
1495              
1496             ###################################################################################################
1497             =head2 fetch_Sensors - Fetch information about all Neurio sensors
1498              
1499             Retrieves information about all Neurio sensors.
1500            
1501             $Neurio->fetch_Sensors($perPage,$page);
1502              
1503             This method accepts the following parameters.
1504             - $perPage : number of results per page - Optional
1505             - $page : page number to return - Optional
1506            
1507             Returns a Perl data structure on success
1508             [
1509             {
1510             "id" : "0x0013A00000000000",
1511             "sensorId" : "0x0013A00000000000",
1512             "email" : "example@example.com",
1513             "installCode" : "26huhV7Drrm1g",
1514             "sensorType" : "powerblaster",
1515             "locationId" : "hSMROBfiTA6huhV7Drrm1h",
1516             "startTime" : "2014-04-21T22:28:32Z",
1517             "endTime" : "2014-04-21T22:45:32Z",
1518             "channels" : [
1519             {
1520             "id" : "4SMROBfiTA6huhV7Drrm1g",
1521             "sensorId" : "2SMROBfiTA6huhV7Drrm1g",
1522             "channel" : 1,
1523             "channelType" : "consumption",
1524             "name" : "channel1",
1525             "start" : "2014-03-21T20:35:32Z",
1526             "end" : "2014-03-21T20:38:32Z",
1527             },...
1528             ]
1529             },...
1530             ]
1531             Returns 0 on failure
1532            
1533             =cut
1534              
1535             sub fetch_Sensors {
1536 0     0 0   my ($self,$perPage,$page) = @_;
1537            
1538 0           my $url = $self->{'Sensors_url'};
1539              
1540             # if optional parameters are defined, add them
1541 0 0         if (defined $perPage) {
1542 0           $url = $url . "?perPage=$perPage";
1543             }
1544 0 0         if (defined $page) {
1545 0           $url = $url . "&page=$page";
1546             }
1547            
1548 0           return $self->__process_get($url);
1549             }
1550              
1551              
1552             ###################################################################################################
1553             =head2 fetch_Sensor - Fetch information about a specific Neurio sensor
1554              
1555             Retrieves information about a specific Neurio sensor.
1556            
1557             $Neurio->fetch_Sensor($sensor_id);
1558              
1559             This method accepts the following parameters.
1560             - $sensor_id : ID of a sensor - Required
1561            
1562             Returns a Perl data structure on success
1563             {
1564             "id" : "0x0013A00000000000",
1565             "sensorId" : "0x0013A00000000000",
1566             "email" : "example@example.com",
1567             "installCode" : "26huhV7Drrm1g",
1568             "sensorType" : "powerblaster",
1569             "locationId" : "hSMROBfiTA6huhV7Drrm1h",
1570             "startTime" : "2014-04-21T22:28:32Z",
1571             "endTime" : "2014-04-21T22:45:32Z",
1572             "channels" : [
1573             {
1574             "id" : "4SMROBfiTA6huhV7Drrm1g",
1575             "sensorId" : "2SMROBfiTA6huhV7Drrm1g",
1576             "channel" : 1,
1577             "channelType" : "consumption",
1578             "name" : "channel1",
1579             "start" : "2014-03-21T20:35:32Z",
1580             "end" : "2014-03-21T20:38:32Z",
1581             },...
1582             ]
1583             }
1584             Returns 0 on failure
1585            
1586             =cut
1587              
1588             sub fetch_Sensor {
1589 0     0 0   my ($self,$sensor_id) = @_;
1590              
1591 0           my $url = $self->{'Sensors_url'}."/";
1592              
1593             # if REQUIRED parameter is defined, add it
1594 0 0         if (defined $sensor_id) {
1595 0           $url = $url . "$sensor_id";
1596             }
1597            
1598 0           return $self->__process_get($url);
1599             }
1600              
1601              
1602              
1603              
1604             ###################################################################################################
1605             =head2 get_version - return the version of the API being used
1606              
1607             Retrieves the version of the API being used.
1608            
1609             $Neurio->get_version();
1610              
1611             This method accepts no parameters:
1612            
1613             Returns a list containing the version and build of the API
1614             Returns 0 on failure
1615            
1616             =cut
1617              
1618             sub get_version {
1619 0     0 0   my $self = shift;
1620 0           my $url = $self->{'base_url'}."/status";
1621 0           my $response = $self->__process_get($url);
1622 0           my ($version,$build) = split('\+build\.',$response->{'apiVersion'});
1623            
1624 0           return ($version,$build);
1625             }
1626              
1627              
1628             ###################################################################################################
1629             =head2 get_uptime - return the uptime of the Neurio Sensor being used
1630              
1631             Retrieves the uptime of the Neurio Sensor being used.
1632            
1633             $Neurio->get_uptime();
1634              
1635             This method accepts no parameters:
1636            
1637             Returns the uptime of the sensor
1638             Returns 0 on failure
1639            
1640             =cut
1641              
1642             sub get_uptime {
1643 0     0 0   my $self = shift;
1644 0           my $url = $self->{'base_url'}."/status";
1645 0           my $response = $self->__process_get($url);
1646            
1647 0           return $response->{'uptime'};
1648             }
1649              
1650              
1651             ###################################################################################################
1652             =head2 dump_Object - shows the contents of the local Neurio object
1653              
1654             shows the contents of the local Neurio object in human readable form
1655              
1656             $Neurio->dump_Object();
1657              
1658             This method accepts no parameters
1659            
1660             Returns nothing
1661            
1662             =cut
1663              
1664             sub dump_Object {
1665 0     0 0   my $self = shift;
1666            
1667 0           $self->printLOG("Key : ".substr($self->{'key'}, 0,120)."\n");
1668 0           $self->printLOG("SecretKey : ".substr($self->{'secret'}, 0,120)."\n");
1669 0           $self->printLOG("Sensor_ID : ".substr($self->{'sensor_id'}, 0,120)."\n");
1670 0           $self->printLOG("Location_ID : ".substr($self->{'location_id'}, 0,120)."\n");
1671 0           $self->printLOG("Access_token : ".substr($self->{'access_token'}, 0,120)."\n");
1672 0           $self->printLOG("Base 64 : ".substr($self->{'base64'}, 0,120)."\n");
1673 0           $self->printLOG("Base URL : ".substr($self->{'base_url'}, 0,120)."\n");
1674 0           $self->printLOG("Samples_Recent_Live URL : ".substr($self->{'Samples_Recent_Live_url'}, 0,120)."\n");
1675 0           $self->printLOG("Samples_Last_Live URL : ".substr($self->{'Samples_Last_Live_url'}, 0,120)."\n");
1676 0           $self->printLOG("Samples URL : ".substr($self->{'Samples_url'}, 0,120)."\n");
1677 0           $self->printLOG("Samples_Full URL : ".substr($self->{'Samples_Full_url'}, 0,120)."\n");
1678 0           $self->printLOG("Stats_Energy URL : ".substr($self->{'Stats_Energy_url'}, 0,120)."\n");
1679 0           $self->printLOG("Appliances URL : ".substr($self->{'Appliances_url'}, 0,120)."\n");
1680 0           $self->printLOG("Appliances_Stats URL : ".substr($self->{'Appliances_Stats_url'}, 0,120)."\n");
1681 0           $self->printLOG("Appliances_Events URL : ".substr($self->{'Appliances_Events_url'}, 0,120)."\n");
1682 0           $self->printLOG("Users URL : ".substr($self->{'Users_url'}, 0,120)."\n");
1683 0           $self->printLOG("Cycles URL : ".substr($self->{'Cycles_url'}, 0,120)."\n");
1684 0           $self->printLOG("Cycles Full URL : ".substr($self->{'Cycles_Full_url'}, 0,120)."\n");
1685 0           $self->printLOG("Cycles Group URL : ".substr($self->{'Cycles_Groups_url'}, 0,120)."\n");
1686 0           $self->printLOG("Edges URL : ".substr($self->{'Edges_url'}, 0,120)."\n");
1687 0           $self->printLOG("Sensors URL : ".substr($self->{'Sensors_url'}, 0,120)."\n");
1688 0           $self->printLOG("Analytics URL : ".substr($self->{'Analytics_url'}, 0,120)."\n");
1689 0           $self->printLOG("debug : ".substr($self->{'debug'}, 0,120)."\n");
1690 0           $self->printLOG("last_code : ".substr($self->{'last_code'}, 0,120)."\n");
1691 0           $self->printLOG("last_reason : ".substr($self->{'last_reason'}, 0,120)."\n");
1692 0           $self->printLOG("last_execution_time : ".substr($self->{'last_exec_time'}, 0,120)."\n");
1693 0           $self->printLOG("rateLimitRemaining : ".substr($self->{'rateLimitRemaining'}, 0,120)."\n");
1694 0           $self->printLOG("rateLimitReset : ".substr($self->{'rateLimitReset'}, 0,120)."\n");
1695 0           $self->printLOG("rateLimitLimit : ".substr($self->{'rateLimitLimit'}, 0,120)."\n");
1696 0           $self->printLOG("contentLength : ".substr($self->{'contentLength'}, 0,120)."\n");
1697              
1698 0           $self->printLOG("\n");
1699             }
1700              
1701             ###################################################################################################
1702             =head2 printLOG - prints to the screen and to a logfile if specified.
1703              
1704             $Neurio->printLOG($string);
1705              
1706             This method accepts the following parameters.
1707             - $string : the string to print - Required
1708            
1709             Returns nothing.
1710            
1711             =cut
1712             sub printLOG{
1713 0     0 0   my $self = shift;
1714 0           my $string = shift;
1715            
1716 0           print $string;
1717            
1718 0 0         if (defined $self->{'$fileHandle'}) { # filehandle defined using $self->debug method
1719 0           my $FH = $self->{'$fileHandle'};
1720 0           print $FH $string;
1721             }
1722             }
1723              
1724              
1725             ###################################################################################################
1726             =head2 get_last_reason - returns the text generated by the most recent fetch
1727              
1728             Returns the HTTP Header reason for the most recent fetch command
1729              
1730             $Neurio->get_last_reason();
1731              
1732             This method accepts no parameters
1733            
1734             Returns the textual reason
1735            
1736             =cut
1737              
1738             sub get_last_reason {
1739 0     0 0   my $self = shift;
1740 0           return $self->{'last_reason'};
1741             }
1742              
1743             ###################################################################################################
1744             =head2 get_last_code - returns the code generated by the most recent fetch
1745              
1746             Returns the HTTP Header code for the most recent fetch command
1747              
1748             $Neurio->get_last_code();
1749              
1750             This method accepts no parameters
1751            
1752             Returns the numeric code
1753            
1754             =cut
1755              
1756             sub get_last_code {
1757 0     0 0   my $self = shift;
1758 0           return $self->{'last_code'};
1759             }
1760              
1761             ###################################################################################################
1762             =head2 get_last_exec_time - returns the execution time for the last fetch
1763              
1764             Returns the number of milliseconds it took for the last fetch call
1765              
1766             $Neurio->get_last_exec_time();
1767              
1768             This method accepts no parameters
1769            
1770             Returns the number of milliseconds
1771            
1772             =cut
1773              
1774             sub get_last_exec_time {
1775 0     0 0   my $self = shift;
1776 0           return $self->{'last_exec_time'};
1777             }
1778              
1779              
1780              
1781              
1782              
1783             ###################################################################################################
1784             ###################################################################################################
1785              
1786             sub __process_get {
1787 0     0     my ($self,$url) = @_;
1788 0           my $time_before = gettimeofday;
1789 0           my $response = $self->{'ua'}->get($url,"Authorization"=>"Bearer ".$self->{'access_token'});
1790 0           my $time_after = gettimeofday;
1791              
1792 0           $self->printLOG(" GET from URL: $url\n");
1793 0           $self->{'last_exec_time'} = eval{($time_after-$time_before)*1000};
  0            
1794 0           $self->{'last_code'} = $response->code;
1795 0           $self->{'rateLimitRemaining'} = $response->header('ratelimit-remaining');
1796 0           $self->{'rateLimitReset'} = $response->header('ratelimit-reset');
1797 0           $self->{'rateLimitLimit'} = $response->header('ratelimit-limit');
1798 0           $self->{'contentLength'} = $response->header('content-length');
1799              
1800 0 0         if ($self->{'debug'}) {$self->printLOG(" Response:".($response->content)."\n");}
  0            
1801 0 0         if ($self->{'debug'}) {$self->printLOG(" Response code:".$response->code."\n\n");}
  0            
1802 0 0         if ($self->{'debug'}) {$self->printLOG(Dumper ($response));}
  0            
1803              
1804 0 0         if ($response->is_success()) {
1805 0           $self->{'last_reason'} = '';
1806 0 0         if ($response->content eq '') { # work around for JSON module which does not handle blank content well
1807 0           return "";
1808             } else {
1809 0           return decode_json($response->content);
1810             }
1811             } else {
1812 0           $self->{'last_reason'} = $response->message;
1813 0 0         if ($self->{'debug'}) {$self->printLOG("\n".(caller(1))[3]."(): Failed with return code ".$self->get_last_code()." - ".$self->get_last_reason()."\n");}
  0            
1814 0           return 0;
1815             }
1816             }
1817              
1818             ###################################################################################################
1819             ###################################################################################################
1820              
1821             sub __process_put {
1822 0     0     my ($self,$url,$params) = @_;
1823 0           my $time_before = gettimeofday;
1824 0           my $encoded = encode_json($params);
1825 0           my $response = $self->{'ua'}->put($url,"Authorization"=>"Bearer ".$self->{'access_token'}, Content_Type => 'application/json', content => $encoded);
1826 0           my $time_after = gettimeofday;
1827              
1828 0           $self->printLOG(" PUT to URL: $url\n");
1829              
1830 0           $self->{'last_exec_time'} = eval{($time_after-$time_before)*1000};
  0            
1831 0           $self->{'last_code'} = $response->code;
1832              
1833 0 0         if ($self->{'debug'}) {$self->printLOG(" Response:".($response->content)."\n");}
  0            
1834 0 0         if ($self->{'debug'}) {$self->printLOG(" Response code:".$response->code."\n\n");}
  0            
1835              
1836 0 0         if ($response->is_success()) {
1837 0           $self->{'last_reason'} = '';
1838 0 0         if ($response->content eq '') { # work around for JSON module which does not handle blank content well
1839 0           return "";
1840             } else {
1841 0           return decode_json($response->content);
1842             }
1843             } else {
1844 0           $self->{'last_reason'} = $response->message;
1845 0 0         if ($self->{'debug'}) {$self->printLOG("\n".(caller(1))[3]."(): Failed with return code ".$self->get_last_code()." - ".$self->get_last_reason()."\n");}
  0            
1846 0           return 0;
1847             }
1848             }
1849              
1850             ###################################################################################################
1851             ###################################################################################################
1852              
1853             sub __process_post {
1854 0     0     my ($self,$url,$params) = @_;
1855 0           my $time_before = gettimeofday;
1856 0           my $encoded = encode_json($params);
1857 0           my $response = $self->{'ua'}->post($url,"Authorization"=>"Bearer ".$self->{'access_token'}, Content_Type => 'application/json', content => $encoded);
1858 0           my $time_after = gettimeofday;
1859              
1860 0           $self->printLOG(" POSTed to URL: $url\n");
1861              
1862 0           $self->{'last_exec_time'} = eval{($time_after-$time_before)*1000};
  0            
1863 0           $self->{'last_code'} = $response->code;
1864              
1865 0 0         if ($self->{'debug'}) {$self->printLOG(" Response:".($response->content)."\n");}
  0            
1866 0 0         if ($self->{'debug'}) {$self->printLOG(" Response code:".$response->code."\n\n");}
  0            
1867              
1868 0 0         if ($response->is_success()) {
1869 0           $self->{'last_reason'} = '';
1870 0 0         if ($response->content eq '') { # work around for JSON module which does not handle blank content well
1871 0           return "";
1872             } else {
1873 0           return decode_json($response->content);
1874             }
1875             } else {
1876 0           $self->{'last_reason'} = $response->message;
1877 0 0         if ($self->{'debug'}) {$self->printLOG("\n".(caller(1))[3]."(): Failed with return code ".$self->get_last_code()." - ".$self->get_last_reason()."\n");}
  0            
1878 0           return 0;
1879             }
1880             }
1881              
1882             ###################################################################################################
1883             ###################################################################################################
1884              
1885             sub __process_patch {
1886 0     0     my ($self,$url,$params) = @_;
1887 0           my $time_before = gettimeofday;
1888 0           my $encoded = encode_json($params);
1889 0           my $request = HTTP::Request->new(PATCH => $url);
1890 0           $request->content($encoded);
1891 0           $request->header('Authorization' => "Bearer ".$self->{'access_token'});
1892 0           $request->header('Content_Type' => "application/json");
1893 0           my $response = $self->{'ua'}->request($request);
1894 0           my $time_after = gettimeofday;
1895              
1896 0           $self->printLOG(" PATCHed URL: $url\n");
1897              
1898 0           $self->{'last_exec_time'} = eval{($time_after-$time_before)*1000};
  0            
1899 0           $self->{'last_code'} = $response->code;
1900              
1901 0 0         if ($self->{'debug'}) {$self->printLOG(" Response:".($response->content)."\n");}
  0            
1902 0 0         if ($self->{'debug'}) {$self->printLOG(" Response code:".$response->code."\n\n");}
  0            
1903              
1904 0 0         if ($response->is_success()) {
1905 0           $self->{'last_reason'} = '';
1906 0 0         if ($response->content eq '') { # work around for JSON module which does not handle blank content well
1907 0           return "";
1908             } else {
1909 0           return decode_json($response->content);
1910             }
1911             } else {
1912 0           $self->{'last_reason'} = $response->message;
1913 0 0         if ($self->{'debug'}) {$self->printLOG("\n".(caller(1))[3]."(): Failed with return code ".$self->get_last_code()." - ".$self->get_last_reason()."\n");}
  0            
1914 0           return 0;
1915             }
1916             }
1917              
1918             ###################################################################################################
1919             ###################################################################################################
1920              
1921             sub __process_delete {
1922 0     0     my ($self,$url,$params) = @_;
1923 0           my $time_before = gettimeofday;
1924 0 0         if (!defined $params) {
1925 0           $params = {};
1926             }
1927 0           my $encoded = encode_json($params);
1928 0           my $response = $self->{'ua'}->delete($url,"Authorization"=>"Bearer ".$self->{'access_token'}, Content_Type => 'application/json', content => $encoded);
1929 0           my $time_after = gettimeofday;
1930              
1931 0           $self->printLOG(" DELETEd from URL: $url\n");
1932              
1933 0           $self->{'last_exec_time'} = eval{($time_after-$time_before)*1000};
  0            
1934 0           $self->{'last_code'} = $response->code;
1935              
1936 0 0         if ($self->{'debug'}) {$self->printLOG(" Response:".($response->content)."\n");}
  0            
1937 0 0         if ($self->{'debug'}) {$self->printLOG(" Response code:".$response->code."\n");}
  0            
1938            
1939 0 0         if ($response->is_success()) {
1940 0           $self->{'last_reason'} = '';
1941 0 0         if ($response->content eq '') { # work around for JSON module which does not handle blank content well
1942 0           return "";
1943             } else {
1944 0           return decode_json($response->content);
1945             }
1946             } else {
1947 0           $self->{'last_reason'} = $response->message;
1948 0 0         if ($self->{'debug'}) {$self->printLOG("\n".(caller(1))[3]."(): Failed with return code ".$self->get_last_code()." - ".$self->get_last_reason()."\n");}
  0            
1949 0           return 0;
1950             }
1951            
1952             }
1953              
1954             ###################################################################################################
1955             =head1 AUTHOR
1956              
1957             Kedar Warriner, C
1958              
1959             =head1 BUGS
1960              
1961             Please report any bugs or feature requests to C
1962             or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Device-Neurio
1963             I will be notified, and then you'll automatically be notified of progress on
1964             your bug as I make changes.
1965              
1966             =head1 SUPPORT
1967              
1968             You can find documentation for this module with the perldoc command.
1969              
1970             perldoc Device::Neurio
1971              
1972             You can also look for information at:
1973              
1974             =over 5
1975              
1976             =item * RT: CPAN's request tracker
1977              
1978             L
1979              
1980             =item * AnnoCPAN: Annotated CPAN documentation
1981              
1982             L
1983              
1984             =item * CPAN Ratings
1985              
1986             L
1987              
1988             =item * Search CPAN
1989              
1990             L
1991              
1992             =back
1993              
1994             =head1 ACKNOWLEDGEMENTS
1995              
1996             Many thanks to:
1997             The guys at Energy Aware Technologies for creating the Neurio sensor and
1998             developping the API.
1999             Everyone involved with CPAN.
2000              
2001             =head1 LICENSE AND COPYRIGHT
2002              
2003             Copyright 2014 Kedar Warriner .
2004              
2005             This program is free software; you can redistribute it and/or modify it
2006             under the terms of either: the GNU General Public License as published
2007             by the Free Software Foundation; or the Artistic License.
2008              
2009             See http://dev.perl.org/licenses/ for more information.
2010              
2011             =cut
2012              
2013             #******************************************************************************
2014             1; # End of Device::Neurio - Return success to require/use statement
2015             #******************************************************************************
2016              
2017