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

Offline Ramiii

  • Jr. Member
  • **
  • Posts: 85
  • Karma: +0/-0
Re: Conditional Scene Execution: Some Examples
« Reply #60 on: March 05, 2014, 06:21:37 am »
Or I can do it via scenes with delayed actions to turn it off 1 min later and conditions would be night only and XBMC not playing.

Offline kiethr

  • Full Member
  • ***
  • Posts: 108
  • Karma: +1/-2
Re: Conditional Scene Execution: Some Examples
« Reply #61 on: March 05, 2014, 05:23:22 pm »
@RexBeckett, how log does it normally take for a response from micasaverde? I have also noticed that even thought the time and date are correct in the UI, when I use the automation tab to see when a scene ran last the date is 29 days ahead


Sent from my iPhone

Offline RexBeckett

  • Master Member
  • *******
  • Posts: 3888
  • Karma: +478/-10
Re: Conditional Scene Execution: Some Examples
« Reply #62 on: March 05, 2014, 06:32:43 pm »
Quote
how log does it normally take for a response from micasaverde?
That varies a lot. If you haven't had a response after a week, try an email to support@getvera.com

Quote
I have also noticed that even thought the time and date are correct in the UI, when I use the automation tab to see when a scene ran last the date is 29 days ahead
Are you sure Vera's date and time is set correctly? Note that the time shown on the UI comes from your PC not Vera. You can see Vera's date and time by looking at the latest LuaUPnP.log entries. See Logs.

Vera time gets set via your network when it reboots (through power-cycle or SETUP -> Net & Wifi -> Reboot). If your network is not running when Vera reboots, the time will not be set correctly.
 

Offline RexBeckett

  • Master Member
  • *******
  • Posts: 3888
  • Karma: +478/-10
Debugging Lua Code in Scenes - kwikLog
« Reply #63 on: March 06, 2014, 06:29:49 am »
Debugging Lua code in scenes can be very frustrating. When something doesn't work as you expected, you need to be able to see which parts of your code are being executed and, often, the value of key variables. Vera provides luup.log(...) to help with this but it is not always easy to find your log entries in LuaUPnP.log with all the other activity there.

kwikLog is a simple function that logs your messages, with a time stamp, to a standalone file. The file may be viewed from a browser by entering <veraip>/kwikLog.txt. A browser page refresh will show you the latest entries.

You can use kwikLog in several ways:
  • Add it to your scene Lua (above where you call it from your code)
  • Add it before code you run in Test Luup code (Lua)
  • Add it to Startup Lua so that you can use it from any scene
If you add it to Startup Lua (APPS -> Develop Apps -> Edit Startup Lua), remove the word local from the first line.

Code: [Select]
local function kwikLog(message, clear)
local socket = require("socket")
local time = socket.gettime() or os.time()
local tms = string.format(".%03d  ",math.floor (1000 * (time % 1)))
local stamp = os.date("%d %b %Y  %T",math.floor(time)) .. tms
local mode = "a+"
if clear then mode = "w+" end
local file = io.open("/www/kwikLog.txt", mode)
file:write(stamp .. (message or "") .. "\n")
file:close()
end

kwikLog has two arguments: The string you wish to log and, optionally, true if you want to clear the log file. If the second argument is missing or false, log messages are appended to the existing file. You can place calls to kwikLog anywhere in your code so you can see what is happening. For example:

Code: [Select]
kwikLog("SuperScene started",true)
local status = luup.variable_get("urn:upnp-org:serviceId:SwitchPower1","Status",123)
if status == "1" then kwikLog("Light is already on!") end
local level = luup.variable_get("urn:upnp-org:serviceId:Dimming1","LoadLevelStatus",123)
kwikLog("Dim level is " .. level)
if (status == "0") and (tonumber(level) > 0) then kwikLog("This can't happen...") end
etc.

Several users have recently had problems with Sunset and Sunrise triggers due to incorrect location information. As a quick demonstration of kwikLog, paste the following code into APPS -> Develop Apps -> Test Luup code (Lua) and click GO.   

Code: [Select]
local function kwikLog(message, clear)
local socket = require("socket")
local time = socket.gettime() or os.time()
local tms = string.format(".%03d  ",math.floor (1000 * (time % 1)))
local stamp = os.date("%d %b %Y  %T",math.floor(time)) .. tms
local mode = "a+"
if clear then mode = "w+" end
local file = io.open("/www/kwikLog.txt", mode)
file:write(stamp .. (message or "") .. "\n")
file:close()
end

kwikLog("Timezone: " .. luup.timezone .. " hours")
kwikLog("City: " .. luup.city)
kwikLog("Latitude: " .. luup.latitude .. " degrees")
kwikLog("Longitude: " .. luup.longitude .. " degrees")
local srtime = os.date("%c",luup.sunrise())
kwikLog("Next Sunrise: " .. srtime)
local sstime = os.date("%c",luup.sunset())
kwikLog("Next Sunset: " .. sstime)

Enter <veraip>/kwikLog.txt in a browser window to see if your location data is correct. Replace <veraip> with the IP address of your Vera (without the <>).
 


« Last Edit: March 06, 2014, 07:52:54 am by RexBeckett »

Offline kiethr

  • Full Member
  • ***
  • Posts: 108
  • Karma: +1/-2
Re: Conditional Scene Execution: Some Examples
« Reply #64 on: March 06, 2014, 10:03:44 pm »
@RexBeckett

Okay so this is pretty strange.  I entered the code you supplied to retrieve the time zone and such from my veralite and it returned the following:
06 Mar 2014  21:27:45.025  Timezone: -5 hours
06 Mar 2014  21:27:45.027  City: Swartz Creek
06 Mar 2014  21:27:45.028  Latitude: 42.9382 degrees
06 Mar 2014  21:27:45.030  Longitude: -83.8244 degrees
06 Mar 2014  21:27:45.031  Next Sunrise: Fri Mar  7 07:01:09 2014
06 Mar 2014  21:27:45.033  Next Sunset: Fri Mar  7 18:32:04 2014

Shortly after I pulled the above information, I triggered the scene we have been fooling with and this is information from the log:

06      03/06/14 21:36:12.513   Device_Variable::m_szValue_set device: 39 service: urn:micasaverde-com:serviceId:SecuritySensor1 variable: Tripped was: 0 now: 1 #hooks: 5 upnp: 0 v:0xb9a730/NONE duplicate:0 <0x2bab9680>
07      03/06/14 21:36:12.514   Event::Evaluate 16 Front Door Light On scene Front Door Light On is true users:(null) allow:1 <0x2bab9680>
08      03/06/14 21:36:12.514   Scene::RunScene running 66 Front Door Light On <0x2bab9680>
50      03/06/14 21:36:12.514   luup_log:0: Scene Debug: Light is off. <0x2bab9680>
50      03/06/14 21:36:12.515   luup_log:0: Scene Debug: startTime = 2332; currentTime = 2136; endTime = 2359 <0x2bab9680>
50      03/06/14 21:36:12.515   luup_log:0: Scene Debug: Skipping actions. <0x2bab9680>
08      03/06/14 21:36:12.516   JobHandler_LuaUPnP::HandleActionRequest device: 61 service: urn:richardgreen:serviceId:VeraAlert1 action: DeviceNotification <0x2bab9680>
08      03/06/14 21:36:12.517   JobHandler_LuaUPnP::HandleActionRequest argument DeviceID=39 <0x2bab9680>
08      03/06/14 21:36:12.517   JobHandler_LuaUPnP::HandleActionRequest argument Description=%20Front%20Door%20is%20tripped <0x2bab9680>
08      03/06/14 21:36:12.517   JobHandler_LuaUPnP::HandleActionRequest argument Name=Front%20Door%20Open <0x2bab9680>
08      03/06/14 21:36:12.517   JobHandler_LuaUPnP::HandleActionRequest argument Service=urn:micasaverde-com:serviceId:SecuritySensor1 <0x2bab9680>
08      03/06/14 21:36:12.518   JobHandler_LuaUPnP::HandleActionRequest argument Variables=Tripped <0x2bab9680>
08      03/06/14 21:36:12.518   JobHandler_LuaUPnP::HandleActionRequest argument Msg=Front%20Door%20-%20Open <0x2bab9680>
08      03/06/14 21:36:12.518   JobHandler_LuaUPnP::HandleActionRequest argument SceneID=88 <0x2bab9680>
08      03/06/14 21:36:12.518   JobHandler_LuaUPnP::HandleActionRequest argument Recipients=kiethr <0x2bab9680>
07      03/06/14 21:36:12.520   Event::Evaluate 20 Front Door Open scene Front Door Open is true users:408711 allow:1 <0x2bab9680>
08      03/06/14 21:36:12.521   Scene::RunScene running 88 Front Door Open <0x2bab9680>
07      03/06/14 21:36:12.521   Event::Evaluate 21 Front Door Open scene Front Door Open is false repeat 0/-1 <0x2bab9680>
07      03/06/14 21:36:12.521   Event::Evaluate 22 Front Door Closed scene Front Door Closed is false repeat 0/-1 <0x2bab9680>
50      03/06/14 21:36:12.524   luup_log:61: VeraAlert:61:SendAlert:Msg:Front Door - Open <0x2b385000>
50      03/06/14 21:36:12.525   luup_log:61: VeraAlert:61:ExpandRecipients:Checking:kiethr <0x2b385000>
50      03/06/14 21:36:12.525   luup_log:61: VeraAlert:61:ExpandRecipients:Adding User Specified Profile:Pushover <0x2b385000>
50      03/06/14 21:36:12.526   luup_log:61: VeraAlert:61:SendAlert:Sending to:Pushover <0x2b385000>
50      03/06/14 21:36:12.527   luup_log:61: VeraAlert:61:PushoverSend:Body:message=Front%20Door%20%2D%20Open&token=axG7NEfje7aHi9z7JqkJNya5K9HGhx&user=8Sw8F92HNwX3sxWYqpwh9CMUrRW5XR&priority=1&sound=intermission&title=Vera%20Alerts <0x2b385000>50      03/06/14 21:36:19.131   luup_log:56: VGinfo: Calling main loop with lul_device: 56 <0x2ceb9680>
50      03/06/14 21:36:19.131   luup_log:56: VGinitPhase: VacationGhost is disabled, sleep and start over <0x2ceb9680>
06      03/06/14 21:36:19.149   Device_Variable::m_szValue_set device: 56 service: urn:upnp-org:serviceId:VGhost1 variable: State was: 0 now: 0 #hooks: 0 upnp: 0 v:0xbf5828/NONE duplicate:1 <0x2ceb9680>
02      03/06/14 21:36:20.101   LOG_CHECK_MEMORY_LEAK pMem start 0x1218000 now 0x1270000 last 0x1256000 leaked 360448 <0x2bab9680>
02      03/06/14 21:36:24.103   ZW_Send_Data node 40 USING ROUTE 18.0.0.0 <0x2beb9680>
04      03/06/14 21:36:24.254   <Job ID="195" Name="pollnode #40 1 cmds" Device="58" Created="2014-03-06 21:36:24" Started="2014-03-06 21:36:24" Completed="2014-03-06 21:36:24" Duration="0.152490000" Runtime="0.150451000" Status="Successful" LastNote="" Node="40" NodeType="ZWaveNonDimmableLight" NodeDescription="Isaac's Light"/>^C
root@MiOS_35007455:/tmp/log/cmh#
root@MiOS_35007455:/tmp/log/cmh#

It still says sunset is way later than what it is.  Tech support tried getting into my box last night however there was an internet outage that prevented them from doing so (just my luck). I think they will try again tonight from the email I received from them.  Ill keep you posted. 

Offline RexBeckett

  • Master Member
  • *******
  • Posts: 3888
  • Karma: +478/-10
Re: Conditional Scene Execution: Some Examples
« Reply #65 on: March 07, 2014, 03:46:49 am »
Yes that is odd. It looks as though it is not correcting sunset for your timezone. If it works in Test Luup, it should work in a scene. Just to complete the picture, add the following at the start of your scene LUUP so all the info is in one place:

Code: [Select]
luup.log("Timezone: " .. luup.timezone .. " hours")
luup.log("City: " .. luup.city)
luup.log("Latitude: " .. luup.latitude)
luup.log("Longitude: " .. luup.longitude)
local srtime = os.date("%c",luup.sunrise())
luup.log("Sunrise: " .. srtime)
local sstime = os.date("%c",luup.sunset())
luup.log("Sunset: " .. sstime)

Offline Minnies

  • Full Member
  • ***
  • Posts: 217
  • Karma: +0/-0
Re: Conditional Scene Execution: Some Examples - Switches
« Reply #66 on: March 10, 2014, 11:14:32 pm »
We often want to allow or block scenes depending on the state of a Z-Wave switch (E.g. a light is on) or a VirtualSwitch (e.g. Home/Away). The VirtualSwitch (VS) plugin is very useful as a means of controlling scenes. You can create several different VS devices to signify various states of your home. E.g. Home/Away, OnVacation, HaveGuests, etc. VS devices can be set manually through the UI, by scenes or with other plugins.

Testing the state of a switch is essentially the same whether it is real or virtual but the serviceID must match the type of switch being tested.

Z-Wave Switch:
Code: [Select]
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)

Virtual Switch:
Code: [Select]
local dID = 32           -- Device ID of your VirtualSwitch
local allow = true       -- true runs scene if switch is on, false blocks it
local status = luup.variable_get("urn:upnp-org:serviceId:VSwitch1","Status",dID)
return ((status == "1") == allow)


Coming next: Time

Trying to adapt this for a multiswitch.  Any thoughts?

Multi switch ID = 175
Desired switch = Status2

local dID = 175           -- Device ID of your VirtualSwitch
local allow = true       -- true runs scene if switch is on, false blocks it
local status = luup.variable_get("urn:upnp-org:serviceId:VSwitch1","Status2",175)
return ((status2 == "1") == allow)

I have tried several different combinations and not been able to get one to pass Luup test.

Offline RexBeckett

  • Master Member
  • *******
  • Posts: 3888
  • Karma: +478/-10
Re: Conditional Scene Execution: Some Examples
« Reply #67 on: March 11, 2014, 02:42:26 am »
Quote
Trying to adapt this for a multiswitch.  Any thoughts?

You need to change the Service ID to the one used by MultiSwitch:

Code: [Select]
local dID = 175           -- Device ID of your MultiSwitch
local allow = true       -- true runs scene if switch is on, false blocks it
local status = luup.variable_get("urn:dcineco-com:serviceId:MSwitch1","Status2",175)
return ((status2 == "1") == allow)

Offline kiethr

  • Full Member
  • ***
  • Posts: 108
  • Karma: +1/-2
Re: Conditional Scene Execution: Some Examples
« Reply #68 on: March 11, 2014, 04:55:22 pm »
@RexBeckett

Here is what tech support had to say:

I checked your unit and it seems that the timezone for your location is setup properly. Please note that the timezone you are able to see in the logs is in UTC format, what?s why you are seeing there 23:24, but after applying your timezone, which is GMT-4, it is 19:24.
If you know for sure that the luup code is written properly, you can also try to use luup.is_night() instead of luup.sunset() and let me know how it goes.

so i am going to change that part of the code and see what happens.


Sent from my iPad using Tapatalk HD

Offline Minnies

  • Full Member
  • ***
  • Posts: 217
  • Karma: +0/-0
Re: Conditional Scene Execution: Some Examples
« Reply #69 on: March 11, 2014, 08:18:11 pm »
Quote
Trying to adapt this for a multiswitch.  Any thoughts?

You need to change the Service ID to the one used by MultiSwitch:

Code: [Select]
local dID = 175           -- Device ID of your MultiSwitch
local allow = true       -- true runs scene if switch is on, false blocks it
local status = luup.variable_get("urn:dcineco-com:serviceId:MSwitch1","Status2",175)
return ((status2 == "1") == allow)

Thanks but still no success when trying it in the test Luup code area.

Here is the data from the switch file:

Name: MultiSwitch
Device_type: urn:schemas-dcineco-com:device:MSwitch175:1
device_file: D_MSwitch175.xml
id: 175
Variables:
Status1   
Status2   
Status3   
Status4   
Status5   
Status6   
Status7   
Status8   

Offline RexBeckett

  • Master Member
  • *******
  • Posts: 3888
  • Karma: +478/-10
Re: Conditional Scene Execution: Some Examples
« Reply #70 on: March 11, 2014, 08:48:04 pm »
I missed spotting your typo in the last line. You are reading the value of Status2 into variable status but using variable status2 in the return statement which does not exist so will return nil. Try this:

Code: [Select]
local dID = 175           -- Device ID of your MultiSwitch
local allow = true       -- true runs scene if switch is on, false blocks it
local status = luup.variable_get("urn:dcineco-com:serviceId:MSwitch1","Status2",dID)
return ((status == "1") == allow)

Edit: I have added the code for MultiSwitch to the examples for Z-Wave and Virtual switches.
« Last Edit: March 22, 2014, 05:46:35 am by RexBeckett »

Offline quinn

  • Newbie
  • *
  • Posts: 19
  • Karma: +2/-3
Re: Conditional Scene Execution: Some Examples
« Reply #71 on: March 27, 2014, 09:48:51 pm »
 I am in the process of committing to using Vera3 for a $2M+ house.  I have been uncertain whether to proceed being doubtful whether certain functionality was possible because of Mios's poor, disorganized and inconsistent documentation, until I found RexBeckett.  His examples are clear and sufficiently detailed to answer most of my concerns.  After reading RexBeckett's work, which skillfully and completely illuminates LUUP plugins even for a na?ve user, LUUP itself seems to be a fairly straight forward and easily mastered language, mostly a C derivative I would say. 

For example, in the case of the Kicklog function he explains "Enter <veraip>/kwikLog.txt in a browser window to see if your location data is correct. Replace <veraip> with the IP address of your Vera (without the <>)".   Notice the careful disambiguating of what "<veraip>" is in his syntax.  Mios should really be paying Rex.

None of this is to suggest that online support is not good.  They are responsive and generally knowledgeable, but one question at a time to them is a very resource consuming approach--on both sides.

Incidentally, I wrote my first program in 1963, I know half a dozen programming languages, including the infamous SAS macro language.  The first program you write in any language is always the toughest.  That is why one or two careful and complete examples in the main documentation would have been most helpful, but a single reference to RexBeckett's forum page would have been much more.

Offline RexBeckett

  • Master Member
  • *******
  • Posts: 3888
  • Karma: +478/-10
Re: Conditional Scene Execution: Some Examples
« Reply #72 on: March 28, 2014, 04:36:10 am »
Many thanks for the feedback @quinn. I'm glad this thread has helped you to get started with Lua.

Offline ilikelife

  • Full Member
  • ***
  • Posts: 126
  • Karma: +2/-0
Re: Conditional Scene Execution: Some Examples
« Reply #73 on: April 04, 2014, 03:27:49 pm »
Hi @RexBeckett,
Since you pointed me here, I hope it's ok to ask questions here about delayed actions.  If not, please just point me in the right direction.
I think I understand that a function is global, so I need to either define variables within the function, or be very careful with naming global vars.   I also read somewhere it's not wise to question your code, but I'm missing something in the following:

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

What is (dev) ?  The 66 started as dID, and within the function, it's devno, but I'm lost with dev.  I hope I caught you in a typo, but I'm not betting on it...  :-[

I've written a solution for keeping a light on for some period past the "no motion" signal, if it's re-tripped during the delay period that seems to work well.  Right now I'm using the brute force method (mostly not using variables) but am passing the DELAY as the single variable until I figure out your encoding them into a string or table.

To turn the light on, I have an empty scene with a trigger on sensor 45 TRIPPED and this in the scene LUUP

Code: [Select]
local SENSOR = 45 -- The door/window sensor device number
local Garage = 16 -- the Garage Light device number
local SES_SID = "urn:micasaverde-com:serviceId:SecuritySensor1"
local SWITCH_SID = "urn:upnp-org:serviceId:SwitchPower1"

local status = luup.variable_get(SWITCH_SID,"Status",Garage)

    if (status == "0") then -- Don't keep turning it on if it's already on.
    luup.call_action(SWITCH_SID,"SetTarget",{newTargetValue="1" },Garage)
end

Then to turn it off, another empty scene with a trigger for sensor 45 NOT TRIPPED, and this in the scene LUUP. 

Code: [Select]
local SENSOR = 45 -- The door/window sensor device number
local Garage = 16 -- the Garage Light device number
local DELAY = 15 -- Seconds for testing with a door sensor
local SES_SID = "urn:micasaverde-com:serviceId:SecuritySensor1"
local SWP1_SID = "urn:upnp-org:serviceId:SwitchPower1"

luup.call_delay( "checkLastTrip", DELAY, DELAY)

-- Turn off the light only when it's not tripped and the DELAY time is expired.
function checkLastTrip()
local DelayTime = tonumber(DELAY)
local tripped = luup.variable_get( "urn:micasaverde-com:serviceId:SecuritySensor1", "Tripped", 45) or "0"
local lastTrip = luup.variable_get( "urn:micasaverde-com:serviceId:SecuritySensor1", "LastTrip", 45) or os.time()
if (tripped == "0" and (os.time() - lastTrip >= DelayTime)) then
luup.call_action("urn:upnp-org:serviceId:SwitchPower1","SetTarget",{newTargetValue="0" },16)
end
end

It works, and doesn't seem to tie up the system with loops that don't end, but it just doesn't seem good form to use empty scenes, but I can't make it work any other way.  Any suggestions or warnings or improvements that you can offer would be much appreciated.

Mike

Offline RexBeckett

  • Master Member
  • *******
  • Posts: 3888
  • Karma: +478/-10
Re: Conditional Scene Execution: Some Examples
« Reply #74 on: April 04, 2014, 04:11:42 pm »
Quote
I also read somewhere it's not wise to question your code, but I'm missing something in the following:
Quote
What is (dev) ?  The 66 started as dID, and within the function, it's devno, but I'm lost with dev.  I hope I caught you in a typo, but I'm not betting on it...  :-[
You're being very cautious, @ilikelife, but I don't bite.  ;D

The third parameter in luup.call_delay(callback, delay, parameter) is a string that is passed to the callback function when the delay expires. I simply use this parameter to pass the device ID that should be turned off. I called the argument dev in the definition of the callback function delayOff. Remember that it must be a string so I converted the string in dev to a number in devno. See: no magic, no typos...

Quote
it just doesn't seem good form to use empty scenes
Empty scenes don't really cost anything but if it bothers you, use a single scene and put your code on individual triggers.

Quote
It works...
I'm surprised if it continues to work reliably because there are a few problems with it:

Your global checkLastTrip function is referring to the local variable DELAY. This may not exist if it has been garbage-collected by the time the callback happens. Either define it inside checkLastTrip or pass it as the string parameter. When you pass a string through luup.call_delay(...), the callback function needs to define the receiving arguments as in my example.

The values returned by luup.variable_get(...) are strings. To avoid problems, use tonumber(...) to convert them before using them in calculations or comparisons.