Transformations of MQTT messages

(Kvoit) #1

Hi, from a door contact, I get MQTT messages of the form
{"contact":true,"linkquality":55,"battery":100,"voltage":3125}

I want to save the contact status and the battery status. For the contact, I would have to extract the contact field and translate the boolean value to OpenClosed.

  1. Is this possible inside the item definition, or do I have to define a raw string item and parse it in a rule?
  2. If it is possible in an item definition, is there any issue receiving the same mqtt message in multiple items?

Thanks in advance!

0 Likes

(Vincent Regaud) #2

Yes it is. You can do both

Not a problem
You just need to install the JSONPATH transformation service in the PaperUI
For example:

String Contact { mqtt="<[broker:topic:state:*:JSONPATH($.contact)]" }
Number Voltage { mqtt="<[broker:topic:state:*:JSONPATH($.voltage)]" }
1 Like

(Thomas Bail) #3

Withe trhe new mqtt Binding it is possible as well. One benefit i see is that the new binding is able to establish a contact channel.

0 Likes

(Angelos) #4

by the way, can someone check if you can apply transformations directly on the channel links of MQTTv2? (I haven’t installed it yet)

0 Likes

(Kvoit) #5

Thanks, but this does only half of what I wanted. There is a dedicated item type for theses switches, Contact.
For that, I have to translate true/false to on/off. How do I combine that with JSONPATH?

discusses combining transformations, but the solution would only have an advantage to writing a rule if I could manage to not hardcode the JSON fieldname …

0 Likes

(Angelos) #6

I don’t see how you can avoid hardcoding this…

see another example of js transformation here:

0 Likes

(Vincent Regaud) #7

Your problem here is that the json.contact returns true or false
openHAB needs OPEN or CLOSED for a contact item.
Unfortunately, you can’t “nest” transformation services. So you will need a transformation that does it all.

Install the javascript transform
Create a file called “doorcontact.js” in the tranform folder with the folowing contents:

(function(jsonString) {
var data = JSON.parse(jsonString);
var doorState = data.contact;
if (doorState.contact) {
    doorState = 'OPEN';
} else {
    doorState = 'CLOSED';
return doorState;
})(input)

Invert the OPEN and CLOSED in case true is CLOSED. I don’t know…

Your item is then:

String Contact { mqtt="<[broker:topic:state:*:JS(doorcontact.js)]" }
0 Likes

(Kvoit) #8

Thanks, I have by now implemented almost exactly that. Where does the “title” part come from? For me, it seems to work without it.

0 Likes

(Vincent Regaud) #9

Soory, that’s a remnant from old code
I have corrected above

0 Likes

(Koenraad Lelong) #10

Hi,
Maybe late, but I’m struggling with a similar problem.
I have a Tasmota-device which I configured to send a JSON (?) string when activated : {“contact”:“1”} or {“contact”:“0”}. I want to modify that 1 or 0 to Closed or Open.
When I configure the item as a string :

String myWemos02 "Wemos02 [%s]" {mqtt="<[mosq:stat/wemos01/SWITCH1:state:default]"}

I can see the contact changing in HabPanel, the whole JSONPATH-string.
With JSONPATH I can send the state (0 or 1) to the item in HabPanel. I have to use a modified version of your config :

String myWemos02 "Wemos02 [%s]" {mqtt="<[mosq:stat/wemos01 SWITCH1:state:JSONPATH($.contact)]"}

See the missing *:. If I add those I get an error.
Now the third step : use javascript to do the modification :

String myWemos02 "Wemos02 [%s]" {mqtt="<[mosq:stat/wemos01/SWITCH1:state:JS(switchcontact.js)]"}

switchcontact.js is this :

(function(jsonString) {
var data = JSON.parse(jsonString);
var contactState = data.contact;

if (contactState == 0) {
    contactState = 'OPEN';
} else {
    contactState = 'CLOSED';
return contactState;
})(input)

I tried this in an online javascript tester and it’s fine. Unfortunately, Openhab2 gives an error :

2019-04-11 19:28:05.463 [WARN ] [.mqtt.internal.MqttMessageSubscriber] - Error processing MQTT message.
org.openhab.core.transform.TransformationException: An error occurred while executing script.
        at org.openhab.core.transform.TransformationHelper$TransformationServiceDelegate.transform(TransformationHelper.java:67) ~[201:org.openhab.core.compat1x:2.4.0]
        at org.openhab.binding.mqtt.internal.MqttMessageSubscriber.processMessage(MqttMessageSubscriber.java:133) [239:org.openhab.binding.mqtt:1.13.0]
        at org.openhab.io.transport.mqtt.internal.MqttBrokerConnection.messageArrived(MqttBrokerConnection.java:570) [240:org.openhab.io.transport.mqtt:1.13.0]
        at org.eclipse.paho.client.mqttv3.internal.CommsCallback.deliverMessage(CommsCallback.java:475) [240:org.openhab.io.transport.mqtt:1.13.0]
        at org.eclipse.paho.client.mqttv3.internal.CommsCallback.handleMessage(CommsCallback.java:379) [240:org.openhab.io.transport.mqtt:1.13.0]
        at org.eclipse.paho.client.mqttv3.internal.CommsCallback.run(CommsCallback.java:183) [240:org.openhab.io.transport.mqtt:1.13.0]
        at java.lang.Thread.run(Thread.java:748) [?:?]

I even tried the simplest function :

(function(i) {
 return "TEST";
}(input)

Gives the same error.
I don’t know what to try next. Any help ?
I’m running Openhab2.40. Javascript transformation is installed.

0 Likes

(Koenraad Lelong) #11

Hi,
I found a solution.
I modified the tasmota MQTT-message to send only 0 or 1. Now with a MAP I have the desired result.
But I would like to know what’s going wrong with the javascript.

0 Likes