Just finished this today…
/**
* Is my home secure?
*
* Copyright 2014 Tim Slagle
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
definition(
name: "Is my home secure?",
namespace: "tslagle13",
author: "Tim Slagle",
description: "Check a set of doors, windows, and locks to see if your home is secure at a certain time or when mode changes.",
category: "Safety & Security",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png"
)
preferences {
section("Which mode changes trigger the check?") {
input "newMode", "mode", title: "Which?", multiple: true, required: false
}
section("When should I check? (once per day)") {
input "timeToCheck", "time", title: "When?(Optional)", required: false
}
section("Vacation mode: Check every X hours. (minimum every 5 hours)") {
input "timeToCheckVacation", "number", title: "How often? (Optional)", required: false
}
section("Which doors, windows, and locks should I check?"){
input "contacts", "capability.contactSensor", title: "Which door(s)?", multiple: true, required: true
input "locks", "capability.lock", title: "Which lock?", multiple: true, required: false
}
section("Notification delay... (defaults to 2 min") {
input "falseAlarmThreshold", "decimal", title: "Number of minutes", required: false
}
section("Via a push notification and/or an SMS message"){
input "phone", "phone", title: "Phone Number (for SMS, optional)", required: false
input "pushAndPhone", "enum", title: "Both Push and SMS?", required: false, options: ["Yes","No"]
}
section("Settings"){
input "sendPushUnsecure", "enum", title: "Send a SMS/push notification when home is unsecure?", metadata:[values:["Yes","No"]], required:true
input "sendPushSecure", "enum", title: "Send a SMS/push notification when house is secure?", metadata:[values:["Yes","No"]], required:true
input "lockAuto", "enum", title: "Lock door(s) automatically if found unsecure?", metadata:[values:["Yes","No"]], required:false
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
initialize()
}
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
unschedule()
initialize()
}
def initialize(){
if (newMode != null) {
subscribe(location, modeChangeHandler)
}
if (timeToCheck != null) {
schedule(timeToCheck, checkDoor)
}
initializeVacation()
schedule(timeToCheck, checkDoor)
}
def initializeVacation() {
if (timeToCheckVacation){
if (timeToCheckVacation > 4)
// Schedule polling daemon to run every N minutes
schedule("0 0 0/${timeToCheckVacation} * * ?", checkDoor)
}
}
def modeChangeHandler(evt) {
log.debug "Mode change to: ${evt.value}"
// Have to handle when they select one mode or multiple
if (newMode.any{ it == evt.value } || newMode == evt.value) {
def delay = (falseAlarmThreshold != null && falseAlarmThreshold != "") ? falseAlarmThreshold * 60 : 2 * 60
runIn(delay, "checkDoor")
}
}
def checkDoor(evt) {
log.debug("checkDoor")
def openContacts = contacts.findAll { it?.latestValue("contact") == 'open' }
def openLocks = locks.findAll { it?.latestValue("lock") == 'unlocked' }
if (openContacts || openLocks){
if (openContacts && openLocks){
def message = "ALERT: ${openContacts.join(', ')} and ${openLocks.join(', ')} are unsecure!"
sendUnsecure(message)
if (lockAuto != "No"){
lockDoors()
}
}
else {
def message = "ALERT: ${openContacts.join(', ')} ${openLocks.join(', ')} unsecure!"
sendUnsecure(message)
if (lockAuto != "No"){
lockDoors()
}
}
}
else if (!openContacts && !openLocks){
def message = "All doors, windows, and locks are secure"
sendSecure(message)
}
}
def lockDoors(){
if (lockAuto == "Yes"){
locks?.lock()
if(sendPushUnsecure != "No") {
log.debug("Sending push message")
if (!phone || pushAndPhone != "No") {
log.debug "sending push"
sendPush("${openLocks.join(', ')} now locked. You're welcome. Enjoy your day.")
}
if (phone) {
log.debug "sending SMS"
sendSms(phone, "${openLocks.join(', ')} now locked. You're welcome. Enjoy your day.")
}
}
}
}
private sendSecure(msg) {
log.debug("checking push")
if(sendPushSecure != "No"){
if (!phone || pushAndPhone != "No") {
log.debug "sending push"
sendPush(msg)
}
if (phone) {
log.debug "sending SMS"
sendSms(phone, msg)
}
}
else {
log.debug("Home is secure but settings don't require push")
}
log.debug(msg)
}
private sendUnsecure(msg) {
log.debug("checking push")
if(sendPushUnsecure != "No") {
log.debug("Sending push message")
if (!phone || pushAndPhone != "No") {
log.debug "sending push"
sendPush(msg)
}
if (phone) {
log.debug "sending SMS"
sendSms(phone, msg)
}
}
else {
log.debug("Home is unseecure but settings don't require push")
}
log.debug(msg)
}