I had to remove it and add it again, and now: Yes! Thank you!
But now of course it becomes clear, that my rule is a desaster.
If the power consumption changes and in the same moment I want to calculate the average power consumption over the last ten minutes of course this number is below any threshold because the media player just started.
Is it possible to use: if(Verbrauch_Kodi.averageSince(now.plusMinutes(10)) > 2)
Instead of minusMinutes in this situation? I guess no because persistence has no numbers for the future, only for the past.
So what would be the best attempt here? Put a timer to wait for 10 minutes after a change in powerconsumption?
The usual approach, which you will find talked about here in the context of monitoring e.g. washing machine cycle, would be to detect when power has reduced to below a threshold.
By implication, the interest in the past when power changes is therefore “was it just working?” and so maybe it’s now stopped.
At that point you might start a timer, or count some more below-threshold reports, before deciding that yes it really has stopped.
That’s what I want to achieve. How do I count more reports for let’s say 10 more minutes, before deciding to switch off the plug?
As mentioned I want to make sure the Mediaplayer had really shut down and not only performed e restart or had a fluctuation in Power Consumption. Therefore, the trigger should be a reduced power consumption as in my rule example. But instead of immediately shutting it down if consumption is below the threshold of 3 Watts, I want the rule to check for 10 minutes after the initial loss in power consumption (trigger) if the consumption stayed below the threshold. How can I achieve this?
If power below threshold -
If your timer already exists, do nothing
Otherwise, make a new timer.
The timer is scheduled for ten minutes time to do your “off” actions.
If power above threshold, cancel any existing timer.
I guess that is your instantaneous power measurement Item?
It’s the .state you are interested in.
Be careful about what you compare it with, if your Item has UoM units.
You don’t need the persistence/average; if the reading rises above threshold it cancels the timer.
If it hasn’t done that in ten minutes, it commands OFF.
Use a unique name for your timer handle variable, so that you don’t accidentally introduce a clash when you write some other timer-using rule later.
Don’t forget to declare it in global namespace.
May I ask somebody to help me check my rule and to correct it?
I made some adjustments, especially with the [|] and () and {}, as VisualStudio reported some errors. For now it seems to be working, but I am not sure with the timer still:
var Timer timerKodiabschalten = null
rule “Kodi Stromzufuhr abschalten wenn ungenutzt”
when
Item Verbrauch_Kodi changed
then
if(Verbrauch_Kodi.state < 2){
if (timerKodiabschalten===null) {
timerKodiabschalten = createTimer(now.plusMinutes (10), [ |
if(Verbrauch_Kodi.state < 2){
Kodi_Energiezufuhr.sendCommand(OFF)
}
])}
}
else if(Verbrauch_Kodi.state > 2){
timerKodiabschalten?.cancel
timerKodiabschalten = null // cancel timer if power consumption raises
}
end
rule "Kodi Stromzufuhr abschalten wenn ungenutzt"
when
Item Verbrauch_Kodi changed
then
logInfo("test", "My rule begins")
logInfo("test", "key value " + Verbrauch_Kodi.state.toString)
if(Verbrauch_Kodi.state < 2){
if (timerKodiabschalten===null) {
logInfo("test", "starting timer")
timerKodiabschalten = createTimer(now.plusMinutes (10), [ |
logInfo("test", "timer begins")
logInfo("test", "key value " + Verbrauch_Kodi.state.toString)
if(Verbrauch_Kodi.state < 2){
Kodi_Energiezufuhr.sendCommand(OFF)
}
])}
}
else if(Verbrauch_Kodi.state > 2){
logInfo("test", "timer aborting")
timerKodiabschalten?.cancel
timerKodiabschalten = null // cancel timer if power consumption raises
} else {
logInfo("test", "unexpectedly here")
}
end
Have a think about edge cases.
What happens if Item state is exactly 2? I think you can do away with else-if() and just use else for cancelling.
What happens after 10 minutes is up the first time? Can you ever create a new timer later? Hint - you need the timer code block to set its own handle to null before exiting, to clear the way for a later run.
Thanks. I’ll try with some logging.
For the unlikely case of consumption being exactly 2 I added >= to the cancel condition.
One last question regarding:
Isn’t the timerKodiabschalten = null line meant to do so? Or do you mean I should include this line also in the first condition where the timer actually gets used? If so, where would I have to add it?
I tested the as in my last post for several on and off cycles and it seems it is working. But I’ll improve it with your tips.
Yes. You will see this technique used in most of the timer examples.
Generally at the end of the timer’s execution block, set the timerKodiabschalten handle back to null, so that it becomes easy for subsequent runs of the rule to detect “there is no timer now”.
That would allow a timer execution to finish without doing anything, if power over threshold, but also not nulling the handle.
When the timer finishes, whatever the outcome, you’ll want to clear the way for the next time.