Calculating Humidity, math problem

Hi, Im trying to calculate relative humidity with the formula shown in the image below:
relhum

I wrote the rule like this:

rule "eed4"
when
      Item t2 received update
then

	 ed4.sendCommand(6.112 * Math.exp((17.502*t2.state as DecimalType)/(240.97+t2.state as DecimalType)))
      ew4.sendCommand(6.112 * Math.exp((17.502*t4.state as DecimalType)/(240.97+t4.state as DecimalType)))
      h4.sendCommand((((ew4)-0.6687451584*(1+0.00115*t4.state as DecimalType)*(t2.state as DecimalType - t4.state as DecimalType)) / ed4 ) * 100)
end

items:
Number h4 “[%.1f]”
Number h5 “[%.1f]”

Number ed4 “[%.1f]”
Number ed5 “[%.1f]”
Number ew4 “[%.1f]”
Number ew5 “[%.1f]”

what am I doing wrong? I can not get it to work
thanks

What isn’t working? How do you know it isn’t working?

1 Like

I put h4 in sitemap, nothing appears and other rules stop working after adding this block of rule

Check your console log - any errors there? What’s the definition of item t2 and t4? Are they Number items?

1 Like

Your formula for h4 uses ew4 and ed4 as if they were variables, but I don’t think they are. It looks to me like you’re writing the values for ew4 and ed4 directly to the Item, not a variable within your code, so your formula for h4 should extract that value from the Items again.

1 Like

If you want to update an Item’s state, then just update it. Sending commands adds overhead for no reason.
ed4.postUpdate( ...

but

This is doomed to failure.
sendCommand (and postUpdate) is asynchronous. The request gets sent away to openHABs events bus, triggering any bindings or rules that are interested, eventually updating the actual Item state. It takes time, a few milliseconds, but real time.
Meantime, your rule does not stop and wait.
If you try to use ed4 (you meant ed4.state I suppose) in the same rule you will probably get the “old” state from before the update was requested.

That’s okay, you already know what you sent - use that directly.

var x = (complicated calculation)
myItem.postUpdate(x)
var z = (more calculation) * x
etc.
1 Like

Also, you only supply one argument to the Math.exp() function, which is certainly going to produce errors, probably already when the rule is loaded, so it’s not going to run at all. Always check the logs for errors when working with rules.

The correct calculation on the first row should be (also changed to assign the value to a variable instead of trying to send a command to the Item as pointed out above):

var ed4 = 6.112 * Math.exp(Math.E, (17.502*t2.state as DecimalType)/(240.97+t2.state as DecimalType))

Math.E is Euler’s number (the e in your equations above), a mathematical constant, which need to be included in the calculation.

1 Like

It’s worth pointing out that there is a whole binding dedicated to doing these sorts of weather calculations. hww3 / org.openhab.binding.weathercalculations / Downloads — Bitbucket Unfortunately it doesn’t appear to be an official binding yet.

A big calculation like that is likely to take quite some time for openHAB to parse. I’ve seen just one line like the above add 10 minutes to the amount of time it takes to parse and load a .rules file like that on a fast machine. On an RPi it could take 30 minutes or more. Are you sure that what’s happening isn’t just that it’s waiting on the rule to be loaded? What’s the CPU doing when you change this file?

In addition to all of the other recommendations made here I suggest you break the calculation up. Any time you have a big calculation all on one line like this it becomes all but impossible to debug and understand.

  • Use variables and do each part of the calculation separately and gradually build up to the full calculation.
  • Log out these intermediate calculations and check these to make sure they make sense.
1 Like

thanks a lot, I’m using var, postUpdate, change Math.E part and use cron timer for decrease load on system as follows:

var Number ed44
var Number ew44

rule "calced44"
when
      Time cron "0 0/1 * 1/1 * ? *"
then

    ed44 = 6.112 * Math.exp(Math.E, (17.502*t2.state as DecimalType)/(240.97+t2.state as DecimalType))
    ew44 = 6.112 * Math.exp(Math.E, (17.502*t1.state as DecimalType)/(240.97+t1.state as DecimalType))
    h4.postUpdate((((ew44)-0.6687451584*(1+0.00115*t1.state as DecimalType)*(t2.state as DecimalType - t1.state as DecimalType)) / ed44 ) * 100)
end

It works, as @rlkoshak said it loads slowly when system boots for the first time, it takes about 8-10 minutes I think…after that it works

No need to make the variables global, unless you need to access them in another rule, which I suppose you don’t?

Just out of curiosity, what kind of temp sensors or service are you using that can supply wet bulb temperature, but doesn’t supply humidity measurements?

2 Likes

Thanks.
I think above code has problem I think in Math.exp section, I change it to Math.pow now the calculation is done correctly, Math.exp return false result.

var Number ed44
var Number ew44

rule "calced44"
when
      Time cron "0 0/1 * 1/1 * ? *"
then

    ed44 = 6.112 * Math.pow(Math.E, (17.502*t2.state as DecimalType)/(240.97+t2.state as DecimalType))
    ew44 = 6.112 * Math.pow(Math.E, (17.502*t1.state as DecimalType)/(240.97+t1.state as DecimalType))
    h4.postUpdate((((ew44)-0.6687451584*(1+0.00115*t1.state as DecimalType)*(t2.state as DecimalType - t1.state as DecimalType)) / ed44 ) * 100)
end

I’m using pt100 type k sensor, because our environment temperature is above 120 C, so I can not use normal humidity sensors.
So we build a wet bulb temperature sensor tank for sensing wet bulb temperature with pt100 and calculate it via formula.

Where’s that, Venus ?

2 Likes

As @rlkoshak suggested, break your maths into shorter lines, using interim variables (they are free of cost). The long parse time has something to do with how deep the “nesting” goes in each line.

1 Like

LOL
No, we use OH for controlling High Temperature wood dryer kiln, the temperature profile varies from 50 C to 130C, so for example, we can not use dht22.

You can make it so it only takes seconds to load if you, as I and rossko57 have suggested break the calculations up. Essentially what you have is a O(N!) algorithm (N factorial or 1234…*N) to check the types of all the arguments of each line of code. So that first line is something like 7! or over 5040 operations, just to check the types. And each of the type checks likely has hundreds or thousands of instructions so it really blows up in terms of processing. The last line is 9! which is 362880. Notice how just adding two operands to that last calculation took it from just over 5000 checks to over 350000 checks. That’s over 405000 operations just to check the types are correct on those three lines of code.

That’s why it blows up so easily. But if you broke it up into multiple lines of code with fewer operands you can reduce that by orders of magnitude.

    val edw = [ t |
        var denominator = 240.97 + t
        var numerator = 17.502 + t
        var exponent = numerator / denominator
        var pow = Math.pow(Math.E, exponent)
        return 6.112 * pow
    ]
    val Number t2Var = t2.state as Number
    val Number t1Var = t1.state as Number    

    val ed44 = edw.apply(t2Var)
    val ew44 = edw.apply(t1Var)

    val numeratora = 1 + .00115*ew44
    val numeratorb = ed44-ew44
    val numerator = edw44 - 0.6687451584 * numeratora * numeratorb
    val div = numerator / ed44
    h4.postUpdate(div * 100)

Now let’s count up the type checking operations.

2! + 2! + 2! + 1! + 1! + 2! + 1! + 1! + 1! + 1! + 3! + 2! +4! + 2! + 2! = 50

By splitting the above into separate lines we took something that took well over 400k operations to check the types down to 50 operations. That’s a 4 orders of magnitude reduction and will mean the difference between taking 8-10 minutes and less than a second to load.

In addition, it gives you more of a chance to log out and see the intermediate operations which could be logged for debugging when the calculation does work.

Finally, this rule will explode if t1 or t2 are not Numbers but are instead NULL or UNDEF or if they carry Units of Measurement. By breaking it up like this you now have one place (where the local variables t1Var and t2Var are defined) where you can check for that.

Note that changing the cron period does absolutely nothing to reduce the load caused by the rules as written. The problem occurs when the .rules file is loaded, not when it runs.

3 Likes