File Coverage

blib/lib/Device/RFXCOM/Base.pm
Criterion Covered Total %
statement 94 94 100.0
branch 23 24 95.8
condition n/a
subroutine 23 23 100.0
pod 3 3 100.0
total 143 144 99.3


line stmt bran cond sub pod time code
1 5     5   29 use strict;
  5         9  
  5         180  
2 5     5   25 use warnings;
  5         9  
  5         205  
3             package Device::RFXCOM::Base;
4             $Device::RFXCOM::Base::VERSION = '1.142010';
5             # ABSTRACT: module for RFXCOM device base class
6              
7              
8 5     5   66 use 5.006;
  5         15  
  5         245  
9             use constant {
10 5         265 DEBUG => $ENV{DEVICE_RFXCOM_BASE_DEBUG},
11             TESTING => $ENV{DEVICE_RFXCOM_TESTING},
12 5     5   30 };
  5         7  
13 5     5   93 use Carp qw/croak/;
  5         9  
  5         280  
14 5     5   2116 use IO::Handle;
  5         17038  
  5         225  
15 5     5   4540 use IO::Select;
  5         8903  
  5         290  
16 5     5   4789 use Time::HiRes;
  5         9270  
  5         24  
17 5     5   582 use Symbol qw/gensym/;
  5         10  
  5         464  
18 5     5   5730 use Device::SerialPort qw( :PARAM :STAT 0.07 );
  5         112895  
  5         1437  
19 5     5   63 use Fcntl;
  5         12  
  5         6507  
20              
21             sub _new {
22 12     12   83 my ($pkg, %p) = @_;
23 12         171 my $self = bless
24             {
25             baud => 4800,
26             port => 10001,
27             discard_timeout => 0.03,
28             ack_timeout => 2,
29             dup_timeout => 0.5,
30             _q => [],
31             _buf => '',
32             _last_read => 0,
33             init_callback => undef,
34             %p,
35             }, $pkg;
36 12 100       131 $self->{plugins} = [$self->plugins()] unless ($self->{plugins});
37 12         315 $self->_open();
38 6         49 $self->_init();
39 6         199 $self;
40             }
41              
42             sub DESTROY {
43 12     12   8565 my $self = shift;
44 12         801 delete $self->{init};
45             }
46              
47              
48             sub queue {
49 1     1 1 775 scalar @{$_[0]->{_q}};
  1         8  
50             }
51              
52              
53             sub _write {
54 22     22   32 my $self = shift;
55 22         73 my %p = @_;
56 22 100       107 $p{raw} = pack 'H*', $p{hex} unless (exists $p{raw});
57 22 100       71 $p{hex} = unpack 'H*', $p{raw} unless (exists $p{hex});
58 22         22 print STDERR "Queued: ", $p{hex}, ' ', ($p{desc}||''), "\n" if DEBUG;
59 22         15 push @{$self->{_q}}, \%p;
  22         52  
60 22 100       73 $self->_write_now unless ($self->{_waiting});
61 22         58 1;
62             }
63              
64             sub _write_now {
65 28     28   43 my $self = shift;
66 28         31 my $rec = shift @{$self->{_q}};
  28         62  
67 28         41 my $wait_record = $self->{_waiting};
68 28 100       60 if ($wait_record) {
69 19         39 delete $self->{_waiting};
70 19         32 my $cb = $wait_record->[1]->{callback};
71 19 100       49 $cb->() if ($cb);
72             }
73 28 100       85 return unless (defined $rec);
74 19         60 $self->_real_write($rec);
75 19         57 $self->{_waiting} = [ $self->_time_now, $rec ];
76             }
77              
78             sub _real_write {
79 19     19   27 my ($self, $rec) = @_;
80 19         22 print STDERR "Sending: ", $rec->{hex}, ' ', ($rec->{desc}||''), "\n" if DEBUG;
81 19         487 syswrite $self->{fh}, $rec->{raw}, length $rec->{raw};
82             }
83              
84              
85             sub filehandle {
86 26     26 1 2313 shift->{fh}
87             }
88              
89             sub _open {
90 11     11   24 my $self = shift;
91 11 100       130 $self->{device} =~ m![/\\]! ?
92             $self->_open_serial_port(@_) : $self->_open_tcp_port(@_)
93             }
94              
95             sub _open_tcp_port {
96 9     9   50 my $self = shift;
97 9         1163 my $dev = $self->{device};
98 9         20 print STDERR "Opening $dev as tcp socket\n" if DEBUG;
99 9         3180 require IO::Socket::INET; import IO::Socket::INET;
  9         40174  
100 9 100       7649 $dev .= ':'.$self->{port} unless ($dev =~ /:/);
101 9 100       92 my $fh = IO::Socket::INET->new($dev) or
102             croak "TCP connect to '$dev' failed: $!";
103 4         1952 return $self->{fh} = $fh;
104             }
105              
106             sub _open_serial_port {
107 2     2   4 my $self = shift;
108 2         5 my $dev = $self->{device};
109 2         2 print STDERR "Opening $dev as serial port\n" if DEBUG;
110 2         12 my $fh = gensym();
111 2 50       46 my $sport = tie (*$fh, 'Device::SerialPort', $dev) or
112             croak "Could not tie serial port, $dev, to file handle: $!";
113 2         33 $sport->baudrate($self->baud);
114 2         20 $sport->databits(8);
115 2         18 $sport->parity("none");
116 2         16 $sport->stopbits(1);
117 2         16 $sport->datatype("raw");
118 2         17 $sport->write_settings();
119              
120 2 100       353 sysopen $fh, $dev, O_RDWR|O_NOCTTY|O_NDELAY or
121             croak "sysopen of '$dev' failed: $!";
122 1         11 $fh->autoflush(1);
123 1         49 binmode($fh);
124 1         7 return $self->{fh} = $fh;
125             }
126              
127              
128             sub baud {
129 3     3 1 27 shift->{baud}
130             }
131              
132             sub _time_now {
133 132     132   1051 Time::HiRes::time
134             }
135              
136             1;
137              
138             __END__