I have a Zooz outdoor motion detector that we use to detect when the dog comes back on the porch so we can let him in. It triggers a virtual contact which triggers an Echo routine to announce he's there. 90% of the time it works just great.
But every once in a while it goes bonkers. The motion detector is set with a 1 minute motion cleared delay. But according to the following it triggered multiple times in one second.
For the contact I am using the 'Virtual Contact With Switch' driver. I have it set for a 5 sec turn off. But it also went on/off multiple times in a second. Here is the events from it.
In the app, my own, I also use a state variable that is supposed to prevent multiple triggers within 10 seconds. But it seems to get ignored when this happens. It's like the state variable doesn't get updated fast enough with the multiple triggers. (Hope that made sense).
So as a consequence we got multiple announcements on our Echo. This is not necessarily a problem but really curious as to why this happens.
This is one of the potential drawbacks to state - it is not updated until the method completes... Not sure how much is actually being executed, but perhaps you could narrow this window by having a separate, one-line method to update the state var? E.g.
def updateState(key, val) {
state[key] = val
}
Then in your other method(s), call this instead of trying to set state directly?
You kinda lost me on that one. Not sure I understand that, but will research it. Here is what I do now, basically:
If (....state.trigger == false) {
make announcement
state.trigger = true
runIn(10, reset state)
}
But I wouldn't need that at all if the motion and contact didn't trigger multiple times when it isn't supposed to.
Re-read your original post - your code is in an app, so you can use atomicState in place of state. The atomic version is updated immediately, instead of waiting for execution to complete.
As to why the device triggers so many times, is this a built-in driver or a custom one? Seems like when it calls sendEvent for motion, it unnecessarily uses "isStateChange: true"
I knew about atomic state, but didn't even think of that. DUH...
The Zooz sensor uses the custom driver from Zooz "Zooz Outdoor Motion Sensor Advanced'.
The contact sensor uses custom driver 'Virtual Contact Sensor With Switch'. I use that as it's easier for me to think of a switch rather than a contact, but Echo needs the contact. But even with that it should stay on for at least 5 secs. Nothing external is turning it back off.
Looking at the code for the contact driver, I see where it will record the event every time it is called even tho it is already on/closed. So that explains part of that. I can account for that in my code, which may solve the whole thing. The only thing that is still wrong is the multiple motion triggers. But now that I understand the contact code I think I can ignore that better.
Make take several days to see if it works. Thanks for the suggestions.
EDIT: Going through this whole scenario, It appears if I do the logic 'dogcontact.close() even tho it is already closed it still sends the command out to Echo. (Or at least I'm thinking that may be happening). So I just put in some logic to not issue the command if the contact is already closed. That way I don't even need the state variable. Will see if that works.
A recent release included an option to make drivers and apps single threaded. This is recommended over using atomicState. I have changed a few of my apps to use this because of similar challenges as the OP and it’s worked awesome.
Update, once I deleted the 'isStateChange: true' in the motion unit driver I haven't had any more issues.
On a side note, I had another app that controlled some back lighting. There are 3 different lights that come on/off together for some things and not together for others. And there are times when it seemed a little flaky. Since the app is subscribed to all three lights plus some switches It was probably getting called multiple times for each operation. I added in the single thread and it has worked much better.