UoM default units and consequences

I just read the release notes and took a look at the “breaking changes”.

Unfortunately I am struggeling to understand the following note:

Core Runtime

Default units have been added for all dimensions. A state description defining the unit should be added to each item that uses a different unit.

After reading this I think “state description” means this:

I also found this.
But that is confusion me even more. I guess that is only meant for developers anyway.

So what do I (as a normal user) have to do?
Can somebody give me a real world example?

Or can you usually ignore this “breaking change” . :wink:

Anyway: Big thanks to a developers for their great work. :+1:

The first place (in the .items file) is the correct one for you. If you use UI for items, you find the correct setting under „metadata / state description“.

first off: don’t ignore - use it! :wink:

no. it’s merely not. It’s a means to get most out of your openHAB powered smarthome.
Let’s see: You’ve got a thermostat, which sends its information in celsius - but you like to see it in the wrong unit :wink: of Fahrenheit? just set your “state description” to Fahrenheit and the rest happens magically.

Or let’s say your smartmeter of your home sends its info in Wh, but you want to use kWh for your UI and dashboard? set “state description” to kWh and the rest is done accordingly.

There IS one big isssue (that’s one reason for the breaking change): your rules could run into problems, if you’re used to compare “dimensionless” numbers. That’s not possible anymore - unless you either strip the UoM from your item in the rule - or add it in the rule to your comparison.

Ok.
So I “just” need to define UoM for all Number items.
And make sure the rules are made for that.

I already tried to use UoM where reasonable. :slight_smile:

Got It.
Thanks. :+1:

If you have a Number Item with units, previously if you sent an update to that Item lacking units (e.g. if you or the binding updated a Number:Temperature to 22.1) the units used by the Item were :person_shrugging: . If you were smart, you applied your own default for that Item by setting the label in your .items file or the state description metadata in the UI.

But we never want to be in a situation of :woman_shrugging: for something like this. It should be deterministic. So now if a unit is not supplied by the binding or what ever is updating the Item, if there isn’t a default set for the Item, a system default will be selected based on your locale.

A related change I think got in is that if you send a number with units to a plain Number Item, the units will be stripped off. This is a huge improvement because prior to that, if you sent a number with units like that, your plain Number item would become a Number with Units. You could never know for sure if the state is a DecimalType or a QuantityType.

tl;dr, now if you have a Number with Units, the state will always have units. If you don’t specify the units on the Item, the system default unit will be applied. If you have a plain Number, its state will never have units.

That looks all good.

Essentially yes, but everybody to use this pay attention please:
Make sure you understand the difference of item (data) type definition versus its definition of how values are to be displayed.

You define the UoM item type using e.g. Number:Power (as you did in your left hand side green box). Those items will then be QuantityType<Power> in your rules, and that data type won’t change no matter what a binding or rule of yours sends to it and if the value has a unit attached or is just a plain number.
The [%.2f %unit%] part of your right hand side green box however is NOT part of that UoM definition: it only affects the display and never the item state itself.
And if I’m not mistaken, it only affects the display in sitemaps, not that inside OH3 Main UI widgets, so as already said by others for correct display there as well you’ll have to use metadata.
By the way metadata can be defined via .items, too, if you don’t want to do that in 2 places, like this:
{ channel="...", stateDescription=" "[ pattern="%.2f W" ] }

Also note that whenever there’s no specific display definition, there’s still defaults that apply. They show the physical unit for the UoM type but if I recall correctly they do not limit the digits behind the comma, so a Number:Power item with no [%.2f W] and no metadata will still display with unit as 1234,5678 W.

4 Likes

Thanks for the correction, I don’t use .items files. I always thought that the [%.1f K] part of the label was parsed to a state description. Good to know that you actually have to set that as metadata.

I am not sure it is correct.
I am myself only using the syntax in label you mentioned.

If the binding doesn’t provide a unit (e.g. the device can report values depending on the device configuration) but the default unit from the locale is wrong how I can I enforce the correct one?

It is the responsibility of the binding to set the appropriate unit when setting the state of a channel that was defined to have a dimension.

Example:
The default unit for temperature from my locale is °C. I have a device that reports the temperature in Farenheit. The binding is unable to set the unit because the unit reported by the device is set through some device configuration.

My understanding is now that implicitly the unit is assumed which means it would be °C, correct?

I don’t know of what binding you speak of. But similar issues arise, if you use MQTT. The MQTT binding doesn’t presently use UoM. In fact I think it treats incoming payloads as string.
I’ve got a weatherstation sending the “wrong” units (Fahrenheit and inches instead of Celsius and millimeter). But without a unit, just the number. So I configured my items to °C and mm and I used “incoming transformation” of the channel to add the °F and inch. With that, if the weatherstatoin sends 15 °F, the item’s metadata automagically updates to -10 °C.

Don’t know, which binding you use - but you could add let’s say a JS-Transformation to your item, so it gets the unit you expect from your device’s configuration. But: the binding itself is in charge of item types. Many bindings already suggests item configurations.

Correct. Set the state description to °F and everything works out fine. The other option is to use a transformation, as @binderth suggests.

Wouldn’t that only change the displayed value and not the state of the item?

The item state or the item value?
Where can I find this “incoming transformation”? I can’t find anything in the docs.

Actually I would have expected a “set-unit” profile with one parameter which then would set/overwrite the unit on the channel, e.g.

MyNumber:Temperature itemName  {channel="channe" [profile="set-unit" unit="°F"]}

So the profile would indicate the the value from the channel is in Fahrenheit while the default Temperature is in °C.
Value from Channel: 15
Item state: -10 °C

That’s MQTT-specific. I use OH3-UI, so it’s this config:

  - id: WetterstationTempOutside
    channelTypeUID: mqtt:number
    label: Außentemperatur
    description: null
    configuration:
      postCommand: false
      min: -30
      stateTopic: devices/weatherstation/tempOutside
      max: 60
      transformationPattern: JS:addFahrenheit.js

the addFahrenheit.js only adds " °F" to the MQTT-payload. The item itself is configured with °C, so everytime the station sends the pure number, the incoming MQTT payload gets the unit added and the item gets updated to °C.

If it’s another binding, which just relays the unitless payload to the item, you have to add the celsius<>fahrenheit Transformation to your item definition:

Number:Temperature itemName  {channel="channel", ... , stateDescription=" "[ pattern="%.2f W" ], transformationPattern="JS:fahrenheit2celsius.js"}

you must have JS-Transformation installed and the fahrenheit2celsius.js simply calculates Celsius from Fahrenheit values.

How wold you make sure then, that incoming values are always coming in in Fahrenheit?

Unfortunately, when UoM was retrofitted in OH2 there was nowhere to add a new Item property “default unit”.
So, they hijacked the existing state presentation stuff to also serve as a source of per-Item default unit.

You are correct - this is used to format Item state for display without affecting the underlying state.
but
As it is also used for Item default unit, it may affect the value before it gets loaded into the Item state i.e. scaling incoming updates to the default.

It’s a kludge and I hope they fix this in OH4

As a use case, imagine I have an Item stored in kWh units but would like to display as “XX kilowatt-hours” or local language. Not easy.

oh yes. A looot of confusion around this would be solved.
But remember: the “real” state of the item is the one getting persisted. So, if you want to have continous persistence for graphs or the like: be sure to stay with one unit - later changes to an item don’t change already persisted values.

The device only reports in Fahrenheit, because it’s configured that way.

The transformationPattern is mqtt binding specific and won’t work e.g. with the Z-Wave binding.

But wouldn’t a manual calculation from Fahrenheit to Celsius make the whole uom concept obsolete anyway? The whole idea behind uom is that the user doesn’t have to convert himself. Supplying the values with units will automatically make openHAB pick the correct calculation.

Imho there are still two points to address

  1. Setting/Overwriting the unit for a value that is sent from a device
  2. Setting/Overwriting the unit on the item (e.g. in case the default from the system locale is not correct)

The first should be done through a profile, because that’s where it fit’s currently the best.

MyNumber:Temperature itemName  {channel="channelUID" [profile="set-unit" unit="°F"]}
MyNumber             itemName  {channel="channelUID" [profile="strip-unit"]}  // for completeness

The second could be part of the item definition, e.g.:

MyNumber:Temperature:°F   itemName

I think for most of the users it’s clear that the label [%.1 °C] will result in a display transformation in the GUI. However inferring the default unit from there when the docs state it defines how the value is represented in the gui is quite creative :wink: :rofl:

Agreed - let’s hope it’ll get better and not only different :wink:

If the binding itself works as designed from the architectural point of view you won’t need to do anything - because it should allow for the correct types.

but as you said:

  1. :white_check_mark: setting the unit on the item: is presently possible
  2. :no_entry_sign: setting the unit coming from the binding’s channel: not every binding does this
  3. :white_check_mark: setting the unit for presentation ( :question: regardless of UI/sitemap/…)

and agreed: there should be a clear distinction and configuration of these three possibilites