2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 12:49:34 +00:00

00_KNXIO.pm: bugfixes & PBP optimization (Forum #127792)

git-svn-id: https://svn.fhem.de/fhem/trunk@29336 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
erwin 2024-11-07 13:44:10 +00:00
parent c5903f32f8
commit 043ea7c201

View File

@ -82,6 +82,9 @@
# 25/04/2024 changed _open for mode S # 25/04/2024 changed _open for mode S
# replaced/removed experimental given/when # replaced/removed experimental given/when
# 19/08/2024 fix error-msg when mode S fails to open # 19/08/2024 fix error-msg when mode S fails to open
# xx/11/2024 replace getimeofday w. Time::HiRes::time
# use AttrNum instead of AttrVal where possible
# PBP remove postfix if
package KNXIO; ## no critic 'package' package KNXIO; ## no critic 'package'
@ -90,7 +93,7 @@ use strict;
use warnings; use warnings;
use IO::Socket; use IO::Socket;
use English qw(-no_match_vars); use English qw(-no_match_vars);
use Time::HiRes qw(gettimeofday); use Time::HiRes qw(time);
use DevIo qw(DevIo_OpenDev DevIo_SimpleWrite DevIo_SimpleRead DevIo_CloseDev DevIo_Disconnected DevIo_IsOpen); use DevIo qw(DevIo_OpenDev DevIo_SimpleWrite DevIo_SimpleRead DevIo_CloseDev DevIo_Disconnected DevIo_IsOpen);
use TcpServerUtils qw(TcpServer_Open TcpServer_SetLoopbackMode TcpServer_MCastAdd TcpServer_MCastRemove use TcpServerUtils qw(TcpServer_Open TcpServer_SetLoopbackMode TcpServer_MCastAdd TcpServer_MCastRemove
TcpServer_MCastSend TcpServer_MCastRecv TcpServer_Close); TcpServer_MCastSend TcpServer_MCastRecv TcpServer_Close);
@ -101,11 +104,11 @@ use GPUtils qw(GP_Import); # Package Helper Fn
# these ones are NOT used! (constants,Policy::Modules::RequireFilenameMatchesPackage,NamingConventions::Capitalization) # these ones are NOT used! (constants,Policy::Modules::RequireFilenameMatchesPackage,NamingConventions::Capitalization)
# these ones are NOT used! (RegularExpressions::RequireDotMatchAnything,RegularExpressions::RequireLineBoundaryMatching) # these ones are NOT used! (RegularExpressions::RequireDotMatchAnything,RegularExpressions::RequireLineBoundaryMatching)
# these ones are NOT used! (ControlStructures::ProhibitCascadingIfElse) # these ones are NOT used! (ControlStructures::ProhibitCascadingIfElse)
# these ones are NOT used! (ControlStructures::ProhibitPostfixControls)
### the following percritic items will be ignored global ### ### the following percritic items will be ignored global ###
## no critic (NamingConventions::Capitalization) ## no critic (NamingConventions::Capitalization)
## no critic (Policy::CodeLayout::ProhibitParensWithBuiltins) ## no critic (Policy::CodeLayout::ProhibitParensWithBuiltins)
## no critic (ValuesAndExpressions::RequireNumberSeparators,ValuesAndExpressions::ProhibitMagicNumbers) ## no critic (ValuesAndExpressions::RequireNumberSeparators,ValuesAndExpressions::ProhibitMagicNumbers)
## no critic (ControlStructures::ProhibitPostfixControls)
## no critic (Documentation::RequirePodSections) ## no critic (Documentation::RequirePodSections)
### import FHEM functions / global vars ### import FHEM functions / global vars
@ -174,7 +177,7 @@ sub KNXIO_Define {
my $name = $arg[0] // return 'KNXIO-define: no name specified'; my $name = $arg[0] // return 'KNXIO-define: no name specified';
$hash->{NAME} = $name; $hash->{NAME} = $name;
$SVNID =~ s/.+[.]pm\s(\S+\s\S+).+/$1/ixms; $SVNID =~ s/.+[.]pm\s(\S+\s\S+).+/$1/ixms;
$hash->{SVN} = $SVNID; # store svn info in dev hash $hash->{'.SVN'} = $SVNID; # store svn info in dev hash
if ((scalar(@arg) >= 3) && $arg[2] !~ /[HMSTX]/xms) { if ((scalar(@arg) >= 3) && $arg[2] !~ /[HMSTX]/xms) {
return q{KNXIO-define: invalid mode specified, valid modes are one of: H M S T X}; return q{KNXIO-define: invalid mode specified, valid modes are one of: H M S T X};
@ -183,10 +186,12 @@ sub KNXIO_Define {
$hash->{model} = $mode; # use it also for fheminfo statistics $hash->{model} = $mode; # use it also for fheminfo statistics
# handle mode X for FHEM2FHEM configs # handle mode X for FHEM2FHEM configs
return InternalTimer(gettimeofday() + 0.2,\&KNXIO_openDev,$hash) if ($mode eq q{X}); return InternalTimer(Time::HiRes::time() + 0.2,\&KNXIO_openDev,$hash) if ($mode eq q{X});
return q{KNXIO-define syntax: "define <name> KNXIO <H|M|T> <ip-address|hostname>:<port> <phy-adress>" } . "\n" . if (scalar(@arg) < 5) {
q{ or "define <name> KNXIO S <pathToUnixSocket> <phy-address>" } if (scalar(@arg) < 5); return q{KNXIO-define syntax: "define <name> KNXIO <H|M|T> <ip-address|hostname>:<port> <phy-adress>" } . "\n" .
q{ or "define <name> KNXIO S <pathToUnixSocket> <phy-address>" };
}
my ($host,$port) = split(/[:]/xms,$arg[3]); my ($host,$port) = split(/[:]/xms,$arg[3]);
@ -197,8 +202,10 @@ sub KNXIO_Define {
if ($mode eq q{M}) { # multicast if ($mode eq q{M}) { # multicast
my $host1 = (split(/[.]/xms,$host))[0]; my $host1 = (split(/[.]/xms,$host))[0];
return q{KNXIO-define: Multicast address is not in the range of 224.0.0.0 and 239.255.255.255 } . if ($host1 < 224 || $host1 > 239) {
q{(default is 224.0.23.12:3671) } if ($host1 < 224 || $host1 > 239); return q{KNXIO-define: Multicast address is not in the range of 224.0.0.0 and 239.255.255.255 } .
q{(default is 224.0.23.12:3671) };
}
$hash->{DeviceName} = $host . q{:} . $port; $hash->{DeviceName} = $host . q{:} . $port;
} }
elsif ($mode eq q{S}) { elsif ($mode eq q{S}) {
@ -230,15 +237,15 @@ sub KNXIO_Define {
my $phytemp = KNXIO_hex2addr($phyaddr); my $phytemp = KNXIO_hex2addr($phyaddr);
$hash->{PhyAddr} = KNXIO_addr2hex($phytemp,2); #convert 2 times for correcting input! $hash->{PhyAddr} = KNXIO_addr2hex($phytemp,2); #convert 2 times for correcting input!
KNXIO_closeDev($hash) if ($init_done && exists($hash->{OLDDEF})); # modify definition.... if ($init_done && exists($hash->{OLDDEF})) {KNXIO_closeDev($hash);} # modify definition....
$hash->{devioLoglevel} = 4; #032023 $hash->{devioLoglevel} = 4; #032023
$hash->{devioNoSTATE} = 1; $hash->{devioNoSTATE} = 1;
$hash->{PARTIAL} = q{}; $hash->{PARTIAL} = q{};
# define helpers # define helpers
$hash->{KNXIOhelper}->{FIFO} = []; # read fifo array $hash->{KNXIOhelper}->{FIFO} = []; # read fifo array
$hash->{KNXIOhelper}->{FIFOW} = []; # write fifo array $hash->{KNXIOhelper}->{FIFOW} = []; # write fifo array
# Devio-parameters # Devio-parameters
$hash->{nextOpenDelay} = $reconnectTO; $hash->{nextOpenDelay} = $reconnectTO;
@ -248,9 +255,7 @@ sub KNXIO_Define {
KNXIO_Log ($name, 3, qq{opening mode=$mode}); KNXIO_Log ($name, 3, qq{opening mode=$mode});
if (! $init_done) { return InternalTimer(Time::HiRes::time() + 0.2,\&KNXIO_openDev,$hash) if (! $init_done);
return InternalTimer(gettimeofday() + 0.2,\&KNXIO_openDev,$hash);
}
return KNXIO_openDev($hash); return KNXIO_openDev($hash);
} }
@ -262,7 +267,7 @@ sub KNXIO_Attr {
if ($cmd eq 'set' && defined($aVal) && $aVal == 1) { if ($cmd eq 'set' && defined($aVal) && $aVal == 1) {
KNXIO_closeDev($hash); KNXIO_closeDev($hash);
} elsif ($cmd eq 'del') { } elsif ($cmd eq 'del') {
InternalTimer(gettimeofday() + 0.2,\&KNXIO_openDev,$hash); InternalTimer(Time::HiRes::time() + 0.2,\&KNXIO_openDev,$hash);
} }
} }
elsif ($cmd eq 'set' && $aName eq 'enableKNXscan' && defined($aVal) && $aVal !~ /[0-2]/xms) { elsif ($cmd eq 'set' && $aName eq 'enableKNXscan' && defined($aVal) && $aVal !~ /[0-2]/xms) {
@ -350,7 +355,7 @@ sub KNXIO_ReadM {
my $buf = shift; my $buf = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
$buf = $hash->{PARTIAL} . $buf if (defined($hash->{PARTIAL})); if (defined($hash->{PARTIAL})) {$buf = $hash->{PARTIAL} . $buf; }
if (length($buf) < 6) { # min required for first unpack if (length($buf) < 6) { # min required for first unpack
$hash->{PARTIAL} = $buf; $hash->{PARTIAL} = $buf;
return; return;
@ -446,7 +451,7 @@ sub KNXIO_ReadH {
KNXIO_handleConn($hash); KNXIO_handleConn($hash);
$hash->{KNXIOhelper}->{SEQUENCECNTR} = 0; $hash->{KNXIOhelper}->{SEQUENCECNTR} = 0;
InternalTimer(gettimeofday() + 60, \&KNXIO_keepAlive, $hash); # start keepalive InternalTimer(Time::HiRes::time() + 60, \&KNXIO_keepAlive, $hash); # start keepalive
return; return;
}, },
0x0208 => sub { # ConnectionState response 0x0208 => sub { # ConnectionState response
@ -459,7 +464,7 @@ sub KNXIO_ReadH {
KNXIO_disconnect($hash,2); KNXIO_disconnect($hash,2);
return; return;
} }
InternalTimer(gettimeofday() + 60, \&KNXIO_keepAlive, $hash); InternalTimer(Time::HiRes::time() + 60, \&KNXIO_keepAlive, $hash);
return; return;
}, },
0x0209 => sub { # Disconnect request 0x0209 => sub { # Disconnect request
@ -482,16 +487,18 @@ sub KNXIO_ReadH {
my $cntrdiff = $rxseqcntr - $hash->{KNXIOhelper}->{SEQUENCECNTR}; my $cntrdiff = $rxseqcntr - $hash->{KNXIOhelper}->{SEQUENCECNTR};
if ($cntrdiff == -1) { if ($cntrdiff == -1) {
KNXIO_Log ($name, 3, q{TunnelRequest duplicate message received: } . KNXIO_Log ($name, 3, q{TunnelRequest duplicate message received: } .
qq{(seqcntr= $rxseqcntr ) - ack it}); qq{(seqcntr= $rxseqcntr ) - ack it});
$discardFrame = 1; # one packet duplicate... we ack it but do not process $discardFrame = 1; # one packet duplicate... we ack it but do not process
} }
elsif ($cntrdiff != 0) { # really out of sequence elsif ($cntrdiff != 0) { # really out of sequence
KNXIO_Log ($name, 3, q{TunnelRequest messaage out of sequence received: } . KNXIO_Log ($name, 3, q{TunnelRequest messaage out of sequence received: } .
qq{(seqcntrRx= $rxseqcntr seqcntrTx= $hash->{KNXIOhelper}->{SEQUENCECNTR} ) - no ack & discard}); qq{(seqcntrRx= $rxseqcntr seqcntrTx= $hash->{KNXIOhelper}->{SEQUENCECNTR} ) - no ack & discard});
return; return;
} }
KNXIO_Log ($name, 4, q{TunnelRequest received - send Ack and decode. } . if (! defined($discardFrame)) {
qq{seqcntrRx= $hash->{KNXIOhelper}->{SEQUENCECNTR}} ) if (! defined($discardFrame)); KNXIO_Log ($name, 4, q{TunnelRequest received - send Ack and decode. } .
qq{seqcntrRx= $hash->{KNXIOhelper}->{SEQUENCECNTR}} );
}
my $tacksend = pack('nnnCCCC',0x0610,0x0421,10,4,$ccid,$rxseqcntr,0); # send ack my $tacksend = pack('nnnCCCC',0x0610,0x0421,10,4,$ccid,$rxseqcntr,0); # send ack
$hash->{KNXIOhelper}->{SEQUENCECNTR} = ($rxseqcntr + 1) % 256; $hash->{KNXIOhelper}->{SEQUENCECNTR} = ($rxseqcntr + 1) % 256;
::DevIo_SimpleWrite($hash,$tacksend,0); ::DevIo_SimpleWrite($hash,$tacksend,0);
@ -524,7 +531,7 @@ sub KNXIO_ReadH {
return; return;
} }
::DevIo_SimpleWrite($hash,$msg,0) if(defined($msg)); # send msg if(defined($msg)) {::DevIo_SimpleWrite($hash,$msg,0); } # send msg
return; return;
} }
@ -617,15 +624,15 @@ sub KNXIO_Write2 {
return if($count == 0); return if($count == 0);
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $timenow = gettimeofday(); my $timenow = Time::HiRes::time();
my $nextwrite = $hash->{KNXIOhelper}->{nextWrite} // $timenow; my $nextwrite = $hash->{KNXIOhelper}->{nextWrite} // $timenow;
my $adddelay = 0.07; my $adddelay = 0.07;
if ($nextwrite > $timenow) { if ($nextwrite > $timenow) {
KNXIO_Log ($name, 3, qq{frequent IO-write - msg-count= $count}) if ($count % 10 == 0); if ($count % 10 == 0) {KNXIO_Log ($name, 3, qq{frequent IO-write - msg-count= $count}); }
KNXIO_Debug ($name, 1, qq{frequent IO-write - msg-count= $count}); KNXIO_Debug ($name, 1, qq{frequent IO-write - msg-count= $count});
InternalTimer($nextwrite + $adddelay, \&KNXIO_Write2,$hash); InternalTimer($nextwrite + $adddelay, \&KNXIO_Write2,$hash);
InternalTimer($timenow + 30.0, \&KNXIO_Flooding,$hash) if ($count == 1); if ($count == 1) {InternalTimer($timenow + 30.0, \&KNXIO_Flooding,$hash);}
return; return;
} }
@ -745,7 +752,7 @@ sub KNXIO_Set {
if (ReadingsVal($name,'state','disconnected') eq 'connected') { if (ReadingsVal($name,'state','disconnected') eq 'connected') {
return qq{$name is connected, no action taken}; return qq{$name is connected, no action taken};
} }
elsif (AttrVal($name,'disable',0) == 1) { elsif (AttrNum($name,'disable',0) == 1) {
return qq{$name is disabled, no action taken}; return qq{$name is disabled, no action taken};
} }
} }
@ -757,7 +764,7 @@ sub KNXIO_Set {
return qq{invalid set cmd $cmd}; return qq{invalid set cmd $cmd};
} }
InternalTimer(gettimeofday() + $adddelay, \&KNXIO_openDev, $hash); InternalTimer(Time::HiRes::time() + $adddelay, \&KNXIO_openDev, $hash);
return; return;
} }
@ -768,12 +775,12 @@ sub KNXIO_Set {
### return from open (sucess/failure) ### return from open (sucess/failure)
sub KNXIO_callback { sub KNXIO_callback {
my $hash = shift; my $hash = shift;
my $err = shift; my $err = shift;
$hash->{nextOpenDelay} = $reconnectTO; $hash->{nextOpenDelay} = $reconnectTO;
if (defined($err)) { if (defined($err) && $err) {
KNXIO_Log ($hash, 2, qq{device open $hash->{NAME} failed with: $err}) if ($err); KNXIO_Log ($hash, 2, qq{device open $hash->{NAME} failed with: $err});
$hash->{NEXT_OPEN} = gettimeofday() + $hash->{nextOpenDelay}; $hash->{NEXT_OPEN} = Time::HiRes::time() + $hash->{nextOpenDelay};
} }
return; return;
} }
@ -822,7 +829,7 @@ sub KNXIO_openDev {
KNXIO_Log ($name, 2, q{DNS failed, check ip/hostname}); KNXIO_Log ($name, 2, q{DNS failed, check ip/hostname});
return; return;
} }
InternalTimer(gettimeofday() + 1,\&KNXIO_openDev,$hash); InternalTimer(Time::HiRes::time() + 1,\&KNXIO_openDev,$hash);
KNXIO_Log ($name, 2, q{waiting for DNS}); KNXIO_Log ($name, 2, q{waiting for DNS});
return; # waiting for DNS return; # waiting for DNS
} }
@ -841,7 +848,7 @@ sub KNXIO_openDev {
delete $hash->{TCPDev}; # devio ? delete $hash->{TCPDev}; # devio ?
$ret = ::TcpServer_Open($hash, $port, $host, 1); $ret = ::TcpServer_Open($hash, $port, $host, 1);
if (defined($ret)) { # error if (defined($ret)) { # error
KNXIO_Log ($name, 2, qq{can't connect: $ret}) if(!$reopen); if(!$reopen) {KNXIO_Log ($name, 2, qq{can't connect: $ret});}
return qq{KNXIO_openDev ($name): can't connect: $ret}; return qq{KNXIO_openDev ($name): can't connect: $ret};
} }
$ret = ::TcpServer_MCastAdd($hash,$host); $ret = ::TcpServer_MCastAdd($hash,$host);
@ -871,7 +878,7 @@ sub KNXIO_openDev {
my $conn = 0; my $conn = 0;
$conn = IO::Socket::INET->new(PeerAddr => "$host:$port", Type => SOCK_DGRAM, Proto => 'udp', Reuse => 1); $conn = IO::Socket::INET->new(PeerAddr => "$host:$port", Type => SOCK_DGRAM, Proto => 'udp', Reuse => 1);
if (!($conn)) { if (!($conn)) {
KNXIO_Log ($name, 2, qq{can't connect: $ERRNO}) if(!$reopen); if(!$reopen) {KNXIO_Log ($name, 2, qq{can't connect: $ERRNO});}
KNXIO_disconnect($hash); KNXIO_disconnect($hash);
readingsSingleUpdate($hash, 'state', 'disconnected', 1); readingsSingleUpdate($hash, 'state', 'disconnected', 1);
return; return;
@ -937,7 +944,7 @@ sub KNXIO_init {
elsif ($mode eq 'H') { elsif ($mode eq 'H') {
my $connreq = KNXIO_prepareConnRequ($hash); my $connreq = KNXIO_prepareConnRequ($hash);
::DevIo_SimpleWrite($hash,$connreq,0); ::DevIo_SimpleWrite($hash,$connreq,0);
InternalTimer(gettimeofday() + 2, \&KNXIO_openTO, $hash); InternalTimer(Time::HiRes::time() + 2, \&KNXIO_openTO, $hash);
} }
# state 'connected' is set in decode_EMI (model ST) or in readH (model H) # state 'connected' is set in decode_EMI (model ST) or in readH (model H)
@ -954,17 +961,19 @@ sub KNXIO_handleConn {
my $hash = shift; my $hash = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
RemoveInternalTimer($hash, \&KNXIO_openTO) if ($hash->{model} eq q{H}); if ($hash->{model} eq q{H}) {RemoveInternalTimer($hash, \&KNXIO_openTO)};
if (exists($hash->{KNXIOhelper}->{startdone})) { if (exists($hash->{KNXIOhelper}->{startdone})) {
KNXIO_Log ($name, 3, q{connected}); KNXIO_Log ($name, 3, q{connected});
readingsSingleUpdate($hash, 'state', 'connected', 1); readingsSingleUpdate($hash, 'state', 'connected', 1);
main::KNX_scan('TYPE=KNX:FILTER=IODev=' . $name) if (AttrNum($name,'enableKNXscan',0) >= 2); # on every connect if (AttrNum($name,'enableKNXscan',0) == 2) { # on every connect
main::KNX_scan('TYPE=KNX:FILTER=IODev=' . $name);
}
} }
else { # fhem start else { # fhem start
KNXIO_Log ($name, 3, q{initial-connect}); KNXIO_Log ($name, 3, q{initial-connect});
readingsSingleUpdate($hash, 'state', 'connected', 0); # no event readingsSingleUpdate($hash, 'state', 'connected', 0); # no event
InternalTimer(gettimeofday() + 30, \&KNXIO_initcomplete, $hash); InternalTimer(Time::HiRes::time() + 30, \&KNXIO_initcomplete, $hash);
} }
return; return;
} }
@ -978,12 +987,14 @@ sub KNXIO_initcomplete {
RemoveInternalTimer($hash,\&KNXIO_initcomplete); RemoveInternalTimer($hash,\&KNXIO_initcomplete);
my $name = $hash->{NAME}; my $name = $hash->{NAME};
if (ReadingsVal($name,'state','disconnected') eq 'connected') { if (ReadingsVal($name,'state','disconnected') eq 'connected') {
main::KNX_scan('TYPE=KNX:FILTER=IODev=' . $name) if (AttrNum($name,'enableKNXscan',0) >= 1); # on 1st connect only if (AttrNum($name,'enableKNXscan',0) == 1) { # on 1st connect only
main::KNX_scan('TYPE=KNX:FILTER=IODev=' . $name);
}
$hash->{KNXIOhelper}->{startdone} = 1; $hash->{KNXIOhelper}->{startdone} = 1;
DoTrigger($name,'INITIALIZED'); DoTrigger($name,'INITIALIZED');
readingsSingleUpdate($hash, 'state', 'connected', 1); # now do event readingsSingleUpdate($hash, 'state', 'connected', 1); # now do event
} }
elsif (AttrVal($name,'disable', 0) != 1) { elsif (AttrNum($name,'disable', 0) != 1) {
KNXIO_Log ($name, 3, q{failed}); KNXIO_Log ($name, 3, q{failed});
} }
return; return;
@ -1019,7 +1030,9 @@ sub KNXIO_dispatch {
my $buf = shift; my $buf = shift;
my @que = []; my @que = [];
@que = @{$hash->{KNXIOhelper}->{FIFO}} if (defined($hash->{KNXIOhelper}->{FIFO}) && ($hash->{KNXIOhelper}->{FIFO} ne q{})); if (defined($hash->{KNXIOhelper}->{FIFO}) && ($hash->{KNXIOhelper}->{FIFO} ne q{})) {
@que = @{$hash->{KNXIOhelper}->{FIFO}};
}
push (@que,$buf); push (@que,$buf);
@{$hash->{KNXIOhelper}->{FIFO}} = @que; @{$hash->{KNXIOhelper}->{FIFO}} = @que;
@ -1057,7 +1070,7 @@ sub KNXIO_processFIFO {
@que = KNXIO_deldupes(@que); @que = KNXIO_deldupes(@que);
$queentries = scalar(@que); $queentries = scalar(@que);
my $qdiff = $queentriesOld - $queentries; my $qdiff = $queentriesOld - $queentries;
KNXIO_Log ($name, 3, qq{deleted $qdiff duplicate msgs from queue, $queentries remain}) if ($qdiff > 0);; if ($qdiff > 0) {KNXIO_Log ($name, 3, qq{deleted $qdiff duplicate msgs from queue, $queentries remain});}
} }
if ($queentries > 0) { # process timer is not running & fifo not empty if ($queentries > 0) { # process timer is not running & fifo not empty
@ -1066,7 +1079,7 @@ sub KNXIO_processFIFO {
KNXIO_Log ($name, 4, qq{dispatching buf=$msg Nr_msgs=$queentries}); KNXIO_Log ($name, 4, qq{dispatching buf=$msg Nr_msgs=$queentries});
KNXIO_dispatch2($hash, $msg); KNXIO_dispatch2($hash, $msg);
if ($queentries > 1) { if ($queentries > 1) {
InternalTimer(gettimeofday() + 0.05, \&KNXIO_processFIFO, $hash); # allow time for new/duplicate msgs to be read InternalTimer(Time::HiRes::time() + 0.05, \&KNXIO_processFIFO, $hash); # allow time for new/duplicate msgs to be read
} }
return; return;
} }
@ -1098,7 +1111,7 @@ sub KNXIO_disconnect {
KNXIO_Log ($name, 1, q{disconnected, waiting to reappear}); KNXIO_Log ($name, 1, q{disconnected, waiting to reappear});
$readyfnlist{"$name.$param"} = $hash; # Start polling $readyfnlist{"$name.$param"} = $hash; # Start polling
$hash->{NEXT_OPEN} = gettimeofday() + $opendelay; $hash->{NEXT_OPEN} = Time::HiRes::time() + $opendelay;
return; return;
} }
@ -1114,7 +1127,7 @@ sub KNXIO_closeDev {
} }
else { else {
::DevIo_CloseDev($hash); ::DevIo_CloseDev($hash);
$hash->{TCPDev}->close() if($hash->{FD}); if ($hash->{FD}) {$hash->{TCPDev}->close();}
} }
delete $hash->{stacktrace}; # clean delete $hash->{stacktrace}; # clean
@ -1128,7 +1141,7 @@ sub KNXIO_closeDev {
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
KNXIO_Log ($name, 3, q{closed}) if ($init_done);; if ($init_done) { KNXIO_Log ($name, 3, q{closed}); }
readingsSingleUpdate($hash, 'state', 'disconnected', 1); readingsSingleUpdate($hash, 'state', 'disconnected', 1);
@ -1183,7 +1196,7 @@ sub KNXIO_decodeEMI {
} }
$data[0] = ($data[0] & 0x3f); # 6 bit data in byte 0 $data[0] = ($data[0] & 0x3f); # 6 bit data in byte 0
shift @data if (scalar(@data) > 1 ); # byte 0 is ununsed if length > 1 if (scalar(@data) > 1 ) {shift @data;} # byte 0 is ununsed if length > 1
my $outbuf = $KNXID . $src . substr($rwp,0,1) . $dst . sprintf('%02x' x scalar(@data),@data); my $outbuf = $KNXID . $src . substr($rwp,0,1) . $dst . sprintf('%02x' x scalar(@data),@data);
KNXIO_Log ($name, 5, qq{outbuf=$outbuf}); KNXIO_Log ($name, 5, qq{outbuf=$outbuf});
@ -1242,7 +1255,7 @@ sub KNXIO_decodeCEMI {
$dst = KNXIO_addr2hex($dst,$dest_addrType); $dst = KNXIO_addr2hex($dst,$dest_addrType);
$data[0] = ($data[0] & 0x3f); # 6 bit data in byte 0 $data[0] = ($data[0] & 0x3f); # 6 bit data in byte 0
shift @data if (scalar(@data) > 1 ); # byte 0 is ununsed if length > 1 if (scalar(@data) > 1 ) {shift @data;} # byte 0 is ununsed if length > 1
my $outbuf = $KNXID . $src . substr($rwp,0,1) . $dst . sprintf('%02x' x scalar(@data),@data); my $outbuf = $KNXID . $src . substr($rwp,0,1) . $dst . sprintf('%02x' x scalar(@data),@data);
KNXIO_Log ($name, 5, qq{outbuf=$outbuf}); KNXIO_Log ($name, 5, qq{outbuf=$outbuf});
@ -1291,7 +1304,7 @@ sub KNXIO_keepAlive {
my $msg = pack('nnnCCnnnn',(0x0610,0x0207,16,$hash->{KNXIOhelper}->{CCID},0, 0x0801,0,0,0)); my $msg = pack('nnnCCnnnn',(0x0610,0x0207,16,$hash->{KNXIOhelper}->{CCID},0, 0x0801,0,0,0));
RemoveInternalTimer($hash,\&KNXIO_keepAlive); RemoveInternalTimer($hash,\&KNXIO_keepAlive);
::DevIo_SimpleWrite($hash,$msg,0); # send conn state requ ::DevIo_SimpleWrite($hash,$msg,0); # send conn state requ
InternalTimer(gettimeofday() + 2,\&KNXIO_keepAliveTO,$hash); # set timeout timer - reset by ConnectionStateResponse InternalTimer(Time::HiRes::time() + 2,\&KNXIO_keepAliveTO,$hash); # set timeout timer - reset by ConnectionStateResponse
return; return;
} }
@ -1322,7 +1335,7 @@ sub KNXIO_TunnelRequestTO {
my $msg = pack('H*',$hash->{KNXIOhelper}->{LASTSENTMSG}); my $msg = pack('H*',$hash->{KNXIOhelper}->{LASTSENTMSG});
::DevIo_SimpleWrite($hash,$msg,0); ::DevIo_SimpleWrite($hash,$msg,0);
delete $hash->{KNXIOhelper}->{LASTSENTMSG}; delete $hash->{KNXIOhelper}->{LASTSENTMSG};
InternalTimer(gettimeofday() + 1.5, \&KNXIO_TunnelRequestTO, $hash); InternalTimer(Time::HiRes::time() + 1.5, \&KNXIO_TunnelRequestTO, $hash);
return; return;
} }
@ -1341,7 +1354,7 @@ sub KNXIO_openTO {
KNXIO_Log ($hash, 3, q{open timeout occured, attempt retry}); KNXIO_Log ($hash, 3, q{open timeout occured, attempt retry});
KNXIO_closeDev($hash); KNXIO_closeDev($hash);
InternalTimer(gettimeofday() + $reconnectTO,\&KNXIO_openDev,$hash); InternalTimer(Time::HiRes::time() + $reconnectTO,\&KNXIO_openDev,$hash);
return; return;
} }
@ -1359,7 +1372,7 @@ sub KNXIO_Log {
return if ($loglvl > $dloglvl); # shortcut performance return if ($loglvl > $dloglvl); # shortcut performance
my $sub = (caller(1))[3] // 'main'; my $sub = (caller(1))[3] // 'main';
$sub = (caller(2))[3] if ($sub =~ /ANON/xms); # anonymous sub if ($sub =~ /ANON/xms) {$sub = (caller(2))[3];} # anonymous sub
my $line = (caller(0))[2]; my $line = (caller(0))[2];
$sub =~ s/^.+[:]+//xms; $sub =~ s/^.+[:]+//xms;