How to write elegant code with Units Of Measurement

I started to learn the concept of Units Of Measurement after I upgraded to OH 4, I know it. existed before however I didn’t really use it in my items. Today I looked through all my Number items and start to add units for the missing ones. After the changes I realised that I also need to adjust some of my rules, and here comes the questions.
I have a simple rule that calculate the percentage of charging power and set a Dimmer to indicate the percentage (I know the max. charging power is 11kW).
Below are the two items representing the current charging in kW and the percentage item:

Number:Power                Output_power                 "Output Power [%.2f kW]"                   (gEaseeBox)           {channel="easee:mastercharger:home:EaseeCharger:state#totalPower", unit="kW"}
Dimmer                      EaseeBox_chargingPowerPct    "EaseeBox Charging Power Pct [%d %%]"      (gEaseeBoxHomeKit)    {homekit="Fan.RotationSpeed"}

The rules that I have now (after some corrections):

    Item Output_power changed
    var Number totalPower = Output_power.state as Number
    var powerPct = new PercentType(totalPower/11000*100)

Ok, here comes with my issues/questions:

  1. For some reason totalPower is always in W instead of kW as unit defined in items file
  2. How can I use Units Of Measurement in script? In my calculation the unit is not used and I feel the way how I did it is wrong.

Anybody who can help me to improve my rules? Thank you!

You’ve cast the state to a Number. Numbers don’t have units. So that would be my first thought. But that doesn’t explain why it’s W. Where are you seeing that it’s W?

You’d use QuantityType.

Note, for a sensor value representing percentage, it’s better to use a Number:Dimensionless with unit %.

It’s not a bad idea to force the value into the desired unit in your rule.

If you make EaseeBox_chargingPowerPct a Number:Dimensionless with unit %,

    var totalPower = (Output_power.state as QuantityType<?>).toUnit('kW')
    var temp = totalPower / 11 | kW
    EaseeBox_chargingPowerPct.sendCommand(temp + ' %')

In Rules DSL, to append a unit to a constant number use Number | unit.

Thank you for your reply! I don’t understand why do you suggest Number:Dimensionless instead of a Dimmer? Both seem to support percentage type, what are the advantages of using Number: Dimensionless with unit % over Dimmer?

This is something new to me - does appending a unit to a float number returns a QuantityType (in this case Dimensionless with unit %)?

No, both do not support PercentType. Only a Dimmer supports a PercentType.

Dimmers are intended to represent something that can be commanded on a sliding scale, like the brightness of a light or the volume of a speaker. A PercentType can only be integer values between 0 and 100.

Number:Dimensionless represents all ratios (decibel, percent, etc). As a number, it can support any ratio value including negatives, over 1, and floating point values. That is what makes it more appropriate for this sort of value. You are not controlling or measuring something in discrete integer percentages. You have a calculation of a ratio.

Assuming EaseeBox_chargingPowerPct is defined as a Number:Dimensionless and has % set in the unit metadata than you can send values with units to the Item as a command or an update (though now that I think about it, command makes no sense here. You are not telling a device to do something, you are recording a sensor reading so this should be an update).

There is no magic here. You can’t magically turn a Number Item to a Number:Dimensionless Item this way. You cannot send invalid units (e.g. 123 kW to a Number:Temperature Item).

1 Like

Thank you for the explanation, very helpful!