File Coverage

blib/lib/NETIOM.pm
Criterion Covered Total %
statement 18 112 16.0
branch 0 20 0.0
condition 0 3 0.0
subroutine 6 27 22.2
pod 0 18 0.0
total 24 180 13.3


line stmt bran cond sub pod time code
1             # $Id: $
2              
3             package NETIOM;
4              
5 1     1   925 use 5.008003;
  1         4  
  1         39  
6              
7 1     1   6 use strict;
  1         2  
  1         34  
8 1     1   14 use warnings;
  1         2  
  1         33  
9              
10 1     1   866 use YAML;
  1         8684  
  1         67  
11 1     1   1046 use LWP::Simple;
  1         1422387  
  1         11  
12              
13 1     1   420 use Carp;
  1         2  
  1         1558  
14              
15             # use Data::Dumper;
16              
17             our $VERSION = '0.10';
18              
19             sub new {
20              
21 0     0 0   my $class = shift;
22 0           my $unit_name = shift;
23              
24 0           my $self;
25              
26 0           $self->{unit_name} = $unit_name;
27 0           $self->{unit_uri} = "http://$unit_name/client.cgi";
28              
29 0 0         if ( _get_set_unit_state($self) ) {
30              
31 0           return bless $self, $class;
32              
33             }
34             else {
35 0           croak "Could not determine state of NET-IOM unit at $unit_name.";
36             }
37             }
38              
39             sub update_state {
40 0     0 0   my $self = shift;
41            
42 0           $self->_get_set_unit_state();
43            
44             }
45              
46             sub get_output {
47 0     0 0   my $self = shift;
48              
49 0           return split //, $self->get_output_bitmap();
50             }
51              
52             sub set_output {
53 0     0 0   my $self = shift;
54 0           my @bitarray = @_;
55              
56 0 0         if ( scalar @bitarray != 16 ) {
57 0           croak "You must supply 16 bits.";
58             }
59              
60 0           my $bit_n = 1;
61 0           foreach my $bit (@bitarray) {
62 0           $self->set_output_bit( $bit_n++, $bit );
63             }
64              
65 0           return $self->get_output();
66             }
67              
68             sub get_output_bitmap {
69 0     0 0   my $self = shift;
70              
71 0           return $self->{state}{digital}{output}{bitmap};
72              
73             }
74              
75             sub set_output_bitmap {
76 0     0 0   my $self = shift;
77 0           my $bitstring = shift;
78              
79 0           return join '', $self->set_output( split //, $bitstring );
80              
81             }
82              
83             sub get_output_bitmap_int {
84 0     0 0   my $self = shift;
85              
86 0           return _netiom_output_to_int( $self->get_output_bitmap() );
87              
88             }
89              
90             sub set_output_bitmap_int {
91 0     0 0   my $self = shift;
92              
93 0           croak "Not implemented.";
94              
95             }
96              
97             sub get_output_bit {
98 0     0 0   my $self = shift;
99 0           my $output = shift;
100              
101 0           my @output_array = split //, $self->get_output_bitmap();
102              
103 0 0         if ($output) {
104 0           return $output_array[ $output - 1 ];
105             }
106             else {
107 0           return @output_array;
108             }
109             }
110              
111             sub set_output_bit {
112 0     0 0   my $self = shift;
113 0           my $output = shift;
114 0           my $set_to_state = shift;
115              
116 0           my $action;
117 0 0         if ($set_to_state) {
118 0           $set_to_state = 1;
119 0           $action = 'A';
120             }
121             else {
122 0           $set_to_state = 0;
123 0           $action = 'B';
124             }
125              
126 0           $output = sprintf( "%02d", $output );
127              
128 0           my $params = "$action$output=$set_to_state";
129              
130 0           $self->_get_set_unit_state($params);
131              
132 0           return $self->get_output_bit($output);
133             }
134              
135             sub get_input_bitmap {
136 0     0 0   my $self = shift;
137              
138 0           return $self->{state}{digital}{input}{bitmap};
139              
140             }
141              
142             sub get_input_bitmap_int {
143 0     0 0   my $self = shift;
144              
145 0           return _netiom_output_to_int( $self->get_input_bitmap() );
146              
147             }
148              
149             sub get_input {
150 0     0 0   my $self = shift;
151              
152 0           return split //, $self->get_input_bitmap();
153              
154             }
155              
156             sub get_input_bit {
157 0     0 0   my $self = shift;
158 0           my $input = shift;
159              
160 0           return ( $self->get_input() )[ $input - 1 ];
161              
162             }
163              
164             sub get_analogue_input {
165 0     0 0   my $self = shift;
166 0           my $input_no = shift;
167              
168 0 0 0       if ( !$input_no ) {
    0          
169             return (
170 0           $self->get_analogue_input(1), $self->get_analogue_input(2),
171             $self->get_analogue_input(3), $self->get_analogue_input(4),
172             );
173             }
174             elsif ( $input_no < 1 or $input_no > 4 ) {
175 0           croak('Analogue inputs numbers are 1 through 4 only.');
176             }
177             else {
178 0           return $self->{state}{analogue}{input}{$input_no};
179             }
180             }
181              
182             sub get_serial {
183 0     0 0   my $self = shift;
184              
185 0           return $self->{state}{serial}{input}{text};
186             }
187              
188             sub set_serial {
189 0     0 0   my $self = shift;
190              
191 0           croak "Not implemented.";
192             }
193              
194             sub get_unit_name {
195 0     0 0   my $self = shift;
196              
197 0           return $self->{unit_name};
198             }
199              
200             sub _get_set_unit_state {
201              
202 0     0     my $self = shift;
203 0           my $param_string = shift;
204              
205 0           my $uri = $self->{unit_uri};
206 0 0         if ($param_string) {
207 0           $uri .= "?$param_string";
208             }
209              
210 0           for ( 1 .. 5 ) { # Try to get a response up to 5 times.
211              
212 0 0         if ( my $state = _process_client_yaml( get($uri) ) ) {
213              
214 0           $self->{state} = $state;
215            
216 0           return 1;
217            
218             }
219             }
220            
221 0           croak "Did not get response from NET-IOM unit $self->{unit_name} when getting/setting state.";
222              
223             }
224              
225             # Turns a string from the net-iom device representing the current output
226             # into an integer with those bits set
227             sub _netiom_output_to_int {
228              
229 0     0     my $bitstring = shift;
230              
231             # We reverse the string, as NET-IOM sends it with LSB first, then we
232             # pack() to turn 16 bytes (each byte is either ascii '0' or '1') into a
233             # 2 byte wide bitstring, and then use vec() to convert that bitstring
234             # into a normal integer.
235 0           return vec( pack( "B16", scalar( reverse($bitstring) ) ), 0, 16 );
236             }
237              
238             sub _process_client_yaml {
239              
240 0     0     my $yaml = shift;
241              
242 0 0         if ( !$yaml ) {
243 0           return;
244             }
245              
246 0           my $netiom_state;
247              
248 0           $yaml =~ s/\n\.\.\..*/\n/sg;
249 0           $yaml =~ s/\000//sg;
250              
251 0           eval { $netiom_state = Load($yaml); };
  0            
252 0 0         if ($@) {
253 0           warn "$@\n";
254 0           warn "$yaml\n";
255 0           return;
256             }
257              
258             # warn Dumper $data;
259              
260 0           return $netiom_state;
261             }
262              
263             1;
264              
265             =encoding utf8
266              
267             =head1 NAME
268              
269             NETIOM - Interact with NETIOMâ„¢ devices.
270              
271             =head1 SYNOPSIS
272              
273             use NETIOM;
274              
275             =head1 DESCRIPTION
276              
277             NETIOM is a stand alone WEB server capable of monitoring 16 digital and
278             4 analogue inputs. It can also control 16 digital outputs.
279              
280             =head1 AUTHOR
281              
282             Adam Clarke
283              
284             =head1 COPYRIGHT
285              
286             Copyright (c) 2010. Adam Clarke.
287              
288             This program is free software; you can redistribute it and/or modify it
289             under the same terms as Perl itself.
290              
291             See http://www.perl.com/perl/misc/Artistic.html
292              
293             =cut
294