JS Transformations in item channel definition

I am moving all my bindings to V2 in order to migrate to OH3.

So far I encountered one issue that I haven’t managed to solve yet:
I want to transform a state received from a binding.

This is my Items definition:

Number APC_TIMELEFT (gAPC) {channel="networkupstools:ups:ups:batteryRuntime" [profile="transform:JS", function="sec2min.js", sourceFormat="%.1f"]}

This is my JS transformation (sec2min.js)

(function(i) {return i / 60; } ) (input)

And this is the error message:

2021-01-29 09:13:47.407 [WARN ] [iles.JavascriptTransformationProfile] - Could not transform state '8308.0 s' with function 'sec2min.js' and format '%.1f'

I tried without sourceFormat and with sourceFormat="%d" or "%.0f" or "%.1f s" but get the same type of error.

(I know I could transform the seconds to minutes using the Time unit of measure, but I want a more general way using the transformation service for future use. So plese help find the error in the above syntax.)

Seems like a version of this bug

This comes from the binding supplied defaults and is misapplied to transform output.

The value input into the transformation seems to be ‘8308.0 s’, i.e with the unit attached. I think you need to handle that properly in your javascript. Try changing to

(function(i) {return parseFloat(i) / 60; } ) (input)

and see if that helps.

So I should not use sourceFormat in transformations?

Tried the suggestion without sourceFormat but I receive no error message but the state = NULL

I’m actually not sure if the format specifier works, it seems that the incoming state is converted to a String before the format specifier is applied, and the ‘f’ format specifier is only applicable for floats/doubles. Try removing it from the item definition.

Edit: saw now you already tried that and it didn’t work. Not sure how to do then…

Can’t test ATM, so use the following with caution:
IMHO your js function expects an input which can be parsed to a number, however it gets a number with a dimension (“s”). I’d try to split that dimension from the number, like:

var temp= i.split (" ");
return temp[0]/ 60;

If that isn’t according your more generell solution, try to remove any non-member character using a reflex or the like.

SourceFormat is about formatting raw data from binding as it gets given to the transform. In almost every case you can let that default (%s) and transform deals with a string.
As an aside, remember that any format produces a string - the transform input is always a string.

Your problem is the other end of the transform, the output to Item, and it is beyond your control. It’s a bug.

OK, a few things to mention here to be complete.

The Channel is returning a Number:Time value so if you make your Item be a Number:Time too then you don’t need to do any transformations at all. You can just change the State Description to use %.2f min and it will convert it to minutes for you.

You can also use the DateTime formatting to show Hours:Minutes:Seconds I think. If you use %s it will display the value as a DateTime (with 1970-01-01 as the date).

In your rules you can use the units too. For example, to see if it’s less than 2 hours

if(APC_TIMELEFT.state < 2 |h) {

As for the transform, i is getting the String “8308.0 s”. You need to strip off the units and then you should be able to parse it into a float you can do math.

var num = parseFloat(i.split(" ")[0]);

NOTE: all of this is assuming that everything is working correctly and not related to the bug rossko57 linked to.