Good afternoon everybody. I’m using a rule to update a proxy element because the SHELLY EM resets the energy total whenever there is no voltage. Although the rule works, there is often no alignment between the data actually recorded by SHELLY and the one stored in the proxy element and the proxy element contains a value less than ten units. Do you have any idea why? I add that this happens whether I use “received update” or “changed” as a trigger on the shelly element.
Thanks
The rule is
rule "Store Shelly Value"
when
Item ShellyItem received update
// or Item ShellyItem changed
then
val Number deltaValue = 0
val Number actualValue = (ShellyItem.state as Number).floatValue
val Number previousValue = (ShellyItem.previousState.state as Number).floatValue
if (actualValue > previousValue) {
deltaValue = actualValue - previousValue
} else if (actualValue < previousValue) {
deltaValue = actualValue
}
val Number totalValue = (ShellyProxyItem.state as Number).floatValue + deltadeltaValue
ShellyProxyItem.postUpdate(totalValue)
end
There is no guarantee that the Item hasn’t changed state by the time the rule ran. If you want the exact value of the Item that triggered the rule, sue the implicit variables.
Persistence is particularly slow. It is unlikely that the new state of the Item has been saved by the time you call previousSate so you’re getting two states ago, not the previous one. Again, use the implicit variables.
Hi Rikoshak, thanks for your answer but can you give me an example?
I’ve had a look but can’t figure out how I’m supposed to reference these implicit variables.
Perfect.
I modified the rule as follows and it seems to work.
A thousand thanks.
rule "Store Shelly Value"
when
Item ShellyItem changed
then
val Number deltaValue = 0
val Number actualValue = (newState as Number).floatValue
val Number previousValue = (previousState as Number).floatValue
if (actualValue > previousValue) {
deltaValue = actualValue - previousValue
} else if (actualValue < previousValue) {
deltaValue = actualValue
}
val Number totalValue = (ShellyProxyItem.state as Number).floatValue + deltadeltaValue
ShellyProxyItem.postUpdate(totalValue)
end
In Rules DSL you end up working against yourself when you force the type of the variables.
val deltaValue = 0
val actualValue = (newState as Number).floatValue
val previousValue = (previousState.state as Number).floatValue
In Rules DSL never use primitives unless absolutely necessary. Furthermore, because you’ve forced the type of the Item to be Number you are immediately undoing the conversion to a primitive float.
val deltaValue = 0
val actualValue = newState as Number
val previousValue = previousState.state as Number
The absolutely most expensive thing you can do in Rules DSL is math with primitives. I once created a relatively simple equation with only four operands which loaded and ran in milliseconds when everything was kept as Number but if forced to be primitives added minutes to the openHAB start time.
val totalValue = (ShellyProxyItem.state as Number) + deltadeltaValue
This particular rule isn’t that much of a problem. But if you’ve more complex rules you might get a performance boost, particularly at OH restart, if you apply these rules for Rules DSL.
You might be happier with one of the other rules languages. As OH moved forward Rules DSL is being left steadily behind. And it lacks lots of standard language features (e.g. true functions) and has weirdness (see my reply above) that means it really should only be treated as a legacy language.
I doubt it will ever go away so long as upsteam Xtend is maintained. But if you are not a programmer, Blockly is a better choice and if you are a programmer anything but Jython is a better choice.
I think my questions are very much related to this topic and since Rich opened the discussion towards other languages, I follow up here… I hope you don’t mind.
I am working on the javascript version of a rule updating a proxy item to ensure proper cumulative counters (e.g. for shelly items which get resets from time to time)…
I have a couple of questions:
I seem to not be able to extract the value without quantity type from the implicit event.itemState and event.oldItemState… I have tried .rawState or .float but none seem to work… Am I missing something?
If I keep the itemState and oldItemState as QuantityTypes, I then seem to not be able to compare the difference between both to check if it is greater than 0…
This is what I tried when manipulating quantity types:
var newValue = event.itemState
var oldValue = event.oldItemState
var increment = newValue.subtract(oldValue)
if (increment.greaterThan(0)) {}
But greatedThan is not available on increment…
Since I could not get this to work, I tried to calculate the increment on “raw values” without units, but was not able of doing it either (.float or .rawState do not exist apparently on event).
I hope I make sense… I’m trying to get the rule as generic as possible so that it can work on multiple types of cumulative indexes.