2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-10 09:16:53 +00:00

00_KNXIO.pm: set-cmds, attr KNXIOdebug (Forum #127792)

git-svn-id: https://svn.fhem.de/fhem/trunk@28396 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
erwin 2024-01-20 16:38:07 +00:00
parent 922daff3bb
commit 4eb2594986
2 changed files with 83 additions and 40 deletions

View File

@ -1,5 +1,6 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it. # Do not insert empty lines here, update check depends on it.
- feature: 00_KNXIO: set-cmds: connect, disconnect, restart
- feature: 76_SolarForecast: Consumer planning can now react dynamically to - feature: 76_SolarForecast: Consumer planning can now react dynamically to
changing or time-shifting PV generation, changing or time-shifting PV generation,
some more minor changes some more minor changes

View File

@ -72,8 +72,11 @@
# add recovery on open Timeout - mode H # add recovery on open Timeout - mode H
# modify dipatch2/ processFIFO # modify dipatch2/ processFIFO
# new Attr KNXIOdebug - special debugging on Loglvl 1 # new Attr KNXIOdebug - special debugging on Loglvl 1
# xx/12/2023 optimize write queue handling - high load # 26/12/2023 optimize write queue handling - high load
# new: write flooding detection # new: write flooding detection
# 20/01/2024 cmdref: KNXIOdebug attribute
# feature add set cmds: connect, disconnect, restart
# modify INITIALIZED logic
package KNXIO; ## no critic 'package' package KNXIO; ## no critic 'package'
@ -132,6 +135,7 @@ my $PAT_IP = '[\d]{1,3}(\.[\d]{1,3}){3}';
my $PAT_PORT = '[\d]{4,5}'; my $PAT_PORT = '[\d]{4,5}';
my $KNXID = 'C'; my $KNXID = 'C';
my $reconnectTO = 10; # Waittime after disconnect my $reconnectTO = 10; # Waittime after disconnect
my $setcmds = q{restart:noArg connect:noArg disconnect:noArg};
my $SVNID = '$Id$'; ## no critic (Policy::ValuesAndExpressions::RequireInterpolationOfMetachars) my $SVNID = '$Id$'; ## no critic (Policy::ValuesAndExpressions::RequireInterpolationOfMetachars)
##################################### #####################################
@ -149,8 +153,9 @@ sub Initialize {
$hash->{RenameFn} = \&KNXIO_Rename; $hash->{RenameFn} = \&KNXIO_Rename;
$hash->{UndefFn} = \&KNXIO_Undef; $hash->{UndefFn} = \&KNXIO_Undef;
$hash->{ShutdownFn} = \&KNXIO_Shutdown; $hash->{ShutdownFn} = \&KNXIO_Shutdown;
$hash->{SetFn} = \&KNXIO_Set;
$hash->{AttrList} = 'disable:1 verbose:1,2,3,4,5 enableKNXscan:0,1,2 KNXIOdebug:1,2,3,4,5 ' . $readingFnAttributes; $hash->{AttrList} = 'disable:1 verbose:1,2,3,4,5 enableKNXscan:0,1,2 KNXIOdebug:1,2,3,4,5,6,7,8,9 ' . $readingFnAttributes;
$hash->{Clients} = 'KNX'; $hash->{Clients} = 'KNX';
$hash->{MatchList} = { '1:KNX' => '^C.*' }; $hash->{MatchList} = { '1:KNX' => '^C.*' };
@ -232,8 +237,6 @@ sub KNXIO_Define {
# 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
# $hash->{KNXIOhelper}->{FIFOTIMER} = 0;
# $hash->{KNXIOhelper}->{FIFOMSG} = q{};
# Devio-parameters # Devio-parameters
$hash->{nextOpenDelay} = $reconnectTO; $hash->{nextOpenDelay} = $reconnectTO;
@ -557,24 +560,6 @@ sub KNXIO_Write {
my $str = $3 // '00'; # undef on read requ my $str = $3 // '00'; # undef on read requ
my $src = KNXIO_hex2addr($hash->{PhyAddr}); my $src = KNXIO_hex2addr($hash->{PhyAddr});
=begin comment
#convert hex-string to array with dezimal values
my @data = map {hex()} $str =~ /(..)/xgms; # PBP 9/2021
$data[0] = 0 if (scalar(@data) == 0); # in case of read !!
my $datasize = scalar(@data);
if ($datasize == 1) {
$data[0] = ($data[0] & 0x3F) | $acpi;
}
else {
$data[0] = $acpi;
}
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));
=end comment
=cut
my $data = 0; my $data = 0;
if (length($str) > 2) { if (length($str) > 2) {
$data = pack ('CH*',$acpi,substr($str,2)); # multi byte write/reply $data = pack ('CH*',$acpi,substr($str,2)); # multi byte write/reply
@ -628,7 +613,7 @@ sub KNXIO_Write2 {
if ($nextwrite > $timenow) { if ($nextwrite > $timenow) {
KNXIO_Log ($name, 4, qq{frequent IO-write - Nr.msg= $count}); KNXIO_Log ($name, 4, qq{frequent IO-write - Nr.msg= $count});
KNXIO_Log ($name, 1, qq{DEBUG1>>frequent IO-write - Nr.msg= $count}) if (AttrVal($name,'KNXIOdebug',0) == 1); KNXIO_Debug ($name, 1, qq{frequent IO-write - Nr.msg= $count});
InternalTimer($nextwrite + $adddelay, \&KNXIO_Write2,$hash); InternalTimer($nextwrite + $adddelay, \&KNXIO_Write2,$hash);
InternalTimer($timenow + 30.0, \&KNXIO_Flooding,$hash) if ($count == 1); InternalTimer($timenow + 30.0, \&KNXIO_Flooding,$hash) if ($count == 1);
return; return;
@ -659,11 +644,10 @@ sub KNXIO_Write2 {
RemoveInternalTimer($hash, \&KNXIO_Flooding); RemoveInternalTimer($hash, \&KNXIO_Flooding);
} }
KNXIO_Log ($name, 5, qq{Mode= $mode buf=} . unpack('H*',$msg) . qq{ rc= $ret}); KNXIO_Log ($name, 5, qq{Mode= $mode buf=} . unpack('H*',$msg) . qq{ rc= $ret});
KNXIO_Log ($name, 1, qq{DEBUG1>>IO-write processed- Nr.msg remain= $count}) if (AttrVal($name,'KNXIOdebug',0) == 1); KNXIO_Debug ($name, 1, qq{IO-write processed- Nr.msg remain= $count});
return; return;
} }
## called by _write2 via timer when number of write cmds exceed limits ## called by _write2 via timer when number of write cmds exceed limits
sub KNXIO_Flooding { sub KNXIO_Flooding {
my $hash = shift; my $hash = shift;
@ -676,6 +660,7 @@ sub KNXIO_Flooding {
# $hash->{KNXIOhelper}->{FIFOW} = []; # ? # $hash->{KNXIOhelper}->{FIFOW} = []; # ?
return; return;
} }
##################################### #####################################
## a FHEM-rename changes the internal IODev of KNX-dev's, ## a FHEM-rename changes the internal IODev of KNX-dev's,
## but NOT the reading IODev & attr IODev ## but NOT the reading IODev & attr IODev
@ -719,6 +704,32 @@ sub KNXIO_Shutdown {
return KNXIO_closeDev($hash); return KNXIO_closeDev($hash);
} }
###################################
## connect, disconnect, restart
sub KNXIO_Set {
my $hash = shift;
my $name = shift;
my $cmd = shift;
return q{no cmd specified for set cmd} if (!defined($cmd));
my $adddelay = 1.0;
given ($cmd) {
when (q{?}) { return qq{unknown argument $cmd choose one of $setcmds}; }
when (q{disconnect}) { return KNXIO_closeDev($hash); }
when (q{connect}) {
return qq{$name is connected, no action taken} if (ReadingsVal($name,'state','disconnected') eq 'connected');
}
when (q{restart}) {
KNXIO_closeDev($hash);
$adddelay = 5.0;
}
default { return qq{invalid set cmd $cmd}; }
}
InternalTimer(gettimeofday() + $adddelay, \&KNXIO_openDev, $hash);
return;
}
################################### ###################################
### functions called from DevIo ### ### functions called from DevIo ###
################################### ###################################
@ -793,6 +804,7 @@ sub KNXIO_openDev {
KNXIO_Log ($name, 5, qq{$mode , $host , $port , reopen= $reopen}); KNXIO_Log ($name, 5, qq{$mode , $host , $port , reopen= $reopen});
my $ret = undef; # result my $ret = undef; # result
delete $hash->{stacktrace}; # clean start
given ($mode) { given ($mode) {
### multicast support via TcpServerUtils ... ### multicast support via TcpServerUtils ...
@ -926,7 +938,7 @@ sub KNXIO_handleConn {
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
$hash->{KNXIOhelper}->{startdone} = 1; # $hash->{KNXIOhelper}->{startdone} = 1;
InternalTimer(gettimeofday() + 30, \&KNXIO_initcomplete, $hash); InternalTimer(gettimeofday() + 30, \&KNXIO_initcomplete, $hash);
} }
return; return;
@ -942,6 +954,7 @@ sub 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 main::KNX_scan('TYPE=KNX:FILTER=IODev=' . $name) if (AttrNum($name,'enableKNXscan',0) >= 1); # on 1st connect only
$hash->{KNXIOhelper}->{startdone} = 1;
DoTrigger($name,'INITIALIZED'); DoTrigger($name,'INITIALIZED');
} }
elsif (AttrVal($name,'disable','disabled') ne 'disabled') { elsif (AttrVal($name,'disable','disabled') ne 'disabled') {
@ -1078,8 +1091,9 @@ sub KNXIO_closeDev {
$hash->{TCPDev}->close() if($hash->{FD}); $hash->{TCPDev}->close() if($hash->{FD});
} }
delete $hash->{stacktrace}; # clean
delete $hash->{nextOpenDelay}; delete $hash->{nextOpenDelay};
delete $hash->{'msg_cnt'}; delete $hash->{'msg_count'};
delete $hash->{'msg_time'}; delete $hash->{'msg_time'};
#NO! delete $hash->{'.CCID'}; #NO! delete $hash->{'.CCID'};
@ -1315,7 +1329,7 @@ sub KNXIO_Log {
my $logtxt = shift; my $logtxt = shift;
my $name = ( ref($dev) eq 'HASH' ) ? $dev->{NAME} : $dev; my $name = ( ref($dev) eq 'HASH' ) ? $dev->{NAME} : $dev;
my $dloglvl = AttrVal($name,'verbose',undef) // AttrVal('global','verbose',3); my $dloglvl = AttrNum($name,'verbose',undef) // AttrNum('global','verbose',3);
return if ($loglvl > $dloglvl); # shortcut performance return if ($loglvl > $dloglvl); # shortcut performance
my $sub = (caller(1))[3] // 'main'; my $sub = (caller(1))[3] // 'main';
@ -1326,6 +1340,22 @@ sub KNXIO_Log {
return; return;
} }
### Logging in debug mode
### attr KNXIOdebug triggered
### calling param: same as Log3: hash/name/undef, loglevel, logtext but loglvl is debug lvl
### return undef
sub KNXIO_Debug {
my $dev = shift // 'global';
my $loglvl = shift // 0;
my $logtxt = shift;
my $name = ( ref($dev) eq 'HASH' ) ? $dev->{NAME} : $dev;
return if ($loglvl != AttrNum($name,'KNXIOdebug',99));
Log3 ($name, 0, qq{$name DEBUG$loglvl>> $logtxt});
return;
}
### translate Error-codes to text ### translate Error-codes to text
### copied from 03_08_01 & 03_08_02_Core document ### copied from 03_08_01 & 03_08_02_Core document
### all i know... ### all i know...
@ -1384,7 +1414,7 @@ __END__
<code>define &lt;name&gt; KNXIO S &lt;UNIX socket-path&gt; &lt;phy-adress&gt;</code> <code>define &lt;name&gt; KNXIO S &lt;UNIX socket-path&gt; &lt;phy-adress&gt;</code>
<code>define &lt;name&gt; KNXIO X</code></pre> <code>define &lt;name&gt; KNXIO X</code></pre>
<b>Connection Types (mode)</b> (first parameter)&colon; <b>Connection Type (mode)</b> (first parameter)&colon;
<ul> <ul>
<li><b>H</b> Host Mode - connect to a KNX-router with UDP point-point protocol.<br/> <li><b>H</b> Host Mode - connect to a KNX-router with UDP point-point protocol.<br/>
This is the mode also used by ETS when you specify <b>KNXNET/IP</b> as protocol. You do not need a KNXD installation. This is the mode also used by ETS when you specify <b>KNXNET/IP</b> as protocol. You do not need a KNXD installation.
@ -1392,24 +1422,26 @@ __END__
If you have delays in FHEM processing close to 1 sec, the protocol may disconnect. It should recover automatically, If you have delays in FHEM processing close to 1 sec, the protocol may disconnect. It should recover automatically,
however KNX-messages could have been lost! however KNX-messages could have been lost!
<br>The benefit of this protocol&colon; every sent and received msg has to be acknowledged within 1 second by the <br>The benefit of this protocol&colon; every sent and received msg has to be acknowledged within 1 second by the
communication partner, msg delivery is verified!</li> communication partner, msg delivery is verified!
</li>
<li><b>M</b> Multicast mode - connect to KNXD's or KNX-router's multicast-tree.<br/> <li><b>M</b> Multicast mode - connect to KNXD's or KNX-router's multicast-tree.<br/>
This is the mode also used by ETS when you specify <b>KNXNET/IP Routing</b> as protocol. This is the mode also used by ETS when you specify <b>KNXNET/IP Routing</b> as protocol.
If you have a KNX-router that supports multicast, you do not need a KNXD installation. If you have a KNX-router that supports multicast, you do not need a KNXD installation.
Default address&colon;port is 224.0.23.12&colon;3671<br/> Default address&colon;port is 224.0.23.12&colon;3671<br/>
Pls. ensure that you have only <b>one</b> GW/KNXD in your LAN that feed the multicast tree!<br/> Pls. ensure that you have only <b>one</b> GW/KNXD in your LAN that feed the multicast tree!<br/>
<del>This mode requires the <code>IO&colon;&colon;Socket&colon;&colon;Multicast</code> perl-module to be installed </li>
on yr. system.
On Debian systems this can be achieved by <code>apt-get install libio-socket-multicast-perl</code>.</del></li>
<li><b>T</b> TCP mode - uses a TCP-connection to KNXD (default port&colon; 6720).<br/> <li><b>T</b> TCP mode - uses a TCP-connection to KNXD (default port&colon; 6720).<br/>
This mode is the successor of the TUL-modul, but does not support direct Serial/USB connection to a TPUart-USB Stick. This mode is the successor of the TUL-modul, but does not support direct Serial/USB connection to a TPUart-USB Stick.
If you want to use a TPUart-USB Stick or any other serial KNX-GW, If you want to use a TPUart-USB Stick or any other serial KNX-GW,
connect the USB-Stick to KNXD and use modes M,S or T to connect to KNXD.</li> connect the USB-Stick to KNXD and use modes M,S or T to connect to KNXD.
</li>
<li><b>S</b> Socket mode - communicate via KNXD's UNIX-socket on localhost. default Socket-path&colon; <li><b>S</b> Socket mode - communicate via KNXD's UNIX-socket on localhost. default Socket-path&colon;
<code>/var/run/knx</code><br/> <code>/var/run/knx</code><br/>
Path might be different, depending on knxd-version or -config specification! Path might be different, depending on knxd-version or -config specification!
This mode is tested ok with KNXD version 0.14.30. It does NOT work with ver. 0.10.0!</li> This mode is tested ok with KNXD version 0.14.30. It does NOT work with ver. 0.10.0!
<li><b>X</b> Special mode - for details see KNXIO-wiki!</li> </li>
<li><b>X</b> Special mode - for details see KNXIO-wiki!
</li>
</ul> </ul>
<br/> <br/>
<b>ip-address&colon;port</b> or <b>hostname&colon;port</b> <b>ip-address&colon;port</b> or <b>hostname&colon;port</b>
@ -1439,9 +1471,15 @@ Suggested parameters for KNXD (Version &gt;= 0.14.30), with systemd&colon;
</code></pre> </code></pre>
</li> </li>
<li><a id="KNXIO-set"></a><strong>Set</strong> - No Set cmd implemented. <li><a id="KNXIO-set"></a><strong>Set</strong><br/>
If you want to restart communication, use Attr disable.<br/><br/></li> <ul>
<li><a id="KNXIO-get"></a><strong>Get</strong> - No Get cmd impemented<br/><br/></li> <li><a id="KNXIO-set-disconnect"></a><b>disconnect</b> - Stop any communication with KNX-bus.<br/>
Difference to <code>attr &lt;device&gt; disable 1</code>: set cmds are volatile, attributes are saved in config!</li>
<li><a id="KNXIO-set-connect"></a><a id="KNXIO-set-restart"></a>
<b>connect</b> or <b>restart</b> - Start or Stop-&gt;5 seconds delay-&gt;Start KNX-bus communication.<br/></li>
</ul><br/></li>
<li><a id="KNXIO-get"></a><strong>Get</strong> - No Get command implemented<br/><br/></li>
<li><a id="KNXIO-attr"></a><strong>Attributes</strong><br/> <li><a id="KNXIO-attr"></a><strong>Attributes</strong><br/>
<ul> <ul>
@ -1456,8 +1494,12 @@ Suggested parameters for KNXD (Version &gt;= 0.14.30), with systemd&colon;
<pre><code> 0 - never (default if Attr not defined) <pre><code> 0 - never (default if Attr not defined)
1 - on fhem start (after &lt;device&gt;&colon;INITIALIZED event) 1 - on fhem start (after &lt;device&gt;&colon;INITIALIZED event)
2 - on fhem start and on every &lt;device&gt;&colon;connected event</code></pre></li> 2 - on fhem start and on every &lt;device&gt;&colon;connected event</code></pre></li>
<li><a id="KNXIO-attr-KNXIOdebug"></a><b>KNXIOdebug</b> -
Log specific events/conditions independent of verbose Level. - use only on developer advice.
Parameters are numeric (1-9), usage may change with every new version!<br/></li>
</ul> </ul>
</li> <br/></li>
<li><a id="KNXIO-events"></a><strong>Events</strong><br/> <li><a id="KNXIO-events"></a><strong>Events</strong><br/>
<ul> <ul>
<li><b>&lt;device&gt;&colon;INITIALIZED</b> - <li><b>&lt;device&gt;&colon;INITIALIZED</b> -