299e6e4a40c52832e9c5c093de3afed0f26127cd
[smartthings-infrastructure.git] / main.groovy
1 //Infrastructure for SmartThings Application
2 //Importing Libraries
3 import groovy.transform.Field
4
5 //Importing Classes
6 import ContactSensor.Contacting
7 import ContactSensor.Contacts
8 import Lock.Locking
9 import Lock.Locks
10 import Switch.Switching
11 import Switch.Switches
12 import Logger.Logger
13 import Location.LocationVar
14 import Location.Phrase
15 import appTouch.Touched
16 import Event.Event
17
18 //GlobalVariables for both Apps
19 //Create a global variable for send event
20 @Field def sendEvent = {eventDataMap -> 
21                         app1.eventHandler(eventDataMap)
22                         app2.eventHandler(eventDataMap)
23                         }
24 //Object for location
25 @Field def locationObject = new LocationVar()
26 //Object for touch
27 @Field def appObject = new Touched(sendEvent, 0)
28
29 //Extracted global objects for both Apps
30 //Global Object for class lock!
31 @Field def lockObject = new Locking(sendEvent, 1)
32 //Global Object for class contactSensor!
33 @Field def contactObject = new Contacting(sendEvent, 1)
34 //Global Object for class Switch!
35 @Field def switchObject = new Switching(sendEvent, 2)
36
37 //Application #1
38 class App1 {
39         def reference
40         def location
41         def app
42
43         //Extracted objects for App1
44         //Object for class lock!
45         def lock1
46         //Object for class contactSensor!
47         def contact
48         //Global variable for number!
49         def minutesLater = 1
50         //Global variable for number!
51         def secondsLater = 2
52         //Global variable for recipients!
53         def recipients = ['AJ']
54         //Global variable for phone number!
55         def phoneNumber = 9495379373
56         //Global Object for functions in subscribe method!
57         def installed = this.&installed
58         //Global Object for functions in subscribe method!
59         def updated = this.&updated
60         //Global Object for functions in subscribe method!
61         def initialize = this.&initialize
62         //Global Object for functions in subscribe method!
63         def lockDoor = this.&lockDoor
64         //Global Object for functions in subscribe method!
65         def unlockDoor = this.&unlockDoor
66         //Global Object for functions in subscribe method!
67         def doorHandler = this.&doorHandler
68
69         App1(Object obj) {
70                 reference = obj
71                 location = obj.locationObject
72                 app = obj.appObject
73                 lock1 = obj.lockObject
74                 contact = obj.contactObject
75         }
76         //Global variables for each app
77         //Settings variable defined to settings on purpose
78         def settings = "Settings"
79         //Global variable for state[mode]
80         def state = [home:[],away:[],night:[]]
81         //Create a global logger object for methods
82         def log = new Logger()
83         //Create a global variable for Functions in Subscribe method
84         def functionList = []
85         //Create a global variable for Objects in Subscribe method
86         def objectList = []
87         //Create a global variable for Events in Subscribe method
88         def eventList = []
89         //Create a global list for function schedulers
90         def timersFuncList = []
91         //Create a global list for timer schedulers
92         def timersList = []
93         //Create a global list for events
94         def evt = []
95
96         //Methods
97         /////////////////////////////////////////////////////////////////////
98         def setLocationMode(String mode) {
99                 location.mode = mode
100         }
101         
102         /////////////////////////////////////////////////////////////////////
103         ////subscribe(obj, func)
104         def subscribe(Object obj, Closure FunctionToCall) {
105                 objectList.add(obj)
106                 eventList.add("Touched")
107                 functionList.add(FunctionToCall)
108         }
109         ////subscribe(obj, event, func)
110         def subscribe(Object obj, String event, Closure FunctionToCall) {
111                 objectList.add(obj)
112                 eventList.add(event)
113                 functionList.add(FunctionToCall)
114         }
115         ////subscribe(obj, event, func, data)
116         def subscribe(Object obj, String event, Closure FunctionToCall, LinkedHashMap metaData) {
117                 objectList.add(obj)     
118                 eventList.add(event)
119                 functionList.add(FunctionToCall)
120         }
121         /////////////////////////////////////////////////////////////////////
122         ////runIn(time, func)
123         def runIn(int seconds, Closure functionToCall) {
124                 timersFuncList.add(functionToCall)
125                 timersList.add(new Timer())
126                 def task = timersList[-1].runAfter(1000*seconds, functionToCall)
127         }
128         /////////////////////////////////////////////////////////////////////
129         ////unschedule(func)
130         def unschedule(Closure functionToUnschedule) {
131                 for (int i = 0;i < timersFuncList.size();i++) {
132                         if (timersFuncList[i] == functionToUnschedule) {
133                                 timersList[i].cancel()
134                         }
135                 }
136         }
137         /////////////////////////////////////////////////////////////////////
138         ////sendNotificationToContacts(text, recipients)
139         def sendNotificationToContacts(String text, List recipients) {
140                 for (int i = 0;i < recipients.size();i++) {
141                         for (int j = 0;j < location.contacts.size();j++) {
142                                 if (recipients[i] == location.contacts[j]) {
143                                         println("Sending \""+text+"\" to "+location.phoneNumbers[j].toString())
144                                 }
145                         }
146                 }
147         }
148         /////////////////////////////////////////////////////////////////////
149         ////sendSms(phone, text)
150         def sendSms(long phoneNumber, String text) {
151                 println("Sending \""+text+"\" to "+phoneNumber.toString())
152         }
153         /////////////////////////////////////////////////////////////////////
154         def eventHandler(LinkedHashMap eventDataMap) {
155                 def value = eventDataMap["value"]
156                 def name = eventDataMap["name"]
157                 def deviceId = eventDataMap["deviceId"]
158                 def descriptionText = eventDataMap["descriptionText"]
159                 def displayed = eventDataMap["displayed"]
160                 def linkText = eventDataMap["linkText"]
161                 def isStateChange = eventDataMap["isStateChange"]
162                 def unit = eventDataMap["unit"]
163                 def data = eventDataMap["data"]
164                 
165                 for (int i = 0;i < eventList.size();i++) {
166                         if (eventList[i] == name) {
167                                 evt.add(new Event())
168                                 evt[-1].value = value
169                                 evt[-1].name = name
170                                 evt[-1].deviceId = deviceId
171                                 evt[-1].descriptionText = descriptionText
172                                 evt[-1].displayed = displayed
173                                 evt[-1].linkText = linkText
174                                 evt[-1].displayName = linkText
175                                 evt[-1].isStateChange = isStateChange
176                                 evt[-1].unit = unit
177                                 evt[-1].data = data
178                                 functionList[i](evt[-1])
179                         }
180                 }
181         }
182
183         def installed(){
184             initialize()
185         }
186         
187         def updated(){
188             unsubscribe()
189             unschedule()
190             initialize()
191         }
192         
193         def initialize(){
194             log.debug "Settings: ${settings}"
195             subscribe(lock1, "lock", doorHandler, [filterEvents: false])
196             subscribe(lock1, "unlock", doorHandler, [filterEvents: false])  
197             subscribe(contact, "contact.open", doorHandler)
198             subscribe(contact, "contact.closed", doorHandler)
199         }
200         
201         def lockDoor(){
202             log.debug "Locking the door."
203             lock1.lock()
204             if(location.contactBookEnabled) {
205                 if ( recipients ) {
206                     log.debug ( "Sending Push Notification..." ) 
207                     sendNotificationToContacts( "${lock1} locked after ${contact} was closed for ${minutesLater} minutes!", recipients)
208                 }
209             }
210             if (phoneNumber) {
211                 log.debug("Sending text message...")
212                 sendSms( phoneNumber, "${lock1} locked after ${contact} was closed for ${minutesLater} minutes!")
213             }
214         }
215         
216         def unlockDoor(){
217             log.debug "Unlocking the door."
218             lock1.unlock()
219             if(location.contactBookEnabled) {
220                 if ( recipients ) {
221                     log.debug ( "Sending Push Notification..." ) 
222                     sendNotificationToContacts( "${lock1} unlocked after ${contact} was opened for ${secondsLater} seconds!", recipients)
223                 }
224             }
225             if ( phoneNumber ) {
226                 log.debug("Sending text message...")
227                 sendSms( phoneNumber, "${lock1} unlocked after ${contact} was opened for ${secondsLater} seconds!")
228             }
229         }
230         
231         def doorHandler(evt){
232             if ((contact.latestValue("contact") == "open") && (evt.value == "locked")) { // If the door is open and a person locks the door then...  
233                 //def delay = (secondsLater) // runIn uses seconds
234                 runIn( secondsLater, unlockDoor )   // ...schedule (in minutes) to unlock...  We don't want the door to be closed while the lock is engaged. 
235             }
236             else if ((contact.latestValue("contact") == "open") && (evt.value == "unlocked")) { // If the door is open and a person unlocks it then...
237                 unschedule( unlockDoor ) // ...we don't need to unlock it later.
238             }
239             else if ((contact.latestValue("contact") == "closed") && (evt.value == "locked")) { // If the door is closed and a person manually locks it then...
240                 unschedule( lockDoor ) // ...we don't need to lock it later.
241             }   
242             else if ((contact.latestValue("contact") == "closed") && (evt.value == "unlocked")) { // If the door is closed and a person unlocks it then...
243                //def delay = (minutesLater * 60) // runIn uses seconds
244                 runIn( (minutesLater * 60), lockDoor ) // ...schedule (in minutes) to lock.
245             }
246             else if ((lock1.latestValue("lock") == "unlocked") && (evt.value == "open")) { // If a person opens an unlocked door...
247                 unschedule( lockDoor ) // ...we don't need to lock it later.
248             }
249             else if ((lock1.latestValue("lock") == "unlocked") && (evt.value == "closed")) { // If a person closes an unlocked door...
250                 //def delay = (minutesLater * 60) // runIn uses seconds
251                 runIn( (minutesLater * 60), lockDoor ) // ...schedule (in minutes) to lock.
252             }
253             else { //Opening or Closing door when locked (in case you have a handle lock)
254                 log.debug "Unlocking the door."
255                 lock1.unlock()
256                 if(location.contactBookEnabled) {
257                     if ( recipients ) {
258                         log.debug ( "Sending Push Notification..." ) 
259                         sendNotificationToContacts( "${lock1} unlocked after ${contact} was opened or closed when ${lock1} was locked!", recipients)
260                     }
261                 }
262                 if ( phoneNumber ) {
263                     log.debug("Sending text message...")
264                     sendSms( phoneNumber, "${lock1} unlocked after ${contact} was opened or closed when ${lock1} was locked!")
265                 }
266             }
267         }
268 }
269
270
271 //Application #2
272 class App2 {
273         def reference
274         def location
275         def app
276
277         //Extracted objects for App2
278         //Object for class Switch!
279         def switchesoff
280         //Object for class Switch!
281         def switcheson
282         //Object for class lock!
283         def lock1
284         //Global variable for mode!
285         def newMode = "away"
286         //Global variable for number!
287         def waitfor = 10
288         //Global Object for functions in subscribe method!
289         def installed = this.&installed
290         //Global Object for functions in subscribe method!
291         def updated = this.&updated
292         //Global Object for functions in subscribe method!
293         def appTouch = this.&appTouch
294
295         App2(Object obj) {
296                 reference = obj
297                 location = obj.locationObject
298                 app = obj.appObject
299                 switchesoff = obj.switchObject
300                 switcheson = obj.switchObject
301                 lock1 = obj.lockObject
302         }
303         //Global variables for each app
304         //Settings variable defined to settings on purpose
305         def settings = "Settings"
306         //Global variable for state[mode]
307         def state = [home:[],away:[],night:[]]
308         //Create a global logger object for methods
309         def log = new Logger()
310         //Create a global variable for Functions in Subscribe method
311         def functionList = []
312         //Create a global variable for Objects in Subscribe method
313         def objectList = []
314         //Create a global variable for Events in Subscribe method
315         def eventList = []
316         //Create a global list for function schedulers
317         def timersFuncList = []
318         //Create a global list for timer schedulers
319         def timersList = []
320         //Create a global list for events
321         def evt = []
322
323         //Methods
324         /////////////////////////////////////////////////////////////////////
325         def setLocationMode(String mode) {
326                 location.mode = mode
327         }
328         
329         /////////////////////////////////////////////////////////////////////
330         ////subscribe(obj, func)
331         def subscribe(Object obj, Closure FunctionToCall) {
332                 objectList.add(obj)
333                 eventList.add("Touched")
334                 functionList.add(FunctionToCall)
335         }
336         ////subscribe(obj, event, func)
337         def subscribe(Object obj, String event, Closure FunctionToCall) {
338                 objectList.add(obj)
339                 eventList.add(event)
340                 functionList.add(FunctionToCall)
341         }
342         ////subscribe(obj, event, func, data)
343         def subscribe(Object obj, String event, Closure FunctionToCall, LinkedHashMap metaData) {
344                 objectList.add(obj)     
345                 eventList.add(event)
346                 functionList.add(FunctionToCall)
347         }
348         /////////////////////////////////////////////////////////////////////
349         ////runIn(time, func)
350         def runIn(int seconds, Closure functionToCall) {
351                 timersFuncList.add(functionToCall)
352                 timersList.add(new Timer())
353                 def task = timersList[-1].runAfter(1000*seconds, functionToCall)
354         }
355         /////////////////////////////////////////////////////////////////////
356         ////unschedule(func)
357         def unschedule(Closure functionToUnschedule) {
358                 for (int i = 0;i < timersFuncList.size();i++) {
359                         if (timersFuncList[i] == functionToUnschedule) {
360                                 timersList[i].cancel()
361                         }
362                 }
363         }
364         /////////////////////////////////////////////////////////////////////
365         ////sendNotificationToContacts(text, recipients)
366         def sendNotificationToContacts(String text, List recipients) {
367                 for (int i = 0;i < recipients.size();i++) {
368                         for (int j = 0;j < location.contacts.size();j++) {
369                                 if (recipients[i] == location.contacts[j]) {
370                                         println("Sending \""+text+"\" to "+location.phoneNumbers[j].toString())
371                                 }
372                         }
373                 }
374         }
375         /////////////////////////////////////////////////////////////////////
376         ////sendSms(phone, text)
377         def sendSms(long phoneNumber, String text) {
378                 println("Sending \""+text+"\" to "+phoneNumber.toString())
379         }
380         /////////////////////////////////////////////////////////////////////
381         def eventHandler(LinkedHashMap eventDataMap) {
382                 def value = eventDataMap["value"]
383                 def name = eventDataMap["name"]
384                 def deviceId = eventDataMap["deviceId"]
385                 def descriptionText = eventDataMap["descriptionText"]
386                 def displayed = eventDataMap["displayed"]
387                 def linkText = eventDataMap["linkText"]
388                 def isStateChange = eventDataMap["isStateChange"]
389                 def unit = eventDataMap["unit"]
390                 def data = eventDataMap["data"]
391                 
392                 for (int i = 0;i < eventList.size();i++) {
393                         if (eventList[i] == name) {
394                                 evt.add(new Event())
395                                 evt[-1].value = value
396                                 evt[-1].name = name
397                                 evt[-1].deviceId = deviceId
398                                 evt[-1].descriptionText = descriptionText
399                                 evt[-1].displayed = displayed
400                                 evt[-1].linkText = linkText
401                                 evt[-1].displayName = linkText
402                                 evt[-1].isStateChange = isStateChange
403                                 evt[-1].unit = unit
404                                 evt[-1].data = data
405                                 functionList[i](evt[-1])
406                         }
407                 }
408         }
409
410         def installed()
411         {
412                 log.debug "Installed with settings: ${settings}"
413                 log.debug "Current mode = ${location.mode}"
414                 subscribe(app, appTouch)
415         }
416         
417         
418         def updated()
419         {
420                 log.debug "Updated with settings: ${settings}"
421                 log.debug "Current mode = ${location.mode}"
422                 unsubscribe()
423                 subscribe(app, appTouch)
424         }
425         
426         def appTouch(evt) {
427                 log.debug "changeMode, location.mode = $location.mode, newMode = $newMode, location.modes = $location.modes"
428             if (location.mode != newMode) {
429                                 setLocationMode(newMode)
430                                 log.debug "Changed the mode to '${newMode}'"
431             }   else {
432                 log.debug "New mode is the same as the old mode, leaving it be"
433                 }
434             log.debug "appTouch: $evt"
435             lock1.lock()
436             switcheson.on()
437             def delay = (waitfor != null && waitfor != "") ? waitfor * 1000 : 120000
438                 switchesoff.off(delay: delay)
439         }
440 }
441
442 @Field def app1 = new App1(this)
443 @Field def app2 = new App2(this)
444 app1.installed()
445 app2.installed()