I made a few changes so I thought I would share. Nothing new… I gathered bits and pieces from all over the forums to put this together.
My biggest problem was when I opened my garage door at the exact same moment the scene ran and the door immediately closed on me. Because of this I decided to monitor when the status for the device was last changed. To do this I used luup.variable_watch in the startup.lua
[code]
function EntryTimeStamp()
LastEntryStatus = os.time()
end
luup.variable_watch(“EntryTimeStamp”, “urn:micasaverde-com:serviceId:DoorLock1”, “Status”, 7)
function GarageTimeStamp()
LastGarageStatus = os.time()
end
luup.variable_watch(“GarageTimeStamp”, “urn:upnp-org:serviceId:SwitchPower1”, “Status”, 8)[/code]
Now whenever the device is locked/unlocked/etc the variables LastEntryStatus or LastGarageStatus update with the current os.time(). The only thing you need to watch for is if the device has yet to change state (ie system reboot) then these variables will be null.
I also left the kwikLog code in I used for debugging because I found it so useful. Anything you log using this will show up at /kwikLog.txt (ie 192.168.8.100/kwikLog.txt)
I also have the option to report only without actually doing anything (I use this during the day). Because of this I included code to throttle back the alerts since we never automatically fix the conditions we’re checking for.
I execute everything in 2 passes. The first pass checks the devices and then corrects any issues or exits if no action is needed. If it does change the device it will pause and make the second pass to verify the action was successful. It then alerts you via SMTP as to what was done (if anything).
My scene just runs on a timed interval and the only thing it does is execute this code. I tried to comment as much as possible but feel free to ask questions. Also, I’m still new to this so any advice is appreciated. Thanks to everyone who helped…
[code]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
local function notify(BODY)
local smtp = require(“socket.smtp”)
local SMTP_SERVER = "smtp.yourisp.net"
--local SMTP_AUTH_USER = "guessed"
--local SMTP_AUTH_PW = "xxxxxxxxx"
local SMTP_PORT = "25"
local USER_SENDING = "me@address.com"
local USER_RECEIVING = "1234567890@txt.att.net"
local USER_RECEIVING2 = "0123456789@txt.att.net"
local SUBJECT = "Vera Alert"
--local BODY = "Test"
local from = USER_SENDING
local rcpt = {
USER_RECEIVING,
USER_RECEIVING2
}
local mesgt = {
headers = {
to = USER_RECEIVING,
subject = SUBJECT
},
body = BODY
}
local r, e = smtp.send{
from = from,
rcpt = rcpt,
source = smtp.message(mesgt),
server = SMTP_SERVER,
port = SMTP_PORT,
--user = SMTP_AUTH_USER,
--password = SMTP_AUTH_PW
}
if (e) then
luup.log("SMTP ERROR: " .. e)
end
end
kwikLog(“Doing my thing”, true)
local message = “”
local actionDoor = “”
local actionGarage = “”
local reportOnly = false – Do we actually lock the door or just report it unlocked
local checkEntry = false – Used to know when to doublecheck lock
local checkGarage = false – Used to know when to doublecheck shut
local maxTimeOpen = 900 – Sets how long (in seconds) since last status change before you lock/shut the device
local reportInterval = 900 – Sets the minimum interval you will be notified when in report only mode
if (not LastEntryStatus) then LastEntryStatus = os.time() end – On system restart this may not be set yet
local timeSinceEntryChange = os.time() - LastEntryStatus – Prevents door from shutting/locking on you
local minutesSinceEntryChange = timeSinceEntryChange / 60 – convert to minutes for reporting
minutesSinceEntryChange = math.floor(minutesSinceEntryChange)
if (not LastGarageStatus) then LastGarageStatus = os.time() end – On system restart this may not be set yet
local timeSinceGarageChange = os.time() - LastGarageStatus – Prevents door from shutting/locking on you
local minutesSinceGarageChange = timeSinceGarageChange / 60 – convert to minutes for reporting
minutesSinceGarageChange = math.floor(minutesSinceGarageChange)
– This puts the code into reportOnly mode during the daytime
if (not luup.is_night()) then reportOnly = true end
kwikLog(“Outside of loop”)
– Run loop twice to verify lock/shut was successful
– Loop 1 will check and lock/shut
– Loop 2 will verify success (will not run if loop 1 did nothing)
for i=1,2 do
kwikLog("I’m here for pass " … i)
-- Check the Entry Door (0 is unlocked)
local varEntryState = luup.variable_get ("urn:micasaverde-com:serviceId:DoorLock1", "Status", 7)
if (varEntryState== "0" and reportOnly == false) then
if (checkEntry == true) then
-- This is the second pass and the door failed to lock
message = message .. "\nDOOR FAILED TO LOCK! CHECK IT!"
else
-- This is the first pass so try and lock the door if enough time has passed
if (timeSinceEntryChange > maxTimeOpen) then
message = message .. "\nEntry Door has been unlocked for " .. minutesSinceEntryChange .. " minutes! Attempting to Lock!"
luup.call_action ("urn:micasaverde-com:serviceId:DoorLock1", "SetTarget", { newTargetValue="1" }, 7)
checkEntry = true
end
end
elseif (checkEntry == true and reportOnly == false) then
-- This is the second pass and the door was successfully lovked last pass
mmessage = message .. "\nDoor was locked!"
elseif (varEntryState== "0" and reportOnly == true) then
-- Don't do anything, just report that the door isn't locked
if (timeSinceEntryChange > reportInterval) then
-- This is to prevent from SPAMing because the door is never locked by this code
message = message .. "\nReport Only: Entry Door has been unlocked for " .. minutesSinceEntryChange .. " minutes!"
end
end
-- Check Garage Door (1 is open)
local varGarageState = luup.variable_get ("urn:upnp-org:serviceId:SwitchPower1", "Status", 8)
if (varGarageState== "1" and reportOnly == false) then
if (checkGarage == true) then
-- This is the second pass and the garage failed to close
message = message .. "\nGARAGE FAILED TO CLOSE! CHECK IT!"
else
-- This is the first pass so try and shut the door if enough time has passed
if (timeSinceGarageChange > maxTimeOpen) then
message = message .. "\nGarage Door has been open for " .. minutesSinceGarageChange .. "minutes! Attempting to Shut!"
luup.call_action ("urn:upnp-org:serviceId:SwitchPower1", "SetTarget", { newTargetValue="0" }, 8)
checkGarage = true
end
end
elseif (checkGarage == true and reportOnly == false) then
-- This is the second pass and the garage was successfully shut last pass
message = message .. "\nGarage door was shut!"
elseif (varGarageState== "1" and reportOnly == true) then
-- Don't do anything, just report that the door isn't closed
if (timeSinceGarageChange > reportInterval) then
-- This is to prevent from SPAMing because the door is never closed by this code
message = message .. "\nReport Only: Garage Door has been open for " .. minutesSinceGarageChange .. "minutes!"
end
end
if (message == "") then
-- No actions were taken on first pass so we can stop now
kwikLog("Finished my thing")
return
end
if (reportOnly == true) then
-- Since we are just reporting we can end now
notify(message)
kwikLog("Finished my thing")
return
end
-- Pause for 120 seconds after first run and check again (to give devices time to report back)
if (i == 1) then luup.sleep(120000) end
end
– Let the users know what happened
kwikLog(“Finished my thing”)
notify(message)[/code]