2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 18:59:33 +00:00

fix: doku, log for undefined vars in topic (sub)

git-svn-id: https://svn.fhem.de/fhem/trunk@18225 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
hexenmeister 2019-01-12 21:13:19 +00:00
parent 1f936174b1
commit 437b37905f

View File

@ -30,6 +30,10 @@
# #
# CHANGE LOG # CHANGE LOG
# #
# 12.01.2018 1.0.9
# change : Doku angepasst, Log-Ausgaben-Format
# fix : stack trace in log bei subscribe mit undefinierten Variablen
#
# 28.12.2018 1.0.8 # 28.12.2018 1.0.8
# change : fuer MQTT2_CLIENT (IOWrite): func. name change "subscribe" -> "subscriptions" # change : fuer MQTT2_CLIENT (IOWrite): func. name change "subscribe" -> "subscriptions"
# kein Befehl "subscribtions" an eine MQTT2_SERVER-Instanz senden # kein Befehl "subscribtions" an eine MQTT2_SERVER-Instanz senden
@ -274,7 +278,7 @@ use warnings;
#my $DEBUG = 1; #my $DEBUG = 1;
my $cvsid = '$Id$'; my $cvsid = '$Id$';
my $VERSION = "version 1.0.8 by hexenmeister\n$cvsid"; my $VERSION = "version 1.0.9 by hexenmeister\n$cvsid";
my %sets = ( my %sets = (
); );
@ -616,7 +620,7 @@ sub initUserAttr($) {
my @devices = devspec2array($devspec); my @devices = devspec2array($devspec);
#Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] initUserAttr: new list: ".Dumper(@devices)); #Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] initUserAttr: new list: ".Dumper(@devices));
#Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] initUserAttr: addToDevAttrList: $prefix"); #Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] initUserAttr: addToDevAttrList: $prefix");
#Log3('xxx',1,"MQTT_GENERIC_BRIDGE:DEBUG:> initUserAttr> devspec: '$devspec', array: ".Dumper(@devices)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] initUserAttr> devspec: '$devspec', array: ".Dumper(@devices));
foreach my $dev (@devices) { foreach my $dev (@devices) {
addToDevAttrList($dev, $prefix.CTRL_ATTR_NAME_DEFAULTS.":textField-long"); addToDevAttrList($dev, $prefix.CTRL_ATTR_NAME_DEFAULTS.":textField-long");
addToDevAttrList($dev, $prefix.CTRL_ATTR_NAME_ALIAS.":textField-long"); addToDevAttrList($dev, $prefix.CTRL_ATTR_NAME_ALIAS.":textField-long");
@ -751,10 +755,10 @@ sub removeOldUserAttr($;$$$) {
# kann spaeter auch delFromDevAttrList Methode genutzt werden # kann spaeter auch delFromDevAttrList Methode genutzt werden
my @devices = devspec2array($devspec); my @devices = devspec2array($devspec);
#Log3('xxx',1,"MQTT_GENERIC_BRIDGE:DEBUG:> removeOldUserAttr> devspec: $devspec, array: ".Dumper(@devices)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] removeOldUserAttr> devspec: $devspec, array: ".Dumper(@devices));
foreach my $dev (@devices) { foreach my $dev (@devices) {
next if grep {$_ eq $dev} @{$newDevices}; next if grep {$_ eq $dev} @{$newDevices};
#Log3('xxx',1,"MQTT_GENERIC_BRIDGE:DEBUG:> removeOldUserAttr> delete: from $dev ".$prefix.CTRL_ATTR_NAME_DEFAULTS); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] removeOldUserAttr> delete: from $dev ".$prefix.CTRL_ATTR_NAME_DEFAULTS);
# O> subs aus fhem.pl nicht nutzen, da diese auch die Steuerungsattribute mit loescht. Vor allem bei global ist das ein Problem # O> subs aus fhem.pl nicht nutzen, da diese auch die Steuerungsattribute mit loescht. Vor allem bei global ist das ein Problem
# delFromDevAttrList($dev,$prefix.CTRL_ATTR_NAME_DEFAULTS.":textField-long"); # delFromDevAttrList($dev,$prefix.CTRL_ATTR_NAME_DEFAULTS.":textField-long");
# delFromDevAttrList($dev,$prefix.CTRL_ATTR_NAME_ALIAS.":textField-long"); # delFromDevAttrList($dev,$prefix.CTRL_ATTR_NAME_ALIAS.":textField-long");
@ -903,7 +907,7 @@ sub CreateSingleDeviceTableAttrAlias($$$$) {
# Attribute-Value zum Parsen # Attribute-Value zum Parsen
sub CreateSingleDeviceTableAttrPublish($$$$) { sub CreateSingleDeviceTableAttrPublish($$$$) {
my($hash, $dev, $map, $attrVal) = @_; my($hash, $dev, $map, $attrVal) = @_;
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> CreateSingleDeviceTableAttrPublish: $dev, $attrVal, ".Dumper($map)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] CreateSingleDeviceTableAttrPublish: $dev, $attrVal, ".Dumper($map));
# collect publish topics # collect publish topics
delete ($map->{$dev}->{':publish'}); delete ($map->{$dev}->{':publish'});
if(defined $attrVal) { if(defined $attrVal) {
@ -916,7 +920,7 @@ sub CreateSingleDeviceTableAttrPublish($$$$) {
# *:topic=<{}> wird jedesmal ausgewertet und ggf. ein passendes Eintrag im Map erzeugt # *:topic=<{}> wird jedesmal ausgewertet und ggf. ein passendes Eintrag im Map erzeugt
# *:topic=# same as *:topic={"$base/$reading"} # *:topic=# same as *:topic={"$base/$reading"}
my($unnamed, $named) = MQTT::parseParams($attrVal,'\s',' ','='); my($unnamed, $named) = MQTT::parseParams($attrVal,'\s',' ','=');
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> CreateSingleDeviceTableAttrPublish: parseParams: ".Dumper($named)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] CreateSingleDeviceTableAttrPublish: parseParams: ".Dumper($named));
if(defined($named)){ if(defined($named)){
my $autoResend = {}; my $autoResend = {};
foreach my $param (keys %{$named}) { foreach my $param (keys %{$named}) {
@ -1008,10 +1012,10 @@ sub getDevicePublishRecIntern($$$$$) {
my $globalReadingMap = $globalPublishMap->{$reading} if defined $globalPublishMap; my $globalReadingMap = $globalPublishMap->{$reading} if defined $globalPublishMap;
my $globalWildcardReadingsMap = $globalPublishMap->{'*'} if defined $globalPublishMap; my $globalWildcardReadingsMap = $globalPublishMap->{'*'} if defined $globalPublishMap;
#Log3('xxx',1,"MQTT_GENERIC_BRIDGE:DEBUG:> getDevicePublishRec> readingMap ".Dumper($readingMap)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] getDevicePublishRec> readingMap ".Dumper($readingMap));
#Log3('xxx',1,"MQTT_GENERIC_BRIDGE:DEBUG:> getDevicePublishRec> wildcardReadingMap ".Dumper($wildcardReadingMap)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] getDevicePublishRec> wildcardReadingMap ".Dumper($wildcardReadingMap));
#Log3('xxx',1,"MQTT_GENERIC_BRIDGE:DEBUG:> getDevicePublishRec> readingMap ".Dumper($globalReadingMap)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] getDevicePublishRec> readingMap ".Dumper($globalReadingMap));
#Log3('xxx',1,"MQTT_GENERIC_BRIDGE:DEBUG:> getDevicePublishRec> wildcardReadingMap ".Dumper($globalWildcardReadingsMap)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] getDevicePublishRec> wildcardReadingMap ".Dumper($globalWildcardReadingsMap));
# topic # topic
my $topic = undef; my $topic = undef;
$topic = $readingMap->{'topic'} if defined $readingMap; $topic = $readingMap->{'topic'} if defined $readingMap;
@ -1146,7 +1150,7 @@ sub retrieveQosRetainExpression($$$$) {
# Evaluiert Werte in Default, wenn diese Variable / Perl-Expressions enthalten # Evaluiert Werte in Default, wenn diese Variable / Perl-Expressions enthalten
sub computeDefaults($$$$$) { sub computeDefaults($$$$$) {
my($hash, $modifier, $globalMap, $devMap, $infoMap) = @_; my($hash, $modifier, $globalMap, $devMap, $infoMap) = @_;
#Log3('xxx',1,"MQTT_GENERIC_BRIDGE:DEBUG:> computeDefaults> infoMap: ".Dumper($infoMap)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] computeDefaults> infoMap: ".Dumper($infoMap));
my $mdLng = length($modifier); my $mdLng = length($modifier);
my $defaultCombined={}; my $defaultCombined={};
$infoMap = {} unless defined $infoMap; $infoMap = {} unless defined $infoMap;
@ -1155,9 +1159,9 @@ sub computeDefaults($$$$$) {
if(startsWith($param,$modifier)) { if(startsWith($param,$modifier)) {
my $key = substr($param,$mdLng); my $key = substr($param,$mdLng);
my $val = $globalMap->{':defaults'}->{$param}; my $val = $globalMap->{':defaults'}->{$param};
#Log3('xxx',1,"MQTT_GENERIC_BRIDGE:DEBUG:> computeDefaults> global eval: key: $key, val: $val"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] computeDefaults> global eval: key: $key, val: $val");
$val = _evalValue2($hash->{NAME},$val,$infoMap); $val = _evalValue2($hash->{NAME},$val,$infoMap);
#Log3('xxx',1,"MQTT_GENERIC_BRIDGE:DEBUG:> computeDefaults> global eval done: val: $val"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] computeDefaults> global eval done: val: $val");
$defaultCombined->{$key}=$val; $defaultCombined->{$key}=$val;
} }
} }
@ -1261,10 +1265,10 @@ sub searchDeviceForTopic($$) {
my $dmap = $map->{$dname}->{':subscribe'}; my $dmap = $map->{$dname}->{':subscribe'};
foreach my $rmap (@{$dmap}) { foreach my $rmap (@{$dmap}) {
my $topicExp = $rmap->{'topicExp'}; my $topicExp = $rmap->{'topicExp'};
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> searchDeviceForTopic: $dname => expr: ".Dumper($topicExp)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] searchDeviceForTopic: $dname => expr: ".Dumper($topicExp));
if (defined($topicExp) and $topic =~ $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:> [$hash->{NAME}] searchDeviceForTopic: match topic: $topic, reading: ".$rmap->{'reading'});
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> searchDeviceForTopic: >>>: \$+{name}: ".$+{name}.", \$+{reading}: ".$+{reading}); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] searchDeviceForTopic: >>>: \$+{name}: ".$+{name}.", \$+{reading}: ".$+{reading});
# Check named groups: $+{reading},.. # Check named groups: $+{reading},..
my $reading = undef; my $reading = undef;
my $oReading = $rmap->{'reading'}; my $oReading = $rmap->{'reading'};
@ -1293,7 +1297,7 @@ sub searchDeviceForTopic($$) {
} }
#$reading = $rmap->{'reading'} unless defined $reading; #$reading = $rmap->{'reading'} unless defined $reading;
next unless defined $reading; next unless defined $reading;
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> searchDeviceForTopic: match topic: $topic, reading: $reading, nREading: $nReading, oReading: $oReading"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] searchDeviceForTopic: match topic: $topic, reading: $reading, nREading: $nReading, oReading: $oReading");
my $tn = $dname.':'.$reading; my $tn = $dname.':'.$reading;
$ret->{$tn}->{'mode'}=$rmap->{'mode'}; $ret->{$tn}->{'mode'}=$rmap->{'mode'};
$ret->{$tn}->{'reading'}=$reading; $ret->{$tn}->{'reading'}=$reading;
@ -1301,7 +1305,7 @@ sub searchDeviceForTopic($$) {
$device = $dname unless defined $device; $device = $dname unless defined $device;
$ret->{$tn}->{'device'}=$device; $ret->{$tn}->{'device'}=$device;
$ret->{$tn}->{'expression'}=$rmap->{'expression'}; $ret->{$tn}->{'expression'}=$rmap->{'expression'};
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> searchDeviceForTopic: deliver: ".Dumper($ret)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] searchDeviceForTopic: deliver: ".Dumper($ret));
} }
} }
} }
@ -1333,8 +1337,8 @@ sub createRegexpForTopic($) {
# Attribute-Value zum Parsen # Attribute-Value zum Parsen
sub CreateSingleDeviceTableAttrSubscribe($$$$) { sub CreateSingleDeviceTableAttrSubscribe($$$$) {
my($hash, $dev, $map, $attrVal) = @_; my($hash, $dev, $map, $attrVal) = @_;
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> CreateSingleDeviceTableAttrSubscribe: $dev, $attrVal, ".Dumper($map)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] CreateSingleDeviceTableAttrSubscribe: $dev, $attrVal, ".Dumper($map));
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> CreateSingleDeviceTableAttrSubscribe: ".Dumper($map)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] CreateSingleDeviceTableAttrSubscribe: ".Dumper($map));
# collect subscribe topics # collect subscribe topics
my $devMap = $map->{$dev}; my $devMap = $map->{$dev};
my $globalMap = $map->{':global'}; my $globalMap = $map->{':global'};
@ -1350,12 +1354,12 @@ sub CreateSingleDeviceTableAttrSubscribe($$$$) {
# *:qos=0 # *:qos=0
# *:expression={...} # *:expression={...}
# *:topic={"$base/$reading/xyz"} => topic = "$base/+/xyz" # *:topic={"$base/$reading/xyz"} => topic = "$base/+/xyz"
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> CreateSingleDeviceTableAttrSubscribe: attrVal: ".Dumper($attrVal)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] CreateSingleDeviceTableAttrSubscribe: attrVal: ".Dumper($attrVal));
my($unnamed, $named) = MQTT::parseParams($attrVal,'\s',' ','=', undef); #MQTT::parseParams($attrVal, undef, undef, '=', undef); my($unnamed, $named) = MQTT::parseParams($attrVal,'\s',' ','=', undef); #MQTT::parseParams($attrVal, undef, undef, '=', undef);
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> CreateSingleDeviceTableAttrSubscribe: parseParams: named ".Dumper($named)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] CreateSingleDeviceTableAttrSubscribe: parseParams: named ".Dumper($named));
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> CreateSingleDeviceTableAttrSubscribe: parseParams: unnamed ".Dumper($unnamed)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] CreateSingleDeviceTableAttrSubscribe: parseParams: unnamed ".Dumper($unnamed));
if(defined($named)){ if(defined($named)){
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> CreateSingleDeviceTableAttrSubscribe: ".Dumper($map)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] CreateSingleDeviceTableAttrSubscribe: ".Dumper($map));
my $dmap = {}; my $dmap = {};
foreach my $param (keys %{$named}) { foreach my $param (keys %{$named}) {
my $val = $named->{$param}; my $val = $named->{$param};
@ -1403,22 +1407,25 @@ sub CreateSingleDeviceTableAttrSubscribe($$$$) {
# $base = _evalValue($hash->{NAME},$base,$base,$dev,'$reading','$name'); # $base = _evalValue($hash->{NAME},$base,$base,$dev,'$reading','$name');
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> sub: old base: $base"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] sub: old base: $base");
# $base verwenden => eval # $base verwenden => eval
#my $topic = _evalValue($hash->{NAME},$val,$base,$dev,'$reading','$name'); #my $topic = _evalValue($hash->{NAME},$val,$base,$dev,'$reading','$name');
my $combined = computeDefaults($hash, 'sub:', $globalMap, $devMap, {'device'=>$dev,'reading'=>'#reading','name'=>'#name','mode'=>$rmap->{'mode'}}); my $combined = computeDefaults($hash, 'sub:', $globalMap, $devMap, {'device'=>$dev,'reading'=>'#reading','name'=>'#name','mode'=>$rmap->{'mode'}});
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> sub: Defaults: ".Dumper($combined)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] sub: Defaults: ".Dumper($combined));
my $topic = _evalValue2($hash->{NAME},$val,{'device'=>$dev,'reading'=>'#reading','name'=>'#name',%$combined}) if defined $val; my $topic = _evalValue2($hash->{NAME},$val,{'device'=>$dev,'reading'=>'#reading','name'=>'#name',%$combined}) if defined $val;
if(!defined($topic)) {
Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE: [$hash->{NAME}] subscribe: error while interpret topic: $val");
} else {
my $old = '#reading'; my $old = '#reading';
my $new = '$reading'; my $new = '$reading';
$topic =~ s/\Q$old\E/$new/g; $topic =~ s/\Q$old\E/$new/g;
$old = '#name'; $old = '#name';
$new = '$name'; $new = '$name';
$topic =~ s/\Q$old\E/$new/g; $topic =~ s/\Q$old\E/$new/g;
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> sub: Topic old: $topic"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] sub: Topic old: $topic");
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> sub: Topic new: $topic"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] sub: Topic new: $topic");
$rmap->{'topicOrig'} = $val; $rmap->{'topicOrig'} = $val;
$rmap->{'topicExp'}=createRegexpForTopic($topic); $rmap->{'topicExp'}=createRegexpForTopic($topic);
@ -1426,13 +1433,14 @@ sub CreateSingleDeviceTableAttrSubscribe($$$$) {
$topic =~ s/\$reading/+/g; $topic =~ s/\$reading/+/g;
$topic =~ s/\$name/+/g; $topic =~ s/\$name/+/g;
$topic =~ s/\$device/+/g; $topic =~ s/\$device/+/g;
}
$rmap->{'topic'} = $topic; $rmap->{'topic'} = $topic;
} # <- topic } # <- topic
$dmap->{$namePart} = $rmap; $dmap->{$namePart} = $rmap;
} }
} }
} }
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> >>> CreateSingleDeviceTableAttrSubscribe ".Dumper($dmap)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] >>> CreateSingleDeviceTableAttrSubscribe ".Dumper($dmap));
my @vals = values %{$dmap}; my @vals = values %{$dmap};
$devMap->{':subscribe'}= \@vals; $devMap->{':subscribe'}= \@vals;
} }
@ -1471,7 +1479,7 @@ sub CreateSingleDeviceTable($$$$$) {
# Geraet-Infos neu einlesen # Geraet-Infos neu einlesen
sub _RefreshDeviceTable($$$$;$$) { sub _RefreshDeviceTable($$$$;$$) {
my ($hash, $dev, $devMapName, $prefix, $attrName, $attrVal) = @_; my ($hash, $dev, $devMapName, $prefix, $attrName, $attrVal) = @_;
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> _RefreshDeviceTable: $dev, $devMapName, $prefix, $attrName, $attrVal"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] _RefreshDeviceTable: $dev, $devMapName, $prefix, $attrName, $attrVal");
# Attribute zu dem angegeben Geraet neu erfassen # Attribute zu dem angegeben Geraet neu erfassen
my $map = $hash->{+HS_TAB_NAME_DEVICES}; my $map = $hash->{+HS_TAB_NAME_DEVICES};
if(defined($attrName)) { if(defined($attrName)) {
@ -1545,11 +1553,11 @@ sub CreateDevicesTable($) {
$map = $hash->{+HS_TAB_NAME_DEVICES}; $map = $hash->{+HS_TAB_NAME_DEVICES};
my @devices = devspec2array($hash->{+HS_PROP_NAME_DEVSPEC}); my @devices = devspec2array($hash->{+HS_PROP_NAME_DEVSPEC});
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> CreateDevicesTable: ".Dumper(@devices)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] CreateDevicesTable: ".Dumper(@devices));
my $prefix = $hash->{+HS_PROP_NAME_PREFIX}; my $prefix = $hash->{+HS_PROP_NAME_PREFIX};
foreach my $dev (@devices) { foreach my $dev (@devices) {
if($dev ne $hash->{NAME}) { if($dev ne $hash->{NAME}) {
Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> CreateDevicesTable for ".$dev); Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] CreateDevicesTable for ".$dev);
CreateSingleDeviceTable($hash, $dev, $dev, $prefix, $map); CreateSingleDeviceTable($hash, $dev, $dev, $prefix, $map);
} }
} }
@ -1585,7 +1593,7 @@ sub UpdateSubscriptions($) {
if(defined($gmap)) { if(defined($gmap)) {
foreach my $dname (keys %{$gmap}) { foreach my $dname (keys %{$gmap}) {
my $smap = $gmap->{$dname}->{':subscribe'}; my $smap = $gmap->{$dname}->{':subscribe'};
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> UpdateSubscriptions: smap = ".Dumper($gmap->{$dname})); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] UpdateSubscriptions: smap = ".Dumper($gmap->{$dname}));
if(defined($smap)) { if(defined($smap)) {
foreach my $rmap (@{$smap}) { foreach my $rmap (@{$smap}) {
my $topic = $rmap->{'topic'}; my $topic = $rmap->{'topic'};
@ -1601,7 +1609,7 @@ sub UpdateSubscriptions($) {
} }
my @topics = keys %{$topicMap}; my @topics = keys %{$topicMap};
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> UpdateSubscriptions: topics = ".Dumper(@topics)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] UpdateSubscriptions: topics = ".Dumper(@topics));
my @new=(); my @new=();
my @remove=(); my @remove=();
foreach my $topic (@topics) { foreach my $topic (@topics) {
@ -1613,19 +1621,19 @@ sub UpdateSubscriptions($) {
push @remove,$topic unless grep {$_ eq $topic} @topics; push @remove,$topic unless grep {$_ eq $topic} @topics;
} }
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> UpdateSubscriptions: remove = ".Dumper(@remove)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] UpdateSubscriptions: remove = ".Dumper(@remove));
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> UpdateSubscriptions: new = ".Dumper(@new)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] UpdateSubscriptions: new = ".Dumper(@new));
if(isIODevMQTT($hash)) { if(isIODevMQTT($hash)) {
foreach my $topic (@remove) { foreach my $topic (@remove) {
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> UpdateSubscriptions: unsubscribe: topic = ".Dumper($topic)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] UpdateSubscriptions: unsubscribe: topic = ".Dumper($topic));
client_unsubscribe_topic($hash,$topic); client_unsubscribe_topic($hash,$topic);
} }
foreach my $topic (@new) { foreach my $topic (@new) {
my $qos = $topicMap->{$topic}->{'qos'}; # TODO: Default lesen my $qos = $topicMap->{$topic}->{'qos'}; # TODO: Default lesen
$qos = 0 unless defined $qos; $qos = 0 unless defined $qos;
my $retain = 0; # not supported my $retain = 0; # not supported
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> UpdateSubscriptions: subscribe: topic = ".Dumper($topic).", qos = ".Dumper($qos).", retain = ".Dumper($retain)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] UpdateSubscriptions: subscribe: topic = ".Dumper($topic).", qos = ".Dumper($qos).", retain = ".Dumper($retain));
client_subscribe_topic($hash,$topic,$qos,$retain) ; client_subscribe_topic($hash,$topic,$qos,$retain) ;
} }
} }
@ -1665,7 +1673,7 @@ sub InitializeDevices($) {
my ($hash) = @_; my ($hash) = @_;
# alles neu aufbauen # alles neu aufbauen
# Deviceliste neu aufbauen, ggf., alte subscription kuendigen, neue abonieren # Deviceliste neu aufbauen, ggf., alte subscription kuendigen, neue abonieren
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> ------------ InitializeDevices --------------"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] ------------ InitializeDevices --------------");
CreateDevicesTable($hash); CreateDevicesTable($hash);
#UpdateSubscriptions($hash); #UpdateSubscriptions($hash);
} }
@ -1688,7 +1696,7 @@ my %getsDebug = (
# Routine fuer FHEM Get-Commando # Routine fuer FHEM Get-Commando
sub Get($$$@) { sub Get($$$@) {
my ($hash, $name, $command, $args) = @_; my ($hash, $name, $command, $args) = @_;
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> get CL: ".Dumper($hash->{CL})); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] get CL: ".Dumper($hash->{CL}));
return "Need at least one parameters" unless (defined $command); return "Need at least one parameters" unless (defined $command);
unless (defined($gets{$command}) or (isDebug($hash) && defined($getsDebug{$command}))) { unless (defined($gets{$command}) or (isDebug($hash) && defined($getsDebug{$command}))) {
my $rstr="Unknown argument $command, choose one of"; my $rstr="Unknown argument $command, choose one of";
@ -1831,7 +1839,7 @@ sub Get($$$@) {
sub Notify() { sub Notify() {
my ($hash,$dev) = @_; my ($hash,$dev) = @_;
if( $dev->{NAME} eq "global" ) { if( $dev->{NAME} eq "global" ) {
#Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> notify for global ".Dumper(@{$dev->{CHANGED}})); #Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] notify for global ".Dumper(@{$dev->{CHANGED}}));
if( grep(m/^(INITIALIZED|REREADCFG)$/, @{$dev->{CHANGED}}) ) { if( grep(m/^(INITIALIZED|REREADCFG)$/, @{$dev->{CHANGED}}) ) {
# FHEM (re)Start # FHEM (re)Start
firstInit($hash); firstInit($hash);
@ -1848,35 +1856,35 @@ sub Notify() {
if($s =~ m/^RENAMED ([^ ]*) ([^ ]*)$/) { if($s =~ m/^RENAMED ([^ ]*) ([^ ]*)$/) {
# Device renamed # Device renamed
my ($old, $new) = ($1, $2); my ($old, $new) = ($1, $2);
#Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> Device renamed: $old => $new"); #Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] Device renamed: $old => $new");
# wenn ein ueberwachtes device, tabelle korrigieren # wenn ein ueberwachtes device, tabelle korrigieren
RenameDeviceInTable($hash, $old, $new); RenameDeviceInTable($hash, $old, $new);
} elsif($s =~ m/^DELETED ([^ ]*)$/) { } elsif($s =~ m/^DELETED ([^ ]*)$/) {
# Device deleted # Device deleted
my ($name) = ($1); my ($name) = ($1);
#Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> Device deleted: $name"); #Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] Device deleted: $name");
# wenn ein ueberwachtes device, tabelle korrigieren # wenn ein ueberwachtes device, tabelle korrigieren
DeleteDeviceInTable($hash, $name); DeleteDeviceInTable($hash, $name);
} elsif($s =~ m/^ATTR ([^ ]*) ([^ ]*) (.*)$/) { } elsif($s =~ m/^ATTR ([^ ]*) ([^ ]*) (.*)$/) {
# Attribut created or changed # Attribut created or changed
my ($sdev, $attrName, $val) = ($1, $2, $3); my ($sdev, $attrName, $val) = ($1, $2, $3);
#Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> attr created/changed: $sdev : $attrName = $val"); #Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] attr created/changed: $sdev : $attrName = $val");
# wenn ein ueberwachtes device und attr bzw. steuer.attr, tabelle korrigieren # wenn ein ueberwachtes device und attr bzw. steuer.attr, tabelle korrigieren
if(IsObservedAttribute($hash,$attrName)) { if(IsObservedAttribute($hash,$attrName)) {
#Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> attr created/changed: observed attr: $attrName = $val"); #Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] attr created/changed: observed attr: $attrName = $val");
RefreshDeviceTable($hash, $sdev, $attrName, $val); RefreshDeviceTable($hash, $sdev, $attrName, $val);
} else { } else {
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> attr created/changed: non observed attr = $val"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] attr created/changed: non observed attr = $val");
# check/ publish atopic => val # check/ publish atopic => val
publishDeviceUpdate($hash, $defs{$sdev}, 'A', $attrName, $val); publishDeviceUpdate($hash, $defs{$sdev}, 'A', $attrName, $val);
} }
} elsif($s =~ m/^DELETEATTR ([^ ]*) ([^ ]*)$/) { } elsif($s =~ m/^DELETEATTR ([^ ]*) ([^ ]*)$/) {
# Attribut deleted # Attribut deleted
my ($sdev, $attrName) = ($1, $2); my ($sdev, $attrName) = ($1, $2);
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> attr deleted: $sdev : $attrName"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] attr deleted: $sdev : $attrName");
# wenn ein ueberwachtes device und attr bzw. steuer.attr, tabelle korrigieren # wenn ein ueberwachtes device und attr bzw. steuer.attr, tabelle korrigieren
if(IsObservedAttribute($hash,$attrName)) { if(IsObservedAttribute($hash,$attrName)) {
Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> attr deleted: observed attr: $attrName"); Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] attr deleted: observed attr: $attrName");
RefreshDeviceTable($hash, $sdev, $attrName, undef); RefreshDeviceTable($hash, $sdev, $attrName, undef);
} else { } else {
# check/ publish atopic => null # check/ publish atopic => null
@ -1900,7 +1908,7 @@ sub checkPublishDeviceReadingsUpdates($$) {
my $triggeredReading = $dev->{'.mqttGenericBridge_triggeredReading'}; my $triggeredReading = $dev->{'.mqttGenericBridge_triggeredReading'};
if(defined $triggeredReading) { if(defined $triggeredReading) {
delete $dev->{'.mqttGenericBridge_triggeredReading'}; delete $dev->{'.mqttGenericBridge_triggeredReading'};
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> Notify [mqttGenericBridge_triggeredReading]=>".$triggeredReading); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] Notify [mqttGenericBridge_triggeredReading]=>".$triggeredReading);
return; return;
} }
@ -1911,7 +1919,7 @@ sub checkPublishDeviceReadingsUpdates($$) {
return "" if(main::IsDisabled($hash->{NAME})); return "" if(main::IsDisabled($hash->{NAME}));
#CheckInitialization($hash); #CheckInitialization($hash);
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> checkPublishDeviceReadingsUpdates ------------------------ "); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] checkPublishDeviceReadingsUpdates ------------------------ ");
# Pruefen, ob ein ueberwachtes Geraet vorliegt # Pruefen, ob ein ueberwachtes Geraet vorliegt
my $devName = $dev->{NAME}; my $devName = $dev->{NAME};
@ -1929,9 +1937,9 @@ sub checkPublishDeviceReadingsUpdates($$) {
} }
foreach my $event (@{deviceEvents($dev,1)}) { foreach my $event (@{deviceEvents($dev,1)}) {
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> Notify for $dev->{NAME} event: $event STATE: $dev->{STATE}"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] Notify for $dev->{NAME} event: $event STATE: $dev->{STATE}");
$event =~ /^([^:]+)(: )?(.*)$/; $event =~ /^([^:]+)(: )?(.*)$/;
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> event: $event, '".((defined $1) ? $1 : "-undef-")."', '".((defined $3) ? $3 : "-undef-")."'"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] event: $event, '".((defined $1) ? $1 : "-undef-")."', '".((defined $3) ? $3 : "-undef-")."'");
my $devreading = $1; my $devreading = $1;
my $devval = $3; my $devval = $3;
if(defined $devreading and defined $devval) { if(defined $devreading and defined $devval) {
@ -1985,7 +1993,7 @@ sub defineGlobalTypeExclude($;$) {
next if($type eq ''); next if($type eq '');
$reading='*' unless defined $reading; $reading='*' unless defined $reading;
$reading = '*' if $reading eq ''; $reading = '*' if $reading eq '';
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> defineGlobalTypeExclude: dir, type, reading: ".Dumper(($dir, $type, $reading))); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] defineGlobalTypeExclude: dir, type, reading: ".Dumper(($dir, $type, $reading)));
if (!defined $dir) { if (!defined $dir) {
$hash->{+HS_PROP_NAME_GLOBAL_EXCLUDES_READING}->{'pub'}->{$reading}=1 if (defined($reading) and ($type eq '*')); $hash->{+HS_PROP_NAME_GLOBAL_EXCLUDES_READING}->{'pub'}->{$reading}=1 if (defined($reading) and ($type eq '*'));
$hash->{+HS_PROP_NAME_GLOBAL_EXCLUDES_TYPE}->{'pub'}->{$type}=$reading if($type ne '*'); $hash->{+HS_PROP_NAME_GLOBAL_EXCLUDES_TYPE}->{'pub'}->{$type}=$reading if($type ne '*');
@ -2039,7 +2047,7 @@ sub defineGlobalDevExclude($;$) {
next if($dev eq ''); next if($dev eq '');
$reading = '*' unless defined $reading; $reading = '*' unless defined $reading;
$reading = '*' if $reading eq ''; $reading = '*' if $reading eq '';
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> defineGlobalDevExclude: dir, dev, reading: ".Dumper(($dir, $dev, $reading))); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] defineGlobalDevExclude: dir, dev, reading: ".Dumper(($dir, $dev, $reading)));
if (!defined $dir) { if (!defined $dir) {
$hash->{+HS_PROP_NAME_GLOBAL_EXCLUDES_DEVICES}->{'pub'}->{$dev}=$reading if($dev ne '*'); $hash->{+HS_PROP_NAME_GLOBAL_EXCLUDES_DEVICES}->{'pub'}->{$dev}=$reading if($dev ne '*');
$hash->{+HS_PROP_NAME_GLOBAL_EXCLUDES_DEVICES}->{'sub'}->{$dev}=$reading if($dev ne '*'); $hash->{+HS_PROP_NAME_GLOBAL_EXCLUDES_DEVICES}->{'sub'}->{$dev}=$reading if($dev ne '*');
@ -2116,7 +2124,7 @@ sub isDoForward($$$) {
$doForward = 'all' unless defined $doForward; $doForward = 'all' unless defined $doForward;
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> isDoForward $devName => $doForward"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] isDoForward $devName => $doForward");
return 1 if $doForward eq 'all'; return 1 if $doForward eq 'all';
return 0; return 0;
@ -2127,12 +2135,12 @@ sub isDoForward($$$) {
sub doPublish($$$$$$$$) { sub doPublish($$$$$$$$) {
my ($hash,$device,$reading,$topic,$message,$qos,$retain,$resendOnConnect) = @_; my ($hash,$device,$reading,$topic,$message,$qos,$retain,$resendOnConnect) = @_;
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> doPublish: topic: $topic, msg: $message, resend mode: ".(defined($resendOnConnect)?$resendOnConnect:"no")); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] doPublish: topic: $topic, msg: $message, resend mode: ".(defined($resendOnConnect)?$resendOnConnect:"no"));
if(!isConnected($hash)) { if(!isConnected($hash)) {
# store message? # store message?
if(defined($resendOnConnect)) { if(defined($resendOnConnect)) {
$resendOnConnect = lc($resendOnConnect); $resendOnConnect = lc($resendOnConnect);
Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> offline publish: store: topic: $topic, msg: $message, mode: $resendOnConnect"); Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] offline publish: store: topic: $topic, msg: $message, mode: $resendOnConnect");
if($resendOnConnect eq 'first' or $resendOnConnect eq 'last' or $resendOnConnect eq 'all') { if($resendOnConnect eq 'first' or $resendOnConnect eq 'last' or $resendOnConnect eq 'all') {
# store msg data # store msg data
my $queue = $hash->{+HELPER}->{+HS_PROP_NAME_PUB_OFFLINE_QUEUE}; my $queue = $hash->{+HELPER}->{+HS_PROP_NAME_PUB_OFFLINE_QUEUE};
@ -2164,7 +2172,7 @@ sub doPublish($$$$$$$$) {
} }
$queue->{$topic} = $topicQueue; $queue->{$topic} = $topicQueue;
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> offline publish: stored: ".Dumper($queue)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] offline publish: stored: ".Dumper($queue));
$hash->{+HELPER}->{+HS_PROP_NAME_PUB_OFFLINE_QUEUE} = $queue; $hash->{+HELPER}->{+HS_PROP_NAME_PUB_OFFLINE_QUEUE} = $queue;
} }
@ -2172,7 +2180,7 @@ sub doPublish($$$$$$$$) {
return 'stored'; return 'stored';
} }
Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> publish: $topic => $message (qos: $qos, retain: ".(defined($retain)?$retain:'0').")"); Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] publish: $topic => $message (qos: $qos, retain: ".(defined($retain)?$retain:'0').")");
if (isIODevMQTT2($hash)){ #if ($hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT2_SERVER') { if (isIODevMQTT2($hash)){ #if ($hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT2_SERVER') {
# TODO: publish MQTT2 # TODO: publish MQTT2
@ -2184,14 +2192,14 @@ sub doPublish($$$$$$$$) {
readingsSingleUpdate($hash,"outgoing-count",$hash->{+HELPER}->{+HS_PROP_NAME_OUTGOING_CNT},1); readingsSingleUpdate($hash,"outgoing-count",$hash->{+HELPER}->{+HS_PROP_NAME_OUTGOING_CNT},1);
return undef; return undef;
} elsif (isIODevMQTT($hash)) { #elsif ($hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT') { } elsif (isIODevMQTT($hash)) { #elsif ($hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT') {
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> doPublish for $devn, $reading, $value, topic: $topic, message: $message"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] doPublish for $devn, $reading, $value, topic: $topic, message: $message");
my $msgid; my $msgid;
if(defined($topic) and defined($message)) { if(defined($topic) and defined($message)) {
$msgid = send_publish($hash->{IODev}, topic => $topic, message => $message, qos => $qos, retain => $retain); $msgid = send_publish($hash->{IODev}, topic => $topic, message => $message, qos => $qos, retain => $retain);
readingsSingleUpdate($hash,"transmission-state","outgoing publish sent",1); readingsSingleUpdate($hash,"transmission-state","outgoing publish sent",1);
$hash->{+HELPER}->{+HS_PROP_NAME_OUTGOING_CNT}++; $hash->{+HELPER}->{+HS_PROP_NAME_OUTGOING_CNT}++;
readingsSingleUpdate($hash,"outgoing-count",$hash->{+HELPER}->{+HS_PROP_NAME_OUTGOING_CNT},1); readingsSingleUpdate($hash,"outgoing-count",$hash->{+HELPER}->{+HS_PROP_NAME_OUTGOING_CNT},1);
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> publish: $topic => $message"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] publish: $topic => $message");
return undef; return undef;
} }
$hash->{message_ids}->{$msgid}++ if defined $msgid; $hash->{message_ids}->{$msgid}++ if defined $msgid;
@ -2199,7 +2207,7 @@ sub doPublish($$$$$$$$) {
} else { } else {
my ($iodt, $iodn) = retrieveIODev($hash); my ($iodt, $iodn) = retrieveIODev($hash);
$iodt = 'undef' unless defined $iodt; $iodt = 'undef' unless defined $iodt;
Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE: unknown IODev: ".$iodt); Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE: [$hash->{NAME}] unknown IODev: ".$iodt);
return 'unknown IODev'; return 'unknown IODev';
} }
} }
@ -2213,7 +2221,7 @@ sub publishDeviceUpdate($$$$$) {
my $devn = $devHash->{NAME}; my $devn = $devHash->{NAME};
my $type = $devHash->{TYPE}; my $type = $devHash->{TYPE};
$mode = 'R' unless defined $mode; $mode = 'R' unless defined $mode;
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> publishDeviceUpdate for $type, $mode, $devn, $reading, $value"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] publishDeviceUpdate for $type, $mode, $devn, $reading, $value");
# bestimmte bekannte types und readings ausschliessen (vor allem 'transmission-state' in der eigenen Instanz, das fuert sonst zu einem Endlosloop) # bestimmte bekannte types und readings ausschliessen (vor allem 'transmission-state' in der eigenen Instanz, das fuert sonst zu einem Endlosloop)
return if($type eq "MQTT_GENERIC_BRIDGE"); return if($type eq "MQTT_GENERIC_BRIDGE");
return if($type eq "MQTT"); return if($type eq "MQTT");
@ -2230,9 +2238,9 @@ sub publishDeviceUpdate($$$$$) {
# extra definierte (ansonsten gilt eine Defaultliste) Types/Readings auschliessen. # extra definierte (ansonsten gilt eine Defaultliste) Types/Readings auschliessen.
return if(isTypeDevReadingExcluded($hash, 'pub', $type, $devn, $reading)); return if(isTypeDevReadingExcluded($hash, 'pub', $type, $devn, $reading));
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> publishDeviceUpdate for $devn, $reading, $value"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] publishDeviceUpdate for $devn, $reading, $value");
my $pubRec = getDevicePublishRec($hash, $devn, $reading); my $pubRec = getDevicePublishRec($hash, $devn, $reading);
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> publishDeviceUpdate pubRec: ".Dumper($pubRec)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] publishDeviceUpdate pubRec: ".Dumper($pubRec));
if(defined($pubRec)) { if(defined($pubRec)) {
# my $msgid; # my $msgid;
@ -2249,7 +2257,7 @@ sub publishDeviceUpdate($$$$$) {
# # damit beim start die Attribute einmal uebertragen werden => geht wohl mangels event beim start nicht # # damit beim start die Attribute einmal uebertragen werden => geht wohl mangels event beim start nicht
# if(!$main::init_done and !defined($resendOnConnect) and ($mode eq 'A')) { # if(!$main::init_done and !defined($resendOnConnect) and ($mode eq 'A')) {
# $resendOnConnect = 'last'; # $resendOnConnect = 'last';
# Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> queueing Attr-Chang at start"); # Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] queueing Attr-Chang at start");
# } # }
$base='' unless defined $base; $base='' unless defined $base;
@ -2279,9 +2287,9 @@ sub publishDeviceUpdate($$$$$) {
} else { } else {
$message = $ret; $message = $ret;
} }
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> eval done: ".Dumper($ret)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] eval done: ".Dumper($ret));
if ($@) { if ($@) {
Log3($hash->{NAME},2,"MQTT_GENERIC_BRIDGE: error while evaluating expression ('".$expression."'') eval error: ".$@); Log3($hash->{NAME},2,"MQTT_GENERIC_BRIDGE: [$hash->{NAME}] error while evaluating expression ('".$expression."'') eval error: ".$@);
} }
use strict "refs"; use strict "refs";
} }
@ -2383,7 +2391,7 @@ sub Attr($$$$) {
my $oldValue = $main::attr{$name}{IODev}; my $oldValue = $main::attr{$name}{IODev};
if ($main::init_done) { if ($main::init_done) {
unless (defined ($oldValue) and ($oldValue eq $value) ) { unless (defined ($oldValue) and ($oldValue eq $value) ) {
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> attr: change IODev"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] attr: change IODev");
MQTT::client_stop($hash) if defined($main::attr{$name}{IODev}) and ($main::attr{$name}{IODev} eq 'MQTT'); MQTT::client_stop($hash) if defined($main::attr{$name}{IODev}) and ($main::attr{$name}{IODev} eq 'MQTT');
$main::attr{$name}{IODev} = $value; $main::attr{$name}{IODev} = $value;
firstInit($hash); firstInit($hash);
@ -2409,7 +2417,7 @@ sub ioDevConnect($) {
# ueberraschenderweise notwendig fuer eine subscribe-Initialisierung. # ueberraschenderweise notwendig fuer eine subscribe-Initialisierung.
MQTT::client_start($hash) if isIODevMQTT($hash); MQTT::client_start($hash) if isIODevMQTT($hash);
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> ioDevConnect"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] ioDevConnect");
# resend stored msgs => doPublish (...., undef) # resend stored msgs => doPublish (...., undef)
my $queue = $hash->{+HELPER}->{+HS_PROP_NAME_PUB_OFFLINE_QUEUE}; my $queue = $hash->{+HELPER}->{+HS_PROP_NAME_PUB_OFFLINE_QUEUE};
@ -2437,7 +2445,7 @@ sub ioDevDisconnect($) {
my $hash = shift; my $hash = shift;
#return if isIODevMQTT2($hash); #if $hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT2_SERVER'; #return if isIODevMQTT2($hash); #if $hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT2_SERVER';
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> ioDevDisconnect"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] ioDevDisconnect");
# TODO ? # TODO ?
} }
@ -2449,13 +2457,13 @@ sub doSetUpdate($$$$$) {
my $dhash = $defs{$device}; my $dhash = $defs{$device};
return unless defined $dhash; return unless defined $dhash;
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE: setUpdate enter: update: $reading = $message"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE: [$hash->{NAME}] setUpdate enter: update: $reading = $message");
my $doForward = isDoForward($hash, $device,$reading); my $doForward = isDoForward($hash, $device,$reading);
if($mode eq 'S') { if($mode eq 'S') {
my $err; my $err;
my @args = split ("[ \t]+",$message); my @args = split ("[ \t]+",$message);
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> mqttGenericBridge_triggeredReading=".Dumper($dhash->{'.mqttGenericBridge_triggeredReading'})); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] mqttGenericBridge_triggeredReading=".Dumper($dhash->{'.mqttGenericBridge_triggeredReading'}));
if(($reading eq '') or ($reading eq 'state')) { if(($reading eq '') or ($reading eq 'state')) {
$dhash->{'.mqttGenericBridge_triggeredReading'}="state" unless $doForward; $dhash->{'.mqttGenericBridge_triggeredReading'}="state" unless $doForward;
#$err = DoSet($device,$message); #$err = DoSet($device,$message);
@ -2470,7 +2478,7 @@ sub doSetUpdate($$$$$) {
readingsSingleUpdate($hash,"updated-set-count",$hash->{+HELPER}->{+HS_PROP_NAME_UPDATE_S_CNT},1); readingsSingleUpdate($hash,"updated-set-count",$hash->{+HELPER}->{+HS_PROP_NAME_UPDATE_S_CNT},1);
return undef; return undef;
} }
Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE: setUpdate: error in set command: ".$err); Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE: [$hash->{NAME}] setUpdate: error in set command: ".$err);
return "error in set command: $err"; return "error in set command: $err";
} elsif($mode eq 'R') { # or $mode eq 'T') { } elsif($mode eq 'R') { # or $mode eq 'T') {
# R - Normale Topic (beim Empfang nicht weiter publishen) # R - Normale Topic (beim Empfang nicht weiter publishen)
@ -2481,7 +2489,7 @@ sub doSetUpdate($$$$$) {
} }
readingsBulkUpdate($dhash,$reading,$message); readingsBulkUpdate($dhash,$reading,$message);
readingsEndUpdate($dhash,1); readingsEndUpdate($dhash,1);
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE: setUpdate: update: $reading = $message"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE: [$hash->{NAME}] setUpdate: update: $reading = $message");
# wird in 'notify' entfernt # delete $dhash->{'.mqttGenericBridge_triggeredReading'}; # wird in 'notify' entfernt # delete $dhash->{'.mqttGenericBridge_triggeredReading'};
$hash->{+HELPER}->{+HS_PROP_NAME_UPDATE_R_CNT}++; $hash->{+HELPER}->{+HS_PROP_NAME_UPDATE_R_CNT}++;
@ -2491,7 +2499,7 @@ sub doSetUpdate($$$$$) {
CommandAttr(undef, "$device $reading $message"); CommandAttr(undef, "$device $reading $message");
return undef; return undef;
} else { } else {
Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE: setUpdate: unexpected mode: ".$mode); Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE: [$hash->{NAME}] setUpdate: unexpected mode: ".$mode);
return "unexpected mode: $mode"; return "unexpected mode: $mode";
} }
return "internal error"; return "internal error";
@ -2512,12 +2520,12 @@ sub Parse($$) {
my $hash = $defs{$dev}; my $hash = $defs{$dev};
# Name mit IODev vegleichen # Name mit IODev vegleichen
my ($iiodt, $iiodn) = retrieveIODev($hash); my ($iiodt, $iiodn) = retrieveIODev($hash);
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE: Parse: test IODev: $iiodn vs. $ioname"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE: [$hash->{NAME}] Parse: test IODev: $iiodn vs. $ioname");
next unless $ioname eq $iiodn; next unless $ioname eq $iiodn;
next unless checkIODevMQTT2($iiodt); next unless checkIODevMQTT2($iiodt);
#next unless isIODevMQTT2($hash); #next unless isIODevMQTT2($hash);
Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE: Parse ($iiodt : '$ioname'): Msg: $topic => $value"); Log3($hash->{NAME},5,"MQTT_GENERIC_BRIDGE: [$hash->{NAME}] Parse ($iiodt : '$ioname'): Msg: $topic => $value");
return onmessage($hash, $topic, $value); return onmessage($hash, $topic, $value);
} }
@ -2527,13 +2535,13 @@ sub Parse($$) {
sub onmessage($$$) { sub onmessage($$$) {
my ($hash,$topic,$message) = @_; my ($hash,$topic,$message) = @_;
#CheckInitialization($hash); #CheckInitialization($hash);
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> onmessage: $topic => $message"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] onmessage: $topic => $message");
$hash->{+HELPER}->{+HS_PROP_NAME_INCOMING_CNT}++; $hash->{+HELPER}->{+HS_PROP_NAME_INCOMING_CNT}++;
readingsSingleUpdate($hash,"incoming-count",$hash->{+HELPER}->{+HS_PROP_NAME_INCOMING_CNT},1); readingsSingleUpdate($hash,"incoming-count",$hash->{+HELPER}->{+HS_PROP_NAME_INCOMING_CNT},1);
my $fMap = searchDeviceForTopic($hash, $topic); my $fMap = searchDeviceForTopic($hash, $topic);
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> onmessage: $fMap : ".Dumper($fMap)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] onmessage: $fMap : ".Dumper($fMap));
my $updated = 0; my $updated = 0;
my @updatedList; my @updatedList;
foreach my $deviceKey (keys %{$fMap}) { foreach my $deviceKey (keys %{$fMap}) {
@ -2559,7 +2567,7 @@ sub onmessage($$$) {
# Bei einem Hash werden Paare als Reading-Wert Paare gesetzt (auch set (stopic), attr (atopic)) # Bei einem Hash werden Paare als Reading-Wert Paare gesetzt (auch set (stopic), attr (atopic))
no strict "refs"; no strict "refs";
local $@; local $@;
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> eval ($expression) !!!"); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] eval ($expression) !!!");
my $value = $message; my $value = $message;
my $ret = eval($expression); my $ret = eval($expression);
if(ref($ret) eq 'HASH') { if(ref($ret) eq 'HASH') {
@ -2573,9 +2581,9 @@ sub onmessage($$$) {
} else { } else {
$message = $ret; $message = $ret;
} }
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> eval done: ".Dumper($ret)); #Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE:DEBUG:> [$hash->{NAME}] eval done: ".Dumper($ret));
if ($@) { if ($@) {
Log3($hash->{NAME},2,"MQTT_GENERIC_BRIDGE: onmessage: error while evaluating expression ('".$expression."'') eval error: ".$@); Log3($hash->{NAME},2,"MQTT_GENERIC_BRIDGE: [$hash->{NAME}] onmessage: error while evaluating expression ('".$expression."'') eval error: ".$@);
} }
use strict "refs"; use strict "refs";
} }
@ -2701,7 +2709,7 @@ sub onmessage($$$) {
<ul> <ul>
<p>the following attributes are supported:</p> <p>the following attributes are supported:</p>
<li><p>IODev<br/> <li><p>IODev<br/>
This attribute is mandatory and must contain the name of a functioning MQTT module instance. MQTT2_SERVER module is not supported.</p> This attribute is mandatory and must contain the name of a functioning MQTT-IO module instance. MQTT, MQTT2_CLIENT and MQTT2_SERVER are supported.</p>
</li> </li>
<li> <li>
@ -3092,7 +3100,7 @@ sub onmessage($$$) {
<p>folgende Attribute werden unterstuetzt:</p> <p>folgende Attribute werden unterstuetzt:</p>
<li><p>IODev<br/> <li><p>IODev<br/>
Dieses Attribut ist obligatorisch und muss den Namen einer funktionierenden MQTT-Modulinstanz enthalten. Dieses Attribut ist obligatorisch und muss den Namen einer funktionierenden MQTT-Modulinstanz enthalten.
Modul MQTT2_SERVER wird nicht unterstuetzt.</p> Es werden derzeit MQTT, MQTT2_CLIENT und MQTT2_SERVER unterstuetzt.</p>
</li> </li>
<li> <li>