mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-05-04 22:19:38 +00:00
Do not block when a device disconnects
git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@320 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
9246dfd5af
commit
d039a686dd
@ -90,7 +90,7 @@ CM11_Initialize($)
|
|||||||
$hash->{ReadFn} = "CM11_Read";
|
$hash->{ReadFn} = "CM11_Read";
|
||||||
$hash->{WriteFn} = "CM11_Write";
|
$hash->{WriteFn} = "CM11_Write";
|
||||||
$hash->{Clients} = ":X10:";
|
$hash->{Clients} = ":X10:";
|
||||||
$hash->{ReadyFn} = "CM11_Ready" if ($^O eq 'MSWin32');
|
$hash->{ReadyFn} = "CM11_Ready";
|
||||||
|
|
||||||
# Normal Devices
|
# Normal Devices
|
||||||
$hash->{DefFn} = "CM11_Define";
|
$hash->{DefFn} = "CM11_Define";
|
||||||
@ -136,6 +136,7 @@ CM11_DoInit($$$)
|
|||||||
}
|
}
|
||||||
|
|
||||||
$po->write_settings;
|
$po->write_settings;
|
||||||
|
$defs{$name}{STATE} = "Initialized";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +148,10 @@ CM11_Define($$)
|
|||||||
my ($hash, $def) = @_;
|
my ($hash, $def) = @_;
|
||||||
my @a = split("[ \t][ \t]*", $def);
|
my @a = split("[ \t][ \t]*", $def);
|
||||||
my $po;
|
my $po;
|
||||||
$hash->{STATE} = "Initialized";
|
|
||||||
|
return "wrong syntax: define <name> FHZ devicename ".
|
||||||
|
"[normal|strangetty] [mobile]" if(@a < 3 || @a > 5);
|
||||||
|
|
||||||
|
|
||||||
delete $hash->{PortObj};
|
delete $hash->{PortObj};
|
||||||
delete $hash->{FD};
|
delete $hash->{FD};
|
||||||
@ -155,6 +159,8 @@ CM11_Define($$)
|
|||||||
my $name = $a[0];
|
my $name = $a[0];
|
||||||
my $dev = $a[2];
|
my $dev = $a[2];
|
||||||
$hash->{ttytype} = $a[3] if($a[3]);
|
$hash->{ttytype} = $a[3] if($a[3]);
|
||||||
|
$hash->{MOBILE} = 1 if($a[4] && $a[4] eq "mobile");
|
||||||
|
$hash->{STATE} = "defined";
|
||||||
|
|
||||||
$attr{$name}{savefirst} = 1;
|
$attr{$name}{savefirst} = 1;
|
||||||
|
|
||||||
@ -164,6 +170,8 @@ CM11_Define($$)
|
|||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$hash->{DeviceName} = $dev;
|
||||||
|
$hash->{PARTIAL} = "";
|
||||||
Log 3, "CM11 opening CM11 device $dev";
|
Log 3, "CM11 opening CM11 device $dev";
|
||||||
if ($^O=~/Win/) {
|
if ($^O=~/Win/) {
|
||||||
require Win32::SerialPort;
|
require Win32::SerialPort;
|
||||||
@ -172,7 +180,13 @@ CM11_Define($$)
|
|||||||
require Device::SerialPort;
|
require Device::SerialPort;
|
||||||
$po = new Device::SerialPort ($dev);
|
$po = new Device::SerialPort ($dev);
|
||||||
}
|
}
|
||||||
return "Can't open $dev: $!\n" if(!$po);
|
if(!$po) {
|
||||||
|
my $msg = "Can't open $dev: $!";
|
||||||
|
Log(3, $msg) if($hash->{MOBILE});
|
||||||
|
return $msg if(!$hash->{MOBILE});
|
||||||
|
$readyfnlist{"$name.$dev"} = $hash;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
Log 3, "CM11 opened CM11 device $dev";
|
Log 3, "CM11 opened CM11 device $dev";
|
||||||
|
|
||||||
$hash->{PortObj} = $po;
|
$hash->{PortObj} = $po;
|
||||||
@ -182,8 +196,6 @@ CM11_Define($$)
|
|||||||
} else {
|
} else {
|
||||||
$readyfnlist{"$name.$dev"} = $hash;
|
$readyfnlist{"$name.$dev"} = $hash;
|
||||||
}
|
}
|
||||||
$hash->{DeviceName} = $dev;
|
|
||||||
$hash->{PARTIAL} = "";
|
|
||||||
|
|
||||||
CM11_DoInit($name, $hash->{ttytype}, $po);
|
CM11_DoInit($name, $hash->{ttytype}, $po);
|
||||||
|
|
||||||
@ -432,23 +444,19 @@ CM11_Read($)
|
|||||||
|
|
||||||
# USB troubleshooting
|
# USB troubleshooting
|
||||||
if(!defined($buf) || length($buf) == 0) {
|
if(!defined($buf) || length($buf) == 0) {
|
||||||
my $devname = $hash->{DeviceName};
|
my $dev = $hash->{DeviceName};
|
||||||
Log 1, "USB device $devname disconnected, waiting to reappear";
|
Log 1, "USB device $dev disconnected, waiting to reappear";
|
||||||
$hash->{PortObj}->close();
|
$hash->{PortObj}->close();
|
||||||
for(;;) {
|
DoTrigger($name, "DISCONNECTED");
|
||||||
sleep(5);
|
|
||||||
if ($^O eq 'MSWin32') {
|
delete($hash->{PortObj});
|
||||||
$hash->{PortObj} = new Win32::SerialPort($devname);
|
delete($selectlist{"$name.$dev"});
|
||||||
}else{
|
$readyfnlist{"$name.$dev"} = $hash; # Start polling
|
||||||
$hash->{PortObj} = new Device::SerialPort($devname);
|
$hash->{STATE} = "disconnected";
|
||||||
}
|
|
||||||
if($hash->{PortObj}) {
|
# Without the following sleep the open of the device causes a SIGSEGV,
|
||||||
Log 1, "USB device $devname reappeared";
|
# and following opens block infinitely. Only a reboot helps.
|
||||||
$hash->{FD} = $hash->{PortObj}->FILENO if !($^O eq 'MSWin32');
|
sleep(5);
|
||||||
CM11_DoInit($name, $hash->{ttytype}, $hash->{PortObj});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -599,10 +607,41 @@ CM11_Read($)
|
|||||||
|
|
||||||
#####################################
|
#####################################
|
||||||
sub
|
sub
|
||||||
CM11_Ready($$) # Windows - only
|
CM11_Ready($$)
|
||||||
{
|
{
|
||||||
my ($hash, $dev) = @_;
|
my ($hash, $dev) = @_;
|
||||||
my $po=$hash->{PortObj};
|
my $po=$hash->{PortObj};
|
||||||
|
|
||||||
|
if(!$po) { # Looking for the device
|
||||||
|
|
||||||
|
my $dev = $hash->{DeviceName};
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
|
||||||
|
$hash->{PARTIAL} = "";
|
||||||
|
if ($^O=~/Win/) {
|
||||||
|
$po = new Win32::SerialPort ($dev);
|
||||||
|
} else {
|
||||||
|
$po = new Device::SerialPort ($dev);
|
||||||
|
}
|
||||||
|
return undef if(!$po);
|
||||||
|
|
||||||
|
Log 1, "USB device $dev reappeared";
|
||||||
|
$hash->{PortObj} = $po;
|
||||||
|
if( $^O !~ /Win/ ) {
|
||||||
|
$hash->{FD} = $po->FILENO;
|
||||||
|
delete($readyfnlist{"$name.$dev"});
|
||||||
|
$selectlist{"$name.$dev"} = $hash;
|
||||||
|
} else {
|
||||||
|
$readyfnlist{"$name.$dev"} = $hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
CM11_DoInit($name, $hash->{ttytype}, $po);
|
||||||
|
DoTrigger($name, "CONNECTED");
|
||||||
|
return undef;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# This is relevant for windows only
|
||||||
return undef if !$po;
|
return undef if !$po;
|
||||||
my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags)=$po->status;
|
my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags)=$po->status;
|
||||||
return ($InBytes>0);
|
return ($InBytes>0);
|
||||||
|
@ -490,39 +490,18 @@ CUL_Read($)
|
|||||||
my $dev = $hash->{DeviceName};
|
my $dev = $hash->{DeviceName};
|
||||||
Log 1, "USB device $dev disconnected, waiting to reappear";
|
Log 1, "USB device $dev disconnected, waiting to reappear";
|
||||||
$hash->{PortObj}->close();
|
$hash->{PortObj}->close();
|
||||||
|
DoTrigger($name, "DISCONNECTED");
|
||||||
|
|
||||||
if($hash->{MOBILE}) {
|
delete($hash->{PortObj});
|
||||||
|
delete($selectlist{"$name.$dev"});
|
||||||
|
$readyfnlist{"$name.$dev"} = $hash; # Start polling
|
||||||
|
$hash->{STATE} = "disconnected";
|
||||||
|
|
||||||
delete($hash->{PortObj});
|
# Without the following sleep the open of the device causes a SIGSEGV,
|
||||||
delete($selectlist{"$name.$dev"});
|
# and following opens block infinitely. Only a reboot helps.
|
||||||
$readyfnlist{"$name.$dev"} = $hash; # Start polling
|
sleep(5);
|
||||||
$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);
|
|
||||||
|
|
||||||
return "";
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
sleep(5);
|
|
||||||
if ($^O eq 'MSWin32') {
|
|
||||||
$hash->{PortObj} = new Win32::SerialPort($dev);
|
|
||||||
}else{
|
|
||||||
$hash->{PortObj} = new Device::SerialPort($dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($hash->{PortObj}) {
|
|
||||||
Log 1, "USB device $dev reappeared";
|
|
||||||
$hash->{FD} = $hash->{PortObj}->FILENO if !($^O eq 'MSWin32');
|
|
||||||
CUL_DoInit($hash);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
my $culdata = $hash->{PARTIAL};
|
my $culdata = $hash->{PARTIAL};
|
||||||
@ -645,7 +624,9 @@ CUL_Ready($) # Windows - only
|
|||||||
if($ret) {
|
if($ret) {
|
||||||
delete($selectlist{"$name.$dev"});
|
delete($selectlist{"$name.$dev"});
|
||||||
delete($readyfnlist{"$name.$dev"});
|
delete($readyfnlist{"$name.$dev"});
|
||||||
|
Log 1, "Won't listen to this device any more";
|
||||||
}
|
}
|
||||||
|
DoTrigger($name, "CONNECTED");
|
||||||
return $ret;
|
return $ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ sub FHZ_ReadAnswer($$$);
|
|||||||
sub FHZ_Crc(@);
|
sub FHZ_Crc(@);
|
||||||
sub FHZ_CheckCrc($);
|
sub FHZ_CheckCrc($);
|
||||||
sub FHZ_XmitLimitCheck($$);
|
sub FHZ_XmitLimitCheck($$);
|
||||||
|
sub FHZ_DoInit($$$);
|
||||||
|
|
||||||
my $msgstart = pack('H*', "81");# Every msg starts wit this
|
my $msgstart = pack('H*', "81");# Every msg starts wit this
|
||||||
|
|
||||||
@ -82,7 +83,37 @@ FHZ_Ready($)
|
|||||||
{
|
{
|
||||||
my ($hash) = @_;
|
my ($hash) = @_;
|
||||||
my $po=$hash->{PortObj};
|
my $po=$hash->{PortObj};
|
||||||
return undef if !$po;
|
|
||||||
|
if(!$po) { # Looking for the device
|
||||||
|
|
||||||
|
my $dev = $hash->{DeviceName};
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
|
||||||
|
$hash->{PARTIAL} = "";
|
||||||
|
if ($^O=~/Win/) {
|
||||||
|
$po = new Win32::SerialPort ($dev);
|
||||||
|
} else {
|
||||||
|
$po = new Device::SerialPort ($dev);
|
||||||
|
}
|
||||||
|
return undef if(!$po);
|
||||||
|
|
||||||
|
Log 1, "USB device $dev reappeared";
|
||||||
|
$hash->{PortObj} = $po;
|
||||||
|
if( $^O !~ /Win/ ) {
|
||||||
|
$hash->{FD} = $po->FILENO;
|
||||||
|
delete($readyfnlist{"$name.$dev"});
|
||||||
|
$selectlist{"$name.$dev"} = $hash;
|
||||||
|
} else {
|
||||||
|
$readyfnlist{"$name.$dev"} = $hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
FHZ_DoInit($name, $hash->{ttytype}, $po);
|
||||||
|
DoTrigger($name, "CONNECTED");
|
||||||
|
return undef;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# This is relevant for windows only
|
||||||
my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags)=$po->status;
|
my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags)=$po->status;
|
||||||
return ($InBytes>0);
|
return ($InBytes>0);
|
||||||
}
|
}
|
||||||
@ -206,7 +237,7 @@ FHZ_SetState($$$$)
|
|||||||
|
|
||||||
#####################################
|
#####################################
|
||||||
sub
|
sub
|
||||||
DoInit($$$)
|
FHZ_DoInit($$$)
|
||||||
{
|
{
|
||||||
my ($name,$type,$po) = @_;
|
my ($name,$type,$po) = @_;
|
||||||
my @init;
|
my @init;
|
||||||
@ -257,6 +288,8 @@ DoInit($$$)
|
|||||||
my $hash = $defs{$name};
|
my $hash = $defs{$name};
|
||||||
delete($hash->{XMIT_TIME});
|
delete($hash->{XMIT_TIME});
|
||||||
delete($hash->{NR_CMD_LAST_H});
|
delete($hash->{NR_CMD_LAST_H});
|
||||||
|
$hash->{STATE} = "Initialized";
|
||||||
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
#####################################
|
#####################################
|
||||||
@ -266,7 +299,9 @@ FHZ_Define($$)
|
|||||||
my ($hash, $def) = @_;
|
my ($hash, $def) = @_;
|
||||||
my @a = split("[ \t][ \t]*", $def);
|
my @a = split("[ \t][ \t]*", $def);
|
||||||
my $po;
|
my $po;
|
||||||
$hash->{STATE} = "Initialized";
|
|
||||||
|
return "wrong syntax: define <name> FHZ devicename ".
|
||||||
|
"[normal|strangetty] [mobile]" if(@a < 3 || @a > 5);
|
||||||
|
|
||||||
delete $hash->{PortObj};
|
delete $hash->{PortObj};
|
||||||
delete $hash->{FD};
|
delete $hash->{FD};
|
||||||
@ -274,6 +309,8 @@ FHZ_Define($$)
|
|||||||
my $name = $a[0];
|
my $name = $a[0];
|
||||||
my $dev = $a[2];
|
my $dev = $a[2];
|
||||||
$hash->{ttytype} = $a[3] if($a[3]);
|
$hash->{ttytype} = $a[3] if($a[3]);
|
||||||
|
$hash->{MOBILE} = 1 if($a[4] && $a[4] eq "mobile");
|
||||||
|
$hash->{STATE} = "defined";
|
||||||
|
|
||||||
$attr{$name}{savefirst} = 1;
|
$attr{$name}{savefirst} = 1;
|
||||||
$attr{$name}{fhtsoftbuffer} = 0;
|
$attr{$name}{fhtsoftbuffer} = 0;
|
||||||
@ -284,6 +321,8 @@ FHZ_Define($$)
|
|||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$hash->{DeviceName} = $dev;
|
||||||
|
$hash->{PARTIAL} = "";
|
||||||
Log 3, "FHZ opening FHZ device $dev";
|
Log 3, "FHZ opening FHZ device $dev";
|
||||||
if ($^O=~/Win/) {
|
if ($^O=~/Win/) {
|
||||||
require Win32::SerialPort;
|
require Win32::SerialPort;
|
||||||
@ -292,7 +331,13 @@ FHZ_Define($$)
|
|||||||
require Device::SerialPort;
|
require Device::SerialPort;
|
||||||
$po = new Device::SerialPort ($dev);
|
$po = new Device::SerialPort ($dev);
|
||||||
}
|
}
|
||||||
return "Can't open $dev: $!\n" if(!$po);
|
if(!$po) {
|
||||||
|
my $msg = "Can't open $dev: $!";
|
||||||
|
Log(3, $msg) if($hash->{MOBILE});
|
||||||
|
return $msg if(!$hash->{MOBILE});
|
||||||
|
$readyfnlist{"$name.$dev"} = $hash;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
Log 3, "FHZ opened FHZ device $dev";
|
Log 3, "FHZ opened FHZ device $dev";
|
||||||
|
|
||||||
$hash->{PortObj} = $po;
|
$hash->{PortObj} = $po;
|
||||||
@ -302,11 +347,8 @@ FHZ_Define($$)
|
|||||||
} else {
|
} else {
|
||||||
$readyfnlist{"$name.$dev"} = $hash;
|
$readyfnlist{"$name.$dev"} = $hash;
|
||||||
}
|
}
|
||||||
$hash->{DeviceName} = $dev;
|
|
||||||
$hash->{PARTIAL} = "";
|
|
||||||
|
|
||||||
DoInit($name, $hash->{ttytype}, $po);
|
|
||||||
|
|
||||||
|
FHZ_DoInit($name, $hash->{ttytype}, $po);
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,20 +583,20 @@ FHZ_Reopen($)
|
|||||||
{
|
{
|
||||||
my ($hash) = @_;
|
my ($hash) = @_;
|
||||||
|
|
||||||
my $devname = $hash->{DeviceName};
|
my $dev = $hash->{DeviceName};
|
||||||
$hash->{PortObj}->close();
|
$hash->{PortObj}->close();
|
||||||
Log 1, "USB device $devname closed";
|
Log 1, "USB device $dev closed";
|
||||||
for(;;) {
|
for(;;) {
|
||||||
sleep(5);
|
sleep(5);
|
||||||
if ($^O eq 'MSWin32') {
|
if ($^O eq 'MSWin32') {
|
||||||
$hash->{PortObj} = new Win32::SerialPort($devname);
|
$hash->{PortObj} = new Win32::SerialPort($dev);
|
||||||
}else{
|
}else{
|
||||||
$hash->{PortObj} = new Device::SerialPort($devname);
|
$hash->{PortObj} = new Device::SerialPort($dev);
|
||||||
}
|
}
|
||||||
if($hash->{PortObj}) {
|
if($hash->{PortObj}) {
|
||||||
Log 1, "USB device $devname reopened";
|
Log 1, "USB device $dev reopened";
|
||||||
$hash->{FD} = $hash->{PortObj}->FILENO if !($^O eq 'MSWin32');
|
$hash->{FD} = $hash->{PortObj}->FILENO if !($^O eq 'MSWin32');
|
||||||
DoInit($hash->{NAME}, $hash->{ttytype}, $hash->{PortObj});
|
FHZ_DoInit($hash->{NAME}, $hash->{ttytype}, $hash->{PortObj});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -578,26 +620,22 @@ FHZ_Read($)
|
|||||||
|
|
||||||
if(!defined($buf) || length($buf) == 0) {
|
if(!defined($buf) || length($buf) == 0) {
|
||||||
|
|
||||||
my $devname = $hash->{DeviceName};
|
my $dev = $hash->{DeviceName};
|
||||||
Log 1, "USB device $devname disconnected, waiting to reappear";
|
Log 1, "USB device $dev disconnected, waiting to reappear";
|
||||||
$hash->{PortObj}->close();
|
$hash->{PortObj}->close();
|
||||||
for(;;) {
|
DoTrigger($name, "DISCONNECTED");
|
||||||
sleep(5);
|
|
||||||
if ($^O eq 'MSWin32') {
|
|
||||||
$hash->{PortObj} = new Win32::SerialPort($devname);
|
|
||||||
}else{
|
|
||||||
$hash->{PortObj} = new Device::SerialPort($devname);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($hash->{PortObj}) {
|
delete($hash->{PortObj});
|
||||||
Log 1, "USB device $devname reappeared";
|
delete($selectlist{"$name.$dev"});
|
||||||
$hash->{FD} = $hash->{PortObj}->FILENO if !($^O eq 'MSWin32');
|
$readyfnlist{"$name.$dev"} = $hash; # Start polling
|
||||||
DoInit($name, $hash->{ttytype}, $hash->{PortObj});
|
$hash->{STATE} = "disconnected";
|
||||||
return;
|
|
||||||
}
|
# Without the following sleep the open of the device causes a SIGSEGV,
|
||||||
}
|
# and following opens block infinitely. Only a reboot helps.
|
||||||
|
sleep(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
my $fhzdata = $hash->{PARTIAL};
|
my $fhzdata = $hash->{PARTIAL};
|
||||||
Log 5, "FHZ/RAW: " . unpack('H*',$buf) .
|
Log 5, "FHZ/RAW: " . unpack('H*',$buf) .
|
||||||
" (Unparsed: " . unpack('H*', $fhzdata) . ")";
|
" (Unparsed: " . unpack('H*', $fhzdata) . ")";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user