Device events vs. timer events in webCoRE

Pistons run due to events that the piston has subscribed to. Most commonly these events are devices like switches, or sensors that report updated status as changes occur to the device.

Another reason a piston can run is a timer. In this case the piston asked to be woken up in the future with a time event. The event happened because the piston requested the event to happen in the future.

The subtle but important point here is

  • device events occur because the device had a state change - the device generated the event (and the piston subscribed to it using an if statement with a trigger comparison).

    • the subscription is set during piston save [or resume] and does not need to be refreshed. (the trigger comparison (if tracking), needs to be evaluated for the trigger comparison value to be updated in webCoRE (ie switch changes) in future checks).
  • timer events occur because the piston requested a future wakeup.

    • the timer event has to be rescheduled ('re-created' or 'refreshed') when the timer fires for the next event to occur in the future.

So here is piston using a timer event (time happens daily in the if statement). Let's look at what is going on:

Screen Shot 2022-03-14 at 4.05.51 PM

The if statement at line 12 is asking for a wakeup at sunset.

The if statement at line 17 is asking for a wakeup at 10:00 PM

When you save a piston, webCoRE does a dummy evaluation of the piston, looking for device subscriptions (there are none in this example) and subscribes to the device/attributes, and for timer requests (there are two), and schedules the timers for the future.

  • during this dummy run, webCoRE goes thru every statement looking for the above and initializes them.

  • so immediately after saving the piston, there are two timer requests pending. webCoRE in the IDE shows the next to run timer request in the piston display at the top of the screen:

Note the Next scheduled: ....

So what happens when the piston runs:

  • the piston receives an 'event' with attribute time with the value of the current time in ms.

    • this event has a reference to which statement number requested the wakeup, and this is how webCoRE knows how to handle the if statements during execution
  • the piston starts its execution at the top and proceeds step by step.

  • lets says the timer is for sunset; webCoRE knows the timer that fired was for line 13 (statement #2 ), so that if statement will evaluate true (when evaluated).

  • when webCoRE gets to line 17 (statement #5) it knows it started for a timer on line 13 (statement #2), so this will evaluate false.

So the result is we logged the message at sunset.

What is unique about timers is when an if statement executes with a timer request time happens daily, webCoRE is actually doing two things for this if statement:

  1. it is scheduling the next timer request to happen in the future for this statement (if it is not already setup)

  2. it is evaluating true/false if the reason we are running now is because this timer fired.

So it is important that timer statements are crossed / evaluated when that timer fires if the timer is a trigger, so that the next timer will be scheduled to run

  • if you don't evaluate/cross the statement when that timer fires, the next timer for that trigger request will not be scheduled, and you will not be woken up next time....

So here is another piston, with a warning.

What is going on:

  • The timer check/request (line 19, statement #4) is nested below an if statement (at line 14)

    • the issue is that sometimes line 19 will be evaluated, and other times it won't.
      • for example, if we saved this piston on Saturday at 3:00 PM (so this is when initialization ran)

        • webCoRE during initialization will set a timer to run at 3:33PM Saturday

        • at 3:33PM Saturday, the timer will fire, and the piston will start execution from the top and evaluate line 15, which will return false (because today is not Monday or Friday)

          • the piston will exit having never crossed/evaluated line 19, so the piston will not schedule a new 3:33PM timer (for the next 3:33 PM which would be Sunday)

This error is the general form of nesting triggers, but with a nasty side effect that future timer will not be scheduled until line 19 is evaluated again (or you edit the piston, or pause/resume the piston).

So what should have been done here:

  • There are [at least] a few choices:

    • You could have used a piston level restriction.

      • The reason this works is that piston level restrictions, if they are false, will still do a dummy run through of the entire piston (which would request the next timer wakeup, much like after saving a piston or resuming it)

      • You have to be ok with the entire piston not running because of the restriction...

    • You could have used an every statement

      • As discussed in other tips, every statements have some things to be aware of.

    • you could add a condition check to the if time happens if statement (after the time happens daily comparison)

      • this likely would be an expression using the function weekdayname()

    • You could have used a timer restriction:

Note in this example the if time happens daily we added the timer restrictions directly to the time happens daily

This is what that setting looks like in the IDE:

When this example piston executes, it will evaluate time happens daily statement (line 15) so that the future timer is scheduled, and the status of the existing timer is evaluated for this piston execution.

So requests for timer events need to be treated like trigger comparisons:

  • keep them at level 1 (looking left to right)

    • avoid nesting them
  • ensure they are crossed on each execution

Again timer event requests are using a trigger comparison (like Time happens daily)

Timer condition comparisons can be nested as you wish.



Download the Hubitat app