Forwarding with MQTT Warn

MQTT Jan 1, 2020

In my environment i will use mosquitto. This is excelent as messaging system to receive and also devlier messages. But this comes up with a disadvantage. It cannot forward messages.

So bad, because I have exactly this problem for now

Mqttwarn for the rescue

mqttwarn (opens new window)is an open source tool that can accomplish this task.

In the diagram you will notice that you can forward one message to multiple receivers / subscribers. We are not limited to a messagebus system, we can deliver to twitter or an fileshare or create an e-mail or... for a full list see here (opens new window).

I decided to try it out for solve my problem.

Installation

So I will try to fokus only on the configuration aspects of mqttwarn. So I decided to creat a docker image for this.

docker run -d -e "MQTTWARNINI=/opt/mqttwarn/conf/mqttwarn.ini" -e "MQTTWARNLOG=/opt/mqttwarn/conf/mqttwarn.log" -v /docker/mqttwarn/conf:/opt/mqttwarn/conf beejay/mqttwarn:latest

After runnign it successfully, it will statrup a container instance. Now we can do the main part... the configuration.

Configuration

First of all there is a general Config to configure the connection to the source.

[defaults]
;the mqtt service to connect (DNSNAME)
hostname     = 'mosquitto'
;the port to use
port         = 1886
;sets the client identifiert
clientid     = 'mqttwarn'
;the username
username     = 'myusert'
;the pasword to use
password     = 'supersecretpassword'
;set the loglevel to verbose
loglevel     = DEBUG
;skip retained messages
skipretained = True
;run wit a clean session id, it will reconnect every time
cleansession = True
;use procotolverion 3
protocol = 3

In this you will define the server to connect on, which user and password it will use. Also which protocol version. There are many more configurations but this is the basic example.

As next step, we will define the target(s).

First of all I will add a debug entry into the default mqttwarn log.

With this base 
; This is a log config
[config:log]
targets = {
    'debug'  : [ 'debug' ],
  }

Not the [config:log] entry at the top. This define the name for the target definition. With debug as target (more later).

My second receiver will be my iobroker instance. This contains an own mqtt server on which I can act with javascript to forward it into my automation server.

[config:mqtt]
; Use the target hostname ()
hostname =  'iobroker'
port =  1886
qos =  0
targets = {
  'hive-teststand'    : [ 'hive/dev-device' ],
  }

In this I will define the connection to the target server iobroker then I will define the connection port of the target server.

You will now notice the target parts. This part is essential fpr addressing the ...yeah... targets. So hive-teststand is an alias for the target hive/dev-device on the target mqtt instance (iobroker).

So now the essential part:


[hive-teststand]
topic = homie/hive-teststand/data/__json__
targets = mqtt:hive-teststand, log:debug

This will define the following:

The configuration hive-teststand will listen to all messages on the topic homie/hive-teststand/data/__json__ and will it redirect to the log:debug and the mqtt:hive-teststand. But why this syntax?

Important! When you not define the topic, it will use the name in [] as topic name. This name must also be unique!

It's very easy, because you can have multiple mqtt targets. So then you cannot address mqtt alone. The targets will be the point. It will define the real target machine and the target topic then.

Example with more than one mqtt receivert

Let's assume you have two mqtt instances configured as follow:


[config:mqtt]
; Use the target hostname ()
hostname =  'iobroker'
port =  1886
qos =  0
targets = {
  'Destination1'    : [ 'hive/debugdata' ],
  }


[config:mqtt]
; Use the target hostname ()
hostname =  'caymanisland'
port =  1886
qos =  0
targets = {
  'destination2'    : [ 'hive/supersecret' ],
  }

Now you will redirect the messages into both targets. This can now done with this snipplet:

[hive-teststand]
topic = homie/hive-teststand/data/__json__
targets = mqtt:destination1,mqtt:destination2, log:debug

With this you will define, that the message will be logged out. Also it will forward the message to the first mqtt instance to topic hive/debugdata and also to hive/supersecret on the other mqtt instance.

What about reformat?

In some cases the format of the messages won't apply to the targets format. So in this case mqttwarn comes up with an handy format feature.

Let's take the example with the two target from above.

Let's assume the input message will be the following:

{"city":"Herne", "temperature": 14.3, "tst" : "1391779336"}

Then let's assume that the second mqtt server requies only a text input instead of a json input like this.

Temperature in Herne is 14.3 °C

Now you can define two rules the first will only forward the message as it is.

[hive-teststand]
topic = homie/hive-teststand/data/__json__
targets = mqtt:destination1, log:debug

The second one does a reformat

[hive-teststand]
topic = homie/hive-teststand/data/__json__
targets =mqtt:destination2
format =  u'Temperature in {city} is {temperature} °C'

Get it to work

Before we can start mqttwarn, we must tell it, that the services must be executed. This can be done with the following line of config:

;for every message run the following subjects
launch = mqtt,log

This will tell mqttwarn, that every message will run throughout the mqtt and log action (defined above).

Tags