mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-30 05:57:08 +00:00
10_KNX.pm: moved KNX_scan function to KNX-Module
git-svn-id: https://svn.fhem.de/fhem/trunk@27761 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
0acf62dc76
commit
9d760d1836
@ -138,8 +138,10 @@
|
|||||||
# cmd-ref: correct wiki links, W3C conformance...
|
# cmd-ref: correct wiki links, W3C conformance...
|
||||||
# error-msg on invalid set dpt1 cmd (on-till...)
|
# error-msg on invalid set dpt1 cmd (on-till...)
|
||||||
# Attr anwerReading now deprecated - converted to putCmd - autosave will be deactivated during fhem-restart if a answerReading is converted - use save!
|
# Attr anwerReading now deprecated - converted to putCmd - autosave will be deactivated during fhem-restart if a answerReading is converted - use save!
|
||||||
# MH 292306xx move KNX_scan Function to KNXIO-Module - update both KNXIO and KNX-Module !!!
|
# MH 20230615 move KNX_scan Function to KNXIO-Module - update both KNXIO and KNX-Module !!!
|
||||||
# update cmd-ref
|
# update cmd-ref
|
||||||
|
# MH 202307xx cleanup, add events chapter to cmd-ref
|
||||||
|
# moved KNX_scan function to KNX-Module, KNX_scan cmdline cmd into new Module 98_KNX_scan.pm
|
||||||
#
|
#
|
||||||
# todo replace cascading if..elsif with given
|
# todo replace cascading if..elsif with given
|
||||||
# todo-9/2023 final removal of attr answerReading conversion
|
# todo-9/2023 final removal of attr answerReading conversion
|
||||||
@ -179,7 +181,7 @@ BEGIN {
|
|||||||
CommandDefMod CommandModify CommandDelete CommandAttr CommandDeleteAttr CommandDeleteReading
|
CommandDefMod CommandModify CommandDelete CommandAttr CommandDeleteAttr CommandDeleteReading
|
||||||
defs modules attr cmds
|
defs modules attr cmds
|
||||||
perlSyntaxCheck
|
perlSyntaxCheck
|
||||||
FW_detail FW_wname FW_directNotify
|
FW_detail FW_wname FW_room FW_directNotify
|
||||||
readingFnAttributes
|
readingFnAttributes
|
||||||
InternalTimer RemoveInternalTimer
|
InternalTimer RemoveInternalTimer
|
||||||
GetTimeSpec
|
GetTimeSpec
|
||||||
@ -477,9 +479,11 @@ sub KNX_Define {
|
|||||||
KNX_Log ($name, 5, join (q{ }, @a));
|
KNX_Log ($name, 5, join (q{ }, @a));
|
||||||
|
|
||||||
#too less arguments or no valid 1st gad
|
#too less arguments or no valid 1st gad
|
||||||
|
if (int(@a) < 3 || $a[2] !~ m/^(?:$PAT_GAD|$PAT_GAD_HEX)/ixms) {
|
||||||
return (qq{KNX_define: wrong syntax or wrong group-format (0-31/0-7/0-255)\n} .
|
return (qq{KNX_define: wrong syntax or wrong group-format (0-31/0-7/0-255)\n} .
|
||||||
qq{ "define $name KNX <group:model[:GAD-name][:set|get|listenonly][:nosuffix]> } .
|
qq{ "define $name KNX <group:model[:GAD-name][:set|get|listenonly][:nosuffix]> } .
|
||||||
q{[<group:model[:GAD-name][:set|get|listenonly][:nosuffix]>]"}) if (int(@a) < 3 || $a[2] !~ m/^(?:$PAT_GAD|$PAT_GAD_HEX)/ixms);
|
q{[<group:model[:GAD-name][:set|get|listenonly][:nosuffix]>]"});
|
||||||
|
}
|
||||||
|
|
||||||
$hash->{'.DEFLINE'} = join(q{ },@a); # temp store defs for define2...
|
$hash->{'.DEFLINE'} = join(q{ },@a); # temp store defs for define2...
|
||||||
return InternalTimer(gettimeofday() + 3.0,\&KNX_Define2,$hash) if (! $init_done);
|
return InternalTimer(gettimeofday() + 3.0,\&KNX_Define2,$hash) if (! $init_done);
|
||||||
@ -552,8 +556,8 @@ sub KNX_Define2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (scalar(@gadArgs)) {
|
if (scalar(@gadArgs)) {
|
||||||
$gadNoSuffix = pop(@gadArgs) if ($gadArgs[-1] =~ /$PAT_GAD_SUFFIX/ixms);
|
$gadNoSuffix = lc(pop(@gadArgs)) if ($gadArgs[-1] =~ /$PAT_GAD_SUFFIX/ixms);
|
||||||
$gadOption = pop(@gadArgs) if (@gadArgs && $gadArgs[-1] =~ /^($PAT_GAD_OPTIONS)$/ixms);
|
$gadOption = lc(pop(@gadArgs)) if (@gadArgs && $gadArgs[-1] =~ /^($PAT_GAD_OPTIONS)$/ixms);
|
||||||
$gadName = pop(@gadArgs) if (@gadArgs);
|
$gadName = pop(@gadArgs) if (@gadArgs);
|
||||||
|
|
||||||
if ($gadName =~ /^$PAT_GAD_NONAME$/ixms) {
|
if ($gadName =~ /^$PAT_GAD_NONAME$/ixms) {
|
||||||
@ -653,7 +657,9 @@ sub KNX_Get {
|
|||||||
my $gadName = shift // KNX_gadNameByNO($hash,1); # use first defined GAD if no argument is supplied
|
my $gadName = shift // KNX_gadNameByNO($hash,1); # use first defined GAD if no argument is supplied
|
||||||
|
|
||||||
return qq{KNX_Get ($name): gadName not defined} if (! defined($gadName));
|
return qq{KNX_Get ($name): gadName not defined} if (! defined($gadName));
|
||||||
KNX_Log ($name, 3, q{too much arguments. Only one argument allowed (gadName). Other Arguments are discarded.}) if (defined(shift));
|
if (defined(shift)) {
|
||||||
|
KNX_Log ($name, 3, q{too much arguments. Only one argument allowed (gadName). Other Arguments are discarded.});
|
||||||
|
}
|
||||||
|
|
||||||
#FHEM asks with a ? at startup - no action, no log - if dev is disabled: no SET/GET pulldown !
|
#FHEM asks with a ? at startup - no action, no log - if dev is disabled: no SET/GET pulldown !
|
||||||
if ($gadName =~ m/\?/xms) {
|
if ($gadName =~ m/\?/xms) {
|
||||||
@ -661,7 +667,7 @@ sub KNX_Get {
|
|||||||
foreach my $key (keys %{$hash->{GADDETAILS}}) {
|
foreach my $key (keys %{$hash->{GADDETAILS}}) {
|
||||||
last if (! defined($key));
|
last if (! defined($key));
|
||||||
my $option = $hash->{GADDETAILS}->{$key}->{OPTION};
|
my $option = $hash->{GADDETAILS}->{$key}->{OPTION};
|
||||||
next if (defined($option) && $option =~ /(?:set|listenonly)/ixms);
|
next if (defined($option) && $option =~ /(?:set|listenonly)/xms);
|
||||||
$getter .= q{ } . $key . ':noArg';
|
$getter .= q{ } . $key . ':noArg';
|
||||||
}
|
}
|
||||||
$getter =~ s/^\s+//gixms; #trim leading blank
|
$getter =~ s/^\s+//gixms; #trim leading blank
|
||||||
@ -681,14 +687,18 @@ sub KNX_Get {
|
|||||||
my $option = $hash->{GADDETAILS}->{$gadName}->{OPTION};
|
my $option = $hash->{GADDETAILS}->{$gadName}->{OPTION};
|
||||||
|
|
||||||
#exit if get is prohibited
|
#exit if get is prohibited
|
||||||
return qq{KNX_Get ($name): did not request a value - "set" or "listenonly" option is defined.} if (defined ($option) && ($option =~ m/(?:set|listenonly)/ixms));
|
if (defined ($option) && ($option =~ m/(?:set|listenonly)/xms)) {
|
||||||
|
return qq{KNX_Get ($name): did not request a value - "set" or "listenonly" option is defined.};
|
||||||
|
}
|
||||||
|
|
||||||
KNX_Log ($name, 5, qq{request value for GAD: $group GAD-NAME: $gadName});
|
KNX_Log ($name, 5, qq{request value for GAD: $group GAD-NAME: $gadName});
|
||||||
|
|
||||||
IOWrite($hash, $KNXID, 'r' . $groupc); #send read-request to the bus
|
IOWrite($hash, $KNXID, 'r' . $groupc); #send read-request to the bus
|
||||||
|
|
||||||
FW_directNotify('#FHEMWEB:' . $FW_wname, 'FW_errmsg(" value for ' . $name . ' - ' . $group . ' requested",5000)', qq{}) if (defined($FW_wname));
|
if (defined($FW_wname)) {
|
||||||
|
FW_directNotify('#FHEMWEB:' . $FW_wname, 'FW_errmsg(" value for ' . $name . ' - ' . $group . ' requested",5000)', qq{});
|
||||||
|
# FW_directNotify($FW_cname, 'FW_errmsg(" value for ' . $name . ' - ' . $group . ' requested",5000)', qq{});
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -729,7 +739,9 @@ sub KNX_Set {
|
|||||||
my $rdName = $hash->{GADDETAILS}->{$targetGadName}->{RDNAMESET};
|
my $rdName = $hash->{GADDETAILS}->{$targetGadName}->{RDNAMESET};
|
||||||
my $model = $hash->{GADDETAILS}->{$targetGadName}->{MODEL};
|
my $model = $hash->{GADDETAILS}->{$targetGadName}->{MODEL};
|
||||||
|
|
||||||
return $name . q{ did not set a value - "get" or "listenonly" option is defined.} if (defined ($option) && ($option =~ m/(?:get|listenonly)/ixms));
|
if (defined ($option) && ($option =~ m/(?:get|listenonly)/xms)) {
|
||||||
|
return $name . q{ did not set a value - "get" or "listenonly" option is defined.};
|
||||||
|
}
|
||||||
|
|
||||||
my $value = $cmd; #process set command with $value as output
|
my $value = $cmd; #process set command with $value as output
|
||||||
#Text neads special treatment - additional args may be blanked words
|
#Text neads special treatment - additional args may be blanked words
|
||||||
@ -1864,6 +1876,82 @@ sub KNX_Log {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
########## public utility functions ##########
|
||||||
|
# FHEM cmd-line cmd is handled by 98_KNX_scan.pm
|
||||||
|
#
|
||||||
|
### get state of devices from KNX_Hardware
|
||||||
|
# called with devspec as argument
|
||||||
|
# e.g : KNX_scan() / KNX_scan('device1') / KNX_scan('device1,dev2,dev3,...') / KNX_scan('room=Kueche'), ...
|
||||||
|
# returns number of "gets" executed
|
||||||
|
sub main::KNX_scan {
|
||||||
|
my $devs = shift;
|
||||||
|
|
||||||
|
$devs = 'TYPE=KNX' if (! defined($devs) || $devs eq q{}); # select all if nothing defined
|
||||||
|
|
||||||
|
if (! $init_done) { # avoid scan before init complete
|
||||||
|
Log3 (undef, 2,'KNX_scan command rejected during FHEM-startup!');
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
my @devlist = devspec2array($devs);
|
||||||
|
|
||||||
|
my $i = 0; #counter devices
|
||||||
|
my $j = 0; #counter devices with get
|
||||||
|
my $k = 0; #counter total get's
|
||||||
|
my $getsarr = q{};
|
||||||
|
|
||||||
|
foreach my $knxdef (@devlist) {
|
||||||
|
next unless $knxdef;
|
||||||
|
next if($knxdef eq $devs && !$defs{$knxdef});
|
||||||
|
my $devhash = $defs{$knxdef};
|
||||||
|
next if ((! defined($devhash)) || ($devhash->{TYPE} ne 'KNX'));
|
||||||
|
|
||||||
|
#check if IO-device is ready
|
||||||
|
my $iodev = $devhash->{IODev}->{NAME};
|
||||||
|
next if (! defined($iodev));
|
||||||
|
# next if ($defs{$iodev}->{STATE} ne 'connected'); # yes:KNXIO/FHEM2FHEM no:TUL/KNXTUL
|
||||||
|
if ($defs{$iodev}->{TYPE} =~ /(?:KNXIO|FHEM2FHEM)/xms) {
|
||||||
|
# next if ($defs{$iodev}->{STATE} ne 'connected' && $defs{$iodev}->{TYPE} =~ /(?:KNXIO|FHEM2FHEM)/xms); # yes:KNXIO/FHEM2FHEM, dont care:TUL/KNXTUL
|
||||||
|
next if ($defs{$iodev}->{STATE} ne 'connected');
|
||||||
|
}
|
||||||
|
else { # all other IO-devs...
|
||||||
|
next if ($defs{$iodev}->{STATE} !~ /(?:initialized|opened|connected)/ixms);
|
||||||
|
}
|
||||||
|
|
||||||
|
$i++;
|
||||||
|
my $k0 = $k; #save previous number of get's
|
||||||
|
foreach my $key (keys %{$devhash->{GADDETAILS}}) {
|
||||||
|
last if (! defined($key));
|
||||||
|
next if($devhash->{GADDETAILS}->{$key}->{MODEL} eq $MODELERR);
|
||||||
|
my $option = $devhash->{GADDETAILS}->{$key}->{OPTION};
|
||||||
|
next if (defined($option) && $option =~ /(?:set|listenonly)/ixms);
|
||||||
|
$k++;
|
||||||
|
$getsarr .= $knxdef . q{ } . $key . q{,};
|
||||||
|
}
|
||||||
|
$j++ if ($k > $k0);
|
||||||
|
}
|
||||||
|
Log3 (undef, 3, qq{KNX_scan: $i devices selected (regex= $devs) / $j devices with get / $k "gets" executing...});
|
||||||
|
doKNX_scan($getsarr) if ($k > 0);
|
||||||
|
return $k;
|
||||||
|
}
|
||||||
|
|
||||||
|
### issue all get cmd's - each one delayed by InternalTimer
|
||||||
|
sub doKNX_scan {
|
||||||
|
my ($devgad, $arr) = split(/,/xms,shift,2);
|
||||||
|
|
||||||
|
my ($name, $gadName) = split(/[\s]/xms,$devgad);
|
||||||
|
KNX_Get ($defs{$name}, $name, $gadName);
|
||||||
|
|
||||||
|
if (defined($arr) && $arr ne q{}) {
|
||||||
|
my $count = split(/,/xms,$arr); # number of remainig pairs
|
||||||
|
my $delay = ($count % 10 == 0)?2:0.2; # extra delay on each 10th request
|
||||||
|
return InternalTimer(gettimeofday() + $delay,\&doKNX_scan,$arr); # does not support array-> use string...
|
||||||
|
}
|
||||||
|
Log3 (undef, 3, q{KNX_scan: finished});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
||||||
@ -1942,7 +2030,8 @@ The reading <state> will be updated with the last sent or received value.&
|
|||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li><a id="KNX-define"></a><strong>Define</strong><br/>
|
<li><a id="KNX-define"></a><strong>Define</strong><br/>
|
||||||
<p><code>define <name> KNX <group>:<dpt>[:[<gadName>]:[set|get|listenonly]:[nosuffix]] [<group>:<dpt> ..] <del>[IODev]</del></code></p>
|
<p><code>define <name> KNX <group>:<dpt>[:[<gadName>]:[set|get|listenonly]:[nosuffix]]
|
||||||
|
[<group>:<dpt> ..] <del>[IODev]</del></code></p>
|
||||||
<p><strong>Important: a KNX device needs at least one valid DPT.</strong> Please refer to <a href="#KNX-dpt">avaliable DPT</a>.
|
<p><strong>Important: a KNX device needs at least one valid DPT.</strong> Please refer to <a href="#KNX-dpt">avaliable DPT</a>.
|
||||||
Otherwise the system cannot en- or decode messages.<br/>
|
Otherwise the system cannot en- or decode messages.<br/>
|
||||||
<strong>Devices defined by autocreate have to be reworked with the suitable dpt and the disable attribute deleted.
|
<strong>Devices defined by autocreate have to be reworked with the suitable dpt and the disable attribute deleted.
|
||||||
@ -2000,7 +2089,9 @@ Examples:
|
|||||||
A running timer-function will be cancelled if a new set cmd (on,off,on-for-,....) for this GAD is issued.<br/>
|
A running timer-function will be cancelled if a new set cmd (on,off,on-for-,....) for this GAD is issued.<br/>
|
||||||
For all other dpt1.<xxx> the min- and max-values can be used for en- and decoding alternatively to on/off.<br/>
|
For all other dpt1.<xxx> the min- and max-values can be used for en- and decoding alternatively to on/off.<br/>
|
||||||
All DPTs: allowed values or range of values are specified here: <a href="#KNX-dpt">KNX-dpt</a><br/>
|
All DPTs: allowed values or range of values are specified here: <a href="#KNX-dpt">KNX-dpt</a><br/>
|
||||||
After successful sending, the value is stored in readings <setName> and state.</p>
|
After successful sending, the value is stored in readings <setName> and state.<br>
|
||||||
|
Do not use wildcards for <deviceName>, the KNX-GW/Bus might be not perfomant enough to handle that.
|
||||||
|
</p>
|
||||||
<pre>
|
<pre>
|
||||||
Examples:
|
Examples:
|
||||||
<code> set lamp2 on # gadName omitted
|
<code> set lamp2 on # gadName omitted
|
||||||
@ -2024,8 +2115,11 @@ Examples:
|
|||||||
<li><a id="KNX-get"></a><strong>Get</strong><br/>
|
<li><a id="KNX-get"></a><strong>Get</strong><br/>
|
||||||
<p>If you execute "get" for a KNX-Element the status will be requested from the device. The device has to be able to respond to a read -
|
<p>If you execute "get" for a KNX-Element the status will be requested from the device. The device has to be able to respond to a read -
|
||||||
this might not be supported by the target KNX-device.<br/>
|
this might not be supported by the target KNX-device.<br/>
|
||||||
If the GAD is restricted in the definition with "set" or "listenonly", the execution will be refused.<br/>
|
If the GAD is restricted in the definition with "set" or "listenonly", the execution will be refused.<br/>
|
||||||
The answer from the bus-device updates the readings <getName> and state.</p>
|
The answer from the bus-device updates the readings <getName> and state.<br>
|
||||||
|
Do not use wildcards for <deviceName>, the KNX-GW/Bus might be not perfomant enough to handle that,
|
||||||
|
use <a href="#KNX-utilities">KNX_scan</a> cmd instead.
|
||||||
|
</p>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li><a id="KNX-attr"></a><strong>Common attributes</strong><br/>
|
<li><a id="KNX-attr"></a><strong>Common attributes</strong><br/>
|
||||||
@ -2067,7 +2161,8 @@ The answer from the bus-device updates the readings <getName> and state.</
|
|||||||
<ul>
|
<ul>
|
||||||
<!--<li><a id="KNX-attr-answerReading"></a>answerReading<br/>
|
<!--<li><a id="KNX-attr-answerReading"></a>answerReading<br/>
|
||||||
If enabled, FHEM answers on read requests. The content of reading state is sent to the bus as answer.
|
If enabled, FHEM answers on read requests. The content of reading state is sent to the bus as answer.
|
||||||
If defined, the content of the reading <putName> is used as value for the answer. This attribute has no effect if the putCmd attribute is set!<br/>
|
If defined, the content of the reading <putName> is used as value for the answer.
|
||||||
|
This attribute has no effect if the putCmd attribute is set!<br/>
|
||||||
<b>This attribute (and reading <putName>) will be deprecated soon,</b> as replacement you can use the Attribute <b>putCmd</b>.
|
<b>This attribute (and reading <putName>) will be deprecated soon,</b> as replacement you can use the Attribute <b>putCmd</b>.
|
||||||
<br/></li>
|
<br/></li>
|
||||||
-->
|
-->
|
||||||
@ -2145,6 +2240,14 @@ Examples:
|
|||||||
</ul>
|
</ul>
|
||||||
<br/></li>
|
<br/></li>
|
||||||
|
|
||||||
|
<li><a id="KNX-events"></a><strong>Events</strong><br/>
|
||||||
|
<p>Events are generated for each reading sent or received to/from KNX-Bus unless restricted by <code>event-xxx</code> attributes
|
||||||
|
or modified by <code>eventMap, stateRegex</code> attributes.
|
||||||
|
KNX-events have this format:</p>
|
||||||
|
<pre> <code><device> <readingName>: <value> # reading event
|
||||||
|
<device> <value> # state event</code></pre>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li><a id="KNX-dpt"></a><strong>DPT - data-point-types</strong><br/>
|
<li><a id="KNX-dpt"></a><strong>DPT - data-point-types</strong><br/>
|
||||||
<p>The following dpt are implemented and have to be assigned within the device definition.
|
<p>The following dpt are implemented and have to be assigned within the device definition.
|
||||||
The values right to the dpt define the valid range of Set-command values and Get-command return values and units.</p>
|
The values right to the dpt define the valid range of Set-command values and Get-command return values and units.</p>
|
||||||
@ -2263,7 +2366,7 @@ Examples:
|
|||||||
</ol>
|
</ol>
|
||||||
<br/></li>
|
<br/></li>
|
||||||
|
|
||||||
<li><a id="KNX-utilities"></a><strong>KNX Utility Functions</strong><br/>
|
<li><a id="KNX-utilities"></a><strong>KNX Utility Functions</strong><br/>
|
||||||
<ul>
|
<ul>
|
||||||
<li><b>KNX_scan</b> Function to be called from scripts or FHEM cmdline.
|
<li><b>KNX_scan</b> Function to be called from scripts or FHEM cmdline.
|
||||||
<br/>Selects all KNX-definitions (specified by the argument) that support a "get" from the device.
|
<br/>Selects all KNX-definitions (specified by the argument) that support a "get" from the device.
|
||||||
@ -2273,8 +2376,7 @@ The command is supported <b>only</b> if the IO-device is of TYPE KNXIO!
|
|||||||
<br/>Useful after a fhem-start to syncronize the readings with the status of the KNX-device.
|
<br/>Useful after a fhem-start to syncronize the readings with the status of the KNX-device.
|
||||||
<br/>The "get" cmds are scheduled asynchronous, with a delay of 200ms between each get. (avoid overloading KNX-bus)
|
<br/>The "get" cmds are scheduled asynchronous, with a delay of 200ms between each get. (avoid overloading KNX-bus)
|
||||||
If called as perl-function, returns number of "get" cmds issued.
|
If called as perl-function, returns number of "get" cmds issued.
|
||||||
<pre>
|
<pre>Examples:
|
||||||
Examples:
|
|
||||||
<code>syntax when used as perl-function (eg. in at, notify,...)
|
<code>syntax when used as perl-function (eg. in at, notify,...)
|
||||||
KNX_scan() - scan all possible devices
|
KNX_scan() - scan all possible devices
|
||||||
KNX_scan('dev-A') - scan device-A only
|
KNX_scan('dev-A') - scan device-A only
|
||||||
|
Loading…
x
Reference in New Issue
Block a user