Piston executes from top to bottom?



this is a common one i see in posted examples, so thought a short note on it might be useful.

pistons execution almost always starts at the top and stops at the bottom, unless there is an exit statement somewhere in the piston that gets executed conditionally or unconditionally.

there is one exception to this, that is a timer statement. when executing a timer, the piston execution starts with the every and stops at the end every.

as an example if this is the piston:

if contact changes to open
    send notification
end if
every day at 11pm
   while contact is open
      send notification
      wait 2 mins
   end while
end every
if contact changes to closed
   play chime
end if

when the piston is triggered by a contact open or close trigger event, the piston will be executed from top to bottom but SKIP the every block. the only time the every block will be executed is when the time condition in the every block becomes true. at that time, ONLY the every block will be executed and NOT the rest of the piston.

so, if you are using an empty every block, expecting the whole piston will be executed - please dont. :slight_smile:

other questions on this? please ask away on this thread.

How are pistons executed?
A quick note on piston execution
EcoBee Battery Level
Piston is skipping statements. Energy Monitor
Help turning three pistons into one
Open garage door and then close it with no Motion
Timer scheduling and global variable offset
How to override motion sensor light?
My "vacation lights" turning on at wrong time
pinned #2


Where is the question? :wink:


He was baiting you :stuck_out_tongue_winking_eye:


didnt want to point to any single example, but now seen a few of these :slight_smile:


Here’s a question:

In the following piston, will the outlet turn on if the switch is off? Meaning, will the piston move on to run the second if statement, if the first is false?

IF switch is on
THEN set bulb to 100%
end if

IF door is open
THEN turn on outlet
end if


Switch is OFF, Door is open

8/31/2017, 4:31:21 PM +176ms
+354ms	║Turning on outlet

Switch is ON, Door is open

8/31/2017, 4:31:08 PM +330ms
+233ms	║Setting to 100
+268ms	║Turning on outlet

Both devices were subscribed to, events from either one causes the IF statements to get evaluated.


So you can put as many IF statements as you like, and have them all simultaneously evaluated, as long as each one has an exit (end if). Is that correct?


“Simultaneous” requires one of the following two:

a) they have no waiting tasks (wait, fade, etc)
b) if they have a waiting task, they are set to run async (meaning next statements won’t wait)

But yeah, you can add as many statements (be them IF, FOR, WHILE, TIMER, ACTION, etc) in as many depth levels as you want. Open world. You can have IF after IF, IF inside IF, any combination you can think of.

   do something;
   wait 2 minutes;
   do something else;
end if;

   do something more;
end if;

In the example above, if condition1 is true, something will be done and then 2 minute wait starts. After two minutes, something else is done, then if condition2 is true at that time, something more will be done. Note that the second if waited on the first if to finish.

If condition1 is false, but condition2 is true, something more is done immediately.

Setting the first if as async will change the behavior:

If the first condition is true, something will be done, then a wait for 2 minutes is initiated. At the same time, if condition2 is true, something more will be done. Two minutes later, something else will be done as well. Note that the second if got executed without waiting for the first if to finish. That is what async does, they run in “parallel”.


This clears a lot up. So the waiting tasks are the only things that will really hold up a piston. Without any waiting task, all conditions run parallel by default. Waiting tasks seem to be a unique thing here, sort of changing the rules for everything after it.


SmartApps are single-threaded so nothing in them really runs in “parallel”. They are still executed in a sequence, top-to-bottom, but so rapidly they seem “parallel”. Anything waiting complicates the execution sequence, you are right.


If I understand this correctly, if there are two IF statements either can fire the piston although both would be evaluated from the top down. Example:

    condition1 (based on presence)
    set variable mode = 1;
    set variable mode = 0;
end if;

    condition2 (based on time of day)
    set variable mode = mode + 2;
end if;

So if condition2 fires because of the time of day, does condition1 get evaluated also? I’m trying to set mode to 0 to 3 based on a combination of conditions.


yes it is. if you dont want that, there is a way to avoid it where the piston still executes from top to bottom but not all of the conditions get evaluated.


Perfect. Thanks for the prompt answer.


So anytime any IF statement in a piston evaluates to true, by default, the entire piston runs top to bottom? I think that explains why I’m having trouble with a couple of my pistons. Thanks!


But if i want to use a “and”.
Meaing that i only want the second if to evaluate if the first one is true.
But i want the third to start no matter what.


I have a piston for my backyard patio lighting that evaluates for several triggers, a few of which are “every day at $sunset”, “every day at $midnight” and “every day at $sunrise”. How can I force the piston to run from top to bottom given these timer events?



you cant with the every statement. use if time happens ... instead.


I looked around for this information for a long time but didn’t find it. I am in the infancy of developing pistons and hope to use many of the examples. this tool is extremely powerful.

OK, so what i am reading on another reply is that a piston will be checked for execution based on what is subscribed to in the piston. It can also set the subscription to ‘never’ for my definition of ‘inactive’ on my initial post.

Thanks folks for this great information.


I’m not sure what other post you are referring to…but if you set a piston to never subscribe to events (as in all of them) then it will just sit there doing noting. If that’s what you want, then you should just Pause the piston instead of unsubscribing from all the events.

It is valid to tell a piston to not subscribe to certain Events if you want to use them as conditions rather than as Triggers (there’s another thread which details the use and difference between those).