Need help with this rule: contact sensor, capture and restore

I'm trying to set up a rule to control my entryway light with my door sensor as a trigger. Here is how I've written the rule:

The problem I have is when I open the door again during the 5 minute delay. The light won't turn off again. I suppose it's just recapturing the light in its on state and that's what it then restores. I want the capture/restore capability to remain, because if the light was on before, I want it to remain on after the door opens, but I don't want a double opening within 5 minutes (like when I take the trash out) to keep the lights on. I'd rather have it just reset the delay to 5 minutes rather than recapture. How would I write that?

All done in simple automation. Can even add time of day restrictions too if you want.

Thanks, I'll give that a shot. I hadn't even considered trying it in simple first.

So, in the restrictions section, when it asks for a switch to cancel the rule, if I set that to the same light I'm controlling, that means it'll ignore this rule if the light is already on? Just making sure I understand how that function works, I'm gonna try it out anyways.

Yep

Everyone goes to rm first. Bangs their head on the table for a while then finds the other apps do it as well as rm. I try to only use rm when I absolutely need conditionals.

Well, I have my rule now set up in simple automation. As far as I can tell, I have it set exactly like your example. It's not working like expected. The light comes on, but never turns off again, even with just a single open event. I'm guessing that turning the light on causes the rest of the rule to cancel or be ignored? I may try this again in RM, but use a conditional rather than capture/restore.

Post a screen shot of what you have.

I think to do this exactly the way they have requested, using RM is the correct route

Trigger: Front Door Open

Action:
Cancel Delayed Actions
If Private Boolean is True 
  Capture EntryLight 
  Set Private Boolean False
end If
Dim: Entrylight 100 --> fade:0
Restore Entry light  Delay 5:00 -- Cancelable
Set private Boolean True Delay 5:00 -- Cancelable

With Simple automation you is not really restoring the state of the light. you are turning it on and off

I can't really tell what's going on with this rule. I've not messed with creating private variables yet, and the rest of this seems a bit beyond my skill level. Mind breaking down how this rule works?

Is the Boolean there just to flag weather the delay timer has expired or not?

Essential. The Boolean is saying do I need to capture this state? Or has it been captured. You don’t have to create this variable. The private Boolean exists in the rule you just have to use it!

I would not use the PB, I would use a local boolean variable. That way you can see what it is set to at any time. There is no way to see what the PB is set to unless you go into the rule and update it. You also can't fix PB easily if you accientally screw it up.

The problem you are running into is the any action that has a delay on it is the first thing that is scheduled when the rule is loaded. So, you are setting your delay. Then your next action is to cancel all delayed actions. So, you are canceling the delay you just set.

If you change your restore with a delay to two separate actions of delay and then an action of restore, it will work.
So, instread of:

Restore Entry light  Delay 5:00 -- Cancelable
Set private Boolean True Delay 5:00 -- Cancelable

I would do:

Delay 5 minutes Cancelable
Restore Light
Set PB (or variable) to true

To put it another way....this is the order that your actions within the rule are handled, since you have a delayed action in there.

  1. Schedule 5 min delayed restore
  2. Scheudle 5 mine delayed PB set to true
  3. Cancel all delayed actions.

So, #3 is canceling #1 and #2. When you have an action of delay, that happens in the order that the rule is laid out. So, that 5 min delay doesn't occur 1st, it occurs 4th or 6th, depending on how you look at "action".

Took me a couple read throughs to grasp what you are saying, but I think I get it. I'd still start the rule with cancelling all delays? This is part of resetting the timer should the door be opened again during the delay?

I find this to not be the case..rules are executed in order. By canceling the delayed actions, you are in fact canceling the actions that are waiting from the previous time the rule has run, if any.

If delayed actions were scheduled Before the first line, dozens of my rules would not function.

@bravenel can probably step in here to set this straight.

I also believe there may be a performance penalty for using a local Boolean over a private. Bruce can probably clear that up too!

The issue above is actually just related to how the standalone "Delay" action works vs. how the "delay" option on an action works. Neither gets scheduled "first thing" unless it happens to be the first action executed (either because it's at the top of the rule action itself or happens to be the first action after a delay, wait, or other wake-up). What does happen is that the plain "Delay" action stops there (when this action is reached), waits for the delay, and continues with the next action when the rule wakes up again after the delay. A "delay" on an action schedules that action for the future (again, when this action is reached) in accordance with the delay, then continues on with the next action. So two actions with "delay 0:05:00" set on them as in the example will both happen at 5 minutes from the time of execution, rather than the first happening in 5 minutes and the next in 5 minutes after that.

Related to the above, "cancel(able)" works differently as a result. Cancelling a standalone "Delay" action cancels the delay plus all actions after it. Cancelling actions with "delay" set on them will cancel those that are scheduled to run but have not yet run. Cancelling everything that runs (or would run) after them is not really applicable here since this type of delay does not block future execution while the delay is in progress, so this is fairly intuitive as long as the difference between the two types of delays is apparent.

Bruce will have to chime in about PB vs. local variable, but my understanding is that neither should really be inefficient; the only thing I've seen mentioned that would come into play is with things like "debouncing" rules for events that might happen in quick succession (say, from a Z-Wave contact sensor that effectively generates duplicate "open" or "close" events for the same real-world action). Most, if not all, of those have been addressed with driver options now, which is probably the best place to handle them anyway, but rules with complicated triggers (or really, just a lot of triggers to an extent that events that match two or more could occur in quick succession--hundreds of milliseconds or so, or less) could still run into this problem. In this case, however, the first thing I'd consider is whether that is really the best way to write the rule.

1 Like

I have never had an instance where cancel delayed actions has canceled actions that are delayed further down the list from this command.

I would be curious to see this post as well. I have never heard of this. This is the closest I could find with minimal stalking (talking about a different issue and doesn't specifically mention when they get scheduled but also mentions nothing about an exception to the statement that actions are executed in order):

Regardless, if there's nothing before the delayed action that would create an additional delay (like a wait, "standalone" delay, and or whatnot), then the difference would be minimal. But I'm still not sure it really works that way (and it seems like the implementation would be quite complex if it it did, given that it would have to check every action before it).

I didn't say not to do this or that either way was a bad idea. :slight_smile:

If this is a standalone "Delay" action, then it should--that's exactly how it works and can be seen with several examples in the docs, including this one:
image

The intent of "Cancel Delayed" actions is not just to stop the delay but also stop any action afterwards from running--notably here, the turning off of the lights (which you would no longer want when motion becomes active).

If it's a delay on an action, then yes, this is more or less what you'd see: a "delay" on an action will not stop at that point in the rule: the next action(s) will run, and you can hardly cancel something that will have already happened. :smiley:

Actions are executed in order, one at a time. Just turn on Action logging to see this in detail.

If an action has a delay on it, you will see that in the logs, and the specified delay is scheduled at that moment (not before, not at the "head of the rule"), for whatever duration is specified. That creates a scheduled job to run that action after the duration of the delay. At that time, just that action runs (again, observe the logs).

If there is a Delay Actions, that schedules a job at that moment for the duration specified, and the rule exits its execution. The scheduled job restarts the rule actions execution after the delay.

Cancel Delayed Actions unschedules whatever jobs were scheduled from cancelable delays.

2 Likes