| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- #!/usr/bin/perl
- #
- # read_ws2000 from device (elv art-Nr. 390-61) and provides socket service (like XPORT),
- # or act as client for this service
- # licence GPL2
- # Thomas Dressler 2008
- # $Id: ws2000_reader.pl,v 1.2 2010-08-01 13:33:13 rudolfkoenig Exp $
- use Switch;
- use strict;
- use IO::Socket;
- use IO::Select;
- our $PortObj;
- my $server;
- our $xport;
- our $sel;
- our $clients;
- our %sockets;
- my ($datum,$data,$lastdate,$lastdata);
- $SIG{INT}=$SIG{TERM}=\&signalhandler;
- $|=1;
- PortOpen($ARGV[0]);
- my $ServerPort=$ARGV[1];
- if ($ServerPort) {
- $server=IO::Socket::INET->new(LocalPort=>$ServerPort,
- ReuseAddr=>1,
- Listen=>10,
- timeout=>1,
- blocking=>0
- );
- die "ServerStart-Error: $@ \n" if !$server;
- $clients=IO::Select->new($server);
- }
- MAINLOOP:
- for(;;) {
- if($server) {
- #only for server mode
- my %message=undef;
- my $fh;
- while(my @ready=$clients->can_read(1)) {
- foreach $fh (@ready) {
- if ($fh==$server) {
- #new connection waiting
- my $new=$server->accept;
- $new->autoflush(1);
- $new->blocking(0);
- $new->timeout(1);
- $clients->add($new);
- my $host=$new->peerhost;
- $sockets{$new}=$host;
- print "\nNew Client:".$host."\n";
- #}else{
- # my $out=undef;
- # $fh->read($out,1);
- # $message{$fh}=$out;
- }
- }
- }
- #check living connections
- foreach my $fh($clients->handles) {
- next if $fh==$server;
- next if ($fh->peerhost);
- print "Terminate ".$sockets{$fh}. " by Check1\n";
- Client_disconnect($fh);
- }
-
- }
- $data=get_data();
- next if ! $data;
- $datum = time();
- next if ($data eq $lastdata) && (($datum - $lastdate) < 30);
- my $result=decode_data($data);
- print scalar localtime().":".$result."\n";
- $lastdata = $data;
- $lastdate = $datum;
- }
- PortClose();
- exit 0;
- #--------SUBs -----------------------------
- sub Clientdisconnect{
- my $fh=shift;
- print "\n Client ".$sockets{$fh}." disconnected!\n";
- $clients->remove($fh);
- delete $sockets{$fh};
- $fh->shutdown(2);
- $fh->close;
- }
- sub PortOpen{
- my $PortName=shift;
- my $quiet=shift ||undef;
-
- if ($PortName=~/^\/dev|^COM/) {
- #normal devices (/dev)
- my $OS=$^O;
- if ($OS eq 'MSWin32') {
- eval ("use Win32::SerialPort;");
- die "$@\n" if ($@);
- $PortObj = new Win32::SerialPort ($PortName, $quiet)
- || die "Can't open $PortName: $^E\n"; # $quiet is optional
- } else {
- eval ("use Device::SerialPort;");
- die "$@\n" if ($@);
- $PortObj = new Device::SerialPort ($PortName, $quiet)
- || die "Can't open $PortName: $^E\n"; # $quiet is optional
-
- }
- #Parameter 19200,8,2,Odd,None
- $PortObj->baudrate(19200);
- $PortObj->databits(8);
- $PortObj->parity("odd");
- $PortObj->stopbits(2);
- $PortObj->handshake("none");
- if (! $PortObj->write_settings) {
- undef $PortObj;
- die "Write Settings failed!\n";
- }
- $sel=IO::Select->new($PortObj->{FD} );
- }elsif($PortName=~/([\w.]+):(\d{1,5})/){
- #Sockets(hostname:port)
- my $host=$1;
- my $port=$2;
- $xport=IO::Socket::INET->new(PeerAddr=>$host,
- PeerPort=>$port,
- timeout=>1,
- blocking=>0
- );
- die "Cannot connect to $PortName -> $@ ( $!) \n" if ! $xport;
- $xport->autoflush(1);
- $sel=IO::Select->new($xport);
- }else{
- die "$PortName is no device and not implemented!\n";
- }
- }
- sub PortClose {
- $PortObj->close if ($PortObj);
- if ($xport) {
- $clients->remove($xport) if $clients;
- $xport->shutdown(2);
- $xport->close;
- }
- if ($clients) {
- foreach my $socket($clients->handles) {
- Clientdisconnect($socket);
- }
- }
- }
- sub signalhandler {
- my $signal=shift;
- PortClose();
- print "\nTerminated by Signal $signal!\n";
- exit;
- }
-
- sub get_data {
-
- my $STX=2;
- my $ETX=3;
- my $retval='';
- my $status='';
- my $out=undef;
- my $message;
- my $byte;
- for(;;) {
- #sleep 1 if(!defined($out) || length($out) == 0);
- $out=undef;
- if ($xport) {
-
- #my @readable=$select->can_read(1);
- #next if $#readable<0;
-
-
- #my $fh;
- #foreach $fh (@readable) {
-
- next if ! $sel->can_read(1);
- $xport->read($out,1);
- #if ($xport->eof) {
- # print "Xport eof\n";
- # print "Server disconnected, terminate!\n";
- # PortClose();
- # exit 1;
-
- #}
-
-
-
- }elsif($PortObj) {
- $out = $PortObj->read(1);
- }
- next if(!defined($out) || length($out) == 0) ;
-
-
- $byte=ord($out);
- if($byte eq $STX) {
- #Log 4, "M232: return value \'" . $retval . "\'";
- $status= "STX";
- $message=$out;
- } elsif($byte eq $ETX) {
- $status= "ETX";
- $message .=$out;
- } elsif ($status eq "STX"){
- $byte=$byte & 0x7F;
- $retval .= chr($byte);
- $message .=$out;
- }
- last if($status eq "ETX");
-
- }
- if ($server) {
- foreach my $client($clients->can_write(1)) {
- next if $client == $server;
- if (!$client->send($message)){
- Clientdisconnect($client);
- next;
- }
-
- }
- }
- return $retval;
- }
- sub decode_data {
- my ($sensor,$daten1,$einheit1,$daten2,$einheit2,$daten3,$einheit3,$result);
- my $data=shift;
- my ($typ,$w1,$w2,$w3,$w4,$w5)=unpack("U*",$data);
- my $group = ($typ & 0x70)/16 ;#/slash for komodo syntax checker!
- my $snr = $typ % 16;
-
-
- switch ( $group ){
- case 7 {
- $sensor = "Fernbedienung";
- $daten1 = $w1 * 10000 + $w2 * 1000 + $w3 * 100 + $w4 * 10 + $w5;
- $result = $sensor . "=" . $daten1 . $einheit1;
- }
- case 0 {
- if ($snr < 8) {
- $sensor = "Temperatursensor V1.1(" . $snr . ")";
- }else{
- $sensor = "Temperatursensor V1.2(" .($snr - 8). ")";
- }
- if ($w1 >= 64) {
- $daten1 = ((255 - $w1 - $w2) / 10) * (-1);
- }else{
- $daten1 = (($w1 * 128 + $w2) / 10);
- }
- $einheit1 = " °C";
- $result = $sensor . "=" . $daten1 . $einheit1;
- }
- case 1 {
- if ($snr <8) {
- $sensor = "Temperatursensor mit Feuchte V1.1(" . $snr . ")";
- }else{
- $sensor = "Temperatursensor mit Feuchte V1.2(" . ($snr - 8) . ")";
- }
- if ($w1 >= 64) {
- $daten1 = ((255 - $w1 - $w2) / 10) * (-1);
- }else{
- $daten1 = (($w1 * 128 + $w2) / 10);
- }
-
- $daten2 = $w3;
- $daten3 = 0;
- $einheit1 = " °C";
- $einheit2 = " %";
-
- $result = $sensor . "=" . $daten1 . $einheit1 . " " . $daten2 .$einheit2;
- }
- case 2 {
- if ( $snr < 8 ) {
- $sensor = "Regensensor V1.1(" . $snr . ")";
- }else{
- $sensor = "Regensensor V1.2(" . ($snr - 8) . ")"
- }
- $daten1 = ($w1 * 128 + $w2) * 0.36;
- $einheit1 = " l/m²";
- $result = $sensor . "=" . $daten1 . $einheit1;
- }
- case 3 {
- if ($snr < 8) {
- $sensor = "Windsensor V1.1(" . $snr . ")";
- }else{
- $sensor = "Windsensor V1.2(" & ($snr - 8) . ")";
- }
- switch( $w3) {
- case 0 { $einheit3 = "±0 °";}
- case 1 { $einheit3 = "± 22,5 °";}
- case 2 { $einheit3 = "± 45 °";}
- case 3 { $einheit3 = "± 67,5 °";}
- }
- $daten1 = ($w1 * 128 + $w2) / 10;
- $daten2 = $w4 * 128 + $w5;
- $einheit1 = " km/h";
- $einheit2 = " °";
- $result = $sensor . "=" . $daten1 . $einheit1 . " " . $daten2 . $einheit2 . " " . $einheit3;
- }
- case 4 {
- if ($snr < 8) {
- $sensor = "Innensensor V1.1(" . $snr . ")";
- }else{
- $sensor = "Innensensor V1.2(" . ($snr - 8) . ")";
- }
- if ($w1 >= 64) {
- $daten1 = ((255 - $w1 - $w2) / 10) * (-1);
- }else{
- $daten1 = (($w1 * 128 + $w2) / 10);
- }
- $daten2 = $w3;
- $daten3 = $w4 * 128 + $w5;
- $einheit1 = " °C";
- $einheit2 = " %";
- $einheit3 = " hPa";
- $result = $sensor . "=" . $daten1 . $einheit1 . " " . $daten2 . $einheit2 . " " . $daten3 . $einheit3;
- }
- case 5 {
- $sensor = "Helligkeitssensor V1.2(" . ($snr - 8) . ")";
- switch ($w3) {
- case 0 {$daten1 = 1;}
- case 1 {$daten1 = 10;}
- case 2 {$daten1 = 100;}
- case 3 {$daten1 = 1000;}
- }
- $daten1 = $daten1 * ($w1 * 128 + $w2);
- $einheit1 = "Lux";
- $result = $sensor . "=" . $daten1 . $einheit1;
- }
- case 6 {
- $sensor = "Pyranometer V1.2(" . ($snr - 8) . ")";
- switch ($w3) {
- case 0 {$daten1 = 1;}
- case 1 {$daten1 = 10;}
- case 2 {$daten1 = 100;}
- case 3 {$daten1 = 1000;}
- }
- $daten1 = $daten1 * ($w1 * 128 + $w2);
- $einheit1 = " W/m²";
- $result = $sensor . "=" . $daten1 . $einheit1;
- }
- else {
- $sensor = "Störung";
- $daten1 = $typ;
- $result = $sensor . "(Group:" . $group . "/Typ:" . $typ . ")";
- }#switch else
-
- }#switch
- return $result;
- }
|