Schedule time based action within rule

I’m searching for a possibility to create a time based event within a rule execution. I’ll try to give an pseudo code which is hopefully self-explanatory:

rule "time based event"
when
Item openhab_item changed
then
if (openhab_item.state < 10) {
>>>>> send command to openhab at 08:00 a.m. <<<<<
} else {
>>>>> send command to openhab at 11:00 a.m. <<<<<
}

I’d like to schedule an action depending on rule execution. The only way I know right now is to create timer like this one:

createTimer(now.plusSeconds(10))

But I want to set a specific / absolute date and time. Is this possible with openHAB 1.8.3?

Thanks!

One approach would be to turn around the checked events. Trigger on a Cron and inside the rule check if item changed.
That way you will need two rules since you can’t combine two crons in a rule (atm ).

You can make your loadvalue of your timer dynamic like this:

var Number actual_time = now.getMinuteOfDay
var Number timerload = 0

rule "time based event"
when
Item openhab_item changed
then
if (openhab_item.state < 10) 
{
	>>>>> send command to openhab at 08:00 a.m. <<<<<

	// for 8:00 -> 8*60 minutes = 480
	if(actual_time > 480)
	{
		timerload = 1440 - actual_time + 480
	}
	else
	{
		timerload = 480 - actual_time
	}
} 
else 
{
>>>>> send command to openhab at 11:00 a.m. <<<<<

	// for 11:00 -> 11*60 minutes = 660
	if(actual_time > 660)
	{
		timerload = 1440 - actual_time + 660
	}
	else
	{
		timerload = 660 - actual_time
	}
}

if(Timer_send!=null) 
{
    Timer_send.cancel
    Timer_send = null
}

Timer_send = createTimer(now.plusMinutes(timerload)) [|
            // do something! 
 			>>>>> send command to openhab <<<<<
			]

Thanks to both of you. :thumbsup:

I’ll try coding of ModuloFS which seems to fit perfectly for my recommendations. Sometimes things could be so easy and I wonder why I’m not coming up with the idea of doing it this way :nerd:

There is one error in this code.

You need to move the actual_time definition inside the rule. As it is now actual_time will get set to the time that OH loaded and parsed the .rules file and never change.

If you do not plan on reusing timerload var in other rules, it too should be defined within the rule. One should scope vars and vals as tightly as possible.

Finally, this is probably just a typo but the rule is missing the end.

If @skidepp wants the command to be sent as close to 08:00 and 11:00 as possible the milliseconds should be processed instead of minutes. Otherwise, the command could be sent as late as 08:00:59 for example.

Personally, I think the code is clearer and more precise if one uses the methods built into now instead of manipulating epoc.

var Timer timer = null

rule "time based event"
when
    Item openhab_item changed
then
    var cmdTime = null
    val eightAM = now.withTimeAtStartOfDay.plusHours(8) // 8am today
    val elevenAM = now.withTimeAtStartOfDay.plusHours(11) // 11am today

    if(open_hab.state < 10){
        if(now.isBefore(eightAM)) cmdTime = eightAM
        else                      cmdTime = eightAM.plusHours(24)
    }
    else {
        if(now.isBefore(elevenAM)) cmdTime = elevenAM
        else                       cmdTime = elevenAM.plusHours(24)
    }

    timer?.cancel // cancel timer if it exists

    timer = createTimer(cmdTime, [|
        // send command
        timer = null
    ])
end

The above code will schedule the event to take place tomorrow if openhab_item changes after 8AM or 11AM.

Note that if you reload your .rules file or restart OH your timers will be lost. You may need a System started rule to recreate the Timer in this case, depending on your use case.

1 Like