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

fix: wildcards in subscriptions, cleanup dev table, minor fixes

git-svn-id: https://svn.fhem.de/fhem/trunk@17262 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
hexenmeister 2018-09-03 20:06:15 +00:00
parent c038479353
commit 69776a109b

View File

@ -29,7 +29,7 @@ use warnings;
#my $DEBUG = 1;
my $cvsid = '$Id$';
my $VERSION = "version 0.9.1 by hexenmeister\n$cvsid";
my $VERSION = "version 0.9.3 by hexenmeister\n$cvsid";
my %sets = (
);
@ -94,8 +94,11 @@ sub MQTT_GENERIC_BRIDGE_Initialize($) {
#if($DEBUG) {
#if($hash->{'.debug'}) {
foreach my $d (keys %defs) {
if($defs{$d}{TYPE} eq "MQTT_GENERIC_BRIDGE") {
$defs{$d}{".initialized"} = 0;
if(defined($defs{$d}{TYPE})) {
if($defs{$d}{TYPE} eq "MQTT_GENERIC_BRIDGE") {
$defs{$d}{".initialized"} = 0;
#Log3($hash->{NAME},1,"MQTT-GB:DEBUG:> !!!!!!!!!!!!!!! $d");
}
}
}
#}
@ -195,6 +198,9 @@ sub isConnected($);
sub ioDevConnect($);
sub ioDevDisconnect($);
sub updateDevCount($);
sub retrieveIODev($);
sub isIODevMQTT2($);
sub isIODevMQTT($);
sub isDebug($) {
my ($hash) = @_;
@ -219,7 +225,7 @@ sub Define() {
$hash->{+HS_PROP_NAME_PREFIX}=$prefix; # store in device hash
$hash->{+HS_PROP_NAME_DEVSPEC} = defined($devspec)?$devspec:".*";
Log3($hash->{NAME},1,"MQTT-GB:DEBUG:> [$hash->{NAME}] Define: params: $name, $type, $hash->{+HS_PROP_NAME_PREFIX}, $hash->{+HS_PROP_NAME_DEVSPEC}");
Log3($hash->{NAME},5,"MQTT-GB:DEBUG:> [$hash->{NAME}] Define: params: $name, $type, $hash->{+HS_PROP_NAME_PREFIX}, $hash->{+HS_PROP_NAME_DEVSPEC}");
$hash->{+HS_PROP_NAME_GLOBAL_EXCLUDES_READING} = {};
$hash->{+HS_PROP_NAME_GLOBAL_EXCLUDES_TYPE} = {};
@ -251,10 +257,37 @@ sub Define() {
sub Undefine() {
my ($hash) = @_;
RemoveInternalTimer($hash);
MQTT::client_stop($hash) if defined($hash->{+HELPER}->{+IO_DEV_TYPE}) and $hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT';
MQTT::client_stop($hash) if isIODevMQTT($hash); #if defined($hash->{+HELPER}->{+IO_DEV_TYPE}) and $hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT';
removeOldUserAttr($hash);
}
sub retrieveIODev($) {
my ($hash) = @_;
my $iodn = AttrVal($hash->{NAME}, "IODev", undef);
my $iodt = undef;
if(defined($iodn) and defined($defs{$iodn})) {
$iodt = $defs{$iodn}{TYPE};
}
$hash->{+HELPER}->{+IO_DEV_TYPE} = $iodt;
return $hash->{+HELPER}->{+IO_DEV_TYPE};
}
sub isIODevMQTT($) {
my ($hash) = @_;
my $iodt = retrieveIODev($hash);
return 0 unless defined $iodt;
return 0 unless $iodt eq 'MQTT';
return 1;
}
sub isIODevMQTT2($) {
my ($hash) = @_;
my $iodt = retrieveIODev($hash);
return 0 unless defined $iodt;
return 0 unless $iodt eq 'MQTT2_SERVER';
return 1;
}
# Erstinitialization.
# Variablen werden im HASH abgelegt, userattr der betroffenen Geraete wird erweitert, MQTT-Initialisierungen.
sub firstInit($) {
@ -275,7 +308,7 @@ sub firstInit($) {
removeOldUserAttr($hash, $prefix_old, $devspec);
}
my @devices = devspec2array($devspec);
Log3($hash->{NAME},1,"MQTT-GB:DEBUG:> [$hash->{NAME}] firstInit: addToDevAttrList: $prefix");
Log3($hash->{NAME},5,"MQTT-GB:DEBUG:> [$hash->{NAME}] firstInit: addToDevAttrList: $prefix");
foreach my $dev (@devices) {
addToDevAttrList($dev, $prefix.CTRL_ATTR_NAME_DEFAULTS.":textField-long");
addToDevAttrList($dev, $prefix.CTRL_ATTR_NAME_ALIAS.":textField-long");
@ -301,7 +334,7 @@ sub firstInit($) {
InternalTimer(gettimeofday()+$hash->{+HELPER}->{+HS_PROP_NAME_INTERVAL}, "MQTT::GENERIC_BRIDGE::timerProc", $hash, 0);
}
MQTT::client_start($hash) if defined $hash->{+HELPER}->{+IO_DEV_TYPE} and $hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT';
MQTT::client_start($hash) if isIODevMQTT($hash); #if defined $hash->{+HELPER}->{+IO_DEV_TYPE} and $hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT';
}
}
@ -321,8 +354,8 @@ sub timerProc($) {
# Parameter: Bridge-Hash
sub isConnected($) {
my $hash = shift;
return MQTT::isConnected($hash->{IODev}) if $hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT';
return 1 if $hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT2_SERVER';
return MQTT::isConnected($hash->{IODev}) if isIODevMQTT($hash); #if $hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT';
return 1 if isIODevMQTT2($hash); #if $hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT2_SERVER';
}
sub updateDevCount($) {
@ -795,10 +828,30 @@ sub CreateSingleDeviceTableAttrSubscribe($$$$) {
my @vals = values %{$dmap};
$devMap->{':subscribe'}= \@vals;
}
$map->{$dev} = $devMap;
}
return undef;
}
sub deleteEmptyDevices($$$) {
my ($hash, $map, $devMapName) = @_;
return unless defined $map;
return unless defined $devMapName;
return unless defined $map->{$devMapName};
# Wenn keine Eintraege => Device loeschen
#Log3($hash->{NAME},1,"MQTT-GB:DEBUG:> >>> deleteEmptyDevices: ".(keys %{$map->{$devMapName}})." - ".Dumper($map->{$devMapName}));
if(defined($map->{$devMapName}->{':publish'})) {
#Log3($hash->{NAME},1,"MQTT-GB:DEBUG:> >>> deleteEmptyDevices: :publish ".(keys %{$map->{$devMapName}->{':publish'}})." - ".Dumper($map->{$devMapName}->{':publish'}));
#if(keys %{$map->{$devMapName}->{':publish'}} == 0) {
# delete($map->{$devMapName}->{':publish'});
#}
}
if(keys %{$map->{$devMapName}} == 0) {
delete($map->{$devMapName});
}
}
sub CreateSingleDeviceTable($$$$$) {
my ($hash, $dev, $devMapName, $prefix, $map) = @_;
# Divece-Attribute fuer ein bestimmtes Device aus Device-Attributen auslesen
@ -807,13 +860,7 @@ sub CreateSingleDeviceTable($$$$$) {
CreateSingleDeviceTableAttrAlias($hash, $devMapName, $map, AttrVal($dev, $prefix.CTRL_ATTR_NAME_ALIAS, undef));
CreateSingleDeviceTableAttrPublish($hash, $devMapName, $map, AttrVal($dev, $prefix.CTRL_ATTR_NAME_PUBLISH, undef));
CreateSingleDeviceTableAttrSubscribe($hash, $devMapName, $map, AttrVal($dev, $prefix.CTRL_ATTR_NAME_SUBSCRIBE, undef));
# Wenn keine Eintraege => Device loeschen
if(defined($map->{$devMapName})) {
#Log3($hash->{NAME},1,"MQTT-GB:DEBUG:> >>> ".(keys %{$map->{$dev}})." - ".Dumper($map->{$dev}));
if(keys %{$map->{$devMapName}} == 0) {
delete($map->{$devMapName});
}
}
deleteEmptyDevices($hash, $map, $devMapName);
}
sub _RefreshDeviceTable($$$$;$$) {
@ -831,6 +878,8 @@ sub _RefreshDeviceTable($$$$;$$) {
# ... oder gleich fuer alle (dann aus Device Attributes gelesen)
CreateSingleDeviceTable($hash, $dev, $devMapName, $prefix, $map);
}
deleteEmptyDevices($hash, $map, $devMapName) unless defined $attrVal;
UpdateSubscriptionsSingleDevice($hash, $dev);
}
@ -905,8 +954,8 @@ sub UpdateSubscriptions($) {
updateDevCount($hash);
return unless defined $hash->{+HELPER}->{+IO_DEV_TYPE};
return if $hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT2_SERVER';
#return unless defined $hash->{+HELPER}->{+IO_DEV_TYPE};
return unless isIODevMQTT($hash); #if $hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT2_SERVER';
my $topicMap = {};
my $gmap = $hash->{+HS_TAB_NAME_DEVICES};
@ -966,8 +1015,8 @@ sub UpdateSubscriptions($) {
sub RemoveAllSubscripton($) {
my ($hash) = @_;
return unless defined $hash->{+HELPER}->{+IO_DEV_TYPE};
return if $hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT2_SERVER';
#return unless defined $hash->{+HELPER}->{+IO_DEV_TYPE};
return unless isIODevMQTT($hash); #if $hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT2_SERVER';
# alle Subscription kuendigen (beim undefine)
@ -1158,7 +1207,7 @@ sub Notify() {
} elsif($s =~ m/^DELETEATTR ([^ ]*) ([^ ]*)$/) {
# Attribut deleted
my ($sdev, $attrName) = ($1, $2);
#Log3($hash->{NAME},5,"MQTT-GB:DEBUG:> attr deleted: $sdev : $attrName");
#Log3($hash->{NAME},1,"MQTT-GB:DEBUG:> attr deleted: $sdev : $attrName");
# wenn ein ueberwachtes device und attr bzw. steuer.attr, tabelle korrigieren
RefreshDeviceTable($hash, $sdev, $attrName, undef) if(IsObservedAttribute($hash,$attrName));
}
@ -1187,13 +1236,16 @@ sub Notify() {
return "" unless ($size>0);
}
Log3($hash->{NAME},5,"Notify for $dev->{NAME}");
foreach my $event (@{$dev->{CHANGED}}) {
#Log3($hash->{NAME},5,"Notify for $dev->{NAME} event: $event STATE: $dev->{STATE}");
$event =~ /^([^:]+)(: )?(.*)$/;
#Log3($hash->{NAME},1,"MQTT-GB:DEBUG:> event: $event, '".((defined $1) ? $1 : "-undef-")."', '".((defined $3) ? $3 : "-undef-")."'");
my $devreading = undef;
my $devval = undef;
if (defined $3 and $3 ne "") {
# pruefen, ob der neue Wert dem 'state' des Devices entspricht
# {$defs{$dev}{STATE}}
if ($dev->{STATE} ne $event) {
#if (defined $3 and $3 ne "") {
#send reading=$1 value=$3
#publishDeviceUpdate($hash, $dev, $1, $3);
$devreading = $1;
@ -1202,8 +1254,10 @@ sub Notify() {
#send reading=state value=$1
#publishDeviceUpdate($hash, $dev, 'state', $1);
$devreading = 'state';
$devval = $1;
#$devval = $1;
$devval = $event;
}
#Log3($hash->{NAME},5,"Notify for $dev->{NAME} reading: $devreading, val: $devval");
if(defined $devreading and defined $devval) {
# wenn ueberwachtes device and reading
publishDeviceUpdate($hash, $dev, $devreading, $devval);
@ -1315,12 +1369,12 @@ sub isTypeDevReadingExcluded($$$$) {
sub doPublish($$$$$) {
my ($hash,$topic,$message,$qos,$retain) = @_;
return unless defined $hash->{+HELPER}->{+IO_DEV_TYPE};
if ($hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT2_SERVER') {
#return unless defined $hash->{+HELPER}->{+IO_DEV_TYPE};
if (isIODevMQTT2($hash)){ #if ($hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT2_SERVER') {
# TODO: publish MQTT2
return;
} elsif ($hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT') {
} elsif (isIODevMQTT($hash)) { #elsif ($hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT') {
#Log3($hash->{NAME},1,"publishDeviceUpdate for $devn, $reading, $value, topic: $topic, message: $message");
my $msgid;
if(defined($topic) and defined($message)) {
@ -1332,7 +1386,9 @@ sub doPublish($$$$$) {
}
$hash->{message_ids}->{$msgid}++ if defined $msgid;
} else {
# TODO: Error unknown IO
my $iodt = retrieveIODev($hash);
$iodt = 'undef' unless defined $iodt;
Log3($hash->{NAME},1,"unknown IODev: ".$iodt);
}
}
@ -1480,11 +1536,11 @@ sub Attr($$$$) {
if ($main::init_done) {
if ($command eq "set") {
MQTT::client_stop($hash) if $hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT';
MQTT::client_stop($hash) if $ioDevType eq 'MQTT';
$main::attr{$name}{IODev} = $value;
MQTT::client_start($hash) if $hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT';
MQTT::client_start($hash) if $ioDevType eq 'MQTT';
} else {
MQTT::client_stop($hash) if $hash->{+HELPER}->{+IO_DEV_TYPE} eq 'MQTT';
MQTT::client_stop($hash) if $ioDevType eq 'MQTT';
}
}
last;
@ -1495,14 +1551,14 @@ sub Attr($$$$) {
sub ioDevConnect($) {
my $hash = shift;
return 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: ioDevConnect");
# TODO
}
sub ioDevDisconnect($) {
my $hash = shift;
return 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");
# TODO
}
@ -1537,7 +1593,7 @@ sub doSetUpdate($$$$$) {
sub onmessage($$$) {
my ($hash,$topic,$message) = @_;
CheckInitialization($hash);
Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE DEBUG: onmessage: $topic => $message");
#Log3($hash->{NAME},1,"MQTT_GENERIC_BRIDGE DEBUG: onmessage: $topic => $message");
$hash->{+HELPER}->{+HS_PROP_NAME_INCOMING_CNT}++;
readingsSingleUpdate($hash,"incoming-count",$hash->{+HELPER}->{+HS_PROP_NAME_INCOMING_CNT},1);