2 * Copyright 2015 SmartThings
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
10 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
11 * for the specific language governing permissions and limitations under the License.
18 * Monitors a set of presence detectors and triggers a mode change when everyone has left.
23 namespace: "smartthings",
24 author: "SmartThings",
25 description: "Monitors a set of SmartSense Presence tags or smartphones and triggers a mode change when everyone has left. Used in conjunction with Big Turn Off or Make It So to turn off lights, appliances, adjust the thermostat, turn on security apps, and more.",
26 category: "Mode Magic",
27 iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/App-LightUpMyWorld.png",
28 iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/App-LightUpMyWorld@2x.png"
32 section("When all of these people leave home") {
33 input "people", "capability.presenceSensor", multiple: true
35 section("Change to this mode") {
36 input "newMode", "mode", title: "Mode?"
38 section("False alarm threshold (defaults to 10 min)") {
39 input "falseAlarmThreshold", "decimal", title: "Number of minutes", required: false
41 section( "Notifications" ) {
42 input("recipients", "contact", title: "Send notifications to", required: false) {
43 input "sendPushMessage", "enum", title: "Send a push notification?", options: ["Yes", "No"], required: false
44 input "phone", "phone", title: "Send a Text Message?", required: false
51 log.debug "Installed with settings: ${settings}"
52 // commented out log statement because presence sensor label could contain user's name
53 //log.debug "Current mode = ${location.mode}, people = ${people.collect{it.label + ': ' + it.currentPresence}}"
54 subscribe(people, "presence", presence)
58 log.debug "Updated with settings: ${settings}"
59 // commented out log statement because presence sensor label could contain user's name
60 //log.debug "Current mode = ${location.mode}, people = ${people.collect{it.label + ': ' + it.currentPresence}}"
62 subscribe(people, "presence", presence)
67 log.debug "evt.name: $evt.value"
68 if (evt.value == "not present") {
69 if (location.mode != newMode) {
70 log.debug "checking if everyone is away"
71 if (everyoneIsAway()) {
72 log.debug "starting sequence"
73 runIn(findFalseAlarmThreshold() * 60, "takeAction", [overwrite: false])
77 log.debug "mode is the same, not evaluating"
81 log.debug "present; doing nothing"
87 if (everyoneIsAway()) {
88 def threshold = 1000 * 60 * findFalseAlarmThreshold() - 1000
89 def awayLongEnough = people.findAll { person ->
90 def presenceState = person.currentState("presence")
92 // This device has yet to check in and has no presence state, treat it as not away long enough
95 def elapsed = now() - presenceState.rawDateCreated.time
98 log.debug "Found ${awayLongEnough.size()} out of ${people.size()} person(s) who were away long enough"
99 if (awayLongEnough.size() == people.size()) {
100 // TODO -- uncomment when app label is available
101 def message = "SmartThings changed your mode to '${newMode}' because everyone left home"
104 setLocationMode(newMode)
106 log.debug "not everyone has been away long enough; doing nothing"
109 log.debug "not everyone is away; doing nothing"
113 private everyoneIsAway()
116 for (person in people) {
117 if (person.currentPresence == "present") {
122 log.debug "everyoneIsAway: $result"
127 if (location.contactBookEnabled) {
128 log.debug("sending notifications to: ${recipients?.size()}")
129 sendNotificationToContacts(msg, recipients)
132 if (sendPushMessage != "No") {
133 log.debug("sending push message")
138 log.debug("sending text message")
145 private findFalseAlarmThreshold() {
146 (falseAlarmThreshold != null && falseAlarmThreshold != "") ? falseAlarmThreshold : 10