File Coverage

blib/lib/Power/Outlet/Shelly.pm
Criterion Covered Total %
statement 20 44 45.4
branch 4 22 18.1
condition n/a
subroutine 8 16 50.0
pod 7 7 100.0
total 39 89 43.8


line stmt bran cond sub pod time code
1             package Power::Outlet::Shelly;
2 1     1   82249 use strict;
  1         9  
  1         25  
3 1     1   4 use warnings;
  1         2  
  1         23  
4 1     1   4 use base qw{Power::Outlet::Common::IP::HTTP::JSON};
  1         1  
  1         374  
5              
6             our $VERSION = '0.48';
7              
8             =head1 NAME
9              
10             Power::Outlet::Shelly - Control and query a Shelly GIPO Relay with HTTP REST API
11              
12             =head1 SYNOPSIS
13              
14             my $outlet = Power::Outlet::Shelly->new(host=>"shelly", index=>0);
15             print $outlet->query, "\n";
16             print $outlet->on, "\n";
17             print $outlet->off, "\n";
18             print $outlet->switch, "\n";
19             print $outlet->cycle, "\n";
20              
21             =head1 DESCRIPTION
22              
23             Power::Outlet::Shelly is a package for controlling and querying a relay index on Shelly hardware.
24              
25             From: L
26              
27             Commands can be executed via web (HTTP) requests, for example:
28              
29             http:///relay/0?turn=on
30             http:///relay/0?turn=off
31             http:///relay/0?turn=toggle
32             http:///relay/0?timer=5
33              
34             =head1 USAGE
35              
36             use Power::Outlet::Shelly;
37             my $outlet = Power::Outlet::Shelly->new(host=>"sw-kitchen", style=>"relay", index=>0);
38             print $outlet->on, "\n";
39              
40             Command Line
41              
42             $ power-outlet Shelly ON host sw-kitchen style relay index 0
43              
44             Command Line (from settings)
45              
46             $ cat /etc/power-outlet.ini
47              
48             [Kitchen]
49             type=Shelly
50             name=Kitchen
51             host=sw-kitchen
52             style=relay
53             index=0
54             groups=Inside Lights
55             groups=Main Floor
56              
57              
58             $ power-outlet Config ON section Kitchen
59             $ curl http://127.0.0.1/cgi-bin/power-outlet-json.cgi?name=Kitchen;action=ON
60              
61             =head1 CONSTRUCTOR
62              
63             =head2 new
64              
65             my $outlet = Power::Outlet->new(type=>"Shelly", host=>"shelly", index=>0);
66             my $outlet = Power::Outlet::Shelly->new(host=>"shelly", index=>0);
67              
68             =head1 PROPERTIES
69              
70             =head2 style
71              
72             Set the style to support "relay" (1, 1L, 2.5, 4, Plug, Uni, EM, 3EM), "light" (Dimmer, Bulb, Vintage, Duo), "color" (RGB Color), or "white" (RGB White)
73              
74             my $style = $outlet->style;
75             my $style = $outlet->style('light');
76              
77             default: relay
78              
79             =cut
80              
81             sub style {
82 1     1 1 3023 my $self = shift;
83 1 50       5 $self->{'style'} = shift if @_;
84 1 50       4 $self->{'style'} = $self->_style_default unless defined $self->{'style'};
85 1         4 return $self->{'style'};
86             }
87              
88 1     1   4 sub _style_default {'relay'};
89              
90             =head2 index
91              
92             Shelly hardware supports zero or more relay indexes starting at 0.
93              
94             Default: 0
95              
96             =cut
97              
98             sub index {
99 1     1 1 3 my $self = shift;
100 1 50       4 $self->{'index'} = shift if @_;
101 1 50       4 $self->{'index'} = $self->_index_default unless defined $self->{'index'};
102 1         3 return $self->{'index'};
103             }
104              
105 1     1   2 sub _index_default {0};
106              
107             =head2 host
108              
109             Sets and returns the hostname or IP address.
110              
111             Default: shelly
112              
113             =cut
114              
115 0     0   0 sub _host_default {'shelly'};
116              
117             =head2 port
118              
119             Sets and returns the port number.
120              
121             Default: 80
122              
123             =cut
124              
125 1     1   3 sub _port_default {'80'};
126              
127             #override Power::Outlet::Common::IP->_port_default
128              
129             =head1 METHODS
130              
131             =head2 name
132              
133             =cut
134              
135             #GET /settings/relay/{index} -> $return->{'name'}
136              
137             sub _name_default {
138 0     0     my $self = shift;
139 0           return $self->_call('/settings')->{'name'};
140             }
141              
142             =head2 query
143              
144             Sends an HTTP message to the device to query the current state
145              
146             =cut
147              
148             sub query {
149 0     0 1   my $self = shift;
150 0 0         return $self->_call('')->{'ison'} ? 'ON' : 'OFF';
151             }
152              
153             =head2 on
154              
155             Sends a message to the device to Turn Power ON
156              
157             =cut
158              
159             sub on {
160 0     0 1   my $self = shift;
161 0 0         return $self->_call('', turn => 'on')->{'ison'} ? 'ON' : 'OFF';
162             }
163              
164             =head2 off
165              
166             Sends a message to the device to Turn Power OFF
167              
168             =cut
169              
170             sub off {
171 0     0 1   my $self = shift;
172 0 0         return $self->_call('', turn => 'off')->{'ison'} ? 'ON' : 'OFF';
173             }
174              
175             =head2 switch
176              
177             Sends a message to the device to toggle the power
178              
179             =cut
180              
181             #override Power::Outlet::Common->switch
182              
183             sub switch {
184 0     0 1   my $self = shift;
185 0 0         return $self->_call('', turn => 'toggle')->{'ison'} ? 'ON' : 'OFF';
186             }
187              
188             =head2 cycle
189              
190             Sends messages to the device to Cycle Power (ON-OFF-ON or OFF-ON-OFF).
191              
192             =cut
193              
194             #override Power::Outlet::Common->cycle
195              
196             sub cycle {
197 0     0 1   my $self = shift;
198 0           my $cycle_duration = $self->cycle_duration; #from Power::Outlet::Common
199 0           my $hash = $self->_call('', timer => $cycle_duration);
200             return $hash->{'timer_started'} > 0 ? 'CYCLE' #is this the correct logic?
201 0 0         : $hash->{'ison'} ? 'ON'
    0          
202             : 'OFF';
203             }
204              
205             =head2 cycle_duration
206              
207             Default; 10 seconds (floating point number)
208              
209             =cut
210              
211             sub _call {
212 0     0     my $self = shift;
213 0           my $settings = shift;
214 0           my %param = @_;
215             #http:///settings/relay/0
216             #http:///relay/0?turn=on
217             #http:///relay/0?timer=10
218 0           $self->http_path(sprintf('%s/%s/%s', $settings, $self->style, $self->index));
219 0           my $url = $self->url(undef); #isa URI from Power::Outlet::Common::IP::HTTP
220 0           $url->query_form(%param);
221 0           my $hash = $self->json_request(GET => $url); #isa HASH
222              
223 0 0         die('Error: Method _call failed to return expected JSON format') unless ref($hash) eq 'HASH';
224 0           return $hash;
225             }
226              
227             =head1 BUGS
228              
229             Please log on RT and send an email to the author.
230              
231             =head1 SUPPORT
232              
233             DavisNetworks.com supports all Perl applications including this package.
234              
235             =head1 AUTHOR
236              
237             Michael R. Davis
238             CPAN ID: MRDVT
239             DavisNetworks.com
240              
241             =head1 COPYRIGHT
242              
243             Copyright (c) 2020 Michael R. Davis
244              
245             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
246              
247             The full text of the license can be found in the LICENSE file included with this module.
248              
249             =head1 SEE ALSO
250              
251             L
252              
253             =cut
254              
255             1;