Trying to understand Syntax

I am just trying to get some lights to turn on based on different times of the day. An example of this is in my kitchen I want the lights to turn on fully between 6 am and 9 am. I want to create a another that would only turn one light on at 50% between 10 p.m. and 6 a.m.

Normally I would think of evaluating the condition this way: KitchenMotion AND (NOW > t2) AND (NOW < t3).

I am struggling to understand the syntax of (A; B; C;) ← how is this logic evaluated? I have now tried to enter it this way based on what I have read: KitchenMotion AND (t2; NOW; t3;). That works, but I’d like to know why it works! :slight_smile:

Here is my current Scene:
Triggers
Name Description
t1 Great Room Motion armed is tripped
KitchenMotion Kitchen Motion armed is tripped

Schedules
Name Type Time Days
t2 Weekly 06:00:00 1,2,3,4,5,6,7
t3 Weekly 09:00:00 1,2,3,4,5,6,7

Conditions
Name Expression
KitchenMorningMotion KitchenMotion AND (t2; NOW; t3;)

Actions

Actions for Condition: KitchenMorningMotion
Device Action Arguments
Island Lights SetLoadLevelTarget newLoadlevelTarget=100
Table SetLoadLevelTarget newLoadlevelTarget=100

From what I understand, for every trigger that occurs, and for every condition that is satisfied, the time stamp is recorded for that particular item.

The syntax (a; b; c) is comparing time stamps and that condition will be true only if the time of A is less than the time of B and that is less than the time of C.

Note that it doesn’t say anything about how close a, b and c are. A could have occurred last weekend, B could be an hour ago, and C just now. When C happens, the condition will get evaluated, and it will become true, since the time comparisons hold up. Just because you string them together in your mind, keep aware that these events could happen any time.

When you use (a; b; c < 5:00), the plugin looks at time stamps for a, b and c, and then looks at the difference between the earliest one and the latest one. If that is less than 5 minutes, the condition is true. (Semicolon adds the additional requirement that the order matters). Again, this doesn’t mean they occurred in the past 5 minutes or anything else, or that any of the events is still ongoing - it’s just looking at the time that each of them most recently occurred and uses that. So if over time, you had events/triggers/conditions a->b->c->b->a->b, it would be looking at only items 3, 5 and 6 in that list, which is the most recent of each, and comparing time stamps of each. The condition (a; b; c < 5:00) will no longer be true, even if the first 3 occurred within 5 minutes, because now the most recent event violated the order requirement.

When you use NOW, you are doing two things: you’re forcing that condition to be evaluated every minute, and you are also using the current time for comparison. If you don’t use NOW, you are relying on the other items to occur in order for your condition to be evaluated.

When you use a static time such as (07:00:00 ; a ; 15:00:00), it uses those time stamps accordingly instead of event times. There is some weirdness about the way this gets evaluated across midnight boundaries, and I have had better luck with separate conditions:

is_after_7 => (07:00:00; NOW)
is_before_3 => (NOW; 15:00:00)
kitchen_lights_on => kitchen_motion AND is_after_7 AND is_before_3

But from what I have read, this should not strictly be necessary.

HTH

I just noticed on re-read that you had an extra semicolon in your logic:

(a; b; c; )

If that was a typo, then my post above applies. If you actually meant that, and it actually works, then I have no idea what that means!

Thank you so much for your reply! That definitely helps me begin to understand this more.

BTW - the final semicolon was a typo.

OK for whatever reason, the semicolon was allowing the logic to process as TRUE and really motion was causing the lights to turn on and not the time of day too.

I have this in there and it doesn’t work:

GreatRoomMotion AND (EarlyEvening; NOW; AidenBedtime)

This does though:

KitchenMotion AND (18:00:00; NOW; 22:00:00)

Can you explain to me why that is?

Here is the output:

Triggers
Name Description
GreatRoomMotion Great Room Motion armed is tripped
KitchenMotion Kitchen Motion armed is tripped

Schedules
Name Type Time Days
EarlyEvening Weekly 18:00:00 1,2,3,4,5,6,7
AidenBedtime Weekly 20:30:00 1,2,3,4,5,6,7

Conditions
Name Expression
KitchenEveningMotion KitchenMotion AND (18:00:00; NOW; 22:00:00)
GreatroomEveningMotion GreatRoomMotion AND (EarlyEvening; NOW; AidenBedtime)
GreatroomOff (GreatRoomMotion; NOW > 10:00)
KitchenOff (KitchenMotion; NOW > 2:00)

Actions

Actions for Condition: KitchenEveningMotion
Device Action Arguments
Island Lights SetLoadLevelTarget newLoadlevelTarget=100
Table SetLoadLevelTarget newLoadlevelTarget=100

Actions for Condition: GreatroomEveningMotion
Device Action Arguments
Ceiling Light SetLoadLevelTarget newLoadlevelTarget=100
Floor Lamp SetTarget newTargetValue=1
Mantle SetLoadLevelTarget newLoadlevelTarget=100
Table Lamp SetTarget newTargetValue=1

Actions for Condition: GreatroomOff
Device Action Arguments
Ceiling Light SetLoadLevelTarget newLoadlevelTarget=0
Floor Lamp SetTarget newTargetValue=0
Table Lamp SetTarget newTargetValue=0
Mantle SetLoadLevelTarget newLoadlevelTarget=0

Actions for Condition: KitchenOff
Device Action Arguments
Island Lights SetLoadLevelTarget newLoadlevelTarget=0
Table SetLoadLevelTarget newLoadlevelTarget=0

I don’t believe you can use a schedule as an operand in the (a;b;c) syntax. abc are either the names of triggers, the names of conditions, the keyword ‘NOW’ or absolute times in hh:mm:ss format.

I would surmise that the reason is because schedules aren’t ‘evaluated’, they are used as triggers to fire something.

As for that final semicolon, I have no idea. Richard would know best.

When you use a schedule in a sequence expression, it will use the timestamp of the last time the schedule fired…if it is noon and you evaluate the condition, EarlyEvening will have YESTERDAY’S timestamp and (EarlyEvening; NOW) will be true because noon today is after yesterday evening.

@ChrisAZ and @rhanson
Thank you for helping others understand. The Sequence expressions add a lot of power to the PL plugins … but are the most difficult concept to explain.

@airedale
Time stamps are assigned when things happen, as a result the only part of a sequence expression that can have a time stamp later than NOW is the time stamp literals of the form: HH:MM:SS … These are only allowed in Sequence expressions and they are always evaluated in the context of the current day.

Time stamps are assigned as follows:

[ul][li]Input Triggers - When they are triggered.
The conditions for a trigger have to return false, before It will accept a new trigger.
If the trigger is When Front Door is Opened … The time will be from when it was opened. If you close the door, the time will still be from the last time the door was opened.
When you open the door again … it will get a new time stamp.[/li]
[li]Schedules - When they occur.
The time stamp of the schedule is always the last time stamp that it occurred … which could be equal to now, if the conditions are being evaluated as a consequence of the scheduled event triggering the evaluation.[/li]
[li]Device Properties - When they change.[/li]
[li]Conditions - When they become true … i.e. they evaluated to false during the previous evaluation … but now evaluate to true.[/li]
[li]NOW - Gets a new time stamp every time it is evaluated. It’s presence in a condition also causes the conditions to be evaluated once per minute.[/li][/ul]

In the PL plugins there are three types of expressions that use these timestamps.

[ul][li]Ordered Events
Event1 ; Event2; … EventN > HH:MM:SS < HH:MM:SS
The semi-colon indicates the event times must be ordered otherwise return false.
When HH:MM:SS is used in conjunction with the < or > they are relative times.
If these are also specified in the sequence expression the difference in time from the newest to oldest events in the list must also meet these conditions.[/li]
[li]Un-Ordered Events
Event1 , Event2, … EventN > HH:MM:SS < HH:MM:SS
The comma, indicates the event times can be in any order. But the difference in time from the newest to oldest events in the list must meet the specified conditions.[/li]
[li]Multi Trigger Events
Event1 @ Count > HH:MM:SS < HH:MM:SS
The last Count occurrences of the event meet the the specified conditions.[/li][/ul]

The Event1 … EventN can be any Input Variable, Condition, NOW, or Absolute time literal of the form HH:MM:SS.

I want to thank all of you for the great repliles. They have been super helpful and got me going down the right track. Hopefully this thread also helps others trying to get acquainted with your great plugin!

Richard - I highly recommend you put your examples you provided below with a sample of either my report or something similar on your site. I searched all over trying to understand it. I even went back to your site after getting this information from you and I can see the tidbits here and there that definitely are all there, they just aren’t as easy to understand as what you provided in this thread.

I am now trying to work on getting a late night condition to work. It seems the logic I put in was evaluating true during a time I didn’t think it should. It was evaluating true at 21:00:00 and should have been only evaluating true between 22:00:00 and 06:00:00. This was the condition:

GreatRoomMotion AND ((GreatRoomMotion; 22:00:00 < NOW) OR (GreatRoomMotion; NOW < 06:00:00))

Can you tell me why it was evaluting to true at 21:00:00?

Thanks for all of the help!

When using Sequence Expressions (or MultiTrigger Expressions) and the HH:MM:SS (Hours, Minutes, Seconds) is associated with the > or < operators these are intervals not absolute times!

So the expression:
(GreatRoomMotion; NOW < 06:00:00)

Will always be true 1 minute after the motion … because 1 minute is always less than 6 Hours.

The correct construct for what you want is:
GreatRoomMotion AND (Not (06:00:00; NOW; 22:00:00))

Here the HH:MM:SS and NOW are in the semi-colon separated lists of events. In this case they are Absolute times evaluated for the current day. The inner clause is true during the day … So a Not means any other time.

OK - I think I understand now.

I am in the midst of trying to get the motion sensor timeouts to be a little bit better for my wife as she is starting to get slightly annoyed by the timeouts. We have agreed that once 15 minutes have gone by the lights could go off, but it seems they are turning off more frequently than that. I have the schlage motion sensors that return a not tripped status 4 minutes after the motion stops. I did not realize they worked that way until this evening. I decided to try writting a new statement to capture the status of not tripped:

(GreatroomMotionNotTripped; NOW > 15:00)

But then I realized that the motion sensor could have sent a not tripped status and then got tripped and stay tripped for over 15 minutes which would then allow the lights to turn off. So I thought maybe I need to write this:

(GreatroomMotion; GreatroomMotionNotTripped; NOW > 15:00)

That doesn’t seem to be working - should it be? I would assume that for this to be true, these things would need to occur:

(GreatroomMotion Timestamp < GreatroomMotionNotTripped Timestamp) < 15:00

Do I need to instead use a NOT in this statement to get it to work - something like:

((Not (GreatroomMotion)); GreatroomMotionNotTripped; NOW > 15:00)

Hopefully these questions help out others!

GreatroomMotion; GreatroomMotionNotTripped; NOW > 15:00)
This is not what you want ... In a sequence expression ... the > 15:00 means that the events are in the specified order and the time from oldest to newest (GreatRoomMotion to NOW) is greater than 15:00 minutes ... so it starts the timer from when the event was [b]Tripped[/b] not when it was not [b]Tripped[/b]

Please attach your complete report so I can see what you are trying to accomplish.

Triggers
Name Description
GreatroomMotion Great Room Motion armed is tripped
KitchenMotion Kitchen Motion armed is tripped
PantryOn Pantry is turned on
GuestBathLightOn Guest Bathroom is turned on
DrivewayMotion Outside Motion armed is tripped
ChandelierOn Chandelier is turned on
OfficeMotion Office Motion armed is tripped
GreatroomMotionNotTripped Great Room Motion armed is not tripped
KitchenMotionNotTripped Kitchen Motion armed is not tripped

Schedules
Name Type Time Days
EarlyEvening Weekly 18:00:00 1,2,3,4,5,6,7
AidenBedtime Weekly 23:30:00 1,2,3,4,5,6,7

Device Properties
Name Device Name Device Variable
OfficeLightLevel Light Level CurrentLevel

Conditions
Name Expression
KitchenEveningMotion KitchenMotion AND (17:00:00; NOW; 20:30:00)
KitchenOff (KitchenMotion;KitchenMotionNotTripped; NOW > 15:00)
KitchenAfterAidenBed KitchenMotion AND (20:30:00; NOW; 22:00:00)
KitchenMotionMorning GreatroomMotion AND (06:00:00; NOW; 07:30:00)
LotsOKitchenMotion (KitchenMotion @ 2< 7:00)
LOMKitchenRearm (LotsOKitchenMotion; NOW > 30:00)
GreatroomEveningMotion GreatroomMotion AND (17:00:00; NOW; 20:30:00)
GreatroomOff (GreatroomMotion; GreatroomMotionNotTripped; NOW > 2:00)
GreatroomAfterAidenBed GreatroomMotion AND (20:30:00; NOW; 22:00:00)
LOMGreatroomRearm (LotsOGreatroomMotion; NOW > 30:00)
LotsOGreatRoomMotion (GreatroomMotion @ 2< 7:00)
GreatroomMorningMotion GreatroomMotion AND (06:00:00; NOW; 07:30:00)
PantryAutoOff (PantryOn; NOW > 2:00)
GuestBathAutoOff (GuestBathLightOn; NOW > 10:00)
Driveway_Motion DrivewayMotion
Driveway_Motion_Off (DrivewayMotion; NOW > 10:00)
ChandelierOff (ChandelierOn; NOW > 10:00)
NightTimeGreatRoom GreatroomMotion AND (Not (06:00:00; NOW; 22:00:00))
NightTimeKitchen KitchenMotion AND (Not (06:00:00; NOW; 22:00:00))

Actions

Actions for Condition: KitchenEveningMotion
Device Action Arguments
Island Lights SetLoadLevelTarget newLoadlevelTarget=100
Table SetLoadLevelTarget newLoadlevelTarget=100

Actions for Condition: GreatroomEveningMotion
Device Action Arguments
Ceiling Light SetLoadLevelTarget newLoadlevelTarget=100
Floor Lamp SetTarget newTargetValue=1
Mantle SetLoadLevelTarget newLoadlevelTarget=100
Table Lamp SetTarget newTargetValue=1

Actions for Condition: GreatroomOff
Device Action Arguments
Ceiling Light SetLoadLevelTarget newLoadlevelTarget=0
Floor Lamp SetTarget newTargetValue=0
Table Lamp SetTarget newTargetValue=0
Mantle SetLoadLevelTarget newLoadlevelTarget=0

Actions for Condition: KitchenOff
Device Action Arguments
Island Lights SetLoadLevelTarget newLoadlevelTarget=0
Table SetLoadLevelTarget newLoadlevelTarget=0

Actions for Condition: PantryAutoOff
Device Action Arguments
Pantry SetTarget newTargetValue=0

Actions for Condition: GuestBathAutoOff
Device Action Arguments
Guest Bathroom SetLoadLevelTarget newLoadlevelTarget=0

Actions for Condition: KitchenAfterAidenBed
Device Action Arguments
Island Lights SetLoadLevelTarget newLoadlevelTarget=60
Table SetLoadLevelTarget newLoadlevelTarget=60

Actions for Condition: GreatroomAfterAidenBed
Device Action Arguments
Floor Lamp SetTarget newTargetValue=1
Table Lamp SetTarget newTargetValue=1
Mantle SetLoadLevelTarget newLoadlevelTarget=60

Actions for Condition: GreatroomMorningMotion
Device Action Arguments
Ceiling Light SetLoadLevelTarget newLoadlevelTarget=100
Floor Lamp SetTarget newTargetValue=1
Table Lamp SetTarget newTargetValue=1

Actions for Condition: KitchenMotionMorning
Device Action Arguments
Island Lights SetLoadLevelTarget newLoadlevelTarget=100
Table SetLoadLevelTarget newLoadlevelTarget=50

Actions for Condition: Driveway_Motion
Device Action Arguments
Driveway Lights SetTarget newTargetValue=1

Actions for Condition: Driveway_Motion_Off
Device Action Arguments
Driveway Lights SetTarget newTargetValue=0

Actions for Condition: ChandelierOff
Device Action Arguments
Chandelier SetLoadLevelTarget newLoadlevelTarget=0

Actions for Condition: LotsOKitchenMotion
Device Action Arguments
Kitchen Motion SetArmed newArmedValue=0

Actions for Condition: LotsOGreatRoomMotion
Device Action Arguments
Great Room Motion SetArmed newArmedValue=0

Actions for Condition: LOMKitchenRearm
Device Action Arguments
Kitchen Motion SetArmed newArmedValue=1

Actions for Condition: NightTimeGreatRoom
Device Action Arguments
Mantle SetLoadLevelTarget newLoadlevelTarget=30

Actions for Condition: NightTimeKitchen
Device Action Arguments
Island Lights SetLoadLevelTarget newLoadlevelTarget=30

Actions for Condition: LOMGreatroomRearm
Device Action Arguments
Great Room Motion SetArmed newArmedValue=1

I would use the following strategy to solve your problems.

Input Trigger
Light1IsOn - When light 1 is on
Motion1 - Motion 1 tripped
NotMotion1 - Motion 1 not tripped

Conditions:
TurnOnLight1 (NOT Light1IsOn) and (Motion1 and … Other conditions … such as night)
AutoOnLight1 TurnOnLight1; Light1IsOn < 30
TurnOffLight1 AutoOnLight1 and (NotMotion1; NOW > 15:00)

Actions:
TurnOnLight1 Turn on Light1
TurnOffLight1 Turn off Light1
[hr]
How this works:

TurnOnLight1 - Will only turn true when the light is off, and motion and other conditions for your auto on. Moments later the light will come on and this condition will turn false. It can’t turn true again until the light is turned off and another motion event happens. While the light is on, repeated motion events will not effect the state of this condition.
AutoOnLight1 - Will turn true when it detects the light was turned on by the action from the TurnOnLight1 condition. This condition will only go false when TurnOnLight1 is re-triggered.
TurnOffLight1 - If the light is auto turned on … and it’s 15 minutes past the last motion … turn off light.

Note: If your light is turned on manually … or by some other event then your condition … This logic will NOT turn it off. The off logic could be modified if you want to turn off the light even if it was not auto turned on by this logic.

Richard,

Why do you have the ‘< 30’ piece?: AutoOnLight1 TurnOnLight1; Light1IsOn < 30

Why not ‘TurnOnLight1; Light1IsOn’

To distinguish the difference between Turned on Automatically and Turned on Manually. It should come one within 30 seconds if an action for TurnOnLight1 caused it to come on.

If you turn it on Manually then your example would evaluate to true … And then the TurnOffLight1 might trigger at the wrong time.

I just got around to implementing this fully because I was traveling for the past 5 days.

OK, so I have this implemented in 3 different rooms in my house and all of them have the exact same reaction.

When I walk in the room for the first time after a while, the lights turn on and just as quickly turn off.

What I think is happening is the Off command is turning true because the Auto condition is satisfied and the MotionNotTripped being greater than 15 minutes also evaluates to true. I hadn’t walked in the room in 15 minutes and so it hasn’t tripped again to reset its value to be lower.

Try the following:
AutoOnLight1 and (Motion1; NotMotion1; NOW > 15:00)

The previous post and this will wait until NotMotion follows Motion before the lights can go out.

The previous one is 15 Minutes from when motion was triggered, and there is currently no motion.

Or this one:

AutoOnLight1 and (Motion1; NotMotion1) and (NotMotion1; NOW > 15:00)

This will be 15 minutes from when the sensor reported NotMotion.
So this will be a little longer than the previous one.