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.
20 namespace: "smartthings",
21 author: "SmartThings",
22 description: "Changes mode when motion ceases after a specific time of night.",
23 category: "Mode Magic",
24 iconUrl: "https://s3.amazonaws.com/smartapp-icons/ModeMagic/good-night.png",
25 iconX2Url: "https://s3.amazonaws.com/smartapp-icons/ModeMagic/good-night@2x.png"
29 section("When there is no motion on any of these sensors") {
30 input "motionSensors", "capability.motionSensor", title: "Where?", multiple: true
32 section("For this amount of time") {
33 input "minutes", "number", title: "Minutes?"
35 section("After this time of day") {
36 input "timeOfDay", "time", title: "Time?"
38 section("And (optionally) these switches are all off") {
39 input "switches", "capability.switch", multiple: true, required: false
41 section("Change to this mode") {
42 input "newMode", "mode", title: "Mode?"
44 section( "Notifications" ) {
45 input("recipients", "contact", title: "Send notifications to") {
46 input "sendPushMessage", "enum", title: "Send a push notification?", options: ["Yes", "No"], required: false
47 input "phoneNumber", "phone", title: "Send a Text Message?", required: false
54 log.debug "Current mode = ${location.mode}"
59 log.debug "Current mode = ${location.mode}"
64 def createSubscriptions()
66 subscribe(motionSensors, "motion.active", motionActiveHandler)
67 subscribe(motionSensors, "motion.inactive", motionInactiveHandler)
68 subscribe(switches, "switch.off", switchOffHandler)
69 subscribe(location, modeChangeHandler)
71 if (state.modeStartTime == null) {
72 state.modeStartTime = 0
76 def modeChangeHandler(evt) {
77 state.modeStartTime = now()
80 def switchOffHandler(evt) {
81 if (correctMode() && correctTime()) {
82 if (allQuiet() && switchesOk()) {
88 def motionActiveHandler(evt)
90 log.debug "Motion active"
93 def motionInactiveHandler(evt)
95 // for backward compatibility
96 if (state.modeStartTime == null) {
97 subscribe(location, modeChangeHandler)
98 state.modeStartTime = 0
101 if (correctMode() && correctTime()) {
102 runIn(minutes * 60, scheduleCheck, [overwrite: false])
108 log.debug "scheduleCheck, currentMode = ${location.mode}, newMode = $newMode"
110 if (correctMode() && correctTime()) {
111 if (allQuiet() && switchesOk()) {
117 private takeActions() {
118 def message = "Goodnight! SmartThings changed the mode to '$newMode'"
120 setLocationMode(newMode)
124 private correctMode() {
125 if (location.mode != newMode) {
128 log.debug "Location is already in the desired mode: doing nothing"
133 private correctTime() {
135 def modeStartTime = new Date(state.modeStartTime)
136 def startTime = timeTodayAfter(modeStartTime, timeOfDay, location.timeZone)
137 if (t0 >= startTime.time) {
140 log.debug "The current time of day (${new Date(t0)}), is not in the correct time window ($startTime): doing nothing"
145 private switchesOk() {
147 for (it in (switches ?: [])) {
148 if (it.currentSwitch == "on") {
153 log.debug "Switches are all off: $result"
158 def threshold = 1000 * 60 * minutes - 1000
159 def states = motionSensors.collect { it.currentState("motion") ?: [:] }.sort { a, b -> b.dateCreated <=> a.dateCreated }
161 if (states.find { it.value == "active" }) {
162 log.debug "Found active state"
165 def sensor = states.first()
166 def elapsed = now() - sensor.rawDateCreated.time
167 if (elapsed >= threshold) {
168 log.debug "No active states, and enough time has passed"
171 log.debug "No active states, but not enough time has passed"
176 log.debug "No states to check for activity"
182 if (location.contactBookEnabled) {
183 sendNotificationToContacts(msg, recipients)
186 if (sendPushMessage != "No") {
187 log.debug("sending push message")
192 log.debug("sending text message")
193 sendSms(phoneNumber, msg)