From 4b3aa3998472aa5bfcc41e4e68865002fc790e08 Mon Sep 17 00:00:00 2001 From: rudolfkoenig <> Date: Sat, 14 Aug 2010 09:40:09 +0000 Subject: [PATCH] USBWX check in for Peter/Wien git-svn-id: https://svn.fhem.de/fhem/trunk@693 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/70_USBWX.pm | 414 ++++++++++++++++++++++++++++++++++++++ fhem/docs/commandref.html | 48 ++++- 2 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 fhem/FHEM/70_USBWX.pm diff --git a/fhem/FHEM/70_USBWX.pm b/fhem/FHEM/70_USBWX.pm new file mode 100644 index 000000000..d8e4af78a --- /dev/null +++ b/fhem/FHEM/70_USBWX.pm @@ -0,0 +1,414 @@ +############################################## +package main; + +use strict; +use warnings; +use Device::SerialPort; + +##################################### +sub +USBWX_Initialize($) +{ +my ($hash) = @_; + +$hash->{ReadFn} = "USBWX_Read"; +$hash->{ReadyFn} = "USBWX_Ready"; +# Normal devices +$hash->{DefFn} = "USBWX_Define"; +$hash->{UndefFn} = "USBWX_Undef"; + +$hash->{GetFn} = "USBWX_Get"; +$hash->{SetFn} = "USBWX_Set"; +$hash->{AttrList}= "model:USB-WDE1 loglevel:0,1,2,3,4,5,6"; +} + +##################################### +sub +USBWX_Define($$) +{ + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + + return "wrong syntax: define USBWX devicename" + if(@a != 3); + + USBWX_CloseDev($hash); + + my $name = $a[0]; + my $dev = $a[2]; + + if($dev eq "none") { + Log 1, "USBWX $name device is none, commands will be echoed only"; + $attr{$name}{dummy} = 1; + return undef; + } + + $hash->{DeviceName} = $dev; + my $ret = USBWX_OpenDev($hash, 0); + return $ret; +} + +##################################### +sub +USBWX_OpenDev($$) +{ +my ($hash, $reopen) = @_; +my $dev = $hash->{DeviceName}; +my $name = $hash->{NAME}; +my $po; + +$hash->{PARTIAL} = ""; +Log 3, "USBWX opening $name device $dev" + if(!$reopen); + +if ($^O=~/Win/) + { + require Win32::SerialPort; + $po = new Win32::SerialPort ($dev); + } +else + { + require Device::SerialPort; + $po = Device::SerialPort->new($dev); + } + +if(!$po) + { + return undef if($reopen); + Log(2, "USBWX Can't open $dev: $!"); + $readyfnlist{"$name.$dev"} = $hash; + $hash->{STATE} = "disconnected"; + return ""; + } + +$hash->{USBWX} = $po; +if( $^O =~ /Win/ ) + { + $readyfnlist{"$name.$dev"} = $hash; + } +else + { + $hash->{FD} = $po->FILENO; + delete($readyfnlist{"$name.$dev"}); + $selectlist{"$name.$dev"} = $hash; + } + +$po->baudrate(9600); +$po->databits(8); +$po->parity('none'); +$po->stopbits(1); +$po->handshake('none'); +$po->reset_error(); +$po->lookclear; # clear buffers + +if($reopen) + { + Log 1, "USBWX $dev reappeared ($name)"; + } +else + { + Log 2, "USBWX opened device $dev"; + } + +$hash->{STATE}=""; # Allow InitDev to set the state +my $ret = USBWX_DoInit($hash); + +if($ret) + { +# try again + Log 1, "USBWX Cannot init $dev, at first try. Trying again."; + my $ret = USBWX_DoInit($hash); + if($ret) + { + USBWX_CloseDev($hash); + Log 1, "USBWX Cannot init $dev, ignoring it"; +# return "USBWX Error Init string."; + } + } +DoTrigger($name, "CONNECTED") if($reopen); + +return undef; +} + +######################## +sub +USBWX_CloseDev($) +{ +my ($hash) = @_; +my $name = $hash->{NAME}; +my $dev = $hash->{DeviceName}; + +return if(!$dev); + +$hash->{USBWX}->close() ; +delete($hash->{USBWX}); +delete($selectlist{"$name.$dev"}); +delete($readyfnlist{"$name.$dev"}); +delete($hash->{FD}); +} + +##################################### +sub +USBWX_Ready($) +{ +my ($hash) = @_; + +return USBWX_OpenDev($hash, 1) +if($hash->{STATE} eq "disconnected"); + +# This is relevant for windows/USB only +my $po = $hash->{USBWX}; +my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags) = $po->status; +return ($InBytes>0); +} + +##################################### +sub +USBWX_Clear($) +{ +my $hash = shift; +my $buf; + +# clear buffer: +if($hash->{USBWX}) + { + while ($hash->{USBWX}->lookfor()) + { + $buf = USBWX_SimpleRead($hash); + } + } + +return $buf; +} + +##################################### +sub +USBWX_DoInit($) +{ +my $hash = shift; +my $name = $hash->{NAME}; +my $init ="?"; +my $buf; + +USBWX_Clear($hash); +USBWX_SimpleWrite($hash, $init); + +return undef; +} + +##################################### +sub USBWX_Undef($$) +{ +my ($hash, $arg) = @_; +my $name = $hash->{NAME}; +delete $hash->{FD}; +$hash->{STATE}='close'; +$hash->{USBWX}->close() if($hash->{USBWX}); +Log 2, "$name shutdown complete"; +return undef; +} + +##################################### +# called from the global loop, when the select for hash->{FD} reports data +sub +USBWX_Read($) +{ +my ($hash) = @_; +my $name = $hash->{NAME}; +my $char; + +#Log 4, "USBWX Read State:$hash->{STATE}"; + +my $mybuf = USBWX_SimpleRead($hash); +my $usbwx_data = $hash->{PARTIAL}; +if ( ( length($usbwx_data) > 1) && ($mybuf eq "\n") ) + { + Log 4, "USBWX/RAW Satz: $usbwx_data !!"; + } + +if(!defined($mybuf) || length($mybuf) == 0) + { + USBWX_Disconnected($hash); + return ""; + } + +$usbwx_data .= $mybuf; + +if ( ( length($usbwx_data) > 27) && ($mybuf eq "\n") ) + { + USBWX_Parse($hash, $usbwx_data); + $hash->{PARTIAL} = ""; + } +else + { + $hash->{PARTIAL} = $usbwx_data; + } +} + + +##################################### +sub +USBWX_Set($@) +{ +my ($hash, @a) = @_; + +my $msg; +my $name=$a[0]; +my $reading= $a[1]; +$msg="$name => No Set function ($reading) implemented"; +Log 1,$msg; +return $msg; +} + +##################################### +sub +USBWX_Get($@) +{ +my ($hash, @a) = @_; + +my $msg; +my $name=$a[0]; +my $reading= $a[1]; +$msg="$name => No Get function ($reading) implemented"; +Log 1,$msg; +return $msg; +} + +######################## +sub +USBWX_SimpleRead($) +{ +my ($hash) = @_; +my $buf; + +if($hash->{USBWX}) + { + $buf = $hash->{USBWX}->read(1) ; + if (length($buf) == 0) + { + $buf = $hash->{USBWX}->read(1) ; + } +# Log 4, "USBWX SimpleRead=>$buf"; + return $buf; + } + +return undef; +} + +######################## +sub +USBWX_SimpleWrite(@) +{ +my ($hash, $msg) = @_; +return if(!$hash); +$hash->{USBWX}->write($msg) if($hash->{USBWX}); +Log 4, "USBWX SimpleWrite $msg"; +select(undef, undef, undef, 0.001); +} + +##################################### +sub +USBWX_Parse($$) +{ +my ($hash,$rmsg) = @_; +my $name = $hash->{NAME}; + +Log 4, "USBWX Parse Msg:$rmsg, State:$hash->{STATE}"; + +my $wxmsg = substr($rmsg, 0, 3); +my $stmsg = substr($rmsg, 2, 3); + +Log 4, "USBWX Parse >$wxmsg<"; +#$1;1;;23,9;;23,6;24,3;;;26,0;;56;;59;58;;;54;;;;;;;0 + +#$1;1;;;;;;;;;;;;;;;;;;;;;;;0 +#1234567890123456789012345678901234567890 + +if ($wxmsg eq "\$1;") + { + my @c = split(";", $rmsg); + + Log 3, "USBWX T1:$c[3] T2:$c[4] T3:$c[5] T4:$c[6] T5:$c[7] T6:$c[8] T7:$c[9] T8:$c[10]"; + + $rmsg =~ s/[\r\n]//g; # Delete the NewLine + $hash->{READINGS}{$name}{VAL} = $rmsg; + $hash->{READINGS}{$name}{TIME} = TimeNow(); + $hash->{STATE}=$rmsg; + $rmsg =~ s/,/./g; # format for FHEM + my @data = split(";", $rmsg); +#add WS300 handler here + my @names = ("T1", "T2", "T3", "T4", "T5", "T6", "T7", "T8"); + my $tn = TimeNow(); + for(my $i = 0; $i < int(@names); $i++) + { + if ($data[$i+2] ne "") # only for existing sensors + { + $hash->{CHANGED}[$i] = "$names[$i]: $data[$i+2] H: $data[$i+10]"; + $hash->{READINGS}{$names[$i]}{TIME} = $tn; + $hash->{READINGS}{$names[$i]}{VAL} = $data[$i+2]; + } + } + DoTrigger($name, undef); + } +#ELV USB-WDE1 v1.1 +#Baud:9600bit/s +#Mode:LogView +elsif ($stmsg eq "ELV") + { + Log 4, "USBWX Parse ID"; + my @c = split(" ", $rmsg); + if ($c[1] eq "USB-WDE1") + { + Log 3, "USBWX $c[1] $c[2] found"; + $rmsg =~ s/[\r\n]/ /g; + $hash->{READINGS}{"status"}{VAL} = $rmsg; + $hash->{READINGS}{"status"}{TIME} = TimeNow(); + } + } +elsif ($wxmsg eq "Mod") + { + Log 4, "USBWX Parse mode $rmsg"; + my @c = split(":", $rmsg); + my @d = split("\n", $c[1]); + $d[0] =~ s/[\r\n]//g; # Delete the NewLine + Log 4, "USBWX Parse mode >$d[0]<"; + if ($d[0] eq "LogView") + { + Log 2, "USBWX in $c[0] $d[0] found"; + $hash->{STATE} = "Initialized"; + + $hash->{READINGS}{"mode"}{VAL} = $d[0]; + $hash->{READINGS}{"mode"}{TIME} = TimeNow(); + } + } +else + { + Log 2, "USBWX unknown:$rmsg"; + } +} + +##################################### +sub +USBWX_Disconnected($) +{ +my $hash = shift; +my $dev = $hash->{DeviceName}; +my $name = $hash->{NAME}; + +return if(!defined($hash->{FD})); # Already deleted + +Log 1, "USBWX $dev disconnected, waiting to reappear"; +USBWX_CloseDev($hash); +$readyfnlist{"$name.$dev"} = $hash; # Start polling +$hash->{STATE} = "disconnected"; + +# Without the following sleep the open of the device causes a SIGSEGV, +# and following opens block infinitely. Only a reboot helps. +sleep(5); + +DoTrigger($name, "DISCONNECTED"); +} + + + +1; diff --git a/fhem/docs/commandref.html b/fhem/docs/commandref.html index e63aa774a..3b8353143 100644 --- a/fhem/docs/commandref.html +++ b/fhem/docs/commandref.html @@ -106,6 +106,7 @@ SISPM   SIS_PMS   USF1000   + USBWX   VantagePro2   WS2000   WS300   @@ -2973,8 +2974,10 @@ Attributes:
Notes: +

ALL4000T


@@ -3029,6 +3032,7 @@ Attributes:
Notes: @@ -4359,6 +4363,48 @@ Terminating + +

USBWX

+ +

weblink