I literally have a clonning version of my server and in one server the rule works flawlessly for over 2 years now and on the cloned version, it does not!
This is surreal.
So the rule is as basic as this:
rule "Irrigation rule"
when
Time cron "0 0 0,8,12,16 * * ? *"
then
if (Humidity.historicState(now).state < 90) {
Irrigation.sendCommand(ON)
offTimer = createTimer(now.plusMinutes(2), [|
Irrigation.sendCommand(OFF)
])
}
end
This is it. If a certain number store in MySQL (in this case the humidity) is lower than 90, then it starts the irrigation for 2 minutes. As simple as that.
Iâve already put a lot of logInfo and it does show the number properly. There is no âcomparisonâ error any other error. It simply does not go inside that âifâ condition.
I even tried to âforceâ that number to be an integer and it did not worked as well.
Iâd first question if your rule retrieves from MySQL at all. Humidity.historicState(now)
will retrieve from whatever you have set as your system default persistence service.
In OH3, that will be rrd4j unless you have changed it.
You can be explicit in your rule - are you using via JDBC? Humidity.historicState(now, "jdbc")
Next thing to consider is Item type. Is this a Number type? Or perhapsa Number:Dimensionless? Has it been changed from one to the other in the past, perhaps?
You can get some really nasty effects involving Number:Dimensionless types (usually expressed with a percent unit â%â) if it involves numbers without a unit - these get an invisible unit âONEâ and are treated as ratios.
Just as the quantity â50 %â is not equal to numeric â50â, neither is the quantity â50 ONEâ, even though it formats to â50â.
The item is indeed this, but it is stored in the database as a double. So as we can see on that logInfo, it shows exactly the number 85.
If I only output directly the item state (OutsideHumidity.state) it actually shows the % in front of the number, just as we see it in the item. But that is why I am grabbing the number that I have in my persistance.
The fact that itâs stored in the database as a double is irrelevant. All numbers are stored as a double.
Persistence does not yet support units of measurement. So whatâs going on is exactly what @rossko57 described. The value is restored. Thereâs no unit provided so the default unit is chosen. The default unit for Number:Dimensionless is ratio which is the one unit that doesnât actually have a visible unit. Exactly 85 in this context is exactly 85 ONE. OH doesnât show the units for a ratio but that doesnât mean itâs not there.
The flow is like this.
The database is queried and it returns 85
OH getâs that number and sees that the Item is a Number:Dimensionless meaning itâs a QuantityType. So it goes down that path instead of the path for plain old Numbers
OH looks at the State Description metadata to see if you have configured the desired units to use. You havenât.
OH uses the default units based in the category (in this case Dimensionless) and your configured locale. In this case thatâs ONE which doesnât actually have a representation.
Unfortunately, OH does not have the ability to do math with QuantityTypes and non-QuantityTypes. Both operands need to be one or the other.
Humidity.historicState(now).state is a QuantityType. 90 is just a plain old number. So you either need to convert the QuantityType to a plain old number:
Humidity.historicState(now).state.floatValue
Or you need to convert the 90 to a QuantityType. Iâm not actually sure how to do that for a ratio, maybe something like one of the following:
90|
new QuantityType(90, '')
90|ONE
new QuantityType(90, 'ONE')
One of those four options ought to work.
But wait, this is a Humidity Item. Itâs not a ratio, itâs a percentage. So letâs make it behave like one.
Make sure youâve defined State Description on this Item and set the units to %.0f %%. Theoretically that should make OH use percentage instead of ratio as the units (see step 3 above).
Convert the 90 to a percentage QuantityType using 90|%.
If that doesnât work, we may need to force it in the rule.
NOTE: You may need to cast the state to a QuantityType for Rules DSL to see the right methods: e.g. (Humidity.historicState(now).state as QuantityType).toUnit('%').
Yes, it is finally working and I didnât knew, at all, these differences. I always assumed the number came straight from MySQL âas isâ and not being transformed âin the backgroundâ by OH. This was very educative and it actually made light on other things that were happening on other rules.
So, in case others want to see the final result, I ended up placing this before the rule:
val Number humidity = (OutsideHumidity.historicState(now).sate as QuantityType).toUnit('%')
Then I just had to do this immediately in the start of the rule:
Just to be clear though. Itâs not being transformed, per se.
historicState.state returns an org.openhab.core.types.State Object just like MyItem.state does. There are all sorts of different State types: QuantityType, OnOffType, PercentType, DateTimeType, etc.
The type of the state depends on the type of the Item. A Number:Dimensionless carries a QuantityType and no other (ignoring UnDefType which youâd never get back from persistence anyway). So when you want to get the state of an Item at some point in the past for a Number:Dimensionless, the only thing that makes sense is to get a QuantityType.
Note, I strongly recommend setting the State Description for this Item so that itâs treated as a percentage by everything in openHAB rather than keeping it as a ratio. If you already have, this might be a limitation with persistence right now and itâs worth taking note of this behavior.
By the way, have you noticed that instead of âstateâ I wrote âsateâ by mistake? I mean, how can this be working if I got it wrong? Does it asume â0â in case there is no valid information?
Also, Iâve tried what you suggested, which actually makes total sense but I am just being very noob here. Iâve tried different combinations and I am not being able to make it work. Am I placing it in the right place here?
Make sure to undo anything youâve done on the link. That will probably break something.
Itâs not working if itâs sate in the code itself that way. When it encounters that line it will complain something like âHistoricState does not have a sate propertyâ.
When units were first introduced, we had to put them as âstringsâ just as you show. blah > 50|"ÂșC"
That still works.
Since then, a DSL enhancement allows ânakedâ units after the pipe. blah > 50|ÂșC
but beware - some units include characters that will upset the rules parser, the obvious one being / which the parser wants to use a maths operator. bleh > 50|km/h error, parser wants to divide 50km by variable h bleh > 50|"km/h" okay
Other rules languages have their own methods and limitations (the pipe | designator is unique to DSL)
Itâs probably not the correct symbol °C (as usually used) looks a bit different from ÂșC (copied from your posts). I see a little line under it in my browser.