I sort of have this working, but think it could be much cleaner. Wondering if anyone has thought about how to implement something like this in a structured and systematic manner:
Initial state = auto control by motion sensor. Light goes to 100% when motion detected and turns off after 20 minutes of no motion.
State # 1 manual trigger from initial state= lighting at 100% stays on for at least 1 hour and auto extended if motion. If no motion return to initial state. Manual trigger also returns to initial state.
State # 2 manual trigger 2x = lighting at 60% stays on for at least 2 hours and auto extended if motion. If no motion return to initial state. Manual trigger also returns to initial state.
State #3 manual trigger 3x = lighting at 30% stays on for at least 2 hours and auto extended by motion. If no motion return to initial state. Manual trigger also return to initial state.
State # 4 manual trigger 4x = lighting at 0% for at least 1 hour. After 1 hour or manual trigger return to initial state.
Currently I have this implemented this with a series of quite complex condition statements, but it is difficult to troubleshoot and get the scenes not to conflict with each other.
Wondering if anyone has done something like this previously or has any recommendations for how to create an exclusive state engine like this in PLEG? I can post my status report, but I’m more interested in taking a more structured approach than what I have done. Once defined the methodology or algorithm for how to do this could be very useful.
I have 1 switch and I wanted to have a rather complex automation scheme for my living room lighting. I also want to change the behavior of the automation depending on if it is day or night.
When I tried to implement just in PLEG for just 3 states my condition statements started getting very complicated and troublesome to troubleshoot.
The solution was to introduce a separate layer of logic using a combination of PLEG and PLTS that tracks state changes and dictates which logic is used to trigger a state change. Independently of this I used PLEG to monitor the PLTS status and determine the actions and behavior for each state. I am using 5 separate states and don’t really see a reason for why I would not be able to easily add more.
These states include: (1) motion control if night (base state) (2) on if day off if night for set time and extended by motion detected. The thinking here is the first state is an override of automatic control. For example, I am playing ps4 at night and don’t want motion to turn on the lights. It is overcast in daytime and I want to use the lights. I am going to sleep and want to turn off the light immediately. I am trying to anticipate the most likely reason to use the switch depending on if it is light or dark and makeing that happen first. Depending on day or night or any other variable the behavior is easy to change. (3,4) Movie modes which are separate dimming levels (60%, 30%) depending on preference. The movie modes stay on for longer since if I am watching a movie I expect less motion. (5) on if night off if day for set period.
To reach each state I click my switch successively within 5 seconds. After 5 seconds I can click the switch at any time before the scene expires to return to the normal automated state.
I was able to implement all of the above with the state model and changes are straightforward. I have been working on documenting it and should finish this weekend.
Here is the documentation showing the working state engine along with some description about why I felt is was needed. Interested to see if anyone finds it useful.
Thanks for sharing this, @pacificdune. It’s a really interesting use of PLEG and PLTS. I can definitely see your EE roots in the design. Impressive stuff! It’s also good to see PLTS being used for something other than outside lights and bathroom fans. ;D
My only caution is that with seven PLxx plugins being used, you have consumed a lot of precious RAM. This may not be a good solution for VeraLite users. If memory is short, it may be worth considering a different approach:
I was faced with a similar requirement for state-based logic to implement at-home simulation of lights, blinds and audio when I’m away. I wanted combinations of absolute, relative and random timing along with event-driven overrides and I had around twenty states. My solution was to write a simple plugin that provides a state register in the form of a Flag variable which can be used with or without the timer. PLEG Conditions just require to check the Flag along with whatever event can cause a state-change. You can see how this works in LogicTimer.
Since I wrote LogicTimer, @RichardTSchaefer has added a lot more capability to PLEG Schedules including randomized and Self-Triggered timers. It would now be feasible to achieve state-based logic by using a VariableContainer variable as the state register and Self-Triggered timers or events to trigger state changes.
I am not suggesting that this approach is better than your solution but it would consume less memory.
I have also though about using another special prefix character in the condition name to allow it to be used on multiple lines.
Each Line could use a conditional expression to set the state, the state being represented by the condition variable.
@Rex, thanks for taking a look! I do have VeraLite. I was also concerned about this having gone through the discussions about multiple PLEG instances. From SysMon my memory available is ~33.5MB and CPU utilization about 25%. These seem OK to me so let me know if you think otherwise…
From a software purity standpoint I agree that using all of these PL instances is inefficient, but, since it works, and there seem to be plenty of resources remaining, let it churn! After all, running my system is all the vera does… As I add more of these in other rooms it will be interesting to see how these numbers are impacted.
[quote=“RichardTSchaefer, post:7, topic:178625”]I have also though about using another special prefix character in the condition name to allow it to be used on multiple lines.
Each Line could use a conditional expression to set the state, the state being represented by the condition variable.[/quote]
Now that is a good idea, Richard. It would make state logic a lot easier to implement. It would also be handy if there was a way to get the timestamp of a Self-Triggered timer’s stop event without needing a Condition for each one.
It would also be handy if there was a way to get the timestamp of a Self-Triggered timer’s stop event without needing a Condition for each one.
Timers already have a timestamp![/quote]
I know they have a timestamp for when they start. Is there are a way to get a timestamp for when they stop without adding a Condition for Not Timer?
[quote=“RexBeckett, post:6, topic:178625”]It would now be feasible to achieve state-based logic by using a VariableContainer variable as the state register and Self-Triggered timers or events to trigger state changes.
I am not suggesting that this approach is better than your solution but it would consume less memory.[/quote]
…This is what I do - my Security System and Occupancy Tracking uses Variable Containers.
PLEG is powerful and complex so troubleshooting is a nightmare with possible timing issue, etc (not easy like a single/set of linear If/Then/Else). After much trial/error I found the easiest way (for troubleshooting, reducing timing problems, making updates/changes easier) is to separate the logic and state tracking as much as possible.
I also decided to allow PLEG to trigger Vera’s native Automation scenes whenever those Scenes can accomplish what I need. This also reduced the PLEG complexity and was much easier to ‘follow’.
… Since I did those things, most of my headaches are gone.
I still see issues when more than one state is changed, a second state is dependent upon the first state change… and they both must be evaluated in a single PLEG condition to determine an Action.
For instance:
If a person is ‘Returning’ home to an empty house then the security system must Disarm and unlock the door.
This means both (PersonHome = ‘Yes’ and HomeOccupied = ‘No’) must be True.
BUT, logic in the Occupancy Tracking PLEG dictates if PersonHome = ‘Yes’ then the Home IS Occupied.
So, I introduced a 3 sec delays…
one between when HomeOccupied changes from ‘No’ to ‘Yes’ - so PLEG hopefully has enough time to evaluate the above statement as True
and one before the Door gets unlocked to ensure the Security is actually Disarmed first - otherwise PLEG alarm will sound as the door will be opened when the system is Armed.
If you know of a better way please let me know as this is clearly not ideal.
Seems like we have all reached the conclusion that separation of the state change logic from the actions is key to making a multi-state implementation work, otherwise it just gets too complicated.
Variable container does seem like an interesting option to track states. I am in the middle of automating another room and will try it this way…
Does anyone have an example for how to configure a self triggered timer in PLEG instead of using a PLTS? I attached what I tried, but I don’t think it was working right…
To trigger a Condition when a Self-Trigger timer ends, you need to get a timestamp for that. This is easily done with an additional Condition. Now you can use a sequence expression:
SomeTerm TimerEnd Not Timer NextStep SomeTerm and TimerEnd and (SomeTerm; TimerEnd)
I believe that since program logic 5.6 was introduced the state engine I had stopped working.
I attached a log file of what is going on. I have a condition based on a PLTS I call LRS1. If LRS1 is On then I want to fire a scene. In my log you will see that LRS1 is On, but the scene has not fired.
This used to work fine, but now does not work. I would like to rewrite using state variables, but first would like to understand why this is no longer working…
The log starts with PLTS LRSA On and another PLTS LRS1 off. When I activate the switch LRControl it turns LRSA off and turns LRS1 On. This happens correctly as it always did.
What does not happen is this condition which is supposed to turn on the lights when LRS1 is active and it is daytime:
During the whole time … the LRSOn was already true.
If you want this to trigger when it’s already on then rename this to _LRSON
This kind of behavior changed in 5.7 … a lot of conditions were inadvertently set to false in previous release.
When I fixed the problem, people are now seeing that they need to mark many of their conditions as needing to trigger the actions, even if the condition is already true. That’s what the underscore does.
So, adding the underscore did fix the issue, but I’m still a bit confused regarding why the condition was true in the first place…
I attached a more simple example:
_LRS60 depends only on the PLTS LRS2 being “On”. It is currently not, but _LRS60 is true. Why would this be? By the time stamps it looks like _LRS60 does not update when LRS2 goes false.