2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 06:39:11 +00:00

00_MQTT: topics and payload patch (Forum: #86270)

git-svn-id: https://svn.fhem.de/fhem/trunk@16674 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
eisler 2018-04-29 12:53:05 +00:00
parent f416081f1f
commit bee096a00c
4 changed files with 43 additions and 23 deletions

View File

@ -1,5 +1,6 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it.
- bugfix: 00_MQTT: topics and payload patch
- bugfix: 73_GardenaSmartBridge: fix fetch token after rereadcfg
- feature: 60_allergy: alternative data source for extended 5 day forecast
- new: 74_HusqvarnaAutomower.pm: New module to control your

View File

@ -242,11 +242,12 @@ sub Set($@) {
};
}
sub parseParams($;$$) {
sub parseParams($;$$$$) {
my ( $cmd, $separator, $joiner ) = @_;
my ( $cmd, $separator, $joiner, $keyvalueseparator, $acceptedkeys ) = @_;
$separator = ' ' if ( !$separator );
$joiner = $separator if ( !$joiner ); # needed if separator is a regexp
$keyvalueseparator = ':' if(!$keyvalueseparator);
my ( @a, %h );
my @params;
@ -260,7 +261,7 @@ sub parseParams($;$$) {
while (@params) {
my $param = shift(@params);
next if ( $param eq "" );
my ( $key, $value ) = split( ':', $param, 2 );
my ( $key, $value ) = split( $keyvalueseparator, $param, 2 );
if ( !defined($value) ) {
$value = $key;
@ -272,6 +273,16 @@ sub parseParams($;$$) {
$value = $param;
$key = undef;
}
# the key can not start with a ' or "
elsif ( $key =~ m/^\s*('|")/ ) {
$value = $param;
$key = undef;
}
# accept known keys only (if defined $acceptedkeys)
elsif (defined($acceptedkeys) and !defined($acceptedkeys->{$key})) {
$value = $param;
$key = undef;
}
#collect all parts until the closing ' or "
while ( $param && $value =~ m/^('|")/ && $value !~ m/$1$/ ) {
@ -321,21 +332,15 @@ sub parseParams($;$$) {
sub parsePublishCmdStr($) {
my ($str) = @_;
if(defined($str) && $str=~m/\s*(?:({.*})\s+)?(.*)/) {
my $exp = $1;
my $rest = $2;
if ($rest){
my @lwa = split("[ \t]+",$rest);
unshift (@lwa,$exp) if($exp);
return parsePublishCmd(@lwa);
}
}
return undef;
return undef unless defined($str);
my @lwa = split("[ \t]+",$str);
return parsePublishCmd(@lwa);
}
sub parsePublishCmd(@) {
my @a = @_;
my ( $aa, $bb ) = parseParams(\@a);
my ( $aa, $bb ) = parseParams(\@a,undef,undef,undef,{qos=>1,retain=>1});
my $qos = 0;
my $retain = 0;
@ -356,7 +361,7 @@ sub parsePublishCmd(@) {
while ( scalar(@xaa) > 0 ) {
my $av = shift @xaa;
if ( $av =~ /\{.*\}/ ) {
if (!defined($expression) and $av =~ /^\{.*\}$/ and scalar(@xaa)>0) {
$expression = $av;
next;
}
@ -695,6 +700,7 @@ sub send_message($$$@) {
sub topic_to_regexp($) {
my $t = shift;
$t =~ s|#$|.\*|;
$t =~ s|\$|\\\$|g;
$t =~ s|\/\.\*$|.\*|;
$t =~ s|\/|\\\/|g;
$t =~ s|(\+)([^+]*$)|(+)$2|;
@ -705,6 +711,7 @@ sub topic_to_regexp($) {
sub client_subscribe_topic($$;$$) {
my ($client,$topic,$qos,$retain) = @_;
push @{$client->{subscribe}},$topic unless grep {$_ eq $topic} @{$client->{subscribe}};
$client->{subscribeQos}->{$topic}=$qos;
my $expr = topic_to_regexp($topic);
push @{$client->{subscribeExpr}},$expr unless grep {$_ eq $expr} @{$client->{subscribeExpr}};
if ($main::init_done) {
@ -723,6 +730,7 @@ sub client_subscribe_topic($$;$$) {
sub client_unsubscribe_topic($$) {
my ($client,$topic) = @_;
$client->{subscribe} = [grep { $_ ne $topic } @{$client->{subscribe}}];
delete $client->{subscribeQos}->{$topic};
my $expr = topic_to_regexp($topic);
$client->{subscribeExpr} = [grep { $_ ne $expr} @{$client->{subscribeExpr}}];
if ($main::init_done) {
@ -744,6 +752,7 @@ sub Client_Define($$) {
$client->{".qos"}->{'*'} = 0;
$client->{".retain"}->{'*'} = "0";
$client->{subscribe} = [];
$client->{subscribeQos} = {};
$client->{subscribeExpr} = [];
AssignIoPort($client);
@ -875,13 +884,15 @@ sub client_attr($$$$$) {
sub client_start($) {
my $client = shift;
my $name = $client->{NAME};
if (! (defined AttrVal($name,"stateFormat",undef))) {
$main::attr{$name}{stateFormat} = "transmission-state";
}
CallFn($client->{NAME},"OnClientStartFn",($client));
#my $name = $client->{NAME};
#if (! (defined AttrVal($name,"stateFormat",undef))) {
# $main::attr{$name}{stateFormat} = "transmission-state";
#}
if (@{$client->{subscribe}}) {
my $msgid = send_subscribe($client->{IODev},
topics => [map { [$_ => $client->{".qos"}->{$_} || MQTT_QOS_AT_MOST_ONCE] } @{$client->{subscribe}}],
topics => [map { [$_ => $client->{subscribeQos}->{$_} || MQTT_QOS_AT_MOST_ONCE] } @{$client->{subscribe}}],
);
$client->{message_ids}->{$msgid}++;
readingsSingleUpdate($client,"transmission-state","subscribe sent",1);
@ -892,6 +903,7 @@ sub client_start($) {
sub client_stop($) {
my $client = shift;
if (@{$client->{subscribe}}) {
my $msgid = send_unsubscribe($client->{IODev},
topics => [@{$client->{subscribe}}],
@ -899,6 +911,8 @@ sub client_stop($) {
$client->{message_ids}->{$msgid}++;
readingsSingleUpdate($client,"transmission-state","unsubscribe sent",1);
}
CallFn($client->{NAME},"OnClientStopFn",($client));
};
1;

View File

@ -39,6 +39,8 @@ sub MQTT_BRIDGE_Initialize($) {
my $hash = shift @_;
require "$main::attr{global}{modpath}/FHEM/00_MQTT.pm";
# Consumer
$hash->{DefFn} = "MQTT::Client_Define";
$hash->{UndefFn} = "MQTT::Client_Undefine";

View File

@ -35,6 +35,8 @@ sub MQTT_DEVICE_Initialize($) {
my $hash = shift @_;
require "$main::attr{global}{modpath}/FHEM/00_MQTT.pm";
# Consumer
$hash->{DefFn} = "MQTT::DEVICE::Define";
$hash->{UndefFn} = "MQTT::Client_Undefine";
@ -188,7 +190,7 @@ sub Attr($$$$) {
};
$attribute =~ /^publishSet(_?)(.*)/ and do {
if ($command eq "set") {
my ( $aa, $bb ) = parseParams($value);
my ( $aa, $bb ) = parseParams($value,undef,undef,undef,{});
my @values = @{$aa};
my $topic = pop @values;
$hash->{publishSets}->{$2} = {
@ -306,7 +308,8 @@ sub onmessage($$$) {
<li>
<p><code>attr &lt;name&gt; autoSubscribeReadings &lt;topic&gt;</code><br/>
specify a mqtt-topic pattern with wildcard (e.c. 'myhouse/kitchen/+') and MQTT_DEVICE automagically creates readings based on the wildcard-match<br/>
e.g a message received with topic 'myhouse/kitchen/temperature' would create and update a reading 'temperature'</p>
e.g a message received with topic 'myhouse/kitchen/temperature' would create and update a reading 'temperature'.<br/>
Please note that topics with spaces will not work here!</p>
</li>
<li>
<p><code>attr &lt;name&gt; subscribeReading_&lt;reading&gt; [{Perl-expression}] [qos:?] [retain:?] &lt;topic&gt;</code><br/>