"Stays Unchanged" condition triggering on every change


1) Give a description of the problem
I have an incredibly simple piston. It should be: If a smartthings multisensor’s orientation hasn’t changed in more than a day, send me a message. However, it seems like it’s sending me the message every time the orientation changes. It’s on my garage door and it definitely opens and closes a few times a day.

The actual goal is alert on a low battery. When the battery gets low enough, the orientation sensor dies, even though the temperature sensor is still working.

2) What is the expected behavior?
It should only alert me if my garage door stays open/closed (closed is more likely) for 1+ days.

3) What is happening/not happening?
I’m getting the alert every time the orientation changes.

4) Post a Green Snapshot of the pistonimage

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


Instead of using stays “unchanged” use Stays any of “Open or Closed” for 1 day. The unchanged part will only trigger after it’s then changed because thats when it figures out if it has been longer than a day since it changed. I know it seems odd but that’s how the trigger works.


I can confirm this behavior. Both on stays changed and stays unchanged. It triggers as long as the condition is true each time the piston is evaluated. It should only trigger once and then it can trigger again when true but only after it was false again.

I was recently discussing this with the other minions.


Using says open or closed will have the same issue. Add something like


$currentEventValue is Open


$currentEventValue is Closed

————————- or you could…


$currentEventArribute is contact


I’m not sure if currentEventArtibute is the right one.


Don’t you just love pistons that you can only test once each 24 hour period? LOL


I’m confused. How will stays open or stays closed have the same problem? If the door is open for a day, it will trigger at 24 hours. Not the next time the door is opened like the stays unchanged problem. You would then need another function for on-going notifications but I would do:

Stays closed for 24 hours -> trigger action and set variable.

Loop while variable is true -> wait x hours and then notify again.

Wouldn’t that be easier?

And yeah, for testing I would use MUCH smaller values, like 5 minutes. Then when you know the timing is correct on the small scale you can scale it up.


Hmm, the stays unchanged condition seems to be unimplemented; it’s literally just return true


LOL… Well that could be a problem. :clown_face:


Ah. Yes, that’d do it. :slight_smile:


Why does this piston work for me then?


Whenever I change the Master Dim’s level, a second later they all adjust.

I did a bit more testing, and with 1 second for the dimming, it works beautifully…
If I increase to “stays unchanged for 10 seconds”, then once there is a change, it always runs 10 seconds later… even if the level changes in that time period…

In other words, the timer is not reset upon changes in the device.

One beauty to this bug is the Master Dim is not used in the code until AFTER the time period. This is perfect for a MasterDimSwitch because if I change the level 3 times within the short time period, only the final level will pass on to the other devices. It is also nice how the other changes during the time period do not set an additional schedule in the future. Only one schedule runs - the first one.

(When used as a trigger, it’s a slight variation of: IF Device changes, then wait X seconds and do Y)

Hmmm, that seems the opposite of @whoismoses’s observations above. Perhaps it follows different rules when used as a condition or a trigger?

If temperature doesn't change in "x" amount of time,do "y"

Put another “if” statement after that with a different device, say a contact sensor for a door. Open the door and I bet the first “if” will also execute.


I just tested, and you are correct. This piston works great if it only has the one trigger.



So is this the part where we do a mystical dance and summen @ady624?


I think if we want different behavior here we have to add new conditions that operate the way you want. Can’t assume that no one is relying on the fact that “Stays …” evaluates to true whenever at least the duration you specify has passed.

Is that the primary issue or are there additional bugs with this condition that I missed (besides “stays unchanged” seeming unimplemented)?


I think that’s it. I also am not sure that the Stays Unchanged even works the way you’re suggesting. If I create a new piston with stays unchanged as something like a a year, then go actuate the sensor, it’ll set off the piston right then (I think I remember that’s how this problem works).

I’m looking for a way to have a piston trigger if a specific attribute (open/close, thermostat mode, temp, whatever) on a specific thing hasn’t changed for more than x time. It seems like a relatively simple condition/trigger, but I might be missing something.



It looks like for now you’re limited to a condition like age([my device: contact]) > limit but I’m not sure if that will trigger or set a schedule. You could use a datetime condition to wake the piston at $now + limit - age([my device: contact]) but that may be challenging to work into a piston.


I think we need to change the wording of the current stays functionality and create new stays functionality.

“Stays” implies an event. “Has been x for at least y” or “has been x for for the last y” doesn’t imply an event.


I agree with @whoismoses. The current wording is not accurate at all.

For clarification, the command:
IF Bulb's level stays unchanged for 10 seconds
is actually doing this:
IF Bulb's level changes, then wait 10 seconds

(it ignores additional changes during that time span, and will not reset the timer)

Preventing flapping of a devcie

I also agree. It seems like when you set up a “Hasn’t Changed For…” Trigger (since we can’t use Stays Unchanged), it should subscribe to the device attribute and also set a schedule for X far in the future (X is whatever you setup in your config). Then if the device attribute event executes the piston, it should delete the schedule and create a new one for $now + X and not pass the conditional. If the schedule ever runs, it should execute the piston and pass the conditional.