Color Looping Piston not working


#1

1) Give a description of the problem
I have written a piston to cycle through hues on a couple of LED strips. I have created a virtual switch in Smarttings that triggers the cycle to turn off and on. What I’d like to do is have this cycle turn off whenever something else changes the hue of the strips (e.g. a scene or manually changing the color in smartthings, etc.)

2) What is the expected behaviour?
I’ve created a variable that changes the hue and then I created a conditional statement that if the hue of the light is different than the variable to turn the virtual switch off, which should then exit the while loop.

3) What is happening/not happening?
The comparison statement is getting “false positives” so to speak. So I turn on the switch to start the cycle, but it then turns off because the conditional statement is evaluated as true.

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

5) Attach logs after turning logging level to Full

11/5/2020, 9:01:41 PM +56ms
+1ms ╔Received event [Home].time = 1604635299593 with a delay of 1462ms
+105ms ║RunTime Analysis CS > 20ms > PS > 57ms > PE > 29ms > CE
+108ms ║Runtime (42097 bytes) successfully initialized in 57ms (v0.3.110.20191009) (106ms)
+109ms ║╔Execution stage started
+142ms ║║Comparison (integer) 9 is_equal_to (integer) 360 = false (1ms)
+143ms ║║Condition #20 evaluated false (5ms)
+144ms ║║Condition group #19 evaluated false (state did not change) (6ms)
+160ms ║║Comparison (integer) 7 is_different_than (integer) 9 = true (1ms)
+161ms ║║Condition #34 evaluated true (14ms)
+162ms ║║Condition group #33 evaluated true (state did not change) (15ms)
+165ms ║║Cancelling statement #35's schedules...
+172ms ║║Skipped execution of physical command [Living Room color loop].off([]) because it would make no change to the device. (3ms)
+173ms ║║Executed [Living Room color loop].off (5ms)
+181ms ║║Comparison (enum) off is (string) on = false (1ms)
+183ms ║║Cancelling condition #32's schedules...
+184ms ║║Condition #32 evaluated false (9ms)
+186ms ║║Cancelling condition #14's schedules...
+187ms ║║Condition group #14 evaluated false (state changed) (12ms)
+192ms ║╚Execution stage complete. (83ms)
+193ms ╚Event processed successfully (193ms)
11/5/2020, 9:01:30 PM +854ms
+1ms ╔Received event [Living Room color loop].switch = off with a delay of 36ms
+8871ms ║RunTime Analysis CS > 17ms > PS > 8814ms > PE > 40ms > CE
+8873ms ║Piston waited at a semaphore for 8766ms
+8875ms ║Runtime (42176 bytes) successfully initialized in 8814ms (v0.3.110.20191009) (8873ms)
+8876ms ║╔Execution stage started
+8883ms ║║Comparison (enum) off changes_to (string) on = false (1ms)
+8885ms ║║Cancelling condition #2's schedules...
+8885ms ║║Condition #2 evaluated false (5ms)
+8887ms ║║Cancelling condition #1's schedules...
+8887ms ║║Condition group #1 evaluated false (state changed) (7ms)
+8889ms ║╚Execution stage complete. (13ms)
+8890ms ╚Event processed successfully (8890ms)
11/5/2020, 9:01:29 PM +586ms
+1ms ╔Received event [Living Room color loop].switch = on with a delay of 36ms
+94ms ║RunTime Analysis CS > 16ms > PS > 51ms > PE > 26ms > CE
+96ms ║Runtime (42114 bytes) successfully initialized in 51ms (v0.3.110.20191009) (94ms)
+97ms ║╔Execution stage started
+104ms ║║Comparison (enum) on changes_to (string) on = true (0ms)
+105ms ║║Cancelling condition #2's schedules...
+106ms ║║Condition #2 evaluated true (5ms)
+107ms ║║Cancelling condition #1's schedules...
+108ms ║║Condition group #1 evaluated true (state changed) (6ms)
+110ms ║║Cancelling statement #3's schedules...
+127ms ║║Executed physical command [Entertainment Center].setColor([[hue:0, saturation:100, level:50]]) (8ms)
+128ms ║║Executed virtual command [Entertainment Center].setHSLColor (10ms)
+135ms ║║Executed physical command [Mantle].setColor([[hue:0, saturation:100, level:50]]) (5ms)
+136ms ║║Executed virtual command [Mantle].setHSLColor (7ms)
+142ms ║║Executed virtual command [Entertainment Center, Mantle].setVariable (3ms)
+148ms ║║Comparison (enum) on is (string) on = true (1ms)
+149ms ║║Cancelling condition #32's schedules...
+150ms ║║Condition #32 evaluated true (6ms)
+151ms ║║Cancelling condition #14's schedules...
+152ms ║║Condition group #14 evaluated true (state changed) (7ms)
+154ms ║║Cancelling statement #16's schedules...
+160ms ║║Calculating (integer) 0 + (integer) 1 >> (integer) 1
+165ms ║║Executed virtual command [Entertainment Center, Mantle].setVariable (2ms)
+172ms ║║Executed physical command [Entertainment Center].setHue([0]) (5ms)
+173ms ║║Executed [Entertainment Center].setHue (6ms)
+178ms ║║Executed physical command [Mantle].setHue([0]) (3ms)
+179ms ║║Executed [Mantle].setHue (5ms)
+182ms ║║Executed virtual command [Entertainment Center, Mantle].wait (1ms)
+184ms ║║Waiting for 1000ms
+1191ms ║║Comparison (integer) 1 is_equal_to (integer) 360 = false (1ms)
+1192ms ║║Condition #20 evaluated false (5ms)
+1193ms ║║Condition group #19 evaluated false (state did not change) (6ms)
+1208ms ║║Comparison (integer) 61 is_different_than (integer) 1 = true (2ms)
+1210ms ║║Condition #34 evaluated true (14ms)
+1211ms ║║Condition group #33 evaluated true (state did not change) (15ms)
+1213ms ║║Cancelling statement #35's schedules...
+1241ms ║║Executed physical command [Living Room color loop].off() (24ms)
+1242ms ║║Executed [Living Room color loop].off (26ms)
+1248ms ║║Comparison (enum) on is (string) on = true (1ms)
+1250ms ║║Condition #32 evaluated true (5ms)
+1251ms ║║Condition group #14 evaluated true (state did not change) (6ms)
+1253ms ║║Cancelling statement #16's schedules...
+1260ms ║║Calculating (integer) 1 + (integer) 1 >> (integer) 2
+1266ms ║║Executed virtual command [Entertainment Center, Mantle].setVariable (3ms)
+1273ms ║║Executed physical command [Entertainment Center].setHue([0]) (4ms)
+1274ms ║║Executed [Entertainment Center].setHue (6ms)
+1279ms ║║Executed physical command [Mantle].setHue([0]) (4ms)
+1280ms ║║Executed [Mantle].setHue (5ms)
+1283ms ║║Executed virtual command [Entertainment Center, Mantle].wait (1ms)
+1284ms ║║Waiting for 1000ms
+2291ms ║║Comparison (integer) 2 is_equal_to (integer) 360 = false (2ms)
+2293ms ║║Condition #20 evaluated false (6ms)
+2294ms ║║Condition group #19 evaluated false (state did not change) (7ms)
+2309ms ║║Comparison (integer) 0 is_different_than (integer) 2 = true (2ms)
+2311ms ║║Condition #34 evaluated true (14ms)
+2312ms ║║Condition group #33 evaluated true (state did not change) (16ms)
+2314ms ║║Cancelling statement #35's schedules...
+2336ms ║║Executed physical command [Living Room color loop].off() (18ms)
+2337ms ║║Executed [Living Room color loop].off (20ms)
+2343ms ║║Comparison (enum) on is (string) on = true (2ms)
+2344ms ║║Condition #32 evaluated true (5ms)
+2345ms ║║Condition group #14 evaluated true (state did not change) (7ms)
+2348ms ║║Cancelling statement #16's schedules...
+2355ms ║║Calculating (integer) 2 + (integer) 1 >> (integer) 3
+2360ms ║║Executed virtual command [Entertainment Center, Mantle].setVariable (3ms)
+2368ms ║║Executed physical command [Entertainment Center].setHue([0]) (4ms)
+2369ms ║║Executed [Entertainment Center].setHue (6ms)
+2374ms ║║Executed physical command [Mantle].setHue([0]) (4ms)
+2375ms ║║Executed [Mantle].setHue (6ms)
+2378ms ║║Executed virtual command [Entertainment Center, Mantle].wait (0ms)
+2379ms ║║Waiting for 1000ms
+3386ms ║║Comparison (integer) 3 is_equal_to (integer) 360 = false (2ms)
+3388ms ║║Condition #20 evaluated false (5ms)
+3389ms ║║Condition group #19 evaluated false (state did not change) (7ms)
+3404ms ║║Comparison (integer) 0 is_different_than (integer) 3 = true (1ms)
+3405ms ║║Condition #34 evaluated true (13ms)
+3407ms ║║Condition group #33 evaluated true (state did not change) (15ms)
+3409ms ║║Cancelling statement #35's schedules...
+3430ms ║║Executed physical command [Living Room color loop].off() (18ms)
+3431ms ║║Executed [Living Room color loop].off (20ms)
+3437ms ║║Comparison (enum) on is (string) on = true (1ms)
+3439ms ║║Condition #32 evaluated true (6ms)
+3440ms ║║Condition group #14 evaluated true (state did not change) (7ms)
+3443ms ║║Cancelling statement #16's schedules...
+3450ms ║║Calculating (integer) 3 + (integer) 1 >> (integer) 4
+3456ms ║║Executed virtual command [Entertainment Center, Mantle].setVariable (3ms)
+3463ms ║║Executed physical command [Entertainment Center].setHue([1]) (4ms)
+3464ms ║║Executed [Entertainment Center].setHue (6ms)
+3469ms ║║Executed physical command [Mantle].setHue([1]) (3ms)
+3470ms ║║Executed [Mantle].setHue (5ms)
+3474ms ║║Executed virtual command [Entertainment Center, Mantle].wait (0ms)
+3475ms ║║Waiting for 1000ms
+4508ms ║║Comparison (integer) 4 is_equal_to (integer) 360 = false (1ms)
+4510ms ║║Condition #20 evaluated false (5ms)
+4511ms ║║Condition group #19 evaluated false (state did not change) (7ms)
+4537ms ║║Comparison (integer) 3 is_different_than (integer) 4 = true (1ms)
+4539ms ║║Condition #34 evaluated true (25ms)
+4540ms ║║Condition group #33 evaluated true (state did not change) (27ms)
+4542ms ║║Cancelling statement #35's schedules...
+4563ms ║║Executed physical command [Living Room color loop].off() (18ms)
+4564ms ║║Executed [Living Room color loop].off (20ms)
+4570ms ║║Comparison (enum) on is (string) on = true (2ms)
+4571ms ║║Condition #32 evaluated true (5ms)
+4572ms ║║Condition group #14 evaluated true (state did not change) (6ms)
+4574ms ║║Cancelling statement #16's schedules...
+4582ms ║║Calculating (integer) 4 + (integer) 1 >> (integer) 5
+4586ms ║║Executed virtual command [Entertainment Center, Mantle].setVariable (3ms)
+4594ms ║║Executed physical command [Entertainment Center].setHue([1]) (5ms)
+4595ms ║║Executed [Entertainment Center].setHue (6ms)
+4600ms ║║Executed physical command [Mantle].setHue([1]) (4ms)
+4601ms ║║Executed [Mantle].setHue (5ms)
+4604ms ║║Executed virtual command [Entertainment Center, Mantle].wait (0ms)
+4605ms ║║Waiting for 1000ms
+5611ms ║║Comparison (integer) 5 is_equal_to (integer) 360 = false (1ms)
+5613ms ║║Condition #20 evaluated false (5ms)
+5614ms ║║Condition group #19 evaluated false (state did not change) (6ms)
+5627ms ║║Comparison (integer) 3 is_different_than (integer) 5 = true (1ms)
+5629ms ║║Condition #34 evaluated true (13ms)
+5630ms ║║Condition group #33 evaluated true (state did not change) (14ms)
+5632ms ║║Cancelling statement #35's schedules...
+5660ms ║║Executed physical command [Living Room color loop].off() (24ms)
+5661ms ║║Executed [Living Room color loop].off (26ms)
+5666ms ║║Comparison (enum) on is (string) on = true (1ms)
+5668ms ║║Condition #32 evaluated true (5ms)
+5669ms ║║Condition group #14 evaluated true (state did not change) (7ms)
+5671ms ║║Cancelling statement #16's schedules...
+5678ms ║║Calculating (integer) 5 + (integer) 1 >> (integer) 6
+5682ms ║║Executed virtual command [Entertainment Center, Mantle].setVariable (3ms)
+5689ms ║║Executed physical command [Entertainment Center].setHue([1]) (4ms)
+5690ms ║║Executed [Entertainment Center].setHue (6ms)
+5695ms ║║Executed physical command [Mantle].setHue([1]) (4ms)
+5696ms ║║Executed [Mantle].setHue (4ms)
+5699ms ║║Executed virtual command [Entertainment Center, Mantle].wait (0ms)
+5699ms ║║Waiting for 1000ms
+6705ms ║║Comparison (integer) 6 is_equal_to (integer) 360 = false (1ms)
+6707ms ║║Condition #20 evaluated false (5ms)
+6708ms ║║Condition group #19 evaluated false (state did not change) (6ms)
+6724ms ║║Comparison (integer) 3 is_different_than (integer) 6 = true (1ms)
+6725ms ║║Condition #34 evaluated true (14ms)
+6726ms ║║Condition group #33 evaluated true (state did not change) (16ms)
+6728ms ║║Cancelling statement #35's schedules...
+6749ms ║║Executed physical command [Living Room color loop].off() (18ms)
+6750ms ║║Executed [Living Room color loop].off (20ms)
+6756ms ║║Comparison (enum) on is (string) on = true (1ms)
+6757ms ║║Condition #32 evaluated true (5ms)
+6758ms ║║Condition group #14 evaluated true (state did not change) (6ms)
+6760ms ║║Cancelling statement #16's schedules...
+6766ms ║║Calculating (integer) 6 + (integer) 1 >> (integer) 7
+6771ms ║║Executed virtual command [Entertainment Center, Mantle].setVariable (2ms)
+6778ms ║║Executed physical command [Entertainment Center].setHue([1]) (5ms)
+6779ms ║║Executed [Entertainment Center].setHue (5ms)
+6784ms ║║Executed physical command [Mantle].setHue([1]) (3ms)
+6785ms ║║Executed [Mantle].setHue (6ms)
+6788ms ║║Executed virtual command [Entertainment Center, Mantle].wait (0ms)
+6789ms ║║Waiting for 1000ms
+7795ms ║║Comparison (integer) 7 is_equal_to (integer) 360 = false (1ms)
+7797ms ║║Condition #20 evaluated false (4ms)
+7798ms ║║Condition group #19 evaluated false (state did not change) (6ms)
+7812ms ║║Comparison (integer) 3 is_different_than (integer) 7 = true (1ms)
+7814ms ║║Condition #34 evaluated true (14ms)
+7815ms ║║Condition group #33 evaluated true (state did not change) (15ms)
+7817ms ║║Cancelling statement #35's schedules...
+7837ms ║║Executed physical command [Living Room color loop].off() (18ms)
+7838ms ║║Executed [Living Room color loop].off (20ms)
+7844ms ║║Comparison (enum) on is (string) on = true (1ms)
+7845ms ║║Condition #32 evaluated true (5ms)
+7846ms ║║Condition group #14 evaluated true (state did not change) (6ms)
+7848ms ║║Cancelling statement #16's schedules...
+7855ms ║║Calculating (integer) 7 + (integer) 1 >> (integer) 8
+7859ms ║║Executed virtual command [Entertainment Center, Mantle].setVariable (3ms)
+7866ms ║║Executed physical command [Entertainment Center].setHue([2]) (4ms)
+7867ms ║║Executed [Entertainment Center].setHue (6ms)
+7910ms ║║Executed physical command [Mantle].setHue([2]) (41ms)
+7916ms ║║Executed [Mantle].setHue (48ms)
+7919ms ║║Executed virtual command [Entertainment Center, Mantle].wait (1ms)
+7920ms ║║Waiting for 1000ms
+8926ms ║║Comparison (integer) 8 is_equal_to (integer) 360 = false (1ms)
+8928ms ║║Condition #20 evaluated false (4ms)
+8929ms ║║Condition group #19 evaluated false (state did not change) (5ms)
+8943ms ║║Comparison (integer) 7 is_different_than (integer) 8 = true (1ms)
+8944ms ║║Condition #34 evaluated true (13ms)
+8945ms ║║Condition group #33 evaluated true (state did not change) (14ms)
+8947ms ║║Cancelling statement #35's schedules...
+8967ms ║║Executed physical command [Living Room color loop].off() (17ms)
+8968ms ║║Executed [Living Room color loop].off (19ms)
+8973ms ║║Comparison (enum) on is (string) on = true (1ms)
+8975ms ║║Condition #32 evaluated true (5ms)
+8976ms ║║Condition group #14 evaluated true (state did not change) (6ms)
+8978ms ║║Cancelling statement #16's schedules...
+8984ms ║║Calculating (integer) 8 + (integer) 1 >> (integer) 9
+8989ms ║║Executed virtual command [Entertainment Center, Mantle].setVariable (3ms)
+8996ms ║║Executed physical command [Entertainment Center].setHue([2]) (4ms)
+8997ms ║║Executed [Entertainment Center].setHue (5ms)
+9002ms ║║Executed physical command [Mantle].setHue([2]) (4ms)
+9003ms ║║Executed [Mantle].setHue (5ms)
+9006ms ║║Executed virtual command [Entertainment Center, Mantle].wait (0ms)
+9007ms ║║Requesting a wake up for Thu, Nov 5 2020 @ 9:01:39 PM MST (in 1.0s)
+9011ms ║╚Execution stage complete. (8914ms)
+9012ms ║Setting up scheduled job for Thu, Nov 5 2020 @ 9:01:39 PM MST (in 1s)
+9018ms ╚Event processed successfully (9018ms)

#2

I have not looked at your logs yet, but generally speaking, it is a good habit to avoid this type of logic:

IF Switch 1's switch changes  (line 23)
Then change Switch 1's switch  (line 52)

… since line 52 will kick off the piston again at the top…
(although you may be OK since that is your very last command)


Also note that mathematically speaking, Hue 0 is the same as Hue 360.
(it’s a 360° circle, so they both represent the same color)


#3

Looking at the log, there seem to be two issues:

  1. The comparison at line 47 is getting values for the hue that you aren’t expecting. I’m not sure exactly what is going on there as I’ve never worked with lights to know how the values behave.

That is the fundamental problem. However …

  1. The while loop is not being terminated by the switch being turned off for about nine to ten seconds. This is because when ‘switch is on’ is evaluated (line 32) the piston first considers the event data and that says the switch has just been turned on so the current status is not checked. After nine seconds or so the piston implements a ‘wait’ by scheduling a wakeup in one second and exiting. This is a precaution to avoid running out of execution time. When it runs again it is because of a time event and so ‘switch is on’ does check the actual status and sees it is off.

#4

Thanks for the help. If I move the while loop outside the conditional statement at line 21. Would this resolve the 2nd problem?


#5

If I am correct in my understanding of how things work, then no it wouldn’t. You can see from the logs that the piston instance is executing because it Received event [Living Room color loop].switch = on and so as long as that instance of the piston runs it will consider that switch to be on.

There is a potential third issue by the way. Your mileage may vary with the ‘physically’ modifier on line 23 to the extent that there is a lot to be said for not using it. For example, two or three years ago support for the required flag was dropped for Z-Wave devices running locally in the hub as it couldn’t be relied upon. I seem to remember webCoRE had a reputation for making a pig’s ear of it too. If it works for you then great, but don’t expect that to always be the case.


#6

How often does an instance of a piston run? What would I do to resolve the issue?


#7

Looking at the pic in the left margin:
A piston runs top to bottom each time that device’s attributes changes at all.

In your original piston, that means it fires when Switch 1’s switch changes to either on or off.
(IE: On executes the THEN block… Off executes everything else, and might break timers)


#8

So if I understand correctly then, everytime it gets to line 38 a new instance of the piston is run. However, because line 23 evaluates as false that instance gets to the end of it’s code and closes. Correct?


#9

Line 38 should not start the piston at the top…

(although line 52 does)


#10

So it is only switch’s attribute changing that would create a new instance of the piston, not any of the devices it is subscribed to.


#11

If you change an attribute that also has a lightning bolt next to it, then yes, the piston starts all over at the top.


Not sure what you mean by this.


#12

The piston is subscribed to 3 devices.

|+1ms|╔Starting piston... (v0.3.110.20191009)|
|---|---|
|+152ms|║╔Subscribing to devices...|
|+161ms|║║Subscribing to Living Room color loop.switch...|
|+194ms|║║Subscribing to Entertainment Center...|
|+195ms|║║Subscribing to Mantle...|
|+196ms|║╚Finished subscribing (54ms)|
|+282ms|║Comparison (enum) off is (string) on = false (1ms)|
|+293ms|╚Piston successfully started (293ms)|

But, according to what you are saying, it only creates a new instance of the piston if the switch change, the line with the lightning bolt.


#13

On piston “72mx”, (top post) the only subscription is “Switch 1's switch”.


#14

Here is what the logs from 72mx show for me when I active the piston (e.g. pause and then resume).

|+1ms|╔Starting piston... (v0.3.110.20191009)|
|---|---|
|+123ms|║╔Subscribing to devices...|
|+137ms|║║Subscribing to Living Room color loop.switch...|
|+234ms|║║Subscribing to Entertainment Center...|
|+235ms|║║Subscribing to Mantle...|
|+236ms|║╚Finished subscribing (116ms)|
|+280ms|║Comparison (enum) off is (string) on = false (2ms)|
|+293ms|║Comparison (integer) 0 is_equal_to (integer) 360 = false (2ms)|
|+313ms|║Comparison (integer) 21 is_different_than (integer) 0 = true (2ms)|
|+323ms|╚Piston successfully started (322ms)|

#15

OK. The piston should only start at the top when “Switch 1's switch” changes.


Notice that (other than WAITS) all of your logs are kicked off with:
Received event [Living Room color loop].switch = X


#16

Cool, thanks.

What I find confusing in the logs is that it doesn’t seem changing the hue to the variable value. For example.

+3450ms ║║Calculating (integer) 3 + (integer) 1 >> (integer) 4 
+3456ms ║║Executed virtual command [Entertainment Center, Mantle].setVariable (3ms) 
+3463ms ║║Executed physical command [Entertainment Center].setHue([1]) (4ms) 
+3464ms ║║Executed [Entertainment Center].setHue (6ms) 
+3469ms ║║Executed physical command [Mantle].setHue([1]) (3ms) 
+3470ms ║║Executed [Mantle].setHue (5ms)

The variable’s value changes to 4, but then it sets the Hue to 1. Why isn’t it setting it to the variable’s value?


#17

Local variables are usually set very quickly, but you could try adding a 200ms WAIT in between line 37 & 38 if it doesn’t have enough time to process.


Edit

You may also want to increase line 39 to at least 12 seconds… Otherwise you are spamming the loop 100 times in a minute and a half.


#18

I can see why you might think that, but if you look closely at logs in situ you will see that there can be two groups of ‘subscriptions’ and your piston has both.

The first batch is displayed in blue and each line has the format Subscribing to Device Name.attribute.... That lists the actual subscriptions to device attribute changes. So your piston is subscribing to one device.

The second batch is displayed in black and each line has the format Subscribing to Device Name... without any mention of an attribute. This lists the other devices that the piston accesses. The piston makes ST think it has subscribed to them even though it hasn’t so when you view those devices in the IDE the piston appears in the ‘In use by’ section (the same info was also used in the Classic app). So there are two devices being used by your piston that it doesn’t subscribe to events for.

It could have been presented differently.


#19

The issue is really that the value you set hue to uses some algorithm to change it from 360 degrees to a percentage. For example when I set the hue to 3 I get this in the log.

+127ms ║║Executed physical command [Mantle].setHue([0]) (6ms)

When I set the hue to 4 I get this in the log

+148ms ║║Executed physical command [Mantle].setHue([1]) (5ms)

However, I change the variable I use to a decimal and step through it makes errors in the math and eventually I get a decimal like this 10.00000000001. If I try to convert a decimal to a integer for my comparison statement it get even weirder. For example, floor(10/3.6) evaluates to 7.