4 * Author: brian@bevey.org
7 * Arm a simple security system based on mode. Has a grace period to allow an
8 * ever present lag in presence detection.
12 name: "Forgiving Security",
13 namespace: "imbrianj",
14 author: "brian@bevey.org",
15 description: "Alerts you if something happens while you're away. Has a settable grace period to compensate for presence sensors that may take a few seconds to be noticed.",
16 category: "Safety & Security",
17 iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
18 iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience%402x.png"
22 section("Things to secure?") {
23 input "contacts", "capability.contactSensor", title: "Contact Sensors", multiple: true, required: false
24 input "motions", "capability.motionSensor", title: "Motion Sensors", multiple: true, required: false
27 section("Alarms to go off?") {
28 input "alarms", "capability.alarm", title: "Which Alarms?", multiple: true, required: false
29 input "lights", "capability.switch", title: "Turn on which lights?", multiple: true, required: false
32 section("Delay for presence lag?") {
33 input name: "presenceDelay", type: "number", title: "Seconds (defaults to 15s)", required: false
36 section("Notifications?") {
37 input "sendPushMessage", "enum", title: "Send a push notification?", metadata: [values: ["Yes", "No"]], required: false
38 input "phone", "phone", title: "Send a Text Message?", required: false
41 section("Message interval?") {
42 input name: "messageDelay", type: "number", title: "Minutes (default to every message)", required: false
56 state.lastTrigger = now()
57 state.deviceTriggers = []
58 subscribe(contacts, "contact.open", triggerAlarm)
59 subscribe(motions, "motion.active", triggerAlarm)
62 def triggerAlarm(evt) {
63 def presenceDelay = presenceDelay ?: 15
65 if(now() - (presenceDelay * 1000) > state.lastTrigger) {
66 log.warn("Stale event - ignoring")
68 state.deviceTriggers = []
71 state.deviceTriggers.add(evt.displayName)
72 state.triggerMode = location.mode
73 state.lastTrigger = now()
75 log.info(evt.displayName + " triggered an alarm. Waiting for presence lag.")
76 runIn(presenceDelay, "fireAlarm")
80 if(state.deviceTriggers.size() > 0) {
81 def devices = state.deviceTriggers.unique().join(", ")
83 if(location.mode == state.triggerMode) {
84 log.info(devices + " alarm triggered and mode hasn't changed.")
85 send(devices + " alarm has been triggered!")
91 log.info(devices + " alarm triggered, but it looks like you were just coming home. Ignoring.")
95 state.deviceTriggers = []
99 def delay = (messageDelay != null && messageDelay != "") ? messageDelay * 60 * 1000 : 0
101 if(now() - delay > state.lastMessage) {
102 state.lastMessage = now()
103 if(sendPushMessage == "Yes") {
104 log.debug("Sending push message.")
109 log.debug("Sending text message.")
117 log.info("Have a message to send, but user requested to not get it.")