/** * Notify If Left Unlocked * * Copyright 2014 George Sudarkoff * * 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: "Notify If Left Unlocked", namespace: "com.sudarkoff", author: "George Sudarkoff", description: "Send a push or SMS notification (and lock, if it's closed) if a door is left unlocked for a period of time.", 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("If this lock...") { input "aLock", "capability.lock", multiple: false, required: true input "openSensor", "capability.contactSensor", title: "Open/close sensor (optional)", multiple: false, required: false } section("Left unlocked for...") { input "duration", "number", title: "How many minutes?", required: true } section("Notify me...") { input "pushNotification", "bool", title: "Push notification" input "phoneNumber", "phone", title: "Phone number (optional)", required: false input "lockIfClosed", "bool", title: "Lock the door if it's closed?" } } def installed() { initialize() } def updated() { unsubscribe() initialize() } def initialize() { log.trace "Initializing with: ${settings}" subscribe(aLock, "lock", lockHandler) } def lockHandler(evt) { log.trace "${evt.name} is ${evt.value}." if (evt.value == "locked") { log.debug "Canceling lock check because the door is locked..." unschedule(notifyUnlocked) } else { log.debug "Starting the countdown for ${duration} minutes..." state.retries = 0 runIn(duration * 60, notifyUnlocked) } } def notifyUnlocked() { // if no open/close sensor specified, assume the door is closed def open = openSensor?.latestValue("contact") ?: "closed" def message = "${aLock.displayName} is left unlocked and ${open} for more than ${duration} minutes." log.trace "Sending the notification: ${message}." sendMessage(message) if (lockIfClosed) { if (open == "closed") { log.trace "And locking the door." sendMessage("Locking the ${aLock.displayName} as prescribed.") aLock.lock() } else { if (state.retries++ < 3) { log.trace "Door is open, can't lock. Rescheduling the check." sendMessage("Can't lock the ${aLock.displayName} because the door is open. Will try again in ${duration} minutes.") runIn(duration * 60, notifyUnlocked) } else { log.trace "The door is still open after ${state.retries} retries, giving up." sendMessage("Unable to lock the ${aLock.displayName} after ${state.retries} retries, giving up.") } } } } def sendMessage(msg) { if (pushNotification) { sendPush(msg) } if (phoneNumber) { sendSMS(phoneNumber, msg) } }