mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 18:59:33 +00:00
00_KNXIO.pm: multiple changes, (Forum #127792)
git-svn-id: https://svn.fhem.de/fhem/trunk@27614 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
f8043e84f3
commit
be738f33a1
@ -50,6 +50,9 @@
|
|||||||
# rework Logging, duplicate msg detection
|
# rework Logging, duplicate msg detection
|
||||||
# 04/04/2023 limit retries for keepalive timeouts
|
# 04/04/2023 limit retries for keepalive timeouts
|
||||||
# rework Logging
|
# rework Logging
|
||||||
|
# 15/05/2023 new "<device>:INITIALIZED" event after sucessful start
|
||||||
|
# change (shorten) timeout parameters on disconnect
|
||||||
|
# cmd-ref: correct wiki links, W3C conformance
|
||||||
|
|
||||||
|
|
||||||
package KNXIO; ## no critic 'package'
|
package KNXIO; ## no critic 'package'
|
||||||
@ -107,9 +110,9 @@ GP_Export(qw(Initialize ) );
|
|||||||
# global vars/constants
|
# global vars/constants
|
||||||
my $PAT_IP = '[\d]{1,3}(\.[\d]{1,3}){3}';
|
my $PAT_IP = '[\d]{1,3}(\.[\d]{1,3}){3}';
|
||||||
my $PAT_PORT = '[\d]{4,5}';
|
my $PAT_PORT = '[\d]{4,5}';
|
||||||
my $TULID = 'C';
|
my $KNXID = 'C';
|
||||||
my $reconnectTO = 10; # Waittime after disconnect
|
my $reconnectTO = 10; # Waittime after disconnect
|
||||||
my $svnid = '$Id$';
|
my $SVNID = '$Id$';
|
||||||
|
|
||||||
#####################################
|
#####################################
|
||||||
sub Initialize {
|
sub Initialize {
|
||||||
@ -138,8 +141,8 @@ sub KNXIO_Define {
|
|||||||
my @arg = split(/[\s\t\n]+/xms,$def);
|
my @arg = split(/[\s\t\n]+/xms,$def);
|
||||||
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(.+)Z.*/$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
|
||||||
|
|
||||||
return q{KNXIO-define: invalid mode specified, valid modes are one of: H M S T X} if ((scalar(@arg) >= 3) && $arg[2] !~ /[HMSTX]/ixms);
|
return q{KNXIO-define: invalid mode specified, valid modes are one of: H M S T X} if ((scalar(@arg) >= 3) && $arg[2] !~ /[HMSTX]/ixms);
|
||||||
|
|
||||||
@ -210,7 +213,10 @@ sub KNXIO_Define {
|
|||||||
|
|
||||||
KNXIO_Log ($name, 3, qq{opening mode=$mode});
|
KNXIO_Log ($name, 3, qq{opening mode=$mode});
|
||||||
|
|
||||||
return InternalTimer(gettimeofday() + 0.2,\&KNXIO_openDev,$hash) if (! $init_done);
|
if (! $init_done) {
|
||||||
|
InternalTimer(gettimeofday() + 30.0,\&KNXIO_initcomplete,$hash); # provide INIIALIZED EVENT
|
||||||
|
return InternalTimer(gettimeofday() + 0.2,\&KNXIO_openDev,$hash);
|
||||||
|
}
|
||||||
return KNXIO_openDev($hash);
|
return KNXIO_openDev($hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,7 +439,7 @@ sub KNXIO_ReadH {
|
|||||||
if ($errcode > 0) {
|
if ($errcode > 0) {
|
||||||
KNXIO_Log ($name, 3, q{ConnectionResponse received } .
|
KNXIO_Log ($name, 3, q{ConnectionResponse received } .
|
||||||
qq{CCID= $hash->{KNXIOhelper}->{CCID} Status=} . KNXIO_errCodes($errcode));
|
qq{CCID= $hash->{KNXIOhelper}->{CCID} Status=} . KNXIO_errCodes($errcode));
|
||||||
KNXIO_disconnect($hash);
|
KNXIO_disconnect($hash,2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
my $phyaddr = unpack('x18n',$buf);
|
my $phyaddr = unpack('x18n',$buf);
|
||||||
@ -451,7 +457,7 @@ sub KNXIO_ReadH {
|
|||||||
if ($errcode > 0) {
|
if ($errcode > 0) {
|
||||||
KNXIO_Log ($name, 3, q{ConnectionStateResponse received } .
|
KNXIO_Log ($name, 3, q{ConnectionStateResponse received } .
|
||||||
qq{CCID= $hash->{KNXIOhelper}->{CCID} Status= } . KNXIO_errCodes($errcode));
|
qq{CCID= $hash->{KNXIOhelper}->{CCID} Status= } . KNXIO_errCodes($errcode));
|
||||||
KNXIO_disconnect($hash);
|
KNXIO_disconnect($hash,2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return InternalTimer(gettimeofday() + 60, \&KNXIO_keepAlive, $hash);
|
return InternalTimer(gettimeofday() + 60, \&KNXIO_keepAlive, $hash);
|
||||||
@ -497,7 +503,7 @@ sub KNXIO_Write {
|
|||||||
my $mode = $hash->{model};
|
my $mode = $hash->{model};
|
||||||
|
|
||||||
KNXIO_Log ($name, 5, 'started');
|
KNXIO_Log ($name, 5, 'started');
|
||||||
return if(!defined($fn) && $fn ne $TULID);
|
return if(!defined($fn) && $fn ne $KNXID);
|
||||||
if (ReadingsVal($name, 'state', 'disconnected') ne 'connected') {
|
if (ReadingsVal($name, 'state', 'disconnected') ne 'connected') {
|
||||||
KNXIO_Log ($name, 3, qq{called while not connected! Msg: $msg lost});
|
KNXIO_Log ($name, 3, qq{called while not connected! Msg: $msg lost});
|
||||||
return;
|
return;
|
||||||
@ -782,6 +788,23 @@ sub KNXIO_init {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
### provide <device> INITIALIZED event
|
||||||
|
### called for KNXIO_define ONLY on FHEM start!
|
||||||
|
### by Internaltimer with significant delay
|
||||||
|
sub KNXIO_initcomplete {
|
||||||
|
my $hash = shift;
|
||||||
|
|
||||||
|
RemoveInternalTimer($hash,\&KNXIO_initcomplete);
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
if (ReadingsVal($name,'state','disconnected') eq 'connected') {
|
||||||
|
DoTrigger($name,'INITIALIZED');
|
||||||
|
}
|
||||||
|
elsif (AttrVal($name,'disable','disabled') ne 'disabled') {
|
||||||
|
KNXIO_Log ($name, 3, q{failed});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
### prepare connection request
|
### prepare connection request
|
||||||
### called from init, disconn response, disconn request
|
### called from init, disconn response, disconn request
|
||||||
### returns packed string, ready for sending with DevIo
|
### returns packed string, ready for sending with DevIo
|
||||||
@ -885,9 +908,12 @@ sub KNXIO_deldupes {
|
|||||||
return grep { !$seen{substr($_,6) }++ } @arr; # ignore C<src-addr>
|
return grep { !$seen{substr($_,6) }++ } @arr; # ignore C<src-addr>
|
||||||
}
|
}
|
||||||
|
|
||||||
###
|
### disconnect and wait for nxt open
|
||||||
|
## second param specifies optional open delay (sec)
|
||||||
sub KNXIO_disconnect {
|
sub KNXIO_disconnect {
|
||||||
my $hash = shift;
|
my $hash = shift;
|
||||||
|
my $opendelay = shift // $reconnectTO;
|
||||||
|
|
||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
my $param = $hash->{DeviceName};
|
my $param = $hash->{DeviceName};
|
||||||
|
|
||||||
@ -896,7 +922,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() + $reconnectTO;
|
$hash->{NEXT_OPEN} = gettimeofday() + $opendelay;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -928,7 +954,8 @@ sub KNXIO_closeDev {
|
|||||||
KNXIO_Log ($name, 3, q{closed}) if ($init_done);;
|
KNXIO_Log ($name, 3, q{closed}) if ($init_done);;
|
||||||
|
|
||||||
readingsSingleUpdate($hash, 'state', 'disconnected', 1);
|
readingsSingleUpdate($hash, 'state', 'disconnected', 1);
|
||||||
DoTrigger($name, 'DISCONNECTED');
|
# DoTrigger($name, 'DISCONNECTED');
|
||||||
|
DoTrigger($name, 'disconnected');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -985,7 +1012,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
|
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);
|
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});
|
||||||
|
|
||||||
return $outbuf;
|
return $outbuf;
|
||||||
@ -1044,7 +1071,7 @@ sub KNXIO_decodeCEMI {
|
|||||||
$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
|
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);
|
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});
|
||||||
|
|
||||||
return $outbuf;
|
return $outbuf;
|
||||||
@ -1102,7 +1129,7 @@ sub KNXIO_keepAliveTO {
|
|||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
my $cntrTO = $hash->{KNXIOhelper}->{CNTRTO};
|
my $cntrTO = $hash->{KNXIOhelper}->{CNTRTO};
|
||||||
|
|
||||||
return KNXIO_disconnect($hash) if ($cntrTO >= 2); # nr of timeouts exceeded
|
return KNXIO_disconnect($hash,3) if ($cntrTO >= 2); # nr of timeouts exceeded
|
||||||
|
|
||||||
$cntrTO++;
|
$cntrTO++;
|
||||||
KNXIO_Log ($name, 3, qq{timeout - retry $cntrTO});
|
KNXIO_Log ($name, 3, qq{timeout - retry $cntrTO});
|
||||||
@ -1201,17 +1228,16 @@ sub KNXIO_errCodes {
|
|||||||
<a id="KNXIO"></a>
|
<a id="KNXIO"></a>
|
||||||
<h3>KNXIO</h3>
|
<h3>KNXIO</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<p>This is a IO-module for KNX-devices. It provides an interface between FHEM and a KNX-Gateway. The Gateway can be either a KNX-Router/KNX-GW or the KNXD-daemon.
|
<li><p>This is a IO-module for KNX-devices. It provides an interface between FHEM and a KNX-Gateway. The Gateway can be either a KNX-Router/KNX-GW or the KNXD-daemon.
|
||||||
FHEM KNX-devices use this module as IO-Device. This Module does <b>NOT</b> support the deprecated EIB-Module!
|
FHEM KNX-devices use this module as IO-Device. This Module does <b>NOT</b> support the deprecated EIB-Module!
|
||||||
</p>
|
</p>
|
||||||
<p>A (german) wiki page is avaliable here: <a href="http://www.fhemwiki.de/wiki/KNXIO">FHEM Wiki</a></p>
|
<p>A (german) wiki page is avaliable here: <a href="https://wiki.fhem.de/wiki/KNXIO">FHEM Wiki</a></p>
|
||||||
|
</li>
|
||||||
|
<li><a id="KNXIO-define"></a><strong>Define</strong>
|
||||||
|
<pre><code>define <name> KNXIO (H|M|T) <(ip-address|hostname):port> <phy-adress></code>
|
||||||
|
<code>define <name> KNXIO S <UNIX socket-path> <phy-adress></code>
|
||||||
|
<code>define <name> KNXIO X</code></pre>
|
||||||
|
|
||||||
<a id="KNXIO-define"></a>
|
|
||||||
<p><strong>Define</strong></p>
|
|
||||||
<p><code>define <name> KNXIO (H|M|T) <(ip-address|hostname):port> <phy-adress></code> <br/>or<br/>
|
|
||||||
<code>define <name> KNXIO S <UNIX socket-path> <phy-adress></code> <br/>or<br/>
|
|
||||||
<code>define <name> KNXIO X</code></p>
|
|
||||||
<ul>
|
|
||||||
<b>Connection Types (mode)</b> (first parameter):
|
<b>Connection Types (mode)</b> (first parameter):
|
||||||
<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/>
|
||||||
@ -1243,36 +1269,48 @@ sub KNXIO_errCodes {
|
|||||||
<li>The physical address is used as the source address of messages sent to KNX network. This address should be one of the defined client pool-addresses of KNXD or Router.</li>
|
<li>The physical address is used as the source address of messages sent to KNX network. This address should be one of the defined client pool-addresses of KNXD or Router.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>All parameters are mandatory. Pls. ensure that you only have <b>one path</b> between your KNX-Installation and FHEM!
|
<br/>All parameters are mandatory. Pls. ensure that you only have <b>one path</b> between your KNX-Installation and FHEM!
|
||||||
Do not define multiple KNXIO- or KNXTUL- or TUL-definitions at the same time. </p>
|
Do not define multiple KNXIO- or KNXTUL- or TUL-definitions at the same time. <br/>
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
<pre><code> define myKNXGW KNXIO H 192.168.1.201:3671 0.0.51
|
<pre><code> define myKNXGW KNXIO H 192.168.1.201:3671 0.0.51
|
||||||
define myKNXGW KNXIO M 224.0.23.12:3671 0.0.51
|
define myKNXGW KNXIO M 224.0.23.12:3671 0.0.51
|
||||||
define myKNXGW KNXIO S /var/run/knx 0.0.51
|
define myKNXGW KNXIO S /var/run/knx 0.0.51
|
||||||
define myKNXGW KNXIO T 192.168.1.200:6720 0.0.51</code></pre>
|
define myKNXGW KNXIO T 192.168.1.200:6720 0.0.51
|
||||||
|
</code>
|
||||||
Suggested parameters for KNXD (Version >= 0.14.30), with systemd:
|
Suggested parameters for KNXD (Version >= 0.14.30), with systemd:
|
||||||
<pre><code> KNXD_OPTS="-e 0.0.50 -E 0.0.51:8 -D -T -S -b ip:" # knxd acts as multicast client - do NOT use -R !
|
<code>
|
||||||
|
KNXD_OPTS="-e 0.0.50 -E 0.0.51:8 -D -T -S -b ip:" # knxd acts as multicast client - do NOT use -R !
|
||||||
KNXD_OPTS="-e 0.0.50 -E 0.0.51:8 -D -T -R -S -b ipt:192.168.xx.yy" # connect to a knx-router with ip-addr
|
KNXD_OPTS="-e 0.0.50 -E 0.0.51:8 -D -T -R -S -b ipt:192.168.xx.yy" # connect to a knx-router with ip-addr
|
||||||
KNXD_OPTS="-e 0.0.50 -E 0.0.51:8 -D -T -R -S -single -b tpuarts:/dev/ttyxxx" # connect to a serial/USB KNX GW </code></pre>
|
KNXD_OPTS="-e 0.0.50 -E 0.0.51:8 -D -T -R -S -single -b tpuarts:/dev/ttyxxx" # connect to a serial/USB KNX GW
|
||||||
The -e and -E parameters must match the definitions in the KNX-router (set by ETS)!
|
</code></pre>
|
||||||
</ul>
|
The -e and -E parameters must match the definitions in the KNX-router (set by ETS)!<br/><br/>
|
||||||
|
</li>
|
||||||
|
|
||||||
<a id="KNXIO-set"></a>
|
<li><a id="KNXIO-set"></a><strong>Set</strong> - No Set cmd implemented.
|
||||||
<p><strong>Set</strong> - No Set cmd implemented</p>
|
If you want to restart communication, use Attr disable.<br/><br/></li>
|
||||||
|
<li><a id="KNXIO-get"></a><strong>Get</strong> - No Get cmd impemented<br/><br/></li>
|
||||||
|
|
||||||
<a id="KNXIO-get"></a>
|
<li><a id="KNXIO-attr"></a><strong>Attributes</strong><br/>
|
||||||
<p><strong>Get</strong> - No Get cmd impemented</p>
|
|
||||||
|
|
||||||
<a id="KNXIO-attr"></a>
|
|
||||||
<p><strong>Attributes</strong></p>
|
|
||||||
<ul>
|
<ul>
|
||||||
<a id="KNXIO-attr-disable"></a><li><b>disable</b> -
|
<li><a id="KNXIO-attr-disable"></a><b>disable</b> -
|
||||||
Disable the device if set to <b>1</b>. No send/receive from bus possible. Delete this attr to enable device again.</li>
|
Disable the device if set to <b>1</b>. No send/receive from bus possible. Delete this attr to enable device again.</li>
|
||||||
<a id="KNXIO-attr-verbose"></a><li><b>verbose</b> -
|
<li><a id="KNXIO-attr-verbose"></a><b>verbose</b> -
|
||||||
increase verbosity of Log-Messages, system-wide default is set in "global" device. For a detailed description see: <a href="#verbose">global-attr verbose</a> </li>
|
increase verbosity of Log-Messages, system-wide default is set in "global" device. For a detailed description see: <a href="#verbose">global-attr verbose</a> <br/></li>
|
||||||
</ul>
|
</ul>
|
||||||
<br/>
|
<br/></li>
|
||||||
|
<li><a id="KNXIO-events"></a><strong>Events</strong><br/>
|
||||||
|
<ul>
|
||||||
|
<li><b><device>:INITIALIZED</b> -
|
||||||
|
This event is triggered 30 sec after FHEM init is complete <b>and</b> the device is connected. It can be used (in a notify ...)
|
||||||
|
to syncronize the status of FHEM-KNX-devices with the KNX-Hardware.
|
||||||
|
Do not use the <code>global:INITIALIZED</code> event for this purpose, the KNX-GW is not ready for communication at that time!<br/>
|
||||||
|
Example: <code>defmod KNXinit_nf notify <KNXIO-device>:INITIALIZED get <KNX-device> <gadName></code></li>
|
||||||
|
<li><b><device>:disconnected</b> -
|
||||||
|
triggered if connection to KNX-GW/KNXD failed. Recovery is attempted.</li>
|
||||||
|
<li><b><device>:connected</b> -
|
||||||
|
triggered if connection to KNX-GW/KNXD is established.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
=end html
|
=end html
|
||||||
|
Loading…
Reference in New Issue
Block a user