Sure. I'm planning on re-writing this using the new method that @chuck.schwer gave me where you add a second boolean "true" parameter to currentValue to avoid all of the "runIn" nonsense... But in the meantime this is what I have that's working fairly well for me right now. It's very specific to my use case so you may need to make some modifications for yours:
definition(
name: "Auto Lock and Unlock Doors",
namespace: "jeremyakers",
author: "Jeremy Akers",
description: "Automatically lock and unlock doors based on HSM state and presense.",
category: "Safety & Security",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience%402x.png"
)
preferences {
section("Parameters: ")
{
input "presence", "capability.presenceSensor", title: "Presence sensors: ", multiple: true
input "locksToLock","capability.lock", title: "Locks to lock when HSM armed: ", multiple: true
input "locksToUnlock","capability.lock", title: "Locks to unlock when anyone arrives: ", multiple: true
input "unlock", "enum", title: "Unlock when presence is detected?", options: ["Yes","No"]
input "recipients", "capability.speechSynthesis", title: "Notifications Device", multiple: true
input "driveway_motion", "capability.motionSensor", title: "Driveway Motion", required: true, multiple: true
input "driveway_virtual_motion", "capability.motionSensor", title: "Virtual Driveway Motion sensor to use trigger lighting", required: true
input "seconds", "number", title: "Seconds", required: true
input "garage_door", "capability.doorControl", title: "Garage Door to Open When home", required: true
input "chimes", "capability.speechSynthesis", title: "Devices to Chime for Driveway Notifications", multiple: true
input "chime_choice", "number", title: "Which chime sound to generate when driveway motion detected"
input "mute_seconds", "number", title: "Seconds to mute driveway Pushover notifcations after closing garage door."
}
}
def installed()
{
subscribe(presence, "presence", statusHandler)
subscribe(location, "hsmStatus", statusHandler)
subscribe(driveway_motion, "motion", motionHandler)
}
def updated()
{
unsubscribe()
subscribe(presence, "presence", statusHandler)
subscribe(location, "hsmStatus", statusHandler)
subscribe(driveway_motion, "motion", motionHandler)
}
def statusHandler(evt)
{
def triggerTime = atomicState.triggerTime
if((now() - triggerTime) < 5000)
{
return
}
atomicState.triggerTime = now()
if (evt.value == "present")
{
if (unlock == "Yes")
{
if (locksToUnlock.count{it.currentLock == "unlocked"} != locksToUnlock.size())
{
sendMessage("[N]Unlocking doors at arrival of $evt.linkText")
}
runIn(3, unlockDoors)
}
}
else if(evt.value == "armedAway" || evt.value == "armedHome")
{
runIn(5, lockDoors)
}
else if(evt.value == "disarmed")
{
sendMessage("[N]HSM was disarmed")
}
//log.info("Thread leaving synchronized block: " + randomThreadID)
}
def unlockDoors()
{
//locksToUnlock.unlock()
for(lock in locksToUnlock)
{
//sendMessage("Unlocking door at arrival of $evt.linkText")
lock.unlock()
pause(2000)
}
}
def lockDoors()
{
if (locksToLock.count{it.currentLock == "locked"} != locksToLock.size())
{
sendMessage("[L]Locking doors after HSM Armed.")
}
//locksToLock.lock()
for(lock in locksToLock)
{
//sendMessage("Door locked after HSM Armed.")
lock.lock()
pause(5000)
}
runIn(10, retryLocks)
}
def retryLocks()
{
for(lock in locksToLock)
{
if (lock.currentValue("lock") != "locked")
{
log.info("Lock failed to lock on first try, retrying: ${lock.displayName}")
lock.lock()
pause(7000)
}
}
runIn(15, verifyLocks)
}
def verifyLocks()
{
for(lock in locksToLock)
{
if (lock.currentValue("lock") != "locked")
{
sendMessage("FAILED to lock ${lock.displayName} after HSM Armed, lock.currentValue = " + lock.currentValue("lock"))
}
}
sendMessage("[L]All doors successfully locked and verified after HSM Armed.")
}
def motionHandler(evt)
{
def triggerTime = atomicState.motionTriggerTime
if(((now() - triggerTime)) < 10000)
{
return
}
atomicState.motionTriggerTime = now()
if(presence.collect { it.eventsSince(new Date(now() - (1000 * seconds)))}.flatten().findAll{ it.value=="present" }) // If someone has recently become "present" after being away.
{
garage_door.open()
sendMessage("Opening Garage door after detecting presence and driveway motion within ${seconds} seconds")
// Give garage door opener time to respond before flooding z-wave network with other commands:
pause(500)
}
chimes.speak(chime_choice.toString()) // Play driveway notification on chime devices.
driveway_virtual_motion.active() // Trigger lighting rules.
}
def sendMessage(msg)
{
log.info(msg)
recipients.speak(msg)
}