Dynamic Cron Strings in Rules?

I’m relatively new to this, and want to know if there is a way to trigger rules with a cron script at differing times each day depending on other variables. For instance, if it’s hot out, I want my pool pump to start at 10 am, but if it’s cold, it doesn’t need to start until noon. On the rules examples page, there’s an example of a rule triggering at sunset using timers, but the coding for that is fairly complicated and it seems like it would take a lot of CPU cycles for counting. What I’d like to do is something like:

rule "Start Pool Pump"
    when
        Time cron "0 0 " + Pool_Start_Time.state + " 1/1 * ? *"
    then
        blah blah blah
end

Is this, or something like it, possible? I suppose I could have the rule run once every hour and use an if statement to turn the pool on if a condition is met, but something like the above would still be more streamlined, and I may want triggers more precise than on the hour.

Thanks!

There is not. To schedule things to happen based on an Item’s state you need to use Timers.

Rule triggers are based on events, not states. You can’t use an AND in a rule trigger either for the same reason.

Timers do not consume CPU counting. They go to sleep until the scheduled time and consume no resources while sleeping. Beyond that, almost never will CPU be a concern on even on board computers like the Raspberry Pi. Do not go out of your way to optimize for CPU.

There are a number of approaches you could take to do this.

  • Set up two rules one for ten and one for noon. If the ten rule runs the pump set a flag. When the noon rule runs check the flag and it if isn’t set run the pump
  • Create one rule that runs at ten. If the temp is too low set a timer to go off at noon and run the pump. Otherwise run the pump now
  • Generate some sort of event to run the pump rather than using cron.

There are many more.

Thanks for the reply, and good to know about the timer really being a sleep function. I’ll read more about how to set up timers, but it sounds like my best option is to set a rule to trigger at the earliest I’d possibly want the pool to turn on, check the temperature (or whatever else), and then sleep until the desired time (the first option won’t work for my setup because I could want the pool to start any time between 10 and 12…and that’s just one example of what I have in mind.

I’m curious on your third option – can you give an example of other events that I could use to trigger a rule at specific (but different from day to day) time?

Let’s say you want the pump to come on two hours after dawn. Using the Astro binding you can create a Switch that will receive an ON command 2 hours after the sun comes up at your location. See

There is an Alarm Clock example (search the forum) that lets you schedule a time in the sitemap and have a rule trigger at that time. It is complicated and a little hacky but it appears to work.

There might be some other type of event that you can use to determine when to start the pump, a motion sensor, presence detection, etc.

Personally I separate the day into a set of time periods (Morning, Day, Evening, Night) which are driven either by set times (e.g. Night starts at 11:00 pm) or astronomical events (e.g. Evening starts 90 minutes before sunset). Then I drive my rules based on those time periods. So I would probably add a Midmorning time period that starts 120 minutes after sunrise and ends at noon. My rule would trigger when TimeOfDay changes to “Midmorning” where I would check the temp and run the pump or set a flag. I’d have another rule that triggers when TimeOfDay changes to “Day” and if the flag wasn’t set run the pump.

I set up my automation this way to increase the simplicity of my environment. Rather than separately keeping track of all sorts of different timers and time periods for different things I separated all that into its own independent module and drive schedules by changing a TimeOfDay Item.

Thanks!

Hi all,

What about

rule "Open windows and balconies"
when
	 Time cron "0 * * * * ?"  //every minute
then
        //if date is equal to the one that I want, which is set as global variable then
              //Do the cool thing
end

could be another very simple idea, no?

I went with the timer approach, which seems to be working nicely. Basically, I have a rule that triggers every morning at 1am, when the system is started, and when my dynamic pool start time variable changes. When any of those things happens, it creates a timer that ends at the pool start time which then turns the pool on. I have a similar rule to turn the pool off. As is evident from my earlier comments in this post, I don’t fully understand system resource use, but I would think that running the rule every minute and calculating whether it was the appropriate time would be more of a draw.

Here’s the rule if you’re interested:

rule "Turn Pool On"
    when
            Time cron "0 1 1 1/1 * ? *"
            or Item PoolTimeStart changed
            or System started
    then
            var DateTime starttime = parse(PoolTimeStart.state.toString)
            if (starttime.minusDays(0).isAfter(now.minusDays(0))) {
                    createTimer(starttime.minusMinutes(0)) [|
                            sendCommand(PoolMode,ON)
                            Thread::sleep(500)
                            if (Today_High.state > 70) {
                                    sendCommand(PoolSolarHeat,ON)
                            } else {
                                    sendCommand(PoolSolarHeat,OFF)
                            }
                    ]
            }
end