2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-14 21:49:12 +00:00

USBWX check in for Peter/Wien

git-svn-id: https://svn.fhem.de/fhem/trunk@693 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2010-08-14 09:40:09 +00:00
parent 9534ab0045
commit 4b3aa39984
2 changed files with 461 additions and 1 deletions

414
fhem/FHEM/70_USBWX.pm Normal file
View File

@ -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 <name> 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;

View File

@ -106,6 +106,7 @@
<a href="#SISPM">SISPM</a> &nbsp;
<a href="#SIS_PMS">SIS_PMS</a> &nbsp;
<a href="#USF1000">USF1000</a> &nbsp;
<a href="#USBWX">USBWX</a> &nbsp;
<a href="#VantagePro2">VantagePro2</a> &nbsp;
<a href="#WS2000">WS2000</a> &nbsp;
<a href="#WS300">WS300</a> &nbsp;
@ -2973,8 +2974,10 @@ Attributes:<br>
Notes:
<ul>
<li>Toggle is special implemented. List name returns "on" or "off" even after a toggle command</li>
</ul>
</ul>
</ul>
<a name="ALL4000T"></a>
<h3>ALL4000T</h3>
<ul>
@ -3005,7 +3008,7 @@ Attributes:<br>
Examples:
<ul>
<code>define lamp1 ALL3076 192.168.8.200 0 7 60</code><br>
<code>define lamp1 ALL4027 192.168.8.200 0 7 60</code><br>
</ul>
</ul>
<br>
@ -3029,6 +3032,7 @@ Attributes:<br>
Notes:
<ul>
<li>Toggle is special implemented. List name returns "on" or "off" even after a toggle command</li>
</ul>
</ul>
</ul>
@ -4359,6 +4363,48 @@ Terminating
</ul>
<a name="USBWX"></a>
<h3>USBWX</h3>
<ul>
<br>
<a name="USBWXdefine"></a>
<b>Define</b>
<ul>
<code>define &lt;name&gt; USBWX &lt;serial device&gt;</code>
<br><br>
Defines an ELV <a href="http://www.elv.de/output/controller.aspx?cid=74&detail=10&detail2=24916&flv=1">USB-WDE1</a> weatherstation attached via usb.<br>
<br>
The WDE1 is able to receive the following sensors:<br>
<ul>
<li>S 300 TH (implemented and tested)
<li>S 300 IA (implemented)
<li>ASH 2200 (implemented)
<li>PS 50 (implemented)
<li>KS 200/300 (NOT yet implemented)
</ul>
<br>
Example:<pre>
define WDE1Device USBWX /dev/ttyUSB0
</pre>
</ul>
<a name="USBWXset"></a>
<b>Set</b> <ul>N/A</ul><br>
<a name="USBWXget"></a>
<b>Get</b> <ul>N/A</ul><br>
<a name="USBWXattr"></a>
<b>Attributes</b>
<ul>
<li><a href="#model">model</a></li>
<li><a href="#loglevel">loglevel</a></li>
</ul>
<br>
</ul>
<a name="weblink"></a>
<h3>weblink</h3>
<ul>