Hi all. Topic says it all. In the code below you can see it takes five lines to record the current state; is there a shorter way?
Why record the state? I wanted to have the motion trigger the light only if the door is not already open. I also found that the xor was prone to race condition so I also handle the case where they both trigger "simultaneously."
Triggers:
Front Door Motion motion *changed*
Front Door contact open
IF (NOT Front Door Light is on AND
( Illuminance of Weather is <= 1200 OR
Time between Sunset-20 minutes and Sunrise+20 minutes) AND
( ( ( Front Door contact open XOR
Front Door Motion motion active) AND
NOT Variable prev_motion = true
) OR
( Front Door contact open AND
Front Door Motion motion active AND
NOT Variable prev_door = true AND
NOT Variable prev_motion = true
)
)) THEN
Set pending to true
On: Front Door Light
Wait for event: Front Door Light turns on --> timeout: 0:00:05
END-IF
IF (Front Door contact open) THEN
Set prev_door to true
ELSE
Set prev_door to false
END-IF
IF (Front Door Motion motion active) THEN
Set prev_motion to true
ELSE
Set prev_motion to false
END-IF
IF (NOT Front Door Light is on) THEN
Set pending to false
END-IF
IF (NOT Variable pending = true OR
Front Door Motion motion active) THEN
Exit Rule
END-IF
Wait for Expression: --> timeout: 0:05:00
Off: Front Door Light
Set pending to false
I wouldn't want to discourage the conversation about how best to achieve what you want using code, it would be a useful thing to know, I expect.
But if I can deviate from that for a moment, could you not setup an RM rule with a Required Expression that the contact sensor is closed, triggered by the motion sensor, which turns the light on?
For the casual observer, this is why some of us encourage people to provide the context of why they are asking a specific technical question, it opens up the possibility for people to come up with and offer an alternative approach. So thankyou @dfacto for doing that...
I am not 100% sure I am following your code but, with your triggers, I don't see anything in the code that should happen if motion goes to inactive so I think you could change your trigger from "Front Door Motion motion changed" to "Front Door Motion active" and it would simplify some of your Code (or actions). Also, you are using Front Door Contact open as a trigger. Technically, a trigger would be Front Door Contact opens or closes. The contact being in a state or open or closed is not a trigger. A trigger is a moment in time and two triggers cannot happen simultaneously. One will always happen before the other. That is why @sburke781 recommends using that state in Required Expression in RM.
If I am misunderstanding what you are trying to accomplish, my apologies.
Thanks for the feedback! Apologies for not explaining; let me do that now.
The goal of this rule is to have the light turn on if I open the door xor if someone approaches the door from the outside. If the door is already open I don't want the motion to trigger the light on. (We leave our door open in summers and I don't want the light to turn on when I walk by in my skimpies.)
The thing that surprised me at first is that I don't want the light to turn on if the motion was previously active because when it transitions to inactive then the xor is triggered. This is the first condition you see.
Another surprise was that sometimes a race condition happens between door and motion so preemption can someone make it seem from the rule's perspective that both triggered simultaneously. This is the second condition you see.
Hopefully with that rationale, things make more sense?
I have the motion inactive trigger because I want the wait timer to trigger after the last motion happened while we're in pending=true mode, ie the light was turned in by the rule. Perhaps there's a better way?
There's always different ways...whether or not they are "better" is subjective.
So for this, you mean that you only want the light to turn on for 5 minutes based on the first instance of motion in that time span? So motion goes active, turn the light off after 5 minutes, even if there's another motion instance. If motion happens after those 5 minutes, turn the light back on?
I am aware of the simple state machine code but I wanted to first see how things play out in RM. Once I learn about avenues for improvement Id be happy to see how the idea fares in a different substrate.
I agree "better" can be subjective and I invite this and any other feedback.
Id like the light to turn off after 5 minutes of motionlessness and only if it was triggered by the rule in the first place. Ie, if the light was turned on manually then I want it to stay on indefinitely. My general philosophy for home automation is that if it was auto turned on it should be auto turned off and if it was manually turned on then it should in general be manually turned off with the possible exception of no one being present. However the front door light as does not fit into this exception because I want to sometimes leave it on even if no one is present.
Front Door Light is off AND
Front Door contact closed AND
Front Door Motion motion inactive AND
( Illuminance of Weather is <= 800 OR
Time between Sunset-10 minutes and Sunrise+10 minutes
)
Triggers:
Front Door contact open
Front Door Motion motion active
Actions:
On: Front Door Light
Wait for Expression: Front Door Motion motion inactive --> duration: 0:05:00
Off: Front Door Light
In english,
Light already on; do nothing (manually turned on). Else, if its dark or night then,
Door closed & motion; turn on light then turn off after 5 minutes of no motion.
Door open & no motion; turn on light then turn off after 5 minutes.
Otherwise, do nothing.
The obvious-in-hindsight trick is that the required condition ensures that we're not already in the xor state--this way when either motion or door triggers then we are guaranteed to be in the xor state.