e06f589664e52fb6fa2a1ce0a021c94535c02d4e
[jpf-core.git] / examples / main / main.groovy
1 //Infrastructure for SmartThings Application
2 //Importing Libraries
3 import groovy.transform.Field
4
5 //Importing Classes
6 ///////////////////
7 public class Touched{
8         def sendEvent
9         private int isTouched
10
11         Touched(Closure sendEvent, int isTouched) {
12                 this.sendEvent = sendEvent
13                 this.isTouched = isTouched
14         }
15
16         //By Model Checker
17         def setValue(LinkedHashMap eventDataMap) {
18                 println("The application is Touched!")
19                 this.isTouched = 1 //Do we need this?
20                 sendEvent(eventDataMap)
21         }
22 }
23 ///////////////////
24 public class Contacting{
25         private int deviceNumbers
26         private List contacts
27         def sendEvent
28                 
29         Contacting(Closure sendEvent, int deviceNumbers) {
30                 this.sendEvent = sendEvent              
31                 this.deviceNumbers = deviceNumbers
32                 this.contacts = []
33                 if (deviceNumbers == 1) {
34                         contacts = [new Contacts(0, "contact0", "closed", "closed")]
35                 } else if (deviceNumbers == 2) {
36                         contacts = [new Contacts(0, "contact0", "closed", "closed"), new Contacts(1, "contact1", "closed", "closed")]
37                 } else if (deviceNumbers == 3) {
38                         contacts = [new Contacts(0, "contact0", "closed", "closed"), new Contacts(1, "contact1", "closed", "closed")
39                                    ,new Contacts(2, "contact2", "closed", "closed")]
40                 }
41         }
42
43         //By Model Checker
44         def setValue(LinkedHashMap eventDataMap) {
45                 contacts[eventDataMap["deviceId"]].setValue(eventDataMap["value"])
46                 sendEvent(eventDataMap)
47         }
48
49         def currentValue(String deviceFeature) {
50                 if (deviceNumbers == 1)
51                         contacts[0].currentValue(deviceFeature)//It is called if we have only one device
52                 else
53                         contacts*.currentValue(deviceFeature)
54         }
55
56         def latestValue(String deviceFeature) {
57                 if (deviceNumbers == 1)
58                         contacts[0].latestValue(deviceFeature)//It is called if we have only one device
59                 else
60                         contacts*.latestValue(deviceFeature)
61         }
62
63         def getAt(int ix) {
64                 contacts[ix]
65         }
66 }
67 ///////////////////
68 public class Contacts {
69         private int id
70         private String displayName
71         private String contactCurrentValue
72         private String contactLatestValue
73
74         Contacts(int id, String displayName, String contactCurrentValue, String contactLatestValue) {
75                 this.id = id
76                 this.displayName = displayName
77                 this.contactCurrentValue = contactCurrentValue
78                 this.contactLatestValue = contactLatestValue
79         }
80
81         def setValue(String value) {
82                 this.contactLatestValue = contactCurrentValue
83                 println("the contact sensor with id:$id is triggered to $value!")
84                 this.contactCurrentValue = value
85         }
86         
87         def currentValue(String deviceFeature) {
88                 if (deviceFeature == "contact") {
89                         return contactCurrentValue
90                 }
91         }
92
93         def latestValue(String deviceFeature) {
94                 if (deviceFeature == "contact") {
95                         return contactLatestValue
96                 }
97         }
98 }
99 ///////////////////
100 public class Event {
101         private int deviceId
102         private String value
103         private String linkText
104         private String displayName
105         private boolean displayed
106         private String name
107         private String descriptionText
108         private boolean isStateChange
109         private String unit
110         private LinkedHashMap data
111         
112         Event() {
113                 this.deviceId = 0
114                 this.linkText = ""
115                 this.value = ""
116                 this.displayName = ""
117                 this.name = ""
118                 this.descriptionText = ""
119                 this.isStateChange = false
120                 this.unit = ""
121                 this.data = []
122                 this.displayed = false
123         }
124 }
125 ///////////////////
126 class LocationVar {
127         private int contactBookEnabled
128         private String modes
129         private String mode
130         private List contacts
131         private List phoneNumbers
132     
133         private Phrase helloHome
134
135         LocationVar() {
136                 this.modes = "'home', 'away', 'night'"
137                 this.mode = "home"
138                 this.helloHome = new Phrase()
139                 this.contactBookEnabled = 1
140                 this.contacts = ['AJ']
141                 this.phoneNumbers = [9495379373]
142         }
143 }
144 ///////////////////
145 class Phrase {
146         private LinkedHashMap phrases
147         
148         Phrase() {
149                 this.phrases = [id:0, label:"Good Morning!"]
150         } 
151         def getPhrases() {
152                 return this.phrases
153         }
154 }
155 ///////////////////
156 public class Locking{
157         int deviceNumbers       
158         List locks      
159         def sendEvent   
160         def timers
161
162         Locking(Closure sendEvent, int deviceNumbers) {
163                 this.sendEvent = sendEvent
164                 this.timers = new Timer()
165                 this.deviceNumbers = deviceNumbers
166                 this.locks = []
167                 if (deviceNumbers == 1) {
168                         locks = [new Locks(sendEvent, 0, "lock0", "locked", "locked")]
169                 } else if (deviceNumbers == 2) {
170                         locks = [new Locks(sendEvent, 0, "lock0", "locked", "locked"), new Locks(sendEvent, 1, "lock1", "locked", "locked")]
171                 } else if (deviceNumbers == 3) {
172                         locks = [new Locks(sendEvent, 0, "lock0", "locked", "locked"), new Locks(sendEvent, 1, "lock1", "locked", "locked")
173                                 ,new Locks(sendEvent, 2, "lock2", "locked", "locked")]
174                 }
175         }
176
177         //By Apps
178         def lock() {
179                 locks*.lock()
180         }
181
182         def lock(LinkedHashMap metaData) {
183                 def task = timers.runAfter(metaData["delay"]) {
184                         locks*.lock()
185                 }
186         }
187
188         def unlock() {
189                 locks*.unlock()
190         }
191
192         def unlock(LinkedHashMap metaData) {
193                 def task = timers.runAfter(metaData["delay"]) {
194                         locks*.unlock()
195                 }
196         }
197
198         //By Model Checker
199         def setValue(LinkedHashMap eventDataMap) {
200                 locks[eventDataMap["deviceId"]].setValue(eventDataMap["value"])
201                 sendEvent(eventDataMap)
202         }
203
204         def currentValue(String deviceFeature) {
205                 if (deviceNumbers == 1) 
206                         locks[0].currentValue(deviceFeature)
207                 else 
208                         locks*.currentValue(deviceFeature)
209         }
210
211         def latestValue(String deviceFeature) {
212                 if (deviceNumbers == 1)
213                         locks[0].latestValue(deviceFeature)
214                 else
215                         locks*.latestValue(deviceFeature)
216         }
217
218         def getAt(int ix) {
219                 locks[ix]
220         }
221 }
222 ///////////////////
223 public class Locks {
224         private int id
225         private String displayName
226         private String lockCurrentValue
227         private String lockLatestValue
228         def sendEvent   
229         def timers
230
231
232         Locks(Closure sendEvent, int id, String displayName, String lockCurrentValue, String lockLatestValue) {
233                 this.id = id
234                 this.sendEvent = sendEvent
235                 this.displayName = displayName
236                 this.lockCurrentValue = lockCurrentValue
237                 this.lockLatestValue = lockLatestValue
238                 this.timers = new Timer()
239         }
240
241         //By Apps
242         def lock() {
243                 println("the door with id:$id is locked!")
244                 this.lockLatestValue = this.lockCurrentValue
245                 this.lockCurrentValue = "locked"
246                 sendEvent([name: "lock", value: "locked", deviceId: this.id, descriptionText: "",
247                           displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
248         }
249
250         def lock(LinkedHashMap metaData) {
251                 def task = timers.runAfter(metaData["delay"]) {
252                         println("the door with id:$id is locked!")
253                         this.lockLatestValue = this.lockCurrentValue
254                         this.lockCurrentValue = "locked"
255                         sendEvent([name: "lock", value: "locked", deviceId: this.id, descriptionText: "",
256                                   displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
257                 }
258         }
259         
260         def unlock() {
261                 println("the door with id:$id is unlocked!")
262                 this.lockLatestValue = this.lockCurrentValue
263                 this.lockCurrentValue = "unlocked"
264                 sendEvent([name: "unlock", value: "unlocked", deviceId: this.id, descriptionText: "",
265                           displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
266         }
267
268         def unlock(LinkedHashMap metaData) {
269                 def task = timers.runAfter(metaData["delay"]) {
270                         println("the door with id:$id is locked!")
271                         this.lockLatestValue = this.lockCurrentValue
272                         this.lockCurrentValue = "locked"
273                         sendEvent([name: "unlock", value: "unlocked", deviceId: this.id, descriptionText: "",
274                                   displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
275                 }
276         }
277
278         //By Model Checker
279         def setValue(String value) {
280                 println("the door with id:$id is $value!")
281                 this.lockLatestValue = this.lockCurrentValue
282                 this.lockCurrentValue = value
283         }
284         
285         def currentValue(String deviceFeature) {
286                 if (deviceFeature == "lock") {
287                         return lockCurrentValue
288                 }
289         }
290
291         def latestValue(String deviceFeature) {
292                 if (deviceFeature == "lock") {
293                         return lockLatestValue
294                 }
295         }
296 }
297 ///////////////////
298 class Logger {
299     private boolean printToConsole = true
300
301     def methodMissing(String name, args) {
302         def messsage = args[0]
303         if (printToConsole) {
304             println messsage
305         }
306     }
307 }
308 ///////////////////
309 public class Switches {
310         private int id = 0      
311         private String displayName
312         private String switchCurrentValue
313         private String switchLatestValue
314         def sendEvent   
315         def timers
316         
317
318         Switches(Closure sendEvent, int id, String displayName, String switchCurrentValue, String switchLatestValue) {
319                 this.sendEvent = sendEvent
320                 this.timers = new Timer()
321
322                 this.id = id
323                 this.displayName = displayName
324                 this.switchCurrentValue = switchCurrentValue
325                 this.switchLatestValue = switchLatestValue
326         }
327
328         //By Apps
329         def on() {
330                 println("the switch with id:$id is on!")
331                 this.switchLatestValue = this.switchCurrentValue
332                 this.switchCurrentValue = "on"
333                 sendEvent([name: "switch", value: "on", deviceId: this.id, descriptionText: "",
334                     displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
335         }
336
337         def on(LinkedHashMap metaData) {
338                 def task = timers.runAfter(metaData["delay"]) {
339                         println("the switch with id:$id is on!")
340                         this.switchLatestValue = this.switchCurrentValue
341                         this.switchCurrentValue = "on"
342                         sendEvent([name: "switch", value: "on", deviceId: this.id, descriptionText: "",
343                             displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
344                 }
345         }
346
347         def off() {
348                 println("the switch with id:$id is off!")
349                 this.switchLatestValue = this.switchCurrentValue
350                 this.switchCurrentValue = "off"
351                 sendEvent([name: "switch", value: "off", deviceId: this.id, descriptionText: "",
352                     displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
353         }
354
355         def off(LinkedHashMap metaData) {
356                 def task = timers.runAfter(metaData["delay"]) {
357                         println("the switch with id:$id is off!")
358                         this.switchLatestValue = this.switchCurrentValue
359                         this.switchCurrentValue = "off"
360                         sendEvent([name: "switch", value: "off", deviceId: this.id, descriptionText: "",
361                             displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
362                 }
363         }
364
365         //By Model Checker
366         def setValue(String value) {
367                 println("the switch with id:$id is $value!")
368                 this.switchLatestValue = this.switchCurrentValue
369                 this.switchCurrentValue = value
370         }
371         
372         def currentValue(String deviceFeature) {
373                 if (deviceFeature == "switch") {
374                         return switchCurrentValue
375                 }
376         }
377
378         def latestValue(String deviceFeature) {
379                 if (deviceFeature == "switch") {
380                         return switchLatestValue
381                 }
382         }
383 }
384 ///////////////////
385 public class Switching{
386         int deviceNumbers       
387         List switches
388         def timers
389         def sendEvent
390
391         Switching(Closure sendEvent, int deviceNumbers) {
392                 this.sendEvent = sendEvent
393                 this.timers = new Timer()
394                 this.deviceNumbers = deviceNumbers
395                 this.switches = []
396                 if (deviceNumbers == 1) {
397                         switches = [new Switches(sendEvent, 0, "switch0", "off", "off")]
398                 } else if (deviceNumbers == 2) {
399                         switches = [new Switches(sendEvent, 0, "switch0", "off", "off"), new Switches(sendEvent, 1, "switch1", "off", "off")]
400                 } else if (deviceNumbers == 3) {
401                         switches = [new Switches(sendEvent, 0, "switch0", "off", "off"), new Switches(sendEvent, 1, "switch1", "off", "off")
402                                    ,new Switches(sendEvent, 2, "switch2", "off", "off")]
403                 }
404         }
405
406         //By Apps
407         def on() {
408                 switches*.on()
409         }
410
411         def on(LinkedHashMap metaData) {
412                 def task = timers.runAfter(metaData["delay"]) {
413                         switches*.on()
414                 }
415         }
416
417         def off() {
418                 switches*.off()
419         }
420
421         def off(LinkedHashMap metaData) {
422                 def task = timers.runAfter(metaData["delay"]) {
423                         switches*.off()
424                 }
425         }
426
427         //By Model Checker
428         def setValue(LinkedHashMap eventDataMap) {
429                 switches[eventDataMap["deviceId"]].setValue(eventDataMap["value"])
430                 sendEvent(eventDataMap)
431         }
432
433
434         def currentValue(String deviceFeature) {
435                 if (deviceNumbers == 1)
436                         switches[0].currentValue(deviceFeature)
437                 else
438                         switches*.currentValue(deviceFeature)
439         }
440
441         def latestValue(String deviceFeature) {
442                 if (deviceNumbers == 1)
443                         switches[0].latestValue(deviceFeature)
444                 else
445                         switches*.latestValue(deviceFeature)
446         }
447
448         def getAt(int ix) {
449                 switches[ix]
450         }
451 }
452
453 //Global variable for sendEvent
454 @Field def sendEvent = {eventDataMap -> 
455                         app1.eventHandler(eventDataMap)
456                         app2.eventHandler(eventDataMap)
457                         }
458
459 //Objects for classes
460 //Object for class switch!
461 @Field def switchObject = new Switching(sendEvent, 1)//not ok
462 //Object for class lock!
463 @Field def lockObject = new Locking(sendEvent, 2)//not ok
464 //Object for location
465 @Field def locationObject = new LocationVar()//not ok
466 //Object for touch
467 @Field def appObject = new Touched(sendEvent, 0)//not ok
468 //Object for contact sensor
469 @Field def contactObject = new Contacting(sendEvent, 1)//not ok
470
471
472 //Application #1
473 class App1 {
474         def reference
475
476         //extracted objs
477         def location
478         //Object for class Touched!
479         def app
480         //Object for class switch!
481         def switchesoff
482         //Object for class switch!
483         def switcheson
484         //Object for class lock!
485         def lock1
486         //Variable for mode!
487         def newMode = "away"
488         //Variable for number!
489         def waitfor = 10
490         //Global Object for functions in subscribe method!
491         def installed = this.&installed
492         //Global Object for functions in subscribe method!
493         def updated = this.&updated
494         //Global Object for functions in subscribe method!
495         def appTouch = this.&appTouch
496
497         App1(Object obj) {
498                 reference = obj         
499                 location = obj.locationObject
500                 app = obj.appObject
501                 //should be created in python
502                 switchesoff = obj.switchObject
503                 switcheson = obj.switchObject
504                 lock1 = obj.lockObject
505         }
506         //GlobalVariables
507         //Settings variable defined to settings on purpose
508         def settings = "Settings"
509         //Global variable for state[mode]
510         def state = [home:[],away:[],night:[]]
511         //Create a global logger object for methods
512         def log = new Logger()
513         //Create a global variable for Functions in Subscribe method
514         def functionList = []
515         //Create a global variable for Objects in Subscribe method
516         def objectList = []
517         //Create a global variable for Events in Subscribe method
518         def eventList = []
519         //Create a global list for function schedulers
520         def timersFuncList = []
521         //Create a global list for timer schedulers
522         def timersList = []
523         //Create a global list for events
524         def evt = []
525
526
527         
528
529         
530         //Methods
531         /////////////////////////////////////////////////////////////////////
532         def definition(LinkedHashMap metaData) {
533                 println("IGNORE -- JUST SOME DEFINITION")
534         }
535
536         /////////////////////////////////////////////////////////////////////
537         def preferences(Closure metaData) {
538                 println("IGNORE -- JUST SOME DEFINITION")
539         }
540         /////////////////////////////////////////////////////////////////////
541         def setLocationMode(String mode) {
542                 location.mode = mode
543         }
544
545         /////////////////////////////////////////////////////////////////////
546         ////subscribe(obj, func)
547         def subscribe(Object obj, Closure FunctionToCall) {
548                 objectList.add(obj)
549                 eventList.add("Touched")
550                 functionList.add(FunctionToCall)
551         }
552         ////subscribe(obj, event, func)
553         def subscribe(Object obj, String event, Closure FunctionToCall) {
554                 objectList.add(obj)
555                 eventList.add(event)
556                 functionList.add(FunctionToCall)
557         }
558         ////subscribe(obj, event, func, data)
559         def subscribe(Object obj, String event, Closure FunctionToCall, LinkedHashMap metaData) {
560                 objectList.add(obj)     
561                 eventList.add(event)
562                 functionList.add(FunctionToCall)
563         }
564         
565         /////////////////////////////////////////////////////////////////////
566         ////runIn(time, func)
567         def runIn(int seconds, Closure functionToCall) {
568                 timersFuncList.add(functionToCall)
569                 timersList.add(new Timer())
570                 def task = timersList[-1].runAfter(1000*seconds, functionToCall)
571         }
572         /////////////////////////////////////////////////////////////////////
573         ////unschedule(func)
574         def unschedule(Closure functionToUnschedule) {
575                 for (int i = 0;i < timersFuncList.size();i++) {
576                         if (timersFuncList[i] == functionToUnschedule) {
577                                 timersList[i].cancel()
578                         }
579                 }
580         }
581         /////////////////////////////////////////////////////////////////////
582         ////sendNotificationToContacts(text, recipients)
583         def sendNotificationToContacts(String text, List recipients) {
584                 for (int i = 0;i < recipients.size();i++) {
585                         for (int j = 0;j < location.contacts.size();j++) {
586                                 if (recipients[i] == location.contacts[j]) {
587                                         println("Sending \""+text+"\" to "+location.phoneNumbers[j].toString())
588                                 }
589                         }
590                 }
591         }
592         /////////////////////////////////////////////////////////////////////
593         ////sendSms(phone, text)
594         def sendSms(long phoneNumber, String text) {
595                 println("Sending \""+text+"\" to "+phoneNumber.toString())
596         }
597         /////////////////////////////////////////////////////////////////////
598         def eventHandler(LinkedHashMap eventDataMap) {
599                 def value = eventDataMap["value"]
600                 def name = eventDataMap["name"]
601                 def deviceId = eventDataMap["deviceId"]
602                 def descriptionText = eventDataMap["descriptionText"]
603                 def displayed = eventDataMap["displayed"]
604                 def linkText = eventDataMap["linkText"]
605                 def isStateChange = eventDataMap["isStateChange"]
606                 def unit = eventDataMap["unit"]
607                 def data = eventDataMap["data"]
608         
609                 for (int i = 0;i < eventList.size();i++) {
610                         if (eventList[i] == name) {
611                                 evt.add(new Event())
612                                 evt[-1].value = value
613                                 evt[-1].name = name
614                                 evt[-1].deviceId = deviceId
615                                 evt[-1].descriptionText = descriptionText
616                                 evt[-1].displayed = displayed
617                                 evt[-1].linkText = linkText
618                                 evt[-1].displayName = linkText
619                                 evt[-1].isStateChange = isStateChange
620                                 evt[-1].unit = unit
621                                 evt[-1].data = data
622                                 functionList[i](evt[-1])
623                         }
624                 }
625         }
626
627         def installed()
628         {
629                 log.debug "Installed with settings: ${settings}"
630                 log.debug "Current mode = ${location.mode}"
631                 subscribe(app, appTouch)
632         }
633
634
635         def updated()
636         {
637                 log.debug "Updated with settings: ${settings}"
638                 log.debug "Current mode = ${location.mode}"
639                 unsubscribe()
640                 subscribe(app, appTouch)
641         }
642
643         def appTouch(evt) {
644                 log.debug "changeMode, location.mode = $location.mode, newMode = $newMode, location.modes = $location.modes"
645             //int i = Verify.getInt(0,2);
646             //list = ['home', 'away', 'night']
647             //location.mode = list[i]
648             if (location.mode != newMode) {
649                                 setLocationMode(newMode)
650                                 log.debug "Changed the mode to '${newMode}'"
651             }   else {
652                 log.debug "New mode is the same as the old mode, leaving it be"
653                 }
654             log.debug "appTouch: $evt"
655             lock1.unlock()
656             switcheson.on()
657             def delay = (waitfor != null && waitfor != "") ? waitfor * 1000 : 120000
658             switchesoff.off(delay: delay)
659         }
660
661
662 }
663
664
665
666 //Application #2
667 class App2 {
668         def reference
669
670         //extractedObjects
671         //extracted objs
672         def location
673         //Object for class Touched!
674         def app
675         //Global Object for class lock!
676         def lock1
677         //Global Object for class contactSensor!
678         def contact
679         //Global variable for number!
680         def minutesLater = 1
681         //Global variable for number!
682         def secondsLater = 10
683         //Global variable for recipients!
684         def recipients = ['AJ']
685         //Global variable for phone number!
686         def phoneNumber = 9495379373
687         //Global Object for functions in subscribe method!
688         def installed = this.&installed
689         //Global Object for functions in subscribe method!
690         def updated = this.&updated
691         //Global Object for functions in subscribe method!
692         def initialize = this.&initialize
693         //Global Object for functions in subscribe method!
694         def lockDoor = this.&lockDoor
695         //Global Object for functions in subscribe method!
696         def unlockDoor = this.&unlockDoor
697         //Global Object for functions in subscribe method!
698         def doorHandler = this.&doorHandler
699         
700
701         App2(Object obj) {
702                 reference = obj         
703                 location = obj.locationObject
704                 app = obj.appObject
705                 //should be created in python
706                 contact = obj.contactObject
707                 lock1 = obj.lockObject
708         }
709         //GlobalVariables
710         //Settings variable defined to settings on purpose
711         def settings = "Settings"
712         //Global variable for state[mode]
713         def state = [home:[],away:[],night:[]]
714         //Create a global logger object for methods
715         def log = new Logger()
716         //Create a global variable for Functions in Subscribe method
717         def functionList = []
718         //Create a global variable for Objects in Subscribe method
719         def objectList = []
720         //Create a global variable for Events in Subscribe method
721         def eventList = []
722         //Create a global list for function schedulers
723         def timersFuncList = []
724         //Create a global list for timer schedulers
725         def timersList = []
726         //Create a global list for events
727         def evt = []
728
729
730         
731
732         
733         //Methods
734         /////////////////////////////////////////////////////////////////////
735         def definition(LinkedHashMap metaData) {
736                 println("IGNORE -- JUST SOME DEFINITION")
737         }
738
739         /////////////////////////////////////////////////////////////////////
740         def preferences(Closure metaData) {
741                 println("IGNORE -- JUST SOME DEFINITION")
742         }
743         /////////////////////////////////////////////////////////////////////
744         def setLocationMode(String mode) {
745                 location.mode = mode
746         }
747
748         /////////////////////////////////////////////////////////////////////
749         ////subscribe(obj, func)
750         def subscribe(Object obj, Closure FunctionToCall) {
751                 objectList.add(obj)
752                 eventList.add("Touched")
753                 functionList.add(FunctionToCall)
754         }
755         ////subscribe(obj, event, func)
756         def subscribe(Object obj, String event, Closure FunctionToCall) {
757                 objectList.add(obj)
758                 eventList.add(event)
759                 functionList.add(FunctionToCall)
760         }
761         ////subscribe(obj, event, func, data)
762         def subscribe(Object obj, String event, Closure FunctionToCall, LinkedHashMap metaData) {
763                 objectList.add(obj)     
764                 eventList.add(event)
765                 functionList.add(FunctionToCall)
766         }
767         
768         /////////////////////////////////////////////////////////////////////
769         ////runIn(time, func)
770         def runIn(int seconds, Closure functionToCall) {
771                 timersFuncList.add(functionToCall)
772                 timersList.add(new Timer())
773                 def task = timersList[-1].runAfter(1000*seconds, functionToCall)
774         }
775         /////////////////////////////////////////////////////////////////////
776         ////unschedule(func)
777         def unschedule(Closure functionToUnschedule) {
778                 for (int i = 0;i < timersFuncList.size();i++) {
779                         if (timersFuncList[i] == functionToUnschedule) {
780                                 timersList[i].cancel()
781                         }
782                 }
783         }
784         /////////////////////////////////////////////////////////////////////
785         ////sendNotificationToContacts(text, recipients)
786         def sendNotificationToContacts(String text, List recipients) {
787                 for (int i = 0;i < recipients.size();i++) {
788                         for (int j = 0;j < location.contacts.size();j++) {
789                                 if (recipients[i] == location.contacts[j]) {
790                                         println("Sending \""+text+"\" to "+location.phoneNumbers[j].toString())
791                                 }
792                         }
793                 }
794         }
795         /////////////////////////////////////////////////////////////////////
796         ////sendSms(phone, text)
797         def sendSms(long phoneNumber, String text) {
798                 println("Sending \""+text+"\" to "+phoneNumber.toString())
799         }
800         /////////////////////////////////////////////////////////////////////
801         def eventHandler(LinkedHashMap eventDataMap) {
802                 def value = eventDataMap["value"]
803                 def name = eventDataMap["name"]
804                 def deviceId = eventDataMap["deviceId"]
805                 def descriptionText = eventDataMap["descriptionText"]
806                 def displayed = eventDataMap["displayed"]
807                 def linkText = eventDataMap["linkText"]
808                 def isStateChange = eventDataMap["isStateChange"]
809                 def unit = eventDataMap["unit"]
810                 def data = eventDataMap["data"]
811         
812                 for (int i = 0;i < eventList.size();i++) {
813                         if (eventList[i] == name) {
814                                 println eventList[i]
815                                 evt.add(new Event())
816                                 evt[-1].value = value
817                                 evt[-1].name = name
818                                 evt[-1].deviceId = deviceId
819                                 evt[-1].descriptionText = descriptionText
820                                 evt[-1].displayed = displayed
821                                 evt[-1].linkText = linkText
822                                 evt[-1].displayName = linkText
823                                 evt[-1].isStateChange = isStateChange
824                                 evt[-1].unit = unit
825                                 evt[-1].data = data
826                                 functionList[i](evt[-1])
827                         }
828                 }
829         }
830
831         def installed(){
832             initialize()
833         }
834
835         def updated(){
836             unsubscribe()
837             unschedule()
838             initialize()
839         }
840
841         def initialize(){
842             log.debug "Settings: ${settings}"
843             subscribe(lock1, "lock", doorHandler, [filterEvents: false])
844             subscribe(lock1, "unlock", doorHandler, [filterEvents: false])  
845             subscribe(contact, "contact.open", doorHandler)
846             subscribe(contact, "contact.closed", doorHandler)
847         }
848
849         def lockDoor(){
850             log.debug "Locking the door."
851             lock1.lock()
852             if(location.contactBookEnabled) {
853                 if ( recipients ) {
854                     log.debug ( "Sending Push Notification..." ) 
855                     sendNotificationToContacts( "${lock1} locked after ${contact} was closed for ${minutesLater} minutes!", recipients)
856                 }
857             }
858             if (phoneNumber) {
859                 log.debug("Sending text message...")
860                 sendSms( phoneNumber, "${lock1} locked after ${contact} was closed for ${minutesLater} minutes!")
861             }
862         }
863
864         def unlockDoor(){
865             log.debug "Unlocking the door."
866             lock1.unlock()
867             if(location.contactBookEnabled) {
868                 if ( recipients ) {
869                     log.debug ( "Sending Push Notification..." ) 
870                     sendNotificationToContacts( "${lock1} unlocked after ${contact} was opened for ${secondsLater} seconds!", recipients)
871                 }
872             }
873             if ( phoneNumber ) {
874                 log.debug("Sending text message...")
875                 sendSms( phoneNumber, "${lock1} unlocked after ${contact} was opened for ${secondsLater} seconds!")
876             }
877         }
878
879         def doorHandler(evt){
880             if ((contact.latestValue("contact") == "open") && (evt.value == "locked")) { // If the door is open and a person locks the door then...  
881                 //def delay = (secondsLater) // runIn uses seconds
882                 runIn( secondsLater, unlockDoor )   // ...schedule (in minutes) to unlock...  We don't want the door to be closed while the lock is engaged. 
883                 println(1)
884             }
885             else if ((contact.latestValue("contact") == "open") && (evt.value == "unlocked")) { // If the door is open and a person unlocks it then...
886                 unschedule( unlockDoor ) // ...we don't need to unlock it later.
887                 println(2)
888             }
889             else if ((contact.latestValue("contact") == "closed") && (evt.value == "locked")) { // If the door is closed and a person manually locks it then...
890                 unschedule( lockDoor ) // ...we don't need to lock it later.
891                 println(3)
892             }   
893             else if ((contact.latestValue("contact") == "closed") && (evt.value == "unlocked")) { // If the door is closed and a person unlocks it then...
894                //def delay = (minutesLater * 60) // runIn uses seconds
895                 runIn( (minutesLater * 2), lockDoor )
896                 //runIn( (minutesLater * 60), lockDoor ) // ...schedule (in minutes) to lock.
897                 println(4)
898             }
899             else if ((lock1.latestValue("lock") == "unlocked") && (evt.value == "open")) { // If a person opens an unlocked door...
900                 unschedule( lockDoor ) // ...we don't need to lock it later.
901                 println(5)
902             }
903             else if ((lock1.latestValue("lock") == "unlocked") && (evt.value == "closed")) { // If a person closes an unlocked door...
904                 //def delay = (minutesLater * 60) // runIn uses seconds
905                 runIn( (minutesLater * 60), lockDoor ) // ...schedule (in minutes) to lock.
906                 println(6)
907             }
908             else { //Opening or Closing door when locked (in case you have a handle lock)
909                 log.debug "Unlocking the door."
910                 lock1.unlock()
911                 println(7)
912                 if(location.contactBookEnabled) {
913                     if ( recipients ) {
914                         log.debug ( "Sending Push Notification..." ) 
915                         sendNotificationToContacts( "${lock1} unlocked after ${contact} was opened or closed when ${lock1} was locked!", recipients)
916                     }
917                 }
918                 if ( phoneNumber ) {
919                     log.debug("Sending text message...")
920                     sendSms( phoneNumber, "${lock1} unlocked after ${contact} was opened or closed when ${lock1} was locked!")
921                 }
922             }
923         }
924 }
925
926
927 @Field def app1 = new App1(this)
928 @Field def app2 = new App2(this)
929 app1.installed()
930 app2.installed()
931 appObject.setValue([name: "Touched", value: "Touched", deviceId: 0, descriptionText: "",
932            displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
933