So I am trying to run this equation in openhab, in dsl it all works except needing to have a negative base in an exponential expression. It doesn’t like that, it just returns NaN. My question is, can Javascript actually handle having a negative base? Or can some other scripting language handle that? Supposedly from what I can find Javascript can handle it but I am also having trouble trying to reformat the rule in Javascript, I have yet to mess with it as Rulesdsl has served my purposes well.
var Number tempf = BigChief_SHT3XTemperature.state as Number
var Number tempc = (tempf - 32)/1.8
var Number hum1 = BigChief_SHT3XHumidity.state as Number
var Number hum2 = hum1/100
//var Number mathe = -Math.E
var Number numeratora = -0.0054*tempc
var Number numeratorb = 2.87+numeratora
var Number numeratorc = (-Math.E) ** numeratorb.floatValue
var Number denominator = Math.log(hum2.floatValue)
var Number numdenom = numeratorc/denominator
var Number emc = Math.pow(numdenom.floatValue,0.72463768115)
SoybeanEMC.postUpdate(emc)
You can’t just tack a negative sign onto a variable and have it negate that variable. You hacve to multiply by negative one. That’s going to be the case in almost any language, including Rules DSL and JavaScript.
Ok, this line of code that I commented out I thought returned the negative of Math.E when I sent that directly to the item I am updating to so I figured it was fine.
//var Number mathe = -Math.E
But I will try your suggestion and see where that gets me! That being said the rule still failed once I got the line where I needed to actually make that number the base of the exponential expression.
var Number numeratorc = (-Math.E) ** numeratorb.floatValue
I tried as written above and below, neither worked. The reasoning for the above solution was that in my reading I found that you could force it to accept the negative base if you wrote it that way, but that may have been for Javascript now that I think about it.
var Number numeratorc = Math.pow(-Math.E, numeratorb.floatvalue```
Trying to recall my high school algebra, but IIRC a negative base in an exponential expression will only work if the exponent is an integer. What physical property are you modeling? Are you sure the expression is not = -1 * (positive number) ** (number)?
Sorry, I haven’t tried it yet. You had asked what I had tried so I was just letting you know what I had already tried, I will try and get it tried out this evening.
So I got some time to try @rlkoshak suggestion, and I’m getting an error, maybe I’m not utilizing it correctly yet.
Type mismatch: cannot convert from Number to double; line 9, column 358, length 5
When I run the rule in this configuration.
var Number tempf = BigChief_SHT3XTemperature.state as Number
var Number tempc = (tempf - 32)/1.8
var Number hum1 = BigChief_SHT3XHumidity.state as Number
var Number hum2 = hum1/100
var Number mathe = (Math.E * -1)
var Number numeratora = -0.0054*tempc
var Number numeratorb = 2.87+numeratora
var Number numeratorc = Math.pow(mathe, numeratorb.floatValue)
var Number denominator = Math.log(hum2.floatValue)
var Number numdenom = numeratorc/denominator
var Number emc = Math.pow(numdenom.floatValue,0.72463768115)
SoybeanEMC.postUpdate(numeratorc)
This is the line in question that is giving that error in the logs.
var Number numeratorc = Math.pow(mathe, numeratorb.floatValue)
I thought when I first started I thought I read that it was best not to assign units because it made it easier to deal with them, apparently that’s not actually the case. Maybe that was the case on an older version?
I didn’t call to floatValue on Math because of a misunderstanding on how it works, I thought if the number didn’t change I didn’t need to call floatValue.
That being said, I called floatValue and received another error.
var Number tempf = BigChief_SHT3XTemperature.state as Number
var Number tempc = (tempf - 32)/1.8
var Number hum1 = BigChief_SHT3XHumidity.state as Number
var Number hum2 = hum1/100
var Number mathe = (Math.E * -1)
var Number numeratora = -0.0054*tempc
var Number numeratorb = 2.87+numeratora
var Number numeratorc = Math.pow(mathe.floatValue, numeratorb.floatValue)
var Number denominator = Math.log(hum2.floatValue)
var Number numdenom = numeratorc/denominator
var Number emc = Math.pow(numdenom.floatValue,0.72463768115)
SoybeanEMC.postUpdate(numeratorc)
And here is the error in logs.
2023-12-19 11:13:50.498 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'SoybeanEMCCalculation' failed: Character N is neither a decimal digit number, decimal point, nor "e" notation exponential mark.
Units have always been useful, particularly when you want one unit and the sensor is giving you a different unit.
In OH 4 you can set the unit metadata on BigCheif_SHT3XTemperature to °C and no matter what the binding is providing the Item will always carry °C. In addition or instead of that in a rule instead of doing the conversion you can use
var tempc = (BigCheif_SHT3XTemperature.state as QuantityType<?>).asUnit('°C.).floatValue
If the Item is already °C you’ll get the state of the Item. If it’s °F, it will convert it to °C for you.
You did change it though. You multiplied it by -1. In Rules DSL the result of all calculations is a BigDecimal which is a Number, not a primitive.
You’ll need to add some logging of the intermediate calculations to narrow it down to a specific line of code that is generating the error and what all the operands on that line are prior to the error.
Ok, I will change that going forward. That is true, I did change that, I’ll clarify, I thought floatValue was for if it was constantly changing, not just if I defined it as a variable and changed it from its original state, but never to change again. I am still getting this error.
2023-12-19 22:04:35.182 [WARN ] [b.core.model.script.actions.BusEvent] - Cannot convert 'NaN' to a state type which item 'SoybeanEMC' accepts: [DecimalType, QuantityType, UnDefType].
With this code.
var Number tempf = BigChief_SHT3XTemperature.state as Number
var Number tempc = (tempf - 32)/1.8
var Number hum1 = BigChief_SHT3XHumidity.state as Number
var Number hum2 = hum1/100
var Number mathe = (Math.E * -1)
var Number numeratora = -0.0054*tempc
var Number numeratorb = 2.87+numeratora
var Number numeratorc = Math.pow(mathe.floatValue,numeratorb.floatValue)
// var Number denominator = Math.log(hum2.floatValue)
//var Number numdenom = numeratorc/denominator
//var Number emc = Math.pow(numdenom.floatValue,0.72463768115)
SoybeanEMC.postUpdate(numeratorc)
I’ve isolated it to this line.
var Number numeratorc = Math.pow(mathe.floatValue,numeratorb.floatValue)
When I run the rule like this, without Math.E being negated, then it runs fine. It’s something to do with having the base being a negative I think.
var Number tempf = BigChief_SHT3XTemperature.state as Number
var Number tempc = (tempf - 32)/1.8
var Number hum1 = BigChief_SHT3XHumidity.state as Number
var Number hum2 = hum1/100
//var Number mathe = (Math.E * -1)
var Number numeratora = -0.0054*tempc
var Number numeratorb = 2.87+numeratora
var Number numeratorc = Math.pow(Math.E,numeratorb.floatValue)
// var Number denominator = Math.log(hum2.floatValue)
//var Number numdenom = numeratorc/denominator
//var Number emc = Math.pow(numdenom.floatValue,0.72463768115)
SoybeanEMC.postUpdate(numeratorc)
I should add that numeratorb, which is the exponent of the line that’s giving me trouble, is not a whole number, it varies based on temp but it should always be a decimal. If that makes a difference.
Out of curiosity (I’m retired and like to see if my memory from 50 years ago is still good ) I ran this on an online calculator yesterday (20 C and 70% humidity) with positive base and
got something like 28 and change. Log of number less than one is also negative so numdenom will also be a positive number.
No, how much it is changing has nothing to do with anything. Data in programming have types. Certain operations only work with certain types. Math.pow() only works with primitive double type variables. If you don’t have a double (a Number is not a double) you have to convert it to a double (in this case by calling floatValue).
NaN stands for “Not a Number”. The result of one of your calculations is producing a non-real number as a result.
I’m sure your knowledge is still better than mine, I haven’t used this math in at least ten years, so that’s not helping the situation! I can make it all work fine if I do the calculation on a calculator, it’s just when I take it into RulesDSL that I get the issue. Here are the values I’m getting from each line of my equation with 20c temp and 70% humidity.
var Number tempf = BigChief_SHT3XTemperature.state as Number
//var Number tempc = (tempf - 32)/1.8
var Number tempc = 20
//var Number hum1 = BigChief_SHT3XHumidity.state as Number
var Number hum1 = 70
var Number hum2 = hum1/100
//var Number mathe = (Math.E * -1)
var Number numeratora = -0.0054*tempc
var Number numeratorb = 2.87+numeratora
// var Number numeratorc = Math.pow(Math.E,numeratorb.floatValue)
// var Number denominator = Math.log(hum2.floatValue)
//var Number numdenom = numeratorc/denominator
//var Number emc = Math.pow(numdenom.floatValue,0.72463768115)
SoybeanEMC.postUpdate(numeratora)
numeratora = -0.10800000000000001
numeratorb = 2.762
So I do have a positive exponent, with negative Euler’s number as the base, and that’s where things go wrong.
Ok, thank you for clarifying! So I read over that and this is close to what I am running into but not exactly I don’t think, nothing there is quite exactly what I have…
If
the first argument is negative infinity and the second argument is greater than zero but not a finite odd integer,then the result is positive infinity.
Euler’s number is infinite(and negative in this case), and the exponent(second argument) is 2.762(with 20c as tempc), but when I do this calculation on a calculator I get a negative(presumably)infinite number instead of a positive…
I’m probably not being clear. You cannot do that and I’m sure that is not what was intended by wherever you found the formula.
Another algebra principle is exponents take priority over multiplication. So do e^2.762, then multiply by -1. It sounds like your calculator has this figured out.
Another option is to multiply both top and bottom by -1, an identity. The -1 goes away on the numerator and the denominator is -1 * log (.7).
That ensures the base nomdenom is also positive. Log (.7) is negative. As to coding that, @rlkoshak is the master of all languages in use by OH.
Lastly log tempc once you start using real data. As number for a number:temperature may return a Rankine value.