############################################## # # fhem bridge to mqtt (see http://mqtt.org) # # Copyright (C) 2014 Norbert Truchsess # # This file is part of fhem. # # Fhem is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # Fhem is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with fhem. If not, see . # # $Id$ # ############################################## use strict; use warnings; my %sets = ( ); my %gets = ( "version" => "", ); sub MQTT_DEVICE_Initialize($) { my $hash = shift @_; # Consumer $hash->{DefFn} = "MQTT::Client_Define"; $hash->{UndefFn} = "MQTT::Client_Undefine"; $hash->{SetFn} = "MQTT::DEVICE::Set"; $hash->{AttrFn} = "MQTT::DEVICE::Attr"; $hash->{AttrList} = "IODev ". "qos:".join(",",keys %MQTT::qos)." ". "publishSet ". "publishSet_.* ". "subscribeReading_.* ". $main::readingFnAttributes; main::LoadModule("MQTT"); } package MQTT::DEVICE; use strict; use warnings; use GPUtils qw(:all); use Net::MQTT::Constants; BEGIN { MQTT->import(qw(:all)); GP_Import(qw( readingsSingleUpdate Log3 )) }; sub Set($@) { my ($hash, @a) = @_; return "Need at least one parameters" if(@a < 2); return "Unknown argument $a[1], choose one of " . join(" ", map {$sets{$_} eq "" ? $_ : "$_:$sets{$_}"} sort keys %sets) if(!defined($sets{$a[1]})); my $command = $a[1]; my $value = $a[2]; if (defined $value) { send_publish($hash->{IODev}, topic => $hash->{publishSets}->{$command}->{topic}, message => $value, qos => $hash->{qos}); readingsSingleUpdate($hash,$command,$value,1); } else { send_publish($hash->{IODev}, topic => $hash->{publishSets}->{""}->{topic}, message => $command, qos => $hash->{qos}); readingsSingleUpdate($hash,"state",$command,1); } return undef; } sub Attr($$$$) { my ($command,$name,$attribute,$value) = @_; my $hash = $main::defs{$name}; ATTRIBUTE_HANDLER: { $attribute =~ /^subscribeReading_(.+)/ and do { if ($command eq "set") { $hash->{subscribeReadings}->{$value} = $1; push @{$hash->{subscribe}},$value unless grep {$_ eq $value} @{$hash->{subscribe}}; if ($main::init_done) { if (my $mqtt = $hash->{IODev}) {; my $msgid = send_subscribe($mqtt, topics => [[$value => $hash->{qos} || MQTT_QOS_AT_MOST_ONCE]], ); $hash->{message_ids}->{$msgid}++; readingsSingleUpdate($hash,"transmission-state","subscribe sent",1) } } } else { foreach my $topic (keys %{$hash->{subscribeReadings}}) { if ($hash->{subscribeReadings}->{$topic} eq $1) { $hash->{subscribe} = [grep { $_ != $topic } @{$hash->{subscribe}}]; delete $hash->{subscribeReadings}->{$topic}; if ($main::init_done) { if (my $mqtt = $hash->{IODev}) {; my $msgid = send_unsubscribe($mqtt, topics => [$topic], ); $hash->{message_ids}->{$msgid}++; } } last; } } } last; }; $attribute =~ /^publishSet(_?)(.*)/ and do { if ($command eq "set") { my @values = split ("[ \t]+",$value); my $topic = pop @values; $hash->{publishSets}->{$2} = { 'values' => \@values, topic => $topic, }; if ($2 eq "") { foreach my $set (@values) { $sets{$set}=""; } } else { $sets{$2}=join(",",@values); } } else { if ($2 eq "") { foreach my $set (@{$hash->{publishSets}->{$2}->{'values'}}) { delete $sets{$set}; } } else { delete $sets{$2}; } delete $hash->{publishSets}->{$2}; } last; }; client_attr($hash,$command,$name,$attribute,$value); } } sub onmessage($$$) { my ($hash,$topic,$message) = @_; if (defined (my $reading = $hash->{subscribeReadings}->{$topic})) { Log3($hash->{NAME},5,"calling readingsSingleUpdate($hash->{NAME},$reading,$message,1"); readingsSingleUpdate($hash,$reading,$message,1); } } 1; =pod =begin html

MQTT


=end html =cut