10_MQTT2_DEVICE.pm: enahance the devicetopic attribute (Forum #126679)

git-svn-id: https://svn.fhem.de/fhem/trunk@25867 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig
2022-03-21 10:10:08 +00:00
parent dcfed2fd5a
commit cbae0b2a9f

View File

@@ -73,7 +73,8 @@ MQTT2_DEVICE_Define($$)
return "wrong syntax for $name: define <name> MQTT2_DEVICE [clientid]" return "wrong syntax for $name: define <name> MQTT2_DEVICE [clientid]"
if(int(@a)); if(int(@a));
$hash->{DEVICETOPIC} = $name if(!AttrVal($name, "devicetopic", 0)); $hash->{".DT"} = ();
$hash->{".DT"}{DEVICETOPIC} = $name if(!AttrVal($name, "devicetopic", 0));
if($hash->{CID}) { if($hash->{CID}) {
my $dpc = $modules{MQTT2_DEVICE}{defptr}{cid}; my $dpc = $modules{MQTT2_DEVICE}{defptr}{cid};
if(!$dpc->{$hash->{CID}}) { if(!$dpc->{$hash->{CID}}) {
@@ -163,7 +164,7 @@ MQTT2_DEVICE_Parse($$)
foreach my $re (keys %{$dp}) { foreach my $re (keys %{$dp}) {
my $reAll = $re; my $reAll = $re;
$reAll =~ s/\$DEVICETOPIC/\.\*/g; $reAll =~ s/\$[a-z0-9_]+/\.\*/gi;
next if(!("$topic:$value" =~ m/^$reAll$/s || next if(!("$topic:$value" =~ m/^$reAll$/s ||
"$cid:$topic:$value" =~ m/^$reAll$/s)); "$cid:$topic:$value" =~ m/^$reAll$/s));
@@ -172,7 +173,7 @@ MQTT2_DEVICE_Parse($$)
my $hash = $defs{$dev}; my $hash = $defs{$dev};
next if(!$hash); next if(!$hash);
my $reRepl = $re; my $reRepl = $re;
$reRepl =~ s/\$DEVICETOPIC/$hash->{DEVICETOPIC}/g; map { $reRepl =~ s/\$$_/$hash->{".DT"}{$_}/g } keys %{$hash->{".DT"}};
next if(!("$topic:$value" =~ m/^$reRepl$/s || next if(!("$topic:$value" =~ m/^$reRepl$/s ||
"$cid:$topic:$value" =~ m/^$reRepl$/s)); "$cid:$topic:$value" =~ m/^$reRepl$/s));
next if(IsDisabled($dev)); next if(IsDisabled($dev));
@@ -180,9 +181,10 @@ MQTT2_DEVICE_Parse($$)
Log3 $dev, 4, "MQTT2_DEVICE_Parse: $dev $topic => $code"; Log3 $dev, 4, "MQTT2_DEVICE_Parse: $dev $topic => $code";
if($code =~ m/^{.*}$/s) { if($code =~ m/^{.*}$/s) {
$code = EvalSpecials($code, ("%TOPIC"=>$topic, "%EVENT"=>$value, my %v = ("%TOPIC"=>$topic, "%EVENT"=>$value, "%NAME"=>$hash->{NAME},
"%DEVICETOPIC"=>$hash->{DEVICETOPIC}, "%NAME"=>$hash->{NAME}, "%CID"=>$cid, "%JSONMAP","\$defs{\"$dev\"}{JSONMAP}");
"%CID"=>$cid, "%JSONMAP","\$defs{\"$dev\"}{JSONMAP}")); map { $v{"%$_"} = $hash->{".DT"}{$_} } keys %{$hash->{".DT"}};
$code = EvalSpecials($code, %v);
my $ret = AnalyzePerlCommand(undef, $code); my $ret = AnalyzePerlCommand(undef, $code);
if($ret && ref $ret eq "HASH") { if($ret && ref $ret eq "HASH") {
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
@@ -329,10 +331,10 @@ MQTT2_buildCmd($$$)
shift @{$a}; shift @{$a};
if($cmd =~ m/^{.*}\s*$/) { if($cmd =~ m/^{.*}\s*$/) {
$cmd = EvalSpecials($cmd, my %v = ("%EVENT" => join(" ",@{$a}),
("%EVENT" => join(" ",@{$a}), "%NAME" => $hash->{NAME});
"%NAME" => $hash->{NAME}, map { $v{"%$_"} = $hash->{".DT"}{$_} } keys %{$hash->{".DT"}};
"%DEVICETOPIC" => $hash->{DEVICETOPIC})); $cmd = EvalSpecials($cmd,%v);
$cmd = AnalyzeCommandChain($hash->{CL}, $cmd); $cmd = AnalyzeCommandChain($hash->{CL}, $cmd);
return if(!$cmd); return if(!$cmd);
@@ -349,7 +351,7 @@ MQTT2_buildCmd($$$)
$cmd .= " ".join(" ",@{$a}) if(@{$a}); $cmd .= " ".join(" ",@{$a}) if(@{$a});
} }
$cmd =~ s/\$NAME/$hash->{NAME}/g; $cmd =~ s/\$NAME/$hash->{NAME}/g;
$cmd =~ s/\$DEVICETOPIC/$hash->{DEVICETOPIC}/g; map { $cmd =~ s/\$$_/$hash->{".DT"}{$_}/g } keys %{$hash->{".DT"}};
} }
return $cmd; return $cmd;
@@ -438,7 +440,19 @@ MQTT2_DEVICE_Attr($$)
$attrName = "" if(!$attrName); $attrName = "" if(!$attrName);
if($attrName eq "devicetopic") { if($attrName eq "devicetopic") {
$hash->{DEVICETOPIC} = ($type eq "del" ? $hash->{NAME} : $param); $hash->{".DT"} = ();
if($type eq "del") {
$hash->{".DT"}{DEVICETOPIC} = $hash->{NAME};
} elsif($param !~ m/=/) {
$hash->{".DT"}{DEVICETOPIC} = $param
} else {
my ($a, $h) = parseParams($param); #126679
foreach my $key (keys %{$h}) {
return "$key is not valid, must only contain a-zA-z0-9_"
if($key !~ m/[a-z0-9_]/);
}
$hash->{".DT"} = $h;
}
MQTT2_DEVICE_addReading($dev, AttrVal($dev, "readingList", "")); MQTT2_DEVICE_addReading($dev, AttrVal($dev, "readingList", ""));
return undef; return undef;
} }
@@ -461,11 +475,10 @@ MQTT2_DEVICE_Attr($$)
if($atype eq "reading") { if($atype eq "reading") {
if($par2 =~ m/^{.*}\s*$/) { if($par2 =~ m/^{.*}\s*$/) {
my $ret = perlSyntaxCheck($par2, my %v = ("%TOPIC"=>1, "%EVENT"=>"0 1 2 3 4 5 6 7 8 9",
("%TOPIC"=>1, "%EVENT"=>"0 1 2 3 4 5 6 7 8 9", "%NAME"=>$dev, "%CID"=>"clientId", "%JSONMAP"=>"");
"%NAME"=>$dev, "%CID"=>"clientId", map { $v{"%$_"} = $hash->{".DT"}{$_} } keys %{$hash->{".DT"}};
"%DEVICETOPIC"=>$hash->{DEVICETOPIC}, my $ret = perlSyntaxCheck($par2, %v);
"%JSONMAP"=>""));
return $ret if($ret); return $ret if($ret);
} else { } else {
return "$dev: bad reading name $par2 ". return "$dev: bad reading name $par2 ".
@@ -474,10 +487,9 @@ MQTT2_DEVICE_Attr($$)
} }
} else { } else {
my $ret = perlSyntaxCheck($par2, my %v = ("%NAME"=>$dev, "%EVENT"=>"0 1 2 3 4 5 6 7 8 9");
("%NAME"=>$dev, map { $v{"%$_"} = $hash->{".DT"}{$_} } keys %{$hash->{".DT"}};
"%EVENT"=>"0 1 2 3 4 5 6 7 8 9", my $ret = perlSyntaxCheck($par2, %v);
"%DEVICETOPIC"=>$dev));
return $ret if($ret); return $ret if($ret);
} }
@@ -603,8 +615,8 @@ MQTT2_DEVICE_addReading($$)
{ {
my ($name, $param) = @_; my ($name, $param) = @_;
MQTT2_DEVICE_delReading($name); MQTT2_DEVICE_delReading($name);
my $hash = $defs{$name};
my $cid = $defs{$name}{CID}; my $cid = $defs{$name}{CID};
my $dt = $defs{$name}{DEVICETOPIC};
foreach my $line (split("\n", $param)) { foreach my $line (split("\n", $param)) {
next if($line eq ""); next if($line eq "");
my ($re,$code) = split(" ", $line,2); my ($re,$code) = split(" ", $line,2);
@@ -612,7 +624,7 @@ MQTT2_DEVICE_addReading($$)
my $errMsg = CheckRegexp($re, "readingList attribute for $name"); my $errMsg = CheckRegexp($re, "readingList attribute for $name");
return $errMsg if($errMsg); return $errMsg if($errMsg);
$re =~ s/\$DEVICETOPIC/$dt/g; map { $re =~ s/\$$_/$hash->{".DT"}{$_}/g } keys %{$hash->{".DT"}};
if($cid && $re =~ m/^$cid:/) { if($cid && $re =~ m/^$cid:/) {
if($re =~ m/^$cid:([^\\\?.*\[\](|)]+):\.\*$/) { # cid:topic:.* if($re =~ m/^$cid:([^\\\?.*\[\](|)]+):\.\*$/) { # cid:topic:.*
$modules{MQTT2_DEVICE}{defptr}{"re:$cid:$1"}{$re}{"$name,$code"} = 1; $modules{MQTT2_DEVICE}{defptr}{"re:$cid:$1"}{$re}{"$name,$code"} = 1;
@@ -652,8 +664,7 @@ MQTT2_DEVICE_Rename($$)
my ($new, $old) = @_; my ($new, $old) = @_;
MQTT2_DEVICE_delReading($old); MQTT2_DEVICE_delReading($old);
MQTT2_DEVICE_addReading($new, AttrVal($new, "readingList", "")); MQTT2_DEVICE_addReading($new, AttrVal($new, "readingList", ""));
$defs{$new}{DEVICETOPIC} = $new $defs{$new}{".DT"}{DEVICETOPIC} = $new if(!AttrVal($new,"devicetopic",undef));
if($defs{$new}{DEVICETOPIC} eq $old && !AttrVal($new,"devicetopic",undef));
MQTT2_DEVICE_setBridgeRegexp(); MQTT2_DEVICE_setBridgeRegexp();
return undef; return undef;
} }
@@ -931,7 +942,7 @@ zigbee2mqtt_devStateIcon255($;$$)
if set to 0, disables extending the readingList, when the IODev if set to 0, disables extending the readingList, when the IODev
autocreate is also set. Default is 1, i.e. new topics will be autocreate is also set. Default is 1, i.e. new topics will be
automatically added to the readingList. automatically added to the readingList.
</li> </li><br>
<a id="MQTT2_DEVICE-attr-bridgeRegexp"></a> <a id="MQTT2_DEVICE-attr-bridgeRegexp"></a>
<li>bridgeRegexp &lt;regexp&gt; newClientId ...<br> <li>bridgeRegexp &lt;regexp&gt; newClientId ...<br>
@@ -965,9 +976,20 @@ zigbee2mqtt_devStateIcon255($;$$)
<a id="MQTT2_DEVICE-attr-devicetopic"></a> <a id="MQTT2_DEVICE-attr-devicetopic"></a>
<li>devicetopic value<br> <li>devicetopic value<br>
replace $DEVICETOPIC in the topic part of readingList, setList and <ul>
getList with value. if not set, $DEVICETOPIC will be replaced with the <li>if value does <b>not</b> contain an equal sign (=),
name of the device. replace $DEVICETOPIC in the topic part of the readingList, setList and
getList attributes with value.</li>
<li>if the value <b>does</b> contain an equal sign (=), then it is
interpreted as
<ul><code>Var1=Var1Value Var2="Value with space" Var3=...</code></ul>
and $Var1,$Var2,$Var3 are replaced in the readingList, setList and
getList attributes with the corresponding value.<br>
Note: the name Var1,etc must only contain the letters A-Za-z0-9_.
If the attribute is not set, $DEVICETOPIC will be replaced with the
name of the device in the attributes mentioned above.
</li>
</ul>
</li><br> </li><br>
<a id="MQTT2_DEVICE-attr-devPos"></a> <a id="MQTT2_DEVICE-attr-devPos"></a>