Author Topic: Simple sequence help?  (Read 519 times)

Offline ibrewster

  • Jr. Member
  • **
  • Posts: 93
  • Karma: +1/-0
Simple sequence help?
« on: April 04, 2017, 06:58:44 pm »
I am hoping someone can help me out with creating a simple sequence for a scene. Basically, what I want is the following:

- Disarm security system (if armed, it may not be)
- Arm security system in away mode
- Open garage door

Each step is simple enough in and of itself, and I can of course use delays in the scene to accomplish this to some extent, but I have a couple of issues with that approach. First, it's not really elegant - if the security system isn't armed, you'll still get a delay before the system arms. And the delay has to be large enough to be *sure* the security system got the message and disarmed so the delay has to be non-trivial.

Secondly, it's somewhat unreliable. Communication time between the Vera and the security system (DSC plugin, BTW), as well as response time of the security system itself, can vary. Try to arm the security system before it's fully disarmed, or open the garage door before the system is in the exit delay state, and the system won't arm.

As such, I would prefer to have an actual sequence, with checks between each step to make sure the previous step completes before running the next. Specifically, I want to make sure that the system is disarmed before I try to arm it, and that the system is in the exit delay state before opening the garage door. And, of course, if the system is disarmed to begin with, go straight to the arm state (although it wouldn't hurt if I had to try to disarm still). How might I accomplish this?

Offline Don Phillips

  • Hero Member
  • *****
  • Posts: 799
  • Karma: +18/-7
    • Worthington Engineering, Inc.
Re: Simple sequence help?
« Reply #1 on: April 04, 2017, 07:54:00 pm »
Have you looked at PLEG? All three conditions would have to be true before your action would execute. The Vera scenes are pretty limited.
Vera 3, UI7 1.7.947, CT101 t-stat, Everspring motion detector, GE/Jasco switch, Leviton outlet, AeonLabs door sensor, Insteon garage control, Blue Iris, Sricam SP011, iPhone locator, APCUPSD, VeraMate, VeraAlerts, PLEG, House Modes, Countdown Timer, DVR, Virtual & Multi Switch, Weather, Sys. Mon.

Offline ibrewster

  • Jr. Member
  • **
  • Posts: 93
  • Karma: +1/-0
Re: Simple sequence help?
« Reply #2 on: April 04, 2017, 08:19:46 pm »
Have you looked at PLEG? All three conditions would have to be true before your action would execute. The Vera scenes are pretty limited.
Which action? I have three actions I want to perform, in sequence: disarm, arm, open. The conditions of arm state=disarmed and arm state=exit delay occur between the actions, and are the indicators that the next action can occur.

I have used PLEG in the past, and it could well solve this situation as well. I'll try to find some time to poke around with it and see if it can create sequences of actions. So far I've only used it for complicated logic to trigger a single scene, not to create sequences of actions with checks. In general, though, I find PLEG to be way over complicated, and prefer simpler methods like luup code if possible.

Offline ember1205

  • Sr. Member
  • ****
  • Posts: 367
  • Karma: +4/-21
Re: Simple sequence help?
« Reply #3 on: April 05, 2017, 10:10:36 am »
Why do you want to disarm the alarm, arm the alarm, and THEN open the door?

Can you provide the CONDITIONS that need to be met for certain things to happen?

Offline ibrewster

  • Jr. Member
  • **
  • Posts: 93
  • Karma: +1/-0
Re: Simple sequence help?
« Reply #4 on: April 05, 2017, 10:19:38 am »
Sure: If my wife and I go shopping in the morning, there is a good chance that the system is still armed stay from the night. Since we will be out of the house, we want the system to be armed away. In order to arm the system away, we first have to disarm the system, thus step 1. Once the system is disarmed, it can then be re-armed away, thus step 2. Since the house needs to be secure before you arm the system away, we need to wait until the system is in "EXIT WAIT" mode *AFTER* issuing the arm command before opening the garage door, step 3. Make sense?

Of course, the garage door needs to close before the system fully arms away, otherwise the alarm sounds, but since we have to get out of the garage first, that's a separate action, not part of the sequence.

In common usage, only the last two steps will be performed most of the time, since we will have already disarmed the system earlier by other means, but having the first step in there ensures I can always use the action whenever I want the system to be armed away and I am leaving from the garage.

Of course, a sequence is a sequence, so, really, this is just one example, and I would think the answer could be extrapolated to *any* sequence of events that need to occur in a particular order for whatever reason.

Offline ember1205

  • Sr. Member
  • ****
  • Posts: 367
  • Karma: +4/-21
Re: Simple sequence help?
« Reply #5 on: April 05, 2017, 10:39:08 am »
How about something like this:

- Use proximity rules to determine that "no one is home"
- Have that run a scene that toggles a virtual switch to "ON" and sends a control to close the garage door (just in case)
- Have the virtual switch being set to "ON" completely disarm the alarm
- Have the disarming of the alarm trigger a scene that arms the alarm "away" IF AND ONLY IF the virtual switch is ON, and the garage door is closed (use a timer of about 45 seconds or so - you'll have to tune it)


It would require using LUA code and having your garage door be part of the VERA system and the alarm system.

Offline ibrewster

  • Jr. Member
  • **
  • Posts: 93
  • Karma: +1/-0
Re: Simple sequence help?
« Reply #6 on: April 05, 2017, 10:49:09 am »
I realized, after re-reading this, that I may not have actually answered the question, so let me try again: The scene will be manually triggered, for example from one of the HomeLink buttons in my car. At the time the scene is triggered, the alarm system may be either in an AMRED STAY state or DISARMED. Upon triggering, the following should occur:

  • ACTION: Send alarm disarm command (if alarm is already disarmed, this just does nothing, no worries)
  • WAIT for CONDITION: DetailedArmMode=Ready (may already be in this state when scene is triggered)
  • ACTION: Send alarm ARM command
  • WAIT for CONDITION: DetailedArmMode=ExitDelay
  • ACTION: Open garage door (actually, close the relay connected to the push button)

Each of the actions is quite simple by itself - I have scenes that do all of them separately for other reasons. The conditions should be similarly easy: that's the actual variable and values I would be checking for, and I have used them as triggers in scenes, so I know they are available. The only difficulty I'm having is figuring out how to put them together in order without just putting a lot of lag between the actions.

Thanks!

Offline ibrewster

  • Jr. Member
  • **
  • Posts: 93
  • Karma: +1/-0
Re: Simple sequence help?
« Reply #7 on: April 05, 2017, 10:54:00 am »
How about something like this:

- Use proximity rules to determine that "no one is home"
- Have that run a scene that toggles a virtual switch to "ON" and sends a control to close the garage door (just in case)
- Have the virtual switch being set to "ON" completely disarm the alarm
- Have the disarming of the alarm trigger a scene that arms the alarm "away" IF AND ONLY IF the virtual switch is ON, and the garage door is closed (use a timer of about 45 seconds or so - you'll have to tune it)


It would require using LUA code and having your garage door be part of the VERA system and the alarm system.

That's not a bad idea, and I might want to implement it as a "backup", since it would ensure that my alarm is armed whenever no one is home. Though it would need some tweaking, since it would be impossible to leave the house with the alarm still armed without setting off said alarm :-) Plus, I'd need a way to over-ride it, for example when we have a babysitter over. Still, the concept is worth of consideration, so thanks!

Offline ember1205

  • Sr. Member
  • ****
  • Posts: 367
  • Karma: +4/-21
Re: Simple sequence help?
« Reply #8 on: April 05, 2017, 11:09:55 am »
How about something like this:

- Use proximity rules to determine that "no one is home"
- Have that run a scene that toggles a virtual switch to "ON" and sends a control to close the garage door (just in case)
- Have the virtual switch being set to "ON" completely disarm the alarm
- Have the disarming of the alarm trigger a scene that arms the alarm "away" IF AND ONLY IF the virtual switch is ON, and the garage door is closed (use a timer of about 45 seconds or so - you'll have to tune it)


It would require using LUA code and having your garage door be part of the VERA system and the alarm system.

That's not a bad idea, and I might want to implement it as a "backup", since it would ensure that my alarm is armed whenever no one is home. Though it would need some tweaking, since it would be impossible to leave the house with the alarm still armed without setting off said alarm :-) Plus, I'd need a way to over-ride it, for example when we have a babysitter over. Still, the concept is worth of consideration, so thanks!

You could use an additional virtual switch as a sort of "Valet mode" control where flipping that to "On" would PREVENT being able to set the alarm into Armed Away mode.

When you're stringing things together, I find it easiest to do each of them with a scene and have some specific action from that scene trigger the next scene in line. That way, there's no need for delays and the completion of one step will trigger the start of the next.

Take your time and really think it through to understand triggers, actions, outcomes, checks and balances, and things like that. I programmed in my scenes to control my outside lights and then had to gut them and start again to implement additional variables that I store on the devices where I set values to be used in subsequent steps to understand how they were turned on in the first place.

If it's dark out, and you open the garage door, I will send a control to the garage lights to turn on. When the door closes, and timer elapses, and the lights turn off. But, what happens if someone is in the garage and turned the lights on manually before it got dark? Or, before the door was opened and that turned them on?

So, I have to extend the variables on that device and then set values to understand that they were turned on manually, by a daily scene, or by an event-driven scene so I better understood what to do when the scene that wanted to turn them off ran.

Offline ibrewster

  • Jr. Member
  • **
  • Posts: 93
  • Karma: +1/-0
Re: Simple sequence help?
« Reply #9 on: April 05, 2017, 11:25:20 am »
You could use an additional virtual switch as a sort of "Valet mode" control where flipping that to "On" would PREVENT being able to set the alarm into Armed Away mode.

When you're stringing things together, I find it easiest to do each of them with a scene and have some specific action from that scene trigger the next scene in line. That way, there's no need for delays and the completion of one step will trigger the start of the next.

Take your time and really think it through to understand triggers, actions, outcomes, checks and balances, and things like that. I programmed in my scenes to control my outside lights and then had to gut them and start again to implement additional variables that I store on the devices where I set values to be used in subsequent steps to understand how they were turned on in the first place.

If it's dark out, and you open the garage door, I will send a control to the garage lights to turn on. When the door closes, and timer elapses, and the lights turn off. But, what happens if someone is in the garage and turned the lights on manually before it got dark? Or, before the door was opened and that turned them on?

So, I have to extend the variables on that device and then set values to understand that they were turned on manually, by a daily scene, or by an event-driven scene so I better understood what to do when the scene that wanted to turn them off ran.

All good points, and yeah, I'll probably have to expand on the concept. My thinking was that since the triggering of the sequence was manual from my car's HomeLink buttons, we'd always be in a known state when triggered. And if we are arming the system away, there better not be anyone in the house that still needs lights on. That said, I'd probably have run into exceptions like what you mentioned at some point - almost certainly if I make it automatic. I'll have to think about how to implement the discrete scene based sequencing - like you said, virtual switches and variables set in one scene that trigger the next. Thanks again!

Offline ibrewster

  • Jr. Member
  • **
  • Posts: 93
  • Karma: +1/-0
Re: Simple sequence help?
« Reply #10 on: April 05, 2017, 02:15:12 pm »
Ok, I think I've figured this out, using some simple lua code. Basically, it goes like this:

Code: [Select]
--get state of whatever
local value, tstamp = luup.variable_get("<service urn>","<variable_name>",<device_id>)

--perform action
luup.call_action("<service urn>", "<action>", "<parameters>", <device_id>)

--check for completion indicator
local i = 0 --timeout watchdog to prevent infinite looping if action never occurs
while ( value ~= "<desired_value>" and i < 16) do
    i = i + 1
    luup.sleep(500) --this should be fairly quick, so only wait half a second between checks.
    value, tstamp = luup.variable_get("<service urn>","<variable_name>",<device_id>)
end

--Perform the next action in the sequence and check for completion using the same pattern as above.
--Repeat as many times as needed to perform all actions.

Note that this code is as yet untested, and can probably be improved upon - for example, I might want to check the return value of the call to luup.call_action to see if the system thinks the action occurred or not, or the device may need to be polled at each loop to make sure it has the current values. Note that the loop would still be necessary when checking the return of call_action, since there could be a difference between the luup engine thinking the call_action was successful, and the action actually completing. In my situation of disarming/arming the security system, call_action returning success only means that the system was *signaled* to arm/disarm, it may take a second longer to *actually* arm/disarm, or it may not at all - if the disarm code was wrong, for example.

That said, this code looks like it should do what I want, and is nice and simple.
« Last Edit: April 05, 2017, 02:42:42 pm by ibrewster »

Offline RichardTSchaefer

  • Master Member
  • *******
  • Posts: 9566
  • Karma: +729/-135
    • RTS Services Plugins
Re: Simple sequence help?
« Reply #11 on: April 05, 2017, 09:16:25 pm »
You have using luup.sleep in a loop that adds up to 8 seconds.
You are getting close to the limit that destabilizes Vera.

You should NEVER use luup.sleep in code where the time (or in a loop where the total time) is more that a couple seconds.

luup.sleep BLOCKS all other LUUP activity and lengthy times can cause various Vera system components to restart for lack of response.

You should remove the loop and make this code event driven using luup.call_delay for a delayed action 500 ms later.
« Last Edit: April 05, 2017, 09:18:34 pm by RichardTSchaefer »

Offline ibrewster

  • Jr. Member
  • **
  • Posts: 93
  • Karma: +1/-0
Re: Simple sequence help?
« Reply #12 on: April 05, 2017, 09:53:34 pm »
You have using luup.sleep in a loop that adds up to 8 seconds.
You are getting close to the limit that destabilizes Vera.

You should NEVER use luup.sleep in code where the time (or in a loop where the total time) is more that a couple seconds.

luup.sleep BLOCKS all other LUUP activity and lengthy times can cause various Vera system components to restart for lack of response.

You should remove the loop and make this code event driven using luup.call_delay for a delayed action 500 ms later.

Makes sense. Of course, one would hope that the delay is never anywhere near the 8 second timeout, but your point remains valid. I'll work on restructuring. Thanks for the tip!

Offline ember1205

  • Sr. Member
  • ****
  • Posts: 367
  • Karma: +4/-21
Re: Simple sequence help?
« Reply #13 on: April 05, 2017, 10:35:14 pm »
Think of the "sleep" function as if it were to put the whole box to sleep because that's basically what it does.

Here's a trimmed example of how I handle turning off my front lights when garage door closes:

Code: [Select]
luup.call_delay ("eval_front_light", 120, "")

function eval_front_light (empty)
     local FrontLight_Status = luup.variable_get("urn:upnp-org:serviceId:SwitchPower1","Status",FrontLight_ID)
     local FrontLight_OnBy = luup.variable_get("urn:<my-urn>:serviceId:PoweredOnBy1","powerOnType",FrontLight_ID)
     if (FrontLight_Status == "1") and (FrontLight_OnBy == "1") then
          luup.variable_set("urn:<my-urn>:serviceId:PoweredOnBy1","powerOnType","0",FrontLight_ID)
          FrontLight_PowerOn = 0
          luup.call_action("urn:upnp-org:serviceId:SwitchPower1","SetTarget",{ newTargetValue="0" },FrontLight_ID)
     end
end
return (true)

I put everything in a function and use the "call_delay" feature to control how long it takes before the function gets run. This will also give you some insight into how I use custom variables to control whether or not the garage door closing will turn the lights off or not.

Offline ibrewster

  • Jr. Member
  • **
  • Posts: 93
  • Karma: +1/-0
Re: Simple sequence help?
« Reply #14 on: April 06, 2017, 11:10:15 am »
With the previous comments in mind, I re-wrote the block to the following using call_delay, which in testing appears to work as desired:

Code: [Select]
-- Watch variable to prevent infinite looping.
local i = 0

--get initial state of whatever, and declare state variable
local value = luup.variable_get("<service urn>","<variable_name>",<device_id>)

--perform first action (may be wrapped in an if block if conditional on initial state)
luup.call_action("<service urn>", "<action>", "<parameters>", <device_id>)

--function to wait for the first step to complete, then trigger the second step
function wait_for_whatever()
    i = i + 1
    --change value in if as appropriate. Maybe declare as a variable that can be used in all, if the same timeout is appropriate everywhere.
    if (i>=8) then
    return false --timeout. Stop here.
    end
 
    --get current state of whatever
    value = luup.variable_get("<service urn>","<variable_name>",<device_id>)
    if ( value == "<desired_value>" ) then
        i=0 --reset watchdog variable for next step, if any
        -- Perform next step in sequence
        luup.call_action("<service urn>", "<action>", "<parameters>", <device_id>)
        -- And call the next "wait for" block, if needed. Same format as this function, repeat as needed.
        luup.call_delay("wait_for_next_whatever", 0) --call immediately, returning from this function.
    else
        luup.call_delay("wait_for_whatever", 1) --call this function again in 1 second if parameters not met
    end
end

function wait_for_next_whatever()
    -- Format this function exactly the same as above, but checking for completion of step 2 and calling step 3
end

--call the first wait function. This will trigger second, third, etc steps in sequence
wait_for_whatever()

I used the call_delay function with a value of 0 when moving from one wait block to the next so the first wait block could return, hopefully keeping the call stack cleaner, but this may or may not actually be beneficial over just calling the next wait block. It does work, however. With my devices, executing a forced poll doesn't appear to be needed - apparently the DSC plugin reports changes in state immediately. However, I could see that being a needed additional step in the wait blocks.

In any case, the above code structure does appear to work to perform actions in sequence, checking for appropriate state changes between actions.
« Last Edit: April 06, 2017, 11:23:01 am by ibrewster »