(another) motion lights control question


#1

1) Give a description of the problem
I’m trying to motion control my hall lights. I started out using an if with the motion detect, with a timer and the off state all in the same execution section, on the basis that repeated motion would re-trigger and break out of the wait, as it felt like an efficient way of doing it.
That didn’t work properly, so I copied the favoured method of triggering on active motion, and then separately watching for a period of inactivity & switching off.
I’ve still clearly not got to grips with the execution & cancellation behaviour of WebCore, as it behaves erratically - the lights always come on, but don’t always go off.

2) What is the expected behaviour?
lights go off after 10 mins

3) What is happening/not happening?
works mostly, but not always, it seems to be “white bulb 9” that fails to switch off.

**4) Post a Green Snapshot of the piston![image|45x37]

5) Attach logs after turning logging level to Full

+1ms	╔Received event [Dining Room Sensor].motion = active with a delay of 59ms
+105ms	║RunTime Analysis CS > 16ms > PS > 29ms > PE > 60ms > CE
+107ms	║Runtime (39837 bytes) successfully initialized in 29ms (v0.3.110.20191009) (105ms)
+108ms	║╔Execution stage started
+123ms	║║Comparison (enum) active is (string) active = true (1ms)
+125ms	║║Condition #2 evaluated true (12ms)
+134ms	║║Comparison (integer) 1 is_less_than_or_equal_to (integer) 5 = true (1ms)
+135ms	║║Condition #3 evaluated true (9ms)
+136ms	║║Condition group #1 evaluated true (state did not change) (24ms)
+144ms	║║Comparison (integer) 23 is_inside_of_range (integer) 16 .. (integer) 22 = false (1ms)
+145ms	║║Condition #5 evaluated false (6ms)
+147ms	║║Condition group #4 evaluated false (state did not change) (8ms)
+149ms	║║Cancelling statement #6's schedules...
+156ms	║║Skipped execution of physical command [Hall 9].on([]) because it would make no change to the device. (4ms)
+157ms	║║Executed [Hall 9].on (6ms)
+173ms	║║Comparison (enum) active stays (string) inactive = false (1ms)
+176ms	║║Comparison (enum) active stays (string) inactive = false (2ms)
+178ms	║║Comparison (enum) inactive stays (string) inactive = true (1ms)
+180ms	║║Cancelling any timed trigger schedules for condition 15
+181ms	║║Cancelling statement #15's schedules...
+182ms	║║Condition #15 evaluated false (21ms)
+183ms	║║Condition group #14 evaluated false (state did not change) (23ms)
+185ms	║╚Execution stage complete. (77ms)
+186ms	╚Event processed successfully (186ms)
30/11/2020, 23:10:48 +874ms
+1ms	╔Received event [LGF Sensor].motion = inactive with a delay of 55ms
+93ms	║RunTime Analysis CS > 16ms > PS > 27ms > PE > 49ms > CE
+95ms	║Runtime (39828 bytes) successfully initialized in 27ms (v0.3.110.20191009) (93ms)
+96ms	║╔Execution stage started
+113ms	║║Comparison (enum) active is (string) active = true (2ms)
+115ms	║║Condition #2 evaluated true (14ms)
+122ms	║║Comparison (integer) 1 is_less_than_or_equal_to (integer) 5 = true (1ms)
+124ms	║║Condition #3 evaluated true (8ms)
+125ms	║║Condition group #1 evaluated true (state did not change) (25ms)
+132ms	║║Comparison (integer) 23 is_inside_of_range (integer) 16 .. (integer) 22 = false (2ms)
+134ms	║║Condition #5 evaluated false (7ms)
+135ms	║║Condition group #4 evaluated false (state did not change) (8ms)
+138ms	║║Cancelling statement #6's schedules...
+145ms	║║Skipped execution of physical command [Hall 9].on([]) because it would make no change to the device. (4ms)
+146ms	║║Executed [Hall 9].on (6ms)
+160ms	║║Comparison (enum) active stays (string) inactive = false (2ms)
+163ms	║║Comparison (enum) inactive stays (string) inactive = true (1ms)
+165ms	║║Comparison (enum) inactive stays (string) inactive = true (1ms)
+167ms	║║Cancelling any timed trigger schedules for condition 15
+168ms	║║Cancelling statement #15's schedules...
+169ms	║║Condition #15 evaluated false (20ms)
+171ms	║║Condition group #14 evaluated false (state did not change) (21ms)
+172ms	║╚Execution stage complete. (76ms)
+174ms	╚Event processed successfully (173ms)
30/11/2020, 23:10:28 +737ms
+1ms	╔Received event [LGF Sensor].motion = active with a delay of 60ms
+90ms	║RunTime Analysis CS > 15ms > PS > 27ms > PE > 48ms > CE
+93ms	║Runtime (39828 bytes) successfully initialized in 27ms (v0.3.110.20191009) (90ms)
+93ms	║╔Execution stage started
+109ms	║║Comparison (enum) active is (string) active = true (1ms)
+111ms	║║Condition #2 evaluated true (13ms)
+118ms	║║Comparison (integer) 1 is_less_than_or_equal_to (integer) 5 = true (1ms)
+119ms	║║Condition #3 evaluated true (7ms)
+120ms	║║Condition group #1 evaluated true (state did not change) (23ms)
+127ms	║║Comparison (integer) 23 is_inside_of_range (integer) 16 .. (integer) 22 = false (2ms)
+129ms	║║Condition #5 evaluated false (7ms)
+130ms	║║Condition group #4 evaluated false (state did not change) (8ms)
+132ms	║║Cancelling statement #6's schedules...
+139ms	║║Skipped execution of physical command [Hall 9].on([]) because it would make no change to the device. (4ms)
+140ms	║║Executed [Hall 9].on (6ms)
+154ms	║║Comparison (enum) active stays (string) inactive = false (2ms)
+156ms	║║Comparison (enum) inactive stays (string) inactive = true (1ms)
+158ms	║║Comparison (enum) active stays (string) inactive = false (1ms)
+161ms	║║Cancelling any timed trigger schedules for condition 15
+162ms	║║Cancelling statement #15's schedules...
+162ms	║║Condition #15 evaluated false (19ms)
+163ms	║║Condition group #14 evaluated false (state did not change) (20ms)
+165ms	║╚Execution stage complete. (72ms)
+166ms	╚Event processed successfully (166ms)
30/11/2020, 23:09:26 +930ms
+1ms	╔Received event [LGF Sensor].motion = inactive with a delay of 74ms
+112ms	║RunTime Analysis CS > 20ms > PS > 39ms > PE > 54ms > CE
+115ms	║Runtime (39829 bytes) successfully initialized in 39ms (v0.3.110.20191009) (113ms)
+116ms	║╔Execution stage started
+133ms	║║Comparison (enum) active is (string) active = true (1ms)
+135ms	║║Condition #2 evaluated true (14ms)
+142ms	║║Comparison (integer) 1 is_less_than_or_equal_to (integer) 5 = true (1ms)
+144ms	║║Condition #3 evaluated true (7ms)
+145ms	║║Condition group #1 evaluated true (state did not change) (24ms)
+152ms	║║Comparison (integer) 23 is_inside_of_range (integer) 16 .. (integer) 22 = false (1ms)
+153ms	║║Condition #5 evaluated false (6ms)
+154ms	║║Condition group #4 evaluated false (state did not change) (7ms)
+157ms	║║Cancelling statement #6's schedules...
+166ms	║║Skipped execution of physical command [Hall 9].on([]) because it would make no change to the device. (5ms)
+167ms	║║Executed [Hall 9].on (7ms)
+182ms	║║Comparison (enum) active stays (string) inactive = false (1ms)
+185ms	║║Comparison (enum) inactive stays (string) inactive = true (1ms)
+187ms	║║Comparison (enum) inactive stays (string) inactive = true (2ms)
+190ms	║║Cancelling any timed trigger schedules for condition 15
+191ms	║║Cancelling statement #15's schedules...
+192ms	║║Condition #15 evaluated false (22ms)
+193ms	║║Condition group #14 evaluated false (state did not change) (23ms)
+195ms	║╚Execution stage complete. (79ms)
+197ms	╚Event processed successfully (196ms)

#2

this could be a couple of things…

I have 6 bulbs in my garage and #3 is acting out:)))
Everytime all 6 go off, in a second #3 comes back on:)

1 - That devices connection to hub
2 - maybe you crated some app related automation early on and forgot about it?


#3

Just poking my head in the door…your log indicates that each time, your “stay inactive for 10 minues” at line 39 is never true. At least one of the three motion sensors is active (in your log) and your outlet 4, bulb 9 and switch 6 never get turned off. I’ll take a deeper look and chime in again.

EDIT : Can you test each motion sensor individually and see how things work?

EDIT #2 : Also note that your first IF does not have a lightning bolt in the left margin. Therefore, it is not a trigger. I presume that you want motion to trigger this piston. May I suggest changing line 18 to “motion changes to active.”


#4

Normally I would recommend this too, but I think in this case, it should be fine as is.
(IE: line 39 will re-evaluate the top IF block at each change)


In your log, there is never a case where the lights should turn off. To clarify:

23:09:26 = motion = inactive (lights turn on because condition #2 is true)
23:10:28 = motion = active (lights turn on because condition #2 is true)
23:10:48 = motion = inactive (lights turn on because condition #2 is true)

In other words, they all need to remain off for 10 minutes before the final block is executed.


#5

I did consider that. It just made things clearer in my mind to have a trigger topside. :slightly_smiling_face:


#6

I know what you mean… I had the urge to say something too, LOL.


#7

One other thing to consider…

Generally speaking, I will only group similar devices (that are using the same handler).
IE: I’d never group a bulb, an outlet, and a switch together. I’d use separate WITH blocks, back to back.

My logic is, a simple “off” command may not be identical between different types of devices. Grouping miss-matched devices just seems to be asking for trouble, LOL.


The following “Pro Tip” does not relate to the original piston,
but is more for others finding this thread in the future:

This “very selective grouping” actually extends even farther.
There are many bulbs I will not group together…
(IE: cool/warm bulbs and RGB bulbs)
… even though many of the commands may be the same.

Using separate WITH blocks essentially creates a step-by-step with you in control of the order, instead of SmartThings. (since nothing happens simultaneously)

I guess technically, this is covered in my earlier statement, since these two bulbs use different handlers.


#8

Thanks v much to all for the pointers - I take the point about “changes to” rather than “is”.
TBH I don’t really understand why it works without a trigger, though it does - that’s not the bit that goes wrong. I’ll change it anyway. (I’m still having a hard time getting my head round the execution paths in Webcore).
My hunch is that it might be the grouping of different devices in the same “with”.
However, I’ve wound the wait down to 1 minute now and am testing, and it’s working flawlessly, without any of the above changes.
Is there any way now to see a device’s events, and what caused them (showed in the classic app, but doesn’t in the new app)? I can’t find it in the IDE.

I’m going to make the suggested changes and monitor.
If it’s stable for a couple of days I’ll mark it solved!


#9

When any one of your motion sensors changes from active -> inactive or inactive -> active, that is a change of state in your trigger (the lightning bolt in the left margin of line 39). That causes your piston to run from top to bottom with each change of state. So if ANY of your motion sensors changes state, a trigger happens. So, when your piston is triggered by line 39, it executes starting at the top. When the condition in line 18 (it’s not a trigger) is evaluated, one of your motion sensors could be “active”, and that will satisfy the “is active” and will execute your first IF. If you change that condition to a trigger by changing it to “changes to active”, then your piston will trigger from there and execute top to bottom. Logically, in my mind, that makes better sense if a piston triggers from the top and runs top to bottom. YMMV.

Also, I try to keep my pistons to just a single trigger, and then conditions, so that I can easily trace the logic. That makes debugging much easier for this aging brain.

I would use log to console at specific locations in your code and monitor your device events (and anything else you like).


#10

Thank you SO much. I get it now - I had assumed that the trigger caused a subscription to that specific event, and that execution jumped back in to that line at that time. Your explanation makes perfect sense! Of course, having made the mods, I now have two triggers in the piston…

I will play with the log to console - looks useful - basically debug logging, at least that’s how I’ll use it to start with.

It does annoy me though that I can no longer find out why a light turned on or a valve opened etc - in the classic app the history would give me the time of the event AND the smartapp that made the change.


#11

This may work most of the time. With a short timer, there is less likely the chance that another trigger will abort the STAY timer. (but I assure you, it is not 100% reliable)


Actually, your original piston has three triggers. (even though only one lightning bolt) Specifically, your original post will run top to bottom at these 7 events:

  • Sensor 2’s motion changes to active
  • Sensor 3’s motion changes to active
  • Sensor 4’s motion changes to active
  • Sensor 2’s motion changes to inactive
  • Sensor 3’s motion changes to inactive
  • Sensor 4’s motion changes to inactive
  • 10 minutes after they are all inactive

Changing line 18 to a trigger will actually have the exact same 7 triggers coming in, but “inactives” will no longer turn on the lights.


#12

Thanks! I am learning!
So why would line 18 being a trigger not turn on the lights if one of the motions is active?
If triggered, the piston would start at the top, and the top if would be true?

Thanks,

James


#13

Yep, I understand that.

You lost me here.


#14

@jamesxheath, If you really want to blow your mind, read through this post about multiple triggers.


#15

This condensed code might help answer both questions:

IF any of 2, 3 or 4's motion is active                  <-- Condition
    Then Turn on
END IF

IF all of 2, 3 & 4's motion stays inactive for 10 mins  <-- Trigger
    Then Turn off
END IF
  • Now picture 2 or 3 sensors are active…
  • Then one goes inactive
  • The piston executes from the top
  • The first IF will turn ON the lights
    (IE: It’s very possible for inactive triggers to turn on the lights)

Usually, this inverted logic is not desirable, so you can change the first block to a trigger,
(or, for more persistency, you can leave the first block as a condition)


#16

Ah, I SO get that now! Thanks bud.