Event not happening after WAIT


1) Give a description of the problem
Corner Lamp not turning off after WAIT

2) What is the expected behavior?

  1. Motion sensor turns on corner lamp
  2. 60 seconds elapse
  3. Corner lamp turns off

3) What is happening/not happening?

  1. Works correctly
  2. Logs show 60 seconds elapsing
  3. Corner lamp stays on, log shows no command sent to turn it off

**4) Post a Green Snapshot of the piston

5) Attach any logs (From ST IDE and by turning logging level to Full)

+0ms ╔Received event [Myhub].time = 1550668032010 with a delay of -886ms
+165ms ║RunTime Analysis CS > 20ms > PS > 129ms > PE > 17ms > CE
+168ms ║Runtime (39606 bytes) successfully initialized in 129ms (v0.3.109.20181207) (167ms)
+169ms ║╔Execution stage started
+171ms ║╚Execution stage complete. (1ms)
+172ms ╚Event processed successfully (172ms)
2/20/2019, 8:06:15 AM +602ms
+1ms ╔Received event [F-Motion Sensor].motion = inactive with a delay of 972ms
+125ms ║RunTime Analysis CS > 15ms > PS > 97ms > PE > 13ms > CE
+127ms ║Runtime (39605 bytes) successfully initialized in 97ms (v0.3.109.20181207) (125ms)
+129ms ║╔Execution stage started
+139ms ║║Comparison (enum) inactive changes_to (string) active = false (1ms)
+141ms ║║Cancelling condition #2’s schedules…
+143ms ║║Condition #2 evaluated false (7ms)
+144ms ║║Cancelling condition #1’s schedules…
+145ms ║║Condition group #1 evaluated false (state changed) (10ms)
+148ms ║╚Execution stage complete. (20ms)
+150ms ╚Event processed successfully (149ms)
2/20/2019, 8:06:11 AM +558ms
+2ms ╔Received event [F-Motion Sensor].motion = active with a delay of 1010ms
+303ms ║RunTime Analysis CS > 28ms > PS > 259ms > PE > 15ms > CE
+305ms ║Runtime (39613 bytes) successfully initialized in 259ms (v0.3.109.20181207) (302ms)
+306ms ║╔Execution stage started
+317ms ║║Comparison (enum) active changes_to (string) active = true (1ms)
+319ms ║║Cancelling condition #2’s schedules…
+320ms ║║Condition #2 evaluated true (8ms)
+322ms ║║Cancelling condition #1’s schedules…
+323ms ║║Condition group #1 evaluated true (state changed) (11ms)
+326ms ║║Cancelling statement #3’s schedules…
+443ms ║║Executed physical command [Corner Lamp].on() (113ms)
+444ms ║║Executed [Corner Lamp].on (115ms)
+449ms ║║Executed virtual command [Corner Lamp].wait (1ms)
+451ms ║║Requesting a wake up for Wed, Feb 20 2019 @ 8:07:12 AM EST (in 60.0s)
+457ms ║╚Execution stage complete. (150ms)
+459ms ║Setting up scheduled job for Wed, Feb 20 2019 @ 8:07:12 AM EST (in 59.994s)
+469ms ╚Event processed successfully (468ms)

If a solution is found for your question then please mark the post as the solution.


Is this a light that you want to stay on when there’s motion or you want the fixed 60 seconds turn off as soon as the motion is detected?

The motion going inactive is canceling the task which is why it’s not turning off.


The general rule of thumb for motion sensors is something like this:

IF Motion changes to active
    Then Turn on light

IF Motion stays inactive for 60 seconds
    Then Turn off light

This ends up being two triggers in the same piston, but the 60 seconds countdown restarts each time it sees motion.

Alternatively, if you want it turning off after 60 seconds even if there is still motion detected, then you can use your original piston. Just select the “With” block and set “Task Cancellation Policy” to Never.


My circumstance s actually more complex. But I wanted to get this building block in-place before building further.

The concept: normal light operations during normal hours. During night/sleep hours, a night light scenario where
A. If the light has been operated by anything other than this piston, this piston does not interfere with it.
B. If the light has been turned on by this piston’s motion sensing, it stays on for 7 minutes and then turns off.
C. If motion is sensed once during that timeframe, the countdown to turn-off does not change.
D. If motion is sensed twice during that timeframe, the light stays on - and it starts the countdown again.

I guess I’m surprised that, since never in the piston do I specify anything about motion turning inactive, the sensor going inactive would turn off the scheduled action.


If you look at the Task Cancellation Policy of the task, that is the default WebCoRE action. If you want it not to cancel then you’ll have to override it.


Another way to explain this:
If the conditions that initiated a block of code changes, then that block is no longer true, so by default, it will stop running that block. Setting TCP to Never can override this default behavior.

In laymans terms, “IF motion changes to active” is only true for a brief moment, and then goes back to false


Not to nitpick… but then why does the 60-second countdown continue? If the block ceases to run when the condition that triggered it changes, then the countdown should also cease?

I get that this is how it was configured. I just can easily see (as in this instance) where you’d want a trigger to set a chain of events in motion, AND have it run even though the trigger condition changes, AND still have instances where you’d want the task to cancel.


The way schedules works is the countdown you see is created at the beginning of the 60 seconds… (the piston is not running during that Waiting period) All it knows is that is should wake up in 60 seconds and continue. If the status changes during the wait, the piston will not be aware of that until the timer has expired. (or another trigger in the same piston fires) It is at that point that the piston sees that the trigger is no longer true, so it will not complete that block of code.


My educated guess would be that you likely have too many triggers in your piston. I generally limit my pistons to a single trigger, or at most two if they are the opposites of each other.

Such as:

Hallway changes to active
Hallway stays inactive for X minutes

Remember, each and every trigger runs thru the code from top to bottom, so the more triggers (lightning bolts) you have in a piston, the more likely there will be an overlap in logic. I can get much more complex pistons with only a single trigger in play.


Another problem in this piston is that after the wait, it comes back in and executes from top to bottom. Since the motion is no longer changing to active, the if is false so it doesn’t go in to execute the ‘off’. At least that is my understanding of how it works. @WCmore will correct me if I’m wrong (but then I will learn :slight_smile: )


Which makes the answer a variable. It always seems to come back to that, doesn’t it.
So the piston should read:

  1. IF
  2. Motion Sensor’s motion changes to active
  3. Set variable1 to true
  4. With lamp,
  5. turn on
  6. Wait 60 seconds
    (during this time, the sensor will change to inactive)
  7. If variable1 = true
  8. Turn lamp off
  9. Set variable1 to false

That would at least allow other possibilities. Perhaps
7. If variable1 = true
8. And global_varX = false
9. Do something else

Etc. just thinking out loud, as it were.


After I try your logic above , I had 2 results :

  • IF ( 7 ) in IF ( 1 ) > lamp stay on.
  • IF ( 1 ) , IF ( 7 ) > lamp turn off when motion change to inactive, the wait no work ???


Line 7, 8 and 9 will never run unless you place them outside the IF, or follow my earlier suggestion and set “Task Cancellation Policy” to Never.


@trandzung, here is the general practice for Waits with motion sensors.


Does anybody have a good example that shows this behavior? I’ve tried testing this and can’t make it happen. My general idea was:

  1. if switch changes to on
  2. send message 1
  3. wait 5 minutes
  4. send message 2
  5. end if

I then flipped the switch on, waited about 10 seconds, and flipped it off. When it came back from the wait, it didn’t notice that the switch was no longer on, and it did send message 2. Is there something different between switches and motion?


Yes, when I use the " wait “, usually I go to " general practice " first. Depending on requirements, I set " Task Cancellation Policy” as a Default or Never.

But I still don’t understand , what is the role of " variable1 " on this logic ?


Personally, I love variables, but they are not needed at all for motion sensors unless you are doing some funky coding, or trying to squeeze in a bunch of triggers into a piston for some reason.


Here is a basic piston showing you how a change to the trigger can stop events after the Wait.

In this test, I manually turned on the switch at 4:37:54, and then turned it off 7 seconds later.

Notice every single line ran except for line 18 (after the Wait)

(if lines 14-18 had “Task Cancellation Policy” set to Never, it would have run the entire block)


OK, that makes sense. Without TCP set, I would assume that a new trigger event would kill the code after the wait. If you didn’t have that second if block, and ran the same test, you’d get the “complete” message. The whole piston isn’t re-run after the wait, just the remaining code…right?


Yes, it picks up where it left off, and continues with any statements that it finds true