[SOLVED] MQTT value conversions within channel (REGEX)

Hello OpenHAB enthousiasts,

I’m struggling for some time now understanding how to be able to transform values retrieved from a mqtt topic to usefull measurement values. For instance: i have bought a WifiLogger for use in my Davis VantagePRO2 weatherstation. I get the MQTT messages in, and am able to get the values i want. But; as the WifiLogger is only able to present temperature values in Fahrenheit i want to convert these values to read as Celsius. S far i get the value like this:

Thing mqtt:topic:mosquitto:davis "Davis VantagePro2" (mqtt:broker:mosquitto) {
    Channels:
        Type number : insidetemp       "Binnentemperatuur"    [ stateTopic="/davis/wflexp.json", transformationPattern="JSONPATH:$.tempin" ]
}

in my items file i have the following item:

Number:Temperature InsideTemp       "Binnentemperatuur [%.1f °C]"     <temperature>     (gTemperatuur,gDavisTemperature)      { channel="mqtt:topic:mosquitto:davis:insidetemp" }

So my item reads 71.4 °C instead of 21.9 °C.

I really hope someone can explain how to explicit tell openhab the value it receives from the mqtt tansform is in fahrenheit so afterwards it is converted automatically,

When MQTT feeds the value to the Number:Temperature Item, you would need a means to tell OH your value is in °F, as opposed to °C or K etc.
Basically your transformation needs to add °F on the end of the numeric value, but a JSONPATH cannot do that on its own I think?

A chained transform should do - a REGEX perhaps, adding °F or | °F to the string?

Do you happen to have some sample code how to do that?

If you change Number: Temperature to just Number, dropping the UOM, will it work as needed?

If not try a forum search on “formatBeforePublish” and see if that could work for what you need.

store the outcome of the json transformation in a (proxy) item, beware it is a string:

String insidetemp_mqttstring "Binnentemperatuur [%s]" { channel="mqtt:topic:mosquitto:davis:insidetemp" }

You can check this string in a sitemap. It should show your value in Fahrenheit.

Prepare a number item to store the outcome after the following transformation by rule below:

Number InsideTemp "Binnentemperatuur [%.1f °C]"  <temperature> (gTemperatuur, gDavisTemperature)

Then set up a rule to

  1. convert this string into a number
  2. convert to degree celsius and store in a number item.

(Why not using UoM: i didn’t get it up running. It would be cool, because it would save you the conversations formula. But… )

rule "Convert MQTT Temperature String to Number and convert unit"
when
    Item insidetemp_mqttstring received update
then    
    var Number temp = Integer::parseInt(insidetemp_mqttstring.state.toString)
    InsideTemp.postUpdate((temp - 32) * 5/9)     // Please check formula and syntax, i did not checked it!
end

Hope it works!

(Perhaps someone can show us, how to use this UoM system. )

tnx Richard, but i don’t want to use rules and extra items to achieve this. I have a lot of values which need conversion for this MQTT topic (mph to km/h. Fahrenheit to Celcius, inch to hPa) so i want to use the UoM system as that’s where it’s designed for. I just need a way to be able to tell openhab what the QuantityType of a received value is… Basically; all values received from my davis channel are imperial values; i need metric values

i’m also not happy about these rules and also have many sensors.
Somewhere i read:

“do not use js transformation - they are consuming cpu time”
“in mqtt 2.5 there will be a transformation …”
“use channel binding and profiles … it is so easy”
“use node-red”
and so on.

I use some of my rules also for publishing values to other bus system (e.g KNX). So i have full controll and can use numbers in rules … for making my home … smart. :slight_smile:

It is a common task: read in MQTT messages and convert it universally …

Guys,

I maybe have another option: the wifilogger sends a textfile every 10 seconds beside the json output. This is the format/content:

04/04/19 12:18:40 8.0 74 3.6 1.3 1.6 162 0.00 0.00 1000.3 SSE 1 km/h C mb mm — --- 0.20 167.00 — 23.9 40 7.8 — 8.3 12:09 2.4 5:18 9.7 11:15 9.7 11:15 1000.6 0:12 998.3 5:31 2.16 2.16 4.8 7.8 — 0.9 0.01 278 — 0.00 0 0 0 0 0 0 0 0 0 0

The good news; all values are metric, so i can use them without conversion. But now i need to get the correct value from this string for each channel i configured. For instance, the 3th value is outside temperature. So how can i get this value through transformationPattern? JS is an option but, as many clearly mentioned, these consume a lot of resources. Any better ideas?

you can use “REGEX” transformation.

First step, always, try to put this information into a string item and see, if openHAB can read this string.
Post your steps … and hope some specialist visit this thread here … :slight_smile:

string is coming in ok, as seen in the log:

2019-04-04 15:02:07.853 [WARN ] [eneric.internal.generic.ChannelState] - Incoming payload '04/04/19 15:02:10 9.2 70 4.0 1.6 1.6 96 0.00 0.00 1000.5 E 1 km/h C mb mm — --- 0.20 167.00 — 24.1 39 8.9 — 9.3 13:07 2.4 5:18 12.9 14:54 12.9 14:54 1000.8 14:25 998.3 5:31 2.16 2.16 12.9 9.4 — 1.6 0.03 543 — 0.00 0 0 0 0 0 0 0 0 0 0 ’ not supported by type ‘NumberValue’

I changed the channel to:

Type number : insidetemp       "Binnentemperatuur"    [ stateTopic="/davis/realtime.txt", transformationPattern="REGEX:(?:[^ ]*\\ ){2}([^ ]*)" ]

This should retrun the 3rd value as tested on https://regex101.com/r/4acpDD/1

Anyone sees what’s the problem?

Solved it. for the REGEX transformation to work the complete payload must be matched by the regex. So the channel looks like this now:

Type number : insidetemp       "Binnentemperatuur"    [ stateTopic="/davis/realtime.txt", transformationPattern="REGEX:(?:[^ ]*\\ ){22}([^ ]*).*" ]

Now i have the correct values for all measurements.