JS Transformation of Number:Power

Hi,

I’m trying to achieve a JS transformation which simply multiplies a value coming from linked channel.

The item which should receive the transformed value looks like this:

Number:Power   PVPower_DayAggregate   "PV Power"  {channel="modbus:e3dc:device:powerplant:power#pv-power-supply" [profile="transform:JS", function="e3dcDayAggregate.js"]}

For transformation I tried the following among other variations:

(function (i) {
  let val = parseInt(i.split(" ")[0], 10);
  val *= 24;
  return val;
})(input);
(function (i) {
  return i * 24;
})(input);

Unfortunately whatever I try I always receive warnings that look like the following and the item values are not transformed:

... [WARN ] [iles.JavaScriptTransformationProfile] - Could not transform state '5000 W' with function 'e3dcDayAggregate.js' and format '%s'

I also tried to change the source format to e.g. to %.0f but that didn’t help either.

Does anyone have an idea what should be changed in order to achieve a correct transformation?

I think if you are trying to feed your result into a Number:Power type Item you should at least put the units back in your return string.

I also tried this one but unfortunately I get the same message in the log.

(function (i) {
  let val = parseInt(i.split(" ")[0], 10);
  val *= 24;
  return val.toString() + " W";
})(input);

Forgot to mention this: I also tried returning a static value so that no calculation is performed and that resulted in the same log messages, so one might assume that something isn’t working as it should while assigning the new value to the item.

Have you installed the JavaScript transformation?

Settings>>transformations
image

Yes, it’s installed.
I already run some other basic transformation e.g. one to round a Number:Temperature value and that one is working just fine.

Found a way that works for me :slightly_smiling_face:
The input value has to be casted to an int first and can be multiplied after.

(function (i) {
  return parseInt(i, 10) * 24;
})(input);

It seems to be a variation of this issue

although the surprise is complaining about “fits everything” %s

What is the channel type here? Guessing #number or number:power?

Your Item has no state presentation in the file definition ( [ ] field in the label), I wonder if it would help to give it one?
This has a side effect of establishing a default unit.

The docs state that it should be Number:Power so your guess should be right.

As an alternative solution that perhaps some people find less error prone:

When it comes to scaling plain numbers from modbus and converting them to UoM (numbers with associated unit), you can use modbus:gainOffset profile. This can be also to write numbers to modbus (with units converted accordingly).

Simply set the profile’s gain parameter to 24 W.

There is a full example using textual config in docs: Modbus - Bindings | openHAB

Using the right word when having technical conversations is very important.

Calling parseInt is parsing the String to an integer. This is not casting.

Casting can occur when you have an Object that is more than one type at the same time. For example a Number Item has a state. That one state is:

  • Object
  • BigDecimal
  • Number
  • State
  • Command

When you use the as command you are saying “of all the types that this Object can be, I want to use it as X.”

MyNumberItem.state as Number

means I want to use MyNumberItem.state as its type as a Number. From that point onward you can only use it as if it were a Number and not as a State or a Command or a BigDecimal or an Object. You would have to recast it to one of those other types to do that.

Notice how String is not one of its types. You can’t cast it to a String.

MyNumberItem.state as String

would generate an error. You can convert the state to a String by calling toString. Converting it not casting either.

You’re absolutely right. Thanks for the clarification.