File Coverage

blib/lib/LightWaveRF.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package LightWaveRF;
2              
3             =head1 NAME
4            
5             LightWaveRF - Integration with LightWaveRF modules
6            
7             =head1 SYNOPSIS
8            
9             use LightWaveRF;
10             my $lw = new LightWaveRF;
11             $lw->register('D1', 'R1', "LivingRoom");
12             $lw->on('LivingRoom');
13            
14             =head1 DESCRIPTION
15            
16             Provides an interface to LightWaveRF modules via the LightWaveRF Wifi Link.
17              
18             =cut
19              
20             =head2 Methods
21              
22             =head3 new
23              
24             my $lf = new LightWaveRF;
25              
26             Instantiates a LightWaveRF object ready to register devices against.
27              
28             =cut
29              
30              
31 2     2   39467 use Moose;
  0            
  0            
32             use IO::Socket::INET;
33             use IO::Select;
34              
35             our $VERSION = 0.04;
36              
37             has '_devices' => (is => 'rw', default => sub{{}});
38             has '_current_msg_id' => (is => 'rw', default => 0 );
39             has '_port' => (is => 'ro', default => 9760);
40              
41             =head3 register
42              
43             $lw->register(<NODE ID>, <DEVICE ID>, <NAME>);
44             $lw->register('R1', 'LivingRoomLight');
45              
46             =cut
47             sub register {
48             my ( $self, $node_id, $device_id, $name ) = @_;
49            
50             $self->_devices->{$name} = {node => $node_id, id => $device_id};
51             }
52              
53             =head3 on
54            
55             $lw->on('LivingRoomLight'); # $lw->send_device_status('LivingRoomlight', 'F1');
56              
57             =cut
58             sub on {
59             my ( $self, $name ) = @_;
60             return $self->send_device_status($name, 'F1');
61             }
62              
63             =head3 off
64            
65             $lw->on('LivingRoomLight'); # $lw->send_device_status('LivingRoomlight', 'F0');
66              
67             =cut
68             sub off {
69             my ( $self, $name ) = @_;
70             return $self->send_device_status($name, 'F0');
71             }
72              
73              
74             =head3 send_device_status
75              
76             $lw->send_device_status('LivingRoomlight', 'F1');
77              
78             =cut
79             sub send_device_status {
80             my ( $self, $name, $status ) = @_;
81             my $device = $self->_devices->{$name};
82              
83             return undef unless $device;
84              
85             $self->_send_status($device->{'node'}, $device->{'id'}, $status);
86              
87             return 1;
88             }
89              
90             sub get_next_msg_id {
91             my $self = shift;
92              
93             $self->_current_msg_id(0) if($self->_current_msg_id) >= 999;
94             my $msg_id = $self->_current_msg_id($self->_current_msg_id+1);
95             return $msg_id;
96             }
97              
98             #Broadcast a status.
99             sub _send_status {
100             my ( $self, $node, $device_id, $status ) = @_;
101              
102             my $broadcast_string = sprintf("%03d", $self->get_next_msg_id ). ",!$device_id$node$status|";
103              
104             my $sock = IO::Socket::INET->new(
105             PeerPort => $self->_port,
106             PeerAddr => inet_ntoa(INADDR_BROADCAST),
107             Proto => 'udp',
108             Broadcast => 1 )
109             or die "Can't bind : $@\n";
110              
111             $sock->send($broadcast_string);
112             }
113              
114             =head2 get_kwh
115              
116             returns the current wattage from the power meter
117              
118             =cut
119             sub get_kwh {
120             #This routine is horrible and completely needs refactoring
121             my $self = shift;
122              
123              
124             my $sel = IO::Select->new;
125             my $in_sock = IO::Socket::INET -> new (LocalPort => 9761,
126             Broadcast => 1,
127             Proto => 'udp')
128             or die "Failed to bind to socket: $@";
129              
130             $sel->add($in_sock);
131             my $timeout = 2;
132             my $mess;
133              
134              
135             my $sock = IO::Socket::INET->new(
136             PeerPort => $self->_port,
137             PeerAddr => inet_ntoa(INADDR_BROADCAST),
138             Proto => 'udp',
139             Broadcast => 1 )
140             or die "Can't bind : $@\n";
141              
142             $sock->send("@?W|EcoQuery");
143              
144              
145             while (1) {
146             my @r = $sel->can_read($timeout);
147             unless (@r) { last; } #Tiemout
148             $in_sock -> recv ($mess, 1024);
149             last;
150             }
151              
152             return unless($mess);
153             $mess =~ /W=(\d*)\,(\d*)\,(\d*),(\d*)/;
154             my $watts = $1;
155              
156             return $watts/1000;
157              
158             }
159              
160              
161             =head1 AUTHOR
162             Graeme Lawton <graeme@per.ly>
163             =cut
164              
165             =head2 Development
166              
167             This module is very much under development and not really production ready yet
168             and there is lots of functinality still to be added to it. Patches welcome git
169             repo is at https://github.com/grim8634/LightWaveRF.git
170              
171             =cut
172             1;