package emeter_lib; # emeter_lib is a library for reading information # out of the e-meter use IO::Socket; use IO::Select; use Fcntl; sub new { my $type = shift; my $self = {}; bless($self, $type); } sub fork { # this function forks off the communications thread # it takes one argument, a comm handler to the dash # it creates a unix domain socket in /tmp # to handle receiving input my $self = shift; my $ob = shift; my $mainsock; my $select; my $sock; my %map; my $cmd; my %update; $map{"time"} = 0; $map{"kwhrs"} = 1; $map{"amps"} = 2; $map{"volts"} = 3; $map{"ahrs"} = 4; $map{"peukert_amps"} = 5; $map{"time_remaining"} = 6; $map{"bar_graph_state"} = 7; $map{"temp"} = 8; $map{"raw"} = 9; $map{"len"} = 10; my @chan = (0,0,0,0,0,0); if(fork()) { return; } else { # we are the child thread # we basically run in circles, screaming # and shouting # we write the dash, and poll the # tcp socket for updates $SIG{CHLD} = IGNORE; $SIG{INT} = IGNORE; $mainsock = IO::Socket::INET->new(Listen => 5, LocalPort => 6557, Proto => 'tcp', ReuseAddr=> 1, ); die "Failed to open port 6557 (already running?)" if(!$mainsock); $select = new IO::Select(); close(STDIN); close(STDOUT); close(STDERR); $select->add($mainsock); $alive = 1; while($alive) { @readable = $select->can_read(0.20); foreach $sock (@readable) { if($sock eq $mainsock) { # new connection $sock = $mainsock->accept(); $sock->timeout(0); fcntl($sock, F_SETFL, O_NONBLOCK); print $sock "EMETER>"; $select->add($sock); } else { $sock->recv($in,255,0); if(! defined $in) { $select->remove($sock); $sock->close(); delete $update{$sock}{val}; delete $update{$sock}{handle}; delete $update{$sock}; } else { ($cmd, $val) = $in =~ /^\W*(\w*)\W*(\w*)\W*$/; $alive = 0 if(($cmd eq "shutdown") && ($val eq "now" )); if($cmd eq "update") { if($val eq "1") { $update{"$sock"} = 1; $update{"$sock"}{val} = 1; $update{"$sock"}{handle} = $sock; } else { $update{"$sock"} = 1; $update{"$sock"}{val} = 0; $update{"$sock"}{handle} = $sock; } } if($cmd eq "quit") { if($val eq "now") { $sock->close(); delete $update{$sock}{val}; delete $update{$sock}{handle}; delete $update{$sock}; } } if($cmd eq "read") { if(! defined $map{"$val"}) { print $sock "ERR no such val $val\n"; } else { $cmd = $chan[$map{"$val"}]; print $sock "$cmd\n"; } } } print $sock "EMETER>"; } } ($len, $data) = $ob->read(60); chop($data); print "loop\n"; $chan[9] = $data; $chan[10] = $len; if($len == 60) { @chan = split(/,/,$data); } $c = 0; print "see\n"; @writable = $select->can_write(0.05); print "do\n"; foreach $key (@writable) { if((defined $update{$key}) && $update{$key}{val} == 1) { $sock = $update{$key}{handle}; print "$sock\n"; $sock->write("UPDATE\n"); } } print "bah\n"; } } die; } 1;