Update Hue Party Mode.groovy
[smartapps.git] / third-party / ecobeeResumeProg.groovy
1 /***
2  *  Copyright 2014 Yves Racine
3  *  LinkedIn profile: ca.linkedin.com/pub/yves-racine-m-sc-a/0/406/4b/
4  *
5  *  Developer retains all right, title, copyright, and interest, including all copyright, patent rights, trade secret 
6  *  in the Background technology. May be subject to consulting fees under the Agreement between the Developer and the Customer. 
7  *  Developer grants a non exclusive perpetual license to use the Background technology in the Software developed for and delivered 
8  *  to Customer under this Agreement. However, the Customer shall make no commercial use of the Background technology without
9  *  Developer's written consent.
10  *
11  *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
12  *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
13  *
14  *  Software Distribution is restricted and shall be done only with Developer's written approval.
15  * 
16  *  Resume Ecobee's Program when people arrive or there is been recent motion at home
17  *  N.B. Requires MyEcobee device available at 
18  *          http://www.ecomatiqhomes.com/#!store/tc3yr 
19  */
20  
21 // Automatically generated. Make future change here.
22 definition(
23         name: "ecobeeResumeProg",
24         namespace: "yracine",
25         author: "Yves Racine",
26         description: "resumes your ecobee's scheduled program when a presence is back home or when motion is detected or when a ST hello mode is changed",
27         category: "My Apps",
28         iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/ecobee.png",
29         iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/ecobee@2x.png"
30 )
31
32 preferences {
33
34         page(name: "About", title: "About", install: false , uninstall: true, nextPage: "selectThermostats") {
35                 section("About") {
36                         paragraph "ecobeeResumeProg, the smartapp that resumes your ecobee's scheduled program when a presence is back home,or when motion is detected or when a ST hello mode is changed"
37                         paragraph "Version 2.1.7" 
38                         paragraph "If you like this smartapp, please support the developer via PayPal and click on the Paypal link below " 
39                                 href url: "https://www.paypal.me/ecomatiqhomes",
40                                         title:"Paypal donation..."
41                         paragraph "Copyright©2014 Yves Racine"
42                                 href url:"http://github.com/yracine/device-type.myecobee", style:"embedded", required:false, title:"More information..."  
43                                         description: "http://github.com/yracine/device-type.myecobee/blob/master/README.md"
44                 }
45         }        
46         page(name: "selectThermostats", title: "Thermostats", install: false , uninstall: false, nextPage: "selectModes") {
47                 section("Resume Program at the ecobee thermostat(s)") {
48                         input "ecobee", "device.myEcobeeDevice", title: "Ecobee Thermostat(s)", multiple: true
49                 }
50                 section("When one of these people arrive at home") {
51                         input "people", "capability.presenceSensor", multiple: true, required:false
52                 }
53                 section("Or there is motion at home on these sensors [optional]") {
54                         input "motions", "capability.motionSensor", title: "Where?", multiple: true, required: false
55                 }
56                 section("False alarm threshold [defaults = 3 minutes]") {
57                         input "falseAlarmThreshold", "decimal", title: "Number of minutes", required: false
58                 }
59         }        
60         page(name: "selectModes", title: "Select Hello ST modes", content: "selectModes")
61         page(name: "Notifications", title: "Notifications Options", install: true, uninstall: false) {
62                 section("Notifications") {
63                         input "sendPushMessage", "enum", title: "Send a push notification?", metadata: [values: ["Yes", "No"]], required:
64                                 false
65                         input "phone", "phone", title: "Send a Text Message?", required: false
66                 }
67         section([mobileOnly:true]) {
68                         label title: "Assign a name for this SmartApp", required: false
69                 }
70         }
71
72 }
73
74
75
76 def selectModes() {
77         def enumModes=[]
78         location.modes.each {
79                 enumModes << it.name
80         }    
81
82         return dynamicPage(name: "selectModes", title: "Select Modes", install: false, uninstall: false, nextPage:
83                         "Notifications") {
84                 section("Or when SmartThings' hello home mode changes to (ex.'Home')[optional]") {
85                         input "newMode", "enum", options: enumModes, multiple:true, required: false
86                 }
87         }
88 }
89
90 def appTouch(evt) {
91         log.debug ("appTouch>location.mode= $location.mode, about to takeAction (manual appTouch)")
92
93         takeActions() 
94 }
95
96
97 def installed() {
98         log.debug "Installed with settings: ${settings}"
99         initialize()
100 }
101
102 def updated() {
103         log.debug "Updated with settings: ${settings}"
104         unsubscribe()
105         initialize()
106 }
107
108 def initialize() {
109         log.debug "Current mode = ${location.mode}, people = ${people.collect{it.label + ': ' + it.currentPresence}}"
110         subscribe(location, changeMode)
111         subscribe(app, appTouch)
112         subscribe(people, "presence", presence)
113         subscribe(motions, "motion", motionEvtHandler)
114
115 }
116
117 def motionEvtHandler(evt) {
118         if ((evt.value == "active") && residentsHaveJustBeenActive()) {
119                 def message = "EcobeeResumeProg>Recent motion just detected at home, do it"
120                 log.info message
121                 send(message)
122                 takeActions()
123         }
124 }
125
126 private residentsHaveJustBeenActive() {
127         def threshold = (falseAlarmThreshold != null && falseAlarmThreshold != "") ? (falseAlarmThreshold*60*1000) as Long : 3*60*1000L
128         def result = true
129         def t0 = new Date(now() - threshold)
130         for (sensor in motions) {
131                 def recentStates = sensor.statesSince("motion", t0)
132                 if (recentStates.find {it.value == "active"}) {
133                         result = false
134                         break
135                 }
136         }
137         log.debug "residentsHaveJustBeenActive: $result"
138         return result
139 }
140
141 def changeMode(evt) {
142
143         Boolean foundMode=false        
144         newMode.each {
145         
146                 if (it==location.mode) {
147                         foundMode=true            
148                 }            
149         }        
150         
151         if (!foundMode) {
152                 log.debug "changeMode>location.mode= $location.mode, newMode=${newMode},foundMode=${foundMode}, not resuming program"
153                 return                  
154         }
155         def message = "EcobeeResumeProg>${newMode} has just been triggered, about to take actions.."
156         log.info message
157         send(message)
158         takeActions()
159 }
160
161
162 def presence(evt) {
163         log.debug "evt.name: $evt.value"
164         def threshold = (falseAlarmThreshold != null && falseAlarmThreshold != "") ? (falseAlarmThreshold*60*1000) as Long : 3*60*1000L
165         def message
166
167         def t0 = new Date(now() - threshold)
168         if (evt.value == "present") {
169
170                 def person = getPerson(evt)
171                 if (person != null) {
172                         def recentNotPresent = person.statesSince("presence", t0).find {
173                                 it.value == "not present"
174                         }
175                         if (!recentNotPresent) {
176                                 message = "EcobeeResumeProg>${person.displayName} just arrived,take actions.."
177                                 log.info message
178                                 send(message)
179                                 takeActions()
180                         }
181                 } else {
182                         message = "EcobeeResumeProg>somebody just arrived at home, but she/he is not been selected for resuming the ecobee program."
183                         log.info message
184                         send(message)
185
186                 }
187         }
188 }
189
190 def takeActions() {
191         def message = "EcobeeResumeProg>resumed program at ${ecobee} thermostats..."
192         ecobee.each {
193                 it.resumeThisTstat()
194         }        
195         send(message)
196 }
197
198
199 private getPerson(evt) {
200         people.find {
201                 evt.deviceId == it.id
202         }
203 }
204
205 private send(msg) {
206         if (sendPushMessage != "No") {
207                 log.debug("sending push message")
208                 sendPush(msg)
209         }
210         if (phone) {
211                 log.debug("sending text message")
212                 sendSms(phone, msg)
213         }
214
215         log.debug msg
216 }