1 //Infrastructure for SmartThings Application
3 import groovy.transform.Field
6 import ContactSensor.Contacting
7 import ContactSensor.Contacts
10 import Switch.Switching
11 import Switch.Switches
13 import Location.LocationVar
14 import Location.Phrase
15 import appTouch.Touched
17 import Timer.SimulatedTimer
20 /////////////////////////////////////////////////////////////////////
21 def eventHandler(LinkedHashMap eventDataMap) {
22 def value = eventDataMap["value"]
23 def name = eventDataMap["name"]
24 def deviceId = eventDataMap["deviceId"]
25 def descriptionText = eventDataMap["descriptionText"]
26 def displayed = eventDataMap["displayed"]
27 def linkText = eventDataMap["linkText"]
28 def isStateChange = eventDataMap["isStateChange"]
29 def unit = eventDataMap["unit"]
30 def data = eventDataMap["data"]
32 for (int i = 0;i < app2.eventList.size();i++) {
33 if (app2.eventList[i] == name) {
34 def event = new Event(value, name, deviceId, descriptionText, displayed, linkText, linkText, isStateChange, unit, data)
36 app2.functionList[i](event)
40 for (int i = 0;i < app1.eventList.size();i++) {
41 if (app1.eventList[i] == name) {
42 def event = new Event(value, name, deviceId, descriptionText, displayed, linkText, linkText, isStateChange, unit, data)
44 app1.functionList[i](event)
49 //GlobalVariables for both Apps
50 //Create a global variable for send event
51 @Field def sendEvent = {eventDataMap ->
52 eventHandler(eventDataMap)
55 @Field def locationObject = new LocationVar()
57 @Field def appObject = new Touched(sendEvent, 0)
58 //Create a global list for events
61 //Extracted global objects for both Apps
62 //Global Object for class lock!
63 @Field def lockObject = new Locking(sendEvent,1)
64 //Global Object for class contactSensor!
65 @Field def contactObject = new Contacting(sendEvent,1)
66 //Global Object for class switch!
67 @Field def switchObject = new Switching(sendEvent, 1)
75 //Extracted objects for App1
76 //Object for class lock!
78 //Object for class contactSensor!
80 //Global variable for number!
82 //Global variable for number!
84 //Global variable for contact!
86 //Global variable for phone!
87 def phoneNumber = 9495379373
89 //Extracted objects for functions for App1
90 //Global Object for functions in subscribe method!
91 def installed = this.&installed
92 //Global Object for functions in subscribe method!
93 def updated = this.&updated
94 //Global Object for functions in subscribe method!
95 def initialize = this.&initialize
96 //Global Object for functions in subscribe method!
97 def lockDoor = this.&lockDoor
98 //Global Object for functions in subscribe method!
99 def unlockDoor = this.&unlockDoor
100 //Global Object for functions in subscribe method!
101 def doorHandler = this.&doorHandler
105 location = obj.locationObject
107 lock1 = obj.lockObject
108 contact = obj.contactObject
110 //Global variables for each app
111 //Settings variable defined to settings on purpose
112 def settings = "Settings"
113 //Global variable for state[mode]
114 def state = [home:[],away:[],night:[]]
115 //Create a global logger object for methods
116 def log = new Logger()
117 //Create a global variable for Functions in Subscribe method
118 def functionList = []
119 //Create a global variable for Objects in Subscribe method
121 //Create a global variable for Events in Subscribe method
123 //Create a global list for function schedulers
124 def timersFuncList = []
125 //Create a global list for timer schedulers
129 /////////////////////////////////////////////////////////////////////
130 def setLocationMode(String mode) {
134 /////////////////////////////////////////////////////////////////////
135 ////subscribe(obj, func)
136 def subscribe(Object obj, Closure FunctionToCall) {
138 eventList.add("Touched")
139 functionList.add(FunctionToCall)
141 ////subscribe(obj, event, func)
142 def subscribe(Object obj, String event, Closure FunctionToCall) {
145 functionList.add(FunctionToCall)
147 ////subscribe(obj, event, func, data)
148 def subscribe(Object obj, String event, Closure FunctionToCall, LinkedHashMap metaData) {
151 functionList.add(FunctionToCall)
153 /////////////////////////////////////////////////////////////////////
154 ////runIn(time, func)
155 def runIn(int seconds, Closure functionToCall) {
156 if (timersFuncList.contains(functionToCall)) {
157 timersList[timersFuncList.indexOf(functionToCall)].cancel()
158 def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds, functionToCall)
160 timersFuncList.add(functionToCall)
161 timersList.add(new SimulatedTimer())
162 def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds, functionToCall)
165 /////////////////////////////////////////////////////////////////////
167 def unschedule(Closure functionToUnschedule) {
168 for (int i = 0;i < timersFuncList.size();i++) {
169 if (timersFuncList[i] == functionToUnschedule) {
170 if (timersList != null)
171 timersList[i].cancel()
178 for (int i = 0;i < timersFuncList.size();i++) {
179 if (timersList != null)
180 timersList[i].cancel()
183 /////////////////////////////////////////////////////////////////////
184 ////sendNotificationToContacts(text, recipients)
185 def sendNotificationToContacts(String text, String recipients) {
186 for (int i = 0;i < recipients.size();i++) {
187 for (int j = 0;j < location.contacts.size();j++) {
188 if (recipients[i] == location.contacts[j]) {
189 println("Sending \""+text+"\" to "+location.phoneNumbers[j].toString())
194 /////////////////////////////////////////////////////////////////////
195 ////sendSms(phone, text)
196 def sendSms(long phoneNumber, String text) {
197 println("Sending \""+text+"\" to "+phoneNumber.toString())
199 /////////////////////////////////////////////////////////////////////
201 def sendPush(String text) {
204 /////////////////////////////////////////////////////////////////////
205 ////schedule(time, nameOfFunction as String)
206 def schedule(String time, String nameOfFunction) {
207 def _inputTime = time.split(':')
208 Date date = new Date()
209 def _currentTime = date.format("HH:mm:ss").split(':')
211 //Convert input time and current time to minutes
212 def inputTime = Integer.parseInt(_inputTime[0])*3600+Integer.parseInt(_inputTime[1])*60
213 def currentTime = Integer.parseInt(_currentTime[0])*3600+Integer.parseInt(_currentTime[1])*60+Integer.parseInt(_currentTime[2])
216 if (inputTime < currentTime) {
217 delay = 24*60*60-inputTime+currentTime
219 delay = inputTime-currentTime
222 timersFuncList.add(nameOfFunction)
223 timersList.add(new SimulatedTimer())
224 def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*1000) {
228 ////schedule(time, nameOfFunction as Closure)
229 def schedule(String time, Closure nameOfFunction) {
230 def _inputTime = time.split(':')
231 Date date = new Date()
232 def _currentTime = date.format("HH:mm:ss").split(':')
234 //Convert input time and current time to minutes
235 def inputTime = Integer.parseInt(_inputTime[0])*3600+Integer.parseInt(_inputTime[1])*60
236 def currentTime = Integer.parseInt(_currentTime[0])*3600+Integer.parseInt(_currentTime[1])*60+Integer.parseInt(_currentTime[2])
239 if (inputTime < currentTime) {
240 delay = 24*60*60-inputTime+currentTime
242 delay = inputTime-currentTime
245 if (timersFuncList.contains(nameOfFunction)) {
246 timersList[timersFuncList.indexOf(nameOfFunction)].cancel()
247 def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds, nameOfFunction)
249 timersFuncList.add(nameOfFunction)
250 timersList.add(new SimulatedTimer())
251 def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds, nameOfFunction)
266 log.debug "Settings: ${settings}"
267 subscribe(lock1, "lock", doorHandler, [filterEvents: false])
268 subscribe(lock1, "unlock", doorHandler, [filterEvents: false])
269 subscribe(contact, "contact.open", doorHandler)
270 subscribe(contact, "contact.closed", doorHandler)
274 log.debug "Locking the door."
276 if(location.contactBookEnabled) {
278 log.debug ( "Sending Push Notification..." )
279 sendNotificationToContacts( "${lock1} locked after ${contact} was closed for ${minutesLater} minutes!", recipients)
283 log.debug("Sending text message...")
284 sendSms( phoneNumber, "${lock1} locked after ${contact} was closed for ${minutesLater} minutes!")
289 log.debug "Unlocking the door."
291 if(location.contactBookEnabled) {
293 log.debug ( "Sending Push Notification..." )
294 sendNotificationToContacts( "${lock1} unlocked after ${contact} was opened for ${secondsLater} seconds!", recipients)
298 log.debug("Sending text message...")
299 sendSms( phoneNumber, "${lock1} unlocked after ${contact} was opened for ${secondsLater} seconds!")
303 def doorHandler(evt){
304 if ((contact.latestValue("contact") == "open") && (evt.value == "locked")) { // If the door is open and a person locks the door then...
305 //def delay = (secondsLater) // runIn uses seconds
306 runIn( secondsLater, unlockDoor ) // ...schedule (in minutes) to unlock... We don't want the door to be closed while the lock is engaged.
308 else if ((contact.latestValue("contact") == "open") && (evt.value == "unlocked")) { // If the door is open and a person unlocks it then...
309 unschedule( unlockDoor ) // ...we don't need to unlock it later.
311 else if ((contact.latestValue("contact") == "closed") && (evt.value == "locked")) { // If the door is closed and a person manually locks it then...
312 unschedule( lockDoor ) // ...we don't need to lock it later.
314 else if ((contact.latestValue("contact") == "closed") && (evt.value == "unlocked")) { // If the door is closed and a person unlocks it then...
315 //def delay = (minutesLater * 60) // runIn uses seconds
316 runIn( (minutesLater * 60), lockDoor ) // ...schedule (in minutes) to lock.
318 else if ((lock1.latestValue("lock") == "unlocked") && (evt.value == "open")) { // If a person opens an unlocked door...
319 unschedule( lockDoor ) // ...we don't need to lock it later.
321 else if ((lock1.latestValue("lock") == "unlocked") && (evt.value == "closed")) { // If a person closes an unlocked door...
322 //def delay = (minutesLater * 60) // runIn uses seconds
323 runIn( (minutesLater * 60), lockDoor ) // ...schedule (in minutes) to lock.
325 else { //Opening or Closing door when locked (in case you have a handle lock)
326 log.debug "Unlocking the door."
328 if(location.contactBookEnabled) {
330 log.debug ( "Sending Push Notification..." )
331 sendNotificationToContacts( "${lock1} unlocked after ${contact} was opened or closed when ${lock1} was locked!", recipients)
335 log.debug("Sending text message...")
336 sendSms( phoneNumber, "${lock1} unlocked after ${contact} was opened or closed when ${lock1} was locked!")
349 //Extracted objects for App2
350 //Object for class switch!
352 //Object for class switch!
354 //Object for class lock!
356 //Global variable for mode!
358 //Global variable for number!
361 //Extracted objects for functions for App2
362 //Global Object for functions in subscribe method!
363 def installed = this.&installed
364 //Global Object for functions in subscribe method!
365 def updated = this.&updated
366 //Global Object for functions in subscribe method!
367 def appTouch = this.&appTouch
371 location = obj.locationObject
373 switchesoff = obj.switchObject
374 switcheson = obj.switchObject
375 lock1 = obj.lockObject
377 //Global variables for each app
378 //Settings variable defined to settings on purpose
379 def settings = "Settings"
380 //Global variable for state[mode]
381 def state = [home:[],away:[],night:[]]
382 //Create a global logger object for methods
383 def log = new Logger()
384 //Create a global variable for Functions in Subscribe method
385 def functionList = []
386 //Create a global variable for Objects in Subscribe method
388 //Create a global variable for Events in Subscribe method
390 //Create a global list for function schedulers
391 def timersFuncList = []
392 //Create a global list for timer schedulers
396 /////////////////////////////////////////////////////////////////////
397 def setLocationMode(String mode) {
401 /////////////////////////////////////////////////////////////////////
402 ////subscribe(obj, func)
403 def subscribe(Object obj, Closure FunctionToCall) {
405 eventList.add("Touched")
406 functionList.add(FunctionToCall)
408 ////subscribe(obj, event, func)
409 def subscribe(Object obj, String event, Closure FunctionToCall) {
412 functionList.add(FunctionToCall)
414 ////subscribe(obj, event, func, data)
415 def subscribe(Object obj, String event, Closure FunctionToCall, LinkedHashMap metaData) {
418 functionList.add(FunctionToCall)
420 /////////////////////////////////////////////////////////////////////
421 ////runIn(time, func)
422 def runIn(int seconds, Closure functionToCall) {
423 if (timersFuncList.contains(functionToCall)) {
424 timersList[timersFuncList.indexOf(functionToCall)].cancel()
425 def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds, functionToCall)
427 timersFuncList.add(functionToCall)
428 timersList.add(new SimulatedTimer())
429 def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds, functionToCall)
432 /////////////////////////////////////////////////////////////////////
434 def unschedule(Closure functionToUnschedule) {
435 for (int i = 0;i < timersFuncList.size();i++) {
436 if (timersFuncList[i] == functionToUnschedule) {
437 if (timersList != null)
438 timersList[i].cancel()
445 for (int i = 0;i < timersFuncList.size();i++) {
446 if (timersList != null)
447 timersList[i].cancel()
450 /////////////////////////////////////////////////////////////////////
451 ////sendNotificationToContacts(text, recipients)
452 def sendNotificationToContacts(String text, String recipients) {
453 for (int i = 0;i < recipients.size();i++) {
454 for (int j = 0;j < location.contacts.size();j++) {
455 if (recipients[i] == location.contacts[j]) {
456 println("Sending \""+text+"\" to "+location.phoneNumbers[j].toString())
461 /////////////////////////////////////////////////////////////////////
462 ////sendSms(phone, text)
463 def sendSms(long phoneNumber, String text) {
464 println("Sending \""+text+"\" to "+phoneNumber.toString())
466 /////////////////////////////////////////////////////////////////////
467 ////schedule(time, nameOfFunction as String)
468 def schedule(String time, String nameOfFunction) {
469 def _inputTime = time.split(':')
470 Date date = new Date()
471 def _currentTime = date.format("HH:mm:ss").split(':')
473 //Convert input time and current time to minutes
474 def inputTime = Integer.parseInt(_inputTime[0])*3600+Integer.parseInt(_inputTime[1])*60
475 def currentTime = Integer.parseInt(_currentTime[0])*3600+Integer.parseInt(_currentTime[1])*60+Integer.parseInt(_currentTime[2])
478 if (inputTime < currentTime) {
479 delay = 24*60*60-inputTime+currentTime
481 delay = inputTime-currentTime
484 timersFuncList.add(nameOfFunction)
485 timersList.add(new SimulatedTimer())
486 def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*1000) {
490 ////schedule(time, nameOfFunction as Closure)
491 def schedule(String time, Closure nameOfFunction) {
492 def _inputTime = time.split(':')
493 Date date = new Date()
494 def _currentTime = date.format("HH:mm:ss").split(':')
496 //Convert input time and current time to minutes
497 def inputTime = Integer.parseInt(_inputTime[0])*3600+Integer.parseInt(_inputTime[1])*60
498 def currentTime = Integer.parseInt(_currentTime[0])*3600+Integer.parseInt(_currentTime[1])*60+Integer.parseInt(_currentTime[2])
501 if (inputTime < currentTime) {
502 delay = 24*60*60-inputTime+currentTime
504 delay = inputTime-currentTime
507 if (timersFuncList.contains(nameOfFunction)) {
508 timersList[timersFuncList.indexOf(nameOfFunction)].cancel()
509 def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds, nameOfFunction)
511 timersFuncList.add(nameOfFunction)
512 timersList.add(new SimulatedTimer())
513 def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds, nameOfFunction)
519 log.debug "Installed with settings: ${settings}"
520 log.debug "Current mode = ${location.mode}"
521 subscribe(app, appTouch)
527 log.debug "Updated with settings: ${settings}"
528 log.debug "Current mode = ${location.mode}"
530 subscribe(app, appTouch)
534 log.debug "changeMode, location.mode = $location.mode, newMode = $newMode, location.modes = $location.modes"
535 if (location.mode != newMode) {
536 setLocationMode(newMode)
537 log.debug "Changed the mode to '${newMode}'"
539 log.debug "New mode is the same as the old mode, leaving it be"
541 log.debug "appTouch: $evt"
544 def delay = (waitfor != null && waitfor != "") ? waitfor * 1000 : 120000
545 switchesoff.off(delay: delay)
549 @Field def app1 = new App1(this)
550 @Field def app2 = new App2(this)
554 // Generate a random variable
555 Random random = new Random(1131)
563 appObject.setValue([name: "Touched", value: "Touched", deviceId: 0, descriptionText: "",
564 displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
565 Thread.sleep(random.nextInt(nextRandom));
577 lockObject.setValue([name: "lock", value: "locked", deviceId: 0, descriptionText: "",
578 displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
579 Thread.sleep(random.nextInt(nextRandom));
589 lockObject.setValue([name: "unlock", value: "unlocked", deviceId: 0, descriptionText: "",
590 displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
591 Thread.sleep(random.nextInt(nextRandom));
596 // Contact sensor events
602 contactObject.setValue([name: "contact.open", value: "open", deviceId: 0, descriptionText: "",
603 displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
604 Thread.sleep(random.nextInt(nextRandom));
615 contactObject.setValue([name: "contact.closed", value: "closed", deviceId: 0, descriptionText: "",
616 displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
617 Thread.sleep(random.nextInt(nextRandom));