Author Topic: Conditional Scene Execution: Some Examples  (Read 142849 times)

Offline RexBeckett

  • Master Member
  • *******
  • Posts: 3888
  • Karma: +476/-10
Conditional Scene Execution: Some Examples - Using Functions
« Reply #15 on: December 20, 2013, 05:52:37 am »
I showed in Multiple Conditions how a code chunk could be converted to a function. With small adjustments, the function call can pass the parameters to be used for the test. Now a single piece of code can be used to test several devices. The function code can even be added to your Startup Lua so it may be called from any scene. In the following examples, I changed the original lines that set the parameters to comments (with --) as a reminder of what each parameter means.


Function to check if a temperature is within a range

Code: [Select]
function checkTemp(dID, tLow, tHigh, allow)
     --dID = 55               -- Device ID of your thermostatic/temperature sensor
     --local tLow = 18        -- Lowest temperature of range
     --local tHigh = 22       -- Highest temperature of range
     --local allow = true     -- true runs scene when in range, false blocks it
     local tCurrent = tonumber((luup.variable_get(     "urn:upnp-org:serviceId:TemperatureSensor1","CurrentTemperature",dID)))
     return (((tCurrent >= tLow) and (tCurrent <= tHigh)) == allow)
end


Function to check the state of a Z-Wave switch

Code: [Select]
function checkSwitch(dID, allow)
     --local dID = 66           -- Device ID of your Z-Wave Switch
     --local allow = true       -- true runs scene if switch is on, false blocks it
     local status = luup.variable_get("urn:upnp-org:serviceId:SwitchPower1","Status",dID)
     return ((status == "1") == allow)
 end


We can use these two functions to implement a more-complex set of conditions. This example, suggested by @parkerc, checks the temperature in three different rooms. If any of the temperatures are out of range, checkTemp(device,min,max,true) returns false. In this case we check if the switch controlling our heating is off and, if so, allow the scene to run to turn it on.

Code: [Select]
if checkTemp(123,18,22,true) and checkTemp(124,18,22,true) and checkTemp(125,18,22,true) then
     return false   -- All temperatures are in range, don't run scene   
else
     return checkSwitch(101,false) -- Run scene if switch is off
end


Adding functions to Startup Lua

Select the APPS tab, click on Develop Apps and select Edit Startup Lua. Add your functions to the end of the existing code and click GO. Now click on Vera's Reload button to restart the luup engine. Your functions should now be available to the luup in any scene.
« Last Edit: December 20, 2013, 06:03:38 am by RexBeckett »

Offline RexBeckett

  • Master Member
  • *******
  • Posts: 3888
  • Karma: +476/-10
Conditional Scene Execution: Some Examples - Multiple Triggers
« Reply #16 on: December 21, 2013, 02:16:17 pm »
Sometimes we want to have several different events or schedules result in essentially the same action but with different settings. An example would be setting different temperature setpoints or dimmer levels depending and time schedules or any of the conditions in the previous examples. The obvious way to do this is with several scenes but there is another way. We can use a global variable to transport our required settings from Trigger Luup event to the main scene LUUP.

This example is for a scene that sets a Thermostat setpoint based on one of three triggers.

Trigger 1 Luup event - Set to 20 during daytime, do nothing at night
Code: [Select]
local function checkDayTime()
     local dID = 23           -- Device ID of your DayTime plugin
     local allow = true       -- true runs scene during daytime, false runs it at night
     local status = luup.variable_get("urn:rts-services-com:serviceId:DayTime","Status",dID)
     return ((status == "1") == allow)
end

if checkDayTime() then
     setTemp = 20
     return true
else
     return false
end

Trigger 2 Luup event - Set to 20 during daytime or 10 at night
Code: [Select]
local function checkDayTime()
     local dID = 23           -- Device ID of your DayTime plugin
     local allow = true       -- true runs scene during daytime, false runs it at night
     local status = luup.variable_get("urn:rts-services-com:serviceId:DayTime","Status",dID)
     return ((status == "1") == allow)
end

if checkDayTime() then
     setTemp = 20
else
     setTemp = 10
end
return true

Trigger 3 Luup event - Set to 18
Code: [Select]
setTemp = 18
return true


Main scene LUUP - Version 1
Code: [Select]
local dID = 55
if (setTemp ~= nil) then
     luup.call_action("urn:upnp-org:serviceId:TemperatureSetpoint1_Heat","SetCurrentSetpoint",{NewCurrentSetpoint=setTemp},dID)
     setTemp = nil
end


Main scene LUUP - Version 2
Code: [Select]
local dID = 55
if (setTemp == nil) then setTemp = 20 end
luup.call_action("urn:upnp-org:serviceId:TemperatureSetpoint1_Heat","SetCurrentSetpoint",{NewCurrentSetpoint=setTemp},dID)
setTemp = nil


Version 1 of the Main scene LUUP will do nothing if run from the UI because, if a trigger did not occur, setTemp will be nil. Version 2, if run from the UI, will set the temperature setpoint to 20.
« Last Edit: November 09, 2014, 07:22:05 am by RexBeckett »

Offline RexBeckett

  • Master Member
  • *******
  • Posts: 3888
  • Karma: +476/-10
Conditional Scene Execution: Some Examples - Time Window
« Reply #17 on: January 07, 2014, 10:47:29 am »
There were two requests for this type of scene condition in the last 24 hours so it must be worth posting here. The objective is to allow or prevent a scene executing when triggers occur in a short time period (window).

All these examples save a timestamp each time they are run using a global variable tLastOnD99. On each run, the saved timestamp is subtracted from the current time and compared to the specified time window (twSecs). To allow this code to be used for more than one triggering device, the 99 in tLastOnD99 should be replaced with the device ID of the triggering device. This is simply to avoid undesired side effects so any other name could be used instead.

As with previous examples, the code may be placed in either a Trigger's Luup event to allow/prevent that trigger or on the scene's LUUP tab where it will affect all triggers and manual operation.

Allow the scene to run when a trigger occurs within twSecs of the last one (e.g. on/off/on):
Code: [Select]
local twSecs = 5 -- Number of seconds in time window
local tNow = os.time()
local tLastOn = tLastOnD99 or 0
tLastOnD99 = tNow
return ((tNow - tLastOn) <= twSecs)

Allow the scene to run provided a trigger occurs at least twSecs after the last one:
Code: [Select]
local twSecs = 5 -- Number of seconds in time window
local tNow = os.time()
local tLastOn = tLastOnD99 or 0
tLastOnD99 = tNow
return ((tNow - tLastOn) >= twSecs)

Generic version:
Code: [Select]
local twSecs = 5 -- Number of seconds in time window
local allow = true              -- true runs scene during time window, false blocks it
local tNow = os.time()
local tLastOn = tLastOnD99 or 0
tLastOnD99 = tNow
return (((tNow - tLastOn) <= twSecs) == allow)

« Last Edit: August 31, 2014, 04:46:44 am by RexBeckett »

Offline RexBeckett

  • Master Member
  • *******
  • Posts: 3888
  • Karma: +476/-10
Service IDs, Variables and Actions
« Reply #18 on: January 21, 2014, 06:31:29 pm »
One of the most frequent problems we see in requests for help with Lua code, is errors in Service IDs and variable or parameter names in luup function calls. These errors can be tricky to find. Even one character in the wrong case will prevent the call working correctly: A luup.variable_get(...) will return a nil instead of the expected value; A luup.call_action(...) may do absolutely nothing.

Listed below are example luup calls for the most common device types. All examples assume that local variable dID contains the ID of the device being addressed. e.g. local dID = 123 Alternatively, replace dID in the calls with the required device ID number. Examples are given for reading a device variable using luup.variable_get(...) and for initiating an action with luup.call_action(...). It is also possible to directly set device variables but, in many cases, this will have little or no apparent effect on the device. Generally it is better to use luup.call_action(...) rather than directly setting device variables.

The examples are also in the attached pdf file. If you drop it on your desktop, you can quickly open it to copy and paste the calls into your Lua. If the device you want to address is not listed, you can find the Service ID by hovering the mouse cursor over the name of the variable on the device's Advanced tab. 


On/Off Switch
Set Target, read Status. "0" = Off, "1" = On.

Code: [Select]
local status = luup.variable_get("urn:upnp-org:serviceId:SwitchPower1", "Status", dID)

luup.call_action("urn:upnp-org:serviceId:SwitchPower1", "SetTarget", {newTargetValue = "1"}, dID)


Virtual Switch
Set Target, read Status. "0" = Off, "1" = On.

Code: [Select]
local status = luup.variable_get("urn:upnp-org:serviceId:VSwitch1", "Status", dID)

luup.call_action("urn:upnp-org:serviceId:VSwitch1", "SetTarget", {newTargetValue = "1"}, dID)


Dimmable Light
Set LoadLevelTarget, read LoadLevelStatus. "0" = Off, "100" = Full.

Code: [Select]
local level = luup.variable_get("urn:upnp-org:serviceId:Dimming1", "LoadLevelStatus", dID)

luup.call_action("urn:upnp-org:serviceId:Dimming1", "SetLoadLevelTarget", {newLoadlevelTarget = "50"}, dID)


Thermostat
Set ModeTarget, read ModeStatus. "Off", "HeatOn", "CoolOn", "AutoChangeOver".

Code: [Select]
local mode = luup.variable_get("urn:upnp-org:serviceId:HVAC_UserOperatingMode1", "ModeStatus", dID)

luup.call_action("urn:upnp-org:serviceId:HVAC_UserOperatingMode1", "SetModeTarget", {NewModeTarget = "Off"}, dID)

Set and read CurrentSetpoint. (Degrees)

Code: [Select]
local setpoint = luup.variable_get("urn:upnp-org:serviceId:TemperatureSetpoint1_Heat", "CurrentSetpoint", dID)

luup.call_action("urn:upnp-org:serviceId:TemperatureSetpoint1_Heat", "SetCurrentSetpoint", {NewCurrentSetpoint = "25"}, dID)

local setpoint = luup.variable_get("urn:upnp-org:serviceId:TemperatureSetpoint1_Cool", "CurrentSetpoint", dID)

luup.call_action("urn:upnp-org:serviceId:TemperatureSetpoint1_Cool", "SetCurrentSetpoint", {NewCurrentSetpoint = "30"}, dID)


Temperature Sensor
Code: [Select]
local temp = luup.variable_get("urn:upnp-org:serviceId:TemperatureSensor1", "CurrentTemperature", dID)

Generic Sensor
Code: [Select]
local level = luup.variable_get("urn:micasaverde-com:serviceId:GenericSensor1", "CurrentLevel", dID)

Light Sensor
Code: [Select]
local level = luup.variable_get("urn:micasaverde-com:serviceId:LightSensor1", "CurrentLevel", dID)

Humidity Sensor
Code: [Select]
local level = luup.variable_get("urn:micasaverde-com:serviceId:HumiditySensor1", "CurrentLevel", dID)

Security Sensor
Code: [Select]
local tripped = luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1", "Tripped", dID)

local armed = luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1", "Armed", dID)

local lasttrip = luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1", "LastTrip", dID)

luup.call_action("urn:micasaverde-com:serviceId:SecuritySensor1", "SetArmed", {newArmedValue = "1"}, dID)


Window Covering
Use Dimmable Light Status variable for current position. Down = 0, Up = 100.

Code: [Select]
local level = luup.variable_get("urn:upnp-org:serviceId:Dimming1", "LoadLevelStatus", dID)

luup.call_action("urn:upnp-org:serviceId:WindowCovering1", "Up", {}, dID)

luup.call_action("urn:upnp-org:serviceId:WindowCovering1", "Down", {}, dID)

luup.call_action("urn:upnp-org:serviceId:WindowCovering1", "Stop", {}, dID)


Variable Container
Set and read VariableN where N is 1 to 5.

Code: [Select]
local vcvar1 = luup.variable_get("urn:upnp-org:serviceId:VContainer1", "Variable1", dID)

luup.variable_set("urn:upnp-org:serviceId:VContainer1", "Variable1",newvalue, dID)

luup.variable_set("urn:upnp-org:serviceId:VContainer1", "Variable5","newtext", dID)


DayTime plugin
Set and read Status. "0" = Night, "1" = Day.

Code: [Select]
local itsday = luup.variable_get("urn:rts-services-com:serviceId:DayTime", "Status", dID)

luup.variable_set("urn:rts-services-com:serviceId:DayTime", "Status", "1", dID)


Edit: 13/05/2014 08:50  Corrected typo in DayTime example.
« Last Edit: May 13, 2014, 03:51:45 am by RexBeckett »

Offline Brientim

  • Beta Testers
  • Sr. Hero Member
  • *****
  • Posts: 2492
  • Karma: +77/-7
Re: Conditional Scene Execution: Some Examples
« Reply #19 on: January 21, 2014, 06:40:02 pm »
Then other was I forget to cover is drilling into the device utilising lu_invoke function. It will eventually display the service ID and actions available for the selected device.

http://vera.IP.address/port_3480/data_request?id=lu_invoke



Offline RexBeckett

  • Master Member
  • *******
  • Posts: 3888
  • Karma: +476/-10
Re: Conditional Scene Execution: Some Examples
« Reply #20 on: January 21, 2014, 07:33:27 pm »
Then other was I forget to cover is drilling into the device utilising lu_invoke function. It will eventually display the service ID and actions available for the selected device.

http://vera.IP.address/port_3480/data_request?id=lu_invoke

A point well made, my antipodean friend. We should perhaps warn though that, just because lu_invoke lists an action doesn't mean that a device or plugin actually implements it.

Offline Brientim

  • Beta Testers
  • Sr. Hero Member
  • *****
  • Posts: 2492
  • Karma: +77/-7
Conditional Scene Execution: Some Examples
« Reply #21 on: January 21, 2014, 07:41:22 pm »
Of course, the warning should be noted by those who venture below the surface of the Vera...
« Last Edit: January 21, 2014, 08:13:43 pm by Brientim »

Offline henryiii

  • Newbie
  • *
  • Posts: 10
  • Karma: +1/-0
Re: Conditional Scene Execution: Some Examples
« Reply #22 on: January 30, 2014, 02:05:27 pm »
I am a new user to Vera. I have a lamp plugged into a Wemo unit that is access through Vera and a switch for the overhead lights. I am trying to create a scene that will turn out the lamp when the overhead is turned on, turn the lamp back on when the over head light is shut off, and the ability to turn them both out at night.

This seems very difficult to me. Step by step, if this is possible, is the only way for me at this point. Please help.

Thank you.

Offline RexBeckett

  • Master Member
  • *******
  • Posts: 3888
  • Karma: +476/-10
Delayed Actions
« Reply #23 on: February 02, 2014, 07:13:15 am »
Another favourite forum question concerns using delays in scene Lua. It is tempting to do this with luup.sleep(milliseconds) but this can lead to problems. While luup.sleep(...) is executing, other Vera events can be blocked. A peak of activity at this point can cause a Vera restart. This is one possible cause of unexplained restarts.

Luup provides a more-robust way of achieving delays with luup.call_delay("callfunction",secs,"parmstring"). This will call the function named callfunction after a delay of secs seconds and pass it the optional parameter parmstring. The called function must be global (i.e. not local). After the luup.call_delay(...), the main code continues to execute and may terminate. Multiple luup.call_delay(...) calls may be made to the same or different called functions.

For example, the following code turns on a light and then turns it off after ten seconds. You could, of course, do this simply with scene action delays but it's a stepping stone.
Code: [Select]
luup.call_action("urn:upnp-org:serviceId:SwitchPower1","SetTarget",{ newTargetValue=1 },66)
luup.call_delay("delayOff",10)
-- Main code terminates at this point

-- Function to be called after delay
function delayOff()
     luup.call_action("urn:upnp-org:serviceId:SwitchPower1","SetTarget",{ newTargetValue=0},66)
end

Because the called function is global, it does not have access to any of the local variables in the main part of your code. You could make your variables global but be careful how you name them to avoid side effects with other code. A cleaner approach is to pass them via the optional parameter. This parameter is a string so you will need to convert numeric data for some purposes.

In this example, the device ID of the switch is passed as the parameter.
Code: [Select]
local dID = 66
luup.call_action("urn:upnp-org:serviceId:SwitchPower1","SetTarget",{ newTargetValue=1 },dID)
luup.call_delay("delayOff",10,dID)

function delayOff(dev)
     local devno = tonumber(dev)
     luup.call_action("urn:upnp-org:serviceId:SwitchPower1","SetTarget",{ newTargetValue=0},devno)
end

The called function can also issue a luup.call_delay(...) to itself. This allows timed sequences to be programmed. The following example will dim a light by 10% every two seconds until it reaches zero.
Code: [Select]
local dID = 99
luup.call_delay("delayDim",2,dID)

function delayDim(dev)
     local devno = tonumber(dev)
     local lls = tonumber((luup.variable_get("urn:upnp-org:serviceId:Dimming1", "LoadLevelStatus", devno)))
     local newlls = lls - 10
     if newlls < 0 then newlls = 0 end
     luup.call_action("urn:upnp-org:serviceId:Dimming1", "SetLoadLevelTarget", {newLoadlevelTarget = newlls}, devno)
     if newlls > 0 then luup.call_delay("delayDim",2,dev) end
end

Only one parameter string can be passed to the called function. If you need to pass more than one item, you will need to encode them into the string. Simple numeric items can be passed as a comma-separated list. The next example uses this technique to pass three numeric values. The resulting code will either dim a light down to zero or up to 100% - depending on its level when the scene is run.
Code: [Select]
local dID = 99
local dstep, dtarget
local level = tonumber((luup.variable_get("urn:upnp-org:serviceId:Dimming1", "LoadLevelStatus", dID)))
if level > 50 then
     dtarget = 0
     dstep = -10
else
     dtarget = 100
     dstep = 10
end
local prms = string.format("%d,%d,%d",dID,dtarget,dstep)
luup.call_delay("delayDim",2,prms)

function delayDim(parms)
     local pdev,ptgt,pstp = string.match(parms,"(%d+),(%d+),([%-%d]+)")
     local devno = tonumber(pdev)
     local target = tonumber(ptgt)
     local step = tonumber(pstp)
     local lls = tonumber((luup.variable_get("urn:upnp-org:serviceId:Dimming1", "LoadLevelStatus", devno)))
     local newlls = lls + step
     if step > 0 then
          if newlls > target then newlls = target end
     else
          if newlls < target then newlls = target end
     end
     luup.call_action("urn:upnp-org:serviceId:Dimming1", "SetLoadLevelTarget", {newLoadlevelTarget = newlls}, devno)
     if newlls ~= target then luup.call_delay("delayDim",2,parms) end
end

Parameters may also be passed as a serialized table. See Passing a Serialized Table.

I hope some of these examples will help to point the way to a solution for your particular requirements. If not, I recommend taking a look at the Program Logic Event Generator (PLEG) plugin.
 
« Last Edit: February 03, 2014, 06:37:05 am by RexBeckett »

Offline RexBeckett

  • Master Member
  • *******
  • Posts: 3888
  • Karma: +476/-10
Re: Conditional Scene Execution: Some Examples
« Reply #24 on: February 02, 2014, 01:19:03 pm »
I am a new user to Vera. I have a lamp plugged into a Wemo unit that is access through Vera and a switch for the overhead lights. I am trying to create a scene that will turn out the lamp when the overhead is turned on, turn the lamp back on when the over head light is shut off, and the ability to turn them both out at night.

This seems very difficult to me. Step by step, if this is possible, is the only way for me at this point. Please help.

Thank you.

@henryiii, you might get more replies if you posted your question in the main Scene Scripting part of the forum. I don't think too many people come here.

It sounds as though you need two scenes: One triggered by the overhead light being turned on that turns off the Wemo light; One triggered by the overhead light being turned off that turns on the Wemo light. Is that really what you want? No other conditions, times, etc?

Offline henryiii

  • Newbie
  • *
  • Posts: 10
  • Karma: +1/-0
Re: Conditional Scene Execution: Some Examples
« Reply #25 on: February 02, 2014, 02:27:55 pm »
The idea is that both lights are not consuming electricity to light the same room at the same time. The over heal light washes out the lamp light. So, it sound like that is what I need. How would I configure that in two scenes then bring then to work the way I intend?
« Last Edit: February 02, 2014, 02:34:42 pm by henryiii »

Offline RexBeckett

  • Master Member
  • *******
  • Posts: 3888
  • Karma: +476/-10
Delayed Actions - Passing a Serialized Table
« Reply #26 on: February 03, 2014, 06:33:35 am »
As explained in an earlier post, the optional parameter passed by luup.call_delay(...) is a single string. If you need to pass several parameters to the called function, a Lua table can be serialized into that string and recreated when the called function executes.

The general-purpose serialize function in the following example will convert a table containing numeric, string, boolean or nested table elements into a single string. The table can be recreated using the Lua loadstring statement.

This example performs the same function as the previous one but a serialized table is used to pass the three numeric values. The values are initially set in the table dparms which is then serialized and sent as the parameter in luup.call_delay(...). The called function uses loadstring to recreate the table as xparms and can then access the individual variables using xparms.<variablename> notation. The resulting code will either dim a light down to zero or up to 100% - depending on its level when the scene is run.

Code: [Select]
local function serialize(val,name)
local tmp = ""
if name then tmp = tmp .. name .. "=" end
if type(val) == "table" then
tmp = tmp .. "{"
for k, v in pairs(val) do
if type(k) == "number" then
tmp =  tmp .. serialize(v) .. ","
else
tmp =  tmp .. serialize(v, k) .. ","
end
end
tmp = tmp .. "}"
elseif type(val) == "number" then
tmp = tmp .. tostring(val)
elseif type(val) == "string" then
tmp = tmp .. string.format("%q", val)
elseif type(val) == "boolean" then
tmp = tmp .. (val and "true" or "false")
else
tmp = tmp .. "\"[inserializeable datatype:" .. type(val) .. "]\""
end
return tmp
end

local dID = 99
local dparms = {}
dparms.dev = dID
local level = tonumber((luup.variable_get("urn:upnp-org:serviceId:Dimming1", "LoadLevelStatus", dID)))
if level > 50 then
     dparms.target = 0
     dparms.step = -10
else
     dparms.target = 100
     dparms.step = 10
end
luup.call_delay("delayDim",2,serialize(dparms))

function delayDim(parms)
     assert(loadstring("xparms="..parms))()
     local lls = tonumber((luup.variable_get("urn:upnp-org:serviceId:Dimming1", "LoadLevelStatus", xparms.dev)))
     local newlls = lls + xparms.step
     if xparms.step > 0 then
          if newlls > xparms.target then newlls = xparms.target end
     else
          if newlls < xparms.target then newlls = xparms.target end
     end
     luup.call_action("urn:upnp-org:serviceId:Dimming1", "SetLoadLevelTarget", {newLoadlevelTarget = newlls}, xparms.dev)
     if newlls ~= xparms.target then luup.call_delay("delayDim",2,parms) end
end

Offline kiethr

  • Full Member
  • ***
  • Posts: 108
  • Karma: +1/-2
Re: Conditional Scene Execution: Some Examples
« Reply #27 on: February 24, 2014, 10:01:01 pm »
Not a code expert by any means, but i could use a little help.  When a door is triggered a light will come on for 5 minutes during certain times of the day (done by LUUP code) What I want to do is add code to only run the scene if the light being triggered is off.  Its kind of a pain if the light was on when the scene ran and the light goes off 5 minutes later when someone else is still working in the room.  So here is the code i have been playing with.  The first two lines is what i added to the code that was working. the device ID is 32 which is a GE/JASCO single pole wall switch. While we are at it I would like to change the local start time to sunset and leave the end time as something I can configure.  Thanks

local switchOnOff = luup.variable_get("urn:upnp-org:serviceId:SwitchPower1", "Status", 32)
if (switchOnOff == "0") then

local startTime = "18:00"
local endTime   = "23:59"
 
local hour = tonumber( startTime:sub( startTime:find("%d+") ) )
local minute = tonumber(startTime:sub(-2))
 
if hour and minute then
    startTime = hour * 100 + minute
else
    luup.log("ERROR: invalid start time")
    return false
end
 
hour = tonumber( endTime:sub( endTime:find("%d+") ) )
minute = tonumber(endTime:sub(-2))
 
if hour and minute then
    endTime = hour * 100 + minute
else
    luup.log("ERROR: invalid end time")
    return false
end
 
local currentTime = os.date("*t")
currentTime = currentTime.hour * 100 + currentTime.min
 
luup.log("startTime = " .. startTime .. "; currentTime = " .. currentTime .. "; endTime = " .. endTime)
 
if startTime <= endTime then
    -- Both the start time and the end time are in the same day:
    -- if the current time is in the given interval, run the scene.
    if startTime <= currentTime and currentTime <= endTime then
        return true
    end
else
    -- The start time is before midnight, and the end time is after midnight:
    -- if the current time is not outside the given interval, run the scene.
    if not (endTime < currentTime and currentTime < startTime) then
        return true
    end
end
 
return false
« Last Edit: February 24, 2014, 10:50:21 pm by kiethr »

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2204
  • Karma: +29/-38
  • Life Moves Pretty Fast....
    • Node Central
Re: Conditional Scene Execution: Some Examples
« Reply #28 on: February 25, 2014, 02:24:38 am »
Hi @kiethr

What are you using to check if someone is still in the room working?

I have a similar set up for my kitchen light but using PLEG, but rather than use the light switch as the trigger I have the EZMotion 3in1 sensor working as an occupancy sensor, so when it's tripped (between a certain time) it comes on and then turns off after x mins when the sensor reports there's no longer any motion/occupancy

Offline RexBeckett

  • Master Member
  • *******
  • Posts: 3888
  • Karma: +476/-10
Re: Conditional Scene Execution: Some Examples
« Reply #29 on: February 25, 2014, 03:16:32 am »
Try this, @kiethr:

Code: [Select]
local switchOnOff = luup.variable_get("urn:upnp-org:serviceId:SwitchPower1", "Status", 32)
if (switchOnOff == "1") then return false end

local endTime   = "23:59"

local ssTime = luup.sunset() % 86400
 
local hour = math.floor(ssTime / 3600)
local minute = math.floor((ssTime % 3600) / 60)
 
local startTime = hour * 100 + minute
 
hour = tonumber( endTime:sub( endTime:find("%d+") ) )
minute = tonumber(endTime:sub(-2))
 
if hour and minute then
    endTime = hour * 100 + minute
else
    luup.log("ERROR: invalid end time")
    return false
end
 
local currentTime = os.date("*t")
currentTime = currentTime.hour * 100 + currentTime.min
 
luup.log("startTime = " .. startTime .. "; currentTime = " .. currentTime .. "; endTime = " .. endTime)
 
if startTime <= endTime then
    -- Both the start time and the end time are in the same day:
    -- if the current time is in the given interval, run the scene.
    if startTime <= currentTime and currentTime <= endTime then
        return true
    end
else
    -- The start time is before midnight, and the end time is after midnight:
    -- if the current time is not outside the given interval, run the scene.
    if not (endTime < currentTime and currentTime < startTime) then
        return true
    end
end
 
return false