2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-15 22:26:04 +00:00

- 66_ECMD.pm: serial port protocols added

- 67_EMCDDevice.pm: readings added


git-svn-id: https://svn.fhem.de/fhem/trunk@808 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
borisneubert 2011-01-25 19:24:48 +00:00
parent be20eafe75
commit 74c0685302
2 changed files with 129 additions and 30 deletions

View File

@ -56,24 +56,18 @@ ECMD_Define($$)
my $name = $a[0];
my $protocol = $a[2];
my $ipaddress= $a[3];
if(@a < 4 || @a > 4 || $protocol ne "telnet") {
my $msg = "wrong syntax: define <name> ECMD telnet <ipaddress[:port]> ";
if(@a < 4 || @a > 4 || (($protocol ne "telnet") && ($protocol ne "serial"))) {
my $msg = "wrong syntax: define <name> ECMD telnet <ipaddress[:port]> or define <name> ECMD serial <devicename[\@baudrate]>";
Log 2, $msg;
return $msg;
}
ECMD_CloseDev($hash);
if($ipaddress eq "none") {
Log 1, "$name ip address is none, commands will be echoed only";
$attr{$name}{dummy} = 1;
return undef;
}
$hash->{Protocol}= $protocol;
$hash->{IPAddress}= $ipaddress;
my $devicename= $a[3];
$hash->{DeviceName} = $devicename;
my $ret = ECMD_OpenDev($hash, 0);
return $ret;
@ -108,18 +102,25 @@ ECMD_CloseDev($)
{
my ($hash) = @_;
my $name = $hash->{NAME};
my $ipaddress = $hash->{IPAddress};
my $dev = $hash->{DeviceName};
return if(!$ipaddress);
return if(!$dev);
if($hash->{TCPDev}) {
$hash->{TCPDev}->close();
delete($hash->{TCPDev});
}
delete($selectlist{"$name.$ipaddress"});
delete($readyfnlist{"$name.$ipaddress"});
} elsif($hash->{USBDev}) {
$hash->{USBDev}->close() ;
delete($hash->{USBDev});
}
($dev, undef) = split("@", $dev); # Remove the baudrate
delete($selectlist{"$name.$dev"});
delete($readyfnlist{"$name.$dev"});
delete($hash->{FD});
}
########################
@ -128,14 +129,17 @@ ECMD_OpenDev($$)
{
my ($hash, $reopen) = @_;
my $protocol = $hash->{Protocol};
my $ipaddress = $hash->{IPAddress};
my $name = $hash->{NAME};
my $devicename = $hash->{DeviceName};
$hash->{PARTIAL} = "";
Log 3, "ECMD opening $name (protocol $protocol, ipaddress $ipaddress)"
Log 3, "ECMD opening $name (protocol $protocol, device $devicename)"
if(!$reopen);
if($hash->{Protocol} eq "telnet") {
# This part is called every time the timeout (5sec) is expired _OR_
# somebody is communicating over another TCP connection. As the connect
# for non-existent devices has a delay of 3 sec, we are sitting all the
@ -144,12 +148,13 @@ ECMD_OpenDev($$)
return;
}
my $conn = IO::Socket::INET->new(PeerAddr => $ipaddress);
my $conn = IO::Socket::INET->new(PeerAddr => $devicename);
if($conn) {
delete($hash->{NEXT_OPEN})
} else {
Log(3, "Can't connect to $ipaddress: $!") if(!$reopen);
$readyfnlist{"$name.$ipaddress"} = $hash;
Log(3, "Can't connect to $devicename: $!") if(!$reopen);
$readyfnlist{"$name.$devicename"} = $hash;
$hash->{STATE} = "disconnected";
$hash->{NEXT_OPEN} = time()+60;
return "";
@ -157,12 +162,74 @@ ECMD_OpenDev($$)
$hash->{TCPDev} = $conn;
$hash->{FD} = $conn->fileno();
delete($readyfnlist{"$name.$ipaddress"});
$selectlist{"$name.$ipaddress"} = $hash;
delete($readyfnlist{"$name.$devicename"});
$selectlist{"$name.$devicename"} = $hash;
} else {
my $baudrate;
($devicename, $baudrate) = split("@", $devicename);
my $po;
if ($^O=~/Win/) {
require Win32::SerialPort;
$po = new Win32::SerialPort ($devicename);
} else {
require Device::SerialPort;
$po = new Device::SerialPort ($devicename);
}
if(!$po) {
return undef if($reopen);
Log(3, "Can't open $devicename: $!");
$readyfnlist{"$name.$devicename"} = $hash;
$hash->{STATE} = "disconnected";
return "";
}
$hash->{USBDev} = $po;
if( $^O =~ /Win/ ) {
$readyfnlist{"$name.$devicename"} = $hash;
} else {
$hash->{FD} = $po->FILENO;
delete($readyfnlist{"$name.$devicename"});
$selectlist{"$name.$devicename"} = $hash;
}
if($baudrate) {
$po->reset_error();
Log 3, "CUL setting $name baudrate to $baudrate";
$po->baudrate($baudrate);
$po->databits(8);
$po->parity('none');
$po->stopbits(1);
$po->handshake('none');
# This part is for some Linux kernel versions whih has strange default
# settings. Device::SerialPort is nice: if the flag is not defined for your
# OS then it will be ignored.
$po->stty_icanon(0);
#$po->stty_parmrk(0); # The debian standard install does not have it
$po->stty_icrnl(0);
$po->stty_echoe(0);
$po->stty_echok(0);
$po->stty_echoctl(0);
# Needed for some strange distros
$po->stty_echo(0);
$po->stty_icanon(0);
$po->stty_isig(0);
$po->stty_opost(0);
$po->stty_icrnl(0);
}
$po->write_settings;
}
if($reopen) {
Log 1, "ECMD $ipaddress reappeared ($name)";
Log 1, "ECMD $name ($devicename) reappeared";
} else {
Log 3, "ECMD device opened";
}
@ -173,7 +240,7 @@ ECMD_OpenDev($$)
if($ret) {
Log 1, "$ret";
ECMD_CloseDev($hash);
Log 1, "Cannot init $ipaddress, ignoring it";
Log 1, "Cannot init $name ($devicename), ignoring it";
}
DoTrigger($name, "CONNECTED") if($reopen);
@ -211,6 +278,7 @@ ECMD_SimpleWrite(@)
return if(!$hash);
$msg .= "\n" unless($nonl);
$hash->{USBDev}->write($msg) if($hash->{USBDev});
syswrite($hash->{TCPDev}, $msg) if($hash->{TCPDev});
select(undef, undef, undef, 0.001);
@ -222,9 +290,13 @@ ECMD_SimpleRead($)
{
my ($hash) = @_;
if($hash->{USBDev}) {
return $hash->{USBDev}->input();
}
if($hash->{TCPDev}) {
my $buf;
if(!defined(sysread($hash->{TCPDev}, $buf, 256))) {
if(!defined(sysread($hash->{TCPDev}, $buf, 1024))) {
ECMD_Disconnected($hash);
return undef;
}
@ -307,14 +379,14 @@ sub
ECMD_Disconnected($)
{
my $hash = shift;
my $ipaddress = $hash->{IPAddress};
my $dev = $hash->{DeviceName};
my $name = $hash->{NAME};
return if(!defined($hash->{FD})); # Already deleted o
Log 1, "$ipaddress disconnected, waiting to reappear";
Log 1, "$dev disconnected, waiting to reappear";
ECMD_CloseDev($hash);
$readyfnlist{"$name.$ipaddress"} = $hash; # Start polling
$readyfnlist{"$name.$dev"} = $hash; # Start polling
$hash->{STATE} = "disconnected";
# Without the following sleep the open of the device causes a SIGSEGV,

View File

@ -71,6 +71,29 @@ ECMDDevice_DeviceParams2Specials($)
return %specials;
}
###################################
sub
ECMDDevice_Changed($$$)
{
my ($hash, $cmd, $value)= @_;
my $name= $hash->{NAME};
my $r= $hash->{READINGS};
my $tn = TimeNow();
$r->{$cmd}{TIME} = $tn;
$r->{$cmd}{VAL} = $value;
$hash->{CHANGED}[0]= "$cmd: $value";
DoTrigger($name, undef) if($init_done);
$hash->{STATE} = "$cmd: $value";
Log GetLogLevel($name, 4), "ECMDDevice $name $cmd: $value";
return $hash->{STATE};
}
###################################
sub
@ -111,7 +134,7 @@ ECMDDevice_Get($@)
my $v= IOWrite($hash, $r);
return "$name $cmdname => $v" ;
return ECMDDevice_Changed($hash, $cmdname, $v);
}
@ -151,7 +174,11 @@ ECMDDevice_Set($@)
my $r = ECMDDevice_AnalyzeCommand($ecmd);
return IOWrite($hash, $r);
my $v= IOWrite($hash, $r);
$v= $params if($params);
return ECMDDevice_Changed($hash, $cmdname, $v);
}