Get Thing or Item name in javascript profile transformation

  • Platform information: image: “openhab/openhab:3.4.1-alpine”

Hi!

to avoid a zoo on javascript transformation functions, I’d like to cluster my common use cases and determine in the function what to do, based on the item name/uid/…, thing name/uid/… for which the transformation was called.

So I have learned from the Transformation - Javascript documentation that one can add URL parameters after the javascript filename (like my_transform.js?srcChannel=KNX_Temperature_Garden).
Still, is there a way to make this with even less custom configuration necessary?

And, yes, I have read that these transformation functions are initially intended to stay isolated :slight_smile: - which is somewhat a shame, because then one could detect jumps in (e.g. temperature) values within a given timeframe that are not plausible without creating a lot of (otherwise unnecessary) proxy items.

At least it is possible to return “undefined” in the transformation for absolut unrealistic cases (I know about Metadata - State Description and use this too in some cases).

Thanks, Alex.

Not sure if you’re aware that javascript transformation no longer exists in openhab 4. In its place is the Script transformation which can use javascript as the language if you installed the jsscripting addon.

SCRIPT transformation is available in openhab 3.4

Could you clarify what you have in mind?

If you pass it the name of the item involved, your script could check with persistence if you wish, or with anything you could do with a script, even checking against other related items.

I have installed the “Javascript Transformation” and configure it in the UI via Item->Channel Link->Profile->JS. So this will be no more in OH4?

My use cases are quite simple:

Currently I am returning with no value for different values that my FreeBUS sensors return incorrectly (but also some Jung components have their issues).

So it would have been nice to have one script that identifies the target item/sending channel/thing and then takes correcting actions for e.g. everything temperature (or everything brightness related for that matter), without adding parameters for every configured script - which is again a source of error and a click pain (where it on the other hand could be automated in one place).

Another thing I do in the transformation script is rounding values to 2 digits to avoid those annoying *.0000000002 or *.9999999997 numbers.

So it is possible in the transformation script to access persistence? That would be interesting indeed. How would I do that? typeOf items is undefined and log.info(Object.keys(this).sort()) only gives input (+ any other variable added via URL encoding)

No. SCRIPT, which replaced JS Transformation as @JimT points out, supports that too. But that’s all you get.

Either you need proxy Items or you don’t. Implementing this in a transformation or a rule wouldn’t change that. And if you don’t want to pass a bunch of hard coded values into the code using URL parameters, you need to use a rule where you do have the Item name and all the other information you are after.

The Smarthome/J marketplace has a set of profiles, one of which handles this case I believe.

Correct. The JS Transformation uses Nashorn JavaScript which no longer exists on OH 4. It has been replaced with the built in SCRIPT transformation which supports all rules languages, not just Nashorn JS.

I don’t understand why the transform needs to know the Item name to do this. There is a custom threshold and correction behavior on a per Item basis?

Hopefully you don’t do any math with these values. Premature rounding is a big source for errors in calculations.

Possibly. I’ve not actually done the experiments yet to see what all gets injected into a SCRIPT transformation. If they work like the old JS Transform, than you need import the Persistence actions and possibly the ItemRegistry to pull the Item Object. The rule context stuff doesn’t get injected into JS Transformations. SCRIPT might work differently though. If the helper libraries are fully injected (and I have reason to believe they are), you can access them through that and may not even need to import anything, or just import the helper library if it isn’t.

But either way you still need to know the Item name. Also be wary of timing issues. Data is stored to Persistence in parallel to other events. I don’t think it would be a problem here but something worth keeping in the back of your mind.

Yes they are fully injected (by the scripting add-on). It is just like your normal rule engine, so you can do everything with the exception that you must return a value of course.

You can even dynamically create an item, a rule, execute another rule, send an email, etc. if you wanted to :grin:

There is a bug that has only been fixed a few hours ago in snapshots, so this bug may also exist in oh34 (I haven’t checked because the implementation of watch service changed at some point and I don’t know when exactly): the scripts for the transformation don’t reload on change, you’d need to restart openhab.

Not a bad idea but currently this isn’t possible without passing an argument.

However, beware, AFAIK transformation works by intercepting data before it made it into the item as state. So at this point the item still contains the old state. The new raw value is just in the input variable

Use display formatting for that, not value transformation.

Yes but only in SCRIPT transformation as I mentioned above and it’s very simple.

Not in JS transformation (afaik, although it may be possible I never looked into it, in any case it will be complicated).

It’s been awhile since I’ve tried it but there seems to be something different in the UI when it comes to creating rules from rules. They don’t get registered in the registry the same way and cannot be managed the same as other rules. For example, if I create a rule from a rule, I cannot disable/enable/delete that same rule from a rule. I can only do that through the UI. But there have been many versions of OH since I last tried that, maybe it works better now.

I’m glad to see that was fixed. I’m the one who filed the issue. And apparently it applied to all transforms, not just SCRIPT and that problem does exist in 3.4.2.

It should be possible and not too complicated. If you import org.openhab.core.persistence.extensions.PersistenceExtensions you can call all the Persistence actions. But you need the Java Item Object in the call so you’d need to import org.eclipse.smarthome.model.script.ScriptServiceUtil to get the Item registry. It would look something like:

var ScriptServiceUtil = Java.type('org.eclipse.smarthome.model.script.ScriptServiceUtil');
var PersistenceExtensions = Java.type('org.openhab.core.persistence.extensions.PersistenceExtensions');

var i = ScriptServiceUtil.getItemRegistry().getItem('MyItem');
var previousState = PersistenceExtensions.previousState(i);

Note that input in the script will be a String and previousState here will be a HistoricItem.

Thanks for your thoughtful answers!
I wanted to give this finally a try today and - of course - failed.

Here is what I tried:

  • create a new Item (_Debug_Temperature, class Point_Measurement, relatesTo Property_Temperature).
  • add to Channel Links a new link to an item channel
  • set Profile to JS (as this is IMO the only reasonable option)
  • set Profile Configuration to
    SCRIPT(graaljs:knx_fix_temperature.script?srcChannel=KNX_Temperature_Alarm&dstItem=_Debug_Temperature):%s
    This was taken from JavaScript Scripting - Automation | openHAB.

What bothers me now is, that in Transformations | openHAB it is mentioned that SCRIPT is not available as profile. For both, version 3.4.2 and upcoming 4.

And indeed, the logs say:

2023-03-29 00:27:24.864 [DEBUG] [rnal.JavaScriptTransformationService] - about to transform '3.68' by the JavaScript 'SCRIPT(graaljs:knx_fix_temperature.scri
pt?srcChannel=KNX_Temperature_Alarm&dstItem=_Debug_Temperature):%s'
2023-03-29 00:27:24.864 [WARN ] [iles.JavaScriptTransformationProfile] - Could not transform state '3.68' with function 'SCRIPT(graaljs:knx_fix_temperature.s
cript?srcChannel=KNX_Temperature_Alarm&dstItem=_Debug_Temperature):%s' and format '%s'
2023-03-29 00:27:24.864 [DEBUG] [iles.JavaScriptTransformationProfile] - Transformed '3.68' into '3.68'

Did I misunderstand here something in the thread up to now?

Also @rlkoshak code fragments from above do not work in the regular JS code, which appears to be obvious to the informed OH community member :wink:

If this PR gets merged (which it hopefully will be), the SCRIPT transformation, which was introduced in 3.4, will NOT be available in Openhab 4.0. Instead, it will be backwards-compatible with the current JS transformation, but without needing to install the JS Transformation addon (in 4.0). Instead, you’d just need to install the JSScripting automation addon. The core will create the JS transformation (without a special transformation addon). It will maintain the same syntax as the old JS transformation.

So perhaps it is best to stick to the JS transformation, and only change to SCRIPT transformation if that PR didn’t get merged into 4.0.

BUT the twist is that currently in 3.x AFAIK, JS transformation uses Nashorn engine, and thus not as convenient to get thing/item etc in your transformation? :frowning:

So to use the modern JSScripting in your transformation, use SCRIPT now, and in 4.x change it to JS…

Profile script transformation will be available in 4.0

I don’t have much to add beyond what @ccutrer said in terms of what’s coming down the line except to say that independent of that PR the SCRIPT transform is not yet supported in Profiles in OH 3.4.2. The PRs for 4.0 may have gone through, I’ve been on vacation for a week and am behind on what’s been merged and not.

But, in addition to using SCRIPT in a Profile being wrong, the :%s is also wrong. You only use that when applying a transform in an Item’s label or the Item’s State Description Pattern.

Also note that the Ruby library allows you to add custom profiles types that would allow your processing to directly receive the item involved, instead of having to add it as a separate query param when using a transformation-based profile: Module: OpenHAB::DSL — openHAB JRuby