Piston runs, Events, wakeups in webCoRE, Asynchronous task blocks

webCoRE pistons (automations) typically execute statements sequentially, There are a few types of execution starts for a piston:


  • Normal execution:

    • An event occurs, Start at the top of the piston, and proceeds step by step until the end of the piston. Events that may start execution:

      • a device event the piston is subscribed to

        • like a switch going on / off, a motion or contact sensor, a presence device arriving or leaving
      • a virtual event the piston is subscribed to:

        • mode events (example away -> home)

        • hub events ( systemStart, etc )

        • a global ( @ ) or hub variable changing ( @@ )

        • a tile click event (clicking a tile in the webCoRE dashboard/IDE)

      • a timer event firing (that was previously scheduled by the piston to fire in the future)

        • timer firing (example if time happens daily)
      • request to execute a piston

        • test run (this is done from the webCoRE IDE via the TEST button

        • other pistons requesting this piston to run ( execute piston command)

        • web requests that call webCoRE endpoint to run the piston


  • Wakeup from timer wait/sleep that began in an earlier run:

    • These are resume operations from one of the above events where the piston decided to wait/sleep and later picks up where it left off and completes its operation after the wait or sleep.

      • these executions logically start at a resumption point (immediately after the wait that was executed) within the piston and continue on from there

        • in reality the piston starts at the top, and 'finds' the resumption point. This is important in that piston restrictions can cause the resumption to end execution immediately.
      • there are several commands / operations that can cause a piston to sleep/wait and then later resume:

        • wait and variants: (is most common)

          • wait random
          • wait for time
          • wait for date
        • web requests - this is due to the external server timing for the request to complete

          • http requests
          • send Email requests using webCoRE servers
          • ifttt requests
          • webCoRE built-in LIFX support commands
        • device commands that accept optional duration/transition time value (and use it)

          • setColorLevel, setLevel
        • multi-step / repeating virtual [device] commands: (where webCoRE creates the effect)

          • flash, flash Level, flash color
          • long duration fades (fade level, fade saturation, fade hue, fade color temperature)

  • An every block timer:

    • This timer event only runs the specific every block. This is described in this tip

  • An On events from block

    • These events only run the specific block

For pistons that only have normal execution, understanding operation is straight forward.

  • piston starts at the top and runs to the end or an exit command, each statement one at a time

  • you don't have to think about asynchronous settings on the piston statements


If your piston has normal execution AND wait/sleep and wakeups from earlier runs, you need to be aware of both Task Cancellation Policy (TCP) and asynchronous.

  • NOTE: The more events the piston subscribes to, the more aware/careful you need to be with TCP. A piston that can wakeup for a lot of different reasons has a lot more chances to have complexity with Task Cancellation Policy (because there are many executions of the controlling condition for the wait)

In another tip, we gave an example of how Task Cancelation Policy works.

  • In many cases its default setting does what you want.

  • The common case you need to change Task Cancellation Policy is you want to start a set of operations/commands, and you do not want them to be cancelled/interrupted by future piston executions and condition changes.


Asynchronous is typically applied to a set of tasks or actions that wait/sleep and wakeup.

  • Asynchronous allows you to have the remaining statements in the piston execute [complete operations] vs. waiting for each task/operation to complete before continuing the next.

  • why would you do this? - Parallelize a block of commands that might otherwise have made the entire piston wait.

    • suppose you want to flash a set of lights for n minutes and turn on a siren or other device at the same time.

      • typical coding might be to flash the lights for n minutes and then turn on the siren

      • however, until the flash completes (in n minutes), the piston will not turn on the siren

      • using asynchronous on this block for the flash would have the flash command start, and the piston would continue on to the turn on the siren command (while the flash continues to operate).

  • How do you set async?

    • Select the block of statements (in this case line 15 the 'with vswitch1') you start executing, but not have the piston wait for the block to complete and use the settings cog to see "Edit Action"

    • Select "Execution Method" and set 'Asynchronous'

  • If the command(s) do not cause a wait, you do not need to be concerned with asynchronous

    • and if the commands cause a wait, you only care if you want that command and other commands to get started immediately (vs. the normal sequentially).

Piston without async:

The siren command will not execute until the flash command completes its repeat (in this case likely 20+ seconds)


Piston with async:

Note the change at line 15, and the pink marking for the async block of commands. The flash command will start and the siren command will start immediately after (within a few ms).

Asynchronous sections only execute the async block (shown in pink) on a timer wakeup within the block, ie since async allowed the rest of the piston to run (immediately), the async section when it completes exits that timer execution (very much like every statements, the end of the async block logically has a 'exit').


  • yes, in this example, you could have re-ordered the siren command and the flash to run the siren command first and achieved a similar behavior in the example. However if the piston had further logic after these commands, the asynchronous would need to be used. (as always there are multiple ways to achieve your goal)
3 Likes

Future use

Download the Hubitat app