OH3 transformation service config for JS and MAP in a Thing Channel: what worked, Qs about what didn't

It took me a long time to find, so I’m sharing what is working in OH3 for channel incoming transforms. I also have some questions/feedback about what didn’t work.

Background

I’m parsing a value from MQTT from my OpenEVSE charger, that comes in like “2”, “5”, etc. I want to map it to a human-readable string like “not connected”, “charging”, etc.

I have OpenHab 3.4.2-1 installed from the stable apt channel, running on Ubuntu, with a local Mosquitto as my MQTT broker.

What Worked

On my server, I have two files:

/etc/openhab/transform/openevse_parse_state.js

(function(data) {
  var lookup = {
    '0':'unknown',
    '1':'not connected',
    '2':'connected',
    '3':'charging',
    '4':'vent required',
    '5':'diode check failed',
    '6':'gfci fault',
    '7':'no ground',
    '8':'stuck relay',
    '9':'gfci self-test failure',
    '10':'over temperature',
    '254':'sleeping','255':'disabled'
  };
  var converted = lookup[data];
  if (converted == undefined) {
    return 'unknown_' + data;
  }
  return converted;
})(input)

and /etc/openhab/transform/openevse_state.map

0=unknown
1=not connected
2=connected
3=charging
4=vent required
5=diode check failed
6=gfci fault
7=no ground
8=stuck relay
9=gfci self-test failure
10=over temperature
254=sleeping
255=disabled
=_source_

(OH3 seems to pick up changes to these files without a restart.)

I added two add-ons via the UI: Settings > Other Add-ons > Transformation Add-ons > Javascript and Map.

Finally, when I set up a Thing for my OpenEVSE through the UI. Settings > Things > (created the new Thing) > Channels. Either of these two values worked for the “Incoming Value Transformations”:

JS:openevse_parse_state.js
or
MAP:openevse_state.map

In the “Code” view, the Thing with the state channel looks like:

UID: mqtt:topic:d432b36bc2:b1f8c9243a
label: OpenEVSE MQTT Thing
thingTypeUID: mqtt:topic
configuration: {}
bridgeUID: mqtt:broker:d432b36bc2
channels:
  - id: openevse_state
    channelTypeUID: mqtt:string
    label: OpenEVSE State
    description: ""
    configuration:
      stateTopic: openevse/state
      transformationPattern: JS:openevse_parse_state.js

Issues and Questions

The Javascript transformation addon docs say to use JS(transformation/myscript.js). But that doesn’t work for me: it has a transformation/ directory prefix that doesn’t seem necessary, and it has a JS( instead of JS:. I saw that in a lot of examples. Also, its “Edit this page on GitHub” link goes to this broken URL.

A lot of documentation also referenced a :%s at the end of the transform, which didn’t work for me.

Many docs like the OpenHAB Transformations docs and posts show a different language for Thing code than what I see in he UI. Is that old/deprecated? Is there another place where the declarations look like Type switch : relay [ stateTopic="shellies/shelly1-############/relay/0", ... ] ? I didn’t see many examples of the YAML code.

The Map Transform addon page didn’t have an example of an input transform, I sent PR #14659.

I set some initial addons in addons.cfg. Then I installed MAP and JS transforms, and at some point later went back and discovered they had been uninstalled. (Not sure if that was because I cleared cache.) At the top of that file it says “This is only regarded at the VERY FIRST START of openHAB”, but after listing javascript,map in there, they didn’t get uninstalled again over some service restarts.

I spent a good few hours puzzling over error messages like Transformation service JS(OPENEVSE_PARSE_STATE.JS) for pattern %s not found!. If there’s a way to debug whether a transform service is installed, and whether a given file is found by the service, that would be great to add to docs about debugging steps somewhere, maybe the Transformations docs.

I also initially found my way to instructions putting files in scripts/ or having a .script extension, from the Transformations doc page; I’m not sure yet what the distinction is between a script transform and the MAP/JS input transforms I was using.

Still, I’m enjoying getting started with OpenHAB!

1 Like

…yes, for an inline script (which is the name of the heading in the documentation). You are applying the transformation into a Thing Channel, which is not an inline script.

Link?

It is the syntax used when creating Things via configuration files, not the UI.

It’s quite easy to get confused when starting out due to the plethora of options available to do the same thing! Welcome to openHAB!

Verify that as there is a known issue right now where OH does not. Though that may only be a problem with new files, not updates to existing files.

The docs were incorrect. But the edit in github link is broken because in OH 4, there is no JS transformation any more. It’s been replaced with the SCRIPT transformation and now supports any installed rules language, not just Nashorn JS.

And the JS( issue has to do with context. Some bindings including MQTT have a slightly different syntax because it was needed in order to support chaining transformations. When a binding deviates from the standard they should document that in their own documentation. You can find MQTT’s here: MQTT Things and Channels - Bindings | openHAB.

There are lots of different places a transformation can be invoked: Thing Channel configs, the transform Profile, Item labels, Sitemap labels, Item State Description Pattern metadata, and in rules. In a few cases, there is also a distinction between a file and inline transformation syntax too, as @hafniumzinc points out.

The :%s applies when using a transformation in Item labels, Sitemap labels, and Item State Description Patterns so be careful to know the context when you see an example and docs. And do please point out situations where the docs are ambiguous or unclear what context they are talking about.

Do not mix addons.cfg and installing add-ons through the UI. Use one or the other, never both. I’m not certain that comment at the top of the file is still valid but either way, when ever the addons.cfg file is loaded, it’s going to make OH’s installed add-ons exactly match that file, installing any that are missing and uninstalling any that are not listed.

I thought this was in OH 3 but maybe it’s only new in OH 4. If you try to use a transform that isn’t installed you get an error in the logs.

That too generates a specific error in the logs.

Though I will admit in neither case does it tell you where the error is coming from, as in which Channel of which Thing. That could definitely be improved. Things are getting better but there is a ways to go still.

SCRIPT replaces the JS transformation in OH 4.0+. MAP is a separate unrelated transformation.

openhab> bundle:list | grep sforma
183 x Active x  80 x 3.4.0.202212131824     x openHAB Core :: Bundles :: Transformation REST Interface
214 x Active x  80 x 3.4.0.202212131822     x openHAB Core :: Bundles :: Transformation Service
301 x Active x  75 x 3.4.0.202212140415     x openHAB Add-ons :: Bundles :: Transformation Service :: JavaScript
302 x Active x  75 x 3.4.0.202212140352     x openHAB Add-ons :: Bundles :: Transformation Service :: Jinja
303 x Active x  75 x 3.4.0.202212140415     x openHAB Add-ons :: Bundles :: Transformation Service :: JSonPath
304 x Active x  75 x 3.4.0.202212140415     x openHAB Add-ons :: Bundles :: Transformation Service :: RegEx
305 x Active x  75 x 3.4.0.202212140415     x openHAB Add-ons :: Bundles :: Transformation Service :: Scale
306 x Active x  75 x 3.4.0.202212140415     x openHAB Add-ons :: Bundles :: Transformation Service :: XPath

Lots to digest, thanks everyone!

New users can only include 2 links in their first post, unfortunately I had to drop some links.

%s at the end of the transform

The Configuration > Transformations docs mention this. I see now that that’s contextualized as apllying to labels as rlkoshak describes (thanks!):

The following example shows a Map transformation (see below) used in the State part of an Item’s label

Number  Livingroom_Temperature_F "Temperature [JS(convert-C-to-F.js):%s °F]"   {/*Some Binding*/}

Things via configuration files, not the UI.

Ah, it definitely confused me that I see a different format (YAML) when I go to the “Code” tab in the UI for a thing, as opposed to those examples. I am excited about using the file-based configuration for OpenHAB (that’s part of why I decided to come try OpenHAB after initially checking out HomeAssistant).

Is there a way to see the Java style Thing configuration code for Things I’ve created in the UI? I see in the Thing docs a strong warning that UI-based Things don’t have associated files, so maybe no. But the examples in those docs look pretty clear, so I can probably rebuild my Things if I want.

I’m not certain that comment at the top of the file is still valid

It’s a very clear/visible place to describe the behavior; I filed a ticket to ask if someone could clarify it. But thanks for clarifying what the expectation is.

It sounds like OH4 makes some significant changes. Just starting out, I’m torn between learning the new way of doing things, and sticking to what’s more stable. I’ve seen a few posts suggesting OH4 is not stable enough for everyday use yet, would your recommendation be to stick with OH3?

Ap15e thanks, I hadn’t come across the console before. I had installed via apt as a systemd service, so I didn’t naturally fall into it. Fun that it’s exposed as a nonstandard ssh port. Sure enough there are my transformations:

> bundle:list
...
295 │ Active │  75 │ 3.4.2                  │ openHAB Add-ons :: Bundles :: Transformation Service :: JavaScript
296 │ Active │  75 │ 3.4.2                  │ openHAB Add-ons :: Bundles :: Transformation Service :: RegEx
297 │ Active │  75 │ 3.4.2                  │ openHAB Add-ons :: Bundles :: Transformation Service :: Map

No. .things files use a completely different syntax. You’ll have to use the Things page in the docs which goes over the basic syntax and examples in the docs and the forum for how to translate from the YAML to .things file syntax. Note, for some add-ons, there are some capabilities that are not possible when using .things files, such as setting config parameters on devices in Zwave.

Also note that it’s a custom syntax that has nothing to do with Java.

There are some scripts scattered here and there on the forum that will pull the Thing from the REST API and create a .things flle out of them.

I personally don’t use and don’t support the use of things files. I find way too much time is spent fighting syntax errors that are impossible to make in the UI. And autodiscovery is always going to trump hand written for me anyway.

I’m a little less that way when it comes to Items and Rules, though even with Items if you plan on using the semantic model the UI is going to be less work for those as well.

It depends on how fast you want to get up and running and whether you are willing to report and follow the reported problems with 4. $ is getting better and M1 is pretty solid on a lot of fronts. But 3.4.2 isn’t getting any new updates so it’s stable. But pay attention to breaking changes because you’ll have to change those.

4.0 release will almost certainly occur in June.