OH4 State Description - exclude %unit% from data passed to transformation

  • Platform information:
    • Hardware: RPi5/
    • openhabian
    • openHAB version: 4.3.2
  • Issue of the topic: I have various Items related to Inverters/Energy that I would like to transform when the amount is greater than 1000 W to x,xkW (e.g. 3256W becomes 3,2kW). importantly there should be no spaces between the number and the “unit” and neither between the “k” and “W”
    *I have a working Transformation that does this however when on the the State Description I add the %unit% the unit is included in the text that is sent to the transformation and the transformation fails. example: JS(config:js:hasThousandToK):%s %unit%
    I have tried using (), {}, to limit what is sent to the transformation but those brackets also get sent
    to test this i created a transformation as follows for testing"
(function(data) {
  var returnValue = "This is the output |" + data + "| "
  return returnValue
})(input)

that is called in State Description like this
JS(config:js:2b1e1ba791):%s Should not be sent to transformation

and it returns the result:
This is the output |50 Hz Should not be sent to transformation|

As you can see from above the text after the %s from the State Description is “passed” to the transformation and returned inside the || items from the transformation
(Note I could specifically rewrite the transformation to split out the needed(1st string)

Question: is there a method to handle this within the State Description?

PS This is my First Post so please advise where my posting amendment/correction as needed.

In order to do this you have to forego the use of %units%.You cannot put the %unit% in the state description pattern because that’s telling the UI “show the Item’s unit”. But you don’t want that because you’ve taken over that in your transformation.

Furthermore, if your Item is a Number:X Item (e.g. Number:Energy) or the transform is used in a Channel that publishes a unit, the unit is always going to be passed to the transformation. It’s up to you to remove it, modify it, change it as desired in your transformation.

Since this is display only transformation:

  • eliminate the %unit% from the pattern, you want to take control of that
  • in your transformation, you will get a value with a unit. It’s up to you to remove it/modify it. But this has nothing to do with the %unit% in the state description pattern. That’s the literal state of the Item. The unit is a part of the state.

So your transformation should look something like:

(function(data) {
  const rval = Quantity(data).toUnit("W"); // convert the String to a Quantity and force it to W
  if(rval.greaterThan("1000 W")) rval = rval.toUnit("kW"); // convert to kW if > 1000 W
  return rval.toString().replace(" ", ""); // remove the space between the number and the unit
})(input)

And your state description pattern should look something like

JS(config:js:hasThousandToK):%s

You don’t want OH to show the unit because you’ve taken over that in your transformation.

Thanks Again Rich

I had suspected that and have done it a little different because I am handling both W and Wh so it becomes simpler to add the "W/Wh in the Widget though not ideal. I will look furthermat this maybe try looking at something like _W or _Wh and then can separate based on the “underscore” character in the transformation which would allow the transformation to be generic.

You can pass arguments to transformations.

(function(data, lowUnit, highUnit, threshold) {
  let rval = Quantity(data).toUnit(lowUnit);
  if(rval.greaterThan(threshold)) rval = rval.toUnit(highUnit);
  return rval.toString().replace(" ", ""); // remove the space between the number and the unit
})(input, lowUnit, highUnit, threshold)

called using

JS(config:js:hasThousandToK?lowUnit="W"&highUnit="kW"&threshold="1000 W"):%s

It doesn’t get more generic than that. So long as you pass in compatible units that will work for any set of units.

Also note, it doesn’t matter what unit data is when it is passed into the transformation. It’s converted to W in the original and lowUnit in this update if it’s something else.

Edit: typo in the transformation, rval shouldn’t be a const since we reassign it.

I’ve posted a version of this without the removal of the space between the value and the unit to the marketplace.

You should be able to install it through Add-on Store → Transformations → Scale Units.

2 Likes

Thank Rich did not even cross my mind to have multiple parameters i will do some further testing and also the transformation in the marketplace is an elegant generic solution