Prevent simultaneous triggers from initiating multiple instances of rule

Hey folks - I have a rule that reminds me that my garage doors are open. I have two garage doors, and opening either triggers the rule to start repeating. Every 30 minutes (starting 15 minutes after the door is opened), I get a message on my phone to remind me that the doors are open. This works great, unless I open both garage doors at the same time. This sometimes causes multiple instances of the rule to run simultaneously, leading to multiple alerts happening every 30 minutes.

Any thoughts to how to prevent a second instance of the rule from running in a more foolproof manner than I have below? I tried to set a variable which helps but still doesn't catch all cases.

Here is an example of the triggers happening simultaneously (the virtual switches are being pushed by IFTTT integration), and consequently, two alerts happening 15 minutes later.

  • 2021-10-09 11:47:25.070 am info - Both garage doors have been open since 11:32 AM
  • 2021-10-09 11:47:25.047 am info - Both garage doors have been open since 11:32 AM
  • 2021-10-09 11:32:24.008 am info - Setting Garage-Door-Alert-Running global variable to true.
  • 2021-10-09 11:32:23.993 am info - Setting Garage-Door-Alert-Running global variable to true.
  • 2021-10-09 11:32:23.819 am info - Garage Door Alert - Start Triggered
  • 2021-10-09 11:32:23.819 am info - Garage Door Alert - Start Triggered
  • 2021-10-09 11:32:23.601 am info - Garage Door Side - Virtual Switch was turned on
  • 2021-10-09 11:32:23.601 am info - Garage Door Main - Virtual Switch was turned on

Here is the rule...
Triggers: Garage Door Main - Virtual Switch, Garage Door Side - Virtual Switch(off, off) any turns on

IF (Variable Garage-Door-Alert-Running(false) = false(T) [TRUE]) THEN
	Log: 'Setting Garage-Door-Alert-Running global variable to true.'
	Set Garage-Door-Alert-Running to true
	Delay 0:15:00
	Repeat every 0:30:00 (stopable)
		IF (Garage Door Main - Virtual Switch, Garage Door Side - Virtual Switch(off, off) all is on(F) [FALSE]) THEN
			Set Display-Name to 'Both garage doors have'
			IF (Variable Garage-Door-Main-Open-Time(02:45 PM) > Garage-Door-Side-Open-Time(11:32 AM)(T) [TRUE]) THEN
				Set Display-Time to Garage-Door-Side-Open-Time(11:32 AM)
			ELSE
				Set Display-Time to Garage-Door-Main-Open-Time(02:45 PM)
			END-IF
		ELSE-IF (Garage Door Main - Virtual Switch(off) is on(F) [FALSE]) THEN
			Set Display-Name to 'Main garage door has'
			Set Display-Time to Garage-Door-Main-Open-Time(02:45 PM)
		ELSE
			Set Display-Name to 'Side garage door has'
			Set Display-Time to Garage-Door-Side-Open-Time(11:32 AM)
		END-IF
		Notify iPhone M: '%Display-Name% been open since %Display-Time%'
		Log: '%Display-Name% been open since %Display-Time%'

Have you thought of setting up an if condition that exits the rule if both doors are either opening or opened?

Perhaps Iā€™m misunderstanding but I donā€™t see how that will help. I want the rule to be running if both doors are opened.

I just want to make sure only one instance is running whether or not one of the doors is opened (whether itā€™s the main or side) or if both are opened (at the same time or staggered by an indeterminate amount of time).

If you use a Boolean variable initialized to true, or Private Boolean (implicitly initialized to true), then give the rule a Predicate rule that the variable or PB must be true. The rule will only run when it's true. Then, the first action of the rule sets it to false, and the last action of the rule sets it to true. Such a rule cannot run again until the prior one is finished.

3 Likes

@bravenel so the difference between your suggestion and what I already tried above sounds like the Predicate rule portion. I havenā€™t used that before, is that conceptually better at this sort of thing than a straight Boolean check in the rule like I have?

Marginally, but effectively the same thing.

@bravenel - Thanks for the advice, I set up some new rules to try this out, but running into some issues with the Predicate Rule that I'm wondering if you can help with.

Basically I have 2 rules.
Predicate for Rule #1 is "Private Boolean is true"
Rule #2 sets the Private Boolean for Rule #1 to true.

This seems to work, but the predicate keeps evaluating to false.
This is shown in the logs.

2021-10-10 07:23:18.218 pm - Garage Door Alert - Start: Predicate Conditions false
2021-10-10 07:23:18.212 pm - Garage Door Alert - Start: Set Private Boolean true from Garage Door Alert - Cancel
2021-10-10 07:23:18.045 pm - Action: Rule Boolean True: 'Garage Door Alert - Start'

Any idea why we seem to correctly set the Private Boolean to true, but the predicate keeps evaluating to false (and, in fact, the rule doesn't run anymore because the predicate is false)

1 Like

@672southmain - Thanks for the quick reply. You guys rock.

1 Like

I just got caught by this....and I am in here re-learning WHY.

I had a WAIT FOR EXPRESSION in an RM rule not even thinking that a re-Triggering (which was happening as a new temperature report came in) was having an impact until I turned full logging on for the rule.

I finally saw this in the Docs: "Any type of "Wait" action is cancelled upon re-triggering of a rule."
https://docs.hubitat.com/index.php?title=Rule-5.1#Trigger_events

There's probably a discussion somewhere in the Doc Set that talks about Triggers and their superseding all; but just the fact that you explained how to use the Boolean here and used it in a rule example you gave me once in the past suggests it might not be a bad idea to mention this as a footnote on the above Doc Page.

I think this is probably less of a concept gap for folks with more experience with Event driven programming.

Tagging @bertabcd1234

Bruce sent me this, too, but I think I missed something the first time I read it--the thread is months old and there are a few different posts about a similar issue. Is the request just to have something like the following documented specifically for PB as a way to make a rule effectively non-re-entrant?

Required Expression: Private Boolean True

Trigger Events: (whatever)

Actions to Run:

Set Private Boolean False (This Rule)
(whatever)
Set Private Boolean True (This Rule)

If so, this exact example isn't spelled out, but the use of a required expression in general to prevent re-entry is (Private Boolean is not the only way to do this, though if you have no other use for it and no use for the same "flag" outside the rule, it is probably the best option). I can add something specific but don't want to make it so long no one bothers to read anything. I'm happy someone did. :smiley:

The fact that trigger events cancel a "Wait" is indeed documented, as the most recent post found.

2 Likes

It's just one of those things that folk new to this might overlook the need for. As I said, I have been given a Rule example from Bruce WITH this very construct in the past and I STILL turned around and overlooked the need for it in a new rule I was making (thinking such things as waits, delays, etc. would do the trick). Maybe there is somewhere better to put a brief discussion of this but it kinda goes with the WAITs are canceled by TRIGGERS discussion (and how to avoid that).

Thanks, the documentation was a good read by the way.