previousState will never be reliable unless you persist everyChange (which is not usual with rrd4j). Even then I’m not sure it works at all well with rrd4j.
The rule trigger event provides some implicit variables -
newState looks useful.
previousState exists if you have a change type trigger.
What makes you think they are ‘empty’?
No, you must have a simple trigger and do any comparisons withing the body of the rule.
Where I say Previous State and State are empty, I meant I have left them null in the Rules UI - I could have been clearer there!
So it sounds like while previousState exists if there’s a change type trigger (and I am getting a value here) it’s not going to be the right thing with rrd4j persistence.
I will test newState in case that returns something interesting but otherwise I guess I need to use a different persistence for items I want to use in rules that will depend on the new value being different by a percentage to the previous value.
What would be ‘best practice’ to achieve this? Rrd4j is working well for everything so far, so I don’t want to add more services than I need.
How about an second item just to hold the last value? On change of the monitored item I could compare the current value with the stored one and do whatever I want the rule to do, and finally update the ‘last value’ item with the current value. That looks like it’d work on paper but feels like I’m over engineering something that might already be possible more simply.
previousState is a stand alone variable, not relying on any persistence at all. It contains the previous state of the Item that triggered the rule.
By implication, it only exists if the rule was triggered by an “changed” trigger.
Usage - logInfo("test", "prev " + previousState.toString)
newState is a stand alone variable that contains the current state of the Item that triggered the rule. The same as someItem.state, it is of use e.g.with group based triggers where you might not easily know who triggered the rule. logInfo("test", "now " + newState.toString)
someItem.previousState() is unrelated to the above, it is a persistence method of each Item.
Thinks; this might not be the right approach, depending on what you are trying to do. What happens if you get ten 1% increases, do you care?
I think maybe it’s because I’m calling a script from the rule rather than embedding the script IN the rule.
previousState always returns the same value in my tests but not the same string:
Energy changed from 31/01/2021, 11:52: TPLink_Power -> 2042.263 to 2042.263 W
I will move the script to the rule script editor instead.
EDIT:
Same response there. With the script contained within the rule UI script editor the output to logging is the same. previousState contains the same value as state
Could you show us what you are doing? previousState (the implicit variable) cannot be the same as the triggering Item state when you use a ‘changed’ rule trigger.
Are you using the release version of OH3.0 ?
I’m still a bit concerned about what you are trying to achieve, rather then the mechanism.
If your sensor reports changes at say 1% intervals you will never detect a 10% change by using any kind of previousState
A spa turns its heater on periodically to maintain water temperature. The smart plug it’s connected to posts power consumption every 30 seconds which is very slightly different every time, usually by < 1 W.
When the heater comes on the power consumption jumps from c. 45 W to about 2.2kW, sometimes in two or three steps, but the first is always the largest. By looking for an large increase or decrease, I can monitor the heater activity.
I found the UI-based rule caused memory heap exceptions (or some combination of what I was doing with Math within the rule) so I moved it to a .rules file.
The key was still getting that previousState value, thanks again!
Not perfectly elegant but it works - mostly. I opted for a couple of value conditions rather than a percentage change, after a few tests, which results in more than one notification sometimes. For example here, there are two notifications because the increase was > 900 twice in a row.
00:46:32.666 [INFO ] [.openhab.core.model.script.spaEnergy] - Spa energy from 43.649 W to 1165.208 W, difference 1121
00:46:32.680 [INFO ] [.openhab.core.model.script.spaEnergy] - The spa heater turned on
00:47:02.715 [INFO ] [.openhab.core.model.script.spaEnergy] - Spa energy from 1165.208 W to 2168.106 W, difference 1002
00:47:02.729 [INFO ] [.openhab.core.model.script.spaEnergy] - The spa heater turned on
00:47:32.957 [INFO ] [.openhab.core.model.script.spaEnergy] - Spa energy from 2168.106 W to 2040.815 W, difference 127
00:48:03.166 [INFO ] [.openhab.core.model.script.spaEnergy] - Spa energy from 2040.815 W to 2039.934 W, difference 0
This is the rule:
rule "Spa Energy Change"
when
Item SpaTPLink_Power changed
then
var int energyDiff = Math.abs(((SpaTPLink_Power.state as Number) - (previousState as Number)).intValue)
logInfo("spaEnergy", "Spa energy from " + previousState + " to " + SpaTPLink_Power.state + ", difference " + energyDiff)
var String emailMessage = null
if ((energyDiff > 1000) && ((SpaTPLink_Power.state as Number) > 900))
{
emailMessage = "The spa heater turned on"
}
else if ((energyDiff > 1000) && ((SpaTPLink_Power.state as Number) < 900))
{
emailMessage = "The spa heater turned off"
}
if (emailMessage !== null)
{
logInfo("spaEnergy", emailMessage)
var String messageSubject = "Spa heater update"
var String messageBody = emailMessage
val mailActions = getActions("mail","mail:smtp...etc")
mailActions.sendMail.... etc
}
end