diff --git a/FHEM/10_MQTT_GENERIC_BRIDGE.pm b/FHEM/10_MQTT_GENERIC_BRIDGE.pm index 33fa306dd..a5f51a0ef 100644 --- a/FHEM/10_MQTT_GENERIC_BRIDGE.pm +++ b/FHEM/10_MQTT_GENERIC_BRIDGE.pm @@ -30,6 +30,18 @@ # # CHANGE LOG # +# 27.12.2018 1.0.6 +# bugfix : inkorrekte Verarbeitung von 'mqttDefaults' mit +# Prefixen 'pub:'/'sub:'. +# : Sonderlocken fuer $base, $name, $reading, $device, +# damit auch xxx:topic={$base} geht (sonst koente nur {"$base"} verwendet werden) +# +# 16.12.2018 1.0.5 +# bugfix : $name im Unterschied zu $reading in mqttSubscribe funktioniert +# nicht. Nach dieser Korrektur wird es erstmal als $reading +# behandelt, soll jedoch noch ueber mqttAlias redefiniert +# werden können. +# # 06.12.2018 1.0.4 # bugfix : Variable $base bei publish leer annehmen falls nicht definiert # @@ -57,36 +69,36 @@ # retain-Flag sollte funktionieren, qos nicht, # wie qos uebermittelt werden soll ist noch unklar # -# 14.11.2018 0.9.9 +# 14.11.2018 0.9.9.9 # feature : Unterstuetzung fuer MQTT2 -> subscribe (Parse) # ! Erfordert Aenderung in MQTT2_CLIENT und MQTT2_SERVER ! # ! in $hash->{Clients} = ":MQTT2_DEVICE:MQTT_GENERIC_BRIDGE:"; # ! und $hash->{MatchList}= { "1:MQTT2_DEVICE" => "^.*", # "2:MQTT_GENERIC_BRIDGE"=>"^.*" }, # -# 11.11.2018 0.9.9 +# 11.11.2018 0.9.9.8 # change : import fuer json2nameValue aus main. # Damit geht JSON-Unterstuetzung ohne Prefix 'main::' # Beispiel: # json:topic=/XTEST/json json:expression={json2nameValue($value)} # -# 04.11.2018 0.9.9 +# 04.11.2018 0.9.9.7 # bugfix : Bei Mehrfachdefinitionen wie 'a|b|c:topic=some/$reading/thing' # wurden beim Treffer alle genannten Readings aktualisiert # anstatt nur der einer passenden. # change : forward blockieren nur fuer Readings (mode 'R'). # -# 18.10.2018 0.9.9 +# 18.10.2018 0.9.9.6 # bugfix : qos/retain/expression aus 'mqttDefaults' in Device wurden nicht # verwendet (Fehler bei der Suche (Namen)) # -# 14.10.2018 0.9.9 +# 14.10.2018 0.9.9.5 # change : 'mqttForward' dokumentiert # improved : Laden von MQTT-Modul in BEGIN-Block verlagert. # Es gab Meldungen ueber Probleme (undefined subroutine) wenn # MQTT-Modul in fhem.cfg nach dem Bridge-Modul stand. # -# 11.10.2018 0.9.9 +# 11.10.2018 0.9.9.4 # change : 'self-trigger-topic' wieder ausgebaut. # feature : 'mqttForward' Attribute fuer ueberwachte Geraete implmentiert. # Moegliche Werte derzeit: 'all' und 'none'. @@ -100,14 +112,14 @@ # zurueckmelden koennen, jedoch Dummies beim Einsatz als # FHEM-UI-Schalter keine Endlosschleifen verursachen. # -# 30.09.2018 0.9.9 +# 30.09.2018 0.9.9.3 # feature finished: globalTypeExclude und globalDeviceExclude incl. Commandref # bugfix : initialization # -# 29.09.2018 0.9.9 +# 29.09.2018 0.9.9.2 # quick fix: received messages forward exclude for 'dummy' # -# 27.09.2018 0.9.9 +# 27.09.2018 0.9.9.1 # imroved : auch bei stopic-Empfang wird nicht weiter gepublisht (s.u.) # (kein self-trigger-stopic implementiert, ggf. bei Bedarf) # bugfix : beim Aendern von devspec (ueberwachte Geraete) werden die @@ -126,11 +138,11 @@ # gepublisht wird. Achtung! Gefahr von Loops und wohl eher # ein Sonderfall, wird daher wird nicht in Commandref aufgenommen. # -# 25.09.2018 0.9.8 +# 25.09.2018 0.9.8.2 # feature : no-trigger-topic - wie readings-topic, es wird jedoch # beim Update kein Trigger gesendet. # -# 23.09.2018 0.9.8 +# 23.09.2018 0.9.8.1 # change : Meldung (Reading: transmission-state) ueber inkompatibles IODev # bugfix : beim Aendern von mqttXXX und globalXXX mit Zeilenumbruechen # werden interne Tabellen nicht aktualisiert @@ -162,11 +174,11 @@ # werden aelteste ueberzaelige Nachrichten verworfen. # (Beispiel: *:resendOnConnect=last) # -# 21.09.2019 0.9.7 +# 21.09.2019 0.9.7.2 # fix : Anlegen / Loeschen von userAttr # change : Vorbereitungen fuer resendOnConnect # -# 16.09.2018 0.9.7 +# 16.09.2018 0.9.7.1 # fix : defaults in globalPublish nicht verfuegbar # fix : atopic in devinfo korrekt anzeigen # improved : Anzeige devinfo @@ -255,7 +267,7 @@ use warnings; #my $DEBUG = 1; my $cvsid = '$Id$'; -my $VERSION = "version 1.0.4 by hexenmeister\n$cvsid"; +my $VERSION = "version 1.0.6 by hexenmeister\n$cvsid"; my %sets = ( ); @@ -793,14 +805,18 @@ sub IsObservedAttribute($$) { # $key: Schluessel. Unter Inhalt aus dem Quellmap unter diesem Schluessel wird in Zielmap kopiert. sub _takeDefaults($$$$) { my ($map, $dev, $valMap, $key) = @_; - if (defined($valMap->{$key})) { + my $pr = ''; + $pr = substr($key, 0, 4) if (length($key)>4); + if(($pr eq 'sub:') or ($pr eq 'pub:')) { + #if (defined($valMap->{$key})) { # ggf. nicht ueberschreiben (damit nicht undefiniertes VErhalten entsteht, # wenn mit und ohne Prefx gleichzeitig angegeben wird. So wird die Definition mit Prefix immer gewinnen) - $map->{$dev}->{':defaults'}->{'pub:'.$key}=$valMap->{$key} unless defined $map->{$dev}->{':defaults'}->{'pub:'.$key}; - $map->{$dev}->{':defaults'}->{'sub:'.$key}=$valMap->{$key} unless defined $map->{$dev}->{':defaults'}->{'sub:'.$key}; + $map->{$dev}->{':defaults'}->{$key}=$valMap->{$key} unless defined $map->{$dev}->{':defaults'}->{$key}; + $map->{$dev}->{':defaults'}->{$key}=$valMap->{$key} unless defined $map->{$dev}->{':defaults'}->{$key}; + } else { + $map->{$dev}->{':defaults'}->{'pub:'.$key}=$valMap->{$key}; + $map->{$dev}->{':defaults'}->{'sub:'.$key}=$valMap->{$key}; } - $map->{$dev}->{':defaults'}->{'pub:'.$key}=$valMap->{'pub:'.$key} if defined($valMap->{'pub:'.$key}); - $map->{$dev}->{':defaults'}->{'sub:'.$key}=$valMap->{'sub:'.$key} if defined($valMap->{'sub:'.$key}); } # Erstellt Strukturen fuer 'Defaults' fuer ein bestimmtes Geraet. @@ -815,6 +831,10 @@ sub CreateSingleDeviceTableAttrDefaults($$$$) { # format: [pub:|sub:]base=ha/wz/ [pub:|sub:]qos=0 [pub:|sub:]retain=0 my($unnamed, $named) = MQTT::parseParams($attrVal,'\s',' ','='); #main::parseParams($attrVal); foreach my $param (keys %{$named}) { + # my $pr = substr($param, 0, 4); + # if($pr eq 'sub:' or $pr eq 'pub:') { + # $param = substr($param, 4); + # } _takeDefaults($map, $dev, $named, $param); } # _takeDefaults($map, $dev, $named, 'base'); @@ -1154,17 +1174,32 @@ sub _evalValue2($$;$$) { if($str =~ m/^{.*}$/) { no strict "refs"; local $@; + my $base = ''; + my $device = ''; + my $reading = ''; + my $name = ''; if(defined($map)) { foreach my $param (keys %{$map}) { my $val = $map->{$param}; my $pname = '$'.$param; $val=$pname unless defined $val; - #Log3('xxx',1,"MQTT_GENERIC_BRIDGE:DEBUG:> replace2: $ret : $pname => $val"); + # Sonderlocken fuer $base, $name, $reading, $device, damit auch xxx:topic={$base} geht (sonst koente nur {"$base"} verwendet werden) + if($pname eq '$base') { + $base = $val; + } elsif ($pname eq '$reading') { + $reading = $val; + } elsif ($pname eq '$device') { + $device = $val; + } elsif ($pname eq '$name') { + $name = $val; + } else { + Log3('xxx',1,"MQTT_GENERIC_BRIDGE:DEBUG:> replace2: $ret : $pname => $val"); $ret =~ s/\Q$pname\E/$val/g; - #Log3('xxx',1,"MQTT_GENERIC_BRIDGE:DEBUG:> replace2 done: $ret"); + Log3('xxx',1,"MQTT_GENERIC_BRIDGE:DEBUG:> replace2 done: $ret"); } } - #Log3('xxx',1,"MQTT_GENERIC_BRIDGE:DEBUG:> eval2 !!!"); + } + #Log3('xxx',1,"MQTT_GENERIC_BRIDGE:DEBUG:> eval2 expr: $ret"); $ret = eval($ret) unless $noEval; #Log3('xxx',1,"MQTT_GENERIC_BRIDGE:DEBUG:> eval2 done: $ret"); if ($@) { @@ -1207,14 +1242,14 @@ sub searchDeviceForTopic($$) { my $dmap = $map->{$dname}->{':subscribe'}; foreach my $rmap (@{$dmap}) { my $topicExp = $rmap->{'topicExp'}; - #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> searchDeviceForTopic: expr: ".Dumper($topicExp)); + #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> searchDeviceForTopic: $dname => expr: ".Dumper($topicExp)); if (defined($topicExp) and $topic =~ $topicExp) { #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> searchDeviceForTopic: match topic: $topic, reading: ".$rmap->{'reading'}); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> searchDeviceForTopic: >>>: \$+{name}: ".$+{name}.", \$+{reading}: ".$+{reading}); # Check named groups: $+{reading},.. my $reading = undef; my $oReading = $rmap->{'reading'}; - my $nReading = $+{name}; + my $nReading = $+{name}; # TODO ummappen ueber 'alias' $nReading = $+{reading} unless defined $nReading; if((!defined($nReading)) or ($oReading eq $nReading)) { $reading = $oReading; @@ -1251,6 +1286,7 @@ sub createRegexpForTopic($) { $t =~ s|#$|.\*|; # Zugriff auf benannte captures: $+{reading} $t =~ s|(\$reading)|(\?\+)|g; + $t =~ s|(\$name)|(\?\+)|g; $t =~ s|(\$device)|(\?\+)|g; $t =~ s|\$|\\\$|g; $t =~ s|\/\.\*$|.\*|; @@ -2711,7 +2747,10 @@ sub onmessage($$$) { The following variables can be used in an expression: $base = corresponding definition from the 'globalDefaults', $reading = Original reading name, $device = device name, and $name = reading alias (see mqttAlias. - If no alias is defined, than $name = $ reading). + If no alias is defined, than $name = $ reading).
+ Furthermore, freely named variables can be defined. These can also be used in the public / subscribe definitions. + These variables are always to be used there with quotation marks. +
All these values can be limited by prefixes ('pub:' or 'sub') in their validity @@ -2875,7 +2914,7 @@ sub onmessage($$$) {

Topic definition with shared part in 'base' variable:
defmod sensor XXX
attr sensor mqttDefaults base={"/$device/$reading"}
- attr sensor mqttPublish *:topic={$base}

+ attr sensor mqttPublish *:topic={"$base"}

@@ -2884,7 +2923,7 @@ sub onmessage($$$) { defmod sensor XXX
attr sensor mqttAlias temperature=temp humidity=hum
attr sensor mqttDefaults base={"/$device/$name"}
- attr sensor mqttPublish temperature:topic={$base} humidity:topic={$base}

+ attr sensor mqttPublish temperature:topic={"$base"} humidity:topic={"$base"}

@@ -3101,7 +3140,10 @@ sub onmessage($$$) { $base = entsprechende Definition aus dem 'globalDefaults', $reading = Original-Readingname, $device = Devicename und $name = Readingalias (s. mqttAlias. - Ist kein Alias definiert, ist $name=$reading). + Ist kein Alias definiert, ist $name=$reading).
+ Weiterhin koennen frei benannte Variablen definiert werden, die neben den oben genannten in den public/subscribe Definitionen + verwendet werden koennen. Allerdings ist zu beachten, dass diese Variablen dort immer mit Anfuehrungszeichen zu verwenden sind. +
Alle diese Werte koennen durch vorangestelle Prefixe ('pub:' oder 'sub') in ihrer Gueltigkeit @@ -3269,7 +3311,7 @@ sub onmessage($$$) {

Topicsdefinition mit Auslagerung von dem gemeinsamen Teilnamen in 'base'-Variable:
defmod sensor XXX
attr sensor mqttDefaults base={"/$device/$reading"}
- attr sensor mqttPublish *:topic={$base}

+ attr sensor mqttPublish *:topic={"$base"}

@@ -3278,7 +3320,7 @@ sub onmessage($$$) { defmod sensor XXX
attr sensor mqttAlias temperature=temp humidity=hum
attr sensor mqttDefaults base={"/$device/$name"}
- attr sensor mqttPublish temperature:topic={$base} humidity:topic={$base}

+ attr sensor mqttPublish temperature:topic={"$base"} humidity:topic={"$base"}