From cea8e0942a0d02464b1f6eb6102aa410b983bb63 Mon Sep 17 00:00:00 2001
From: erwin
Date: Tue, 5 Mar 2024 19:25:57 +0000
Subject: [PATCH] 10_KNX.pm: minor fixes, see: (Forum #122582)
git-svn-id: https://svn.fhem.de/fhem/trunk@28603 2b470e98-0d58-463d-a4d8-8e2adae1ed80
---
fhem/FHEM/10_KNX.pm | 98 ++++++++++++++++++++++++---------------------
1 file changed, 53 insertions(+), 45 deletions(-)
diff --git a/fhem/FHEM/10_KNX.pm b/fhem/FHEM/10_KNX.pm
index 706b2e65a..4877b2c9b 100644
--- a/fhem/FHEM/10_KNX.pm
+++ b/fhem/FHEM/10_KNX.pm
@@ -169,6 +169,9 @@
# additional dpts 14.xxx - see cmdref
# fix dpt14 min/max values
# performance tuning in define
+# MH 20240305 change dpt1.009 max-value from closed->close
+# prevent gadName 'state' in define when nosuffix specified
+# add on-for...|off-for... to forbidden gadNames
#
# todo replace cascading if..elsif with given
# todo-11/2023 final removal of attr answerReading conversion
@@ -248,7 +251,8 @@ my $PAT_GAD_OPTIONS = 'get|set|listenonly';
#pattern for GAD-suffixes
my $PAT_GAD_SUFFIX = 'nosuffix';
#pattern for forbidden GAD-Names
-my $PAT_GAD_NONAME = '^(on|off|value|raw|' . $PAT_GAD_OPTIONS . q{|} . $PAT_GAD_SUFFIX . ')';
+#my $PAT_GAD_NONAME = '^(on|off|value|raw|' . $PAT_GAD_OPTIONS . q{|} . $PAT_GAD_SUFFIX . ')';
+my $PAT_GAD_NONAME = 'on|off|on-for-timer|on-until|off-for-timer|off-until|toggle|raw|rgb|string|value';
#pattern for DPT
my $PAT_GAD_DPT = 'dpt\d+\.?\d*';
#pattern for dpt1 (standard)
@@ -265,10 +269,11 @@ my $PAT_DPT16_CLR = qr/>CLR {CODE=>'dpt1', UNIT=>q{}, PATTERN=>qr/($PAT_DPT1_PAT)/ixms, MIN=>'off', MAX=>'on', SETLIST=>'on,off,toggle',
@@ -282,7 +287,7 @@ my %dpttypes = (
'dpt1.006' => {CODE=>'dpt1', UNIT=>q{}, PATTERN=>qr/($PAT_DPT1_PAT|low|high)/ixms, MIN=>'low', MAX=>'high'},
'dpt1.007' => {CODE=>'dpt1', UNIT=>q{}, PATTERN=>qr/($PAT_DPT1_PAT|decrease|increase)/ixms, MIN=>'decrease', MAX=>'increase'},
'dpt1.008' => {CODE=>'dpt1', UNIT=>q{}, PATTERN=>qr/($PAT_DPT1_PAT|up|down)/ixms, MIN=>'up', MAX=>'down'},
- 'dpt1.009' => {CODE=>'dpt1', UNIT=>q{}, PATTERN=>qr/($PAT_DPT1_PAT|closed|open)/ixms, MIN=>'open', MAX=>'closed'},
+ 'dpt1.009' => {CODE=>'dpt1', UNIT=>q{}, PATTERN=>qr/($PAT_DPT1_PAT|close|open)/ixms, MIN=>'open', MAX=>'close'},
'dpt1.010' => {CODE=>'dpt1', UNIT=>q{}, PATTERN=>qr/($PAT_DPT1_PAT|start|stop)/ixms, MIN=>'stop', MAX=>'start'},
'dpt1.011' => {CODE=>'dpt1', UNIT=>q{}, PATTERN=>qr/($PAT_DPT1_PAT|inactive|active)/ixms, MIN=>'inactive', MAX=>'active'},
'dpt1.012' => {CODE=>'dpt1', UNIT=>q{}, PATTERN=>qr/($PAT_DPT1_PAT|not_inverted|inverted)/ixms, MIN=>'not_inverted', MAX=>'inverted'},
@@ -651,7 +656,8 @@ sub KNX_Define2 {
$attr{$name}->{disable} = 1 if (AttrVal($name,'disable',0) != 1);
}
elsif (!defined($dpttypes{$gadModel})) { #check model-type
- push(@logarr,qq{invalid model $gadModel for group-number $gadNo, consult commandref - avaliable DPT});
+ push(@logarr,qq{invalid dpt $gadModel for group-number $gadNo, consult commandref - avaliable DPT});
+ $attr{$name}->{disable} = 1 if (AttrVal($name,'disable',0) != 1);
next;
}
elsif ($gadNo == 1) { # gadModel ok - use first gad as mdl reference for fheminfo
@@ -663,10 +669,16 @@ sub KNX_Define2 {
$gadOption = lc(pop(@gadArgs)) if (@gadArgs && $gadArgs[-1] =~ /^($PAT_GAD_OPTIONS)$/ixms);
$gadName = pop(@gadArgs) if (@gadArgs);
- if ($gadName =~ /^$PAT_GAD_NONAME$/ixms) {
- push(@logarr,qq{forbidden gad-name $gadName});
+# if ($gadName =~ /^($PAT_GAD_NONAME)$/ixms) {
+ if ($gadName =~ /^($PAT_GAD_NONAME)$/xms) { # allow mixed case
+ push(@logarr,qq{forbidden gadName $gadName});
next;
}
+
+ if ($gadName eq q{state} && defined($gadNoSuffix)) {
+ $gadName = q{g} . $gadNo;
+ push(@logarr,qq{forbidden gadName: state - modified to: $gadName});
+ }
}
if (defined($hash->{GADTABLE}->{$gadCode})) {
@@ -1214,22 +1226,7 @@ sub KNX_Parse {
elsif ($cmd =~ /[r]/ixms) {
my $cmdAttr = AttrVal($deviceName, 'putCmd', undef);
next if (! defined($cmdAttr) || $cmdAttr eq q{});
-=begin comment
-# replaced by block below !!
- # special experiment for Amenophis86
- if ($cmdAttr eq 'noReply') {
- if ($iohash->{PhyAddr} eq KNX_hexToName2($src)) { # match src-address with phy of IOdev
- # from fhem - delete ignore reply flag
- delete $deviceHash->{GADDETAILS}->{$gadName}->{noreplyflag}; # allow when sent from fhem
- }
- else {
- KNX_Log ($deviceName, 4, q{read msg from } . KNX_hexToName2($src) . qq{ for $deviceName $gadName IODev= $iohash->{PhyAddr}});
- $deviceHash->{GADDETAILS}->{$gadName}->{noreplyflag} = gettimeofday() + 2;
- }
- next; # cannot use putCmd logic!
- }
-=end comment
-=cut
+
# generate
my $putName = $getName =~ s/get/put/irxms;
$putName .= ($putName eq $getName)?q{-put}:q{}; # nosuffix
@@ -1241,6 +1238,7 @@ sub KNX_Parse {
KNX_Log ($deviceName, 2, qq{putCmd eval error gadName=$gadName - no reply sent!});
next; # dont send!
}
+
## special experiment for Amenophis86
elsif ($value eq 'noReply') {
if ($iohash->{PhyAddr} eq KNX_hexToName2($src)) { # match src-address with phy of IOdev
@@ -1300,7 +1298,12 @@ sub KNX_autoCreate {
### KNX_SetReadings is called from KNX_Set and KNX_Parse
# calling param: $hash, $gadName, $value, caller (set/parse), trigger (event yes/no)
sub KNX_SetReadings {
- my ($hash, $gadName, $value, $src, $trigger) = @_;
+# my ($hash, $gadName, $value, $src, $trigger) = @_;
+ my $hash = shift;
+ my $gadName = shift;
+ my $value = shift;
+ my $src = shift // q{fhem}; # undef when called from set
+ my $trigger = shift // 1; # trigger if undef
my $name = $hash->{NAME};
@@ -1314,13 +1317,14 @@ sub KNX_SetReadings {
$value .= q{ } . $unit;
}
- my $lsvalue = 'fhem'; # called from set
+ my $lsvalue = q{fhem}; # called from set
my $rdName = $hash->{GADDETAILS}->{$gadName}->{RDNAMESET};
- if (defined($src) && ($src ne q{})) { # called from parse
+ if ($src ne q{fhem}) { # called from parse
+# if (defined($src) && ($src ne q{})) { # called from parse
$lsvalue = KNX_hexToName2($src);
$rdName = $hash->{GADDETAILS}->{$gadName}->{RDNAMEGET};
}
- my $trievents = (defined($trigger))?$trigger:1;
+# my $trievents = (defined($trigger))?$trigger:1;
#execute stateRegex
my $state = KNX_replaceByRegex ($hash, $rdName, $value);
@@ -1347,7 +1351,8 @@ sub KNX_SetReadings {
}
readingsBulkUpdate($hash, 'state', $state);
}
- readingsEndUpdate($hash, $trievents);
+# readingsEndUpdate($hash, $trievents);
+ readingsEndUpdate($hash, $trigger);
return;
}
@@ -2143,6 +2148,7 @@ sub KNX_chkIO {
sub doKNX_scan {
my $iohash = shift // return;
+ return if (! exists($iohash->{Helper}->{knxscan}));
my $count = scalar(@{$iohash->{Helper}->{knxscan}});
if ($count > 0 ) {
my ($devName,$gadName) = split(/\s/xms, shift(@{$iohash->{Helper}->{knxscan}}),2);
@@ -2223,11 +2229,11 @@ This module provides a basic set of operations (on, off, toggle, on-until, on-fo
devices and to send values to the bus.
Sophisticated setups can be achieved by combining multiple KNX-groupaddresses:datapoints (GAD's:dpt's)
in one KNX device instance.
-KNX defines a series of Datapoint Type as standard data types used to allow general interpretation of values
- of devices manufactured by different vendors.
+
KNX defines a series of Data-Point-Types (dpt) as standard data types to allow
+ interpretation/encoding of messages from/to devices manufactured by different vendors.
These datatypes are used to interpret the status of a device, so the readings in FHEM will show the
correct value and optional unit.
-For each received telegram there will be a reading containing the received value and the sender address.
+
For each received message there will be a reading containing the received value and the sender address.
For every set, there will be a reading containing the sent value.
The reading <state> will be updated with the last sent or received value.
A (german) wiki page is avaliable here: FHEM Wiki
@@ -2236,26 +2242,27 @@ The reading <state> will be updated with the last sent or received value.&
Define
define <name> KNX <group>:<dpt>[:[<gadName>]:[set|get|listenonly]:[nosuffix]]
[<group>:<dpt> ..] [IODev]
-Important: a KNX device needs at least one valid DPT. Please refer to avaliable DPT.
- Otherwise the system cannot en- or decode messages.
-Devices defined by autocreate have to be reworked with the suitable dpt and the disable attribute deleted.
+Important: a KNX device needs at least one valid DPT.
+ The system cannot en- or de-code messages without a valid dpt defined.
+Devices defined by autocreate have to be configured with a correct dpt and the disable attribute deleted.
Otherwise they won't do anything.
The <group> parameter is either a group name notation (0-31/0-7/0-255) or the hex representation of it
([00-1f][0-7][00-ff]) (5 digits). All of the defined groups can be used for bus-communication.
- It is not allowed to have the same group-address more then once in one device. You can have multiple devices containing
+ It is not allowed to have the same group-address more then once in one device. You can have multiple FHEM-devices containing
the same group-adresses.
As described above the parameter <dpt> has to contain the corresponding DPT - matching the dpt-spec of the KNX-Hardware.
-The gadNames are default named "g<number>". The corresponding reading-names are getG<number>
+
The gadName default is "g<number>". The corresponding reading-names are getG<number>
and setG<number>.
The optional parameteter <gadName> may contain an alias for the GAD. The following gadNames are not allowed:
- on, off, on-for-timer, on-until, off-for-timer, off-until, toggle, raw, rgb, string, value, set, get, listenonly, nosuffix
+ state, on, off, on-for-timer, on-until, off-for-timer, off-until, toggle, raw, rgb, string, value, set, get, listenonly, nosuffix
- because of conflict with cmds & parameters.
If you supply <gadName> this name is used instead. The readings are <gadName>-get and <gadName>-set.
The synonyms <getName> and <setName> are used in this documentation.
-If you add the option "nosuffix", <getName> and <setName> have the identical name - only <gadName>.
+If you add the option "nosuffix", <getName> and <setName> have the identical name - <gadName>.
+Both sent and received bus messages will be stored in the same reading <gadName>
If you want to restrict the GAD, you can use the options "get", "set", or "listenonly". The usage should be self-explanatory.
It is not possible to combine the options.
-Specifying an IO-Device in define is now deprecated! Use attribute IODev instead,
+
Specifying an IO-Device in define is deprecated! Use attribute IODev instead,
but only if absolutely required!
The first group is used for sending by default. If you want to send to a different group, you have to address it.
E.g: set <name> <gadName> <value>
@@ -2283,10 +2290,11 @@ Examples:
Set
-set <deviceName> [<gadName>] <on|off|toggle>
- set <deviceName> [<gadName>] <on-for-timer|off-for-timer> <duration seconds>
- set <deviceName> [<gadName>] <on-until|off-until> <timespec>
- set <deviceName> [<gadName>] <value>
+set <deviceName> [<gadName>] on|off|toggle
+ set <deviceName> <gadName> blink <nr of blinks> <duration seconds>
+ set <deviceName> <gadName> on-for-timer|off-for-timer <duration seconds>
+ set <deviceName> <gadName> on-until|off-until <timespec (HH:MM[:SS])>
+
Set sends the given value to the bus.
If <gadName> is omitted, the first listed GAD of the device is used.
If the GAD is restricted in the definition with "get" or "listenonly", the set-command will be refused.
For dpt1 and dpt1.001 valid values are on, off, toggle and blink. Also the timer-functions can be used.
@@ -2443,7 +2451,7 @@ Examples:
Events
Events are generated for each reading sent or received to/from KNX-Bus unless restricted by event-xxx attributes
or modified by eventMap, stateRegex attributes.
- KNX-events have this format:
+
KNX-events have this format:
<device> <readingName>: <value> # reading event
<device> <value> # state event
@@ -2462,7 +2470,7 @@ Examples:
dpt1.006 low, high
dpt1.007 decrease, increase
dpt1.008 up, down
-dpt1.009 open, closed
+dpt1.009 open, close
dpt1.010 stop, start
dpt1.011 inactive, active
dpt1.012 not_inverted, inverted