OH 4 Units

Hi all,

So I finally upgraded our core system to OH4 from OH3. A few days ago. All seemed good - although I finally noticed one minor thing due to the units now getting normalized in OH4.

So the blank part 08/20 00:00 is when the servers were offline for disk imagining - prior to the backup - just in case snapshots failed, etc… no issue.

Then there’s a blip where it kicks in with OH3 before the OH4 upgrade is run.

Now there’s the fun bit. The VeSync binding I initially did porting of the protocol from pyvesync, originally mapped the units as what I would call pass-through. From what the binding specified through the entire system, so it was reflective of what the unit displayed. With the upgrade it changed the units to kg/m3, which effectively zeroed out the units and would have made the rules invalid I believe.

I have added another column to the VeSync binding Readme.md called units and specified the explicit units against the channel, where the normalized mappings would impact the binding.

I really hate suggesting anything that creates work for us developers, but my experiences makes me think for OH 4 all bindings may need a doc revisit, and a unit column added if they don’t have it.

I say this as I wouldn’t have a clue what to use, and luckily from the context of writing the binding could figure out what to google until I found the correct unit’s def. to use and test. Now at least users can see it in the documentation when that gets merged - I would have been stumped however as a end user, who didn’t know the units of the protocol. (Also its still a pig to find what is the correct unit string entry to use - I see other UI suggestions elsewhere to fix this :+1:).

In the meantime it makes me think that anything that maps to a non standard unit, need’s this column and we unfortunately need to check for it on PRs as well?

Any thoughts - the above is hopefully just useful input based on my experience.(Maybe there is already a unit column in other bindings I’ve never seen?).

I think we are missing some details.

Did you apply unit metadata to these Items prior to or immediately after the upgrade to 4 if at all?

If not, did the Item’s State Description Pattern include units (not including %unit%)?

How was the upgrade performed?

The way it’s supposed to work is:

  1. .items files per the release notes, all Number:X type Items should have unit metadata added. If not updating all, at a minimum those Items that have a State Description Pattern that shows the Item as a different unit from the default or from what the Channel provides must have unit metadata added.

  2. Managed Items mostly get the unit metadata added automatically during the upgrade process. If the Item has a unit in the State Description Pattern, that is used for the unit. If it has %unit% or doesn’t have that metadata, the unit advertised by the Channel is used (I’m not sure how that is detected, maybe. If that doesn’t exist, the system default for that unit is used.

So the first step is to determine if for you something failed in either 1 (i.e. you didn’t manually add the metadata) or 2 (something failed during the upgrade or there is an edge case not handled).

Note, if the unit on the Item doesn’t match the unit provided by the Channel, the value will be converted to the unit on the Item before the Item’s state is updated, meaning the Item will always carry the user specified unit regardless of what the add-on delivers or what the state description pattern uses to display it.

I do think that add-on authors should always document what units a Channel delivers if it publishes values in units. If for no other reason, because users can now choose to link those Channels to just a Number (throwing away the units) in which case they’ll need to know what units the value is coming over as just for their knowledge on how to use it. But now with the unit metadata the user has a bit more control over the state that the Item actually stores, and therefore what units the value gets saved to persistence.

Hi @rlkoshak,

Okay so to try and explain the binding maps the value in question using this:

updateState(DEVICE_CHANNEL_AIRQUALITY_PM25,
new QuantityType<>(purifierStatus.result.result.airQualityValue, Units.MICROGRAM_PER_CUBICMETRE));

In channel-types.xml for that channel it has:

Number:Density
Air Quality PPM2.5
Indicator of current air quality

Now the item line was:

Number:Density LoungeAPAirQuality “Lounge Air Purifier Air Quality [%.0f%]” { channel=“vesync:airPurifier:vesyncServers:loungeAirFilter:airQuality” }

In 3.4 this showed and persisted the units as µg/m³

Upon upgrading to v4. The units became kg/m³. So the units no longer pass through what the binding specifies in code, but go “may be incorrectly named by me” a normalized base unit. Hence it gave the persisted data as shown in the original post.

Of course when it was µg/m³ changing to kg/m³ means rules using µg/m³ won’t work as they are now evaluating against a different persisted value.

The documentation I have updated to:

Number:Density LoungeAPAirQuality “Lounge Air Purifier Air Quality [%.0f%]” { unit=“µg/m³”,channel=“vesync:airPurifier:vesyncServers:loungeAirFilter:airQuality” }

and added a unit definition against the channel details.

As for the display / use of this parameter the units need to be specified to µg/m³ in order to match the scales shown by the unit.

Does that make sense?

I think your first point is the key bit:

.items files per the release notes, all Number:X type Items should have unit metadata added

However it used to pass-through and wasn’t in the binding doc’s until my new PR goes in. So as a user I would struggle to find the right “units” to set for the channel or any other ones, is my main gripe - not with the normalization that OpenHab does as such.Hence the doc’s should have unit’s specified otherwise it it can result in what looks like a fault, where actually the data is just re-based to a different unit. P.S It doesn’t help grafana / influx combo, appears to show the units from the latest persisted value, so its not immediately clear the units changed.

P.S at the end of the original graph on the first post (the values started coming in as unit has then been set as updated in the docs).

Right. So no unit is specified. Therefore the default unit for that unit of measurement type is what gets applied.

Previously, given no other information, the unit in the state update was applied so what came from the Channel was passed through. Now the value is always converted (if necessary) to the unit of the Item. When unit metadata isn’t defined that base unit is going to be the system wide default for that UoM.

Persistence saves the state of the Item without units. It just saves the number. One of the problems that arose with the old way that was fixed in 4.0 was the following scenario (among others). Let’s say you have a Channel that publishes °C. The Item’s State Description Pattern is set to show the Item as °F. In this scenario the Item’s state is °C so that’s what gets saved. However, on restoreOnStartup the only unit that is known at that point is the State Description Pattern so that 22 °C gets restored to the Item as 22 °F and until that Item gets updated from the Channel again, it’s going to be wildly off.

So yes it is important that binding authors specify the unit in the docs for their Channels. But there is a nuance there because even if the unit published is documented to be °C (for example), if my default units is set to imperial, my Item will be set to °F, given no other information (i.e. unit metadata is not defined).

Ultimately, I think the rule should be “always define the unit metadata to be what you want for the Item. Never rely on the defaults.” If you follow that rule, it doesn’t matter what units the Channel publishes. Either the unit will match or it will be converted automatically. In either case, the end user gets the units they want.

However, because it’s possible to link a Channel to a Number Item too, it’s important to document the units so that those users know what values they are receiving because no conversion will take place in that case. The units are just dropped.

All great points, and don’t disagree with any of it. As a user however I do want the binding usually setup or the ability to set it up, without researching units for the device, and you’ve said also the units should be documented, in which case this problem goes away a sensible unit “suggestion” is documented. I think that’s the key ask is can we ensure units are specified not as a mandatory suggestion but starting point, so users know how to get a reasonable starting representation of the data pulled in (where possible).

Yeah your right about the units I could have sworn I saw kg/m3 on the UI interface - but I can see its coded into the UI, so must have been mistaken.

Part of my point is it doesn’t matter what units the device reports. If it reports a density, the user can and should choose the density unit that makes sense to them. If none of the options make sense to them, well they need to research the units anyway so they can even interpret the value in the first place.

That doesn’t mean that binding authors should not document what the unit is or what a sensible unit should be. But ultimately, the user should choose what makes sense to them regardless of what the device reports. Or, if they don’t want units they have that choice as well.

Yeah completely agree, I think this is the point I was trying to make :slight_smile:

That doesn’t mean that binding authors should not document what the unit is or what a sensible unit should be.

Your completely right it should be the users choice, and all of the logic to persist in that selected format makes perfect sense. Just figuring out the correct units if the modules doc’s don’t get that information, I can see making more noisy threads. Just trying to think if there’s any way to suggest improvements to the units page, to make life easier (I may need to read up more on the whole units system first however).

There really is no “correct” unit. There are a collection of valid units that each type supports. But any one of them is correct. If you, for example, have a Number:Temperature, °C, °F, and °K are all valid choices. Any one of those is “correct”.

What units the binding author choose isn’t the “correct” unit. It just happens to be one of the valid units to represent that value. One can find the the list of valid units for each Number Item type in the UoM docs. The binding docs definitely indicate what type of Item a Channel is expected to be linked to. And with that information one can look at the table on the UoM page to see what units are possible.

The only additional complication is that some units support prefixes while others don’t. For example you can have kWh but not k°F. The latter makes no sense. So a little bit about what is being measured needs to be understood by the end user.