//Infrastructure for SmartThings Application //Importing Libraries import groovy.transform.Field //Importing Classes import ContactSensor.ContactSensor import ContactSensor.ContactSensors import DoorControl.DoorControl import DoorControl.DoorControls import Lock.Lock import Lock.Locks import Thermostat.Thermostat import Thermostat.Thermostats import Switch.Switch import Switch.Switches import PresenceSensor.PresenceSensor import PresenceSensor.PresenceSensors import Logger.Logger import Location.LocationVar import Location.Phrase import appTouch.Touched import NfcTouch.NfcTouch 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 to call function @Field def appObject = new Touched(sendEvent, 0) //Create a global list for events @Field def evt = [] //Global Object for class Touch Sensor! @Field def touchSensorObject = new NfcTouch(sendEvent, 1) //Global Object for class switch! @Field def switchObject = new Switches(sendEvent, 1) //Global Object for class lock! @Field def lockObject = new Locks(sendEvent, 1) //Global Object for class door control! @Field def doorControlObject = new DoorControls(sendEvent, 1) //Global Object for class contact sensor! @Field def contactObject = new ContactSensors(sendEvent, 1) //Global Object for class presence sensor! @Field def presenceSensorObject = new PresenceSensors(sendEvent, 1) //Global Object for class thermostat! @Field def thermostatObject = new Thermostats(sendEvent, 1) //Application #1 class App1 { def reference def location def app //Extracted objects for App1 //Object for class Touch Sensor! def tag //Object for class switch! def switch1 //Object for class lock! def lock //Object for class door control! def garageDoor //Global variable for enum! def masterSwitch = "40" //Global variable for enum! def masterLock = "20" //Global variable for enum! def masterDoor = "40" //Extracted objects for functions for App1 //Global Object for functions in subscribe method! def pageTwo = this.&pageTwo //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 currentStatus = this.¤tStatus //Global Object for functions in subscribe method! def touchHandler = this.&touchHandler App1(Object obj) { reference = obj location = obj.locationObject app = obj.appObject tag = obj.touchSensorObject switch1 = obj.switchObject lock = obj.lockObject garageDoor = obj.doorControlObject } //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) { if (obj == app) { objectList.add(obj) eventList.add("Touched") functionList.add(FunctionToCall) } else if (obj == location) { objectList.add(obj) eventList.add("Location") 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 pageTwo() { dynamicPage(name: "pageTwo") { section("If set, the state of these devices will be toggled each time the tag is touched, " + "e.g. a light that's on will be turned off and one that's off will be turned on, " + "other devices of the same type will be set to the same state as their master device. " + "If no master is designated then the majority of devices of the same type will be used " + "to determine whether to turn on or off the devices.") { if (switch1 || masterSwitch) { input "masterSwitch", "enum", title: "Master switch", options: switch1.collect{[(it.id): it.displayName]}, required: false } if (lock || masterLock) { input "masterLock", "enum", title: "Master lock", options: lock.collect{[(it.id): it.displayName]}, required: false } if (garageDoor || masterDoor) { input "masterDoor", "enum", title: "Master door", options: garageDoor.collect{[(it.id): it.displayName]}, required: false } } section([mobileOnly:true]) { label title: "Assign a name", required: false mode title: "Set for specific mode(s)", required: false } } } def installed() { log.debug "Installed with settings: ${settings}" initialize() } def updated() { log.debug "Updated with settings: ${settings}" unsubscribe() initialize() } def initialize() { subscribe tag, "nfcTouch", touchHandler subscribe app, touchHandler } private currentStatus(devices, master, attribute) { log.trace "currentStatus($devices, $master, $attribute)" def result = null if (master) { result = devices.find{it.id == master}?.currentValue(attribute) } else { def map = [:] devices.each { def value = it.currentValue(attribute) map[value] = (map[value] ?: 0) + 1 log.trace "$it.displayName: $value" } log.trace map result = map.collect{it}.sort{it.value}[-1].key } log.debug "$attribute = $result" result } def touchHandler(evt) { log.trace "touchHandler($evt.descriptionText)" if (switch1) { def status = currentStatus(switch1, masterSwitch, "switch") switch1.each { if (status == "on") { it.off() } else { it.on() } } } if (lock) { def status = currentStatus(lock, masterLock, "lock") lock.each { if (status == "locked") { lock.unlock() } else { lock.lock() } } } if (garageDoor) { def status = currentStatus(garageDoor, masterDoor, "status") garageDoor.each { if (status == "open") { it.close() } else { it.open() } } } } } //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 = "home" //Global variable for number! def waitfor = 10 //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) { if (obj == app) { objectList.add(obj) eventList.add("Touched") functionList.add(FunctionToCall) } else if (obj == location) { objectList.add(obj) eventList.add("Location") 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() def events = [1,2,3,4,5,6,7] def list = events.permutations() int count = Verify.getInt(0,list.size()-1) println "COUNT: " + count list[count].each { switch(it) { case 1: appObject.setValue([name: "Touched", value: "Touched", deviceId: 0, descriptionText: "", displayed: true, linkText: "", isStateChange: false, unit: "", data: []]) println "1" break case 2: lockObject.setValue([name: "lock0", value: "locked", deviceId: 0, descriptionText: "", displayed: true, linkText: "", isStateChange: false, unit: "", data: []]) println " 2" break case 3: lockObject.setValue([name: "lock0", value: "unlocked", deviceId: 0, descriptionText: "", displayed: true, linkText: "", isStateChange: false, unit: "", data: []]) println " 3" break case 4: contactObject.setValue([name: "contact0", value: "open", deviceId: 0, descriptionText: "", displayed: true, linkText: "", isStateChange: false, unit: "", data: []]) println " 4" break case 5: contactObject.setValue([name: "contact0", value: "closed", deviceId: 0, descriptionText: "", displayed: true, linkText: "", isStateChange: false, unit: "", data: []]) println " 5" break case 6: switchObject.setValue([name: "switch0", value: "on", deviceId: 0, descriptionText: "", displayed: true, linkText: "", isStateChange: false, unit: "", data: []]) println " 6" break case 7: switchObject.setValue([name: "switch0", value: "off", deviceId: 0, descriptionText: "", displayed: true, linkText: "", isStateChange: false, unit: "", data: []]) println " 7" default: break } }