Understanding Scheduling Timers


#1

1) Give a description of the problem
I wrote an example piston to try to understand how scheduling works. I thought I understood, but clearly I do not.

The piston is set up to initialize only once (by manually running it) … it then attempts to set up 6 timers each one minute apart (with an offset of 30 seconds) …

2) What is the expected behavior?
I thought I would see 6 timers being set, but in fact only one timer is scheduled and it is for the furthest out timer, not the next timer.

3) What is happening/not happening?
Only the last furthest out timer (+6 minutes) is scheduled.

4) Post a Green Snapshot of the pistonimage

5) Attach any logs (From ST IDE and by turning logging level to Full)
(PASTE YOUR LOGS HERE BETWEEN THE MARKS THEN HIGHLIGHT ALL OF THE LOGS SND CLICK ON THE </> ICON TO FORMAT THEM)


#2

One note … set the NextChange to 1 so that it only attempts to initializes the timers once.


#3

In general, webCoRE only schedules one wakeup per piston. (The nearest one)
When that one runs, it sets up the next schedule.

You have set the index to begin at 5 (counting down)… So:
5 x 60 seconds + 30 seconds = 5.5 minutes.

With your current wording, the first schedule will be 5m 30s after it runs.
When it loops again, the next one will be an additional 4m 30s later
The next cycle, it will schedule 3m 30 seconds down the road.
etc…

The last loop will execute at the 18 minute mark


#4

with this piston It actually makes no difference whether the loop is up or down … i played with it both ways to try to figure it out…

Sometimes I see (not with this piston) “… with x more jobs pending” … does that mean those are never other timers waiting to trigger?

Let me reduce the seconds to try to confirm the behavior you are suggestion (so I dont have to wait so long)

Thanks!

James


#5

@WCmore … unfortunately no change in behavior … (i reduced the time to 15 secs between timers) … yes, the last timer ~5*15 secs is set … but after it triggers there are no more timers in the queue … so its done.

I don’t think the other timers are actually getting set in the loop, only the last one (or first, not sure) actually are set.

Is this the expected behavior and is there another way I should be doing this?

My desire is to schedule a piston to run at some preset intervals that are determined programatically. I’ve written another piston that pops a timer off a queue after each trigger until no more remain, but I would have thought this is built into webcore (i must be doing something wrong or don’t understand something.

James


#6

I am no means an expert on looping, but I just tested a loop in a piston, repeating ten times every 5 seconds. After each iteration, I see this in the log:

Setting up scheduled job for X (in 4.991s), with 1 more job pending


temp

(Switch 1 was OFF during testing to force the 5 second wait)


#7

Thanks WC - but this is a very different case where the WAIT holds execution at that point for some period … what I am trying to do is to retrigger the piston from the top.

James


#8

Yea, it was just a test for the re-scheduling… (it schedules a wakeup once per wait)

Also interesting to note that when looping, webCoRE does not know HOW many waits will happen (beyond the next one) because the new code has not run yet


On your piston, your only trigger is inside the loop.

My general rule of thumb is to keep my triggers top level (far left - un-indented) and I keep the conditions and logic inside that block.


#9

Thanks - Im trying to understand the operation of these timers … there are times when I want to force the execution of the piston from the top at specific times. This is easy to do when the times are static, but I am setting the times based on a data table.

At this point, Im moved on to use my own timer list and starting the next timer when the previous one triggers. But still would like to understand why this example doesn’t work.

James


#10

I use a variable to do this all the time.

Wait {integerVariable} seconds


#11

You can also use variables as an adjustable time for execution like this:

temp

but the piston will not notice a change in the global until after it runs.
(so you’d have to account for that in your coding)


#12

The way I understand a Wait is that it pauses execution at that point in the piston (I have observed that behavior) … so I cannot use a wait as I am trying to restart the piston from the top.


#13

Just a tiny recap since I am not sure all of my responses registered:

webCoRE only schedules one wakeup per piston. (The nearest one)


I think this is because your only trigger is inside the loop, instead of outside it. I have never worked on a loop with a trigger inside. (only conditions)


In my opinion, using an integer (or time) variable is the way to go


Then your trigger needs to be at the top. (outside the loop) Just be aware that depending on your wording, the new trigger may cancel and start a new loop from square one, OR it may run a second loop asynchronously.


You are correct.


I think maybe I should also clarify one more peculiar behavior.

If you have a top level (non-indented) line that says:
Time happens at {timerTmp}
That time/schedule will not be seen or set until the piston is running.

In other words, to let a new variable time be seen by webCoRE, and scheduled for a wakeup, the piston has to run first, then see the new variable, then finish the code, and then set the wakeup to the new time.

To get around this, I sometimes cheat a bit and throw in a line like this.

every day at 8:00 AM
do
end every

(Yes, that block is completely empty)

This simple command simply forces the piston to schedule a wakeup based on the current variable.


#14

Yes I use similar constructions as well. Effectively, an empty “If time happens at:” does the same thing.

The mystery remains … I believe it must be due to the fact that the same “if time happens” statement is being used to schedule multiple events. Only one of the events is queued and the others are ignored.

Thanks! Hopefully someone can enlighten us :slight_smile:


#15

I think I know what is happening, but I would need to see your piston to clarify…


#16

I believe this only happens when you have multiple triggers in the piston… (in other words each trigger may schedule one wakeup, from what I have seen)


Is this a condition statement, or a trigger statement? There’s a huge difference in the way it plays out


I would love to see this code please… It goes against everything I have ever seen with webCoRE, but would love to learn more.


#17

Hi @WCmore - Thanks for the help … I think we should return to the original issue with the code posted at the top… I’ve done many tests and it does appear that timers are not always scheduled (or queued as a job) when the “If Time Happens” is done as a for loop. If you download that code you will see what I mean.

If I placed 2 or more “If Time Happens” directly inline with each other (i.e. not in a for loop), the timers are all scheduled and queued as one would expect.

Not sure why this limitation exist, or if there is an obvious way around it.


#18

I have explained every issue you have mentioned… Why won’t you post a green snapshot of the things you just mentioned? It makes no sense, and neither of us can learn if it is kept hidden.

For clarification, a trigger is a split moment in time. On the other hand, a condition can be a long stretch of time. I suspect you may have your terminology mixed up… Perhaps you meant “conditions inside a nested IF”.

Consider this simple piston:

IF the front door changes to open  <-- Trigger (split moment in time)
    Then Wait 5 seconds
    IF Light changes to on         <-- Trigger (split moment in time)
        Then send SMS
    END IF
END IF

Can you see that you could test this piston a thousand times, and the SMS will never be sent unless the light is turned on exactly 5000 milliseconds after the door opens?? Triggers do not belong inside an IF trigger. It is better to put conditions inside the IF.

The proper way for this quick example is this:

IF the front door changes to open  <-- Trigger (split moment in time)
    Then Wait 5 seconds
    IF Light *IS* on               <-- Condition (long lasting)
        Then send SMS
    END IF
END IF

This method would work everytime!

If you are unwilling to go into any details with the statements you made in the last couple of posts, then I will disregard all those statements, and will encourage others to ignore it as well, or they will have a nightmare with their pistons.

Personally, I would rather learn and teach good practices. Since your pistons aren’t working, perhaps there is some truth to what I have been saying…


#19

Have you downloaded and tried the piston I referenced? I am very familiar with conditions and triggers … and that is a tangent issue to what I am talking about. It sounds like you may not want to help out here which is fine. I am just trying to understand how Webcore deals with the case I posted.

Thanks!


#20

It will not download. Probably corrupted