If we take your simple piston as an example, it will (by default) be run whenever a contact attribute event is received from your contact sensor, regardless of whether the comparison is ‘contact is open’ (condition) or ‘contact changes to open’ (trigger). This is because, if there aren’t any explicit triggers, pistons fall back to considering their conditions when deciding what events to subscribe to.
When the piston runs, ‘contact changes to open’ will look to see if the event that ran the piston uses the contact in question. If it does it will look to see if the event says the new state is ‘open’. It will then check its cache to see if it has recorded it being ‘closed’ last time it heard anything. If all those conditions are met, the comparison is true. So there are a few points to consider:
- Events can sometimes get delayed. You might be responding to things that happened e.g. thirty seconds ago.
- It is perfectly possible to receive two ‘open’ events in a row, without an intermediate ‘closed’, whether by design in the device handler, or by events getting delayed or lost and coming out of order. If that happens the comparison returns false.
- If the piston runs for any other event, such as the ‘Test’ button in webCoRE, the comparison returns false. Only the contact event matters.
On the the other hand a ‘contact is open’ will go and check the SmartThings device object to see what the current value of the attribute is. If it is ‘open’ it will return true. Things to consider:
- It doesn’t matter why the piston is running, the comparison only considers the state at the moment it is evaluated. That behaviour can be useful when things have got out of bonk for some reason. It can also be bad if you aren’t expecting the piston to run when it does.
It is horses for courses really. I tend to favour conditions unless I definitely need a trigger.