Rule / Persistence: Shut off Power after 5min of low Power-Consumption

Maybe it got lost in copy/paste, but your createTimer is missing vital delimeters for its code block, | [ ]

Your cancel section should test to see if the timer is non-null before trying to cancel, else that will error.
There is a shortcut for that -

Ok. I added it and the shortcut, hopefully in the right way, as I did not fully understand how to use both

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

I tested it with no luck. It seems the command is not triggered.

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

Add some diagnostics temporarily

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. :wink:

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”.

My rule now looks like below. If you agree I have not to fear major errors comming up, I could mark this as solves


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)
                timerKodiabschalten = null
            }
            ])}
    }
    if(Verbrauch_Kodi.state >= 2){
        timerKodiabschalten?.cancel
        timerKodiabschalten = null   		// cancel timer if power consumption raises
    }
end

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.

	        timerKodiabschalten = createTimer(now.plusMinutes (10), [ |
                if(Verbrauch_Kodi.state < 2){     
	               Kodi_Energiezufuhr.sendCommand(OFF)
                }
                timerKodiabschalten = null
            ])}

Thanks. Sometimes the logic still strikes me. :smiley:

It happens. I spent an hour last night looking at a rule where a simple
if ( X or Y ) didn’t do what I expected because of an oversight.