//Infrastructure for SmartThings Application //Importing Libraries import groovy.transform.Field //Importing Classes import ContactSensor.Contacting import ContactSensor.Contacts import Lock.Locking import Lock.Locks import Switch.Switching import Switch.Switches import Logger.Logger import Location.LocationVar import Location.Phrase import appTouch.Touched import Event.Event import Timer.SimulatedTimer //Global eventHandler ///////////////////////////////////////////////////////////////////// def eventHandler(LinkedHashMap eventDataMap) { def value = eventDataMap["value"] def name = eventDataMap["name"] def deviceId = eventDataMap["deviceId"] def descriptionText = eventDataMap["descriptionText"] def displayed = eventDataMap["displayed"] def linkText = eventDataMap["linkText"] def isStateChange = eventDataMap["isStateChange"] def unit = eventDataMap["unit"] def data = eventDataMap["data"] for (int i = 0;i < app2.eventList.size();i++) { if (app2.eventList[i] == name) { def event = new Event(value, name, deviceId, descriptionText, displayed, linkText, linkText, isStateChange, unit, data) evt.add(event) app2.functionList[i](event) } } for (int i = 0;i < app1.eventList.size();i++) { if (app1.eventList[i] == name) { def event = new Event(value, name, deviceId, descriptionText, displayed, linkText, linkText, isStateChange, unit, data) evt.add(event) app1.functionList[i](event) } } } //GlobalVariables for both Apps //Create a global variable for send event @Field def sendEvent = {eventDataMap -> eventHandler(eventDataMap) } //Object for location @Field def locationObject = new LocationVar() //Object for touch @Field def appObject = new Touched(sendEvent, 0) //Create a global list for events @Field def evt = [] //Extracted global objects for both Apps //Global Object for class lock! @Field def lockObject = new Locking(sendEvent,1) //Global Object for class contactSensor! @Field def contactObject = new Contacting(sendEvent,1) //Global Object for class switch! @Field def switchObject = new Switching(sendEvent, 1) //Application #1 class App1 { def reference def location def app //Extracted objects for App1 //Object for class lock! def lock1 //Object for class contactSensor! def contact //Global variable for number! def minutesLater = 1 //Global variable for number! def secondsLater = 10 //Global variable for contact! def recipients = "AJ" //Global variable for phone! def phoneNumber = 9495379373 //Extracted objects for functions for App1 //Global Object for functions in subscribe method! def installed = this.&installed //Global Object for functions in subscribe method! def updated = this.&updated //Global Object for functions in subscribe method! def initialize = this.&initialize //Global Object for functions in subscribe method! def lockDoor = this.&lockDoor //Global Object for functions in subscribe method! def unlockDoor = this.&unlockDoor //Global Object for functions in subscribe method! def doorHandler = this.&doorHandler App1(Object obj) { reference = obj location = obj.locationObject app = obj.appObject lock1 = obj.lockObject contact = obj.contactObject } //Global variables for each app //Settings variable defined to settings on purpose def settings = "Settings" //Global variable for state[mode] def state = [home:[],away:[],night:[]] //Create a global logger object for methods def log = new Logger() //Create a global variable for Functions in Subscribe method def functionList = [] //Create a global variable for Objects in Subscribe method def objectList = [] //Create a global variable for Events in Subscribe method def eventList = [] //Create a global list for function schedulers def timersFuncList = [] //Create a global list for timer schedulers def timersList = [] //Methods ///////////////////////////////////////////////////////////////////// def setLocationMode(String mode) { location.mode = mode } ///////////////////////////////////////////////////////////////////// ////subscribe(obj, func) def subscribe(Object obj, Closure FunctionToCall) { objectList.add(obj) eventList.add("Touched") functionList.add(FunctionToCall) } ////subscribe(obj, event, func) def subscribe(Object obj, String event, Closure FunctionToCall) { objectList.add(obj) eventList.add(event) functionList.add(FunctionToCall) } ////subscribe(obj, event, func, data) def subscribe(Object obj, String event, Closure FunctionToCall, LinkedHashMap metaData) { objectList.add(obj) eventList.add(event) functionList.add(FunctionToCall) } ///////////////////////////////////////////////////////////////////// ////runIn(time, func) def runIn(int seconds, Closure functionToCall) { if (timersFuncList.contains(functionToCall)) { timersList[timersFuncList.indexOf(functionToCall)].cancel() def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds, functionToCall) } else { timersFuncList.add(functionToCall) timersList.add(new SimulatedTimer()) def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds, functionToCall) } } ///////////////////////////////////////////////////////////////////// ////unschedule(func) def unschedule(Closure functionToUnschedule) { for (int i = 0;i < timersFuncList.size();i++) { if (timersFuncList[i] == functionToUnschedule) { if (timersList != null) timersList[i].cancel() } } } def unschedule() { for (int i = 0;i < timersFuncList.size();i++) { if (timersList != null) timersList[i].cancel() } } ///////////////////////////////////////////////////////////////////// ////sendNotificationToContacts(text, recipients) def sendNotificationToContacts(String text, String recipients) { for (int i = 0;i < recipients.size();i++) { for (int j = 0;j < location.contacts.size();j++) { if (recipients[i] == location.contacts[j]) { println("Sending \""+text+"\" to "+location.phoneNumbers[j].toString()) } } } } ///////////////////////////////////////////////////////////////////// ////sendSms(phone, text) def sendSms(long phoneNumber, String text) { println("Sending \""+text+"\" to "+phoneNumber.toString()) } ///////////////////////////////////////////////////////////////////// ////sendPush(text) def sendPush(String text) { println(text) } ///////////////////////////////////////////////////////////////////// ////schedule(time, nameOfFunction as String) def schedule(String time, String nameOfFunction) { def _inputTime = time.split(':') Date date = new Date() def _currentTime = date.format("HH:mm:ss").split(':') //Convert input time and current time to minutes def inputTime = Integer.parseInt(_inputTime[0])*3600+Integer.parseInt(_inputTime[1])*60 def currentTime = Integer.parseInt(_currentTime[0])*3600+Integer.parseInt(_currentTime[1])*60+Integer.parseInt(_currentTime[2]) def delay if (inputTime < currentTime) { delay = 24*60*60-inputTime+currentTime } else { delay = inputTime-currentTime } timersFuncList.add(nameOfFunction) timersList.add(new SimulatedTimer()) def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*1000) { "$nameOfFunction"() } } ////schedule(time, nameOfFunction as Closure) def schedule(String time, Closure nameOfFunction) { def _inputTime = time.split(':') Date date = new Date() def _currentTime = date.format("HH:mm:ss").split(':') //Convert input time and current time to minutes def inputTime = Integer.parseInt(_inputTime[0])*3600+Integer.parseInt(_inputTime[1])*60 def currentTime = Integer.parseInt(_currentTime[0])*3600+Integer.parseInt(_currentTime[1])*60+Integer.parseInt(_currentTime[2]) def delay if (inputTime < currentTime) { delay = 24*60*60-inputTime+currentTime } else { delay = inputTime-currentTime } if (timersFuncList.contains(nameOfFunction)) { timersList[timersFuncList.indexOf(nameOfFunction)].cancel() def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds, nameOfFunction) } else { timersFuncList.add(nameOfFunction) timersList.add(new SimulatedTimer()) def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds, nameOfFunction) } } def installed(){ initialize() } def updated(){ unsubscribe() unschedule() initialize() } def initialize(){ log.debug "Settings: ${settings}" subscribe(lock1, "lock", doorHandler, [filterEvents: false]) subscribe(lock1, "unlock", doorHandler, [filterEvents: false]) subscribe(contact, "contact.open", doorHandler) subscribe(contact, "contact.closed", doorHandler) } def lockDoor(){ log.debug "Locking the door." lock1.lock() if(location.contactBookEnabled) { if ( recipients ) { log.debug ( "Sending Push Notification..." ) sendNotificationToContacts( "${lock1} locked after ${contact} was closed for ${minutesLater} minutes!", recipients) } } if (phoneNumber) { log.debug("Sending text message...") sendSms( phoneNumber, "${lock1} locked after ${contact} was closed for ${minutesLater} minutes!") } } def unlockDoor(){ log.debug "Unlocking the door." lock1.unlock() if(location.contactBookEnabled) { if ( recipients ) { log.debug ( "Sending Push Notification..." ) sendNotificationToContacts( "${lock1} unlocked after ${contact} was opened for ${secondsLater} seconds!", recipients) } } if ( phoneNumber ) { log.debug("Sending text message...") sendSms( phoneNumber, "${lock1} unlocked after ${contact} was opened for ${secondsLater} seconds!") } } def doorHandler(evt){ if ((contact.latestValue("contact") == "open") && (evt.value == "locked")) { // If the door is open and a person locks the door then... //def delay = (secondsLater) // runIn uses seconds runIn( secondsLater, unlockDoor ) // ...schedule (in minutes) to unlock... We don't want the door to be closed while the lock is engaged. } else if ((contact.latestValue("contact") == "open") && (evt.value == "unlocked")) { // If the door is open and a person unlocks it then... unschedule( unlockDoor ) // ...we don't need to unlock it later. } else if ((contact.latestValue("contact") == "closed") && (evt.value == "locked")) { // If the door is closed and a person manually locks it then... unschedule( lockDoor ) // ...we don't need to lock it later. } else if ((contact.latestValue("contact") == "closed") && (evt.value == "unlocked")) { // If the door is closed and a person unlocks it then... //def delay = (minutesLater * 60) // runIn uses seconds runIn( (minutesLater * 60), lockDoor ) // ...schedule (in minutes) to lock. } else if ((lock1.latestValue("lock") == "unlocked") && (evt.value == "open")) { // If a person opens an unlocked door... unschedule( lockDoor ) // ...we don't need to lock it later. } else if ((lock1.latestValue("lock") == "unlocked") && (evt.value == "closed")) { // If a person closes an unlocked door... //def delay = (minutesLater * 60) // runIn uses seconds runIn( (minutesLater * 60), lockDoor ) // ...schedule (in minutes) to lock. } else { //Opening or Closing door when locked (in case you have a handle lock) log.debug "Unlocking the door." lock1.unlock() if(location.contactBookEnabled) { if ( recipients ) { log.debug ( "Sending Push Notification..." ) sendNotificationToContacts( "${lock1} unlocked after ${contact} was opened or closed when ${lock1} was locked!", recipients) } } if ( phoneNumber ) { log.debug("Sending text message...") sendSms( phoneNumber, "${lock1} unlocked after ${contact} was opened or closed when ${lock1} was locked!") } } } } //Application #2 class App2 { def reference def location def app //Extracted objects for App2 //Object for class switch! def switchesoff //Object for class switch! def switcheson //Object for class lock! def lock1 //Global variable for mode! def newMode = "away" //Global variable for number! def waitfor = 4 //Extracted objects for functions for App2 //Global Object for functions in subscribe method! def installed = this.&installed //Global Object for functions in subscribe method! def updated = this.&updated //Global Object for functions in subscribe method! def appTouch = this.&appTouch App2(Object obj) { reference = obj location = obj.locationObject app = obj.appObject switchesoff = obj.switchObject switcheson = obj.switchObject lock1 = obj.lockObject } //Global variables for each app //Settings variable defined to settings on purpose def settings = "Settings" //Global variable for state[mode] def state = [home:[],away:[],night:[]] //Create a global logger object for methods def log = new Logger() //Create a global variable for Functions in Subscribe method def functionList = [] //Create a global variable for Objects in Subscribe method def objectList = [] //Create a global variable for Events in Subscribe method def eventList = [] //Create a global list for function schedulers def timersFuncList = [] //Create a global list for timer schedulers def timersList = [] //Methods ///////////////////////////////////////////////////////////////////// def setLocationMode(String mode) { location.mode = mode } ///////////////////////////////////////////////////////////////////// ////subscribe(obj, func) def subscribe(Object obj, Closure FunctionToCall) { objectList.add(obj) eventList.add("Touched") functionList.add(FunctionToCall) } ////subscribe(obj, event, func) def subscribe(Object obj, String event, Closure FunctionToCall) { objectList.add(obj) eventList.add(event) functionList.add(FunctionToCall) } ////subscribe(obj, event, func, data) def subscribe(Object obj, String event, Closure FunctionToCall, LinkedHashMap metaData) { objectList.add(obj) eventList.add(event) functionList.add(FunctionToCall) } ///////////////////////////////////////////////////////////////////// ////runIn(time, func) def runIn(int seconds, Closure functionToCall) { if (timersFuncList.contains(functionToCall)) { timersList[timersFuncList.indexOf(functionToCall)].cancel() def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds, functionToCall) } else { timersFuncList.add(functionToCall) timersList.add(new SimulatedTimer()) def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds, functionToCall) } } ///////////////////////////////////////////////////////////////////// ////unschedule(func) def unschedule(Closure functionToUnschedule) { for (int i = 0;i < timersFuncList.size();i++) { if (timersFuncList[i] == functionToUnschedule) { if (timersList != null) timersList[i].cancel() } } } def unschedule() { for (int i = 0;i < timersFuncList.size();i++) { if (timersList != null) timersList[i].cancel() } } ///////////////////////////////////////////////////////////////////// ////sendNotificationToContacts(text, recipients) def sendNotificationToContacts(String text, String recipients) { for (int i = 0;i < recipients.size();i++) { for (int j = 0;j < location.contacts.size();j++) { if (recipients[i] == location.contacts[j]) { println("Sending \""+text+"\" to "+location.phoneNumbers[j].toString()) } } } } ///////////////////////////////////////////////////////////////////// ////sendSms(phone, text) def sendSms(long phoneNumber, String text) { println("Sending \""+text+"\" to "+phoneNumber.toString()) } ///////////////////////////////////////////////////////////////////// ////schedule(time, nameOfFunction as String) def schedule(String time, String nameOfFunction) { def _inputTime = time.split(':') Date date = new Date() def _currentTime = date.format("HH:mm:ss").split(':') //Convert input time and current time to minutes def inputTime = Integer.parseInt(_inputTime[0])*3600+Integer.parseInt(_inputTime[1])*60 def currentTime = Integer.parseInt(_currentTime[0])*3600+Integer.parseInt(_currentTime[1])*60+Integer.parseInt(_currentTime[2]) def delay if (inputTime < currentTime) { delay = 24*60*60-inputTime+currentTime } else { delay = inputTime-currentTime } timersFuncList.add(nameOfFunction) timersList.add(new SimulatedTimer()) def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*1000) { "$nameOfFunction"() } } ////schedule(time, nameOfFunction as Closure) def schedule(String time, Closure nameOfFunction) { def _inputTime = time.split(':') Date date = new Date() def _currentTime = date.format("HH:mm:ss").split(':') //Convert input time and current time to minutes def inputTime = Integer.parseInt(_inputTime[0])*3600+Integer.parseInt(_inputTime[1])*60 def currentTime = Integer.parseInt(_currentTime[0])*3600+Integer.parseInt(_currentTime[1])*60+Integer.parseInt(_currentTime[2]) def delay if (inputTime < currentTime) { delay = 24*60*60-inputTime+currentTime } else { delay = inputTime-currentTime } if (timersFuncList.contains(nameOfFunction)) { timersList[timersFuncList.indexOf(nameOfFunction)].cancel() def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds, nameOfFunction) } else { timersFuncList.add(nameOfFunction) timersList.add(new SimulatedTimer()) def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds, nameOfFunction) } } def installed() { log.debug "Installed with settings: ${settings}" log.debug "Current mode = ${location.mode}" subscribe(app, appTouch) } def updated() { log.debug "Updated with settings: ${settings}" log.debug "Current mode = ${location.mode}" unsubscribe() subscribe(app, appTouch) } def appTouch(evt) { log.debug "changeMode, location.mode = $location.mode, newMode = $newMode, location.modes = $location.modes" if (location.mode != newMode) { setLocationMode(newMode) log.debug "Changed the mode to '${newMode}'" } else { log.debug "New mode is the same as the old mode, leaving it be" } log.debug "appTouch: $evt" lock1.lock() switcheson.on() def delay = (waitfor != null && waitfor != "") ? waitfor * 1000 : 120000 switchesoff.off(delay: delay) } } @Field def app1 = new App1(this) @Field def app2 = new App2(this) app1.installed() app2.installed() // Generate a random variable Random random = new Random(1131) int nextRandom = 10 // Touch events new Thread() { @Override public void run() { while(true) { appObject.setValue([name: "Touched", value: "Touched", deviceId: 0, descriptionText: "", displayed: true, linkText: "", isStateChange: false, unit: "", data: []]) Thread.sleep(random.nextInt(nextRandom)); } } }.start() // Lock events new Thread() { @Override public void run() { while(true) { lockObject.setValue([name: "lock", value: "locked", deviceId: 0, descriptionText: "", displayed: true, linkText: "", isStateChange: false, unit: "", data: []]) Thread.sleep(random.nextInt(nextRandom)); } } }.start() new Thread() { @Override public void run() { while(true) { lockObject.setValue([name: "unlock", value: "unlocked", deviceId: 0, descriptionText: "", displayed: true, linkText: "", isStateChange: false, unit: "", data: []]) Thread.sleep(random.nextInt(nextRandom)); } } }.start() // Contact sensor events new Thread() { @Override public void run() { while(true) { contactObject.setValue([name: "contact.open", value: "open", deviceId: 0, descriptionText: "", displayed: true, linkText: "", isStateChange: false, unit: "", data: []]) Thread.sleep(random.nextInt(nextRandom)); } } }.start() new Thread() { @Override public void run() { while(true) { contactObject.setValue([name: "contact.closed", value: "closed", deviceId: 0, descriptionText: "", displayed: true, linkText: "", isStateChange: false, unit: "", data: []]) Thread.sleep(random.nextInt(nextRandom)); } } }.start()