"Changes to" does not trigger?


#1

1) Give a description of the problem
I have a piston that monitors a global variable, and set piston state to false when the global variable changes to “false” (string value), but it only detects changes to true, not changes to false.

Note that originally the global variable was set as boolean, when I saw out not working for the same reason I changed it to string for the value comparison.

2) What is the expected behavior?
When global variable changes from “true” to “false”, it can detect the change and set piston state to false.

3) What is happening/not happening?
Global variable changes from “false” to “true” not detected, log data shows it’s regarding the “changes to” trigger as false. (“Comparison (string) “false” changes_to (string) “false” = false (1ms)” on below log)

When changes from “false” to “true” though, it’s working as expected. (“Comparison (string) “true” changes_to (string) “true” = true (1ms)” on below log)

**4) Post a Green Snapshot of the piston!

**5) Attach any logs **

Working log:

10/23/2018, 10:18:24 PM +847ms
+0ms ╔Received event [Home].:892b416409f20adf038cd1ba2cd3cd89: = @AllPresent with a delay of 54ms
+102ms ║RunTime Analysis CS > 18ms > PS > 58ms > PE > 26ms > CE
+104ms ║Runtime (41771 bytes) successfully initialized in 58ms (v0.3.108.20180906) (103ms)
+105ms ║╔Execution stage started
+116ms ║║Comparison (string) "true" changes_to (string) "true" = true (1ms)
+118ms ║║Cancelling condition #3's schedules...
+119ms ║║Condition #3 evaluated true (7ms)
+120ms ║║Cancelling condition #1's schedules...
+121ms ║║Condition group #1 evaluated true (state changed) (10ms)
+124ms ║║Cancelling statement #8's schedules...
+129ms ║║Executed virtual command setState (1ms)
+137ms ║║AllPresent has changed to true
+138ms ║║Executed virtual command log (2ms)
+142ms ║╚Execution stage complete. (36ms)
+143ms ╚Event processed successfully (144ms)

Non-working log:

10/24/2018, 8:16:27 AM +343ms
+0ms ╔Received event [Home].:892b416409f20adf038cd1ba2cd3cd89: = @AllPresent with a delay of 64ms
+109ms ║RunTime Analysis CS > 19ms > PS > 63ms > PE > 27ms > CE
+111ms ║Runtime (41769 bytes) successfully initialized in 63ms (v0.3.108.20180906) (110ms)
+113ms ║╔Execution stage started
+123ms ║║Comparison (string) "false" changes_to (string) "true" = false (1ms)
+125ms ║║Cancelling condition #3's schedules...
+127ms ║║Condition #3 evaluated false (7ms)
+128ms ║║Cancelling condition #1's schedules...
+129ms ║║Condition group #1 evaluated false (state changed) (10ms)
+134ms ║║Comparison (string) "false" changes_to (string) "false" = false (1ms)
+136ms ║║Condition #4 evaluated false (5ms)
+138ms ║║Condition group #2 evaluated false (state did not change) (7ms)
+140ms ║╚Execution stage complete. (28ms)
+142ms ╚Event processed successfully (143ms)

Thanks in advance for the help!


#2

I tried your piston. If you remove the “ “ around the word true and false it seemed to work for me. I reworked a little too while in there


#3

Thanks a lot for the help! I’ll try to put in and see that when I get back home tonight. Would that single condition be sufficient for both false – true & true – false check?


#4

Yup, if it evaluates as true it will perform the “then” tasks, and if it evaluates as false it will perform the “else” tasks.

BTW what are you using for presence sensor? If you are using webcore’s Presence sensor you can forcit it away or home by clicking on the cog in the upper right corner of the smartthings app when viewing the device (presence sensor). It will open another page and from ther you can select presence mode to force it away/home/or automatic… that way you can test without having to leave. Just make sure you change back to automatic when done or it will stay in whatever you forced it too.


#5

Oh I didn’t know that, thanks for the tip and I’ll think about it when I have time.

The reason for this is that I need an overall indicator for me and my wife’s presence for lights automation, the default triggers for “changes to” would only evaluated to true when both presence sensors changes at the same time, and that’s not realistic at all. Now I’m setting it to both presence “are” not present and it works. Problem is that when I arrive home alone with my super laggy Android presence sensor, I’ll ask Google home to change ST from away to home mode and light up the house. But since I have another trigger that evaluates both sensor “are” not present, piston will trigger and turn off all the lights again since my phone’s presence is still away.

So I need this solution to detected only “changes to” event instead of "are’ status.


#6

Just tried with a different value (1 and 0) of the global variable, no avail…

Your example would work, but I just noticed that my light automation piston has many different conditions for different time of day, so a simple if-then won’t work.

What’s strange is when I manually set the global variable to true, and then run the other piston that changes the global variable, then this piston is working perfectly:

Comparison (string) 0 changes_to (integer) 0 = true (1ms)

However whenever it’s running automatically i.e. the global variable changes based on my presence, and then this piston observes the variable change, then it clearly tells comparison is not successful:

Comparison (string) 0 changes_to (integer) 0 = false (1ms)

What would be the reason for this?

Thanks in advance for the help


#7

There could be issues with using multiple “changes to” conditions on the same value (i.e. device attribute or variable) in your piston. The changes to condition works by checking the last known value encoded in the piston’s cache. Each time a condition is evaluated that cache may be updated for the device attribute or variable used in the condition, so I don’t think the if @var changes to X else if @var changes to Y will work.

You may get more mileage out of this construct:

if @AllPresent changes { 
    if @AllPresent is true { ... } 
    else { .. } 
}

This is more versatile than if @AllPresent changes to true { ... } else { ... } which will evaluate the else any time the piston is triggered by something other than the @AllPresent change (i.e. if other logic in the piston is triggered when your door opens then the else will run as well).

If you’re talking about the modified piston that @Gopack2 posted I don’t know why this would happen. If this is part of a larger piston I think we would need more info to figure out what’s going on.


#8

The explanation above about why the else if does not work was not quite correct. The “changes” condition does not actually check the cache for “the last value of @AllPresent” but rather “the last value of this specific condition.” Makes sense.

However, and this may really be the part that is affecting you, the value cache for that condition is only updated if the condition is evaluated. With the if/else if construct the else if condition is only evaluated when the if evaluates to false.

In your first example, let’s say @AllPresent is false when the piston first runs. The changes to always evaluates false on the first run because it does not have a previous value. So both conditions will evaluate to false on the first run and both conditions will be saved to the cache with the previous value of false. Now your wife comes home and @AllPresent changes to true. The piston is triggered and the first condition evaluates to true, but the second condition is not evaluated. The piston cache is left with a previous value of true for the first condition, but still false for the second condition.

You leave to buy beer and @AllPresent becomes false. The first condition evaluates to false because it’s not changing to true, but the second also evaluates to false because the last value, as far as it knows, is false so there is no change. That’s why else if is unreliable with conditions that respond to changes.

So you will definitely avoid that with the nested if shown in my previous reply since there is only one changing condition. The remaining question if you’re using this in a larger piston is whether the condition is evaluated every time the piston runs or not or if something else could be preventing it from evaluating and therefore disrupt detection of that change.


#9

Wow, thank you so much @ipaterson, I’m very enlightened! You’re probably right about the condition cached value, that explains why everytime I change the global variable manually it works since the old value is being updated.

I’ll try to integrate your suggestions above but definately need some work since my pistons also have date and time conditions.