I would like some feedback and advice on a rule I am trying to write. I have it written out, but the part I am stuck on has to do with waiting for events and a Button press. If I place a timeout on the “wait for event” and the next action as setting my variable false, it would always occur because I let the time out happen. What I really want is a way to capture the button press and set the variable without triggering the rule again. I figure I could make this happen in another rule, but I want it all contained in one. I hope that makes sense, I posted my idea below.
Garage door
Predicate- night variable is true
Triggers - mode changes to sleep OR garage door changes to open
Local Variables- Auto shut garage door Boolean
Actions-
Wait X minutes
Alert iPhone- “the garage door has been open for X minutes, it will close automatically in two minutes if not overwritten “
Set variable to “true” indicating the garage will be automatically shut
Wait for event- physical button double pressed indicating I want the garage to stay open and set variable to “false” don’t close the garage door. - timeout 2 minutes
IF- Variable equals true. Close the garage door.
ELSE
variable equals false. Don’t close the garage door.
END IF
You can exploit the behavior of the "built-in" %device% variable here. Normally, this refers to the name of the triggering device. "Wait for event" will set this variable to "timeout" if the wait ended because of the timeout rather than the actual event (or to the device name in the other case), so after your Wait for Event (with timeout), you could do something like:
Set myLocalVariable to %device%
IF (Variable myLocalVariable = "timeout") THEN
Close door
ELSE
(do things here if button pressed, or just leave it out?)
END-IF
You'll need to create a local string variable in this rule (or use a hub variable if you really want), since you can't directly access %device% in the way you'd need to without this workaround.
I also don't think that, with this, you'd need the local variable you suggested originally.
Something you didn't mention but is still a concern: your very first action of "Wait X minutes" will not be cancelled if the door closes--so the next actions will continue after that time regardless. What you probably want is:
Wait for condition: garage door closed --> duration X minutes
Note the use of "duration" on this wait (not to be confused with "timeout"). This will only continue if the door stays closed for that long, which is probably what you want.
This, in general, is not necessarily a good goal...but in this case, it probably doesn't matter either way.
If I exploit %device% then I have to add the physical button to the list of things which trigger this rule. Since my first action is to wait for 5 minutes till the door closes, wouldn’t pressing the button restart that wait because it re-triggers the rule?
Yes, a trigger will cancel a wait. You could also look at %device% first thing when the rule is triggered if it contains the name of the button then you set the variable and do what you need to halt the door.
Agree, a single rule is not necessarily a good goal. I find it often simpler to write and manage when you split a complex rule into smaller rules. Maybe just a personal preference.
For example, you can simplify this rule by using a global (hub variable in RM5.1) for the boolean 'AutoGarageDoorShut'. Then in your main rule above, initially set the variable to true on the trigger, execute the wait, then close if the boolean is TRUE.
Write a separate rule which triggers on your switch and sets the hub variable to false.
This resets the boolean whenever your timer is triggered (garage door is opened), and separates your variable test from the garage door timer. There is no reason you have to time both events, the switch trigger/set can run any/all the time.
Why would you need to add it as a trigger? From your description, it doesn't sound like you'd need to (you only want to use it to "cancel" things, right? the "Wait..." should do everything you need in that case).
I think you said that %device% usually is the trigger device, so got a little confused.
What I think I am understanding now is %device% will capture the event, in this case double press, of the last device used in the rule, not necessarily just a device which appears in the trigger list itself?
It starts off as the trigger device and in many Rules will remain that way. "Wait..." actions are special in that they can modify the value of this device; this feature was added so it was easier to tell after a wait whether you got to that action due to the timeout or do to an actual event or condition. Referring to another device in the Rule does not change it, outside of this circumstance (e.g., it will not change just because you're inside an IF testing the value of a device attribute).
But while this is good to know, I'm not even sure it matters here: all you need to care about it whether it is equal to "timeout" or not. (I would recommend testing against that, not the name of your device. It's a string representing the name, not an actual reference to the device, and so is subject to accidents that could break it if you go the other way, IMHO.)
So now my greatest misunderstanding here may be with the timeout itself.
If I write:
Set variable “timeout”
Wait for events “button double press”—- time out 2 minutes
Set variable %device%
Am I to understand a timeout on the button will then skip the action listed below it, but the rule will evaluate a separate conditional block below that anyway?
I'm not sure what you mean with the Set variable “timeout” line. (You do need to create a local variable, but this is done elsewhere in the UI.) The timeout and line after it look like they are on the right track. But if you want to use the value of this variable--to determine whether or not you should proceed--you'll need to use conditional actions (IFs) like I had in that post.
A timeout will not cause any subsequent actions to be skipped. Whether becsuse of the event or timeout, the Rule will resume with the next action. This is why you probably want that action to store the value of device into a "real" variable, then use a conditional to test that value and act accordingly.
EDIT: Maybe you're thinking you need to set the value to "timeout" in case it doesn't get set to the device name from an event? You do not. Rule Machine makes %device% equal to timeout on its own if that's what happened.
So it sounds like I might be overthinking what rule machine is smart enough to know.
Wait for the actions with a timeout
A timeout will set the variable to timeout
A double press will set the variable otherwise.
Use a conditional action block after that to decide whether to hold the door or close it.
Sounds right! The only catch is that you do need to make a "real" variable to store and check the value of %device% (the "variable" in question, a built-in one), as you are limited in the places you can use it without making a real/full one on your own.
Understood. I won't likely have time to chew into it till the weekend, pesky day job and all. I will report back on the progress then. I really appreciate your help, and really the help of the community as a whole. Everyone is so willing and responsive to help me learn.
Also @demillerusn, I am starting to see this sometimes true, I have a few complex climate and geofencing rules that I simply had to split into multiple rules.