From 717eb0cbf7fd3c4343787a7d8e863c6336442e29 Mon Sep 17 00:00:00 2001 From: erwin <> Date: Mon, 27 Mar 2023 18:44:00 +0000 Subject: [PATCH] 00_KNXIO.pm: code improvements, (Forum #127792) git-svn-id: https://svn.fhem.de/fhem/trunk@27366 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/00_KNXIO.pm | 229 ++++++++++++++++++++++-------------------- 1 file changed, 120 insertions(+), 109 deletions(-) diff --git a/fhem/FHEM/00_KNXIO.pm b/fhem/FHEM/00_KNXIO.pm index 58ca693a8..d85d7abfa 100644 --- a/fhem/FHEM/00_KNXIO.pm +++ b/fhem/FHEM/00_KNXIO.pm @@ -43,9 +43,11 @@ # change internal PhyAddr to reabable format + range checking on define. # 19/12/2022 cleanup # 23/01/2023 cleanup, simplify _openDev -# xx/02/2023 PBP changes +# 13/03/2023 PBP changes # replace cascading if..elsif with given # replace GP_Import: Devio,Tcpserver,HttpUtils with use stmts +# 28/03/2023 cleanup +# rework Logging, duplicate msg detection package KNXIO; ## no critic 'package' @@ -56,7 +58,8 @@ use IO::Socket; use English qw(-no_match_vars); use Time::HiRes qw(gettimeofday); 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 TcpServer_MCastSend TcpServer_MCastRecv TcpServer_Close); +use TcpServerUtils qw(TcpServer_Open TcpServer_SetLoopbackMode TcpServer_MCastAdd TcpServer_MCastRemove + TcpServer_MCastSend TcpServer_MCastRecv TcpServer_Close); use HttpUtils qw(HttpUtils_gethostbyname HttpUtils_gethostbyname ip2str); use feature qw(switch); no if $] >= 5.017011, warnings => 'experimental'; @@ -73,9 +76,6 @@ use GPUtils qw(GP_Import GP_Export); # Package Helper Fn ### import FHEM functions / global vars ### run before package compilation -#DevIo_OpenDev DevIo_SimpleWrite DevIo_SimpleRead DevIo_CloseDev DevIo_Disconnected DevIo_IsOpen -#TcpServer_Open TcpServer_SetLoopbackMode TcpServer_MCastAdd TcpServer_MCastRemove TcpServer_MCastSend TcpServer_MCastRecv TcpServer_Close -#HttpUtils_gethostbyname ip2str BEGIN { # Import from main context GP_Import( @@ -189,7 +189,10 @@ sub KNXIO_Define { my $phytemp = KNXIO_hex2addr($phyaddr); $hash->{PhyAddr} = KNXIO_addr2hex($phytemp,2); #convert 2 times for correcting input! - KNXIO_closeDev($hash) if ($init_done || exists($hash->{OLDDEF})); # modify definition.... + KNXIO_closeDev($hash) if ($init_done && exists($hash->{OLDDEF})); # modify definition.... + + $hash->{devioLoglevel} = 4; #032023 + $hash->{devioNoSTATE} = 1; $hash->{PARTIAL} = q{}; # define helpers @@ -203,7 +206,7 @@ sub KNXIO_Define { delete $hash->{NEXT_OPEN}; RemoveInternalTimer($hash); - Log3 ($name, 3, qq{KNXIO_define ($name): opening device mode=$mode}); + KNXIO_Log ($name, 3, qq{opening mode=$mode}); return InternalTimer(gettimeofday() + 0.2,\&KNXIO_openDev,$hash) if (! $init_done); return KNXIO_openDev($hash); @@ -240,12 +243,12 @@ sub KNXIO_Read { $buf = ::DevIo_SimpleRead($hash); } if (!defined($buf) || length($buf) == 0) { - Log3 ($name, 1, 'KNXIO_Read: no data - disconnect'); + KNXIO_Log ($name, 1, q{no data - disconnect}); KNXIO_disconnect($hash); return; } - Log3 ($name, 5, 'KNXIO_Read: buf= ' . unpack('H*',$buf)); + KNXIO_Log ($name, 5, 'buf=' . unpack('H*',$buf)); ### process in indiv. subs my $readmodes = { @@ -260,7 +263,7 @@ sub KNXIO_Read { return; } - Log3 ($name, 2, qq{KNXIO_Read failed - invalid mode $mode specified}); + KNXIO_Log ($name, 2, qq{failed - invalid mode $mode specified}); return; } @@ -309,17 +312,17 @@ sub KNXIO_ReadM { # header format: 0x06 - header size / 0x10 - KNXNET-IPVersion / 0x0530 - Routing Indicator / 0xYYYY - Header size + size of cEMIFrame my ($header, $header_routing, $total_length) = unpack('nnn',$buf); - Log3 ($name, 5, 'KNXIO_ReadM: header=' . sprintf('%04x',$header) . ' routing=' . sprintf('%04x',$header_routing) . - qq{ TotalLength= $total_length (dezimal)}); + KNXIO_Log ($name, 5, 'header=' . sprintf('%04x',$header) . ' routing=' . sprintf('%04x',$header_routing) . + qq{ TotalLength= $total_length (dezimal)}); if ($header != 0x0610 ) { - Log3 ($name, 1, 'KNXIO_ReadM: invalid header size or version'); + KNXIO_Log ($name, 1, 'invalid header size or version'); $hash->{PARTIAL} = undef; # delete all we have so far # KNXIO_disconnect($hash); #? return; } if (length($buf) < $total_length) { # 6 Byte header + min 11 Byte data - Log3 ($name,4, 'KNXIO_ReadM: still waiting for complete packet (short packet length)'); + KNXIO_Log ($name,4, 'still waiting for complete packet (short packet length)'); $hash->{PARTIAL} = $buf; # still not enough return; } @@ -337,14 +340,14 @@ sub KNXIO_ReadM { return; } elsif ($header_routing == 0x0531) { # routing Lost Message - Log3 ($name, 3, 'KNXIO_ReadM: a routing-lost packet was received !!! - Problems with bus or KNX-router ???'); + KNXIO_Log ($name, 3, 'a routing-lost packet was received !!! - Problems with bus or KNX-router ???'); } elsif ($header_routing == 0x0201) { # search request - Log3 ($name, 4, 'KNXIO_ReadM: a search-request packet was received'); + KNXIO_Log ($name, 4, 'a search-request packet was received'); } else { - Log3 ($name, 4, q{KNXIO_ReadM: a packet with unsupported service type } . - sprintf('%04x',$header_routing) . q{ was received. - discarded}); + KNXIO_Log ($name, 4, q{a packet with unsupported service type } . + sprintf('%04x',$header_routing) . q{ was received. - discarded}); } return; } # /multicast @@ -361,7 +364,7 @@ sub KNXIO_ReadH { my $name = $hash->{NAME}; if ( unpack('n',$buf) != 0x0610) { - Log3 ($name, 3, 'KNXIO_ReadH: invalid Frame Header received - discarded'); + KNXIO_Log ($name, 3, 'invalid Frame Header received - discarded'); return; } @@ -372,26 +375,25 @@ sub KNXIO_ReadH { my $errcode = 0; my $responseID = unpack('x2n',$buf); - given ($responseID) { ## + given ($responseID) { # handle most frequent id's first -## if ( $responseID == 0x0420) { # Tunnel request when (0x0420) { # Tunnel request ($ccid,$rxseqcntr) = unpack('x7CC',$buf); my $discardFrame = undef; if ($rxseqcntr == ($hash->{KNXIOhelper}->{SEQUENCECNTR} - 1)) { - Log3 ($name, 3, q{KNXIO_ReadH: TunnelRequest received: duplicate message received } . - qq{(seqcntr= $rxseqcntr ) - ack it}); + KNXIO_Log ($name, 3, q{TunnelRequest received: duplicate message received } . + qq{(seqcntr= $rxseqcntr ) - ack it}); $hash->{KNXIOhelper}->{SEQUENCECNTR}--; # one packet duplicate... we ack it but do not process $discardFrame = 1; } if ($rxseqcntr != $hash->{KNXIOhelper}->{SEQUENCECNTR}) { # really out of sequence - Log3 ($name, 3, q{KNXIO_ReadH: TunnelRequest received: out of sequence, } . - qq{(seqcntrRx= $rxseqcntr seqcntrTx= $hash->{KNXIOhelper}->{SEQUENCECNTR} ) - no ack & discard}); + KNXIO_Log ($name, 3, q{TunnelRequest received: out of sequence, } . + qq{(seqcntrRx= $rxseqcntr seqcntrTx= $hash->{KNXIOhelper}->{SEQUENCECNTR} ) - no ack & discard}); return; } - Log3 ($name, 4, q{KNXIO_ReadH: TunnelRequest received - send Ack and decode. } . - qq{seqcntrRx= $hash->{KNXIOhelper}->{SEQUENCECNTR}} ) if (! defined($discardFrame)); + KNXIO_Log ($name, 4, q{TunnelRequest received - send Ack and decode. } . + qq{seqcntrRx= $hash->{KNXIOhelper}->{SEQUENCECNTR}} ) if (! defined($discardFrame)); my $tacksend = pack('nnnCCCC',0x0610,0x0421,10,4,$ccid,$hash->{KNXIOhelper}->{SEQUENCECNTR},0); # send ack $hash->{KNXIOhelper}->{SEQUENCECNTR}++; $hash->{KNXIOhelper}->{SEQUENCECNTR} = 0 if ($hash->{KNXIOhelper}->{SEQUENCECNTR} > 255); @@ -404,38 +406,31 @@ sub KNXIO_ReadH { return if (! defined($cemiRes)); return KNXIO_dispatch($hash,$cemiRes); } -## elsif ( $responseID == 0x0421) { # Tunneling Ack when (0x0421) { # Tunneling Ack ($ccid,$txseqcntr,$errcode) = unpack('x7CCC',$buf); if ($errcode > 0) { - Log3 ($name, 3, qq{KNXIO_ReadH: Tunneling Ack received CCID= $ccid txseq= $txseqcntr Status= } . KNXIO_errCodes($errcode)); + KNXIO_Log ($name, 3, qq{Tunneling Ack received CCID= $ccid txseq= $txseqcntr Status= } . KNXIO_errCodes($errcode)); #what next ? } $hash->{KNXIOhelper}->{SEQUENCECNTR_W}++; $hash->{KNXIOhelper}->{SEQUENCECNTR_W} = 0 if ($hash->{KNXIOhelper}->{SEQUENCECNTR_W} > 255); return RemoveInternalTimer($hash,\&KNXIO_TunnelRequestTO); # all ok, stop timer -# RemoveInternalTimer($hash,\&KNXIO_TunnelRequestTO); # all ok, stop timer } -## if ( $responseID == 0x0202) { # Search response when (0x0202) { # Search response -# elsif ( $responseID == 0x0202) { # Search response - Log3 ($name, 4, 'KNXIO_ReadH: SearchResponse received'); + KNXIO_Log ($name, 4, 'SearchResponse received'); my (@contolpointIp, $controlpointPort) = unpack('x6CCCn',$buf); return; } -## elsif ( $responseID == 0x0204) { # Decription response when (0x0204) { # Decription response - Log3 ($name, 4, 'KNXIO_ReadH: DescriptionResponse received'); + KNXIO_Log ($name, 4, 'DescriptionResponse received'); return; } -## if ( $responseID == 0x0206) { # Connection response when (0x0206) { # Connection response -# elsif ( $responseID == 0x0206) { # Connection response ($hash->{KNXIOhelper}->{CCID},$errcode) = unpack('x6CC',$buf); # save Comm Channel ID,errcode RemoveInternalTimer($hash,\&KNXIO_keepAlive); if ($errcode > 0) { - Log3 ($name, 3, q{KNXIO_ReadH: ConnectionResponse received } . - qq{CCID= $hash->{KNXIOhelper}->{CCID} Status=} . KNXIO_errCodes($errcode)); + KNXIO_Log ($name, 3, q{ConnectionResponse received } . + qq{CCID= $hash->{KNXIOhelper}->{CCID} Status=} . KNXIO_errCodes($errcode)); KNXIO_disconnect($hash); return; } @@ -443,40 +438,35 @@ sub KNXIO_ReadH { $hash->{PhyAddr} = KNXIO_addr2hex($phyaddr,2); # correct Phyaddr. # DoTrigger($name, 'CONNECTED'); readingsSingleUpdate($hash, 'state', 'connected', 1); - Log3 ($name, 3, qq{KNXIO $name connected}); + KNXIO_Log ($name, 3, qq{$name connected}); $hash->{KNXIOhelper}->{SEQUENCECNTR} = 0; return InternalTimer(gettimeofday() + 60, \&KNXIO_keepAlive, $hash); # start keepalive } -## elsif ( $responseID == 0x0208) { # ConnectionState response when (0x0208) { # ConnectionState response ($hash->{KNXIOhelper}->{CCID}, $errcode) = unpack('x6CC',$buf); RemoveInternalTimer($hash,\&KNXIO_keepAlive); RemoveInternalTimer($hash,\&KNXIO_keepAliveTO); # reset timeout timer if ($errcode > 0) { - Log3 ($name, 3, q{KNXIO_ReadH: ConnectionStateResponse received } . - qq{CCID= $hash->{KNXIOhelper}->{CCID} Status= } . KNXIO_errCodes($errcode)); + KNXIO_Log ($name, 3, q{ConnectionStateResponse received } . + qq{CCID= $hash->{KNXIOhelper}->{CCID} Status= } . KNXIO_errCodes($errcode)); KNXIO_disconnect($hash); return; } return InternalTimer(gettimeofday() + 60, \&KNXIO_keepAlive, $hash); } -## if ( $responseID == 0x0209) { # Disconnect request when (0x0209) { # Disconnect request -# elsif ( $responseID == 0x0209) { # Disconnect request - Log3 ($name, 4, 'KNXIO_ReadH: DisconnectRequest received, restarting connenction'); + KNXIO_Log ($name, 4, ' DisconnectRequest received, restarting connection'); $ccid = unpack('x6C',$buf); $msg = pack('nnnCC',(0x0610,0x020A,8,$ccid,0)); ::DevIo_SimpleWrite($hash,$msg,0); # send disco response $msg = KNXIO_prepareConnRequ($hash); } -## elsif ( $responseID == 0x020A) { # Disconnect response when (0x020A) { # Disconnect response - Log3 ($name, 4, 'KNXIO_ReadH: DisconnectResponse received - sending connrequ'); + KNXIO_Log ($name, 4, 'DisconnectResponse received - sending connrequ'); $msg = KNXIO_prepareConnRequ($hash); } -## else { default { - Log3 ($name, 3, 'KNXIO_ReadH: invalid response received: ' . unpack('H*',$buf)); + KNXIO_Log ($name, 3, 'invalid response received: ' . unpack('H*',$buf)); return; } } @@ -504,14 +494,14 @@ sub KNXIO_Write { my $name = $hash->{NAME}; my $mode = $hash->{model}; - Log3 ($name, 5, 'KNXIO_write: started'); + KNXIO_Log ($name, 5, 'started'); return if(!defined($fn) && $fn ne $TULID); if (ReadingsVal($name, 'state', 'disconnected') ne 'connected') { - Log3 ($name, 3, qq{KNXIO_write called while not connected! Msg: $msg lost}); + KNXIO_Log ($name, 3, qq{called while not connected! Msg: $msg lost}); return; } - Log3 ($name, 5, qq{KNXIO_write: sending $msg}); + KNXIO_Log ($name, 5, qq{sending $msg}); my $acpivalues = {r => 0x00, p => 0x01, w => 0x02}; @@ -534,9 +524,9 @@ sub KNXIO_Write { $data[0] = $acpi; } - Log3 ($name, 5, q{KNXIO_Write: data=} . sprintf('%02x' x scalar(@data), @data) . - sprintf(' size=%02x acpi=%02x', $datasize, $acpi) . - q{ src=} . KNXIO_addr2hex($src,2) . q{ dst=} . KNXIO_addr2hex($dst,3)); + KNXIO_Log ($name, 5, q{data=} . sprintf('%02x' x scalar(@data), @data) . + sprintf(' size=%02x acpi=%02x', $datasize, $acpi) . + q{ src=} . KNXIO_addr2hex($src,2) . q{ dst=} . KNXIO_addr2hex($dst,3)); my $completemsg = q{}; my $ret = 0; @@ -558,10 +548,10 @@ sub KNXIO_Write { } $ret = ::DevIo_SimpleWrite($hash,$completemsg,0) if ($mode ne 'M'); - Log3 ($name, 4, qq{KNXIO_Write: Mode= $mode buf=} . unpack('H*',$completemsg) . qq{ rc= $ret}); + KNXIO_Log ($name, 4, qq{Mode= $mode buf=} . unpack('H*',$completemsg) . qq{ rc= $ret}); return; } - Log3 ($name, 2, qq{KNXIO_write: Could not send message $msg}); + KNXIO_Log ($name, 2, qq{Could not send message $msg}); return; } @@ -574,10 +564,10 @@ sub KNXIO_Rename { my $oldname = shift; if (! IsDevice($newname,'KNXIO')) { - Log3 (undef, 1, qq{KNXIO_Rename: $newname is not a KNXIO device!}); + KNXIO_Log ($oldname, 1, qq{$newname is not a KNXIO device!}); return; } - Log3 (undef, 3, qq{KNXIO_Rename: device $oldname renamed to $newname}); + KNXIO_Log ($oldname, 3, qq{device $oldname renamed to $newname}); #check if any reading IODev has still the old KNXIO name... my @KNXdevs = devspec2array('TYPE=KNX:FILTER=r:IODev=' . $oldname); @@ -589,7 +579,7 @@ sub KNXIO_Rename { delete ($attr{$KNXdev}->{IODev}); $logtxt .= qq{, attr IODev -> deleted!}; } - Log3 (undef, 3, qq{KNXIO_Rename: device $KNXdev change: } . $logtxt); + KNXIO_Log ($KNXdev, 3, qq{device change: $logtxt}); } return; } @@ -619,7 +609,7 @@ sub KNXIO_callback { $hash->{nextOpenDelay} = $reconnectTO; if (defined($err)) { - Log3 ($hash, 2, qq{KNXIO_callback: device open $hash->{NAME} failed with: $err}) if ($err); + KNXIO_Log ($hash, 2, qq{device open $hash->{NAME} failed with: $err}) if ($err); $hash->{NEXT_OPEN} = gettimeofday() + $hash->{nextOpenDelay}; } return; @@ -642,11 +632,11 @@ sub KNXIO_gethostbyname_Cb { if ($error) { delete $hash->{DeviceName}; delete $hash->{PORT}; - Log3 ($name, 1, qq{KNXIO_define ($name): hostname could not be resolved: $error}); + KNXIO_Log ($name, 1, qq{hostname could not be resolved: $error}); return qq{KNXIO-define: hostname could not be resolved: $error}; } my $host = ::ip2str($dhost); - Log3 ($name, 3, qq{KNXIO_define ($name): DNS query result= $host}); + KNXIO_Log ($name, 3, qq{DNS query result= $host}); $hash->{DeviceName} = $host . q{:} . $hash->{PORT}; delete $hash->{PORT}; return; @@ -679,11 +669,11 @@ sub KNXIO_openDev { if (exists $hash->{DNSWAIT}) { $hash->{DNSWAIT} += 1; if ($hash->{DNSWAIT} > 5) { - Log3 ($name, 2, qq{KNXIO_openDev ($name): DNS failed, check ip/hostname}); + KNXIO_Log ($name, 2, qq{DNS failed, check ip/hostname}); return; } InternalTimer(gettimeofday() + 1,\&KNXIO_openDev,$hash); - Log3 ($name, 2, qq{KNXIO_openDev ($name): waiting for DNS}); + KNXIO_Log ($name, 2, q{waiting for DNS}); return; # waiting for DNS } return if (! exists($hash->{DeviceName})); # DNS failed ! @@ -692,7 +682,7 @@ sub KNXIO_openDev { my $param = $hash->{DeviceName}; # ip:port or UNIX:STREAM: my ($host, $port) = split(/[:]/ixms,$param); - Log3 ($name, 5, qq{KNXIO_openDev ($name): $mode , $host , $port , reopen= $reopen}); + KNXIO_Log ($name, 5, qq{$mode , $host , $port , reopen= $reopen}); my $ret = undef; # result @@ -701,12 +691,12 @@ sub KNXIO_openDev { delete $hash->{TCPDev}; # devio ? $ret = ::TcpServer_Open($hash, $port, $host, 1); if (defined($ret)) { # error - Log3 ($name, 2, qq{KNXIO_openDev ($name): can't connect: $ret}) if(!$reopen); + KNXIO_Log ($name, 2, qq{can't connect: $ret}) if(!$reopen); return qq{KNXIO_openDev ($name): can't connect: $ret}; } $ret = ::TcpServer_MCastAdd($hash,$host); if (defined($ret)) { # error - Log3 ($name, 2, qq{KNXIO_openDev ($name): MC add failed: $ret}) if(!$reopen); + KNXIO_Log ($name, 2, qq{MC add failed: $ret}) if(!$reopen); return qq{KNXIO_openDev ($name): MC add failed: $ret}; } @@ -721,7 +711,7 @@ sub KNXIO_openDev { elsif ($mode eq 'S') { $host = (split(/[:]/ixms,$param))[2]; # UNIX:STREAM: if (!(-S -r -w $host) && $init_done) { - Log3 ($name, 2, q{KNXIO_openDev ($name): Socket not available - (knxd running?)}); + KNXIO_Log ($name, 2, q{Socket not available - (knxd running?)}); return qq{KNXIO_openDev ($name): Socket not available - (knxd running?)}; } $ret = ::DevIo_OpenDev($hash,$reopen,\&KNXIO_init); # no callback @@ -732,7 +722,7 @@ sub KNXIO_openDev { my $conn = 0; $conn = IO::Socket::INET->new(PeerAddr => "$host:$port", Type => SOCK_DGRAM, Proto => 'udp', Reuse => 1); if (!($conn)) { - Log3 ($name, 2, qq{KNXIO_openDev ($name): can't connect: $ERRNO}) if(!$reopen); + KNXIO_Log ($name, 2, qq{can't connect: $ERRNO}) if(!$reopen); $readyfnlist{"$name.$param"} = $hash; readingsSingleUpdate($hash, 'state', 'disconnected', 1); $hash->{NEXT_OPEN} = gettimeofday() + $reconnectTO; @@ -747,7 +737,7 @@ sub KNXIO_openDev { $selectlist{"$name.$param"} = $hash; my $retxt = ($reopen)?'reappeared':'opened'; - Log3 ($name, 3, qq{KNXIO_openDev ($name): device $retxt}); + KNXIO_Log ($name, 3, qq{device $retxt}); $ret = KNXIO_init($hash); } @@ -757,7 +747,7 @@ sub KNXIO_openDev { } if(defined($ret) && $ret) { - Log3 ($name, 1, qq{KNXIO_openDev ($name): Cannot open KNXIO-Device - ignoring it}); + KNXIO_Log ($name, 1, q{Cannot open KNXIO-Device - ignoring it}); KNXIO_closeDev($hash); } @@ -784,7 +774,7 @@ sub KNXIO_init { else { # DoTrigger($name, 'CONNECTED'); readingsSingleUpdate($hash, 'state', 'connected', 1); - Log3 ($name, 3, qq{KNXIO $name connected}); + KNXIO_Log ($name, 3, qq{connected}); } return; @@ -854,30 +844,31 @@ sub KNXIO_processFIFO { RemoveInternalTimer($hash,'KNXIO::KNXIO_processFIFO'); if ($hash->{KNXIOhelper}->{FIFOTIMER} != 0) { # dispatch still running, do a wait loop - Log3 ($name, 5, qq{KNXIO_processFIFO ($name): dispatch not complete, waiting}); + KNXIO_Log ($name, 5, q{dispatch not complete, waiting}); InternalTimer(gettimeofday() + 0.1, 'KNXIO::KNXIO_processFIFO', $hash); return; } my @que = @{$hash->{KNXIOhelper}->{FIFO}}; - if (scalar(@que) > 1) { # delete any duplicates - my $queentriesOld = scalar(@que); + my $queentries = scalar(@que); + if ($queentries > 1) { # delete any duplicates + my $queentriesOld = $queentries; @que = KNXIO_deldupes(@que); - Log3 ($name, 5, qq{KNXIO_processFIFO ($name): deleted } . ($queentriesOld - scalar(@que)) . - q{ duplicate msg from queue, } . scalar(@que) . q{ remain}); + $queentries = scalar(@que); + KNXIO_Log ($name, 5, q{deleted } . ($queentriesOld - $queentries) . + qq{ duplicate msgs from queue, $queentries remain}); } - my $queentries = scalar(@que); if ($queentries > 0) { # process timer is not running & fifo not empty $hash->{KNXIOhelper}->{FIFOMSG} = shift (@que); @{$hash->{KNXIOhelper}->{FIFO}} = @que; $hash->{KNXIOhelper}->{FIFOTIMER} = 1; - Log3 ($name, 4, qq{KNXIO_processFIFO ($name): buf= $hash->{KNXIOhelper}->{FIFOMSG} Nr_msgs= $queentries}); + KNXIO_Log ($name, 4, qq{buf=$hash->{KNXIOhelper}->{FIFOMSG} Nr_msgs=$queentries}); # InternalTimer(gettimeofday() + 1.0, \&KNXIO_dispatch2, $hash); # testing delay InternalTimer(gettimeofday() + 0.05, 'KNXIO::KNXIO_dispatch2', $hash); # allow time for duplicate msgs to be read return; } - Log3 ($name, 5, qq{KNXIO_processFIFO ($name): finished}); + KNXIO_Log ($name, 5, q{finished}); return; } @@ -888,7 +879,8 @@ sub KNXIO_deldupes { my @arr = @_; my %seen; - return grep { !$seen{$_}++ } @arr; +# return grep { !$seen{$_}++ } @arr; + return grep { !$seen{substr($_,6) }++ } @arr; # ignore C } ### @@ -899,7 +891,7 @@ sub KNXIO_disconnect { ::DevIo_Disconnected($hash); - Log3 ($name, 1, qq{KNXIO_disconnect ($name): device disconnected, waiting to reappear}); + KNXIO_Log ($name, 1, qq{disconnected, waiting to reappear}); $readyfnlist{"$name.$param"} = $hash; # Start polling $hash->{NEXT_OPEN} = gettimeofday() + $reconnectTO; @@ -931,7 +923,7 @@ sub KNXIO_closeDev { RemoveInternalTimer($hash); - Log3 ($name, 3, qq{KNXIO_closeDev ($name): device closed}) if ($init_done);; + KNXIO_Log ($name, 3, q{closed}) if ($init_done);; readingsSingleUpdate($hash, 'state', 'disconnected', 1); DoTrigger($name, 'DISCONNECTED'); @@ -955,24 +947,24 @@ sub KNXIO_decodeEMI { my ($len, $id, $src, $dst, $acpi, @data) = unpack('nnnnCC*',$buf); if (($len + 2) != length($buf)) { - Log3 ($name, 4, qq{KNXIO_decodeEMI: buffer length mismatch $len } . length($buf) - 2); + KNXIO_Log ($name, 4, qq{buffer length mismatch $len } . length($buf) - 2); return; } if ($id != 0x0027) { if ($id == 0x0026) { - Log3 ($name, 4, 'KNXIO_decodeEMI: OpenGrpCon response received'); + KNXIO_Log ($name, 4, 'OpenGrpCon response received'); # DoTrigger($name, 'CONNECTED'); readingsSingleUpdate($hash, 'state', 'connected', 1); - Log3 ($name, 3, qq{KNXIO $name connected}); + KNXIO_Log ($name, 3, qq{connected}); } else { - Log3 ($name, 3, 'KNXIO_decodeEMI: invalid message code ' . sprintf('%04x',$id)); + KNXIO_Log ($name, 3, 'invalid message code ' . sprintf('%04x',$id)); } return; } - Log3 ($name, 4, q{KNXIO_decodeEMI: src=} . KNXIO_addr2hex($src,2) . q{ - dst=} . KNXIO_addr2hex($dst,3) . q{ - leng=} . scalar(@data) . - q{ - data=} . sprintf('%02x' x scalar(@data),@data)); + KNXIO_Log ($name, 4, q{src=} . KNXIO_addr2hex($src,2) . q{ - dst=} . KNXIO_addr2hex($dst,3) . q{ - leng=} . + scalar(@data) . q{ - data=} . sprintf('%02x' x scalar(@data),@data)); $src = KNXIO_addr2hex($src,0); # always a phy-address $dst = KNXIO_addr2hex($dst,1); # always a Group addr @@ -982,9 +974,9 @@ sub KNXIO_decodeEMI { my @acpicodes = qw(read preply write invalid); my $rwp = $acpicodes[$acpi]; if (! defined($rwp) || ($rwp eq 'invalid')) { - Log3 ($name, 3, 'KNXIO_decodeEMI: no valid acpi-code (read/reply/write) received, discard packet'); - Log3 ($name, 4, qq{discarded packet: src=$src dst=$dst acpi=} . sprintf('%02x',$acpi) . - ' leng=' . scalar(@data) . ' data=' . sprintf('%02x' x scalar(@data),@data)); + KNXIO_Log ($name, 3, 'no valid acpi-code (read/reply/write) received, discard packet'); + KNXIO_Log ($name, 4, qq{discarded packet: src=$src dst=$dst acpi=} . sprintf('%02x',$acpi) . + q{ length=} . scalar(@data) . q{ data=} . sprintf('%02x' x scalar(@data),@data)); return; } @@ -992,7 +984,7 @@ sub KNXIO_decodeEMI { shift @data if (scalar(@data) > 1 ); # byte 0 is ununsed if length > 1 my $outbuf = $TULID . $src . substr($rwp,0,1) . $dst . sprintf('%02x' x scalar(@data),@data); - Log3 ($name, 5, qq{KNXIO_decodeEMI: $outbuf}); + KNXIO_Log ($name, 5, qq{outbuf=$outbuf}); return $outbuf; } @@ -1008,7 +1000,7 @@ sub KNXIO_decodeCEMI { my $name = $hash->{NAME}; my ($mc, $addlen) = unpack('CC',$buf); if ($mc != 0x29 && $mc != 0x2e) { - Log3 ($name, 4, 'KNXIO_decodeCEMI: wrong MessageCode ' . sprintf("%02x",$mc) . ', discard packet'); + KNXIO_Log ($name, 4, 'wrong MessageCode ' . sprintf("%02x",$mc) . ', discard packet'); return; } @@ -1016,7 +1008,7 @@ sub KNXIO_decodeCEMI { my ($ctrlbyte1, $ctrlbyte2, $src, $dst, $tcf, $acpi, @data) = unpack('x' . $addlen . 'CCnnCCC*',$buf); if (($ctrlbyte1 & 0xF0) != 0xB0) { # standard frame/no repeat/broadcast - see 03_06_03 EMI_IMI specs - Log3 ($name, 4, 'KNXIO_decodeCEMI: wrong ctrlbyte1 ' . sprintf("%02x",$ctrlbyte1) . ', discard packet'); + KNXIO_Log ($name, 4, 'wrong ctrlbyte1 ' . sprintf("%02x",$ctrlbyte1) . ', discard packet'); return; } my $prio = ($ctrlbyte1 & 0x0C) >>2; # priority @@ -1024,23 +1016,23 @@ sub KNXIO_decodeCEMI { my $hop_count = ($ctrlbyte2 & 0x70) >> 4; # bits 6-4 if ($tcf != scalar(@data)) { # $tcf: number of NPDU octets, TPCI octet not included! - Log3 ($name, 4, 'KNXIO_decodeCEMI: Datalength not consistent'); + KNXIO_Log ($name, 4, 'Datalength not consistent'); return; } my $srcd = KNXIO_addr2hex($src,2); # always a phy-address my $dstd = KNXIO_addr2hex($dst,$dest_addrType + 2); - Log3 ($name, 4, qq{KNXIO_decodeCEMI: src=$srcd dst=$dstd destaddrType=$dest_addrType prio=$prio hop_count=$hop_count leng=} . - scalar(@data) . ' data=' . sprintf('%02x' x scalar(@data),@data)); + KNXIO_Log ($name, 4, qq{src=$srcd dst=$dstd destaddrType=$dest_addrType prio=$prio hop_count=$hop_count } . + q{length=} . scalar(@data) . q{ data=} . sprintf('%02x' x scalar(@data),@data)); $acpi = ((($acpi & 0x03) << 2) | (($data[0] & 0xC0) >> 6)); my @acpicodes = qw(read preply write invalid); my $rwp = $acpicodes[$acpi]; if (! defined($rwp) || ($rwp eq 'invalid')) { # not a groupvalue-read/write/reply - Log3 ($name, 3, 'KNXIO_decodeCEMI: no valid acpi-code (read/reply/write) received - discard packet'); - Log3 ($name, 4, qq{discarded packet: src=$srcd dst=$dstd destaddrType=$dest_addrType prio=$prio hop_count=$hop_count} . - ' leng=' . scalar(@data) . ' data=' . sprintf('%02x' x scalar(@data),@data)); + KNXIO_Log ($name, 3, 'no valid acpi-code (read/reply/write) received - discard packet'); + KNXIO_Log ($name, 4, qq{discarded packet: src=$srcd dst=$dstd destaddrType=$dest_addrType prio=$prio hop_count=$hop_count} . + q{ length=} . scalar(@data) . q{ data=} . sprintf('%02x' x scalar(@data),@data)); return; } @@ -1051,7 +1043,7 @@ sub KNXIO_decodeCEMI { shift @data if (scalar(@data) > 1 ); # byte 0 is ununsed if length > 1 my $outbuf = $TULID . $src . substr($rwp,0,1) . $dst . sprintf('%02x' x scalar(@data),@data); - Log3 ($name, 5, qq{KNXIO_decodeCEMI: buf=$outbuf}); + KNXIO_Log ($name, 5, qq{outbuf=$outbuf}); return $outbuf; } @@ -1088,7 +1080,7 @@ sub KNXIO_keepAlive { my $hash = shift; my $name = $hash->{NAME}; - Log3 ($name, 4, 'KNXIO_keepalive - expect ConnectionStateResponse'); + KNXIO_Log ($name, 4, 'expect ConnectionStateResponse'); my $msg = pack('nnnCCnnnn',(0x0610,0x0207,16,$hash->{KNXIOhelper}->{CCID},0, 0x0801,0,0,0)); RemoveInternalTimer($hash,\&KNXIO_keepAlive); @@ -1102,7 +1094,7 @@ sub KNXIO_keepAliveTO { my $hash = shift; my $name = $hash->{NAME}; - Log3 ($name, 3, 'KNXIO_keepAlive timeout - retry'); + KNXIO_Log ($name, 3, 'timeout - retry'); return KNXIO_keepAlive($hash); } @@ -1115,7 +1107,7 @@ sub KNXIO_TunnelRequestTO { RemoveInternalTimer($hash,\&KNXIO_TunnelRequestTO); # try resend...but only once if (exists($hash->{KNXIOhelper}->{LASTSENTMSG})) { - Log3 ($name, 3, 'KNXIO_TunnelRequestTO hit - attempt resend'); + KNXIO_Log ($name, 3, 'timeout - attempt resend'); my $msg = $hash->{KNXIOhelper}->{LASTSENTMSG}; ::DevIo_SimpleWrite($hash,$msg,0); delete $hash->{KNXIOhelper}->{LASTSENTMSG}; @@ -1123,7 +1115,7 @@ sub KNXIO_TunnelRequestTO { return; } - Log3 ($name, 3, 'KNXIO_TunnelRequestTO hit - sending disconnect request'); + KNXIO_Log ($name, 3, 'timeout - sending disconnect request'); # send disco request my $hpai = pack('nCCCCn',(0x0801,0,0,0,0,0)); @@ -1132,6 +1124,24 @@ sub KNXIO_TunnelRequestTO { return; } +### unified Log handling +### calling param: same as Log3: hash/name/undef, loglevel, logtext +### prependes device, subroutine, linenr. to Log msg +### return undef +sub KNXIO_Log { + my $dev = shift || 'global'; + my $loglvl = shift; + my $logtxt = shift; + + my $sub = (caller(1))[3] || 'main'; + my $line = (caller(0))[2]; + my $name = ( ref($dev) eq "HASH" ) ? $dev->{NAME} : $dev; + $sub =~ s/.+[:]+//xms; + + Log3 ($name, $loglvl, qq{$name [$sub $line]: $logtxt}); + return; +} + ### translate Error-codes to text ### copied from 03_08_01 & 03_08_02_Core document ### all i know... @@ -1185,7 +1195,8 @@ sub KNXIO_errCodes {

Define

define <name> KNXIO (H|M|T) <(ip-address|hostname):port> <phy-adress>
or
-define <name> KNXIO S <UNIX socket-path> <phy-adress>

+define <name> KNXIO S <UNIX socket-path> <phy-adress>
or
+define <name> KNXIO X

    Connection Types (mode) (first parameter):