I’m building an automation for a Ring-to-Open mode for my front door. When RTO is activated, my Nuki Smart Lock unlocks the door, my Ring Chime is snoozed, and then I wait for a ding event on my Ring Doorbell within three minutes. When pressed, my Shelly triggers the door buzzer so I can push the door open.
Waiting for the doorbell ding is a bit complicated, because the “ding state” sometimes remains “on” from a previous ding, even if the doorbell has stopped recording. I solve this by defining a start_ts
variable with the current timestamp at the beginning of the script, and then use a template trigger that checks both the ding state being “on” and the lastDing
attribute being greater or equal to start_ts
.
That all works well in theory, the problem is timing. Sometimes I press the doorbell while the Nuki unlock service call is still ongoing. In that case the template is already true
when waiting for the trigger, so I miss it. I could solve this by adding a condition check first. However, that still suffers from a race condition, because two subsequent steps (the condition check and the template trigger) are not executed atomically/point-in-time wise wrt. event bus: the condition could evaluate to false, then the template changes to true, and only then does the automation start waiting for the trigger, so I’d still miss the false->true edge.
I’ve contemplated waiting for the doorbell ring in a parallel branch, but that would make the script orders of magnitude more complicated, because I have to replicate stop conditions (door opened, RTO disabled, home unoccupied), cleanup steps (unsnooze the chime) to those branches.
What would solve this quite elegantly would be a setting for template triggers to also trigger if the template evaluates to true at the beginning. By checking for this after subscribing to state changes, a race condition would be effectively eliminated. PyScript supports this via state_check_now
, and right now I’m most likely eyeing rewriting the script in PyScript, but I’d usually like to reserve PyScript for more complex automations.
I understand that triggers in HA are always supposed to be event-based, but then I wonder how one is supposed to use a “wait for trigger/template” action in an automation without exposing oneself to race conditions? This surely can’t be intended.
The RTO script can be found here: RTO · GitHub