MQTT THING transformation - Convert strings to a SWITCH or NUMBER type

Hi, I have a MQTT broker set up in different machine on my network than the one running OpenHAB. I have OpenHAB to communicating to said broker and have been able to define THINGS for the parameters/fields I want to use. There is one particular field that comes in JSON format, and it is a pump speed. The speed is stored as OFF, LOW or HIGH.

{"Time":"23.12.2022, 09:53:39","Pump 1":"OFF","Pump 2":"OFF","Circulating Pump":"ON"}

I can map an ITEM to it and get a STRING type to get the state of the pump speed, no issues there. But I will like have either a SWITCH type of ITEM (ON or OFF that is), or in a best case, a NUMBER type of item where 0=OFF, 1=LOW and 2=HIGH.

In trying to get the ITEMS as a SWITCH OpenHAB interprets the OFF value with no issues, and it always interprets the LOW value as ON sets the switch to ON (so far so good!), but it does not recognizes the HIGH value and it throws an error complaining that HIGH is not defined as in the SWITCH library.

I tried to define the state as: on=“HI”, on=“LOW”, off=“OFF” on the THING configuration after the transformationPattern, but again, it recognizes OFF and LOW, but it complains about HIGH.

I even tried to use the MAP transformation after ingesting the JSON data on the THING config, but that was not successful.

At this point, I am not certain if what I want to do is possible, but I figured I could ask for help. If I could transform the data into a SWITCH type as it comes in, that would be good… it would be best if I could convert it into a NUMBER (e.g 1, 2 3 3 per my comment above) so that I can graph it over time on my INFLUX/GRAFANA stack and get a meaningful trending (graphing strings is not as intuitive)

Here is my THING set up:

Type string : pumps_pump1  "Pump 1"  [stateTopic="spa/pumps/state", transformationPattern="JSONPATH:$.['Pump 1']" ]
Type string : pumps_pump2  "Pump 2"  [stateTopic="spa/pumps/state", transformationPattern="JSONPATH:$.['Pump 2']" ]

Here in my ITEM set up:

String  HotTub_Pump_State_1   "Hot Tub Pump #1"   (HotTub_Pumps)      { channel="mqtt:topic:hottub:pumps_pump1" }
String  HotTub_Pump_State_2   "Hot Tub Pump #2"   (HotTub_Pumps)      { channel="mqtt:topic:hottub:pumps_pump2" }

Thanks in advance for any help that can be provided.

I would:

  • Keep your Channels as Strings
  • Modify your Channels to chain a MAP transformation after the JSONPATH transformation.
  • In this MAP you convert your strings to numbers.
  • Modify your Items to Numbers

I think that should do it?

Looks like I’ve previously solved this using a JS Transformation - see the first two posts in this thread.. And both the Channels and Items are numbers. Interesting!

1 Like

Thanks for the quick reply, after seeing your referenced post and suggestions I got very excited and thought that could get this to work… unfortunately its not. I see the difference in your approach and is to keep the channel as a STRING but let the item be a NUMBER (I was making both NUMBERS before)… but now, I don’t get any errors on OH, but the item never gets updated upon broker changes/calls.

Here is how I redefined the thing:

Type string : pumps_pump_test                 "Pump Test"                  [stateTopic="spa/pumps/state", transformationPatternOut="JSONPATH:$.['Pump 1']nMAP:test1.map" ]

Here the item:

Number              HotTub_Pump_Test               "Hot Tub Pump Test"                      (HotTub_Pumps)      { channel="mqtt:topic:hottub:pumps_pump_test" }

And the map file (which is in the transform folder):

OFF=0
LOW=1
HIGH=2

I think I did it correctly, but as I said the item HotTub_Pump_Test is not getting anything… any ideas what might be going on here? maybe an error on my syntax?

Thanks!

You have not used the correct character to chain transformations - you will probably see an error in the logs.

Transformations can be chained by separating them with the mathematical intersection character “∩”

Well… I feel really silly… I read all the docs multiple times and my brain did register the fact that the mathematical intersection character was the one to be used… but I guess my sub-conscience and fingers thought otherwise.

I am happy to say that now everything works like a charm!!! Many thanks in helping me with this.

While we are on the topic if MQTT channels and transformation, on the same broker I have quite a peculiar case. I have a few channels that reads the reminder in days on when a filter needs to be cleaned. The JSON payload shows as:

{"Time":"23.12.2022, 17:53:29","RinseFilter":"-45","CleanFilter":"-15","ChangeWater":"15","CheckSpa":"655"}

I have channels and items created to get the number into OpenHAB and it works like a charm. The issue I have is that when the broker starts up for the first time, the first JSON payload it writes is:

{"Time":"19.12.2022, 14:19:10","Filter Status:Clean":false,"Filter Status:Purge":false}

As you can see, this first set of data does not include the “RinseFilter”, “CleanFIlter”, “ChangeWater” and “CheckSpa” parameters and thus OpenHAB throws this error:

14:19:10.694 [WARN ] [tt.generic.ChannelStateTransformation] - Executing the JSONPATH-transformation failed: Invalid path '$.CleanFilter' in '{"Time":"19.12.2022, 14:19:10","Filter Status:Clean":false,"Filter Status:Purge":false}'
14:19:10.694 [WARN ] [tt.generic.ChannelStateTransformation] - Executing the JSONPATH-transformation failed: Invalid path '$.ChangeWater' in '{"Time":"19.12.2022, 14:19:10","Filter Status:Clean":false,"Filter Status:Purge":false}'
14:19:10.694 [WARN ] [tt.generic.ChannelStateTransformation] - Executing the JSONPATH-transformation failed: Invalid path '$.RinseFilter' in '{"Time":"19.12.2022, 14:19:10","Filter Status:Clean":false,"Filter Status:Purge":false}'
14:19:10.706 [WARN ] [tt.generic.ChannelStateTransformation] - Executing the JSONPATH-transformation failed: Invalid path '$.CheckSpa' in '{"Time":"19.12.2022, 14:19:10","Filter Status:Clean":false,"Filter Status:Purge":false}'

After a minute or two, the MQTT Broker sends the correct payload with the proper keys, and all the items in OH are updated with no issues, therefore life is good… but… I will like to get rid of this error.

So, is there a way to define the channel or data transformation such that if the JSON keys that are predefined on the channel are not present, error is not shown and simply the item doesn’t update until the correct payload shows up a few minutes later?

I have searched the forum and googled but have not found a tread that shed some light on how to deal with this, and I can’t think of a way to to incorporate a logical decision on the transformation parameter when the data is ingested by MQTT.

Here is how I have those channels set up:

Type number : reminders_rinse_filter          "Reminder Rinse Filter"      [stateTopic="spa/reminders/state", unit="day", transformationPattern="JSONPATH:$.RinseFilter" ]
Type number : reminders_clean_filter          "Reminder Clean Filter"      [stateTopic="spa/reminders/state", unit="day", transformationPattern="JSONPATH:$.CleanFilter" ]
Type number : reminders_change_water          "Reminder Change Water"      [stateTopic="spa/reminders/state", unit="day", transformationPattern="JSONPATH:$.ChangeWater" ]
Type number : reminders_check_spa             "Reminder Check Spa"         [stateTopic="spa/reminders/state", unit="day", transformationPattern="JSONPATH:$.CheckSpa" ]

Items:

Number:Time         HotTub_Reminders_Rinse_Filter  "Hot Tub Reminder: Rinse Filter"         (HotTub_Reminders)  { channel="mqtt:topic:hottub:reminders_rinse_filter" }
Number:Time         HotTub_Reminders_Clean_Filter  "Hot Tub Reminder: Clean Filter"         (HotTub_Reminders)  { channel="mqtt:topic:hottub:reminders_clean_filter" }
Number:Time         HotTub_Reminders_Change_Water  "Hot Tub Reminder: Change Water"         (HotTub_Reminders)  { channel="mqtt:topic:hottub:reminders_change_water" }
Number:Time         HotTub_Reminders_Check_Spa     "Hot Tub Reminder: Check Spa"            (HotTub_Reminders)  { channel="mqtt:topic:hottub:reminders_check_spa" }

Thanks again for all the help provided!

It’s only a warning, not an error. I ignore these.

If you still care, use REGEX filters!

Owww! thanks again, reading the referenced post and applying the REGEX has gotten rid of the warnings (by filtering on the key what the channel is scoped to), I am going to have to wait a day for the device to send an actual update on the value to the broker and then see that OH accepts the filter, and then the item gets updated… but I am optimistic, don’t see why it wouldn’t work.

For sake of completeness, here is the REGEX on the channels:


 Type number : reminders_rinse_filter          "Reminder Rinse Filter"      [stateTopic="spa/reminders/state", unit="day", transformationPattern="REGEX:(.*RinseFilter.*)∩JSONPATH:$.RinseFilter" ]
 Type number : reminders_clean_filter          "Reminder Clean Filter"      [stateTopic="spa/reminders/state", unit="day", transformationPattern="REGEX:(.*CleanFilter.*)∩JSONPATH:$.CleanFilter" ]
 Type number : reminders_change_water          "Reminder Change Water"      [stateTopic="spa/reminders/state", unit="day", transformationPattern="REGEX:(.*ChangeWater.*)∩JSONPATH:$.ChangeWater" ]
 Type number : reminders_check_spa             "Reminder Check Spa"         [stateTopic="spa/reminders/state", unit="day", transformationPattern="REGEX:(.*CheckSpa.*)∩JSONPATH:$.CheckSpa" ]
1 Like

And Yup… today the device sent an update thru the defined reminder channel, which met the filter criteria defined by the REGEX and it passed on!

Thanks for all the help.

Case closed.

1 Like