1 //Infrastructure for SmartThings Application
3 import groovy.transform.Field
11 Touched(Closure sendEvent, int isTouched) {
12 this.sendEvent = sendEvent
13 this.isTouched = isTouched
17 def setValue(LinkedHashMap eventDataMap) {
18 println("The application is Touched!")
19 this.isTouched = 1 //Do we need this?
20 sendEvent(eventDataMap)
24 public class Contacting{
25 private int deviceNumbers
29 Contacting(Closure sendEvent, int deviceNumbers) {
30 this.sendEvent = sendEvent
31 this.deviceNumbers = deviceNumbers
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")]
44 def setValue(LinkedHashMap eventDataMap) {
45 contacts[eventDataMap["deviceId"]].setValue(eventDataMap["value"])
46 sendEvent(eventDataMap)
49 def currentValue(String deviceFeature) {
50 if (deviceNumbers == 1)
51 contacts[0].currentValue(deviceFeature)//It is called if we have only one device
53 contacts*.currentValue(deviceFeature)
56 def latestValue(String deviceFeature) {
57 if (deviceNumbers == 1)
58 contacts[0].latestValue(deviceFeature)//It is called if we have only one device
60 contacts*.latestValue(deviceFeature)
68 public class Contacts {
70 private String displayName
71 private String contactCurrentValue
72 private String contactLatestValue
74 Contacts(int id, String displayName, String contactCurrentValue, String contactLatestValue) {
76 this.displayName = displayName
77 this.contactCurrentValue = contactCurrentValue
78 this.contactLatestValue = contactLatestValue
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
87 def currentValue(String deviceFeature) {
88 if (deviceFeature == "contact") {
89 return contactCurrentValue
93 def latestValue(String deviceFeature) {
94 if (deviceFeature == "contact") {
95 return contactLatestValue
103 private String linkText
104 private String displayName
105 private boolean displayed
107 private String descriptionText
108 private boolean isStateChange
110 private LinkedHashMap data
116 this.displayName = ""
118 this.descriptionText = ""
119 this.isStateChange = false
122 this.displayed = false
127 private int contactBookEnabled
130 private List contacts
131 private List phoneNumbers
133 private Phrase helloHome
136 this.modes = "'home', 'away', 'night'"
138 this.helloHome = new Phrase()
139 this.contactBookEnabled = 1
140 this.contacts = ['AJ']
141 this.phoneNumbers = [9495379373]
146 private LinkedHashMap phrases
149 this.phrases = [id:0, label:"Good Morning!"]
156 public class Locking{
162 Locking(Closure sendEvent, int deviceNumbers) {
163 this.sendEvent = sendEvent
164 this.timers = new Timer()
165 this.deviceNumbers = deviceNumbers
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")]
182 def lock(LinkedHashMap metaData) {
183 def task = timers.runAfter(metaData["delay"]) {
192 def unlock(LinkedHashMap metaData) {
193 def task = timers.runAfter(metaData["delay"]) {
199 def setValue(LinkedHashMap eventDataMap) {
200 locks[eventDataMap["deviceId"]].setValue(eventDataMap["value"])
201 sendEvent(eventDataMap)
204 def currentValue(String deviceFeature) {
205 if (deviceNumbers == 1)
206 locks[0].currentValue(deviceFeature)
208 locks*.currentValue(deviceFeature)
211 def latestValue(String deviceFeature) {
212 if (deviceNumbers == 1)
213 locks[0].latestValue(deviceFeature)
215 locks*.latestValue(deviceFeature)
225 private String displayName
226 private String lockCurrentValue
227 private String lockLatestValue
232 Locks(Closure sendEvent, int id, String displayName, String lockCurrentValue, String lockLatestValue) {
234 this.sendEvent = sendEvent
235 this.displayName = displayName
236 this.lockCurrentValue = lockCurrentValue
237 this.lockLatestValue = lockLatestValue
238 this.timers = new Timer()
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: []])
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: []])
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: []])
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: []])
279 def setValue(String value) {
280 println("the door with id:$id is $value!")
281 this.lockLatestValue = this.lockCurrentValue
282 this.lockCurrentValue = value
285 def currentValue(String deviceFeature) {
286 if (deviceFeature == "lock") {
287 return lockCurrentValue
291 def latestValue(String deviceFeature) {
292 if (deviceFeature == "lock") {
293 return lockLatestValue
299 private boolean printToConsole = true
301 def methodMissing(String name, args) {
302 def messsage = args[0]
303 if (printToConsole) {
309 public class Switches {
311 private String displayName
312 private String switchCurrentValue
313 private String switchLatestValue
318 Switches(Closure sendEvent, int id, String displayName, String switchCurrentValue, String switchLatestValue) {
319 this.sendEvent = sendEvent
320 this.timers = new Timer()
323 this.displayName = displayName
324 this.switchCurrentValue = switchCurrentValue
325 this.switchLatestValue = switchLatestValue
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: []])
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: []])
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: []])
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: []])
366 def setValue(String value) {
367 println("the switch with id:$id is $value!")
368 this.switchLatestValue = this.switchCurrentValue
369 this.switchCurrentValue = value
372 def currentValue(String deviceFeature) {
373 if (deviceFeature == "switch") {
374 return switchCurrentValue
378 def latestValue(String deviceFeature) {
379 if (deviceFeature == "switch") {
380 return switchLatestValue
385 public class Switching{
391 Switching(Closure sendEvent, int deviceNumbers) {
392 this.sendEvent = sendEvent
393 this.timers = new Timer()
394 this.deviceNumbers = deviceNumbers
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")]
411 def on(LinkedHashMap metaData) {
412 def task = timers.runAfter(metaData["delay"]) {
421 def off(LinkedHashMap metaData) {
422 def task = timers.runAfter(metaData["delay"]) {
428 def setValue(LinkedHashMap eventDataMap) {
429 switches[eventDataMap["deviceId"]].setValue(eventDataMap["value"])
430 sendEvent(eventDataMap)
434 def currentValue(String deviceFeature) {
435 if (deviceNumbers == 1)
436 switches[0].currentValue(deviceFeature)
438 switches*.currentValue(deviceFeature)
441 def latestValue(String deviceFeature) {
442 if (deviceNumbers == 1)
443 switches[0].latestValue(deviceFeature)
445 switches*.latestValue(deviceFeature)
453 //Global variable for sendEvent
454 @Field def sendEvent = {eventDataMap ->
455 app1.eventHandler(eventDataMap)
456 app2.eventHandler(eventDataMap)
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
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
478 //Object for class Touched!
480 //Object for class switch!
482 //Object for class switch!
484 //Object for class lock!
488 //Variable for number!
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
499 location = obj.locationObject
501 //should be created in python
502 switchesoff = obj.switchObject
503 switcheson = obj.switchObject
504 lock1 = obj.lockObject
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
517 //Create a global variable for Events in Subscribe method
519 //Create a global list for function schedulers
520 def timersFuncList = []
521 //Create a global list for timer schedulers
523 //Create a global list for events
531 /////////////////////////////////////////////////////////////////////
532 def definition(LinkedHashMap metaData) {
533 println("IGNORE -- JUST SOME DEFINITION")
536 /////////////////////////////////////////////////////////////////////
537 def preferences(Closure metaData) {
538 println("IGNORE -- JUST SOME DEFINITION")
540 /////////////////////////////////////////////////////////////////////
541 def setLocationMode(String mode) {
545 /////////////////////////////////////////////////////////////////////
546 ////subscribe(obj, func)
547 def subscribe(Object obj, Closure FunctionToCall) {
549 eventList.add("Touched")
550 functionList.add(FunctionToCall)
552 ////subscribe(obj, event, func)
553 def subscribe(Object obj, String event, Closure FunctionToCall) {
556 functionList.add(FunctionToCall)
558 ////subscribe(obj, event, func, data)
559 def subscribe(Object obj, String event, Closure FunctionToCall, LinkedHashMap metaData) {
562 functionList.add(FunctionToCall)
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)
572 /////////////////////////////////////////////////////////////////////
574 def unschedule(Closure functionToUnschedule) {
575 for (int i = 0;i < timersFuncList.size();i++) {
576 if (timersFuncList[i] == functionToUnschedule) {
577 timersList[i].cancel()
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())
592 /////////////////////////////////////////////////////////////////////
593 ////sendSms(phone, text)
594 def sendSms(long phoneNumber, String text) {
595 println("Sending \""+text+"\" to "+phoneNumber.toString())
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"]
609 for (int i = 0;i < eventList.size();i++) {
610 if (eventList[i] == name) {
612 evt[-1].value = value
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
622 functionList[i](evt[-1])
629 log.debug "Installed with settings: ${settings}"
630 log.debug "Current mode = ${location.mode}"
631 subscribe(app, appTouch)
637 log.debug "Updated with settings: ${settings}"
638 log.debug "Current mode = ${location.mode}"
640 subscribe(app, appTouch)
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}'"
652 log.debug "New mode is the same as the old mode, leaving it be"
654 log.debug "appTouch: $evt"
657 def delay = (waitfor != null && waitfor != "") ? waitfor * 1000 : 120000
658 switchesoff.off(delay: delay)
673 //Object for class Touched!
675 //Global Object for class lock!
677 //Global Object for class contactSensor!
679 //Global variable for number!
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
703 location = obj.locationObject
705 //should be created in python
706 contact = obj.contactObject
707 lock1 = obj.lockObject
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
720 //Create a global variable for Events in Subscribe method
722 //Create a global list for function schedulers
723 def timersFuncList = []
724 //Create a global list for timer schedulers
726 //Create a global list for events
734 /////////////////////////////////////////////////////////////////////
735 def definition(LinkedHashMap metaData) {
736 println("IGNORE -- JUST SOME DEFINITION")
739 /////////////////////////////////////////////////////////////////////
740 def preferences(Closure metaData) {
741 println("IGNORE -- JUST SOME DEFINITION")
743 /////////////////////////////////////////////////////////////////////
744 def setLocationMode(String mode) {
748 /////////////////////////////////////////////////////////////////////
749 ////subscribe(obj, func)
750 def subscribe(Object obj, Closure FunctionToCall) {
752 eventList.add("Touched")
753 functionList.add(FunctionToCall)
755 ////subscribe(obj, event, func)
756 def subscribe(Object obj, String event, Closure FunctionToCall) {
759 functionList.add(FunctionToCall)
761 ////subscribe(obj, event, func, data)
762 def subscribe(Object obj, String event, Closure FunctionToCall, LinkedHashMap metaData) {
765 functionList.add(FunctionToCall)
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)
775 /////////////////////////////////////////////////////////////////////
777 def unschedule(Closure functionToUnschedule) {
778 for (int i = 0;i < timersFuncList.size();i++) {
779 if (timersFuncList[i] == functionToUnschedule) {
780 timersList[i].cancel()
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())
795 /////////////////////////////////////////////////////////////////////
796 ////sendSms(phone, text)
797 def sendSms(long phoneNumber, String text) {
798 println("Sending \""+text+"\" to "+phoneNumber.toString())
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"]
812 for (int i = 0;i < eventList.size();i++) {
813 if (eventList[i] == name) {
816 evt[-1].value = value
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
826 functionList[i](evt[-1])
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)
850 log.debug "Locking the door."
852 if(location.contactBookEnabled) {
854 log.debug ( "Sending Push Notification..." )
855 sendNotificationToContacts( "${lock1} locked after ${contact} was closed for ${minutesLater} minutes!", recipients)
859 log.debug("Sending text message...")
860 sendSms( phoneNumber, "${lock1} locked after ${contact} was closed for ${minutesLater} minutes!")
865 log.debug "Unlocking the door."
867 if(location.contactBookEnabled) {
869 log.debug ( "Sending Push Notification..." )
870 sendNotificationToContacts( "${lock1} unlocked after ${contact} was opened for ${secondsLater} seconds!", recipients)
874 log.debug("Sending text message...")
875 sendSms( phoneNumber, "${lock1} unlocked after ${contact} was opened for ${secondsLater} seconds!")
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.
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.
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.
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.
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.
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.
908 else { //Opening or Closing door when locked (in case you have a handle lock)
909 log.debug "Unlocking the door."
912 if(location.contactBookEnabled) {
914 log.debug ( "Sending Push Notification..." )
915 sendNotificationToContacts( "${lock1} unlocked after ${contact} was opened or closed when ${lock1} was locked!", recipients)
919 log.debug("Sending text message...")
920 sendSms( phoneNumber, "${lock1} unlocked after ${contact} was opened or closed when ${lock1} was locked!")
927 @Field def app1 = new App1(this)
928 @Field def app2 = new App2(this)
931 appObject.setValue([name: "Touched", value: "Touched", deviceId: 0, descriptionText: "",
932 displayed: true, linkText: "", isStateChange: false, unit: "", data: []])