Update sonos-music-modes.groovy
[smartapps.git] / official / garage-door-monitor.groovy
1 /**
2  *  Copyright 2015 SmartThings
3  *
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:
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
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.
12  *
13  *  Garage Door Monitor
14  *
15  *  Author: SmartThings
16  */
17 definition(
18     name: "Garage Door Monitor",
19     namespace: "smartthings",
20     author: "SmartThings",
21     description: "Monitor your garage door and get a text message if it is open too long",
22     category: "Safety & Security",
23     iconUrl: "https://s3.amazonaws.com/smartapp-icons/Meta/garage_contact.png",
24     iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Meta/garage_contact@2x.png"
25 )
26
27 preferences {
28         section("When the garage door is open...") {
29                 input "multisensor", "capability.threeAxis", title: "Which?"
30         }
31         section("For too long...") {
32                 input "maxOpenTime", "number", title: "Minutes?"
33         }
34         section("Text me at (optional, sends a push notification if not specified)...") {
35         input("recipients", "contact", title: "Notify", description: "Send notifications to") {
36             input "phone", "phone", title: "Phone number?", required: false
37         }
38         }
39 }
40
41 def installed()
42 {
43         subscribe(multisensor, "acceleration", accelerationHandler)
44 }
45
46 def updated()
47 {
48         unsubscribe()
49         subscribe(multisensor, "acceleration", accelerationHandler)
50 }
51
52 def accelerationHandler(evt) {
53         def latestThreeAxisState = multisensor.threeAxisState // e.g.: 0,0,-1000
54         if (latestThreeAxisState) {
55                 def isOpen = Math.abs(latestThreeAxisState.xyzValue.z) > 250 // TODO: Test that this value works in most cases...
56                 def isNotScheduled = state.status != "scheduled"
57
58                 if (!isOpen) {
59                         clearSmsHistory()
60                         clearStatus()
61                 }
62
63                 if (isOpen && isNotScheduled) {
64                         runIn(maxOpenTime * 60, takeAction, [overwrite: false])
65                         state.status = "scheduled"
66                 }
67
68         }
69         else {
70                 log.warn "COULD NOT FIND LATEST 3-AXIS STATE FOR: ${multisensor}"
71         }
72 }
73
74 def takeAction(){
75         if (state.status == "scheduled")
76         {
77                 def deltaMillis = 1000 * 60 * maxOpenTime
78                 def timeAgo = new Date(now() - deltaMillis)
79                 def openTooLong = multisensor.threeAxisState.dateCreated.toSystemDate() < timeAgo
80
81                 def recentTexts = state.smsHistory.find { it.sentDate.toSystemDate() > timeAgo }
82
83                 if (!recentTexts) {
84                         sendTextMessage()
85                 }
86                 runIn(maxOpenTime * 60, takeAction, [overwrite: false])
87         } else {
88                 log.trace "Status is no longer scheduled. Not sending text."
89         }
90 }
91
92 def sendTextMessage() {
93         log.debug "$multisensor was open too long, texting phone"
94
95         updateSmsHistory()
96         def openMinutes = maxOpenTime * (state.smsHistory?.size() ?: 1)
97         def msg = "Your ${multisensor.label ?: multisensor.name} has been open for more than ${openMinutes} minutes!"
98     if (location.contactBookEnabled) {
99         sendNotificationToContacts(msg, recipients)
100     }
101     else {
102         if (phone) {
103             sendSms(phone, msg)
104         } else {
105             sendPush msg
106         }
107     }
108 }
109
110 def updateSmsHistory() {
111         if (!state.smsHistory) state.smsHistory = []
112
113         if(state.smsHistory.size() > 9) {
114                 log.debug "SmsHistory is too big, reducing size"
115                 state.smsHistory = state.smsHistory[-9..-1]
116         }
117         state.smsHistory << [sentDate: new Date().toSystemFormat()]
118 }
119
120 def clearSmsHistory() {
121         state.smsHistory = null
122 }
123
124 def clearStatus() {
125         state.status = null
126 }