How to easy calculate item value x1000

  • Platform information:
    runtimeInfo:
    version: 3.1.0
    buildString: Release Build
    locale: de-DE
    systemInfo:
    configFolder: /etc/openhab
    userdataFolder: /var/lib/openhab
    logFolder: /var/log/openhab
    javaVersion: 11.0.12
    javaVendor: Azul Systems, Inc.
    javaVendorVersion: Zulu11.50+19-CA
    osName: Linux
    osVersion: 5.10.60+
    osArchitecture: arm
    availableProcessors: 1
    freeMemory: 42707944
    totalMemory: 135356416

  • Issue of the topic:
    Short explanation: I just want to calculate the value I get from the binding/thing/item/sensor *1000 because the current value from the sensor is wrong by the value of 1000.

Long one:
I have a Eurotronic VOC-Sensor which is working fine in my environment.
The only problem is, that the Channel “sensor_voc” delivers VOC values wrong by 1000. The values are for example “1.234” (which I know by the way that this should be a comma (such as in english notation) and not the thousand-dot)

I already (after a houreless search at the Internet) tried this things:

  • using offset profile at the item (*1000/x1000) => wont work, maybe because only positive and negative values are allowed (not excactly described in UI and documentation)
  • Metadata, state description (very bad documentation about the possible parameters and syntax)
  • REGEX (
"0\.", ".\.", ".\\.",

and so many more) to extract the value behind the zero and dot (bad documentation as well, missing all possible methods and more specific examples)

Maybe the solution is that easy, but if it is so, its very difficult to find that out. I spend hours to search all forums via Google or search here.

As well I want to force the item to show always full numbers. That means, if the solution via REGEX is gonna be working: If the value is maybe 1.2 (the sensor itself pushes that information) it should show 1200, because 12 is not a possible value or another example: 0.3 should be shown as 300.

Who could help me here?

It’s not entirely clear for what use you want this new multiplied number will be put. Will it be charted? Used in rules? Used in expressions to make a dynamic MainUI Widget?

What type of Item is VOC-Sensor?

What binding is used to populate this Item?

These are all details that need answers as your end goal can change the overall approach.

  1. Question: Well I did not think of all the options but long term I would use all of them. But first its enough to see the current value (e.g. in widget) and also store and show it it in a chart.
  2. I dont exactly know what you mean with type in this case. Would this screenshot be helpful?
  3. The binding is the (only) Z-Wave binding from Chris Jackson in Version 3.1.0

Well the end goal could not be the essential thing to get know how to calculate with items or vaules?
But as I already read many people want to calculate and all I see are very long scripts to get to the point. If this is the result I think openHAB is no solution for me.
The whole openHAB system seems so easy, wide and smooth starting at the installation and ending at the great experience at the webUI on smartphones.
But why is such a simple operation so difficult?

EDIT: I had it backwards. Multiplying by 1000 give parts per trillion, not parts per million.

Well, if all you care about is how it appears on the sitemap you can use a transformation. The Item will remain the value given to it by the binding but you’ll see it modified in the UI.

But if you want to use this value elsewhere then you need to change the value before it gets to the Item. And there we have choices for approaches based on other details like which binding it comes from and the Item’s type.

If you only use this value in a Rule for other calculations then you don’t need to change anything at all but just multiply it in the rule. However, the units of the value come into play here too.

OK so it’s a Number:Dimensionless using “parts per billion” (ppb) as the units. Are you sure the value is wrong? Maybe what you really want is “parts per million trillion” (ppt). That’s the whole point of units of measurement. You don’t need to do anything really to convert between compatible units. You just need to specify which units you want to use.

So assuming you want ppt you can just specify that in the State Description metadata pattern. The field you want to set is Pattern and the docs for what goes there is Items | openHAB.

In this case all you really need to do is tell it to use ppt as the units.

%d ppt

That will change its display to ppt instead of ppt everywhere in MainUI.

However, the charting will still use ppb. There is no way around that for now.

Because it’s not a simple operation. In your mind you are just wanting to multiply a number by 1000. But as you can see it’s way more complicated than that. For one it’s not just a simple number.

Don’t be fooled by all the wonderful work the developers have done to make openHAB as easy to use as it is. Home automation is hard. It’s unbelievably complicated. Almost nothing you do in home automation is going to be as easy as you think it should be. Unfortunately that’s just the state of the world right now in home automation.

That’s not to say that it’s unachievable, even by people who don’t consider themselves to be technically skilled. But you will have many hurdles like this to overcome going forward. When you encounter something that seems like it should be simple but it’s not, that probably means its not so simple as it seems. So before you spin your wheels for hours, ask for help. Be sure to provide as many details as possible and always state your end goal (not how you hope to achieve it, this is called the XY Problem). There are many ways to do things in OH and the best one depends on what your ultimate goal is. Sometimes it may be a radically different approach.

And just for illustration, here’s another way that may work to force the Item to use ppt. But it’s going to involve the JavaScript Transformation and a Profile.

First we need to write the code that will transform the value to ppt. Put the following into a toppt.js file in the $OH_CONF/transform folder (e.g. /etc/openhab/transformation).

(function(i) {
    var num = Number.parseFloat(i);
    num *= 1000;
    return num+" ppt";
})(input)

NOTE: I just typed that in, there may be errors.

All transforms work on the string representation of an Item’s state. So we need to parse that string into a number we can do math with. Thankfully JavaScript’s Number.parseFloat() function will stop as soon as it hits a character that doesn’t belong in a number instead of throwing an error. This is important because this is a Units of Measurement Number so the state is actually “0.5 ppb”. That " ppt" is part of the state.

Then we multiply it by 1000 and return the new value with the new units appended: “500 ppt”.

That should force OH to use “ppt” as the default units for that Item from now on which will cause it to chart the ppt instead of ppb too.

Yet another way involves using proxy Items and a Rule. See Design Pattern: Proxy Item. Trigger a rule for when VOC-Sensor changes. The Script Action in Rules DSL would be something like

VOC-Sensor-Proxy.postUpdate((VOC-Sensor.state as QuantityType).toUnit("ppt"))

That will update the proxy Item with the value converted to ppm similarly to how the transformation worked. Only in a rule we have more options to manipulate the units.

To summarize:

  • This is really an XP Problem. You don’t want to multiple by 1000, you want to use the right units by default.
  • Modifying the value returned by a binding really isn’t something that is nor can it be simple.
  • I presented three different ways to deal with this problem. The State Description Pattern is the simplest, most straight forward, and is going to address your immediate needs.
  • The second approach would be best used in cases where the sensor needs to be adjusted and it’s not using Units of Measurement or the adjustment is more involved than a simple change in units.
  • The third approach would be best used in cases where the Items involved are not using units of measurement or the calculation for the new state depends on the states of other Items. It’s also the best approach if the sensor’s readings are not reliable as it gives you the chance to ignore the unreasonable values.

So hopefully you can see now how your end goals can radically change what our answers might be.

Thank you rlkoshak, for your real good, detailed answer.

First, forget the unit. (That’s the problem with screenshots when you don’t blur out the parts which aren’t needed at all).
I think that the units millions and billions appear here has inadvertently misled you. The unit is not the problem here.

Lets say, to make it easier, the value multiplicated with 1000 is better readable for me. Thats all.
If the unit is there or not, I dont care.

So I am sorry to say thats really complex.
As my title says: It should be easy. Well I understand thats not easy at openHAB but other Smart Homes, to invalidate your thesis can easily do this.
Just to give one example: In Homematic you can store a value from a sensor in an systemvariable. And with this variable you can calculate or whatever in scripts. Further you can calculate before storing it in the variable.
But thats not the topic here. And yes both systems are not directly compareable. But the thought behind the easy scripting language is good there.

I am a beginner and many others too, so sorry for that.
Could you write me a short manual with script, which gets the current value from the sensor, multiplicate with 1000 and stores it in another item so I can continue with the value in that new item, such as create a chart.
What I have to import (transformators?). What do I have to create (Script, Rule?). What are the steps.
It will not only help me.

Thank you!

1 Like

EDIT: I had it backwards, multiplying by 1000 gives ppt, not ppm.

But I can’t forget the unit. The Item is a Number:Dimensionless. That type of Item carries Units of Measurement. We can’t just ignore it. It’s an intrinsic part of the Item’s state and it must be dealt with.

And never blur out anything except private information when asking for help like this. We are perfectly capable of ignore the stuff that may be irrelevant. But you may not have the knowledge or experience yet to know what is relevant and may blur out a key piece of information. In this case the fact that it’s a Number:Dimensionless with a default units of ppb is critical information.

But that’s my point. Whether you care or not the unit is there. A Number and a Number:Dimensionless are two different thing. You can’t just multiply the value by 1000 without taking into account the units. And if you multiply it by 1000 you no longer have ppb, you have ppt. Since the unit is there whether or not you want it to be there, why not just take advantage of the features built into OH to use ppt instead of ppb?

This is the XY Problem. You just want to multiple the number by 1000. But what you really need is to just use the right units.

Well, if other systems can meet your needs perhaps they are better fit for you. It’s more complicated here in this specific case because OH doesn’t just deal with numbers. It deals with units too.

And really, if all you want to do is show this Item multiplies by ppt, what can be easier than adding %d ppt to the Item’s State Description? OH will do the math for you. Of course where this get’s more powerful is when your sensor is publishing °F but you want to use °C, or the sensor is reporting in Wh but you want to use Joules.

And if OH can’t do it as easy as you think it should be? You prefer no answer at all? You prefer an answer that doesn’t actually help you achieve your end goal because, in your inexperience you seem to think you know how it’s supposed to work?

Sounds like Items.

Sounds like that Profile example I posted above.

I kind of already did, three times over. For an Item that has units what I posted above are the ways to do it. Either you tell it to display the units you want or you tell it to store the units you want.

Option1: State Description

  1. Open the Item
  2. Click on “Add Metadata”
  3. Select “State Description”
  4. Enter “%d ppt” for the Pattern

It will now show the value as ppb*1000 (i.e. ppt) everywhere in OH.

Option 2: Transformation/Profile

  1. Create a text file named /etc/openhab/transform/ppb2ppm.js
  2. Enter the JavaScript I posted above
  3. Install the JavaScript Transformation add-on under Data Transformation
  4. Open the Link between the Item and the Channel.
  5. Select “Transform” as the profile to apply on the Link.
  6. Enter “JS” for the transformation type and ppb2ppt.js

It will now show ppb1000 (i.e. ppt) and the Item’s value will actually be stored internally as ppb1000 (i.e. ppt).

Option 3: Rule

  1. Create a Rule
  2. Create a Proxy Number:Dimensionless Item to store the converted value
  3. Add an Item Event trigger to run the rule when the original Item changes
  4. Add a Script Action, choose Rules DSL as the language, and include the line of code above as the code.

Every time the original Item changes with a new ppb value, the proxy Item will be updated with the ppm equivalent.

Note: the Script Action is code. It can do anything you want it to do.

What if the Item were just a Number?

This seems to be what you are after, but you can’t get there because your original Item isn’t just a Number.

But if it were just a Number then you can use the JS transformation as described above with the following JS tranformation:

(function(i) {
    var num = Number.parseFloat(i);
    num *= 1000;
    return num;
})(input)

Notice, the only difference is we removed the " ppt" units from the return statement which we can do because the Item is just a Number.

I think that will work. Until very recently Profile transformations would only work with String Items, not Number Items.

To do it in a rule, do it the same as described above and use the following as the line of code.

VOC-Sensor-Proxy.postUpdate((VOC-Sensor.state as Number) * 1000)

Or, because it’s just a Number Item you can use Blockly.

You couldn’t use Blockly before because the Item isn’t just a Number, it’s Number:Dimensionless.

I think you should take a step back here.

The maker of the device claims to deliver VOC sensing in ppm units. Is that not happening?

In openHAB terms, that means you should link the binding VOC channel to an Item of type Number:Dimensionless (the type that support %, dB, ppm etc. units) without any kind of profile or transformation.
That should update your Item with ppm value, including units. Is that not happening? Look in your events.log to be sure,never mind what the UI says for now.

Once you’ve got unmolested ppm values in your Item, then you can change the default units if you like. That’s a per-Item change, carried out on the Item metadata in the pattern field.

That would actually be unusual. Most VOC sensors I’ve encountered over the years do report in ppb, not ppm. But now I’m wondering if I had it backwards in my code above. Multiplying by 1000 would give ppt, not ppm. We’d divide by 1000 to get to ppm.

I’ll go and edit my posts accordingly.

I got ppm from Eurotrnics sales blurb, do not entirely trust that.
But here’s an interesting find
https://forum.z-wave.me/viewtopic.php?t=34089

Same problem, VOC of say 0.4 in ppm is correct but different display wanted.

In OH, it would be good to see the actual updates here. But on the face of it the OP has only to put ppb in his metadata if that’s what they want.

Sorry for the late answer.
Thanks for the Blockly, this works fine.
@rlkoshak I hadnt thought that the item type is that much important, because I can change it as I want without any visible effect so this was not so important

In general, the unit is not important. Dot. I dont know what they really want to tell ppb/ppm.
But the manual explains the values only from 0 to 5500. So with that big scale a 0,XXX is not really important.

But all in all I decided to change to another system which is easier to handle.

So apologies for wasting your time. Have a nice day!