Piston cancelling execution, no idea why


#1

1) Give a description of the problem
I have a piston which looks at the motion sensor’s activity.
When it goes into inactive it is set to wait 60 seconds to turn off the light that was previously on.
This assures that if there is motion again within these 60 seconds, the piston will stop executing and start again when the motion is inactive so that the light stays on until I am gone.

Maybe the way I am handling this isn’t the best way to accomplish what I want to do?

2) What is the expected behavior?
Turn off the light if below steps are completed:

  • motion changes to inactive
  • wait 60 seconds

3) What is happening/not happening?
Piston stops before 60sec wait ends. Even though there was no new motion.

4) Post a Green Snapshot of the piston

5) Attach logs after turning logging level to Full
5/11/2020, 10:13:49 AM +430ms
+1ms ╔Received event [Sensor Hal Boven].motion = inactive with a delay of 68ms
+227ms ║RunTime Analysis CS > 18ms > PS > 137ms > PE > 71ms > CE
+229ms ║Runtime (38700 bytes) successfully initialized in 137ms (v0.3.110.20191009) (227ms)
+230ms ║╔Execution stage started
+243ms ║║Comparison (enum) on is (string) on = true (2ms)
+245ms ║║Cancelling condition #12’s schedules…
+246ms ║║Condition #12 evaluated true (10ms)
+247ms ║║Cancelling condition #1’s schedules…
+248ms ║║Condition group #1 evaluated true (state changed) (12ms)
+252ms ║║Comparison (enum) inactive changes_to (string) inactive = false (0ms)
+254ms ║║Cancelling condition #2’s schedules…
+255ms ║║Condition #2 evaluated false (6ms)
+256ms ║║Cancelling condition #1’s schedules…
+257ms ║║Condition group #1 evaluated false (state changed) (8ms)
+259ms ║╚Execution stage complete. (29ms)
+261ms ╚Event processed successfully (261ms)
5/11/2020, 10:13:10 AM +783ms
+2ms ╔Received event [Sensor Hal Boven].motion = active with a delay of 83ms
+153ms ║RunTime Analysis CS > 21ms > PS > 62ms > PE > 70ms > CE
+156ms ║Runtime (38693 bytes) successfully initialized in 62ms (v0.3.110.20191009) (153ms)
+158ms ║╔Execution stage started
+173ms ║║Comparison (enum) off is (string) on = false (1ms)
+175ms ║║Cancelling condition #12’s schedules…
+176ms ║║Condition #12 evaluated false (12ms)
+178ms ║║Cancelling condition #1’s schedules…
+179ms ║║Condition group #1 evaluated false (state changed) (15ms)
+182ms ║╚Execution stage complete. (24ms)
+183ms ╚Event processed successfully (183ms)


#2

Looking at the logs, what is actually happening is ‘changes to inactive’ is evaluating as false for some reason. The piston doesn’t seem to have cached the earlier change to active. There must be something I still don’t understand about how things work.

I think that if you subscribe to events you ought to make sure they can be evaluated when they come along, otherwise why create explicit triggers? So personally I’d lose the restriction and have:

if motion sensor changes to inactive
and
dimmer is on

Whether that is just personal taste or there is a technical reason for it, is another question.


#3

Hmm, okay I’ll give that a try.
You mean like this then?


#4

Yeah that is what he was saying, although, and it’s a personal preference of mine and I don’t think it matters in this case…

I like to have my trigger by itself. The trigger is what starts things off, I then set up my conditions. I would put the SWITCH is ON below the THEN with another IF and leave the trigger by itself.


#5

Yes that is what I meant. I couldn’t really see anything wrong with your original piston but as it clearly didn’t work I took that to mean my understanding is incomplete.

What I do know is that when you do a ‘changes to inactive’, the piston compares the ‘new’ value carried in the event data with a cached ‘old’ value. However I’ve never figured out exactly when the ‘old’ value gets updated. So I was wondering if the previous instance of the piston (where motion has just changed to active) never evaluating the trigger was the problem.


#6

Actually, the problem with your piston is that after the 60 second wait, the ‘changes to inactive’ is no longer true. It just IS inactive. I suggest moving the wait in with the turn off and set that with to ‘Never cancel tasks’. Then you should be good to go.

EDIT: Sorry, got pulled away. Should look like this:

with
   Dimmer 1
do
   wait 60 seconds
   turn off
end with

Also, I forgot you want to cancel if activity resumes so suggest you add a separate trigger:

if dimmer 1 changes to active
then
   cancel all pending tasks
end if

Not sure how you turn the dimmer on but you could also add that to the block above.


#7

The truth of ‘changes to inactive’ is only determined when the comparison is evaluated. After the 60 second wait the piston wakes up, starts at the top and immediately fast forwards past the wait and so doesn’t evaluate the condition again.

The problem shown in the logs is that the piston receives the motion active event followed a little while later by the inactive event. However when the piston evaluates ‘changes to inactive’ it is returning false so it never gets to the ‘then’ block to even start the wait. For some reason it hasn’t recorded that the previous event was ‘active’ and so doesn’t think the value has changed.


#8

I suspect you will have success if you totally remove the “ONLY WHEN” line.
(webCoRE is smart enough to not send an off command to a device that is already off)

IE, this should do what you want:

IF Sensor 3's motion stays inactive for 60 seconds
    Then Turn off Dimmer 1
END IF

The “Turn off” will be cancelled anytime motion is detected.


#9

aha this is exactly what I needed and it simplifies the code.
Thanks all for your replies. I learned something new today :slight_smile: